找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 787|回复: 5
收起左侧

我的单片机+iic程序怎么读写不了? 搞了好几天搞不明白

[复制链接]
ID:1009775 发表于 2022-3-11 19:41 | 显示全部楼层 |阅读模式
求求大佬们看看哪出问题了,1602模块没问题 仿真里读出来的是一个黑块  

at24c02.c
  1. #include <reg52.h>
  2. #include <intrins.h>
  3. #define uchar unsigned char
  4. #define uint unsigned int
  5.         
  6. sbit SCK = P1^3;
  7. sbit SDA = P1^4;

  8. void Delayms(uint x);
  9. void Delayus(uchar x);
  10. void Delay5us();
  11. void Delay5ms();

  12. void init(){
  13.         SCK = 1;
  14.         _nop_();_nop_();_nop_();
  15.         SDA = 1;
  16.         _nop_();_nop_();_nop_();
  17. }
  18. void start(){
  19.         SCK = 1;
  20.         _nop_();_nop_();_nop_();
  21.         SDA = 1;
  22.         _nop_();_nop_();_nop_();
  23.         _nop_();_nop_();_nop_();
  24.         SDA = 0;
  25.         _nop_();_nop_();_nop_();
  26.         _nop_();_nop_();_nop_();
  27.         SCK = 0;
  28. }
  29.         
  30. void stop(){
  31.         SCK  =1;
  32.         SDA = 0;
  33.         _nop_();_nop_();_nop_();
  34.         _nop_();_nop_();_nop_();
  35.         SDA = 1;
  36.         _nop_();_nop_();_nop_();
  37.         _nop_();_nop_();_nop_();
  38.         SDA = 0;
  39.         SCK = 0;
  40. }
  41. void WaitAck(){
  42.         uchar i = 0;
  43.         SDA = 1;
  44.         SCK = 1;
  45.         Delayus(5);
  46.         while(SDA == 1 && (i < 250))
  47.                 i++;
  48.         SCK = 0;
  49.         _nop_(), _nop_(), _nop_();
  50. }


  51. //void react(){
  52. //        SCK = 0;
  53. //        SDA = 1;
  54. //        SDA = 0;
  55. //        SCK = 1;
  56. //        _nop_();_nop_();_nop_();
  57. //        _nop_();_nop_();_nop_();
  58. //        SCK = 0;
  59. //        SDA = 1;
  60. //}
  61. void noack(){
  62.          SDA=1;
  63.          _nop_();_nop_();_nop_();
  64.          SCK=1;
  65.          _nop_();_nop_();_nop_();
  66.                 _nop_();_nop_();_nop_();
  67.          SCK=0;
  68.          _nop_();_nop_();_nop_();
  69.                 SDA = 0;
  70. }

  71. uchar readByte(){
  72.         uchar i, k = 0;
  73.         for(i = 0; i < 8; i++){
  74.                 SCK = 0;
  75.                 k <<= 1;
  76.                 Delay5us();        
  77.                 if(SDA == 1){
  78.                         k |= 0x01;
  79.                 }
  80.                 SCK = 0;
  81.                 Delay5us();
  82.         }
  83.         _nop_();
  84.         Delay5ms();
  85.         return k;
  86. }

  87. void writeByte(uchar dat){
  88.         uchar i = 0;
  89.         for(i = 0; i < 8; i++){
  90.                 SCK = 0;
  91.                 Delay5us();
  92.                 SDA = dat & 0x80;
  93.                 _nop_();_nop_();_nop_();_nop_();
  94.                 SCK = 1;
  95.                 Delay5us();
  96.                 dat <<= 1;
  97.         }
  98.         SCK = 0;
  99.         _nop_();_nop_();_nop_();
  100.         Delay5ms();
  101. }

  102. void addByte(uchar wordAddress, uchar dat){
  103.         start();
  104.         writeByte(0xa0);
  105.         WaitAck();
  106.         writeByte(wordAddress);
  107.         WaitAck();
  108.         writeByte(dat);
  109.         WaitAck();
  110.         stop();
  111.         Delayms(5);
  112. }

  113. uchar readAddByta(uchar wordAddress){
  114.         uchar dat;
  115.         start();
  116.         writeByte(0xa0);
  117.         WaitAck();
  118.         writeByte(wordAddress);
  119.         WaitAck();
  120.         stop();
  121.         start();
  122.         writeByte(0xa1);
  123.         WaitAck();
  124.         dat = readByte();
  125.         noack();
  126.         stop();
  127.         return dat;
  128. }

  129. void Delayms(uint x){
  130.         int i, j;
  131.         for(i = x; i > 0; --i){
  132.                 for(j = 110; j > 0; --j);
  133.         }
  134. }
  135. void Delayus(uchar x){
  136.         while(x--);
  137. }

  138. void Delay5us()                //@12.000MHz
  139. {
  140.         _nop_();
  141. }

  142. void Delay5ms()                //@12.000MHz
  143. {
  144.         unsigned char i, j;

  145.         i = 10;
  146.         j = 183;
  147.         do
  148.         {
  149.                 while (--j);
  150.         } while (--i);
  151. }
