📄 function.c
字号:
#include <./Atmel/at89x52.h>
#include <stdio.h>
#include "source.h"
#include <intrins.h>
#include <absacc.h>
//_nop_();0.65us fosc=18.432
void delay_macnine_ncircle(unsigned char cnt){//11+6*cnt machin circle. /*延时ns*/
while(cnt--);
}
void delay_10us(unsigned char tus){//fosc=18.432 /*延时10us的整数倍,其中tus为10us的整数倍*/
tus--;
while(tus--){
_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();
}
}
/*i2c max rate: 100k, so delay is needed*/
/*定义宏,把I2C的函数进行抽象*/
#define DELAY _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_()
#define I2CDATA SDA /*for read data from bit port*/
#define I2CSETDATA SDA=1 /*sda=1 macro*/
#define I2CCLRDATA SDA=0 /*sda=0 macro*/
#define I2CSETCLK SCL=1 /*scl=1 macro*/
#define I2CCLRCLK SCL=0 /*scl=0 macro*/
#define i2c_start AT24C64_start
#define i2c_stop AT24C64_stop
#define i2c_write_byte AT24C64_write_byte
#define i2c_read_byte AT24C64_read_byte
#define i2c_wait_ack AT24C64_wait_ack
#define i2c_send_ack AT24C64_send_ack
#define i2c_send_notack AT24C64_send_notack
void i2c_start(){/*I2C的开始函数*/
I2CSETDATA;
I2CSETCLK;
DELAY;
I2CCLRDATA;
DELAY;
I2CCLRCLK;
}
void i2c_stop(){/*I2C的停止函数*/
I2CCLRCLK;
I2CCLRDATA;
DELAY;
I2CSETCLK;
DELAY;
I2CSETDATA;
}
void i2c_write_byte(unsigned char ch)/*I2C的写一个字节*/
{
unsigned char i=8;
while(i--){
I2CCLRCLK;_nop_();
if(ch&0x80)
I2CSETDATA;
else
I2CCLRDATA;
ch<<=1;DELAY;
I2CSETCLK;DELAY;
}
I2CCLRCLK;
}
unsigned char i2c_read_byte(void)/*I2C读一个字节*/
{
unsigned char i=8;
unsigned char ddata=0;
I2CSETDATA ;
while (i--){
ddata<<=1 ;
I2CCLRCLK;DELAY;
I2CSETCLK;DELAY;
ddata|=I2CDATA;
}
I2CCLRCLK;
return ddata;
}
bit i2c_wait_ack(void)/*I2C等待芯片的ACK*/
{
unsigned char errtime=255;//因故障接收方无ACK 超时值为255
I2CSETDATA;DELAY;
I2CSETCLK ;DELAY;
while(I2CDATA){
errtime--;
if (!errtime){
i2c_stop();
return 0;
}
}
I2CCLRCLK;
return 1;
}
void i2c_send_ack(void)/*对I2C芯片发送ACK*/
{
I2CCLRDATA; DELAY;
I2CSETCLK; DELAY;
I2CCLRCLK;
}
void i2c_send_notack(void)/*对I2C芯片发送NO ACK*/
{
I2CSETDATA ; DELAY;
I2CSETCLK ; DELAY;
I2CCLRCLK;
}
#define DEVICEAW 0Xa0
#define DEVICEAR 0Xa1
/*下面是把以上的I2C操作转换为对AT24C64的EEPROM的操作以上介绍,可以得出以下函数*/
void AT24C64_wbytes(unsigned char *add,unsigned char len,unsigned char *buf){//max 32 bytes
/*为对EEPROM写多个字节,由于地址回转的问题,最多写32个字节*/
unsigned char hadd,ladd;
unsigned char i;
hadd=add[0];
ladd=add[1];
AT24C64_start();
AT24C64_write_byte(DEVICEAW);
AT24C64_wait_ack();
AT24C64_write_byte(hadd);
AT24C64_wait_ack();
AT24C64_write_byte(ladd);
AT24C64_wait_ack();
for(i=0;i<len;i++){
AT24C64_write_byte(buf[i]);
AT24C64_wait_ack();
}
AT24C64_stop();
delay_10us(100);//delay 1 ms for write byte.
delay_10us(100);
delay_10us(100);
delay_10us(100);
delay_10us(100);/*延时5毫秒,因为在两次写操作之间必须有5ms的延时才能进行下一次写*/
}
void AT24C64_rbytes(unsigned char *add,unsigned char len,unsigned char *buf){
/*对EEPROM进行多个字节的读操作,同样由于地址回转的问题,最多只能读32个字节*/
unsigned char hadd,ladd;
unsigned char i;
hadd=add[0];
ladd=add[1];
AT24C64_start();
AT24C64_write_byte(DEVICEAW);
AT24C64_wait_ack();
AT24C64_write_byte(hadd);
AT24C64_wait_ack();
AT24C64_write_byte(ladd);
AT24C64_wait_ack();
for(i=0;i<len;i++){
AT24C64_start();
AT24C64_write_byte(DEVICEAR);
AT24C64_wait_ack();
buf[i]=AT24C64_read_byte();
}
AT24C64_stop();
}
void init_eeprom(void){/*开始时,对EEPROM进行初始化,把EEPROM的存储单元都设置为0*/
unsigned char temp;
unsigned int add;
temp=0;
for(add=0;add<EEPROM_MAX_SPACE;add++){
AT24C64_wbytes((unsigned char *)&add,1,&temp);
}
}
unsigned char eeprom_write(unsigned int adr, unsigned int len, unsigned char *src){
/*为写EEPROM的进一步封装,这个函数的写的字节数可以任意长的*/
unsigned int temp;
unsigned int eeprom_grid;/*为取EEPROM一个页面64字节的整数地址*/
unsigned int eeprom_last;/*写EEPROM的最后存储单元的地址*/
unsigned char i;
eeprom_last=adr+len;
temp=adr/EEPROM_PAGE_LEN;
eeprom_grid=(temp+1)*EEPROM_PAGE_LEN;
temp=eeprom_last>eeprom_grid?eeprom_grid:eeprom_last;
AT24C64_wbytes((unsigned char *)&adr,temp-adr,src);
while(1){
if(eeprom_grid<eeprom_last){
adr=eeprom_grid;
eeprom_grid +=EEPROM_PAGE_LEN;
temp=eeprom_last>eeprom_grid?eeprom_grid:eeprom_last;
AT24C64_wbytes((unsigned char *)&adr,temp-adr,src);
}
else
break;//jump out the while
}
}
unsigned char eeprom_read(unsigned int adr, unsigned int len, unsigned char *src){
/**为对EEPROM的读函数的进一步封装,可以读任意个字节数*/
unsigned int i=0;
unsigned int rest;
while(1){
rest=len;
if(rest<=EEPROM_PAGE_LEN){/*如果剩下的字节数小于EEPROM_PAGE_LEN就把剩下的字节数读出来*/
AT24C64_rbytes((unsigned char *)&adr,(unsigned char)rest,src+i*EEPROM_PAGE_LEN);
break;
}
else{/*如果剩下的字节数大于EEPROM_PAGE_LEN就读EEPROM_PAGE_LEN个字节*/
AT24C64_rbytes((unsigned char *)&adr,EEPROM_PAGE_LEN,src+i*EEPROM_PAGE_LEN);
rest -=EEPROM_PAGE_LEN;
}
i++;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -