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

分析一个STM32模拟I2C的代码,亲测可用

[复制链接]
阿松松 发布时间:2015-1-5 14:17
I2C配置顺序引发的异常案例

基于stm32的I2C总线通讯简介及使用操作(附代码)

分享关于STM32f103 的硬件IIC I2C 调试心得


楼主前段时间苦调UV传感器,无奈硬件I2C怎么也用不起来,楼主水平还是太弱,无奈只好转入软件模拟I2C,不过话说模拟I2C的波形似乎要比硬件I2C的要好很多呢。调好的代码与大家分享下。。。源模板是哥们做好的读取E2的代码。
  1. #include "stm32f10x.h"
  2. //===============================================================================
  3. //GPIO 模拟I2C ,操作EP2ROM IC(AT24C02)
  4. #define  E2PROM_SDA  GPIO_Pin_7
  5. #define  E2PROM_SCL  GPIO_Pin_6
  6. #define  E2PROM_CMD_WRITE  0xa0
  7. #define  E2PROM_CMD_READ   0xa1
  8. #define        I2C_DELAY                    254                                                        //

  9. I2C延时

  10. static void
  11. DelayMs(uint8_t uc)
  12. {
  13.         uint8_t        i, j;

  14.         for (i=0; i<uc; i++) {
  15.                 for (j=0; j<I2C_DELAY; j++);
  16.         }
  17. }
  18. /*************************************************************
  19. *函数名称:I2CStart
  20. *函数功能:I2C开始信号
  21. *输入参数:
  22. *输出参数:
  23. *备           注:时钟线高时,数据线由高到低的跳变,表示I2C开始信号
  24. **************************************************************/
  25. void I2CStart( void )
  26. {
  27.   GPIO_SetBits( GPIOB, E2PROM_SDA );
  28.   DelayMs(1);
  29.   GPIO_SetBits( GPIOB, E2PROM_SCL );
  30.   DelayMs(1);
  31.   GPIO_ResetBits( GPIOB, E2PROM_SDA );
  32.   DelayMs(1);

  33.   GPIO_ResetBits( GPIOB, E2PROM_SCL );
  34. }

  35. /*************************************************************
  36. *函数名称:I2CStop
  37. *函数功能:I2C停止信号
  38. *输入参数:
  39. *输出参数:
  40. *备           注:时钟线高时,数据线由低到高的跳变,表示I2C停止信号
  41. **************************************************************/
  42. void I2CStop( void )
  43. {
  44.   GPIO_ResetBits( GPIOB, E2PROM_SDA );
  45.   DelayMs(1);
  46.   GPIO_SetBits( GPIOB, E2PROM_SCL );
  47.   DelayMs(1);
  48.   GPIO_SetBits( GPIOB, E2PROM_SDA );
  49.   DelayMs(1);

  50.   GPIO_ResetBits( GPIOB, E2PROM_SCL );
  51. }

  52. /*************************************************************
  53. *函数名称:I2CSlaveAck
  54. *函数功能:I2C从机设备应答查询
  55. *输入参数:
  56. *输出参数:
  57. *备           注:
  58. **************************************************************/
  59. unsigned char I2CSlaveAck( void )
  60. {
  61.   GPIO_InitTypeDef GPIO_InitStruct;
  62.   unsigned int TimeOut;
  63.   unsigned char RetValue;

  64.   GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;  /*这里一定要设成输入上拉,否则不能读出数据*/
  65.   GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
  66.   GPIO_InitStruct.GPIO_Pin = E2PROM_SDA;
  67.   GPIO_Init( GPIOB, &GPIO_InitStruct );

  68.   GPIO_SetBits( GPIOB, E2PROM_SCL );
  69.   TimeOut = 10000;
  70.   while( TimeOut-- > 0 )
  71.   {
  72.     if( SET == GPIO_ReadInputDataBit( GPIOB, E2PROM_SDA ) )
  73.     {
  74.       RetValue = RESET;
  75.       break;
  76.     }
  77.     else
  78.     {
  79.       RetValue = SET;
  80.     }
  81.   }
  82.   GPIO_ResetBits( GPIOB, E2PROM_SCL );
  83.    
  84.   GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
  85.   GPIO_Init( GPIOB, &GPIO_InitStruct );
  86.   return RetValue;
  87. }

  88. /*************************************************************
  89. *函数名称:I2CWriteByte
  90. *函数功能:I2C写一字节数据
  91. *输入参数:
  92. *输出参数:
  93. *备           注:
  94. **************************************************************/
  95. void I2CWriteByte( unsigned char byte )
  96. {
  97.   unsigned char i;

  98.   for( i=0; i<8; i++ )
  99.   {
  100.     if( 0X80 & byte )
  101.       GPIO_SetBits( GPIOB, E2PROM_SDA );
  102.     else
  103.       GPIO_ResetBits( GPIOB, E2PROM_SDA );
  104.     byte <<= 1;
  105.     DelayMs(1);

  106.     GPIO_SetBits( GPIOB, E2PROM_SCL );
  107.     DelayMs(1);
  108.     GPIO_ResetBits( GPIOB, E2PROM_SCL );
  109.     DelayMs(1);
  110.   }
  111. }

  112. /*************************************************************
  113. *函数名称:I2CReadByte
  114. *函数功能:I2C读一字节数据
  115. *输入参数:
  116. *输出参数:
  117. *备           注:
  118. **************************************************************/
  119. unsigned char I2CReadByte( void )
  120. {
  121.   unsigned char i;
  122.   unsigned char ReadValue = 0;
  123.   GPIO_InitTypeDef GPIO_InitStruct;
  124.   unsigned char bit;

  125.   GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;  /*这里一定要设成输入上拉,否则不能读出数据*/
  126.   GPIO_InitStruct.GPIO_Pin = E2PROM_SDA;
  127.   GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
  128.   GPIO_Init( GPIOB, &GPIO_InitStruct );
  129.   for( i=0; i<8; i++ )
  130.   {
  131.     GPIO_SetBits( GPIOB, E2PROM_SCL );
  132.     DelayMs(1);
  133.     if( SET == GPIO_ReadInputDataBit( GPIOB, E2PROM_SDA ) )
  134.       bit = 0X01;
  135.     else
  136.       bit = 0x00;
  137.       
  138.     ReadValue = (ReadValue<<1)|bit;
  139.     GPIO_ResetBits( GPIOB, E2PROM_SCL );
  140.     DelayMs(1);
  141.   }

  142.   GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
  143.   GPIO_Init( GPIOB, &GPIO_InitStruct );
  144.   return ReadValue;
  145. }

  146. /*************************************************************
  147. *函数名称:E2promWriteByte
  148. *函数功能:E2PROM指定地址写一字节数据
  149. *输入参数:addr  E2PROM地址
  150.                              data  写入的数据
  151. *输出参数:SET: 写入正常;RESET:写入错误
  152. *备           注:
  153. **************************************************************/
  154. uint8_t E2promWriteByte( uint16_t addr, uint8_t data )
  155. {
  156.   //asm("CPSID I");  //关中断
  157.   I2CStart();

  158.   I2CWriteByte( E2PROM_CMD_WRITE );
  159.   if( RESET == I2CSlaveAck() )
  160.   {
  161.     return RESET;
  162.   }/*
  163.   I2CWriteByte( (addr >> 8) & 0xFF );
  164.   if( RESET == I2CSlaveAck() )
  165.   {
  166.     return RESET;
  167.   } */
  168.   I2CWriteByte( addr & 0xFF);
  169.   if( RESET == I2CSlaveAck() )
  170.   {
  171.     return RESET;
  172.   }
  173.   I2CWriteByte( data );
  174.   if( RESET == I2CSlaveAck() )
  175.   {
  176.     return RESET;
  177.   }
  178.   I2CStop();
  179.   //asm("CPSIE I");  //关中断

  180.   return SET;
  181. }

  182. /*************************************************************
  183. *函数名称:E2promReadByte
  184. *函数功能:E2PROM指定地址读一字节数据
  185. *输入参数:addr  E2PROM地址
  186. *输出参数:返回读出的数据
  187. *备           注:
  188. **************************************************************/  
  189. uint8_t E2promReadByte( unsigned short int addr )
  190. {
  191.   unsigned char ReadValue;

  192.   I2CStart();

  193.   I2CWriteByte( E2PROM_CMD_WRITE );
  194.   if( RESET == I2CSlaveAck() )
  195.   {
  196.     return RESET;
  197.   }/*
  198.   I2CWriteByte( (addr >> 8) & 0xFF );
  199.   if( RESET == I2CSlaveAck() )
  200.   {
  201.     return RESET;
  202.   }  */
  203.   I2CWriteByte( addr & 0xFF );
  204.   if( RESET == I2CSlaveAck() )
  205.   {
  206.     return RESET;
  207.   }
  208.   I2CStart();
  209.   I2CWriteByte( E2PROM_CMD_READ );
  210.   if( RESET == I2CSlaveAck() )
  211.   {
  212.     return RESET;
  213.   }
  214.   ReadValue = I2CReadByte();
  215.   I2CStop();

  216.   return ReadValue;   
  217. }
