誰有ch563讀寫AT24C02程序嗎?用C51的程序來改,就是不成功
您好,AT24C02應(yīng)該是一個IIC從機(jī)器件,CH563沒有硬件的IIC,可以采用 GPIO模擬,可以用邏輯分析儀或者示波器抓取一下兩根線上的信號波形,看一下是不是在時序有什么問題。
AT24C02非常適合存儲一些經(jīng)常修改的小數(shù)據(jù),比ch563 自帶的DataFlash更靈活。小數(shù)據(jù)用AT24Cxx,中量數(shù)據(jù)用DataFlash,大量數(shù)據(jù)用TF卡,這樣ch563就非常好用了。
經(jīng)過幾天的努力,已經(jīng)能讓ch563正常讀寫AT24C02了,代碼是從51單片機(jī)STC15W上移植過來的。ch563的代碼還沒整理好,先發(fā)一個STC15W上的代碼,給大家參考一下,ch563的整理完了再發(fā)上來。
/************************
基于STC15W的51單片機(jī)對AT24C02進(jìn)行數(shù)據(jù)讀寫
AT24C02_write是寫入數(shù)據(jù)程序
AT24C02_read是讀出數(shù)據(jù)程序
AT24C02是2K的容量,但我們一條數(shù)據(jù)是8位的,所以我們實際是能存儲256條數(shù)據(jù),對于一些需要不斷更改的小數(shù)據(jù),AT24C02是非常合適的。
************************/
#include //這個地方可能不能正常顯示,是stc15w的頭文件
#include? ? ? ?//這個地方可能不能正常顯示,是intrins文件
#define uint unsigned int
#define INT8 unsigned char? //通常是寫成uchar,但這些寫成INT8,是為是方便移植程序到32位的單片機(jī)CH563上時與原廠給的程序相對應(yīng)
#define? WRITE24C02? 0xA0? //注意:AT24C02的A0、A1、A2腳全接地
#define? ? READ24C02? 0xA1
sbit SDA=P2^7;? ? ?//AT24C02串行數(shù)據(jù) 5腳? <-對于不同的系統(tǒng)板,需要在此處進(jìn)行修改
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)? ?//函數(shù)功能:iic開始
{
? SDA=1;
I2C_delay();
? SCL=1;
I2C_delay();
? SDA=0;
I2C_delay();
? SCL=0;
I2C_delay();
}
void I2C_stop(void)? ?// 函數(shù)功能: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)//函數(shù)功能:向AT24C02的address中寫入數(shù)據(jù)dat
{?
I2C_delay();
?I2C_write(address,dat);
I2C_delay();
}
INT8 AT24C02_read(INT8 address)//函數(shù)功能:從AT24C02的address中讀出數(shù)據(jù)dat
{
?INT8 temp;
I2C_delay();
?temp=I2C_read(address);
I2C_delay();?
?return (temp);
}
void InitUART(void)//串口初始化
{
? ? ?AUXR &= ~0x01;? ? ? //串口1使用定時器T1
? ? ?AUXR &= ~(1<<6);? ?//定時器T1設(shè)置為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;? ? ? ? ? ? ? ? ? ? ?//發(fā)送完成標(biāo)志
? ? EA=1;? ? ? ? ? ? ? ? ? ?//CPU開放中斷
}
void SendOneByte(INT8 c)?
{?
? ? while(!TI);?
? ? TI = 0;?
? ? SBUF = c;?
}?
/***************************************************
函數(shù)功能:主函數(shù)
***************************************************/
main(void)
{
INT8 k1,r,r1;
P2M1=0X00;? //設(shè)置成準(zhǔn)雙向口? P27? P26
P2M0=0X00;? ? ? ? ? ? ?
InitUART(); //串口初始化
while(1)
{
for(r=0;r<=255;r++)
{
r1=r;
?AT24C02_write(r,r1); //向AT24C02的地址r處寫入數(shù)據(jù)r1
?delaymss(2000);
k1=AT24C02_read(r);? //從AT24C02的地址r處讀取數(shù)據(jù),賦值給k1
SendOneByte(r1);? //用串口發(fā)送寫入的數(shù)據(jù)
SendOneByte(k1);? ?//用串口發(fā)送讀出的數(shù)據(jù)
delaymss(3000);
}
}
}
CH563讀寫AT24C02程序,經(jīng)一天一夜的跑程序驗證,沒有問題,未發(fā)現(xiàn)任何一個讀寫數(shù)據(jù)錯誤。
從STC15W單片機(jī)的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用于監(jiān)控演示程序的進(jìn)度,低電平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 低電平驅(qū)動LED顯示 */
#define LED_OUT_1(? )? ? { R32_PB_OUT |= LED; }? ? ? ? ? ? ? ? ? ? ? ? ? ? /* LED 高電平關(guān)閉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中斷函數(shù)
* Input? ? ? ? ? : None
* Output? ? ? ? ?: None
* Return? ? ? ? ?: None
*******************************************************************************/
void Delay_a()//延時函數(shù)
{
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)? //寫數(shù)據(jù)函數(shù)
{?
I2C_delay();
?I2C_write(address,dat);
I2C_delay();
}
INT8 AT24C02_read(INT8 address) //讀數(shù)據(jù)函數(shù)
{
?INT8 temp;
I2C_delay();
?temp=I2C_read(address);
I2C_delay();
?return (temp);
}
//AT24C02存儲程序結(jié)束
void Uart1_Init( UINT32 baud ) //串口初始化。這段函數(shù)是直接從原廠實例照抄來的。
{
? ? 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;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/* 預(yù)分頻 */
? ? R8_UART1_DLM = x>>8;
? ? R8_UART1_DLL = x&0xff;
? ? R8_UART1_LCR = RB_LCR_WORD_SZ ;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/* 設(shè)置字節(jié)長度為8? ? */
??
? ? R8_UART1_FCR = RB_FCR_FIFO_TRIG|RB_FCR_TX_FIFO_CLR|RB_FCR_RX_FIFO_CLR |? ??
? ? ? ? ? ? ? ? ? ?RB_FCR_FIFO_EN ;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/* 設(shè)置FIFO觸發(fā)點為28,清發(fā)送和接收FIFO,F(xiàn)IFO使能 */
? ?
? ? 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發(fā)送一字節(jié)子程序
* Input? ? ? ? ? : dat -要發(fā)送的數(shù)據(jù)
* Output? ? ? ? ?: None
* Return? ? ? ? ?: None
*******************************************************************************/
void UART1_SendByte( UINT8 dat )? ?//串口發(fā)送
{? ? ? ??
? ? R8_UART1_THR? = dat;
? ? while( ( R8_UART1_LSR & RB_LSR_TX_ALL_EMP ) == 0 );? ? ? ? ? ? ? ? ? ? ? ? ?/* 等待數(shù)據(jù)發(fā)送 */? ? ? ?
}
/******************************
? 主函數(shù)
*******************************/
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寫入數(shù)據(jù)
Delay_a();? //延時函數(shù)。
Delay_a();? //讀出函數(shù)不能直接放在寫入函數(shù)后面,中間要有足夠的延時,否則可能讀不出正確的數(shù)據(jù)
Delay_a();
Delay_a();
Delay_a();
Delay_a();
b8=AT24C02_read(a1);? //從AT24C02讀出數(shù)據(jù) 。注意:讀出函數(shù)不能直接放在寫入函數(shù)后面,中間要有足夠的延時,否則可能讀不出正確的數(shù)據(jù)
UART1_SendByte(a1); //串口輸出往AT24C02寫入的數(shù)據(jù)
UART1_SendByte(b8); //串口輸出從AT24C02讀出的數(shù)據(jù)
}
}
}