OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3554|回复: 8

关于AT24C02不能连续读问题

[复制链接]

2

主题

14

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
260
金钱
260
注册时间
2017-7-17
在线时间
33 小时
发表于 2017-10-10 19:24:10 | 显示全部楼层 |阅读模式
小弟碰到AT24C02不能从指定直接地址开始读取,设定跨页写入一堆数组,从指定地址开始读数组,只能读取一个字节数据,不能达到连续读的效果,现将代码拷贝如下:

/****************************I2C.C*************************************/
#include "i2c.h"
#include "stm32f1xx_hal.h"
#include "delay.h"

#define     I2C             GPIOB
#define     I2C_SCL_PIN     GPIO_PIN_6
#define     I2C_SDA_PIN     GPIO_PIN_7

void GPIO_I2C_Init()
{
    GPIO_InitTypeDef I2C_Init;

    __HAL_RCC_GPIOB_CLK_ENABLE();                           //打开GPIO_B时钟

    I2C_Init.Mode=GPIO_MODE_OUTPUT_OD;
    I2C_Init.Pin=I2C_SCL_PIN|I2C_SDA_PIN;
    I2C_Init.Pull=GPIO_NOPULL;
    I2C_Init.Speed=GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(I2C,&I2C_Init);
}

void GPIO_I2C_SCL(u8 val)
{
    if(val)
        HAL_GPIO_WritePin(I2C,I2C_SCL_PIN,GPIO_PIN_SET);
    else
        HAL_GPIO_WritePin(I2C,I2C_SCL_PIN,GPIO_PIN_RESET);
}

void GPIO_I2C_SDA(u8 val)
{
    if(val)
        HAL_GPIO_WritePin(I2C,I2C_SDA_PIN,GPIO_PIN_SET);
    else
        HAL_GPIO_WritePin(I2C,I2C_SDA_PIN,GPIO_PIN_RESET);   
}

u8   GPIO_I2C_SDA_STA()
{
    if(HAL_GPIO_ReadPin(I2C,I2C_SDA_PIN)==GPIO_PIN_SET)
        return 1;
    else
        return 0;
}

void I2C_START()
{
    GPIO_I2C_SCL(1);
    GPIO_I2C_SDA(1);
    delay_us(4);
    GPIO_I2C_SDA(0);
    delay_us(4);
    GPIO_I2C_SCL(0);
}

void I2C_STOP()
{
    GPIO_I2C_SCL(0);
    GPIO_I2C_SDA(0);
    delay_us(4);
    GPIO_I2C_SCL(1);
    GPIO_I2C_SDA(1);
    delay_us(4);
}
//产生应答
void I2C_ACK(void)
{
    GPIO_I2C_SCL(0);
    GPIO_I2C_SDA(0);
    delay_us(2);   
    GPIO_I2C_SCL(1);
    delay_us(2);
    GPIO_I2C_SCL(0);
}
//不产生应答
void I2C_NOACK()
{
    GPIO_I2C_SCL(0);
    GPIO_I2C_SDA(1);
    delay_us(2);   
    GPIO_I2C_SCL(1);
    delay_us(2);
    GPIO_I2C_SCL(0);   
}

u8  I2C_WAIT_ACK()
{
    u8 err=0;
//    GPIO_I2C_SDA(1);
    GPIO_I2C_SCL(0);
    delay_us(2);
    GPIO_I2C_SCL(1);
    while(GPIO_I2C_SDA_STA())
    {        
        err++;
        if(err>255)

        {
            I2C_STOP();
            return 1;
        }
    }
    GPIO_I2C_SCL(0);
    return 0;
}

void I2C_WRITE_BYTE(u8 data)
{
    u8 i;
    for(i=0;i<8;i++)
    {
        GPIO_I2C_SCL(0);
        delay_us(2);
        if(data&0x80)
            GPIO_I2C_SDA(1);
        else
            GPIO_I2C_SDA(0);
        GPIO_I2C_SCL(1);
        data<<=1;
        delay_us(2);               
    }

}

u8   I2C_READ_BYTE(u8 ack)
{
    u8 i,temp=0x00;
    for(i=0;i<8;i++)
    {
        GPIO_I2C_SCL(0);
        delay_us(2);
        GPIO_I2C_SCL(1);
        temp<<=1;
        if(GPIO_I2C_SDA_STA())
            temp++;
        delay_us(2);   
    }
    if(ack)
        I2C_ACK();
    else
        I2C_NOACK();
    return temp;
}

/*************************I2C.H***********************************/
#ifndef __I2C_H
#define __I2C_H
#include "stm32f1xx_hal.h"

#define u8  uint8_t
#define u16 uint16_t

void GPIO_I2C_Init(void);
void GPIO_I2C_SCL(u8 val);
void GPIO_I2C_SDA(u8 val);
u8   GPIO_I2C_SDA_STA(void);
void I2C_START(void);
void I2C_STOP(void);
void I2C_ACK(void);
void I2C_NOACK(void);
u8   I2C_WAIT_ACK(void);
u8   I2C_READ_BYTE(u8 ack);
void I2C_WRITE_BYTE(u8 data);
#endif


/**************************24C02.C***************************/
#include "at24c02.h"
#include "stm32f1xx_hal.h"
#include "delay.h"
#include "i2c.h"

#define   MAX_ADDR      255
#define   MAX_PAGE      8


void AT24C02_WRITEONEBYTE(u8 writeadrr,u8 data)
{
    I2C_START();
    I2C_WRITE_BYTE(0xA0);
    I2C_WAIT_ACK();
    I2C_WRITE_BYTE(writeadrr);
    I2C_WAIT_ACK();
    I2C_WRITE_BYTE(data);
    I2C_WAIT_ACK();
    I2C_STOP();
    delay_ms(10);
}

u8   AT24C02_READONEBYTE(u8 readadrr)
{
    u8 temp=0x00;
    I2C_START();
    I2C_WRITE_BYTE(0xA0);
    I2C_WAIT_ACK();
    I2C_WRITE_BYTE(readadrr);
    I2C_WAIT_ACK();
    I2C_START();
    I2C_WRITE_BYTE(0xA1);
    I2C_WAIT_ACK();
    temp=I2C_READ_BYTE(0);
    I2C_STOP();
    return temp;
}

u8  AT24C02_WRITEPAGEBYTE(u8 writeaddr,u8 *pointbuff,u8 size)
{
    u8 i;
    if((MAX_ADDR-writeaddr)<size-1)
        return 0;
    while(size>(MAX_PAGE-writeaddr%8))
    {
    u8 temp;
    temp=MAX_PAGE-writeaddr%8;             //temp表示当前页剩下可写的字节数
    I2C_START();
    I2C_WRITE_BYTE(0xA0);
    I2C_WAIT_ACK();
    I2C_WRITE_BYTE(writeaddr);
    I2C_WAIT_ACK();
        for(i=temp;i>0;i--)
    {
        I2C_WRITE_BYTE(*(pointbuff++));
        I2C_WAIT_ACK();
    }
    I2C_STOP();
    delay_ms(10);
    writeaddr=writeaddr+temp;
    size=size-temp;
    }                  

    I2C_START();
    I2C_WRITE_BYTE(0xA0);
    I2C_WAIT_ACK();
    I2C_WRITE_BYTE(writeaddr);
    I2C_WAIT_ACK();
    for(i=size;i>0;i--)
    {
        I2C_WRITE_BYTE(*(pointbuff++));
        I2C_WAIT_ACK();
    }
    I2C_STOP();
    delay_ms(10);
    return 1;
}

u8 AT24C02_READSEQBYTE(u8 readaddr,u8 *pbuff,u8 size)
{
    if(size>(256-readaddr))
        return 0;
    I2C_START();
    I2C_WRITE_BYTE(0xA0);
    I2C_WAIT_ACK();
    I2C_WRITE_BYTE(readaddr);
    I2C_WAIT_ACK();
    I2C_START();
    I2C_WRITE_BYTE(0xA1);
    I2C_WAIT_ACK();
    while(size--)
    {
        *(pbuff++)=I2C_READ_BYTE(size);
    }
    I2C_STOP();   
    return 1;
}

/************************24C02.H********************************************/
#ifndef __24C02_H
#define __24C02_H
#include "stm32f1xx_hal.h"

#define u8  uint8_t
#define u16 uint16_t

void AT24C02_WRITEONEBYTE(u8 adrr,u8 data);
u8   AT24C02_READONEBYTE(u8 adrr);   
u8   AT24C02_WRITEPAGEBYTE(u8 writeaddr,u8 *pointbuff,u8 size);
u8   AT24C02_READSEQBYTE(u8 readaddr,u8 *pbuff,u8 size);

#endif


/******************************MIAN.C************************************/
#include "stm32f1xx_hal.h"
#include "delay.h"
#include "i2c.h"
#include "at24c02.h"


u8 a[]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,8};
u8 b[5];   
u8 read_byte;
int main()
{
//    rtc_time rtc;
    SystemClock_Config();
    GPIO_I2C_Init();
/*    GPIO_DS1302_Init();
    DS1302_WP_DISABLE();
    DS1302_WRITE_CMD(0x80,0x10);
    DS1302_WRITE_CMD(0x82,0x22);
    DS1302_WRITE_CMD(0x84,0x12);
    DS1302_WP_ENABLE();
    DS1302_WP_DISABLE();
    rtc.dat=22;
    rtc.day=5;
    rtc.hour=15;
    rtc.min=49;
    rtc.mon=9;
    rtc.sec=0;
    rtc.year=17;
    DS1302_WRITE_TIME(&rtc);
    DS1302_WP_ENABLE();
    while(1)
    {


        a=DS1302_READ_CMD(0x81+0);
        b=DS1302_READ_CMD(0x81+2);
        c=DS1302_READ_CMD(0x81+4);
        d=DS1302_READ_CMD(0x81+6);
        e=DS1302_READ_CMD(0x81+8);
        f=DS1302_READ_CMD(0x81+10);
        g=DS1302_READ_CMD(0x81+12);
        delay_ms(1000);
    }
    I2C_START();
    I2C_WRITE_BYTE(0xA0);
    I2C_WAIT_ACK();
    I2C_WRITE_BYTE(0x01);
    I2C_WAIT_ACK();
    I2C_WRITE_BYTE(0x15);
    I2C_WAIT_ACK();
    I2C_STOP();

    delay_ms(10);

    I2C_START();
    I2C_WRITE_BYTE(0xA0);
    I2C_WAIT_ACK();
    I2C_WRITE_BYTE(0x01);
    I2C_WAIT_ACK();
    I2C_START();
    I2C_WRITE_BYTE(0xA1);
    I2C_WAIT_ACK();
    read_byte=I2C_READ_BYTE(0);
    I2C_STOP();
    while(1);      
    AT24C02_WRITEONEBYTE(0x01,0x85);
    read_byte=AT24C02_READONEBYTE(0x01);       */
    AT24C02_WRITEPAGEBYTE(0x13,a,sizeof(a));
    AT24C02_READSEQBYTE(0x17,b,5);
    while(1);   
}



