你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

基于STM32f030硬件I2C经验分享

[复制链接]
攻城狮Melo 发布时间:2023-3-30 16:55
STM32F030的硬件I2C程序,整理一下如下,注意使用的时候i2c器件地址的问题,文章最后有说明。

i2c_hard.c 文件:
  1. #include "i2c_hard.h"

  2. static int I2C_Timeout = 0;

  3. void i2c1_port_init(void)
  4. {
  5.         GPIO_InitTypeDef GPIO_InitStructure;
  6.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
  7.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
  8.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  9.         GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
  10.         GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  11.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  12.         GPIO_Init(GPIOB, &GPIO_InitStructure);
  13.         GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_1);
  14.         GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_1);
  15. }

  16. void i2c1_init(void)
  17. {
  18.         I2C_InitTypeDef I2C_InitStructure;
  19.         RCC_I2CCLKConfig(RCC_I2C1CLK_SYSCLK);
  20.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
  21.         I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
  22.         I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
  23.         I2C_InitStructure.I2C_AnalogFilter = I2C_AnalogFilter_Enable;
  24.         I2C_InitStructure.I2C_DigitalFilter = 0x00;
  25.         I2C_InitStructure.I2C_OwnAddress1 = 0x00;
  26.         I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
  27.         I2C_InitStructure.I2C_Timing = 0x30E32E44;
  28.         I2C_Init(I2C1, &I2C_InitStructure);
  29.         I2C_Cmd(I2C1, ENABLE);
  30. }

  31. /**
  32.   * @brief  从I2C1总线上的某一器件的某一起始地址中读取一定字节的数据到数组中
  33.   * @param  driver_Addr:I2C器件地址
  34.   * @param  start_Addr:起始字节地址
  35.   * @param  number_Bytes:要读取的字节数量(小于一页)
  36.   * @param  read_Buffer:存放读取数据的数组指针
  37.   * @retval 是否读取成功
  38.   */
  39. I2C_Status I2C1_Read_NBytes(uint8_t driver_Addr, uint8_t start_Addr, uint8_t number_Bytes, uint8_t *read_Buffer)
  40. {
  41.   uint8_t read_Num;

  42.   I2C_Timeout = I2C_TIMEOUT;
  43.   while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) != RESET)
  44.   {
  45.     if((I2C_Timeout--) == 0)
  46.     {
  47.       return I2C_FAIL;
  48.     }
  49.   }

  50.   I2C_TransferHandling(I2C1, driver_Addr, 1, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);

  51.   I2C_Timeout = I2C_TIMEOUT;
  52.   while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TXIS) == RESET)
  53.   {
  54.     if((I2C_Timeout--) == 0)
  55.     {
  56.       return I2C_FAIL;
  57.     }
  58.   }

  59.   I2C_SendData(I2C1, start_Addr);

  60.   I2C_Timeout = I2C_TIMEOUT;
  61.   while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TC) == RESET)
  62.   {
  63.     if((I2C_Timeout--) == 0)
  64.     {
  65.       return I2C_FAIL;
  66.     }
  67.   }

  68.   I2C_TransferHandling(I2C1, driver_Addr, number_Bytes,  I2C_AutoEnd_Mode, I2C_Generate_Start_Read);

  69.   for(read_Num = 0; read_Num < number_Bytes; read_Num++)
  70.   {
  71.     I2C_Timeout = I2C_TIMEOUT;
  72.     while(I2C_GetFlagStatus(I2C1, I2C_FLAG_RXNE) == RESET)
  73.     {
  74.       if((I2C_Timeout--) == 0)
  75.       {
  76.         return I2C_FAIL;
  77.       }
  78.     }

  79.     read_Buffer[read_Num] = I2C_ReceiveData(I2C1);
  80.   }

  81.   I2C_Timeout = I2C_TIMEOUT;
  82.   while(I2C_GetFlagStatus(I2C1, I2C_FLAG_STOPF) == RESET)
  83.   {
  84.     if((I2C_Timeout--) == 0)
  85.     {
  86.       return I2C_FAIL;
  87.     }
  88.   }

  89.   return I2C_OK;
  90. }

  91. /**
  92.   * @brief  从I2C1的总线上的某一器件的某一起始地址中读取一定字节的数据到数组中
  93.   * @param  driver_Addr:I2C器件地址
  94.   * @param  start_Addr:起始字节地址
  95.   * @param  number_Bytes:要读取的字节数量(小于一页)
  96.   * @param  write_Buffer:存放读取数据的数组指针
  97.   * @retval 是否读取成功
  98.   */
  99. I2C_Status I2C1_Write_NBytes(uint8_t driver_Addr, uint8_t start_Addr, uint8_t number_Bytes, uint8_t *write_Buffer)
  100. {
  101.   uint8_t write_Num;

  102.   I2C_Timeout = I2C_TIMEOUT;
  103.   while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) != RESET)
  104.   {
  105.     if((I2C_Timeout--) == 0)
  106.     {
  107.       return I2C_FAIL;
  108.     }
  109.   }

  110.   I2C_TransferHandling(I2C1, driver_Addr, 1, I2C_Reload_Mode, I2C_Generate_Start_Write);

  111.   I2C_Timeout = I2C_TIMEOUT;
  112.   while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TXIS) == RESET)
  113.   {
  114.     if((I2C_Timeout--) == 0)
  115.     {
  116.       return I2C_FAIL;
  117.     }
  118.   }

  119.   I2C_SendData(I2C1, start_Addr);

  120.   I2C_Timeout = I2C_TIMEOUT;
  121.   while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TCR) == RESET)
  122.   {
  123.     if((I2C_Timeout--) == 0)
  124.     {
  125.       return I2C_FAIL;
  126.     }
  127.   }

  128.   I2C_TransferHandling(I2C1, driver_Addr, number_Bytes, I2C_AutoEnd_Mode, I2C_No_StartStop);

  129.   for(write_Num = 0; write_Num < number_Bytes; write_Num++)
  130.   {
  131.     I2C_Timeout = I2C_TIMEOUT;
  132.     while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TXIS) == RESET)
  133.     {
  134.       if((I2C_Timeout--) == 0)
  135.       {
  136.         return I2C_FAIL;
  137.       }
  138.     }

  139.     I2C_SendData(I2C1, write_Buffer[write_Num]);
  140.   }

  141.   I2C_Timeout = I2C_TIMEOUT;
  142.   while(I2C_GetFlagStatus(I2C1, I2C_FLAG_STOPF) == RESET)
  143.   {
  144.     if((I2C_Timeout--) == 0)
  145.     {
  146.       return I2C_FAIL;
  147.     }
  148.   }

  149.   return I2C_OK;
  150. }
