谁有ch563读写AT24C02程序吗?用C51的程序来改,就是不成功
您好,AT24C02应该是一个IIC从机器件,CH563没有硬件的IIC,可以采用 GPIO模拟,可以用逻辑分析仪或者示波器抓取一下两根线上的信号波形,看一下是不是在时序有什么问题。
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);
}
}
}
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读出的数据
}
}
}