📄 2464.c
字号:
//*******************************************************************
//********File name :24C64 eeprom's write and read
//********File create date :2008/5/27
//********Design dept :ATE
//********Systm explain :Atmage 88 ,8m/8
//*******************************************************************
#include "C.h"
//*******************************************************************
//上位机发送:"AA+55+读取字节数高字节+读取字节数低字节+CHKSUM"后,
//下位机开始读24C64,相应的字节数发送给上位机.
//*******************************************************************
//通信波特率:4800,N,8,1 内部时种分频
//*******************************************************************
int Eepaddress=0x0000; //要读取的24C64内部存贮器单元地址
int Eep_long; //保存上位机发数来的,将要读取的字节个数数据
char Eepdata[32];
int read_byte=32;
int usart_bit=0; //计录串口接收数据个数
int step_bit_0=0;
char command_dataH;
char command_dataL;
char RXD_chksum;
//*******************************************************************
void main()
{
Mcu_init();
initial_usart();
Sei();
while(1)
{
if(step_bit_0==0x01) //上位机发送的命今接收成功
{
step_bit_0=0x00;
char chksum_sum=0xAA+0X55+command_dataH+command_dataL;
if(RXD_chksum==chksum_sum) //whether the chksum is right of data,if the data is right for It's downflow,then return
{
Eepaddress=0x0000;
Eep_long=command_dataH*256+command_dataL;
// 以下程序如果上位机发送的要读取的字节数小于32字节,程序单字节读取.每次所读取的数据放在Eepdata[0]中;
//如果大于32字节按块读取,先读32倍数的字节数,余数按单节读取.
//如果大于24C64的存贮器最大范围(8192字节).下位机不读取数取,也不发送.
//********************************************
if(Eep_long<=32) //小于32时,一位一位读取
{
for(int b=0;b<Eep_long;b++)
{
AT24C64_R(Eepaddress);
UDR0=Eepdata[0];
while(!CHKBIT(UCSR0A,TXC0));//wait for sending
SETBIT(UCSR0A,TXC0);
}
}
else //大于32是按块读取
{
if(!(Eep_long>8192)) //大于24C64读取范围时,不读取数据,也不回复给上位机
{
for(int a=0;a<(Eep_long/32);a++)
{
AT24C64_RB(Eepaddress,read_byte);
for(int b=0;b<read_byte;b++)
{
UDR0=Eepdata[b];
while(!CHKBIT(UCSR0A,TXC0));//wait for sending
SETBIT(UCSR0A,TXC0);
}
}
for(int b=0;b<(Eep_long%32);b++)
{
AT24C64_R(Eepaddress);
UDR0=Eepdata[0];
while(!CHKBIT(UCSR0A,TXC0));//wait for sending
SETBIT(UCSR0A,TXC0);
}
}
}
}
}
Nop();
}
}
//********************************************************************
//串口通信说明:
//串口通信:4800,N,8,1
//接收中断使能,允许发送和接收
//********************************************************************
void initial_usart(void)
{
UBRR0H=0;
UBRR0L=12; //BAUD 4800
UCSR0B=(1<<RXCIE0)|(1<<RXEN0)|(1<<TXEN0);//ENABLE
UCSR0C=(3<<UCSZ00);//no check bit, 8 bits, 1 stop
}
//*******************************************************************
//引脚定义
//*******************************************************************
void Mcu_init()
{
OUT_SDA;
OUT_SCL;
}
//********************************************************************
//接收数据中断:
//********************************************************************
#pragma vector=USART_RX_vect
__interrupt
void USART_RX(void)
{
unsigned char command=UDR0;
if(usart_bit==0)
{
if(command==0XAA)
usart_bit=1;
else
usart_bit=0;
}
else if(usart_bit==1)
{
if(command==0x55)
usart_bit=2;
else
usart_bit=0;
}
else if(usart_bit==2)
{
command_dataH=command;
usart_bit=3;
}
else if(usart_bit==3)
{
command_dataL=command;
usart_bit=4; //只接收4个字节,如还有数据则从数据头开始检测
}
else if(usart_bit==4)
{
RXD_chksum=command;
step_bit_0=0x01; //接收成功
usart_bit=0; //只接收5个字节,如还有数据则从数据头开始检测
}
}
//*******************************************************************
//单字节写程序
//PartAdd_W 为器件地址+写命今
//AT24C64_address为要操作的I2C芯片的内部存贮单元,为双字节(24C64)
//Data 为要写入的数据
//*******************************************************************
void AT24C64_W(int AT24C64_address,int Data)
{
I2C_Start();
I2C_Send_Byte(0xa0 );
I2C_Send_Byte(AT24C64_address/256 );
I2C_Send_Byte(AT24C64_address %256 );
I2C_Send_Byte(Data);
I2C_Stop();
Delay_N_mS(10);
}
//******************************************************************
//单字节读程序:
//AT24C64_address为要操作的I2C芯片的内部存贮单元,为双字节(24C64)
//******************************************************************
void AT24C64_R(int AT24C64_address)
{
I2C_Start();
I2C_Send_Byte(0xa0);
I2C_Send_Byte(AT24C64_address/256 );
I2C_Send_Byte(AT24C64_address % 256 );
I2C_Start();
I2C_Send_Byte(0xa1);
Eepdata[0]=I2C_Receive_Byte();
I2C_Nack();
I2C_Stop();
Eepaddress++; //读取一个字节时不需此步.调用完此子程序后.你所要读取单元字节的数据已放入Eepdata[0].直接用
}
//********************************************************************
//32字节(块)读程序
//********************************************************************
void AT24C64_RB(int AT24C64_address,int eep_byte)
{
I2C_Start();
I2C_Send_Byte(0xa0);
I2C_Send_Byte(AT24C64_address/256 );
I2C_Send_Byte(AT24C64_address%256 );
I2C_Start();
I2C_Send_Byte(0xa1);
for(int a=0;a<eep_byte;a++)
{
Eepdata[a]= I2C_Receive_Byte();
I2C_Ack();
Eepaddress++; //地址加1
}
I2C_Stop();
}
//********************************************************************
//接收数据:
//用来接收数据
//********************************************************************
char I2C_Receive_Byte(void)
{
char Data_C=0;
char Bitcont;
IN_SDA; //切换数据线为输入状态
for(Bitcont=0;Bitcont<8;Bitcont++)
{
Nop();
SCL_0;
Delay_10_uS();
SCL_1;
Delay_10_uS();
Data_C=Data_C<<1;
if(!(CHK_SDA==0))
Data_C=Data_C+1;
Nop();
Nop();
}
SCL_0;
Delay_10_uS();
OUT_SDA; //恢复数据线为输出状态
return Data_C;
}
//********************************************************************
//*起始说明: *
//*在时钟为高时,数据线由高变低. *
//********************************************************************
void I2C_Start(void)
{
Delay_10_uS();
SDA_1;// I2C_SDA =1;
Delay_10_uS();
SCL_1;// I2C_SCK =1;
Delay_10_uS();
SDA_0;// I2C_SDA = 0;
Delay_10_uS();
SCL_0;// I2C_SCK = 0;
Delay_10_uS();
}
//********************************************************************
//*结束说明: *
//*在时钟为高时,数据线由低变高 *
//********************************************************************
void I2C_Stop(void)
{
Delay_10_uS();
SDA_0;// I2C_SDA = 0;
Delay_10_uS();
SCL_1;// I2C_SCK = 1;
Delay_10_uS();
SDA_1;// I2C_SDA = 1;
Delay_10_uS();
}
//********************************************************************
//主机发送应答位
//********************************************************************
void I2C_Ack(void)
{
Delay_10_uS();
SDA_0;// I2C_SDA=0;
Delay_10_uS();
SCL_1;// I2C_SCK=1;
Delay_10_uS();
SCL_0;// I2C_SCK=0;
Delay_10_uS();
}
//********************************************************************
//主机发送非应答位
//********************************************************************
void I2C_Nack(void)
{
Delay_10_uS();
SDA_1;// I2C_SDA=1;
Delay_10_uS();
SCL_1;// I2C_SCK=1;
Delay_10_uS();
SCL_1;// I2C_SCK=0;
Delay_10_uS();
}
//********************************************************************
//*发送说明:
//*在发送数据时,时钟线在高时,数据不能变化,只有在时钟为低时,数据才可变*
//********************************************************************
void I2C_Send_Byte(char d)
{
char i = 8;
while( i-- )
{
Delay_10_uS();
if ( d &0x80 ) SDA_1;//I2C_SDA =1;
else SDA_0;//I2C_SDA =0;
Delay_10_uS();
SCL_1;// I2C_SCK = 1;
Delay_10_uS();
Nop();
Nop();
Nop();
Nop();
Nop();
Nop();
Nop();
Nop();
Nop();
Nop();
Nop();
SCL_0;// I2C_SCK = 0;
d = d << 1;
}
Delay_10_uS();
SDA_1;// I2C_SDA = 1;
Delay_10_uS();
SCL_1;// I2C_SCK = 1;
Delay_10_uS();
Nop();
Nop();
Nop();
Nop();
Nop();
Nop();
Nop();
Nop();
Nop();
SCL_0;// I2C_SCK =0;
//Delay_10_uS();
}
//********************************************************************
//延时
//********************************************************************
void Delay_10_uS(void)
{
Nop();
Nop();
}
//********************************************************************
//延时程序
//********************************************************************
void Delay_N_mS( int n_milisecond) /* n mS delay */
{
char i;
while(n_milisecond--)
{
i=8;
while(i--);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -