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

STM32F103+VL53L0测距(二)

[复制链接]
STMCU小助手 发布时间:2022-12-7 16:03
对于STM32F103单片机来说,它是自带了硬件 IIC,但是出于使用习惯和程序可移植性考虑,我们一般选择用 IO 口去模拟 I2C 协议。
使用 IO 口模拟 IIC 的好处有三点:
1. 使用 IO 模拟 IIC 协议可以让大家把之前学过的 GPIO 知识再进行深度的理解和扩展;
2. 加深对 IIC 时序流程的认识;
3. 方便移植到 STM32 的任何一个引脚,如再做修改可以移植到其他 MCU 平台。

当然这种方法也存在一些缺点,比如考虑这样一种极端情况,在程序运行时会有执行时
间很长的中断服务函数打断 IIC 时序,造成 IIC 写失败或者读失败。如果存在这种情况,建
议大家在进行 IIC 操作之前关闭全局中断,使用后再打开。

首先,对模拟I2C的I/O管脚进行宏定义,包括SDA线、SCL线管脚的定义等,代码如下:

  1. #define RCC_I2C_PORT         RCC_APB2Periph_GPIOB               

  2. #define PORT_I2C_SCL        GPIOB               
  3. #define PIN_I2C_SCL                GPIO_Pin_6               

  4. #define PORT_I2C_SDA        GPIOB                       
  5. #define PIN_I2C_SDA                GPIO_Pin_7               

  6. #define I2C_SCL_PIN                GPIO_Pin_6                       
  7. #define I2C_SDA_PIN                GPIO_Pin_7                       


  8. #define I2C_SCL_1()  PORT_I2C_SCL->BSRR = I2C_SCL_PIN                       
  9. #define I2C_SCL_0()  PORT_I2C_SCL->BRR = I2C_SCL_PIN                               

  10. #define I2C_SDA_1()  PORT_I2C_SDA->BSRR = I2C_SDA_PIN                               
  11. #define I2C_SDA_0()  PORT_I2C_SDA->BRR = I2C_SDA_PIN                               

  12. #define I2C_SDA_READ()  ((PORT_I2C_SDA->IDR & I2C_SDA_PIN) != 0)       
  13. #define I2C_SCL_READ()  ((PORT_I2C_SCL->IDR & I2C_SCL_PIN) != 0)       

  14. void SetSDA_IN(void)
  15. {
  16.         GPIO_InitTypeDef GPIO_InitStructure;
  17.         RCC_APB2PeriphClockCmd(RCC_I2C_PORT, ENABLE);       
  18.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  19.         GPIO_InitStructure.GPIO_Pin = PIN_I2C_SDA;
  20.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  21.         GPIO_Init(PORT_I2C_SDA, &GPIO_InitStructure);
  22. }
  23. void SetSDA_OUT(void)
  24. {
  25.         GPIO_InitTypeDef GPIO_InitStructure;
  26.         RCC_APB2PeriphClockCmd(RCC_I2C_PORT, ENABLE);       
  27.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  28.         GPIO_InitStructure.GPIO_Pin = PIN_I2C_SDA;
  29.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
  30.         GPIO_Init(PORT_I2C_SDA, &GPIO_InitStructure);
  31. }       
复制代码

