IIC 总线通信 主机接收一个字节时,为什么要在一开始令SDA=1

2019-07-15 14:56发布


友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
7条回答
michael_llh
1楼-- · 2019-07-15 15:59
楼主能够说得更详细一点吗?
具体你是IIC通信双方是谁,同时应该严格安装通信双发给的同时时序进行编写
jiciwi
2楼-- · 2019-07-15 21:45
有个起始条件的吧
福华
3楼-- · 2019-07-15 23:53
michael_llh 发表于 2016-2-25 20:31
楼主能够说得更详细一点吗?
具体你是IIC通信双方是谁,同时应该严格安装通信双发给的同时时序进行编写

单片机STC90C51和EEPROM AT24C16通信
  1. #include"i2c.h"

  2. /*******************************************************************************
  3. * 函 数 名         : Delay1us()
  4. * 函数功能                   : 延时
  5. * 输    入         : 无
  6. * 输    出         : 无
  7. *******************************************************************************/

  8. void I2C_Delay10us()
  9. {
  10.         uchar a, b;
  11.         for(b=1; b>0; b--)
  12.         {
  13.                 for(a=2; a>0; a--);
  14.         }
  15. }
  16. /*******************************************************************************
  17. * 函 数 名         : I2C_Start()
  18. * 函数功能                   : 起始信号:在I2C_SCL时钟信号在高电平期间I2C_SDA信号产生一个下降沿
  19. * 输    入         : 无
  20. * 输    出         : 无
  21. * 备    注         : 起始之后I2C_SDA和I2C_SCL都为0
  22. *******************************************************************************/

  23. void I2C_Start()
  24. {
  25.         I2C_SDA = 1;
  26.         I2C_Delay10us();
  27.         I2C_SCL = 1;
  28.         I2C_Delay10us();//建立时间是I2C_SDA保持时间>4.7us
  29.         I2C_SDA = 0;
  30.         I2C_Delay10us();//保持时间是>4us
  31.         I2C_SCL = 0;                       
  32.         I2C_Delay10us();               
  33. }
  34. /*******************************************************************************
  35. * 函 数 名           : I2C_Stop()
  36. * 函数功能                 : 终止信号:在I2C_SCL时钟信号高电平期间I2C_SDA信号产生一个上升沿
  37. * 输    入           : 无
  38. * 输    出                  : 无
  39. * 备    注           : 结束之后保持I2C_SDA和I2C_SCL都为1;表示总线空闲
  40. *******************************************************************************/

  41. void I2C_Stop()
  42. {
  43.         I2C_SDA = 0;
  44.         I2C_Delay10us();
  45.         I2C_SCL = 1;
  46.         I2C_Delay10us();//建立时间大于4.7us
  47.         I2C_SDA = 1;
  48.         I2C_Delay10us();               
  49. }
  50. /*******************************************************************************
  51. * 函 数 名           : I2cSendByte(uchar num)
  52. * 函数功能                  : 通过I2C发送一个字节。在I2C_SCL时钟信号高电平期间,
  53. *                    * 保持发送信号I2C_SDA保持稳定
  54. * 输    入           : num ,ack
  55. * 输    出                  : 0或1。发送成功返回1,发送失败返回0
  56. * 备    注           : 发送完一个字节I2C_SCL=0, 需要应答则应答设置为1,否则为0
  57. *******************************************************************************/

  58. uchar I2C_SendByte(uchar dat, uchar ack)
  59. {
  60.         uchar a = 0,b = 0;//最大255,一个机器周期为1us,最大延时255us。
  61.                        
  62.         for(a=0; a<8; a++)//要发送8位,从最高位开始
  63.         {
  64.                 I2C_SDA = dat >> 7;         //起始信号之后I2C_SCL=0,所以可以直接改变I2C_SDA信号
  65.                 dat = dat << 1;
  66.                 I2C_Delay10us();
  67.                 I2C_SCL = 1;
  68.                 I2C_Delay10us();//建立时间>4.7us
  69.                 I2C_SCL = 0;
  70.                 I2C_Delay10us();//时间大于4us               
  71.         }

  72.         I2C_SDA = 1;
  73.         I2C_Delay10us();
  74.         I2C_SCL = 1;
  75.         while(I2C_SDA && (ack == 1))//等待应答,也就是等待从设备把I2C_SDA拉低
  76.         {
  77.                 b++;
  78.                 if(b > 200)         //如果超过200us没有应答发送失败,或者为非应答,表示接收结束
  79.                 {
  80.                         I2C_SCL = 0;
  81.                         I2C_Delay10us();
  82.                         return 0;
  83.                 }
  84.         }

  85.         I2C_SCL = 0;
  86.         I2C_Delay10us();
  87.         return 1;               
  88. }
  89. /*******************************************************************************
  90. * 函 数 名           : I2cReadByte()
  91. * 函数功能                     : 使用I2c读取一个字节
  92. * 输    入           : 无
  93. * 输    出                  : dat
  94. * 备    注           : 接收完一个字节I2C_SCL=0
  95. *******************************************************************************/

  96. uchar I2C_ReadByte()
  97. {
  98.         uchar a = 0,dat = 0;
  99.         I2C_SDA = 1;                        //为什么?????????????????????????
  100.         I2C_Delay10us();
  101.         for(a=0; a<8; a++)//接收8个字节
  102.         {
  103.                 I2C_SCL = 1;
  104.                 I2C_Delay10us();
  105.                 dat <<= 1;
  106.                 dat |= I2C_SDA;
  107.                 I2C_Delay10us();
  108.                 I2C_SCL = 0;
  109.                 I2C_Delay10us();
  110.         }
  111.         return dat;               
  112. }
复制代码
福华
4楼-- · 2019-07-16 03:01
 精彩回答 2  元偷偷看……
michael_llh
5楼-- · 2019-07-16 06:30
好好看一下AT24C16的操作时序就知道为什么这么写了,从bus time那一章好好看一下就可以明白。不懂再留言

datasheet.pdf (444.98 KB, 下载次数: 53)
福华
6楼-- · 2019-07-16 08:41
michael_llh 发表于 2016-2-28 00:08
好好看一下AT24C16的操作时序就知道为什么这么写了,从bus time那一章好好看一下就可以明白。不懂再留言

http://a4.qpic.cn/psb?/38930a9a- ... CIMC1hhMJy1TDYZ7M61*oD9Q1eO59BSo!/b/dFcBAAAAAAAA&ek=1&kp=1&pt=0&bo=nwVXAp8FVwIFACM!&sce=0-12-12&rf=viewer_311
单片机从AT24C16接收数据时序看SDA OUT没错吧
实在看不出来为什么接收时单片机必须把SDA拉高?
(我英语昨天刚过4级)

一周热门 更多>