ATC2402 IIC连续读写的问题

2019-07-20 11:54发布

STM32软件IIC与AT24C02通信
程序运行开始先读取三个时间值
static u8 g_second = 0, g_minute = 0, g_hour = 0;

static void InitData(void)
{       
        g_hour   = IICGet()->ReadByte(100);
        g_minute = IICGet()->ReadByte(101);
        g_second = IICGet()->ReadByte(102);
       
        printf("%d ", g_hour);
        printf("%d ", g_minute);
        printf("%d ", g_second);
        printf(" ");
}


定时器每秒钟向AT24C02写三个时间值
void Timer1_Callback(void *p_tmr, void *p_arg)
{
        CPU_SR_ALLOC();
        OS_CRITICAL_ENTER();
       
        g_second++;
        if(g_second >= 60)
        {
                g_second = 0;
                g_minute++;
        }
        if(g_minute >= 60)
        {
                g_second = 0;
                g_hour++;
        }
        if(g_hour >= 24)
        {
                g_hour = 0;
        }       
       
        IICGet()->WriteByte(100, g_hour);       
        IICGet()->WriteByte(101, g_minute);       
        IICGet()->WriteByte(102, g_second);       
       
        OLEDFun()->ShowNumber(48, 0, 2, g_hour);
        OLEDFun()->ShowNumber(72, 0, 2, g_minute);
        OLEDFun()->ShowNumber(96, 0, 2, g_second);
       
        OS_CRITICAL_EXIT();       
}


每次STM32复位后,发现g_hour、g_second读写都是对的,g_minute读写不成功,每次都为0,多次测试发现连续读写都是第一个成功,第二个不成功,第三个成功,第四个不成功,间隔似的。
检查了IIC驱动代码
IIC.c

#include "sys.h"
#include "IIC.h"

static IICFun                m_Instance;
static IICFun                *pthis = NULL;


//static void SDA_Out(Level b_level)
//{
//        if(b_level == High)
//                GPIO_SetBits(IIC_SDA_GPIO_TYPE, IIC_SDA_GPIO_PIN);
//        else
//                GPIO_ResetBits(IIC_SDA_GPIO_TYPE, IIC_SDA_GPIO_PIN);
//}

//static void SCK_Out(Level b_level)
//{
//        if(b_level == High)
//                GPIO_SetBits(IIC_SCK_GPIO_TYPE, IIC_SCK_GPIO_PIN);
//        else
//                GPIO_ResetBits(IIC_SCK_GPIO_TYPE, IIC_SCK_GPIO_PIN);
//}

static void IIC_Start(void)
{
        SDA_OUT();
        IIC_SDA = 1;
        IIC_SCL = 1;
        delay_us(4);
        IIC_SDA = 0;
        delay_us(4);
        IIC_SCL = 0;
}

static void IIC_Stop(void)
{
        SDA_OUT();
        IIC_SCL = 0;
        IIC_SDA = 0;
        delay_us(4);
        IIC_SCL = 1;
        delay_us(4);
        IIC_SDA = 1;
        delay_us(4);
}

static void ACK(void)
{
        IIC_SCL = 0;
        SDA_OUT();
        IIC_SDA = 0;
        delay_us(4);
        IIC_SCL = 1;
        delay_us(4);
        IIC_SCL = 0;
}

static void No_ACK(void)
{
        IIC_SCL = 0;       
        SDA_OUT();
        IIC_SDA = 1;
        delay_us(4);
        IIC_SCL = 1;
        delay_us(4);
        IIC_SCL = 0;
}

static u8 Wait_ACK(void)
{
        u8 ucErrTime=0;
        SDA_IN();
        IIC_SDA = 1;       
        delay_us(4);       
        IIC_SCL = 1;
        delay_us(4);
        while(READ_SDA)
        {
                ucErrTime++;
                if(ucErrTime >250)
                {
                        IIC_Stop();
                        return 1;
                }
        }
        IIC_SCL=0;
        return 0;
}
static void WriteByte(u8 data)
{
        u8 i;
       
        SDA_OUT();
        IIC_SCL = 0;
        for(i=0; i<8; i++)
        {
                if(data & 0x80)
                        IIC_SDA = 1;
                else
                        IIC_SDA = 0;
                data <<= 1;
                delay_us(4);
                IIC_SCL = 1;
                delay_us(4);
                IIC_SCL = 0;
                delay_us(4);
        }       
}

