模拟I2C代码逻辑可以用在任何单片机上,从51,到16位私有核的MSP430,再到32位的STM32和瑞萨,只要是有单片机的场合,就必定能用模拟I2C代码进行通信,模拟I2C代码逻辑的编写,是对每个嵌入式开发工程师的基本考验。直接使用官方的SCI0接口所对应的引脚,即P100和P101:
微信图片_20230727181756.jpg

我平时的习惯是使用寄存器进行GPIO操作:

#define I2C_SCL_P100_HIGH                                   R_PFS->PORT[1].PIN[0].PmnPFS_b.PODR = 1
  • #define I2C_SCL_P100_LOW                                    R_PFS->PORT[1].PIN[0].PmnPFS_b.PODR = 0

  • #define I2C_SDA_P101_HIGH                                   R_PFS->PORT[1].PIN[1].PmnPFS_b.PODR = 1
  • #define I2C_SDA_P101_LOW                                    R_PFS->PORT[1].PIN[1].PmnPFS_b.PODR = 0
  • 复制代码



    I2C驱动代码直接移植原子的代码即可:

    void I2C_IDLE_P100_P101()
  • {
  •         I2C_SDA_P101_OUT();
  •         I2C_SDA_P101_HIGH;
  •         I2C_SCL_P100_HIGH;
  •         R_BSP_SoftwareDelay(4 , BSP_DELAY_UNITS_MICROSECONDS);
  • }

  • void I2C_Start_P100_P101(void)
  • {
  •         I2C_SDA_P101_OUT();
  •         I2C_SDA_P101_HIGH;
  •         I2C_SCL_P100_HIGH;            
  •         R_BSP_SoftwareDelay(4 , BSP_DELAY_UNITS_MICROSECONDS);
  •         I2C_SDA_P101_LOW;
  •         R_BSP_SoftwareDelay(4 , BSP_DELAY_UNITS_MICROSECONDS);
  •         I2C_SCL_P100_LOW;
  •    R_BSP_SoftwareDelay(4 , BSP_DELAY_UNITS_MICROSECONDS);
  • }       

  • void I2C_Stop_P100_P101(void)
  • {
  •         I2C_SDA_P101_OUT();
  •         I2C_SDA_P101_LOW;
  •   I2C_SCL_P100_HIGH;
  •   R_BSP_SoftwareDelay(4 , BSP_DELAY_UNITS_MICROSECONDS);
  •   I2C_SDA_P101_HIGH;
  • }

  • uint8_t I2C_Wait_Ack_P100_P101(void)
  • {
  •         uint8_t rvalue;
  •         I2C_SDA_P101_OUT();
  •         I2C_SDA_P101_HIGH;
  •         R_BSP_SoftwareDelay(4 , BSP_DELAY_UNITS_MICROSECONDS);
  •         I2C_SCL_P100_HIGH;
  •         R_BSP_SoftwareDelay(4 , BSP_DELAY_UNITS_MICROSECONDS);
  •         I2C_SDA_P101_IN();
  •         if(I2C_SDA_P101_READ)
  •         {
  •                 rvalue = 1;
  •         }
  •         else
  •         {
  •                 rvalue = 0;
  •         }
  •         I2C_SCL_P100_LOW;
  •         R_BSP_SoftwareDelay(4 , BSP_DELAY_UNITS_MICROSECONDS);
  •         return rvalue;
  • }

  • void I2C_Ack_P100_P101(void)
  • {
  •         I2C_SDA_P101_OUT();
  •         I2C_SDA_P101_LOW;
  •         R_BSP_SoftwareDelay(4 , BSP_DELAY_UNITS_MICROSECONDS);
  •         I2C_SCL_P100_HIGH;
  •         R_BSP_SoftwareDelay(4 , BSP_DELAY_UNITS_MICROSECONDS);
  •         I2C_SCL_P100_LOW;
  •         R_BSP_SoftwareDelay(4 , BSP_DELAY_UNITS_MICROSECONDS);
  •         I2C_SDA_P101_HIGH;
  • }

  • void I2C_NAck_P100_P101(void)
  • {
  •         I2C_SDA_P101_OUT();
  •         I2C_SDA_P101_HIGH;
  •         R_BSP_SoftwareDelay(4 , BSP_DELAY_UNITS_MICROSECONDS);
  •         I2C_SCL_P100_HIGH;
  •         R_BSP_SoftwareDelay(4 , BSP_DELAY_UNITS_MICROSECONDS);
  •         I2C_SCL_P100_LOW;
  •         R_BSP_SoftwareDelay(4 , BSP_DELAY_UNITS_MICROSECONDS);
  • }       

  • void I2C_Send_Byte_P100_P101(uint8_t txd)
  • {                        
  •   uint8_t i;   
  •         I2C_SDA_P101_OUT();
  •         I2C_SCL_P100_LOW;
  •   for(i = 0 ; i < 8 ; i ++)
  •   {              
  •                 if((txd&0x80)>>7)
  •                         I2C_SDA_P101_HIGH;
  •                 else
  •                         I2C_SDA_P101_LOW;
  •                 txd <<= 1;           
  •                 R_BSP_SoftwareDelay(20 , BSP_DELAY_UNITS_MICROSECONDS);
  •                 I2C_SCL_P100_HIGH;
  •                 R_BSP_SoftwareDelay(20 , BSP_DELAY_UNITS_MICROSECONDS);
  •                 I2C_SCL_P100_LOW;
  •                 R_BSP_SoftwareDelay(20 , BSP_DELAY_UNITS_MICROSECONDS);
  •    }       
  •         R_BSP_SoftwareDelay(20 , BSP_DELAY_UNITS_MICROSECONDS);
  • }             

  • uint16_t I2C_Read_Byte_P100_P101(uint8_t ack)
  • {
  •         uint8_t i;
  •         uint16_t dat = 0;
  •         I2C_SDA_P101_IN();
  •   for(i = 0 ; i < 8 ; i++)
  •         {
  •                 I2C_SCL_P100_LOW;
  •                 R_BSP_SoftwareDelay(20 , BSP_DELAY_UNITS_MICROSECONDS);
  •                 I2C_SCL_P100_HIGH;
  •                 dat <<= 1;
  •                 if(I2C_SDA_P101_READ)       
  •                         dat++;   
  •                 R_BSP_SoftwareDelay(20 , BSP_DELAY_UNITS_MICROSECONDS);
  •   }               

  •     if (!ack)
  •         I2C_NAck_P100_P101();
  •     else
  •         I2C_Ack_P100_P101();
  •     return dat;
  • }

  • uint8_t I2C_Read_Addr_P100_P101(uint8_t dev_addr , uint8_t reg)
  • {
  •         uint8_t res;
  •         I2C_Start_P100_P101();
  •         I2C_Send_Byte_P100_P101((dev_addr << 1) | 0);
  •         I2C_Wait_Ack_P100_P101();
  •         I2C_Send_Byte_P100_P101(reg);
  •         I2C_Wait_Ack_P100_P101();
  •         I2C_Start_P100_P101();
  •         I2C_Send_Byte_P100_P101((dev_addr << 1) | 1);
  •         I2C_Wait_Ack_P100_P101();
  •         res = I2C_Read_Byte_P100_P101(0);
  •         I2C_Stop_P100_P101();
  •         return res;               
  • }

  • void I2C_Read_Datas_P100_P101(uint8_t dev_addr , uint8_t reg , uint8_t data_len , uint8_t data[])
  • {
  •         while(data_len)
  •         {
  •         *data = I2C_Read_Addr_P100_P101(dev_addr , reg++);
  •         data ++;
  •         data_len --;
  •     }       
  • }

  • void I2C_Write_Reg_Data_P100_P101(uint8_t dev_addr , uint8_t reg , uint8_t data)
  • {
  •         I2C_Start_P100_P101();
  •         I2C_Send_Byte_P100_P101((dev_addr << 1) | 0);
  •         I2C_Wait_Ack_P100_P101();
  •         I2C_Send_Byte_P100_P101(reg);
  •         I2C_Wait_Ack_P100_P101();
  •         I2C_Send_Byte_P100_P101(data);
  •         I2C_Wait_Ack_P100_P101();
  •         I2C_Stop_P100_P101();
  • }

  • void I2C_Write_Reg_Datas_P100_P101(uint8_t dev_addr , uint8_t reg , uint8_t data_len , uint8_t data[])
  • {
  •         int i;
  •         I2C_Start_P100_P101();
  •         I2C_Send_Byte_P100_P101((dev_addr << 1) | 0);
  •         I2C_Wait_Ack_P100_P101();
  •         I2C_Send_Byte_P100_P101(reg);
  •         I2C_Wait_Ack_P100_P101();
  •         for(i = 0 ; i < data_len ; i++)
  •         {
  •                 I2C_Send_Byte_P100_P101(data[i]);
  •                 I2C_Wait_Ack_P100_P101();
  •         }
  •   I2C_Stop_P100_P101();
  •   R_BSP_SoftwareDelay(10 , BSP_DELAY_UNITS_MILLISECONDS);
  • }

  • #define ATH20_SLAVE_ADDRESS                                                                0x38

  • #define BMP280_PRESSURE_OSR                                                                            (BMP280_OVERSAMP_8X)
  • #define BMP280_TEMPERATURE_OSR                                                            (BMP280_OVERSAMP_16X)
  • #define BMP280_MODE                                                                                                            (BMP280_PRESSURE_OSR << 2 | BMP280_TEMPERATURE_OSR << 5 | BMP280_NORMAL_MODE)

  • #define BMP280_SLAVE_ADDRESS_0x76                                        0x76
  • #define BMP280_SLAVE_ADDRESS_0x77                                                    0x77               

  • /*calibration parameters */
  • #define BMP280_DIG_T1_LSB_REG                   0x88
  • #define BMP280_DIG_T1_MSB_REG                   0x89
  • #define BMP280_DIG_T2_LSB_REG                   0x8A
  • #define BMP280_DIG_T2_MSB_REG                   0x8B
  • #define BMP280_DIG_T3_LSB_REG                   0x8C
  • #define BMP280_DIG_T3_MSB_REG                   0x8D
  • #define BMP280_DIG_P1_LSB_REG                   0x8E
  • #define BMP280_DIG_P1_MSB_REG                   0x8F
  • #define BMP280_DIG_P2_LSB_REG                   0x90
  • #define BMP280_DIG_P2_MSB_REG                   0x91
  • #define BMP280_DIG_P3_LSB_REG                   0x92
  • #define BMP280_DIG_P3_MSB_REG                   0x93
  • #define BMP280_DIG_P4_LSB_REG                   0x94
  • #define BMP280_DIG_P4_MSB_REG                   0x95
  • #define BMP280_DIG_P5_LSB_REG                   0x96
  • #define BMP280_DIG_P5_MSB_REG                   0x97
  • #define BMP280_DIG_P6_LSB_REG                   0x98
  • #define BMP280_DIG_P6_MSB_REG                   0x99
  • #define BMP280_DIG_P7_LSB_REG                   0x9A
  • #define BMP280_DIG_P7_MSB_REG                   0x9B
  • #define BMP280_DIG_P8_LSB_REG                   0x9C
  • #define BMP280_DIG_P8_MSB_REG                   0x9D
  • #define BMP280_DIG_P9_LSB_REG                   0x9E
  • #define BMP280_DIG_P9_MSB_REG                   0x9F

  • #define BMP280_CHIPID_REG                    0xD0  /*Chip ID Register */
  • #define BMP280_RESET_REG                     0xE0  /*Softreset Register */
  • #define BMP280_STATUS_REG                    0xF3  /*Status Register */
  • #define BMP280_CTRLMEAS_REG                  0xF4  /*Ctrl Measure Register */
  • #define BMP280_CONFIG_REG                    0xF5  /*Configuration Register */
  • #define BMP280_PRESSURE_MSB_REG              0xF7  /*Pressure MSB Register */
  • #define BMP280_PRESSURE_LSB_REG              0xF8  /*Pressure LSB Register */
  • #define BMP280_PRESSURE_XLSB_REG             0xF9  /*Pressure XLSB Register */
  • #define BMP280_TEMPERATURE_MSB_REG           0xFA  /*Temperature MSB Reg */
  • #define BMP280_TEMPERATURE_LSB_REG           0xFB  /*Temperature LSB Reg */
  • #define BMP280_TEMPERATURE_XLSB_REG          0xFC  /*Temperature XLSB Reg */


  • #define BMP280_SLEEP_MODE                                                                                (0x00)
  • #define BMP280_FORCED_MODE                                                                        (0x01)
  • #define BMP280_NORMAL_MODE                                                                        (0x03)

  • #define BMP280_TEMPERATURE_CALIB_DIG_T1_LSB_REG             (0x88)
  • #define BMP280_PRESSURE_TEMPERATURE_CALIB_DATA_LENGTH       (24)
  • #define BMP280_DATA_FRAME_SIZE                                                        (6)

  • #define BMP280_OVERSAMP_SKIPPED                                                        (0x00)
  • #define BMP280_OVERSAMP_1X                                                                        (0x01)
  • #define BMP280_OVERSAMP_2X                                                                        (0x02)
  • #define BMP280_OVERSAMP_4X                                                                        (0x03)
  • #define BMP280_OVERSAMP_8X                                                                        (0x04)
  • #define BMP280_OVERSAMP_16X                                                                        (0x05)

  • #define CONST_PF                                                                                                                 0.1902630958       
  • //(1/5.25588f) Pressure factor
  • #define FIX_TEMP                                                                                                                 25                               
  • // Fixed Temperature. ASL is a function of pressure and temperature, but as the temperature changes so much (blow a little towards the flie and watch it drop 5 degrees) it corrupts the ASL estimates.
  • // TLDR: Adjusting for temp changes does more harm than good.

  • typedef struct
  • {
  •     uint16_t dig_T1;/* calibration T1 data */
  •     int16_t dig_T2; /* calibration T2 data */
  •     int16_t dig_T3; /* calibration T3 data */
  •     uint16_t dig_P1;/* calibration P1 data */
  •     int16_t dig_P2; /* calibration P2 data */
  •     int16_t dig_P3; /* calibration P3 data */
  •     int16_t dig_P4; /* calibration P4 data */
  •     int16_t dig_P5; /* calibration P5 data */
  •     int16_t dig_P6; /* calibration P6 data */
  •     int16_t dig_P7; /* calibration P7 data */
  •     int16_t dig_P8; /* calibration P8 data */
  •     int16_t dig_P9; /* calibration P9 data */
  •     int t_fine; /* calibration t_fine data */
  • } bmp280Calib;

  • uint8_t msb , lsb , xlsb;
  • float var1 , var2;
  • bmp280Calib  bmp280Cal;

  • uint8_t BMP280_Init(void)
  • {
  •         uint8_t bmp280_id;
  •         uint8_t tmp[1];

  •         I2C_Read_Datas_P100_P101(BMP280_SLAVE_ADDRESS_0x77 , BMP280_CHIPID_REG, 1, &bmp280_id);

  •         printf("bmp280_id = 0x%x\n" , bmp280_id);

  •         I2C_Read_Datas_P100_P101(BMP280_SLAVE_ADDRESS_0x77, BMP280_DIG_T1_LSB_REG , 24 , (uint8_t *)&bmp280Cal);

  •         //printf("%d %d %d %d %d %d %d %d %d %d %d %d\n" ,
  •         // bmp280Cal.dig_T1 , bmp280Cal.dig_T2 , bmp280Cal.dig_T3 ,
  •         // bmp280Cal.dig_P1 , bmp280Cal.dig_P2 , bmp280Cal.dig_P3 ,
  •         // bmp280Cal.dig_P4 , bmp280Cal.dig_P5 , bmp280Cal.dig_P6 ,
  •         // bmp280Cal.dig_P7 , bmp280Cal.dig_P8 , bmp280Cal.dig_P9);

  •         tmp[0] = BMP280_MODE;
  •         I2C_Write_Reg_Datas_P100_P101(BMP280_SLAVE_ADDRESS_0x77 , BMP280_CTRLMEAS_REG , 1 , tmp);

  •         tmp[0] = 5 << 2;
  •         I2C_Write_Reg_Datas_P100_P101(BMP280_SLAVE_ADDRESS_0x77 , BMP280_CONFIG_REG , 1 , tmp);

  •         return bmp280_id;
  • }

  • float BMP280PressureToAltitude(float* pressure)
  • {
  •     if (*pressure > 0)
  •     {
  •         return ((pow((1015.7f / (*pressure)), CONST_PF) - 1.0f) * (FIX_TEMP + 273.15f)) / 0.0065f;
  •     }
  •     else
  •     {
  •         return 0;
  •     }
  • }

  • void BMP280_Read_Pressure_Tempature(float * pres , float * temp)
  • {
  •         msb = I2C_Read_Addr_P100_P101(BMP280_SLAVE_ADDRESS_0x77 , BMP280_PRESSURE_MSB_REG);
  •         lsb = I2C_Read_Addr_P100_P101(BMP280_SLAVE_ADDRESS_0x77 , BMP280_PRESSURE_LSB_REG);
  •         xlsb = I2C_Read_Addr_P100_P101(BMP280_SLAVE_ADDRESS_0x77 , BMP280_PRESSURE_XLSB_REG);


  •     *pres = (msb * 65536 | lsb * 256 | xlsb) >> 4;

  •         msb = I2C_Read_Addr_P100_P101(BMP280_SLAVE_ADDRESS_0x77 , BMP280_TEMPERATURE_MSB_REG);
  •         lsb = I2C_Read_Addr_P100_P101(BMP280_SLAVE_ADDRESS_0x77 , BMP280_TEMPERATURE_LSB_REG);
  •         xlsb = I2C_Read_Addr_P100_P101(BMP280_SLAVE_ADDRESS_0x77 , BMP280_TEMPERATURE_XLSB_REG);

  •     *temp = (msb * 65536 | lsb * 256 | xlsb) >> 4;

  •     var1 = ((*temp) / 16384.0 - bmp280Cal.dig_T1 / 1024.0)*(bmp280Cal.dig_T2);
  •     var2 = (((*temp) / 131072.0 - bmp280Cal.dig_T1 / 8192.0) *
  •          ((*temp) / 131072.0 - bmp280Cal.dig_T1 / 8192.0)) * bmp280Cal.dig_T3;
  •     *temp = var1 + var2;
  •     *temp /= 5120.0;

  •     var1 = ((*temp) / 2.0) - 64000.0;
  •     var2 = var1 * var1*(bmp280Cal.dig_P6) / 32768.0;
  •     var2 = var2 + var1 * (bmp280Cal.dig_P5)*2.0;
  •     var2 = (var2 / 4.0) + ((bmp280Cal.dig_P4)*65536.0);
  •     var1 = (bmp280Cal.dig_P3)*var1*var1 / 524288.0 + (bmp280Cal.dig_P2)*var1 / 524288.0;
  •     var1 = (1.0 + var1 / 32768.0)*(bmp280Cal.dig_P1);

  •     *pres = 1048576.0 - (*pres);
  •     *pres = ((*pres) - (var2 / 4096.0))*6250.0 / var1;
  •     var1 = (bmp280Cal.dig_P9) * (*pres) * (*pres) / 2147483648.0;
  •     var2 = (*pres) * (bmp280Cal.dig_P8) / 32768.0;
  •     *pres = (*pres) + (var1 + var2 + (bmp280Cal.dig_P7)) / 16.0;
  • }
  • 复制代码

    运行效果:
    12.jpg