找回密码
 立即注册
查看: 3564|回复: 6

I2C求助贴,改的官网范例,读出的都是ff

[复制链接]

该用户从未签到

1

主题

3

回帖

17

积分

新手上路

积分
17
发表于 2022-11-26 15:33:43 | 显示全部楼层 |阅读模式
网上买的8a8k64s4a12,和ds3231的模块,上面还有一个24c32,P14接的SDA,P15接SCL,VCC和GND都是在U8W连过来的,我想读写24c32成功了再学3231,可是读出来都是0xff,我知道看别人的原代码很乱,但有人能指点一下吗?



#include <STC8.h>
#include <stdio.h>
#include <intrins.h>
unsigned char flag,Dat24c32H,Dat24c32L;
bit busy;
sbit SDA=P1^4;
sbit SCL=P1^5;
void UartInit(void)                //9600bps@24.000MHz
{
       
        SCON = 0x50;                                //8位数据,可变波特率
        AUXR |= 0x01;                                //串口1选择定时器2为波特率发生器
        AUXR &= 0xFB;                                //定时器时钟12T模式
        T2L = 0xE8;                                        //设置定时初始值
        T2H = 0xFF;                                        //设置定时初始值
        AUXR |= 0x10;                                //定时器2开始计时

        EA=1;                                                                //打开总中断
}

void delayxms(unsigned int xms)                //延时
        {
                unsigned int i,j;
                for(i=xms;i>0;i--)
                        for(j=1350;j>0;j--);
        }

void I2C_Isr() interrupt 24
{
    _push_(P_SW2);
    P_SW2|=0x80;
    if (I2CMSST&0x40)
    {
        I2CMSST&=~0x40;                       //清中断标志
        busy = 0;
    }
    _pop_(P_SW2);
}

void Start()
{
    busy=1;
    I2CMSCR=0x81;                             //发送START命令
    while(busy);
}

void SendData(char dat)
{
    I2CTXD=dat;                               //写数据到数据缓冲区
    busy=1;
    I2CMSCR=0x82;                             //发送SEND命令
    while(busy);
}

void RecvACK()
{
    busy=1;
    I2CMSCR=0x83;                             //发送读ACK命令
    while(busy);
}

char RecvData()
{
    busy=1;
    I2CMSCR=0x84;                             //发送RECV命令
    while(busy);
    return I2CRXD;
}

void SendACK()
{
    I2CMSST=0x00;                             //设置ACK信号
    busy = 1;
    I2CMSCR=0x85;                             //发送ACK命令
    while(busy);
}

void SendNAK()
{
    I2CMSST=0x01;                             //设置NAK信号
    busy=1;
    I2CMSCR=0x85;                             //发送ACK命令
    while(busy);
}

void Stop()
{
    busy=1;
    I2CMSCR=0x86;                             //发送STOP命令
    while(busy);
}

void Delay()
{
    int i;

    for (i=0; i<3000; i++)
    {
        _nop_();_nop_();
        _nop_();_nop_();
        _nop_();_nop_();
        _nop_();_nop_();
    }
}

void main()
{
    P_SW2 = 0x80;
                UartInit();
    I2CCFG = 0xe0;                              //使能I2C主机模式
    I2CMSST = 0x00;
  
    Start();                                    //发送起始命令
    SendData(0xa0);                             //发送设备地址+写命令
    RecvACK();
    SendData(0x00);                             //发送存储地址高字节
    RecvACK();
    SendData(0x01);                             //发送存储地址低字节
    RecvACK();
    SendData(0x12);                             //写测试数据1
    RecvACK();
    SendData(0x78);                             //写测试数据2
    RecvACK();
    Stop();                                     //发送停止命令

    Delay();                                    //等待设备写数据

    Start();                                    //发送起始命令
    SendData(0xa0);                             //发送设备地址+写命令
    RecvACK();
    SendData(0x00);                             //发送存储地址高字节
    RecvACK();
    SendData(0x01);                             //发送存储地址低字节
    RecvACK();
    Start();                                    //发送起始命令
    SendData(0xa1);                             //发送设备地址+读命令
    RecvACK();
    Dat24c32H=RecvData();                            //读取数据1
    SendACK();
    Dat24c32L=RecvData();                            //读取数据2
    SendNAK();
    Stop();                                     //发送停止命令

    P_SW2 = 0x00;

    while (1)
                                {
                           TI=1;
                                printf("READ Dat24C32H=%bx   Dat24C32L=%bx \n",Dat24c32H,Dat24c32L);
               
                                while(!TI);
                                delayxms(2000);
                         }
}








1.jpg
2.jpg
3.png
回复 送花