正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

2

主题

14

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
260
金钱
260
注册时间
2017-7-17
在线时间
33 小时
 楼主| 发表于 2017-10-10 19:25:53 | 显示全部楼层
目前只能读出第一个字节0x04,后面的都是0x00。
回复 支持 反对

使用道具 举报

2

主题

14

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
260
金钱
260
注册时间
2017-7-17
在线时间
33 小时
 楼主| 发表于 2017-10-10 19:27:10 | 显示全部楼层
保证写字节都是OK的,之前一个字节,一个字节读,都是可以的,就是连续读会出现这样的问题,望各位坛友多多指教。
回复 支持 反对

使用道具 举报

24

主题

695

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1666
金钱
1666
注册时间
2016-4-29
在线时间
266 小时
发表于 2017-10-10 19:45:54 | 显示全部楼层
没有仔细看代码,检查一下I2C连续读的时序
回复 支持 反对

使用道具 举报

2

主题

14

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
260
金钱
260
注册时间
2017-7-17
在线时间
33 小时
 楼主| 发表于 2017-10-10 22:58:55 | 显示全部楼层
d1z1y2 发表于 2017-10-10 19:45
没有仔细看代码,检查一下I2C连续读的时序

时序感觉没有什么问题。
回复 支持 反对

使用道具 举报

2

主题

14

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
260
金钱
260
注册时间
2017-7-17
在线时间
33 小时
 楼主| 发表于 2017-10-10 22:59:59 | 显示全部楼层
本帖最后由 superliu588 于 2017-10-10 23:02 编辑
d1z1y2 发表于 2017-10-10 19:45
没有仔细看代码,检查一下I2C连续读的时序

后来还是用单字节轮询去连续读字节了,就是效率低了点。
u8 AT24C02_READSEQBYTE(u8 readaddr,u8 *pbuff,u8 size)
{
    if(size>(256-readaddr))
        return 0;
/*    I2C_START();
    I2C_WRITE_BYTE(0xA0);
    I2C_WAIT_ACK();
    I2C_WRITE_BYTE(readaddr);
    I2C_WAIT_ACK();
    I2C_START();
    I2C_WRITE_BYTE(0xA1);
    I2C_WAIT_ACK();  */
    while(size)
    {
        *pbuff++=AT24C02_READONEBYTE(readaddr++);
        size--;
    }
    return 1;
}
回复 支持 反对

使用道具 举报

15

主题

338

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1278
金钱
1278
注册时间
2016-3-16
在线时间
283 小时
发表于 2017-10-11 10:10:35 | 显示全部楼层
可能是IIC时序问题
回复 支持 反对

使用道具 举报

24

主题

695

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1666
金钱
1666
注册时间
2016-4-29
在线时间
266 小时
发表于 2017-10-11 12:12:56 | 显示全部楼层
读单字节没问题,而连续读有问题,就可以判断是连续读的时序有问题,再检查一下,不要凭感觉,先检查再说
回复 支持 反对

使用道具 举报

2

主题

14

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
260
金钱
260
注册时间
2017-7-17
在线时间
33 小时
 楼主| 发表于 2017-10-15 22:58:21 | 显示全部楼层
本帖最后由 superliu588 于 2017-10-15 22:59 编辑

后来问题找到了。是主机向从机发应答时,数据脚置低后没有释放总线导致的。现在OK了,虽然不是你说的这个问题点,但是还是要谢谢你给了我检查上的帮助。
//产生应答
void I2C_ACK(void)
{
    GPIO_I2C_SCL(0);
    GPIO_I2C_SDA(0);
    delay_us(2);   
    GPIO_I2C_SCL(1);
    delay_us(2);
    GPIO_I2C_SCL(0);
    GPIO_I2C_SDA(1);        //必须释放SDA总线
}
//不产生应答
void I2C_NOACK()
{
    GPIO_I2C_SCL(0);
    GPIO_I2C_SDA(1);
    delay_us(2);   
    GPIO_I2C_SCL(1);
    delay_us(2);
    GPIO_I2C_SCL(0);
    GPIO_I2C_SDA(1);        //必须释放SDA总线   
}

回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-10 00:40

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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