單片機: EEPROM和串口通信
內容:此程序用於檢測EEPROM性能,測試方法例如以下:寫入24c02一個數據,然後在內存中改變這些數據。 掉電後主內存將失去這些信息,然後從24c02中調入這些數據。看是否與寫入的同樣。
電腦通過串口發送一個十六進制的數據到單片機,存儲進24c02,要求斷電重新啟動後在數碼管上顯示上一次發送的數據。
(本例是1us機器周期,即晶振頻率要小於12MHZ)
#include <reg52.h> //頭文件的包括 #include <intrins.h> #define _Nop() _nop_() //定義空指令 #define DataPort P0 sbit WEI=P2^7; sbit DUAN=P2^6; // 常,變量定義區 unsigned char code dofly_DuanMa[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f, 0x77,0x7c,0x39,0x5e,0x79,0x71,0x40,0x00};// 顯示段碼值0~F,-,全空 unsigned char code dofly_WeiMa[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//分別相應相應的數碼管點亮,即位碼 unsigned char TempData[8]; sbit SDA=P2^1; //模擬I2C數據傳送位 sbit SCL=P2^0; //模擬I2C時鐘控制位 bit ack; //應答標誌位 unsigned char res; void DelayUs2x(unsigned char t);//函數聲明 void DelayMs(unsigned char t); void Delay(unsigned int t) { while(t--); } void InitUART(void) { SCON=0x50; TMOD|=0x20; TH1=0xFD; TR1=1; EA=1; } void DelayUs2x(unsigned char t) { while(--t); } void DelayMs(unsigned char t) { while(t--) { //大致延時1mS DelayUs2x(245); DelayUs2x(245); } } void Display(unsigned char FirstBit,unsigned char Num) { unsigned char i; for(i=0;i<Num;i++) { DataPort=0; //清空數據。防止有交替重影 DUAN=1; //段鎖存 DUAN=0; DataPort=dofly_WeiMa[i+FirstBit]; //取位碼 WEI=1; //位鎖存 WEI=0; DataPort=TempData[i]; //取顯示數據,段碼 DUAN=1; //段鎖存 DUAN=0; Delay(200); // 掃描間隙延時。時間太長會閃爍, //太短會造成重影 } } /*------------------------------------------------ 啟動總線 ------------------------------------------------*/ void Start_I2c() { SDA=1; //發送起始條件的數據信號 _Nop(); SCL=1; _Nop(); //起始條件建立時間大於4.7us,延時 _Nop(); _Nop(); _Nop(); _Nop(); SDA=0; //發送起始信號 _Nop(); //起始條件鎖定時間大於4μ _Nop(); _Nop(); _Nop(); _Nop(); SCL=0; //鉗住I2C總線。準備發送或接收數據 _Nop(); _Nop(); } /*------------------------------------------------ 結束總線 ------------------------------------------------*/ void Stop_I2c() { SDA=0; //發送結束條件的數據信號 _Nop(); //發送結束條件的時鐘信號 SCL=1; //結束條件建立時間大於4μ _Nop(); _Nop(); _Nop(); _Nop(); _Nop(); SDA=1; //發送I2C總線結束信號 _Nop(); _Nop(); _Nop(); _Nop(); } void SendByte(unsigned char c) { unsigned char BitCnt; for(BitCnt=0;BitCnt<8;BitCnt++) //要傳送的數據長度為8位 { if((c<<BitCnt)&0x80)SDA=1; //推斷發送位 else SDA=0; _Nop(); SCL=1; //置時鐘線為高,通知被控器開始接收數據位 _Nop(); _Nop(); //保證時鐘高電平周期大於4μ _Nop(); _Nop(); _Nop(); SCL=0; } _Nop(); _Nop(); SDA=1; //8位發送完後釋放數據線。準備接收應答位 _Nop(); _Nop(); SCL=1; _Nop(); _Nop(); _Nop(); if(SDA==1)ack=0; else ack=1; //推斷是否接收到應答信號 SCL=0; _Nop(); _Nop(); } unsigned char RcvByte() { unsigned char retc; unsigned char BitCnt; retc=0; SDA=1; //置數據線為輸入方式 for(BitCnt=0;BitCnt<8;BitCnt++) { _Nop(); SCL=0; //置時鐘線為低,準備接收數據位 _Nop(); _Nop(); //時鐘低電平周期大於4.7us _Nop(); _Nop(); _Nop(); SCL=1; //置時鐘線為高使數據線上數據有效 _Nop(); _Nop(); retc=retc<<1; if(SDA==1)retc=retc+1; //讀數據位,接收的數據位放入retc中 _Nop(); _Nop(); } SCL=0; _Nop(); _Nop(); return(retc); } /*---------------------------------------------------------------- 應答子函數 原型: void Ack_I2c(void); ----------------------------------------------------------------*/ void Ack_I2c(void) { SDA=0; _Nop(); _Nop(); _Nop(); SCL=1; _Nop(); _Nop(); //時鐘低電平周期大於4μ _Nop(); _Nop(); _Nop(); SCL=0; //清時鐘線,鉗住I2C總線以便繼續接收 _Nop(); _Nop(); } /*---------------------------------------------------------------- 非應答子函數 原型: void NoAck_I2c(void); ----------------------------------------------------------------*/ void NoAck_I2c(void) { SDA=1; _Nop(); _Nop(); _Nop(); SCL=1; _Nop(); _Nop(); //時鐘低電平周期大於4μ _Nop(); _Nop(); _Nop(); SCL=0; //清時鐘線。鉗住I2C總線以便繼續接收 _Nop(); _Nop(); } /*---------------------------------------------------------------- 向無子地址器件發送字節數據函數 函數原型: bit ISendByte(unsigned char sla,ucahr c); 功能: 從啟動總線到發送地址。數據,結束總線的全過程,從器件地址sla. 假設返回1表示操作成功,否則操作有誤。 註意: 使用前必須已結束總線。----------------------------------------------------------------*/ /*bit ISendByte(unsigned char sla,unsigned char c) { Start_I2c(); //啟動總線 SendByte(sla); //發送器件地址 if(ack==0)return(0); SendByte(c); //發送數據 if(ack==0)return(0); Stop_I2c(); //結束總線 return(1); } */ /*---------------------------------------------------------------- 向有子地址器件發送多字節數據函數 函數原型: bit ISendStr(unsigned char sla,unsigned char suba,ucahr *s,unsigned char no); 功能: 從啟動總線到發送地址。子地址,數據,結束總線的全過程,從器件 地址sla,子地址suba。發送內容是s指向的內容,發送no個字節。 假設返回1表示操作成功。否則操作有誤。 註意: 使用前必須已結束總線。 ----------------------------------------------------------------*/ bit ISendStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no) { unsigned char i; Start_I2c(); //啟動總線 SendByte(sla); //發送器件地址 if(ack==0)return(0); SendByte(suba); //發送器件子地址 if(ack==0)return(0); for(i=0;i<no;i++) { SendByte(*s); //發送數據 if(ack==0)return(0); s++; } Stop_I2c(); //結束總線 return(1); } /*---------------------------------------------------------------- 向無子地址器件讀字節數據函數 函數原型: bit IRcvByte(unsigned char sla,ucahr *c); 功能: 從啟動總線到發送地址,讀數據。結束總線的全過程,從器件地 址sla,返回值在c. 假設返回1表示操作成功,否則操作有誤。
註意: 使用前必須已結束總線。 ----------------------------------------------------------------*/ /*bit IRcvByte(unsigned char sla,unsigned char *c) { Start_I2c(); //啟動總線 SendByte(sla+1); //發送器件地址 if(ack==0)return(0); *c=RcvByte(); //讀取數據 NoAck_I2c(); //發送非就答位 Stop_I2c(); //結束總線 return(1); } */ /*---------------------------------------------------------------- 向有子地址器件讀取多字節數據函數 函數原型: bit ISendStr(unsigned char sla,unsigned char suba,ucahr *s,unsigned char no); 功能: 從啟動總線到發送地址。子地址,讀數據,結束總線的全過程,從器件 地址sla。子地址suba,讀出的內容放入s指向的存儲區。讀no個字節。
假設返回1表示操作成功,否則操作有誤。
註意: 使用前必須已結束總線。
----------------------------------------------------------------*/ bit IRcvStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no) { unsigned char i; Start_I2c(); //啟動總線 SendByte(sla); //發送器件地址 if(ack==0)return(0); SendByte(suba); //發送器件子地址 if(ack==0)return(0); Start_I2c(); SendByte(sla+1); if(ack==0)return(0); for(i=0;i<no-1;i++) { *s=RcvByte(); //發送數據 Ack_I2c(); //發送就答位 s++; } *s=RcvByte(); NoAck_I2c(); //發送非應位 Stop_I2c(); //結束總線 return(1); } /*------------------------------------------------ 主函數 ------------------------------------------------*/ void main() { unsigned char doflye; // 定義暫時變量 unsigned char i; IRcvStr(0xae,4,&doflye,1); //調用存儲數據 TempData[0]=dofly_DuanMa[doflye/16]; TempData[1]=dofly_DuanMa[doflye%16]; InitUART(); ES=1; while(1) { Display(0,2); doflye=res; ISendStr(0xae,4,&doflye,1); //寫入24c02 } } void UART_SER(void) interrupt 4 { unsigned char Temp; // unsigned char i; if(RI) { RI=0; Temp=SBUF; res=Temp; TempData[0]=dofly_DuanMa[Temp/16]; TempData[1]=dofly_DuanMa[Temp%16]; } if(TI) TI=0; }
單片機: EEPROM和串口通信