复制代码


收藏 5 评论18 发布时间:2015-1-5 14:17

举报

18个回答
大秦正声 回答时间:2015-1-18 13:59:46
40./*************************************************************

41.*函数名称:I2CStop

42.*函数功能:I2C停止信号

43.*输入参数:

44.*输出参数:

45.*备           注:时钟线高时,数据线由低到高的跳变,表示I2C停止信号

46.**************************************************************/

47.void I2CStop( void )

48.{

49.  GPIO_ResetBits( GPIOB, E2PROM_SDA );

50.  DelayMs(1);

51.  GPIO_SetBits( GPIOB, E2PROM_SCL );

52.  DelayMs(1);

53.  GPIO_SetBits( GPIOB, E2PROM_SDA );

54.  DelayMs(1);

55.

///这句不要56.  GPIO_ResetBits( GPIOB, E2PROM_SCL );

57.}

阿松松 回答时间:2015-1-5 15:42:40
晓枫VS枯叶 发表于 2015-1-5 15:37
https://www.stmcu.org.cn/module/forum/thread-598153-1-1.html之前发过,你去看看吧!

嗯,十分感谢。。。
以后还是得和大家多交流,不能闭门造车,我那个硬件I2C自己吭哧吭哧搞了半个多月,也没结果
阿松松 回答时间:2015-1-5 15:33:49
晓枫VS枯叶 发表于 2015-1-5 15:22
我的F0上的I2C跑了两天两夜没死机(可能是侥幸),F4上的I2C能用但是没测试很长时间! ...

