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

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

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

  3. #define I2C_SDA_P101_HIGH                                   R_PFS->PORT[1].PIN[1].PmnPFS_b.PODR = 1
  4. #define I2C_SDA_P101_LOW                                    R_PFS->PORT[1].PIN[1].PmnPFS_b.PODR = 0



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

  1. void I2C_IDLE_P100_P101()
  2. {
  3.         I2C_SDA_P101_OUT();
  4.         I2C_SDA_P101_HIGH;
  5.         I2C_SCL_P100_HIGH;
  6.         R_BSP_SoftwareDelay(4 , BSP_DELAY_UNITS_MICROSECONDS);
  7. }

  8. void I2C_Start_P100_P101(void)
  9. {
  10.         I2C_SDA_P101_OUT();
  11.         I2C_SDA_P101_HIGH;
  12.         I2C_SCL_P100_HIGH;            
  13.         R_BSP_SoftwareDelay(4 , BSP_DELAY_UNITS_MICROSECONDS);
  14.         I2C_SDA_P101_LOW;
  15.         R_BSP_SoftwareDelay(4 , BSP_DELAY_UNITS_MICROSECONDS);
  16.         I2C_SCL_P100_LOW;
  17.    R_BSP_SoftwareDelay(4 , BSP_DELAY_UNITS_MICROSECONDS);
  18. }       

  19. void I2C_Stop_P100_P101(void)
  20. {
  21.         I2C_SDA_P101_OUT();
  22.         I2C_SDA_P101_LOW;
  23.   I2C_SCL_P100_HIGH;
  24.   R_BSP_SoftwareDelay(4 , BSP_DELAY_UNITS_MICROSECONDS);
  25.   I2C_SDA_P101_HIGH;
  26. }

  27. uint8_t I2C_Wait_Ack_P100_P101(void)
  28. {
  29.         uint8_t rvalue;
  30.         I2C_SDA_P101_OUT();
  31.         I2C_SDA_P101_HIGH;
  32.         R_BSP_SoftwareDelay(4 , BSP_DELAY_UNITS_MICROSECONDS);
  33.         I2C_SCL_P100_HIGH;
  34.         R_BSP_SoftwareDelay(4 , BSP_DELAY_UNITS_MICROSECONDS);
  35.         I2C_SDA_P101_IN();
  36.         if(I2C_SDA_P101_READ)
  37.         {
  38.                 rvalue = 1;
  39.         }
  40.         else
  41.         {
  42.                 rvalue = 0;
  43.         }
  44.         I2C_SCL_P100_LOW;
  45.         R_BSP_SoftwareDelay(4 , BSP_DELAY_UNITS_MICROSECONDS);
  46.         return rvalue;
  47. }

  48. void I2C_Ack_P100_P101(void)
  49. {
  50.         I2C_SDA_P101_OUT();
  51.         I2C_SDA_P101_LOW;
  52.         R_BSP_SoftwareDelay(4 , BSP_DELAY_UNITS_MICROSECONDS);
  53.         I2C_SCL_P100_HIGH;
  54.         R_BSP_SoftwareDelay(4 , BSP_DELAY_UNITS_MICROSECONDS);
  55.         I2C_SCL_P100_LOW;
  56.         R_BSP_SoftwareDelay(4 , BSP_DELAY_UNITS_MICROSECONDS);
  57.         I2C_SDA_P101_HIGH;
  58. }

  59. void I2C_NAck_P100_P101(void)
  60. {
  61.         I2C_SDA_P101_OUT();
  62.         I2C_SDA_P101_HIGH;
  63.         R_BSP_SoftwareDelay(4 , BSP_DELAY_UNITS_MICROSECONDS);
  64.         I2C_SCL_P100_HIGH;
  65.         R_BSP_SoftwareDelay(4 , BSP_DELAY_UNITS_MICROSECONDS);
  66.         I2C_SCL_P100_LOW;
  67.         R_BSP_SoftwareDelay(4 , BSP_DELAY_UNITS_MICROSECONDS);
  68. }       

  69. void I2C_Send_Byte_P100_P101(uint8_t txd)
  70. {                        
  71.   uint8_t i;   
  72.         I2C_SDA_P101_OUT();
  73.         I2C_SCL_P100_LOW;
  74.   for(i = 0 ; i < 8 ; i ++)
  75.   {              
  76.                 if((txd&0x80)>>7)
  77.                         I2C_SDA_P101_HIGH;
  78.                 else
  79.                         I2C_SDA_P101_LOW;
  80.                 txd <<= 1;           
  81.                 R_BSP_SoftwareDelay(20 , BSP_DELAY_UNITS_MICROSECONDS);
  82.                 I2C_SCL_P100_HIGH;
  83.                 R_BSP_SoftwareDelay(20 , BSP_DELAY_UNITS_MICROSECONDS);
  84.                 I2C_SCL_P100_LOW;
  85.                 R_BSP_SoftwareDelay(20 , BSP_DELAY_UNITS_MICROSECONDS);
  86.    }       
  87.         R_BSP_SoftwareDelay(20 , BSP_DELAY_UNITS_MICROSECONDS);
  88. }             

  89. uint16_t I2C_Read_Byte_P100_P101(uint8_t ack)
  90. {
  91.         uint8_t i;
  92.         uint16_t dat = 0;
  93.         I2C_SDA_P101_IN();
  94.   for(i = 0 ; i < 8 ; i++)
  95.         {
  96.                 I2C_SCL_P100_LOW;
  97.                 R_BSP_SoftwareDelay(20 , BSP_DELAY_UNITS_MICROSECONDS);
  98.                 I2C_SCL_P100_HIGH;
  99.                 dat <<= 1;
  100.                 if(I2C_SDA_P101_READ)       
  101.                         dat++;   
  102.                 R_BSP_SoftwareDelay(20 , BSP_DELAY_UNITS_MICROSECONDS);
  103.   }               

  104.     if (!ack)
  105.         I2C_NAck_P100_P101();
  106.     else
  107.         I2C_Ack_P100_P101();
  108.     return dat;
  109. }

  110. uint8_t I2C_Read_Addr_P100_P101(uint8_t dev_addr , uint8_t reg)
  111. {
  112.         uint8_t res;
  113.         I2C_Start_P100_P101();
  114.         I2C_Send_Byte_P100_P101((dev_addr << 1) | 0);
  115.         I2C_Wait_Ack_P100_P101();
  116.         I2C_Send_Byte_P100_P101(reg);
  117.         I2C_Wait_Ack_P100_P101();
  118.         I2C_Start_P100_P101();
  119.         I2C_Send_Byte_P100_P101((dev_addr << 1) | 1);
  120.         I2C_Wait_Ack_P100_P101();
  121.         res = I2C_Read_Byte_P100_P101(0);
  122.         I2C_Stop_P100_P101();
  123.         return res;               
  124. }

  125. void I2C_Read_Datas_P100_P101(uint8_t dev_addr , uint8_t reg , uint8_t data_len , uint8_t data[])
  126. {
  127.         while(data_len)
  128.         {
  129.         *data = I2C_Read_Addr_P100_P101(dev_addr , reg++);
  130.         data ++;
  131.         data_len --;
  132.     }       
  133. }

  134. void I2C_Write_Reg_Data_P100_P101(uint8_t dev_addr , uint8_t reg , uint8_t data)
  135. {
  136.         I2C_Start_P100_P101();
  137.         I2C_Send_Byte_P100_P101((dev_addr << 1) | 0);
  138.         I2C_Wait_Ack_P100_P101();
  139.         I2C_Send_Byte_P100_P101(reg);
  140.         I2C_Wait_Ack_P100_P101();
  141.         I2C_Send_Byte_P100_P101(data);
  142.         I2C_Wait_Ack_P100_P101();
  143.         I2C_Stop_P100_P101();
  144. }

  145. void I2C_Write_Reg_Datas_P100_P101(uint8_t dev_addr , uint8_t reg , uint8_t data_len , uint8_t data[])
  146. {
  147.         int i;
  148.         I2C_Start_P100_P101();
  149.         I2C_Send_Byte_P100_P101((dev_addr << 1) | 0);
  150.         I2C_Wait_Ack_P100_P101();
  151.         I2C_Send_Byte_P100_P101(reg);
  152.         I2C_Wait_Ack_P100_P101();
  153.         for(i = 0 ; i < data_len ; i++)
  154.         {
  155.                 I2C_Send_Byte_P100_P101(data[i]);
  156.                 I2C_Wait_Ack_P100_P101();
  157.         }
  158.   I2C_Stop_P100_P101();
  159.   R_BSP_SoftwareDelay(10 , BSP_DELAY_UNITS_MILLISECONDS);
  160. }

  161. #define ATH20_SLAVE_ADDRESS                                                                0x38

  162. #define BMP280_PRESSURE_OSR                                                                            (BMP280_OVERSAMP_8X)
  163. #define BMP280_TEMPERATURE_OSR                                                            (BMP280_OVERSAMP_16X)
  164. #define BMP280_MODE                                                                                                            (BMP280_PRESSURE_OSR << 2 | BMP280_TEMPERATURE_OSR << 5 | BMP280_NORMAL_MODE)

  165. #define BMP280_SLAVE_ADDRESS_0x76                                        0x76
  166. #define BMP280_SLAVE_ADDRESS_0x77                                                    0x77               

  167. /*calibration parameters */
  168. #define BMP280_DIG_T1_LSB_REG                   0x88
  169. #define BMP280_DIG_T1_MSB_REG                   0x89
  170. #define BMP280_DIG_T2_LSB_REG                   0x8A
  171. #define BMP280_DIG_T2_MSB_REG                   0x8B
  172. #define BMP280_DIG_T3_LSB_REG                   0x8C
  173. #define BMP280_DIG_T3_MSB_REG                   0x8D
  174. #define BMP280_DIG_P1_LSB_REG                   0x8E
  175. #define BMP280_DIG_P1_MSB_REG                   0x8F
  176. #define BMP280_DIG_P2_LSB_REG                   0x90
  177. #define BMP280_DIG_P2_MSB_REG                   0x91
  178. #define BMP280_DIG_P3_LSB_REG                   0x92
  179. #define BMP280_DIG_P3_MSB_REG                   0x93
  180. #define BMP280_DIG_P4_LSB_REG                   0x94
  181. #define BMP280_DIG_P4_MSB_REG                   0x95
  182. #define BMP280_DIG_P5_LSB_REG                   0x96
  183. #define BMP280_DIG_P5_MSB_REG                   0x97
  184. #define BMP280_DIG_P6_LSB_REG                   0x98
  185. #define BMP280_DIG_P6_MSB_REG                   0x99
  186. #define BMP280_DIG_P7_LSB_REG                   0x9A
  187. #define BMP280_DIG_P7_MSB_REG                   0x9B
  188. #define BMP280_DIG_P8_LSB_REG                   0x9C
  189. #define BMP280_DIG_P8_MSB_REG                   0x9D
  190. #define BMP280_DIG_P9_LSB_REG                   0x9E
  191. #define BMP280_DIG_P9_MSB_REG                   0x9F

  192. #define BMP280_CHIPID_REG                    0xD0  /*Chip ID Register */
  193. #define BMP280_RESET_REG                     0xE0  /*Softreset Register */
  194. #define BMP280_STATUS_REG                    0xF3  /*Status Register */
  195. #define BMP280_CTRLMEAS_REG                  0xF4  /*Ctrl Measure Register */
  196. #define BMP280_CONFIG_REG                    0xF5  /*Configuration Register */
  197. #define BMP280_PRESSURE_MSB_REG              0xF7  /*Pressure MSB Register */
  198. #define BMP280_PRESSURE_LSB_REG              0xF8  /*Pressure LSB Register */
  199. #define BMP280_PRESSURE_XLSB_REG             0xF9  /*Pressure XLSB Register */
  200. #define BMP280_TEMPERATURE_MSB_REG           0xFA  /*Temperature MSB Reg */
  201. #define BMP280_TEMPERATURE_LSB_REG           0xFB  /*Temperature LSB Reg */
  202. #define BMP280_TEMPERATURE_XLSB_REG          0xFC  /*Temperature XLSB Reg */


  203. #define BMP280_SLEEP_MODE                                                                                (0x00)
  204. #define BMP280_FORCED_MODE                                                                        (0x01)
  205. #define BMP280_NORMAL_MODE                                                                        (0x03)

  206. #define BMP280_TEMPERATURE_CALIB_DIG_T1_LSB_REG             (0x88)
  207. #define BMP280_PRESSURE_TEMPERATURE_CALIB_DATA_LENGTH       (24)
  208. #define BMP280_DATA_FRAME_SIZE                                                        (6)

  209. #define BMP280_OVERSAMP_SKIPPED                                                        (0x00)
  210. #define BMP280_OVERSAMP_1X                                                                        (0x01)
  211. #define BMP280_OVERSAMP_2X                                                                        (0x02)
  212. #define BMP280_OVERSAMP_4X                                                                        (0x03)
  213. #define BMP280_OVERSAMP_8X                                                                        (0x04)
  214. #define BMP280_OVERSAMP_16X                                                                        (0x05)

  215. #define CONST_PF                                                                                                                 0.1902630958       
  216. //(1/5.25588f) Pressure factor
  217. #define FIX_TEMP                                                                                                                 25                               
  218. // 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.
  219. // TLDR: Adjusting for temp changes does more harm than good.

  220. typedef struct
  221. {
  222.     uint16_t dig_T1;/* calibration T1 data */
  223.     int16_t dig_T2; /* calibration T2 data */
  224.     int16_t dig_T3; /* calibration T3 data */
  225.     uint16_t dig_P1;/* calibration P1 data */
  226.     int16_t dig_P2; /* calibration P2 data */
  227.     int16_t dig_P3; /* calibration P3 data */
  228.     int16_t dig_P4; /* calibration P4 data */
  229.     int16_t dig_P5; /* calibration P5 data */
  230.     int16_t dig_P6; /* calibration P6 data */
  231.     int16_t dig_P7; /* calibration P7 data */
  232.     int16_t dig_P8; /* calibration P8 data */
  233.     int16_t dig_P9; /* calibration P9 data */
  234.     int t_fine; /* calibration t_fine data */
  235. } bmp280Calib;

  236. uint8_t msb , lsb , xlsb;
  237. float var1 , var2;
  238. bmp280Calib  bmp280Cal;

  239. uint8_t BMP280_Init(void)
  240. {
  241.         uint8_t bmp280_id;
  242.         uint8_t tmp[1];

  243.         I2C_Read_Datas_P100_P101(BMP280_SLAVE_ADDRESS_0x77 , BMP280_CHIPID_REG, 1, &bmp280_id);

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

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

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

  251.         tmp[0] = BMP280_MODE;
  252.         I2C_Write_Reg_Datas_P100_P101(BMP280_SLAVE_ADDRESS_0x77 , BMP280_CTRLMEAS_REG , 1 , tmp);

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

  255.         return bmp280_id;
  256. }

  257. float BMP280PressureToAltitude(float* pressure)
  258. {
  259.     if (*pressure > 0)
  260.     {
  261.         return ((pow((1015.7f / (*pressure)), CONST_PF) - 1.0f) * (FIX_TEMP + 273.15f)) / 0.0065f;
  262.     }
  263.     else
  264.     {
  265.         return 0;
  266.     }
  267. }

  268. void BMP280_Read_Pressure_Tempature(float * pres , float * temp)
  269. {
  270.         msb = I2C_Read_Addr_P100_P101(BMP280_SLAVE_ADDRESS_0x77 , BMP280_PRESSURE_MSB_REG);
  271.         lsb = I2C_Read_Addr_P100_P101(BMP280_SLAVE_ADDRESS_0x77 , BMP280_PRESSURE_LSB_REG);
  272.         xlsb = I2C_Read_Addr_P100_P101(BMP280_SLAVE_ADDRESS_0x77 , BMP280_PRESSURE_XLSB_REG);


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

  274.         msb = I2C_Read_Addr_P100_P101(BMP280_SLAVE_ADDRESS_0x77 , BMP280_TEMPERATURE_MSB_REG);
  275.         lsb = I2C_Read_Addr_P100_P101(BMP280_SLAVE_ADDRESS_0x77 , BMP280_TEMPERATURE_LSB_REG);
  276.         xlsb = I2C_Read_Addr_P100_P101(BMP280_SLAVE_ADDRESS_0x77 , BMP280_TEMPERATURE_XLSB_REG);

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

  278.     var1 = ((*temp) / 16384.0 - bmp280Cal.dig_T1 / 1024.0)*(bmp280Cal.dig_T2);
  279.     var2 = (((*temp) / 131072.0 - bmp280Cal.dig_T1 / 8192.0) *
  280.          ((*temp) / 131072.0 - bmp280Cal.dig_T1 / 8192.0)) * bmp280Cal.dig_T3;
  281.     *temp = var1 + var2;
  282.     *temp /= 5120.0;

  283.     var1 = ((*temp) / 2.0) - 64000.0;
  284.     var2 = var1 * var1*(bmp280Cal.dig_P6) / 32768.0;
  285.     var2 = var2 + var1 * (bmp280Cal.dig_P5)*2.0;
  286.     var2 = (var2 / 4.0) + ((bmp280Cal.dig_P4)*65536.0);
  287.     var1 = (bmp280Cal.dig_P3)*var1*var1 / 524288.0 + (bmp280Cal.dig_P2)*var1 / 524288.0;
  288.     var1 = (1.0 + var1 / 32768.0)*(bmp280Cal.dig_P1);

  289.     *pres = 1048576.0 - (*pres);
  290.     *pres = ((*pres) - (var2 / 4096.0))*6250.0 / var1;
  291.     var1 = (bmp280Cal.dig_P9) * (*pres) * (*pres) / 2147483648.0;
  292.     var2 = (*pres) * (bmp280Cal.dig_P8) / 32768.0;
  293.     *pres = (*pres) + (var1 + var2 + (bmp280Cal.dig_P7)) / 16.0;
  294. }

运行效果:
12.jpg