?? at03.c
字號:
/* 這里舉出一個實例(讀寫串行EEPROM芯片at2402) */
/************************************************************************/
/* Name:AT24C02存儲器的讀寫程序,用到I2C總線,含相對獨立的I2C總線讀寫函數 */
/************************************************************************/
#include<string.h>
#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
//#define DELAY_TIME 60 /*經實驗,不要小于50!否則可能造成時序混亂*/
//#define TRUE 1
//#define FALSE 0
sbit SCL=P2^6;/*假設由P3.4和P3.5控制*/
sbit SDA=P2^7;
sbit LCD_RS=P3^5;
sbit LCD_RW=P3^6;
sbit LCD_E=P3^7;
/********** Function Definition 函數定義 ************/
void DELAY(unsigned int t) /*延時函數*/
{
while(t!=0)
t--;
}
void I2C_Start(void)
{
/*啟動I2C總線的函數,當SCL為高電平時使SDA產生一個負跳變*/
SDA=1;
SCL=1;
DELAY(60);
SDA=0;
DELAY(60);
SCL=0;
DELAY(60);
}
void I2C_Stop(void)
{
/*終止I2C總線,當SCL為高電平時使SDA產生一個正跳變*/
SDA=0;
SCL=1;
DELAY(60);
SDA=1;
DELAY(60);
SCL=0;
DELAY(60);
}
void SEND_0(void) /* SEND ACK */
{
/*發送0,在SCL為高電平時使SDA信號為低*/
SDA=0;
SCL=1;
DELAY(60);
SCL=0;
DELAY(60);
}
void SEND_1(void)
{
/*發送1,在SCL為高電平時使SDA信號為高*/
SDA=1;
SCL=1;
DELAY(60);
SCL=0;
DELAY(60);
}
bit Check_Acknowledge(void)
{
/*發送完一個字節后檢驗設備的應答信號*/
SDA=1;
SCL=1;
DELAY(30);
F0=SDA;
DELAY(30);
SCL=0;
DELAY(60);
if(F0==1)
return 0;
return 1;
}
void WriteI2CByte(char b)reentrant
{
/*向I2C總線寫一個字節*/
char i;
for(i=0;i<8;i++)
if((b<<i)&0x80)
SEND_1();
else
SEND_0();
}
char ReadI2CByte(void)reentrant
{
/*從I2C總線讀一個字節*/
char b=0,i;
for(i=0;i<8;i++)
{
SDA=1; /*釋放總線*/
SCL=1; /*接受數據*/
DELAY(10);
F0=SDA;
DELAY(10);
SCL=0;
if(F0==1)
{
b=b<<1;
b=b|0x01;
}
else
b=b<<1;
}
return b;
}
/**********以下為讀寫24c02的函數**********/
void Write_One_Byte(char addr,char thedata)
{
bit acktemp=1;
/*write a byte to mem*/
I2C_Start();
WriteI2CByte(0xa0);
acktemp=Check_Acknowledge();
WriteI2CByte(addr); /*address*/
acktemp=Check_Acknowledge();
WriteI2CByte(thedata); /*thedata*/
acktemp=Check_Acknowledge();
I2C_Stop();
DELAY(60);
}
void Write_A_Page(char addr,char *buffer,char num)
{
bit acktemp=1;
//bit wrtmp;
int i;
/*write a page to at24c02*/
I2C_Start();
WriteI2CByte(0xa0);
acktemp=Check_Acknowledge();
WriteI2CByte(addr);/*address*/
acktemp=Check_Acknowledge();
for(i=0;i<num;i++)
{
WriteI2CByte(buffer[i]);
if(!Check_Acknowledge())
{
I2C_Stop();
}
}
I2C_Stop();
DELAY(60);
}
char Read_One_Byte(char addr)
{
bit acktemp=1;
char mydata;
/*read a byte from mem*/
I2C_Start();
WriteI2CByte(0xa0);
acktemp=Check_Acknowledge();
WriteI2CByte(addr);/*address*/
acktemp=Check_Acknowledge();
I2C_Start();
WriteI2CByte(0xa1);
acktemp=Check_Acknowledge();
mydata=ReadI2CByte();
acktemp=Check_Acknowledge();
return mydata;
I2C_Stop();
}
void Read_N_Bytes(char addr,char *buffer,char n)
{
bit acktemp=1;
int i=0;
/*read 8 bytes from mem*/
I2C_Start();
WriteI2CByte(0xa0);
acktemp=Check_Acknowledge();
WriteI2CByte(addr);/*address*/
acktemp=Check_Acknowledge();
I2C_Start();
WriteI2CByte(0xa1);
acktemp=Check_Acknowledge();
for(i=0;i<n;i++)
{
buffer[i]=ReadI2CByte();
if(i!=n-1)
SEND_0(); /*發送應答*/
else
SEND_1(); /*發送非應答*/
}
I2C_Stop();
}
/***********************************/
/*--------------------------------------
;模塊名稱:delay_n10us();
;功 能:延時函數,延時約n個10us
;-------------------------------------*/
void delay_n10us(uint n) //延時n個10us@12M晶振
{
uint i;
for(i=n;i>0;i--)
{
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
}
}
/*--------------------------------------
;模塊名稱:LCD_write_command();
;功 能:LCD1602寫指令函數
;-------------------------------------*/
void LCD_write_command(uchar dat)
{
delay_n10us(10);
LCD_RS=0; //指令
LCD_RW=0; //寫入
LCD_E=1; //允許
P0=dat;
delay_n10us(10); //實踐證明,我的LCD1602上,用for循環1次就能完成普通寫指令。
LCD_E=0;
delay_n10us(10); //實踐證明,我的LCD1602上,用for循環1次就能完成普通寫指令。
}
/*--------------------------------------
;模塊名稱:LCD_init();
;功 能:初始化LCD1602
;-------------------------------------*/
void LCD_init(void)
{
delay_n10us(10);
LCD_write_command(0x38);//設置8位格式,2行,5x7
delay_n10us(10);
LCD_write_command(0x0c);//整體顯示,關光標,不閃爍
delay_n10us(10);
LCD_write_command(0x06);//設定輸入方式,增量不移位
delay_n10us(10);
LCD_write_command(0x01);//清除屏幕顯示
delay_n10us(100); //延時清屏,延時函數,延時約n個10us
LCD_write_command(0x0d);////開顯示,并顯示光標
delay_n10us(100); //延時清屏,延時函數,延時約n個10us
}
/*--------------------------------------
;模塊名稱:LCD_write_data();
;功 能:LCD1602寫數據函數
;-------------------------------------*/
void LCD_write_data(uchar dat)
{
delay_n10us(10);
LCD_RS=1; //數據
LCD_RW=0; //寫入
LCD_E=1; //允許
P0=dat;
delay_n10us(10);
LCD_E=0;
delay_n10us(10);
}
/*--------------------------------------
;模塊名稱:LCD_disp_char();
;功 能:LCD1602顯示一個字符函數,在某個屏幕位置上顯示一個字符,X(0-15),y(1-2)。
;-------------------------------------*/
void LCD_disp_char(uchar x,uchar y,uchar dat)
{
uchar address;
if(y==1)
address=0x80+x;
else
address=0xc0+x;
LCD_write_command(address);
LCD_write_data(dat);
}
/*--------------------------------------
;模塊名稱:LCD_disp_str();
;功 能:LCD1602顯示字符串函數,在某個屏幕起始位置{X(0-15),y(1-2)}上顯示一個字符串。
;-------------------------------------*/
void LCD_disp_str(uchar x,uchar y,uchar *str)
{
uchar address;
if(y==1)
address=0x80+x;
else
address=0xc0+x;
LCD_write_command(address);
while(*str!='\0')
{
LCD_write_data(*str);
str++;
}
}
void main()
{
//int i;
char mybyte;
char code myarray[15]={0x46,0x4C,0x59,0x3A,0x31,0x33,0x36,0x34,0x30,0x33,0x30,0x38,0x30,0x34,0x31};
char code myarray2[9]={0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49};
char rdarray[20];
//Write_One_Byte(0x20,0x34);
Write_A_Page(0x00,myarray2,9);
//Write_A_Page(0x18,myarray2,9);
mybyte=Read_One_Byte(0x00);
Read_N_Bytes(0x00,rdarray,9);
P1=rdarray[8];
LCD_init();
LCD_disp_str(0,1,myarray2);
LCD_disp_str(0,2,rdarray);
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -