WCH沁恒单片机
直播中

kasdlak

8年用户 1237经验值
擅长:光电显示
私信 关注
[问答]

ch563读写AT24C02程序就是不成功怎么处理?

谁有ch563读写AT24C02程序吗?用C51的程序来改,就是不成功
  

回帖(3)

胡燕珍

2022-5-31 12:00:35
您好,AT24C02应该是一个IIC从机器件,CH563没有硬件的IIC,可以采用 GPIO模拟,可以用逻辑分析仪或者示波器抓取一下两根线上的信号波形,看一下是不是在时序有什么问题。
举报

吕昊

2022-5-31 12:01:03
AT24C02非常适合存储一些经常修改的小数据,比ch563 自带的DataFlash更灵活。小数据用AT24Cxx,中量数据用DataFlash,大量数据用TF卡,这样ch563就非常好用了。
经过几天的努力,已经能让ch563正常读写AT24C02了,代码是从51单片机STC15W上移植过来的。ch563的代码还没整理好,先发一个STC15W上的代码,给大家参考一下,ch563的整理完了再发上来。




/************************
基于STC15W的51单片机对AT24C02进行数据读写
AT24C02_write是写入数据程序
AT24C02_read是读出数据程序


AT24C02是2K的容量,但我们一条数据是8位的,所以我们实际是能存储256条数据,对于一些需要不断更改的小数据,AT24C02是非常合适的。
************************/


#include  //这个地方可能不能正常显示,是stc15w的头文件
#include       //这个地方可能不能正常显示,是intrins文件 
#define uint unsigned int
#define INT8 unsigned char  //通常是写成uchar,但这些写成INT8,是为是方便移植程序到32位的单片机CH563上时与原厂给的程序相对应
#define  WRITE24C02  0xA0  //注意:AT24C02的A0、A1、A2脚全接地
#define    READ24C02  0xA1
sbit SDA=P2^7;     //AT24C02串行数据 5脚
sbit SCL=P2^6;    //AT24C02串行时钟 6脚


void delaymss(uint xms)  // 延时
{
uint x, y;
for(x = xms; x > 0; x--)
   for(y = 110; y > 0; y--);
}
void I2C_delay(void)//IIC通信延时用.注意这个延时非常重要,如果延时的时间不够,那么就不能正常通信

{
  _nop_();_nop_();_nop_();_nop_();
   _nop_();_nop_();_nop_();_nop_();
    _nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
}
void I2C_start(void)   //函数功能:iic开始
{
  SDA=1;
I2C_delay();
  SCL=1;
I2C_delay();
  SDA=0;
I2C_delay();
  SCL=0;
I2C_delay();
}


void I2C_stop(void)   // 函数功能:iic停止
{
  SDA=0;
I2C_delay();
  SCL=1;
I2C_delay();
  SDA=1;
I2C_delay();
  SCL=0;
I2C_delay();
}


void I2C_send_ack(bit k)
{
  SDA=k;
  I2C_delay();
  SCL=1;
  I2C_delay();
  SCL=0;
}


void I2C_write_byte(INT8 dat)
{
  INT8 i,i2;
   for (i=8;i>0;i--)
    {
    SCL=0;
I2C_delay();
i2=(dat&0x80)/0x80;
SDA=i2;//i2的值不是1就是0
    dat<<=1;
    I2C_delay();
    I2C_delay();
    SCL=1;
    I2C_delay();
    }
   SCL=0;  
}


INT8 I2C_read_byte(void)
{
  INT8 i,dat;
   for (i=0;i<8;i++)
    {
    SCL=0;
I2C_delay();
    SDA=1;
    I2C_delay();
    SCL=1;
    dat<<=1;
      I2C_delay();
    if(SDA)
       dat++;
    }
   SCL=0;
     
   return (dat);
}


void I2C_write(INT8 address,INT8 dat)
{


I2C_start();
I2C_write_byte(WRITE24C02);   
I2C_send_ack(0);
I2C_write_byte(address);  
I2C_send_ack(0);   
I2C_write_byte(dat);   
I2C_send_ack(1);
I2C_stop();
}


