[APM32F4] 【APM32F411V Tiny Board测评】硬件I2C读取传感器测试

[复制链接]
 楼主| WoodData 发表于 2024-5-23 17:53 | 显示全部楼层 |阅读模式
本次研究了一下APM32F411的I2C接口功能。看了一下官方例子是使用的中断模式,感觉不太方便。这里我就不使用中断模式操作I2C接口。
首先初始化I2C接口IO和外设:使用PB8和PB9的I2C1外设。
  1. void drv_i2c_gpio_init( void )
  2. {
  3.     GPIO_Config_T   gpioConfigStruct;

  4.     /* Enable I2C related Clock */
  5.     RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOB);
  6.    
  7. #ifdef I2C_USE_GPIO

  8. #else
  9.     I2C_Config_T    i2cConfigStruct;
  10.    
  11.     gpioConfigStruct.mode = GPIO_MODE_AF;
  12.     gpioConfigStruct.speed = GPIO_SPEED_50MHz;
  13.     gpioConfigStruct.pin = GPIO_PIN_8 | GPIO_PIN_9;
  14.     gpioConfigStruct.otype = GPIO_OTYPE_OD;
  15.     gpioConfigStruct.pupd = GPIO_PUPD_UP;
  16.     GPIO_Config(GPIOB, &gpioConfigStruct);
  17.    
  18.     /* Free I2C_SCL and I2C_SDA */
  19.     GPIO_ConfigPinAF(GPIOB, GPIO_PIN_SOURCE_8, GPIO_AF_I2C1);
  20.     GPIO_ConfigPinAF(GPIOB, GPIO_PIN_SOURCE_9, GPIO_AF_I2C1);
  21.    
  22.     /*  Config I2C1 */
  23.     RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_I2C1);
  24.     I2C_Reset(I2C1);
  25.     i2cConfigStruct.mode = I2C_MODE_I2C;
  26.     i2cConfigStruct.dutyCycle = I2C_DUTYCYCLE_2;
  27.     i2cConfigStruct.ackAddress = I2C_ACK_ADDRESS_7BIT;
  28.     i2cConfigStruct.ownAddress1 = 0XA0;
  29.     i2cConfigStruct.ack = I2C_ACK_DISABLE;
  30.     i2cConfigStruct.clockSpeed = 100000;
  31.     I2C_Config(I2C1, &i2cConfigStruct);
  32.    
  33.     I2C_DisableDualAddress(I2C1);
  34.     /* Enable I2Cx */
  35.     I2C_Enable(I2C1);

  36. #endif
  37. }


