Initial import of STM32 IoT sensor node
This commit is contained in:
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user