请选择 进入手机版 | 继续访问电脑版

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

基于STM32软件实现底层函数经验分享—IIC通信

[复制链接]
攻城狮Melo 发布时间:2023-3-18 15:50
使用GPIO引脚模拟SDA和SCL总线实现软件模拟IIC通信,IIC的具体通信协议层和物理层链接:
  1. #ifndef __BSP_IIC_H
  2. #define __BSP_IIC_H

  3. #include "stm32f10x.h"



  4. #define SCL_PORT         GPIOA
  5. #define SCL_PIN          GPIO_Pin_2
  6. #define SCL_MOOD         GPIO_Mode_Out_OD
  7. #define SCL_SPEED        GPIO_Speed_50MHz

  8. #define SDA_PORT         GPIOA
  9. #define SDA_PIN          GPIO_Pin_3
  10. #define SDA_MOOD         GPIO_Mode_Out_OD
  11. #define SDA_SPEED        GPIO_Speed_50MHz

  12. #define SDA_1()          GPIO_SetBits(SDA_PORT, SDA_PIN)
  13. #define SDA_0()          GPIO_ResetBits(SDA_PORT, SDA_PIN)

  14. #define SCL_1()          GPIO_SetBits(SCL_PORT, SCL_PIN)
  15. #define SCL_0()          GPIO_ResetBits(SCL_PORT, SCL_PIN)

  16. #define SDA_READ         GPIO_ReadInputDataBit(SDA_PORT, SDA_PIN)


  17. /* ACK原型为acknowledge,意为:报告已收到 */
  18. void Delay(void);
  19. void IIC_START(void);
  20. void IIC_STOP(void);
  21. void IIC_ACK(void);
  22. void IIC_NACK(void);
  23. uint8_t IIC_ReadACK(void);
  24. void IIC_SendByte(uint8_t data)        ;
  25. uint8_t IIC_ReadByte(void);
  26. void IIC_GPIO_Config(void);




  27. #endif     /* __BSP_IIC_H */