使用道具 举报

  • TA的每日心情
    开心
    7 天前
  • 签到天数: 16 天

    [LV.4]偶尔看看III

    16

    主题

    724

    回帖

    2578

    积分

    超级版主

    积分
    2578
    发表于 2022-11-26 20:15:18 | 显示全部楼层
    你需要确认你测试板上AT24C32的A0、A1、A2这3个脚的连接方法
    是接GND还是接VCC,然后对程序中的设备地址进行相应的修改

    (范例程序默认这3个脚接地)

    该用户从未签到

    1

    主题

    3

    回帖

    17

    积分

    新手上路

    积分
    17
     楼主| 发表于 2022-11-26 22:00:55 | 显示全部楼层
    zhp 发表于 2022-11-26 20:15
    你需要确认你测试板上AT24C32的A0、A1、A2这3个脚的连接方法
    是接GND还是接VCC,然后对程序中的设备地址进 ...

    A0A1A2都是悬空的,我在程序里加上读3231的秒位和分位的语句,3231数据读出来了,难道是我24C32写的不对吗?
  • TA的每日心情
    开心
    7 天前
  • 签到天数: 16 天

    [LV.4]偶尔看看III

    16

    主题

    724

    回帖

    2578

    积分

    超级版主

    积分
    2578
    发表于 2022-11-26 22:22:59 | 显示全部楼层
    z9051638 发表于 2022-11-26 22:00
    A0A1A2都是悬空的,我在程序里加上读3231的秒位和分位的语句,3231数据读出来了,难道是我24C32写的不对 ...

    DS3231能正确读写,说明I2C控制程序没问题
    读写AT24C32失败,很大可能是设备地址不匹配
    A0、A1、A2悬空,那要看芯片内部是否在这3脚有上拉或者下拉
    你可以用万用表测量一下这3个教悬空时的电平
    如果是高电平,则需要修改代码中的设备地址

    不过一般设计电路时,这3个脚一定是外部接GND或者VCC,
    进行地址选择,悬空设计倒是很少见

    该用户从未签到

    1

    主题

    3

    回帖

    17

    积分

    新手上路

    积分
    17
     楼主| 发表于 2022-11-27 12:06:39 | 显示全部楼层
    是的,如你所说,悬空不行,人家设计的本意可能是让自己焊硬件地址,先谢谢指点,我的程序中我还有点不明白的地方,上图,望帮解答一下

    该用户从未签到

    1

    主题

    3

    回帖

    17

    积分

    新手上路

    积分
    17
     楼主| 发表于 2022-11-27 12:12:12 | 显示全部楼层
    zhp 发表于 2022-11-26 22:22
    DS3231能正确读写,说明I2C控制程序没问题
    读写AT24C32失败,很大可能是设备地址不匹配
    A0、A1、A2悬空, ...

    是的,如你所说,悬空不行,人家设计的本意可能是让自己焊硬件地址,先谢谢指点,我的程序中我还有点不明白的地方,上图,望帮解答一下

            Start();
                    SendData(0xd0);
                    RecvACK();
                    SendData(0x00);
                    RecvACK();
                    Start();
                    SendData(0xd1);
                    RecvACK();
                    Dat3231sec00=RecvData();
                    //SendACK();                                这两个SendACK,加上就执行不到下面的printf语句,去掉就正常了,我看范例每个接收后面都加一个啊,这里为什么不行?24c32的这也加了,却没卡住,加在这好像就卡在这里了
                   
                   
                    Start();
                    SendData(0xd0);
                    RecvACK();
                    SendData(0x01);
                    RecvACK();
                    Start();
                    SendData(0xd1);
                    RecvACK();
                    Dat3231min01=RecvData();
                    //SendACK();                                这两个SendACK,加上就执行不到下面的printf语句,去掉就正常了,我看范例每个接收后面都加一个啊,这里为什么不行?
                   
                    Start();
                    SendData(0xd0);
                    RecvACK();
                    SendData(0x02);
                    RecvACK();
                    Start();
                    SendData(0xd1);
                    RecvACK();
                    Dat3231hour02=RecvData();
                    SendNAK();
                   
                    Stop();
                   
                   
                    // P_SW2 = 0x00;

       
                               TI=1;
                                    printf("READ Dat24C32H=%bx  Dat24C32L=%bx  TIME   %bx:%bx:%bx  \n",Dat24c32H,Dat24c32L,Dat3231hour02,Dat3231min01,Dat3231sec00);
                   
                                    while(!TI);
                                    delayxms(1000);
                             }
  • TA的每日心情
    开心
    7 天前
  • 签到天数: 16 天

    [LV.4]偶尔看看III

    16

    主题

    724

    回帖

    2578

    积分

    超级版主

    积分
    2578
    发表于 2022-11-27 12:48:28 | 显示全部楼层
    z9051638 发表于 2022-11-27 12:12
    是的,如你所说,悬空不行,人家设计的本意可能是让自己焊硬件地址,先谢谢指点,我的程序中我还有点不明 ...

    I2C协议中,正常的数据读写都一定是9个数据位
    读取数据后,必须回一个ACK或者NAK,所以你的这段代码应该是没问题的
    我不太了解DS3231,你可以尝试读取最后一笔数据后回NAK看看(正确的I2C协议就是这样的)
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

    GMT+8, 2024-5-18 18:42 , Processed in 0.081913 second(s), 55 queries .

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.

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