INT8 I2C_read(INT8 address)
{
INT8 dat;
I2C_start();
I2C_write_byte(WRITE24C02);
I2C_send_ack(0);
I2C_write_byte(address);
I2C_send_ack(1);
I2C_start();
I2C_write_byte(READ24C02);
I2C_send_ack(0);
dat=I2C_read_byte();
I2C_send_ack(1);
I2C_stop();      
  return (dat);
}




void AT24C02_write(INT8 address,INT8 dat)//函数功能:向AT24C02的address中写入数据dat
{
I2C_delay();
I2C_write(address,dat);
I2C_delay();
}


INT8 AT24C02_read(INT8 address)//函数功能:从AT24C02的address中读出数据dat
{
INT8 temp;
I2C_delay();
temp=I2C_read(address);
I2C_delay();
return (temp);
}


void InitUART(void)//串口初始化
{


     AUXR &= ~0x01;      //串口1使用定时器T1
     AUXR &= ~(1<<6);   //定时器T1设置为1T的12分频模式
    TMOD=0x20;            //定时器T1使用工作方式2
    TH1=0xfd;               // 串口工作模式1下, 11.0592M晶振波特率计算: Baud=(2^SMOD / 32)*Fosc/(12*(256-X)), 其中Fosc=11059200
    TL1=0xfd;               //计算得到Baud=9600
    TR1=1;                   //开始计时   
    PCON=0x00;           //SMOD=0;
    SCON=0x50;           //串口工作模式1
    TI=1;                     //发送完成标志
    EA=1;                   //CPU开放中断
}


void SendOneByte(INT8 c)
{
    while(!TI);
    TI = 0;
    SBUF = c;
}


/***************************************************
函数功能:主函数
***************************************************/
main(void)
{
INT8 k1,r,r1;
P2M1=0X00;  //设置成准双向口  P27  P26
P2M0=0X00;            
InitUART(); //串口初始化
while(1)
{
for(r=0;r<=255;r++)
{
r1=r;


AT24C02_write(r,r1); //向AT24C02的地址r处写入数据r1
delaymss(2000);
k1=AT24C02_read(r);  //从AT24C02的地址r处读取数据,赋值给k1


SendOneByte(r1);  //用串口发送写入的数据
SendOneByte(k1);   //用串口发送读出的数据
delaymss(3000);
}
}
}
举报

陈忠阳

2022-5-31 12:01:21
CH563读写AT24C02程序,经一天一夜的跑程序验证,没有问题,未发现任何一个读写数据错误。
从STC15W单片机的c51程序移植过来的。分享出来给大家。


#include "stdio.h"
#include "string.h"
#include "CH563SFR.H"
#include "SYSFREQ.H"


#define  WRITE24C02  0xA0//AT24C02的A0、A1、A2管脚接地
#define    READ24C02  0xA1


#define SCL               (1<<9)//SCL 为PB9脚
#define SDA               (1<<8)//SDA  为PB8脚


/* 连接一个LED用于监控演示程序的进度,低电平LED亮 */
#define LED                     1<<19  //LED灯是PB19管脚


#define LED_OUT_INIT(  )     { R32_PB_OUT |= LED; R32_PB_DIR |= LED; }         /* LED 高电平为输出方向 */
#define LED_OUT_0(  )      { R32_PB_CLR |= LED; }                            /* LED 低电平驱动LED显示 */
#define LED_OUT_1(  )    { R32_PB_OUT |= LED; }                            /* LED 高电平关闭LED显示 */




#define SDA_OUT_INIT(  )     { R32_PB_OUT |= SDA; R32_PB_DIR |= SDA; }    /* SDA 高电平为输出方向 */     
#define SDA_OUT_0(  )      { R32_PB_CLR |= SDA; }           /* SDA 输出0 */               
#define SDA_OUT_1(  )    { R32_PB_OUT |= SDA; }            /* SDA 输出1 */                 


#define SCL_OUT_INIT(  )     { R32_PB_OUT |= SDA; R32_PB_DIR |= SCL; }  /* SCL 高电平为输出方向 */      
#define SCL_OUT_0(  )      { R32_PB_CLR |= SCL; }      /* SCL 输出0 */                       
#define SCL_OUT_1(  )    { R32_PB_OUT |= SCL; }         /* SCL 输出1 */                    