复制代码


  1. void Delay(void)
  2. {
  3.         uint8_t i;

  4.         /* 
  5.                  下面的时间是通过逻辑分析仪测试得到的。
  6.     工作条件:CPU主频72MHz ,MDK编译环境,1级优化
  7.   
  8.                 循环次数为10时,SCL频率 = 205KHz
  9.                 循环次数为7时,SCL频率 = 347KHz, SCL高电平时间1.5us,SCL低电平时间2.87us
  10.                  循环次数为5时,SCL频率 = 421KHz, SCL高电平时间1.25us,SCL低电平时间2.375us
  11.         */
  12.         for (i = 0; i < 10; i++);
  13. }


  14. /* SCL高电平时期SDA产生下降沿表示起始信号 */
  15. void IIC_START(void)
  16. {
  17.         SDA_1();
  18.         SCL_1();
  19.         Delay();
  20.        
  21.         SDA_0();
  22.         Delay();
  23.         SCL_0();
  24.         Delay();
  25. }



  26. /* SCL高电平时期SDA产生上升沿表示停止信号 */
  27. void IIC_STOP(void)
  28. {
  29.         SDA_0();
  30.         SCL_1();
  31.         Delay();
  32.        
  33.         SDA_1();
  34.         Delay();
  35.   /* 停止信号后SDA和SCL都为高电平 */
  36. }


  37. /* SCL高电平时期 SDA保持低电平代表 应答信号 */
  38. void IIC_ACK(void)
  39. {
  40.         SDA_0();
  41.         Delay();
  42.         SCL_1();
  43.         Delay();
  44.        
  45.         SCL_0();
  46.         Delay();
  47.         SDA_1();
  48. /* 随后释放SDA总线 */
  49. }


  50. /* SCL高电平时期 SDA保持高电平代表 非应答信号 */
  51. void IIC_NACK(void)
  52. {
  53.         SDA_1();
  54.         Delay();
  55.         SCL_1();
  56.         Delay();
  57.        
  58.         SCL_0();
  59. /* SDA已经为高电平,无需释放 */
  60. }


  61. /* CPU产生一个SCL时钟,读取应答  ACK:0   NACK:1*/
  62. /* 因为SDA平时为高电平,所以没有收到应答时,SDA还为高电平,即读取到 1 为非应答 */
  63. uint8_t IIC_ReadACK(void)
  64. {
  65.         uint8_t k;
  66.         /* 释放SDA总线 */
  67.         SDA_1();
  68.         Delay();
  69.         /* SCL为高电平时,才会读取有效数据 */
  70.         SCL_1();
  71.         Delay();
  72.        
  73.         /* 读取信号 */
  74.         if(SDA_READ==1)
  75.                 k=1;
  76.         else
  77.                 k=0;
  78.         /* 收到信号后SCL要拉低 */
  79.         SCL_0();
  80.         Delay();
  81.         return k;
  82. }


  83. /* 发送一个字节,先发送高位 */
  84. void IIC_SendByte(uint8_t data)
  85. {
  86.         uint8_t n=0x01;
  87.         int i;
  88.         SCL_0();
  89.         Delay();
  90.         for(i=7;i>=0;i--)
  91.         {
  92.                 if(n&(data>>i))
  93.                 {
  94.                         SDA_1();
  95.                         Delay();
  96.                         SCL_1();
  97.                         Delay();
  98.                 }
  99.                 else
  100.                 {
  101.                         SDA_0();
  102.                         Delay();
  103.                         SCL_1();
  104.                         Delay();
  105.                 }
  106.                 SCL_0();
  107.                 Delay();
  108.         }
  109.         /* 发送完一个字节后释放SDA总线 */
  110.         SDA_1();
  111.         Delay();
  112.        
  113. }

  114. /* 读取一个字节,在CPU产生的SCL高电平时期读取 */
  115. uint8_t IIC_ReadByte(void)
  116. {
  117. //        uint8_t i,data=0;
  118. //        for(i=0;i<8;i++)
  119. //        {
  120. //                SCL_1();
  121. //                Delay();
  122. //                if(SDA_READ)
  123. //                {
  124. //                        data++; /* 利用自增实现对最低位写 1  */
  125. //                }
  126. //                data<<=1;
  127. //                SCL_0();
  128. //                Delay();
  129. //               
  130. //        }
  131. //        return data;
  132. //       
  133.        
  134.         uint8_t i;
  135.        
  136.         uint8_t temp = 0;
  137.        
  138.         for(i=0;i<8;i++)
  139.         {               
  140.                 temp<<=1;
  141.                
  142.                 SCL_1();
  143.                 Delay();
  144.                
  145.                 if( SDA_READ==1 )
  146.                 {
  147.                         temp += 1;
  148.                 }
  149.                
  150.                 SCL_0();
  151.                 Delay();
  152.         }               
  153.        
  154.         return temp;
  155. }



  156. /* 配置SCL和SDA对应的GPIO引脚,模式都为开漏输出 */
  157. void IIC_GPIO_Config(void)
  158. {
  159.         GPIO_InitTypeDef GPIO_InitStruct;
  160.        
  161.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  162.        
  163.         GPIO_InitStruct.GPIO_Pin = SCL_PIN;
  164.         GPIO_InitStruct.GPIO_Mode = SCL_MOOD;
  165.         GPIO_InitStruct.GPIO_Speed = SCL_SPEED;
  166.         GPIO_Init(SCL_PORT, &GPIO_InitStruct);
  167.        
  168.   GPIO_InitStruct.GPIO_Pin = SDA_PIN;
  169.         GPIO_InitStruct.GPIO_Mode = SDA_MOOD;
  170.         GPIO_InitStruct.GPIO_Speed = SDA_SPEED;
  171.         GPIO_Init(SDA_PORT, &GPIO_InitStruct);
  172.        
  173. /* 给一个停止信号,使IIC总线上所有设备处于复位 */
  174.         IIC_STOP();
  175.        
  176. }


复制代码
转载自:Aspirant-GQ
如有侵权请联系删除


收藏 评论0 发布时间:2023-3-18 15:50

举报

0个回答
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版