下面就是我的I2C读写接口:
  1. static int __CheckErrFlag(I2C_T* i2c)
  2. {
  3.     int bflag;
  4.     bflag = 0;
  5.     if(I2C_ReadStatusFlag(i2c, I2C_FLAG_BERR))    //
  6.     {
  7.         bflag =1;
  8.         I2C_ClearStatusFlag(i2c, I2C_FLAG_BERR);    //
  9.     }
  10.     if(I2C_ReadStatusFlag(i2c, I2C_FLAG_AL))    //
  11.     {
  12.         bflag =2;
  13.         I2C_ClearStatusFlag(i2c, I2C_FLAG_AL);    //
  14.     }
  15.     if(I2C_ReadStatusFlag(i2c, I2C_FLAG_AE))    //
  16.     {
  17.         bflag =3;
  18.         I2C_ClearStatusFlag(i2c, I2C_FLAG_AE);    //
  19.     }
  20.     if(I2C_ReadStatusFlag(i2c, I2C_FLAG_OVRUR))    //
  21.     {
  22.         bflag =4;
  23.         I2C_ClearStatusFlag(i2c, I2C_FLAG_OVRUR);    //
  24.     }
  25.     if(I2C_ReadStatusFlag(i2c, I2C_FLAG_PECE))    //
  26.     {
  27.         bflag =5;
  28.         I2C_ClearStatusFlag(i2c, I2C_FLAG_PECE);    //
  29.     }
  30.     if(I2C_ReadStatusFlag(i2c, I2C_FLAG_TTE))    //
  31.     {
  32.         bflag =6;
  33.         I2C_ClearStatusFlag(i2c, I2C_FLAG_TTE);    //
  34.     }
  35.     if(I2C_ReadStatusFlag(i2c, I2C_FLAG_SMBALT))    //
  36.     {
  37.         bflag =7;
  38.         I2C_ClearStatusFlag(i2c, I2C_FLAG_SMBALT);    //
  39.     }
  40.     return bflag;
  41. }

  42. static int __WaitEvtTimeout(I2C_T* i2c, I2C_EVENT_T evt)
  43. {
  44.     volatile uint32_t timeout;
  45.     timeout = 10000;
  46.     while (!I2C_ReadEventStatus(i2c, evt))
  47.     {
  48.         timeout--;
  49.         if(timeout == 0)
  50.         {
  51.             return -1;
  52.         }
  53.         if(__CheckErrFlag(i2c))
  54.         {
  55.             return 1;
  56.         }
  57.     }
  58.     return 0;
  59. }

  60. uint8_t I2C_WriteByte(uint8_t index,uint32_t dev_addr, uint32_t addr,uint8_t Byte)
  61. {
  62.     while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_BUSBSY) == SET)    //bus busy
  63.     {
  64.         I2C_EnableGenerateStop(I2C1);
  65.         delay_us(15);
  66.         break;
  67.     }
  68.     /* Send START condition */
  69.     I2C_EnableGenerateStart(I2C1);
  70.     while (! I2C_ReadEventStatus(I2C1, I2C_EVENT_MASTER_MODE_SELECT));   //wait flag
  71.     /* Send address for write */
  72.     I2C_Tx7BitAddress(I2C1, dev_addr << 1, I2C_DIRECTION_TX);
  73.     __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);   //wait flag
  74.     /* Send the current byte */
  75.     I2C_TxData(I2C1,addr &0xff);
  76.     __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING);
  77.     /* Send the current byte */
  78.     I2C_TxData(I2C1,Byte);
  79.    __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED);
  80.     I2C_EnableGenerateStop(I2C1);
  81.     while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_BUSBSY) == SET);
  82.    
  83.     return 0;
  84. }

  85. uint8_t I2C_ReadByte (uint8_t index,uint32_t dev_addr, uint32_t addr)
  86. {
  87.     uint8_t buff;
  88.    
  89.     while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_BUSBSY) == SET)    //bus busy
  90.     {
  91.         I2C_EnableGenerateStop(I2C1);
  92.         delay_us(15);
  93.         break;
  94.     }
  95.     /* Send START condition */
  96.     I2C_EnableGenerateStart(I2C1);
  97.     while (! I2C_ReadEventStatus(I2C1, I2C_EVENT_MASTER_MODE_SELECT));   //wait flag
  98.     /* Send address for write */
  99.     I2C_Tx7BitAddress(I2C1, dev_addr << 1, I2C_DIRECTION_TX);
  100.     __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);   //wait flag
  101.     /* Send the current byte */
  102.     I2C_TxData(I2C1,addr &0xff);
  103.     __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED);
  104.    
  105.     /* Send START condition */
  106.     I2C_EnableGenerateStart(I2C1);
  107.     while (! I2C_ReadEventStatus(I2C1, I2C_EVENT_MASTER_MODE_SELECT));   //wait flag
  108.     /* Send address for write */
  109.     I2C_Tx7BitAddress(I2C1, dev_addr << 1, I2C_DIRECTION_RX);
  110.     __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED);   //wait flag
  111.    
  112.     I2C_DisableAcknowledge(I2C1);
  113.     __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED);
  114.     /* Recv the current byte */
  115.     buff = I2C_RxData(I2C1);
  116.    
  117.     I2C_EnableGenerateStop(I2C1);
  118.     while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_BUSBSY) == SET);
  119.    
  120.     return buff;
  121. }


  1. uint8_t I2C_PageWrite(uint8_t index,uint32_t dev_addr, uint32_t addr,uint8_t *str,uint32_t num)
  2. {
  3.     uint32_t i;
  4.    
  5.     if((num == 0)||(str==NULL)) return 1;
  6.    
  7.     while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_BUSBSY) == SET)    //bus busy
  8.     {
  9.         I2C_EnableGenerateStop(I2C1);
  10.         delay_us(15);
  11.         break;
  12.     }
  13.     /* Send START condition */
  14.     I2C_EnableGenerateStart(I2C1);
  15.     while (! I2C_ReadEventStatus(I2C1, I2C_EVENT_MASTER_MODE_SELECT));   //wait flag
  16.     /* Send address for write */
  17.     I2C_Tx7BitAddress(I2C1, dev_addr << 1, I2C_DIRECTION_TX);
  18.     __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);   //wait flag
  19.     /* Send the current byte */
  20.     I2C_TxData(I2C1,addr &0xff);
  21.     for(i=num;i>0;i--)
  22.     {
  23.         __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING);
  24.         /* Send the current byte */
  25.         I2C_TxData(I2C1,*str++);
  26.     }
  27.     __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED);
  28.     I2C_EnableGenerateStop(I2C1);
  29.     while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_BUSBSY) == SET);
  30.    
  31.     return 0;
  32. }

  33. uint8_t I2C_PageRead (uint8_t index,uint32_t dev_addr, uint32_t addr,uint8_t *str,uint32_t num)
  34. {
  35.     uint32_t i;
  36.    
  37.     if((num == 0)||(str==NULL)) return 1;
  38.    
  39.     while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_BUSBSY) == SET)    //bus busy
  40.     {
  41.         I2C_EnableGenerateStop(I2C1);
  42.         delay_us(15);
  43.         break;
  44.     }
  45.     /* Send START condition */
  46.     I2C_EnableGenerateStart(I2C1);
  47.     while (! I2C_ReadEventStatus(I2C1, I2C_EVENT_MASTER_MODE_SELECT));   //wait flag
  48.     /* Send address for write */
  49.     I2C_Tx7BitAddress(I2C1, dev_addr << 1, I2C_DIRECTION_TX);
  50.     __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);   //wait flag
  51.     /* Send the current byte */
  52.     I2C_TxData(I2C1,addr &0xff);
  53.     __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED);
  54.    
  55.     /* Send START condition */
  56.     I2C_EnableGenerateStart(I2C1);
  57.     while (! I2C_ReadEventStatus(I2C1, I2C_EVENT_MASTER_MODE_SELECT));   //wait flag
  58.     /* Send address for write */
  59.     I2C_Tx7BitAddress(I2C1, dev_addr << 1, I2C_DIRECTION_RX);
  60.     __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED);   //wait flag
  61.    
  62.     for(i=num-1;i>0;i--)
  63.     {
  64.         I2C_EnableAcknowledge(I2C1);
  65.         __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED);
  66.         /* Recv the current byte */
  67.         *str++ = I2C_RxData(I2C1);
  68.     }
  69.    
  70.     I2C_DisableAcknowledge(I2C1);
  71.     __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED);
  72.     /* Recv the current byte */
  73.     *str++ = I2C_RxData(I2C1);
  74.    
  75.     I2C_EnableGenerateStop(I2C1);
  76.     while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_BUSBSY) == SET);
  77.     return 0;
  78. }