void SDA_c(void) //SDA输入初始化
{
    R32_PB_PU |= (SDA);                                   /* 上拉 */
    R32_PB_DIR &= (~SDA);                               /* 输入 */
}


/*******************************************************************************
* Function Name  : IRQ_Handler
* Description    : IRQ中断函数
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/


void Delay_a()//延时函数
{
INT32 i3;
for(i3=0;i3<1000000;i3++);
}




__irq void IRQ_Handler( void )   
{
    while(1);
}


__irq void FIQ_Handler( void )
{
    while(1);
}




//AT24C02存储程序开始
void I2C_delay() // IIC延时用,如果延时时间不够,IIC可能不能正常工作
{
INT8 i4,i5;
for(i4=0;i4<120;i4++)
{
i5=i5+1;
}
}


void I2C_start(void)  //AT24C02开始
{
SDA_OUT_INIT(  );
SCL_OUT_INIT(  );
SDA_OUT_1(  );
// SDA=1;
I2C_delay();
SCL_OUT_1(  );
//  SCL=1;
I2C_delay();
SDA_OUT_0(  );
//  SDA=0;
I2C_delay();
SCL_OUT_0(  );
// SCL=0;
I2C_delay();
}


void I2C_stop(void)  //AT24C02停止
{
SDA_OUT_INIT(  );
SDA_OUT_0(  );
//  SDA=0;
I2C_delay();
SCL_OUT_1(  );
//  SCL=1;
I2C_delay();
SDA_OUT_1(  );
//  SDA=1;
I2C_delay();
SCL_OUT_0(  );
//  SCL=0;
I2C_delay();
}


void I2C_send_ack(INT8 k)
{
if(k==1)
{
SDA_OUT_1(  );
}
else
{
SDA_OUT_0(  );
}
// SDA=k;
  I2C_delay();
SCL_OUT_1(  );
//  SCL=1;
  I2C_delay();
SCL_OUT_0(  );
//  SCL=0;
}


void I2C_write_byte(INT8 dat)
{
  INT8 i,i2;
   for (i=8;i>0;i--)
    {
SCL_OUT_0(  );
//   SCL=0;
I2C_delay();
  //  SDA=(bit)(dat&0x80);
i2=(dat&0x80)/0x80;
if(i2==1)
{
SDA_OUT_1(  );
}
else
{
SDA_OUT_0(  );
}
//SDA=i2;
    dat<<=1;
    I2C_delay();
    I2C_delay();
SCL_OUT_1(  );
//    SCL=1;
    I2C_delay();
    }
SCL_OUT_0(  );
//   SCL=0;  
}
INT8 I2C_read_byte(void)
{
  INT8 i,dat8;
   for (i=0;i<8;i++)
    {
SCL_OUT_0(  );
//   SCL=0;
SDA_OUT_INIT(  );
I2C_delay();
SDA_OUT_1(  );
//    SDA=1;
    I2C_delay();
  SCL_OUT_1(  );
//   SCL=1;
    dat8<<=1;
SDA_c(); //SDA输入
      I2C_delay();
if(R32_PB_PIN&SDA)
{
dat8++;
}
  //  if(SDA)
  //     dat++;
    }
  SCL_OUT_0(  );
//  SCL=0;   
   return (dat8);
}
void I2C_write(INT8 address,INT8 dat)
{
//INT8 temp;
I2C_start();
I2C_write_byte(WRITE24C02);   
I2C_send_ack(0);
I2C_write_byte(address);  
I2C_send_ack(0);   
I2C_write_byte(dat);   
I2C_send_ack(1);
I2C_stop();
}


INT8 I2C_read(INT8 address)
{
INT8 dat;
I2C_start();
I2C_write_byte(WRITE24C02);
I2C_send_ack(0);
I2C_write_byte(address);
I2C_send_ack(1);
// I2C_stop();
I2C_start();
I2C_write_byte(READ24C02);
I2C_send_ack(0);
dat=I2C_read_byte();
  SDA_OUT_INIT(  );
I2C_send_ack(1);
I2C_stop();      
// temp=dat/16;
// dat=dat%16;
// dat=dat+temp*10;
  return (dat);
}




void AT24C02_write(INT8 address,INT8 dat)  //写数据函数
{
I2C_delay();
I2C_write(address,dat);
I2C_delay();
}
INT8 AT24C02_read(INT8 address) //读数据函数
{
INT8 temp;
I2C_delay();
temp=I2C_read(address);
I2C_delay();
return (temp);
}


//AT24C02存储程序结束


void Uart1_Init( UINT32 baud ) //串口初始化。这段函数是直接从原厂实例照抄来的。
{
    UINT32 x;


    x = 10 * FREQ_SYS/ 8 / baud;                                                /* 115200bps */
    x += 5;                                                                     /* 四舍五入 */
    x /= 10;
    R8_UART1_LCR = RB_LCR_DLAB;                                                 /* DLAB位置1 */
    R8_UART1_DIV = 1;                                                           /* 预分频 */
    R8_UART1_DLM = x>>8;
    R8_UART1_DLL = x&0xff;


    R8_UART1_LCR = RB_LCR_WORD_SZ ;                                             /* 设置字节长度为8    */
  
    R8_UART1_FCR = RB_FCR_FIFO_TRIG|RB_FCR_TX_FIFO_CLR|RB_FCR_RX_FIFO_CLR |   
                   RB_FCR_FIFO_EN ;                                             /* 设置FIFO触发点为28,清发送和接收FIFO,FIFO使能 */
   
    R8_UART1_IER = RB_IER_TXD_EN | RB_IER_LINE_STAT |RB_IER_THR_EMPTY |
                   RB_IER_RECV_RDY  ;                                           /* TXD enable   !!TXD使能*/
    R8_UART1_MCR = RB_MCR_OUT2;                                                
    R8_INT_EN_IRQ_0 |= RB_IE_IRQ_UART1;                                         /* 串口中断输出使能 */
    R32_PB_SMT |= RXD1|TXD1;                                                    /* RXD1 schmitt input, TXD1 slow rate  !!RXD1施密特输入,TXD1低速率 */
    R32_PB_PD  &= ~ RXD1;                                                       /* disable pulldown for RXD1, keep pullup  !!禁用RXD1的下拉,保持向上下拉*/
    R32_PB_DIR |= TXD1;                                                         /* TXD1 output enable !!TXD1输出使能*/
}