复制代码

main.c
  1. #include <reg52.h>
  2. #include <intrins.h>
  3. #include "at24c02.h"
  4. #include "proteus_1602.h"
  5. #define uchar unsigned char
  6. #define uint unsigned int
  7. sbit SCK = P1^3;
  8. sbit SDA = P1^4;
  9. void main(){
  10.         Delayms(2000);
  11.         while(1){
  12.                 uchar temp = 0;
  13.                 init();
  14.                 init_1602();
  15.                 addByte(0x00, 0x00);
  16.                 Delayms(10);
  17.                 temp = readAddByta(0x00);
  18.                 writeData_1602(temp + 0x38);
  19.                 Delayms(50);
  20.         }         
  21. }
复制代码



回复

使用道具 举报

ID:1009775 发表于 2022-3-11 19:42 | 显示全部楼层
1602模块没问题 仿真里读出来的是一个黑块  
回复

使用道具 举报

ID:488334 发表于 2022-3-12 02:56 | 显示全部楼层
IIC的时序很重要,最好尝试的用逻辑分析仪读一下时序,看看是不是时序出现问题,还有如果时序没问题的话,要看时间,比如起始信号,一高一低时间会不会太短,导致从机识别不了IIC的起始信号等等。
回复

使用道具 举报

ID:161164 发表于 2022-3-12 08:09 | 显示全部楼层
要贴就贴全一点
为什么不把at24c02.h/proteus_1602.h/proteus_1602.c也贴上来?

void WaitAck(){
        uchar i = 0;
        SDA = 0;
        SCK = 1;
        Delayus(5);
        while(SDA == 1 && (i < 250))
                i++;
        SCK = 0;
        _nop_(), _nop_(), _nop_();
}
回复

使用道具 举报

ID:776619 发表于 2022-3-13 10:53 | 显示全部楼层
读写两句间加个延时看看,器件两个动作要有间隔的。
回复

使用道具 举报