static u8 ReadByte(u8 IsAck)
{
        u8 i, receive = 0;
        SDA_IN();
        for(i=0; i<8; i++)
        {
                IIC_SCL = 0;
                delay_us(4);
                IIC_SCL = 1;
                delay_us(4);
                receive <<= 1;
                if(READ_SDA)
                        receive++;
                delay_us(4);
        }
        if(IsAck)
                ACK();
        else
                No_ACK();
       
        return receive;
}       

static void WriteOneByte(u8 ReadAddr, u8 DataToWrite)
{
        IIC_Start();  
        WriteByte(AT24X02_1        | IIC_WRITE_CMD);       
        Wait_ACK();         
        WriteByte(ReadAddr);  //address
        Wait_ACK();
        WriteByte(DataToWrite);     //·¢&#203;í×&#214;&#189;ú                                                          
        Wait_ACK();                                
        IIC_Stop();//2úéúò&#187;&#184;&#246;í£&#214;1ì&#245;&#188;t
        delay_ms(20);       
}
static u8 ReadOneByte(u8 ReadAddr)
{
        u8 i, receive = 0, ack;
        IIC_Start();  
        WriteByte(AT24X02_1        | IIC_WRITE_CMD);
        Wait_ACK();
        WriteByte(ReadAddr);
        Wait_ACK();
       
        IIC_Start();  
        WriteByte(AT24X01 | IIC_READ_CMD);
        Wait_ACK();       
        receive = ReadByte(FALSE);

        IIC_Stop();//2úéúò&#187;&#184;&#246;í£&#214;1ì&#245;&#188;t       
        delay_ms(20);
        return receive;
}


static void Read_Data(u8 addr, u8 size, u8 *buff)
{
        u8 i;
       
        if(NULL != buff)
        {
                for(i=0; i<size; i++)
                {
                        IIC_Start();  
                        WriteByte(AT24X02_1        | IIC_WRITE_CMD);   //·¢&#203;í&#198;÷&#188;tμ&#216;&#214;·0XA0,D′êy&#190;Y          
                        Wait_ACK();
                        WriteByte(addr++);   //·¢&#203;íμíμ&#216;&#214;·
                        Wait_ACK();            
                        IIC_Start();                     
                        WriteByte(AT24X01 | IIC_READ_CMD);           //&#189;&#248;è&#235;&#189;óê&#213;&#196;£ê&#189;                          
                        Wait_ACK();                
                        if(i<size - 1)
                                *(buff+i)=ReadByte(TRUE);       
                        else
                                *(buff+i)=ReadByte(FALSE);       
                        IIC_Stop();//2úéúò&#187;&#184;&#246;í£&#214;1ì&#245;&#188;t       
                        delay_ms(20);
                }
        }
}

static void Write_Data(u8 addr, u8 size, u8 *buff)
{
        u8 i;
       
        if(NULL != buff)
        {
                for(i=0; i<size; i++)
                {
                        IIC_Start();  
                        WriteByte(AT24X02_1        | IIC_WRITE_CMD);       
                        Wait_ACK();         
                        WriteByte(addr++);  //address
                        Wait_ACK();
                        WriteByte(*buff++);     //·¢&#203;í×&#214;&#189;ú                                                          
                        Wait_ACK();                                
                        IIC_Stop();//2úéúò&#187;&#184;&#246;í£&#214;1ì&#245;&#188;t
                        delay_ms(20);
                }
        }
}
static void IIC_Init(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;
        //RCC->APB2ENR|=1<<4;//&#207;èê1&#196;üíaéèIO PORTCê±&#214;ó
        RCC_APB2PeriphClockCmd(        RCC_APB2Periph_GPIOB, ENABLE );       
          
        GPIO_InitStructure.GPIO_Pin = IIC_SDA_GPIO_PIN ;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD ;   //í&#198;íìê&#228;3&#246;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(IIC_SDA_GPIO_TYPE, &GPIO_InitStructure);
       
        GPIO_InitStructure.GPIO_Pin = IIC_SCK_GPIO_PIN ;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD ;   //í&#198;íìê&#228;3&#246;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(IIC_SCK_GPIO_TYPE, &GPIO_InitStructure);       
       
        IIC_SDA = 1;
        IIC_SCL = 1;
}