/*******************************************************************************
* Function Name  : UART1_SendByte
* Description    : 串口1发送一字节子程序
* Input          : dat -要发送的数据
* Output         : None
* Return         : None
*******************************************************************************/


void UART1_SendByte( UINT8 dat )   //串口发送
{        
    R8_UART1_THR  = dat;
    while( ( R8_UART1_LSR & RB_LSR_TX_ALL_EMP ) == 0 );                         /* 等待数据发送 */      
}
/******************************
  主函数
*******************************/
void main()
{
INT8 a1,b1,b8;
LED_OUT_INIT( );  // 指示灯初始化, IO为输出
LED_OUT_0( );   //指示灯亮                                            
Delay_a();   //延时
LED_OUT_1( ); //指示灯灭
b1=1;
// AT24C02_write(a1,b1);//保存b1值到a1地址,a1的地址可以是0-255
//b8=AT24C02_read(a1);//读取存储在a1地址的值


Uart1_Init( 115200 );  //串口初始化,波特率115200
while(1)
{
for(a1=0;a1<=255;a1++)
{
AT24C02_write(a1,a1);  //往AT24C02写入数据
Delay_a();  //延时函数。
Delay_a();  //读出函数不能直接放在写入函数后面,中间要有足够的延时,否则可能读不出正确的数据
Delay_a();
Delay_a();
Delay_a();
Delay_a();
b8=AT24C02_read(a1);  //从AT24C02读出数据 。注意:读出函数不能直接放在写入函数后面,中间要有足够的延时,否则可能读不出正确的数据
UART1_SendByte(a1); //串口输出往AT24C02写入的数据
UART1_SendByte(b8); //串口输出从AT24C02读出的数据
}
}
}
举报

更多回帖

发帖
×
20
完善资料,
赚取积分