关于AT24C02不能连续读问题

2019-08-13 19:32发布

小弟碰到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);   
}



友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
8条回答
superliu588
1楼-- · 2019-08-13 22:37
目前只能读出第一个字节0x04,后面的都是0x00。
superliu588
2楼-- · 2019-08-14 03:47
保证写字节都是OK的,之前一个字节,一个字节读,都是可以的,就是连续读会出现这样的问题,望各位坛友多多指教。
d1z1y2
3楼-- · 2019-08-14 09:32
 精彩回答 2  元偷偷看……
superliu588
4楼-- · 2019-08-14 11:58
d1z1y2 发表于 2017-10-10 19:45
没有仔细看代码,检查一下I2C连续读的时序

时序感觉没有什么问题。
superliu588
5楼-- · 2019-08-14 13:25
本帖最后由 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;
}
zhsyghhz
6楼-- · 2019-08-14 16:27
可能是IIC时序问题

一周热门 更多>