ID:856329 发表于 2022-3-13 11:56 | 显示全部楼层
iic通信和晶振频率24c02的地址都有关系,错一点都可能导致通信失败。
分享一下自用的驱动程序,仅供参考。
晶振12MHz或者11.0592MHz,24c02的3个地址全接地。
at24c02.c
  1. #include "at24c02.h"
  2. #include "delay.h"

  3. //IIC启动
  4. void Start(void)
  5. {
  6.         SDA1=1;
  7.         Delay_Us(2);
  8.         SCL1=1;
  9.         Delay_Us(2);//建立时间是SDA保持时间>4.7us
  10.         SDA1=0;
  11.         Delay_Us(2);//保持时间是>4us
  12.         SCL1=0;                       
  13.         Delay_Us(2);
  14. }
  15. //IIC停止
  16. void Stop(void)
  17. {
  18.         SDA1=0;
  19.         Delay_Us(2);
  20.         SCL1=1;
  21.         Delay_Us(2);//建立时间大于4.7us
  22.         SDA1=1;
  23.         Delay_Us(4);               
  24. }
  25. //IIC发送字节
  26. //dat:要发送的字节
  27. void Send_Byte(unsigned char dat)
  28. {
  29.         unsigned char a=0,b=0;
  30.         for(a=0;a<8;a++)//要发送8位,从最高位开始
  31.         {
  32.                 SDA1=dat>>7;         //起始信号之后SCL=0,所以可以直接改变SDA信号
  33.                 dat=dat<<1;
  34.                 Delay_Us(2);
  35.                 SCL1=1;
  36.                 Delay_Us(2);//建立时间>4.7us
  37.                 SCL1=0;
  38.                 Delay_Us(2);//时间大于4us
  39.         }       
  40. }
  41. //IIC检查应答
  42. bit Check_Ack(void)
  43. {
  44.         //unsigned char t;
  45.         SCL1=0;
  46.         SDA1=1;
  47.         Delay_Us(2);
  48.         SCL1=1;
  49.         Delay_Us(2);
  50.         CY=SDA1;
  51.         SCL1=0;
  52.         Delay_Us(2);       
  53.         return(CY);
  54. }
  55. //IIC应答
  56. void Ack(void)
  57. {
  58.         SDA1=0;   //EEPROM通过在收到每个地址或数据之后
  59.         SCL1=1;   //置SDA低电平的方式确认表示收到读SDA口状态
  60.         Delay_Us(1);
  61.         SCL1=0;
  62.         Delay_Us(1);
  63.         SDA1=1;
  64. }
  65. //IIC无应答
  66. void NoAck(void)
  67. {
  68.         SDA1=1;
  69.         SCL1=1;
  70.         Delay_Us(1);
  71.         SCL1=0;
  72. }
  73. //IIC接收字节
  74. unsigned char Receive_Byte(void)
  75. {
  76.         unsigned char a=0,dat=0;
  77.         SDA1=1;                        //起始和发送一个字节之后SCL都是0
  78.         Delay_Us(2);
  79.         for(a=0;a<8;a++)//接收8个字节
  80.         {
  81.                 SCL1=1;
  82.                 Delay_Us(2);
  83.                 dat<<=1;
  84.                 dat|=SDA1;
  85.                 Delay_Us(2);
  86.                 SCL1=0;
  87.                 Delay_Us(2);
  88.         }
  89.         return dat;               
  90. }
  91. //At24cxx读写数据
  92. //addr:要读/写数据的地址
  93. //*dat:要读/写的数据
  94. //length;数据的长度
  95. //RW:1:写,0:读
  96. void At24c02_RW(unsigned char addr,unsigned char *dat,unsigned char length,bit RW)
  97. {
  98.         Start();
  99.         Send_Byte(0xa0);//发送写器件地址
  100.         Check_Ack();
  101.         Send_Byte((unsigned char)addr);//发送要写入内存地址
  102.         Check_Ack();
  103.         if(RW)                 //写
  104.         {        while(length--)
  105.                 {
  106.                         Send_Byte(*dat++);
  107.                         Check_Ack();       
  108.                 }
  109.         }
  110.         else
  111.         {
  112.                 Start();
  113.                 Send_Byte(0xa1);
  114.                 Check_Ack();
  115.                 while(--length)
  116.                 {
  117.                         *dat++=Receive_Byte();
  118.                          Ack();
  119.                 }
  120.                 *dat=Receive_Byte();//读取最后一个字节
  121.                 NoAck();
  122.         }
  123.         Stop();
  124.         if(RW)
  125.         Delay_Us(1000);
  126. }

复制代码


at24c02.h
  1. #ifndef __AT24C02_H__
  2. #define __AT24C02_H__

  3. #include<reg52.h>

  4. sbit SCL1=P2^1;
  5. sbit SDA1=P2^0;

  6. void Start(void);
  7. void Stop(void);
  8. bit Check_Ack(void);
  9. void Ack(void);
  10. void NoAck(void);
  11. void Send_Byte(unsigned char dat);
  12. unsigned char Receive_Byte(void);
  13. void At24c02_RW(unsigned char addr,unsigned char *dat,unsigned char length,bit RW);

  14. #endif
复制代码


delay.c
  1. #include "delay.h"

  2. /*******************************************************************************
  3. * 函 数 名         : Delay_Us()
  4. * 函数功能                   : 延时1us
  5. * 输    入         : i
  6. * 输    出         : 无
  7. *******************************************************************************/
  8. void Delay_Us(int i)
  9. {
  10.         while(i--);
  11. }
  12. /*******************************************************************************
  13. * 函 数 名         : Delay_Ms()
  14. * 函数功能                   : 延时1Ms
  15. * 输    入         : m
  16. * 输    出         : 无
  17. *******************************************************************************/
  18. void Delay_Ms(int m)
  19. {
  20.         while(m--)
  21.         {
  22.                  Delay_Us(125);
  23.         }
  24. }
复制代码
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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