?? 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 + -