复制代码

i2c_hard.h 文件:
  1. #ifndef __I2C_HARD_H__
  2. #define __I2C_HARD_H__
  3. #include "stm32f0xx.h"
  4. #include "delay.h"
  5. #include "USART1.h"
  6. #include "bsp.h"

  7. #define I2C_TIMEOUT 2000

  8. typedef enum
  9. {
  10.         I2C_OK = 0,
  11.         I2C_FAIL
  12. }I2C_Status;

  13. void i2c1_port_init(void);
  14. void i2c1_init(void);
  15. I2C_Status I2C1_Read_NBytes(uint8_t driver_Addr, uint8_t start_Addr, uint8_t number_Bytes, uint8_t *read_Buffer);
  16. I2C_Status I2C1_Write_NBytes(uint8_t driver_Addr, uint8_t start_Addr, uint8_t number_Bytes, uint8_t *write_Buffer);

  17. #endif
复制代码

但是注意,这里的 I2C1_Read_NBytes 和 I2C1_Write_NBytes 函数中的 driver_Addr 不是 7位格式的,需要将I2C器件的硬件地址左移1位,这也是我被坑之后用逻辑分析仪测出来的,下图为地址左移后抓取的正确波形:

20200508125937956.png

上述波形对应的程序:
  1. I2C1_Write_NBytes(0x68 << 1,0x75,1,&data);    //MPU6050硬件地址0x68
复制代码

————————————————
版权声明:哐哐哐 Quan如有侵权请联系删除



收藏 评论0 发布时间:2023-3-30 16:55

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版