找回密码
 立即注册
查看: 4657|回复: 11

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
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:38
  • 最近打卡:2025-04-30 14:38:57

25

主题

977

回帖

3599

积分

超级版主

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

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

1

主题

3

回帖

17

积分

新手上路

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

A0A1A2都是悬空的,我在程序里加上读3231的秒位和分位的语句,3231数据读出来了,难道是我24C32写的不对吗?
  • 打卡等级:偶尔看看III
  • 打卡总天数:38
  • 最近打卡:2025-04-30 14:38:57

25

主题

977

回帖

3599

积分

超级版主

积分
3599
发表于 2022-11-26 22:22:59 | 显示全部楼层
z905*** 发表于 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 | 显示全部楼层
zh*** 发表于 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);
                         }
  • 打卡等级:偶尔看看III
  • 打卡总天数:38
  • 最近打卡:2025-04-30 14:38:57

25

主题

977

回帖

3599

积分

超级版主

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

I2C协议中,正常的数据读写都一定是9个数据位
读取数据后,必须回一个ACK或者NAK,所以你的这段代码应该是没问题的
我不太了解DS3231,你可以尝试读取最后一笔数据后回NAK看看(正确的I2C协议就是这样的)
  • 打卡等级:初来乍到
  • 打卡总天数:1
  • 最近打卡:2025-03-11 19:25:05

1

主题

5

回帖

59

积分

注册会员

积分
59
发表于 2025-3-11 19:25:05 | 显示全部楼层
我用的是STC8H8K64U自带的IIC功能,也有你的这种情况未解决,我用逻辑分析仪测试了一下。DS时钟和液晶屏都正常工作,就是这个24C32写入读取不出来。。。。我的2张图中就是写入和读取的图形,看着没啥问题,就是写入读取都是FF,我的A0A1A2都接到了上拉电阻。地址是0XAE
截图202503111923515650.jpg
截图202503111924025028.jpg
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:1
  • 最近打卡:2025-03-11 19:25:05

1

主题

5

回帖

59

积分

注册会员

积分
59
发表于 2025-3-11 20:39:53 | 显示全部楼层
我的刚才处理好了,我用的是8H8K64U自带的IIC功能和官方的库修改的,我的模块和你的一样,代码如下:
写入:
void Write_IIC_24c32_command(u16 u16_addr,u8 u8_data)
{
        Start();
        SendData(0XAE|WRITE_CMD);  
        RecvACK();
        SendData(((u16_addr>>8)&0xff));                        //write command
        RecvACK();
        SendData((u16_addr&0xff));
        RecvACK();
        SendData(u8_data);
        RecvACK();
        SendNAK();
        Stop();
}
读取:
u8 Read_IIC_24c32_data(u16 u16_addr)
{
        u8 reg_data=0;
        Start();
        SendData(0XAE);
        RecvACK();
        SendData(u16_addr>>8);                        //write command
        RecvACK();
        SendData(u16_addr);
        RecvACK();
        Start();
        SendData(0XAF);
        RecvACK();
        reg_data = RecvData();
        SendNAK();
        Stop();
        return reg_data;
}
https://www.stcaimcu.com/forum.php?mod=attachment&aid=ODc2MTR8NGZlMWE4MmJ8MTc0NjEyMjAwMnwwfA%3D%3D
截图202503112039329095.jpg
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看I
  • 打卡总天数:15
  • 最近打卡:2025-04-30 08:42:14

10

主题

126

回帖

1463

积分

版主

积分
1463
发表于 2025-3-12 08:38:30 | 显示全部楼层
https://www.stcaimcu.com/forum.p ... ;extra=&page=11  已在这个帖子帮问,到时关注下此贴102楼
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-5-2 01:53 , Processed in 0.129623 second(s), 117 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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