(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