完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
您好,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读出的数据 } } } |
|
|
|
只有小组成员才能发言,加入小组>>
494 浏览 1 评论
CH579M+RT-Thread,RTC从Sleep模式唤醒失败是什么原因?
2886 浏览 2 评论
2382 浏览 1 评论
839浏览 2评论
514浏览 1评论
CH32F103C8T6使用当前官网上的CDC例程会出现设备描述符请求失败
381浏览 1评论
660浏览 1评论
riscv-none-embed-objcopy: \'PWM_Output.elf\': No such file这个咋解决,
397浏览 1评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-4 03:06 , Processed in 2.275549 second(s), Total 81, Slave 64 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号