对于MAX30102这款模块其实网上已经有很多教学,但是很可惜,这些教学都千篇一律,代码例程更像是清朝的代码,个个代码都长得一样,连注释都一样。我想分享一些对于新手而言友好一点的教学,有用的,不一样的教学。因此,我做出了一个违背祖宗的决定!!!废话不多说直接开整。
我们这次的目标很简单,能建立通信, 能读出数据,能识别手指。
我们一个一个步骤的来
1.建立通信
这款模块使用的是 I2C通信协议,对于I2C的时序我相信大家都已经了解,但我这里也给出我的 I2C代码(默默感谢一下浩哥),这里的I2C使用的是软件模拟。
#define RCC_IIC_SCL RCC_AHB1Periph_GPIOE //端口时钟
#define IIC_SCL_PORT GPIOE //端口号
#define IIC_SCL GPIO_Pin_3 //引脚
#define RCC_IIC_SDA RCC_AHB1Periph_GPIOE
#define IIC_SDA_PORT GPIOE
#define IIC_SDA GPIO_Pin_4
//io操作
#define IIC_SCL_H GPIO_SetBits(IIC_SCL_PORT,IIC_SCL); //SCL置1
#define IIC_SCL_L GPIO_ResetBits(IIC_SCL_PORT,IIC_SCL);//SCL置0
#define IIC_SDA_H GPIO_SetBits(IIC_SDA_PORT,IIC_SDA); //SDA置1
#define IIC_SDA_L GPIO_ResetBits(IIC_SDA_PORT,IIC_SDA);//SDA置0
#define READ_SDA GPIO_ReadInputDataBit(IIC_SDA_PORT,IIC_SDA)//读取SDA输入引脚电平
void IICx_GPIO_Init(void);
void IIC_SDA_OUT(void);
void IIC_SDA_IN(void);
void IIC_Start(void);
void IIC_Stop(void);
void IIC_ACK(void);
void IIC_NACK(void);
void IIC_SendByte(uint8_t data);
uint8_t IIC_ReadByte(uint8_t ack);
uint8_t IIC_WaitACK(void);
uint16_t BH1750_ReadData(void);
void IICx_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
//GPIO时钟
RCC_AHB1PeriphClockCmd(RCC_IIC_SCL, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_IIC_SDA, ENABLE);
//SCL GPIO初始化
GPIO_InitStructure.GPIO_Pin=IIC_SCL;
GPIO_InitStructure.GPIO_Mode= GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType=GPIO_OType_OD; //开漏输出
GPIO_InitStructure.GPIO_Speed=GPIO_High_Speed;
GPIO_Init(IIC_SCL_PORT, &GPIO_InitStructure);
//SDA GPIO初始化
GPIO_InitStructure.GPIO_Pin=IIC_SDA;
GPIO_InitStructure.GPIO_Mode= GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType=GPIO_OType_OD; //开漏输出
GPIO_InitStructure.GPIO_Speed=GPIO_High_Speed;
GPIO_Init(IIC_SDA_PORT, &GPIO_InitStructure);
IIC_SCL_H;
IIC_SDA_H;
}
//配置SDA数据线为输出
void IIC_SDA_OUT(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
//SDA GPIO初始化
GPIO_InitStructure.GPIO_Pin=IIC_SDA;
GPIO_InitStructure.GPIO_Mode= GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType=GPIO_OType_OD; //开漏输出
GPIO_InitStructure.GPIO_Speed=GPIO_High_Speed;
GPIO_Init(IIC_SDA_PORT, &GPIO_InitStructure);
}
//配置SDA数据线为输入
void IIC_SDA_IN(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
//SDA GPIO初始化
GPIO_InitStructure.GPIO_Pin=IIC_SDA;
GPIO_InitStructure.GPIO_Mode= GPIO_Mode_IN;
GPIO_InitStructure.GPIO_Speed=GPIO_High_Speed;
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP; //上拉,仅对输入有效
GPIO_Init(IIC_SDA_PORT, &GPIO_InitStructure);
}
//IIC时序信号
//IIC开始信号
void IIC_Start(void)
{
IIC_SDA_OUT();
IIC_SCL_H;
IIC_SDA_H;
Delay_us(4);//让高电平保持稳定
IIC_SDA_L; // 拉低SDA
Delay_us(4);
IIC_SCL_L; //钳住IIC总线,准备发送或者接收数据
}
//IIC停止信号
void IIC_Stop(void)
{
IIC_SDA_OUT();
IIC_SCL_H;
IIC_SDA_L; //SAD低
Delay_us(4);//等待时序稳定
IIC_SDA_H; //SDA高
}
//IIC应答
void IIC_ACK(void)
{
IIC_SDA_OUT();
IIC_SCL_L; //在SCL低电平的时候,SDA可以进行数据切换(1和0切换)
IIC_SDA_L; //SDA低电平表示应答型号
Delay_us(1);//让电平稳定
IIC_SCL_H; //拉高SCL,表示此时SDA的数据有效
Delay_us(1);
IIC_SCL_L; //拉低SCL,表示SCL一个周期结束
}
//IIC非应答
void IIC_NACK(void)
{
IIC_SDA_OUT();
IIC_SCL_L; //在SCL低电平的时候