MAX32630自带I2C协议,可直接调用相应的库函数,我们知道,STM32F4的库函数典型的I2C协议用SCK和SDA的输出高低电平建立握手机制。今天,我们将这种方式应用于MAX32630
(1)以MAX30100血氧传感器为例
其实将STM32F4的模拟I2C协议移植过来非常简单,主要是管脚输出输入的配置,代码如下:
- /*-------------------------------------------------------------------------------
- 文件名称:myiic.c
- 文件描述:模拟IIC时序控制,
- 编写整理:Justice
- ---------------------------------------------------------------------------------*/
- #include "Com.h"
- gpio_cfg_t GPIO_I2C_Control;
- const gpio_cfg_t I2C_COL_Pin[] = {
- { PORT_3, PIN_4, GPIO_FUNC_GPIO, GPIO_PAD_OPEN_DRAIN_PULLUP },
- { PORT_3, PIN_4, GPIO_FUNC_GPIO, GPIO_PAD_OPEN_DRAIN_PULLUP },
- { PORT_3, PIN_4, GPIO_FUNC_GPIO, GPIO_PAD_INPUT_PULLUP },
- { PORT_3, PIN_6, GPIO_FUNC_GPIO, GPIO_PAD_OPEN_DRAIN_PULLUP },
- };
- #define I2C_Speed 1
- //初始化IIC
- void IIC_Init(void)
- {
- GPIO_Config(&I2C_COL_Pin[0]);
- GPIO_Config(&I2C_COL_Pin[1]);
- //GPIO_Config(&I2C_COL_Pin[3]);
- GPIO_OutSet(&I2C_COL_Pin[0]);
- GPIO_OutSet(&I2C_COL_Pin[1]);
- // GPIO_OutSet(&I2C_COL_Pin[3]);
- }
- void SDA_OUT(void)
- {
- GPIO_Config(& I2C_COL_Pin[0]);
- }
- void SDA_IN(void)
- {
- GPIO_Config(& I2C_COL_Pin[2]);
- }
- //产生IIC起始信号
- void IIC_Start(void)
- {
- SDA_OUT(); //sda线输出
- GPIO_OutSet(&I2C_COL_Pin[0]); //IIC_SDA=1;
- GPIO_OutSet(&I2C_COL_Pin[1]); //IIC_SCL=1;
- delay_us(4);
- GPIO_OutClr(&I2C_COL_Pin[0]); //IIC_SDA=0 START:when CLK is high,DATA change form high to low
- delay_us(4);
- GPIO_OutClr(&I2C_COL_Pin[1]);////IIC_SCL=0;钳住I2C总线,准备发送或接收数据
- }
- //产生IIC停止信号
- void IIC_Stop(void)
- {
- SDA_OUT();//sda线输出
- GPIO_OutClr(&I2C_COL_Pin[1]);//IIC_SCL=0;
- GPIO_OutClr(&I2C_COL_Pin[0]); //IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
- delay_us(4);
- GPIO_OutSet(&I2C_COL_Pin[1]); //IIC_SCL=1;
- GPIO_OutSet(&I2C_COL_Pin[0]); //IIC_SDA=1;//发送I2C总线结束信号
- delay_us(4);
- }
- //等待应答信号到来
- //返回值:1,接收应答失败
- // 0,接收应答成功
- uint8_t IIC_Wait_Ack(void)
- {
- uint8_t ucErrTime=0;
- SDA_IN(); //SDA设置为输入
- GPIO_OutSet(&I2C_COL_Pin[0]); //IIC_SDA=1;
- delay_us(1);
- GPIO_OutSet(&I2C_COL_Pin[1]); //IIC_SCL=1;
- delay_us(1);
- while(GPIO_InGet(&I2C_COL_Pin[2]))
- {
- ucErrTime++;
- if(ucErrTime>250)
- {
- IIC_Stop();
- return 1;
- }
- }
- GPIO_OutClr(&I2C_COL_Pin[1]);//IIC_SCL=0;//时钟输出0
- return 0;
- }
- //产生ACK应答
- void IIC_Ack(void)
- {
- GPIO_OutClr(&I2C_COL_Pin[1]);//IIC_SCL=0;
- SDA_OUT();
- GPIO_OutClr(&I2C_COL_Pin[0]); //IIC_SDA=0;
- delay_us(2);
- GPIO_OutSet(&I2C_COL_Pin[1]);//IIC_SCL=1;
- delay_us(2);
- GPIO_OutClr(&I2C_COL_Pin[1]);//IIC_SCL=0;
- }
- //不产生ACK应答
- void IIC_NAck(void)
- {
- GPIO_OutClr(&I2C_COL_Pin[1]);//IIC_SCL=0;
- SDA_OUT();
- GPIO_OutSet(&I2C_COL_Pin[0]);//IIC_SDA=1;
- delay_us(2);
- GPIO_OutSet(&I2C_COL_Pin[1]);//IIC_SCL=1;
- delay_us(2);
- GPIO_OutClr(&I2C_COL_Pin[1]);//IIC_SCL=0;
- }
- //IIC发送一个字节
- //返回从机有无应答
- //1,有应答
- //0,无应答
- void IIC_Send_Byte(uint8_t txd)
- {
- uint8_t t;
- SDA_OUT();
- GPIO_OutClr(&I2C_COL_Pin[1]);//IIC_SCL=0;//拉低时钟开始数据传输
- for(t=0;t<8;t++)
- {
- if((txd&0x80)>>7)
- {
- GPIO_OutSet(&I2C_COL_Pin[0]);
- }
- else
- {
- GPIO_OutClr(&I2C_COL_Pin[0]);
- }
- txd<<=1;
- delay_us(I2C_Speed);
- GPIO_OutSet(&I2C_COL_Pin[1]);//IIC_SCL=1;
- delay_us(I2C_Speed);
- GPIO_OutClr(&I2C_COL_Pin[1]);//IIC_SCL=0;
- delay_us(I2C_Speed);
- }
- }
- //读1个字节,ack=1时,发送ACK,ack=0,发送nACK
- uint8_t IIC_Read_Byte(unsigned char ack)
- {
- unsigned char i,receive=0;
- SDA_IN();//SDA设置为输入
- for(i=0;i<8;i++ )
- {
- GPIO_OutClr(&I2C_COL_Pin[1]);//IIC_SCL=0;
- delay_us(I2C_Speed);
- GPIO_OutSet(&I2C_COL_Pin[1]);//IIC_SCL=1;
- receive<<=1;
- if(GPIO_InGet(&I2C_COL_Pin[2]))receive++;
- delay_us(1);
- }
- if (!ack)
- IIC_NAck();//发送nACK
- else
- IIC_Ack(); //发送ACK
- return receive;
- }
复制代码
是不是很简单,这个模拟I2C协议我已经测试过了,包括MAX30100血氧传感器和MPU6050都可以驱动。
头文件也提供给你们吧,代码如下:
- #ifndef __MYIIC_H
- #define __MYIIC_H
- #include "Com.h"
-
- //IO方向设置
- void SDA_OUT(void);
- void SDA_IN(void);
- //IO操作函数
- #define IIC_PORT PORT_5|PORT_6
- #define IIC_SCL PIN_0
- #define IIC_SDA PIN_7
- //IIC所有操作函数
- void IIC_Init(void); //初始化IIC的IO口
- void IIC_Start(void); //发送IIC开始信号
- void IIC_Stop(void); //发送IIC停止信号
- void IIC_Send_Byte(uint8_t txd); //IIC发送一个字节
- uint8_t IIC_Read_Byte(unsigned char ack);//IIC读取一个字节
- uint8_t IIC_Wait_Ack(void); //IIC等待ACK信号
- void IIC_Ack(void); //IIC发送ACK信号
- void IIC_NAck(void); //IIC不发送ACK信号
- void IIC_Write_One_Byte(uint8_t daddr,uint8_t addr,uint8_t data);
- uint8_t IIC_Read_One_Byte(uint8_t daddr,uint8_t addr);
- #endif
- 后面的驱动如何调用你们就自己解决吧,洗洗睡啦,还有一个月就要提交作品了,大家加油
复制代码