static u8 Check_AT2402(void)
{
        u8 temp;
        static u8 data = 0x55;

        IIC_Start();  
        WriteByte(AT24X02_1        | IIC_WRITE_CMD);       
        Wait_ACK();         
        WriteByte(0xff);  //address
        Wait_ACK();
        WriteByte(data);     //·¢&#203;í×&#214;&#189;ú                                                          
        Wait_ACK();                                
    IIC_Stop();//2úéúò&#187;&#184;&#246;í£&#214;1ì&#245;&#188;t
        delay_ms(10);
       
                                                                                                                                                       
    IIC_Start();  
        WriteByte(AT24X02 | IIC_WRITE_CMD);   //·¢&#203;í&#198;÷&#188;tμ&#216;&#214;·0XA0,D′êy&#190;Y          
        Wait_ACK();
    WriteByte(0xff);   //·¢&#203;íμíμ&#216;&#214;·
        Wait_ACK();            
        IIC_Start();                     
        WriteByte(AT24X02 | IIC_READ_CMD);           //&#189;&#248;è&#235;&#189;óê&#213;&#196;£ê&#189;                          
        Wait_ACK();         
    temp=ReadByte(FALSE);                  
    IIC_Stop();//2úéúò&#187;&#184;&#246;í£&#214;1ì&#245;&#188;t
        if(temp == data)
                printf("AT24C02 Init Succeed ");
        else
                printf("No Fine AT24C02 ");
        return temp;
}

static void New(void)
{
        pthis = &m_Instance;
        pthis->Init = IIC_Init;
        pthis->ReadByte = ReadOneByte;
        pthis->WriteByte = WriteOneByte;
        pthis->Check = Check_AT2402;
        pthis->ReadData = Read_Data;
        pthis->WriteData = Write_Data;
}

IICFun        *IICGet(void)
{
        if(pthis == NULL)
        {
                New();
        }
        return pthis;
}


IIC.h
#ifndef        _IIC_H_
#define        _IIC_H_

#define SDA_IN()    {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)8<<28;}
#define SDA_OUT()         {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)1<<28;}

#define                IIC_SDA_GPIO_PIN                GPIO_Pin_7
#define                IIC_SDA_GPIO_TYPE                GPIOB
#define                IIC_SCK_GPIO_PIN                GPIO_Pin_6
#define                IIC_SCK_GPIO_TYPE                GPIOB

#define                IIC_WRITE_CMD        0x00
#define                IIC_READ_CMD        0x01

#define                AT24X02_1                0xA0
#define                AT24X02_2                0xA2
//IO2ù×÷oˉêy         
#define IIC_SCL    PBout(6) //SCL
#define IIC_SDA    PBout(7) //SDA         
#define READ_SDA   PBin(7)  //ê&#228;è&#235;SDA

typedef struct
{
        void (*Init)(void);
        u8   (*ReadByte)(u8 ReadAddr);
        void (*WriteByte)(u8 ReadAddr, u8 DataToWrite);
        u8    (*Check)(void);
        void (*ReadData)(u8 addr, u8 size, u8 *buff);
        void (*WriteData)(u8 addr, u8 size, u8 *buff);
}IICFun;

IICFun        *IICGet(void);


#endif

根据网友遇到的情况修改开漏输出或者推挽输出效果无变化
单次读数据和连续读数据也是数据间隔式丢失
读完数据延时增加到100ms也不解决第二个数据读写丢失的问题
从串口输出可以看到复位后g_hour和g_second确实保存了,但是g_minute丢失

不知道是读写时序问题还是其他问题
困扰我很多天了
望各位指教

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。