困擾我幾的程序終於搞定了,前幾天我對AT24C02一直讀不準確,找了N長時間的程序都沒有頭緒,後來在板哥的指點下,一下子明白了,原因很簡單,我在AT24C02_read()最後沒有加延時, 主要還是對時序沒有控制好呀,用板哥的一句話是我們對器件的了解還不很熟,我現在也感到,一定要先了解了器件的特性,我們才能遊刃有餘把握住每一個容易疏忽的細節,在這裡,板哥確實教會了我好多東西,在我剛學單片機時,他就對我說時序很重要,現在終於是看到了. 好了不羅嗦了,最後得出一點,最好在每個讀寫結束時加個延時,如果對時間要求不是很重要的話,加的長一點無所謂,如果要求比較高的話,那先加長延時,然後慢慢的減. #include #include
//輸入方式設置 #define LCD_AC_AUTO_INCREMENT 0x06 //數據讀、寫操作后,AC自動增一 #define LCD_AC_AUTO_DECREASE 0x04 //數據讀、寫操作后,AC自動減一 #define LCD_MOVE_ENABLE 0x05 //數據讀、寫操作,畫面平移 #define LCD_MOVE_DISENABLE 0x04 //數據讀、寫操作,畫面不動 #define LCD_GO_HOME 0x02 //AC=0,游標、畫面回HOME位 //設置顯示、游標及閃爍開、關 #define LCD_DISPLAY_ON 0x0C //顯示開 #define LCD_DISPLAY_OFF 0x08 //顯示關 #define LCD_CURSOR_ON 0x0A //游標顯示 #define LCD_CURSOR_OFF 0x08 //游標不顯示 #define LCD_CURSOR_BLINK_ON 0x09 //游標閃爍 #define LCD_CURSOR_BLINK_OFF 0x08 //游標不閃爍 //游標、畫面移動,不影響DDRAM #define LCD_LEFT_MOVE 0x18 //LCD顯示左移一位 #define LCD_RIGHT_MOVE 0x1C //LCD顯示右移一位 #define LCD_CURSOR_LEFT_MOVE 0x10 //游標左移一位 #define LCD_CURSOR_RIGHT_MOVE 0x14 //游標右移一位 //工作方式設置 #define LCD_DISPLAY_DOUBLE_LINE 0x38 //兩行顯示 #define LCD_DISPLAY_SINGLE_LINE 0x30 //單行顯示 #define LCD_CLEAR_SCREEN 0X01 //清屏 /***********************LCD1602地址相關******************************/ #define LINE1_HEAD 0x80 // 第一行DDRAM起始地址 #define LINE2_HEAD 0xc0 // 第二行DDRAM起始地址 #define LINE1 0 //第一行 #define LINE2 1 //第二行 #define LINE_LENGTH 16 //每行的最大字元長度 /***********************LCD1602接線引腳定義************************** **********************可根據實際電路改變*******************************/ #define LCDIO P2 //定義P2口與LCD1602的數據口相接 sbit LCD_RS=P1^4; sbit LCD_RW=P1^3; sbit LCD_EN=P1^2; sbit LCD_BUSY=LCDIO^7; /**********************另外相關的定義*********************************/ #define HIGH 1 #define LOW 0 #define TURE 1 #define FALSE 0 #define uchar unsigned char #define uint unsigned int #define NUM 10 /*************************以下是函數的申明部分*************************/ void LCD_init(void); //LCD1602初始化 void LCD_send_command(uchar command); // void LCD_send_data(uchar dat); void LCD_write_char(uchar x,uchar y,uchar dat); void LCD_write_string(uchar x,uchar y,char *Data); void delay_ms(uint n); void LCD_check_busy(void); /*********************結束***********************************************/ //at24c02 part #define WRITE24C02 0xA0 #define READ24C02 0xA1 //I2C part #define Wait1us _nop_(); #define Wait2us {_nop_();_nop_();} #define Wait4us {Wait2us;Wait2us;} #define Wait8us {Wait4us;Wait4us;} #define Wait10us {Wait8us;Wait2us;} sbit SDA=P2^7; //AT24C02 serial data pin 5 sbit SCL=P2^6; //AT24C02 serial clock pin 6 /********************************************************************/ void I2C_start(void);//I2C start function void I2C_stop(void);//I2C stop function //void I2C_send_ack(void);//I2C send responsion function void I2C_send_noack(void); void I2C_write_byte(unsigned char IIC_data);//I2C bus write byte function unsigned char I2C_read_byte(void);//I2C bus read byte function /********************************************************************/ void AT24C02_write(unsigned char address,unsigned char *buf,unsigned char n);//write 24c02 information function void AT24C02_read(unsigned char address,unsigned char *buf,unsigned char n);//read 24c02 information function /********************************************************************/ void Mcu_init(void);//system initize funcition void I2C_init(void); unsigned char count[2]; unsigned char sharebuf[NUM]; /********************************************************************/ void main() { unsigned char temp; Mcu_init(); while(1) { sharebuf[0]=count[1]; sharebuf[1]=count[0]; AT24C02_write(0x00,sharebuf,2); AT24C02_read(0x00,sharebuf,2); temp=sharebuf[0]; LCD_write_string(0x00,LINE1,"AT24C02 TEST"); LCD_write_char(0x0e,LINE1,(temp/10) 0x30); LCD_write_char(0x0f,LINE1,(temp%10) 0x30); LCD_write_string(0x00,LINE2,"TIMER0 JISHU"); LCD_write_char(0x0e,1,(count[1]/10) 0x30); LCD_write_char(0x0f,1,(count[1]%10) 0x30); } } /***********************************************************************/ void timer0(void) interrupt 1 using 1 { TH0=-(12000/256); TL0=-(12000%256); count[0]=count[0]+1; if(count[0]==100) { count[0]=0; count[1]=count[1]+1; if(count[1]==99) count[1]=0; } } /***********************************************************************/ void Mcu_init(void) { TMOD=0x01; TH0=-(12000/256); TL0=-(12000%256); EA=HIGH; ET0=HIGH; TR0=HIGH; LCD_init(); } /***********************************************************************/ /******************************** I2C PART **************************/ void I2C_start(void) { SDA=1; SCL=1; SDA=0; SCL=0; } /***********************************************************************/ void I2C_stop(void) { SCL=0; SDA=0; SCL=1; SDA=1; } /***********************************************************************/ void I2C_send_ack(void) { SDA=0; SCL=1; SCL=0; SDA=1; } /*************************************************************************/ void I2C_send_noack(void) { SDA=1; SCL=1; SCL=0; } /*****************************************************************************/ bit TestAck() { bit ErrorBit; SDA=1; SCL=1; ErrorBit=SDA; SCL=0; return(ErrorBit); } /***********************************************************************/ void I2C_write_byte(unsigned char input) { unsigned char temp; for(temp=8;temp!=0;temp--) { SDA=(bit)(input&0x80); SCL=1; SCL=0; input=input<<1; } } /***********************************************************************/ unsigned char I2C_read_byte(void) { unsigned char temp,rbyte=0; for(temp=8;temp!=0;temp--) { SCL=1; rbyte=rbyte<<1; rbyte=rbyte ((unsigned char)(SDA)); SCL=0; } return(rbyte); } /************************************************************************/ void AT24C02_write(unsigned char address,unsigned char *buf,unsigned char Nbyte) { I2C_start(); I2C_write_byte(WRITE24C02); TestAck(); I2C_write_byte(address); TestAck(); for(;Nbyte!=0;Nbyte--) { I2C_write_byte(*buf); TestAck(); buf++; } I2C_stop(); delay_ms(10);//這個很重要,調了幾天問題就是出在h里的,最好在每個函數之間加延時 } /************************************************************************/ void AT24C02_read(unsigned char address,unsigned char *buf,unsigned char Nbyte) { I2C_start(); I2C_write_byte(WRITE24C02); TestAck(); I2C_write_byte(address); TestAck(); I2C_start(); I2C_write_byte(READ24C02); TestAck(); while(Nbyte!=1) { *buf=I2C_read_byte(); I2C_send_ack(); buf++; Nbyte--; } *buf=I2C_read_byte(); I2C_send_noack(); I2C_stop(); } /**************LCD1602的初始化***************************/ void LCD_init(void) { LCD_send_command(LCD_DISPLAY_DOUBLE_LINE); LCD_send_command(LCD_AC_AUTO_INCREMENT LCD_MOVE_DISENABLE); LCD_send_command(LCD_DISPLAY_ON LCD_CURSOR_OFF); LCD_send_command(LCD_CLEAR_SCREEN); } /***********************檢測LCD狀態*********************************/ void LCD_check_busy(void) { do { LCD_EN=0; LCD_RS=0; LCD_RW=1; LCDIO=0xff; LCD_EN=1; } while(LCD_BUSY==1); LCD_EN=0; } /************LCD1602寫命令*******************************/ void LCD_send_command(uchar command) { LCD_check_busy(); LCD_RS=LOW; LCD_RW=LOW; LCD_EN=HIGH; LCDIO=command; LCD_EN=LOW; } /********************************************************/ /*****************LCD1602寫數據**************************/ void LCD_send_data(uchar dat) { LCD_check_busy(); LCD_RS=HIGH; LCD_RW=LOW; LCD_EN=HIGH; LCDIO=dat; LCD_EN=LOW; } /***********************LCD1602顯示字元*********************************/ void LCD_write_char(uchar x,uchar y,uchar dat) { unsigned char address; if (y == LINE1) address = LINE1_HEAD + x; else address = LINE2_HEAD + x; LCD_send_command(address); LCD_send_data(dat); } /******************LCD1602顯示字元串*********************/ void LCD_write_string(uchar x,uchar y,uchar *Data) { if(y==LINE1) { if(x<LINE_LENGTH) { LCD_send_command(LINE1_HEAD+x); for(;x<LINE_LENGTH&&*Data!=''''\0'''';x++) { LCD_send_data(*(Data++)); } if(*Data!=''''\0'''') { x=0; y=LINE2; } } } if(y==LINE2) { LCD_send_command(LINE2_HEAD+x); for(;x<LINE_LENGTH&&*Data!=''''\0'''';x++) { LCD_send_data(*(Data++)); } } } /****************************************************************/ /********************延時函數***********************************/ /***************************************************************/ void delay_ms(uint n) { uint i,j; for(i=n;i>0;i--) for(j=0;j<1140;j++) ; } |