F4上的可用?
为什么我的就死活调试不通呢,从器件无法响应?

嗯,分享下经验
我们不能屈从权威
hlt512 回答时间:2015-1-5 15:05:12
好像1系列的,大家都用模拟IIC
阿松松 回答时间:2015-1-5 15:13:25
hlt512 发表于 2015-1-5 15:05
好像1系列的,大家都用模拟IIC

额,我一个4系列的也用的是模拟I2C,硬件的死活不通,记得有人给我说过是有问题,可是我的就是硬硬的不通,怎么破
晓枫VS枯叶 回答时间:2015-1-5 15:22:31
我的F0上的I2C跑了两天两夜没死机(可能是侥幸),F4上的I2C能用但是没测试很长时间!
晓枫VS枯叶 回答时间:2015-1-5 15:37:11
hlt512 回答时间:2015-1-5 16:48:45
阿松松 发表于 2015-1-5 15:13
额,我一个4系列的也用的是模拟I2C,硬件的死活不通,记得有人给我说过是有问题,可是我的就是硬硬的不通 ...

每个人对资料的理解不通,你理解估计有极限
mengqiqq 回答时间:2015-1-8 06:54:35
学习学习,楼主辛苦!
阿松松 回答时间:2015-1-8 16:54:49
hlt512 发表于 2015-1-5 16:48
每个人对资料的理解不通,你理解估计有极限

确实,所以还得仔细揣摩下,到底哪儿出问题了
相思谷 回答时间:2015-1-8 16:59:36
谢谢分享
阿松松 回答时间:2015-1-8 19:31:12

嗯,多多交流
大秦正声 回答时间:2015-1-8 19:39:27
很好!多谢
hlt512 回答时间:2015-1-13 10:01:23
阿松松 发表于 2015-1-8 16:54
确实,所以还得仔细揣摩下,到底哪儿出问题了

我是在加ST币的
12下一页

所属标签

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