接下来便是模拟I2C的初始化函数与时序操作的函数
初始化操作与GPIO初始化基本一致:
1.配置时钟;
2.配置管脚的输入输出模式,其中输出模式最好设为上拉输出;
3.设置管脚。

  1. void bsp_InitI2C(void)
  2. {
  3.         GPIO_InitTypeDef GPIO_InitStructure;

  4.         RCC_APB2PeriphClockCmd(RCC_I2C_PORT, ENABLE);       

  5.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  6.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;       
  7.        
  8.         GPIO_InitStructure.GPIO_Pin = PIN_I2C_SCL;
  9.         GPIO_Init(PORT_I2C_SCL, &GPIO_InitStructure);

  10.         GPIO_InitStructure.GPIO_Pin = PIN_I2C_SDA;
  11.         GPIO_Init(PORT_I2C_SDA, &GPIO_InitStructure);
  12.         i2c_Stop();
  13. }
  14. static void i2c_Delay(void)
  15. {
  16.         uint8_t i;
  17.         for (i = 0; i < 30; i++);
  18. }
  19. void i2c_Start(void)
  20. {
  21.         SetSDA_OUT();
  22.         I2C_SDA_1();
  23.         I2C_SCL_1();
  24.         i2c_Delay();
  25.         I2C_SDA_0();
  26.         i2c_Delay();
  27.        
  28.         I2C_SCL_0();
  29.         i2c_Delay();
  30. }
  31. void i2c_Stop(void)
  32. {
  33.         SetSDA_OUT();
  34.         I2C_SDA_0();
  35.         I2C_SCL_1();
  36.         i2c_Delay();
  37.         I2C_SDA_1();
  38.         i2c_Delay();
  39. }
  40. void i2c_SendByte(uint8_t _ucByte)
  41. {
  42.         uint8_t i;
  43.         SetSDA_OUT();
  44.         for (i = 0; i < 8; i++)
  45.         {
  46.                 if (_ucByte & 0x80)
  47.                 {
  48.                         I2C_SDA_1();
  49.                 }
  50.                 else
  51.                 {
  52.                         I2C_SDA_0();
  53.                 }
  54.                 i2c_Delay();
  55.                 I2C_SCL_1();
  56.                 i2c_Delay();
  57.                 I2C_SCL_0();
  58.                 if (i == 7)
  59.                 {
  60.                          I2C_SDA_1();
  61.                 }
  62.                 _ucByte <<= 1;       
  63.                 i2c_Delay();
  64.         }
  65. }
  66. uint8_t i2c_ReadByte(void)
  67. {
  68.         uint8_t i;
  69.         uint8_t value;
  70.         SetSDA_IN();
  71.         value = 0;
  72.         for (i = 0; i < 8; i++)
  73.         {
  74.                 value <<= 1;
  75.                 I2C_SCL_1();
  76.                 i2c_Delay();
  77.                 if (I2C_SDA_READ())
  78.                 {
  79.                         value++;
  80.                 }
  81.                 I2C_SCL_0();
  82.                 i2c_Delay();
  83.         }
  84.         return value;

  85. }
  86. uint8_t i2c_WaitAck(void)
  87. {
  88.         uint8_t re;
  89.         SetSDA_IN();
  90.         I2C_SDA_1();       
  91.         i2c_Delay();
  92.         I2C_SCL_1();       
  93.         i2c_Delay();
  94.         if (I2C_SDA_READ())       
  95.         {
  96.                 re = 1;
  97.         }
  98.         else
  99.         {
  100.                 re = 0;
  101.         }
  102.         I2C_SCL_0();
  103.         i2c_Delay();
  104.         return re;
  105. }
  106. void i2c_Ack(void)
  107. {
  108.         I2C_SDA_0();       
  109.         i2c_Delay();
  110.         I2C_SCL_1();       
  111.         i2c_Delay();
  112.         I2C_SCL_0();
  113.         i2c_Delay();
  114.         I2C_SDA_1();       
  115. }
  116. void i2c_NAck(void)
  117. {
  118.         I2C_SDA_1();       
  119.         i2c_Delay();
  120.         I2C_SCL_1();       
  121.         i2c_Delay();
  122.         I2C_SCL_0();
  123.         i2c_Delay();
  124. }
  125. uint8_t i2c_CheckDevice(uint8_t _Address)
  126. {
  127.         uint8_t ucAck;

  128.         if (I2C_SDA_READ() && I2C_SCL_READ())
  129.         {
  130.                 i2c_Start();               
  131.                
  132.                 i2c_SendByte(_Address | I2C_WR);
  133.                 ucAck = i2c_WaitAck();

  134.                 i2c_Stop();                       

  135.                 return ucAck;
  136.         }
  137.         return 1;       
  138. }
复制代码

以上便是STM32F103模拟I2C的全部操作。
————————————————
版权声明:TangPeng_HanMO

收藏 评论0 发布时间:2022-12-7 16:03

举报

0个回答

所属标签

相似分享

官网相关资源

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