调试这个I2C花了不少时间,主要是这个时序状态。我这里是用逻辑分析仪一步步慢慢调试出来的。
下面是一个检测I2C设备地址的函数,检测总线上设备。通过shell来检查地址状态。
  1. static int __AddrDetect(uint8_t addr)
  2. {
  3.     uint32_t bflag;

  4.     while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_BUSBSY) == SET)    //bus busy
  5.     {
  6.         I2C_EnableGenerateStop(I2C1);
  7.         delay_us(15);
  8.         break;
  9.     }
  10.     /* Send START condition */
  11.     I2C_EnableGenerateStart(I2C1);
  12.     while (! I2C_ReadEventStatus(I2C1, I2C_EVENT_MASTER_MODE_SELECT));   //wait flag
  13.     /* Send address for write */
  14.     I2C_Tx7BitAddress(I2C1, addr << 1, I2C_DIRECTION_TX);
  15.     bflag = 0;
  16.     while (! I2C_ReadEventStatus(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
  17.     {
  18.         delay_us(25);
  19.         bflag = __CheckErrFlag(I2C1);
  20.         if(bflag)    break;
  21.     }
  22.     delay_us(10);
  23.     I2C_EnableGenerateStop(I2C1);
  24.    
  25.     return bflag;
  26. }

  27. #if UART_SHELL == 2
  28. #include "nr_micro_shell.h"

  29. void I2C_AddrDetect(char argc, char *argv)
  30. {
  31.     int i,j;
  32.    
  33.     printf("Detect I2C addr:\r\n");
  34.    
  35.     for(i=0;i<8;i++)
  36.     {
  37.         for(j=0;j<16;j++)
  38.         {
  39.             if(__AddrDetect(j + i*16) == 0) printf("%02X ",j + i*16);
  40.             else  printf("-- ");
  41.             delay_ms(1);
  42.         }
  43.         printf("\r\n");
  44.     }
  45.     printf("\r\nDetect I2C addr over.\r\n");
  46. }

  47. NR_SHELL_CMD_EXPORT(i2c_detect,   I2C_AddrDetect,     "I2C detect device address");

  48. #endif

1.jpg

这里我板子上接了4个I2C设备。分别是光照的RPR0521RS,3轴加速度BM1422,气压BM1383,和温湿度SHTC3。
接下来我们看看设备检测效果:
2.png
可以看到检测了4个地址设备了。

设备驱动都写好了测试成功,也可以通过shell读取数据了:
3.png


您需要登录后才可以回帖 登录 | 注册

本版积分规则

127

主题

4778

帖子

28

粉丝
快速回复 在线客服 返回列表 返回顶部

127

主题

4778

帖子

28

粉丝
快速回复 在线客服 返回列表 返回顶部