Initial import of STM32 IoT sensor node

This commit is contained in:
yzfh
2026-10-19 15:47:18 +08:00
commit a51794b022
100 changed files with 46274 additions and 0 deletions
+157
View File
@@ -0,0 +1,157 @@
#include "systick.h"
#include "bitband.h"
#include "gpio_iic.h"
static GPIO_InitTypeDef GPIO_InitStructSDAOut;
static GPIO_InitTypeDef GPIO_InitStructSDAIn;
// 位段定义
#define IIC_SCL_OUT PBOut(6)
#define IIC_SDA_OUT PBOut(7)
#define IIC_SDA_IN PBIn(7)
// 初始化 IIC 的IO 端口:SDA:PB7,SCL:PB6
void iic_init(void)
{
GPIO_InitTypeDef GPIO_InitStructSCL;
// 使能时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
// 初始化 PB6 为开漏输出
GPIO_InitStructSCL.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_InitStructSCL.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructSCL.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructSCL);
// 初始化 PB7 为开漏输出
GPIO_InitStructSDAOut.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_InitStructSDAOut.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructSDAOut.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructSDAOut);
// 设置 SCL和SDA 都为高电平
IIC_SCL_OUT = 1;
IIC_SDA_OUT = 1;
// 填充 PB7 为上拉输入状态的结构体(后续备用)
GPIO_InitStructSDAIn.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructSDAIn.GPIO_Pin = GPIO_Pin_7;
}
// 设置 SDA 为输入模式
static void iic_set_sda_in(void)
{
GPIO_Init(GPIOB, &GPIO_InitStructSDAIn);
}
// 设置 SDA 为输出模式
static void iic_set_sda_out(void)
{
GPIO_Init(GPIOB, &GPIO_InitStructSDAOut);
}
// 主机发送起始信号
void iic_start(void)
{
iic_set_sda_out();
IIC_SDA_OUT = 1;
IIC_SCL_OUT = 1;
delay_us(2);
IIC_SDA_OUT = 0;
delay_us(2);
IIC_SCL_OUT = 0;
delay_us(1);
}
//主机发送停止信号
void iic_stop(void)
{
iic_set_sda_out();
IIC_SCL_OUT = 0;
IIC_SDA_OUT = 0;
delay_us(2);
IIC_SCL_OUT = 1;
delay_us(1);
IIC_SDA_OUT = 1;
delay_us(2);
}
// 主机发送一个字节
void iic_send_byte(u8 txd)
{
int bit;
iic_set_sda_out();
for (bit = 7; bit >= 0; bit--) {
// 拉低时钟线
IIC_SCL_OUT = 0;
delay_us(1);
// 变化数据线的数据
IIC_SDA_OUT = (txd >> bit) & 0x01;
delay_us(1);
IIC_SCL_OUT = 1;
delay_us(2);
}
IIC_SCL_OUT = 0; // 发送完毕拉低时钟线。
}
// 主机接收一个字节并回复ack,参数ack:1表示应答,0表示非应答。
u8 iic_recv_byte(u8 ack)
{
int bit;
u8 value = 0; // 用于保存最终的返回值
iic_set_sda_in(); // 设置为输入模式
for (bit = 7; bit >= 0; bit--) {
IIC_SCL_OUT = 0; // 拉低时钟线
delay_us(2);
IIC_SCL_OUT = 1;
delay_us(2);
if (IIC_SDA_IN) {
value |= (0x01 << bit);
}
}
IIC_SCL_OUT = 0;
// 接收8为数据,根据参数ack 回复应答或非应答。
if (ack)
iic_send_ack();
else
iic_send_nack();
return value;
}
// 主机等待从机,如果从机未响应(收到NACK),则发送停止
// 信号结束本次通信,非应答返回1(NACK),应答返回0,ACK);
u8 iic_wait_ack(void)
{
u8 error_timeout = 0;
IIC_SCL_OUT = 0; // 拉低时钟线
iic_set_sda_in(); // 设置为输入模式
delay_us(1);
IIC_SCL_OUT = 1; // 拉高时钟线。
// 等待从机拉低的引号
while (IIC_SDA_IN) {
error_timeout++;
if (error_timeout > 250) {
iic_stop(); // 发送停止信号,然后返回1
return 1;
}
}
IIC_SCL_OUT = 0; // 拉低时钟线
return 0;
}
// 主机发送 ACK
void iic_send_ack(void)
{
IIC_SCL_OUT = 0; // 拉低时钟线
iic_set_sda_out(); // 变为输出模式
IIC_SDA_OUT = 0; // 低电平为应答ACK
delay_us(2);
IIC_SCL_OUT = 1; // 拉高时钟线
delay_us(2);
IIC_SCL_OUT = 0;
}
// 主机发送 NACK
void iic_send_nack(void)
{
IIC_SCL_OUT = 0; // 拉低时钟线
iic_set_sda_out(); // 变为输出模式
IIC_SDA_OUT = 1; // 高电平为非应答NACK
delay_us(2);
IIC_SCL_OUT = 1; // 拉高时钟线
delay_us(2);
IIC_SCL_OUT = 0;
}