找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1673|回复: 7
打印 上一主题 下一主题
收起左侧

发送完地址后24c02一直不产生应答,附单片机程序

[复制链接]
跳转到指定楼层
楼主
ID:967353 发表于 2021-9-21 16:43 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
  1. #include "mpu_i2c.h"
  2. #include "usart.h"

  3. //配置i2c端口
  4. void I2C_GPIO_Config(void)
  5. {
  6.         //定义结构体
  7.         GPIO_InitTypeDef  GPIO_InitStruct;
  8.         
  9.         //打开SDA与SCL端口时钟
  10.         RCC_APB2PeriphClockCmd(I2C_SDA_CLK,ENABLE);
  11.         RCC_APB2PeriphClockCmd(I2C_SCL_CLK,ENABLE);
  12.         
  13.         //配置SDA端口
  14.   GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD;//开漏复用输出
  15.         GPIO_InitStruct.GPIO_Pin = I2C_SDA_Pin;
  16.         GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
  17.   GPIO_Init(I2C_SDA_PORT,&GPIO_InitStruct);        

  18.         //配置SCL端口
  19.   GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD;//开漏复用输出
  20.         GPIO_InitStruct.GPIO_Pin = I2C_SCL_Pin;
  21.         GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
  22.   GPIO_Init(I2C_SCL_PORT,&GPIO_InitStruct);        

  23. }


  24. void I2C_InitConfig(void)
  25. {
  26.         I2C_GPIO_Config();
  27. }


  28. void delay(void)
  29. {
  30.         uint8_t time = 10;
  31.         while(time--)
  32.         {
  33.         }
  34. }


  35. void I2C_START(void)
  36. {
  37.         SDA_OUT();
  38.         I2C_SDA_1();
  39.         I2C_SCL_1();
  40.         delay();
  41.         I2C_SDA_0();
  42.         delay();
  43.         I2C_SCL_0();
  44.         delay();
  45. }

  46. void  I2C_STOP(void)
  47. {
  48.         SDA_OUT();
  49.         I2C_SDA_0();
  50.         I2C_SCL_1();
  51.         delay();
  52.         I2C_SDA_0();
  53.         delay();
  54. }

  55. void I2C_Ack(void)
  56. {
  57.         I2C_SCL_0();
  58.         I2C_SDA_1();
  59.         delay();
  60.         I2C_SDA_1();
  61.         delay();
  62.         I2C_SDA_0();
  63.         delay();
  64.         I2C_SCL_1();
  65.         delay();
  66.         I2C_SCL_0();
  67.         delay();
  68.         I2C_SDA_1();
  69. }

  70. void I2C_NACK(void)
  71. {
  72.         I2C_SCL_0();
  73.         I2C_SDA_0() ;
  74.         delay();
  75.         I2C_SDA_1();
  76.         delay();
  77.         I2C_SCL_1();
  78.         delay();
  79.         I2C_SCL_0();
  80.         delay();
  81.         I2C_SDA_0();
  82.         delay();
  83. }

  84. void I2C_Sent_Byte(uint8_t msg)
  85. {
  86.         uint8_t i;
  87.         SDA_OUT();
  88.   I2C_SCL_0();
  89.         delay();
  90.         /* 先发送字节的高位bit7 */
  91.         for (i = 0; i < 8; i++)
  92.         {               
  93.                 if (msg & 0x80 ==1)
  94.                 {
  95.                 I2C_SDA_1();
  96.                 }
  97.                 else
  98.                 {
  99.                 I2C_SDA_0();
  100.                 }
  101.                 delay();
  102.                 I2C_SCL_1();
  103.                 delay();        
  104.                 I2C_SCL_0();
  105.                 if (i == 7)
  106.                 {
  107.                 I2C_SDA_1(); // 释放总线
  108.                 }
  109.                 msg <<= 1;        /* 左移一个bit */
  110.                 delay();
  111.         }
  112.         I2C_SCL_0();
  113. }


  114. uint8_t I2C_Read_Byte(void)
  115. {
  116.         uint8_t i;
  117.         uint8_t receive = 0;
  118.         
  119.         /* 读到的第一位为数据的7bit位!!!
  120.            所以每次读取数据时都要将数据左移一位*/
  121.         
  122.         I2C_SCL_1();//锁定SCL线,确保其稳定

  123.         for(i=0;i<8;i++)
  124.         {
  125.                 receive <<= 1;
  126.                 I2C_SCL_0();//读取数据时拉低SCL
  127.                 delay();
  128.                 if(I2C_SDA_State() == 1)
  129.                 {
  130.                         receive++;
  131.                 }
  132.                 I2C_SCL_0();
  133.                 delay();
  134.                
  135.         }
  136.         
  137.         return receive;
  138. }


  139. void delay_us(uint8_t i)
  140. {
  141.         while(i--)
  142.         {
  143.         }
  144. }

  145. uint8_t I2C_WaitAck(void)
  146. {
  147.         uint8_t re;

  148.         I2C_SDA_1();        /* CPU释放SDA总线 */
  149.         delay();
  150.         I2C_SCL_1();        /* CPU驱动SCL = 1, 此时器件会返回ACK应答 */
  151.         delay();
  152.         if (I2C_SDA_State())        /* CPU读取SDA口线状态 */
  153.         {
  154.                 re = 1;
  155.         }
  156.         else
  157.         {
  158.                 re = 0;
  159.         }
  160.         I2C_SCL_0();
  161.         delay();
  162.         return re;
  163. }






  164. uint8_t  EEPROM_Byte_Write(uint16_t _usAddress, uint16_t data)
  165. {
  166.         uint8_t i;
  167.         //开始信号
  168.         I2C_START();
  169.         //发送地址
  170.         I2C_Sent_Byte(Slave_Addr | I2C_Write);
  171.         //检测应答
  172.         //delay();
  173.         //return printf("SDA的状态为:%d\n",I2C_SDA_State());
  174.         if(I2C_WaitAck() != 0)
  175.         {
  176.                 return printf("写入失败,未检测到响应1\n");
  177.         }
  178.         //发送从机中的数据地址(起始地址)
  179.         I2C_Sent_Byte(_usAddress);
  180.   //检测应答
  181.         if(I2C_WaitAck() != 0)
  182.         {
  183.                 return printf("写入失败,未检测到响应2\n");
  184.         }
  185.         
  186.         for(i=0;i<8;i++)
  187.         {
  188.                 I2C_Sent_Byte(data & 0x80);
  189.                 I2C_Ack();
  190.                 data <<= 1;
  191.         }
  192.         return printf("写入完成!!!\n");
  193. }




  194. uint8_t  EEPROM_Byte_Read(uint8_t *_pReadBuf, uint16_t _usAddress, uint16_t _usSize)
  195. {
  196.         uint8_t i;
  197.         //开始信号
  198.         
  199.         //test SDA
  200.         //return printf("开始信号前SDA状态为:%d\n",READ_I2C_SDA());
  201.         
  202.         I2C_START();
  203.         //发送地址
  204.         
  205.         //test SDA
  206.         //return printf("开始信号后SDA状态为:%d\n",READ_I2C_SDA());
  207.         
  208.         I2C_Sent_Byte(Slave_Addr | I2C_Write);

  209.         //test SDA
  210.         //return printf("发送地址后SDA状态为:%d\n",READ_I2C_SDA());
  211.         
  212.         //检测应答
  213.         if(I2C_WaitAck() != 0)
  214.         {
  215.                 return printf("读取失败,未检测到响应1\n");
  216.         }
  217.         //发送从机中的数据地址(起始地址)
  218.         I2C_Sent_Byte(_usAddress);
  219.   //检测应答
  220.         if(I2C_WaitAck() != 0)
  221.         {
  222.                 return printf("读取失败,未检测到响应2\n");
  223.         }
  224.         //开始信号
  225.         I2C_START();
  226.         //发送地址
  227.         I2C_Sent_Byte(Slave_Addr | I2C_Read);
  228.          //检测应答
  229.         if(I2C_WaitAck() != 0)
  230.         {
  231.                 return printf("读取失败,未检测到响应3\n");
  232.         }
  233.         
  234.         //读取数据
  235.         for(i=0;i< _usSize;i++)
  236.         {

  237. //                if(I2C_GetFlagStatus(I2C_Driver,I2C_FLAG_BUSY) == SET)
  238. //                {
  239. //                        return printf("他妈的锁死了,读取失败\n");
  240. //                }
  241.                
  242.                 _pReadBuf[i] = I2C_Read_Byte();//每次读取一个字节
  243.                 if(i != (_usSize-1))
  244.                 {
  245.                         I2C_Ack();
  246.                 }
  247.                 else
  248.                 {
  249.                         I2C_NACK();
  250.                 }
  251.         }
  252.         
  253.         //发送停止信号
  254.         I2C_STOP();
  255.         
  256.         return printf("读取完成!\n");
  257.         
  258. }
复制代码
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:967353 发表于 2021-9-21 16:44 | 只看该作者
前前后后搞了几天了,真不知道问题出在了哪里
回复

使用道具 举报

板凳
ID:123289 发表于 2021-9-21 22:28 | 只看该作者
用示波器看通讯的波形,是否与手册上说的相符。
回复

使用道具 举报

地板
ID:161164 发表于 2021-9-21 23:17 | 只看该作者
放入Protues仿真看波型时序
如有硬件示波器更好
回复

使用道具 举报

5#
ID:887202 发表于 2021-9-22 09:20 | 只看该作者
你的IIC_READ_BYTE函数,读取数据的时候为什么要先把SCL拉低????应该是先把SCL拉高,然后读取数据再拉低循环8次。按照你的操作,先把SCL拉高,读取之前又拉低了,这时候你读取即可能是高电平也可能是低电平,根据IIC的协议,这时候SDA上的电平是允许变化的,所以这么读是有问题的。建议你用逻辑分析仪去抓一下IIC,然后再结合你的代码分析。最好去看一下别人的IIC怎么写的,参考一下
回复

使用道具 举报

6#
ID:624769 发表于 2021-9-22 17:10 | 只看该作者
没仔细看,但是,看到STOP就觉得不太对劲了……
STOP 不是应该拉高时钟之后,拉高数据线么?为什么,拉高时钟之后,你SDA 还是 0?
void  I2C_STOP(void)
{
        SDA_OUT();
        I2C_SDA_0();
        I2C_SCL_1();
        delay();
        I2C_SDA_0();      // 这里不应该  SDA 1 么?
        delay();
}

你仔细看看你的整个时序 我感觉 你的 读 ACK 那里 也 少一个 CLK 0,所以读不到 ACK
回复

使用道具 举报

7#
ID:668885 发表于 2021-9-22 17:28 | 只看该作者
用逻辑分析仪,抓波形,看发送接收有没有问题
回复

使用道具 举报

8#
ID:887202 发表于 2021-9-22 17:51 | 只看该作者
整个IIC的起始信号,停止信号等都有问题啊,都不用逻辑分析仪抓了,肯定通讯不成功的,你去看别人写好的IIC吧,对照着IIC的协议时序仔细看
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表