完整代碼下載地址: http://www.zg4o1577.cn/f/2402avr.rar
main函數: /* 程序功能:ATMEGA16讀寫24C02 作者:朱波 時間:2012年1月30日 說明:程序運行后會從0開始自動計數到256(對字節操作的結果) 當復位或者斷電時24C02保存斷電時的數據,當重新啟動后 計數值會從斷電時的值開始計數 */ #include <iom16v.h> #include <macros.h> #include"delay.h" #include"display.h" #include"24C02.h" #define uchar unsigned char #define uint unsigned int uint num;//定義變量用于讀取24C02中的數值,注意必須為uint型 void main() { LCD_init(); twi_init(); while(1) { num=IIC_Read(0x00);//從器件中讀取(0x00是器件地址) num=num+1;//加1 num=num%1000;//關鍵語句,沒有此句則不工作*/ IIC_Write(num,0x00);//加1后寫入器件 display(); } } 延時函數delay.c #include"delay.h" void delay(unsigned int ms) { unsigned int i,j; for(i=0;i<ms;i++) { for(j=0;j<1141;j++); } } 顯示函數display.c #include <iom16v.h> #include <macros.h> #include"display.h" #define uchar unsigned char #define uint unsigned int uchar table1[]="0123456789"; uchar table2[]="zhubo-24C02"; uchar table3[]="result:"; extern uint num;//主函數中的值 void write_com(uchar com) { PORTD&=~BIT(4); PORTD&=~BIT(5); PORTB=com; PORTD|=BIT(6); delay(1); PORTD&=~BIT(6); } void write_dat(uchar dat) { PORTD|=BIT(4); PORTD&=~BIT(5); PORTB=dat; PORTD|=BIT(6); delay(1); PORTD&=~BIT(6); } void LCD_init() { DDRB=0XFF; DDRD|=BIT(4)|BIT(5)|BIT(6); PORTD&=~BIT(6); write_com(0X38); delay(5); write_com(0X01); delay(5); write_com(0X0C); delay(5); write_com(0X06); delay(5); } void display() { uint i; write_com(0X80+0); delay(5); for(i=0;i<7;i++) { write_dat(table3[i]); delay(5); } //這是在1602液晶中顯示數值的方法 write_com(0X80+8); delay(5); write_dat(table1[num/1000]); delay(5); write_com(0X80+9); delay(5); write_dat(table1[num%1000/100]); delay(5); write_com(0X80+10); delay(5); write_dat(table1[num%100/10]); delay(5); write_com(0X80+11); delay(5); write_dat(table1[num%10]); delay(5); write_com(0X80+0X40);//仿真與實際1602有區別 delay(5); for(i=0;i<11;i++) { write_dat(table2[i]); delay(5); } } 24C02.c: #include <iom16v.h> #include <macros.h> #include"24C02.h" #define uchar unsigned char #define uint unsigned int //主機模式啟動狀態碼 #define I2C_START 0x08 //啟動總線 #define I2C_RESTART 0x10 //重新啟動總線 //主機發送模式狀態碼 #define I2C_MT_SLA_ACK 0x18 //SLA+W寫地址已發送,收到應答位 #define I2C_MT_SLA_NACK 0x20 //SLA+W寫地址已發送,收到非應答位 #define I2C_MT_DATA_ACK 0x28 //寫入數據已發送,收到應答位 #define I2C_MT_DATA_NACK 0x30 //寫入數據已發送,收到應答位 #define I2C_MT_ARB_LOST 0x38 //SLA+W或數據仲裁失敗 //主機接收模式狀態碼 #define I2C_MR_ARB_LOST 0x38 //SLA+R或NOT ACK的仲裁失敗 #define I2C_MR_SLA_ACK 0x40 //SLA+R已發送,收到應答位 #define I2C_MR_SLA_NACK 0x48 //SLA+R已發送,收到非應答位 #define I2C_MR_DATA_ACK 0x50 //接收到數據,應答位已返回 #define I2C_MR_DATA_NACK 0x58 //接收到數據,非應答位已返回 //從機接收模式狀態碼 #define I2C_SR_SLA_ACK 0x60 //自己的SLA+W已經被接收ACK已返回 #define I2C_SR_ARB_LOST_SLA_ACK 0x68 //SLA+R/W作為主機的仲裁失敗,自己的SLA+W已經被接收ACK已返回 #define I2C_SR_GCALL_ACK 0x70 //接收到廣播地址ACK已返回 #define I2C_SR_ARB_LOST_GCALL_ACK 0x78 //SLA+R/W作為主機的仲裁失敗,接收到廣播地址ACK已返回 #define I2C_SR_DATA_ACK 0x80 //以前以自己的SLA+W被尋址,數據已經被接收ACK已返回 #define I2C_SR_DATA_NACK 0x88 //以前以自己的SLA+W被尋址,數據已經被接收NOT ACK已返回 #define I2C_SR_GCALL_DATA_ACK 0x90 //以前以廣播方式被尋址,數據已經被接收ACK已返回 #define I2C_SR_GCALL_DATA_NACK 0x98 //以前以廣播方式被尋址,數據已經被接收NOT ACK已返回 #define I2C_SR_STOP 0xA0 //在以從機工作時接收到STOP或重復START //從機發送模式狀態碼 #define I2C_ST_SLA_ACK 0xA8 //自己的SLA+R已經被接收ACK已返回 #define I2C_ST_ARB_LOST_SLA_ACK 0xB0 //SLA+R/W作為主機的仲裁失敗,自己的SLA+R已經被接收ACK已返回 #define I2C_ST_DATA_ACK 0xB8 //TWDR里數據已經被發送接收到ACK #define I2C_ST_DATA_NACK 0xC0 //TWDR里數據已經被發送接收到NOT ACK #define I2C_ST_LAST_DATA 0xC8 //TWDR的一字節數據已經發送(TWAE='0'),接收到ACK //其他狀態碼 #define I2C_NO_INFO 0xF8 //沒有相關的狀態信息,TWINT='0' #define I2C_BUS_ERROR 0x00 //由于非法的START或STOP引起的總線錯誤 //定義SLA中讀寫控制位極性 #define I2C_READ 1 #define I2C_WRITE 0 #define RD_DEVICE_ADDR 0XA1 //寫的器件地址 #define WD_DEVICE_ADDR 0XA0 //讀的器件地址 //常用TWI操作(主模式寫和讀) #define Start() (TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN)) #define Stop() (TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWSTO)) #define Wait() {while(!(TWCR&(1<<TWINT)));} #define TestAck() (TWSR&0XF8) #define SetAck (TWCR|=(1<<TWEA)) #define SetNoAck (TWCR&=~(1<<TWEA)) #define Twi() (TWCR=(1<<TWINT)|(1<<TWEN))//重新啟動發送數據 #define Write8Bit(x) {TWDR=(x);TWCR=(1<<TWINT)|(1<<TWEN);}//裝入SLA_W到TWDR //寄存器,TWINT位清零,啟動發送地址 //定義運行狀態返回值極性 #define I2C_ERR 0 //錯誤 #define I2C_CRR 1 //正確 //定義TWINT位置位查詢等待時間 #define WAITCOUNT 50 //3.6864M時,此處必須大于60,驗證得知小于60,程序均不能正常工作 void twi_init()//硬件初始化 { TWBR=0X20;//TWBR的值不小于10 TWCR=0X04;//使能TWI操作 TWSR=0;//1分頻 } uchar IIC_Write(uchar wdata,uchar addr)//字節寫操作 { //按照時序來寫 Start();//開始 Wait();//等待 if(TestAck()!=I2C_START)//測試 return 1;// 如果出錯則返回1 Write8Bit(WD_DEVICE_ADDR);//寫器件地址(SLAVE ADDRESS) Wait();//等待 if(TestAck()!=I2C_MT_SLA_ACK )//檢驗TWI狀態寄存器,屏蔽 return 1;//預分頻位,如果狀態字不是SLA+R已發送,收到應答位 //轉出錯處理 ,(SLA針對的是器件地址)此時時序中第一個ACK結束 Write8Bit(addr);//寫數據地址(要存儲到哪個字節上BYTE ADDRESS) Wait();//等待 if(TestAck()!=I2C_MT_DATA_ACK )//檢驗TWI狀態寄存器,屏蔽 return 1;//預分頻位,如果狀態字不是寫入數據已發送,收到應答位 //轉出錯,到此時序中第二個ACK結束 Write8Bit(wdata);//寫數據(DATA) Wait();//等待 if(TestAck()!=I2C_MT_DATA_ACK)//DATA和ADDRESS是EEPROM內部的就用 return 1; //I2C_MT_DATA_ACK Stop(); return 0;//運行到STOP處都沒有出錯就返回0 } uchar IIC_Read(uchar addr)//根據選擇讀時序來寫的 { uchar temp;//定義此變量從單片機中讀取數據 //此段與上個函數相同 Start(); Wait(); if(TestAck()!=I2C_START)//測試 return 1; //此段與上個函數相同 Write8Bit(WD_DEVICE_ADDR);//寫器件地址(SLAVE ADDRESS) Wait(); if(TestAck()!=I2C_MT_SLA_ACK)//sla是器件外部 return 1;//此處時序下方的第一個ACK完成 Write8Bit(addr);//寫存儲地址(BYTE ADDRESS) Wait(); if(TestAck()!=I2C_MT_DATA_ACK)//器件內部用I2C_MT_DATA_ACK return 1;//此處時序下方的第二個ACK完成 Start();//根據時序又出現了START Wait(); if(TestAck()!=I2C_RESTART)//判斷是否是重復START出現 return 1;//如果出錯則返回1 Write8Bit(RD_DEVICE_ADDR);//讀器件地址(SLAVE ADDRESS) Wait(); if(TestAck()!=I2C_MR_SLA_ACK)//現在是主機接收所以不是T而是R return 1;//此處時序下方的第三個ACK完成 Twi();//重新啟動TWI總線 Wait(); if(TestAck()!=I2C_MR_DATA_NACK)//向器件里讀數據,時序中為NO ACK return 1;//程序到了這里數據已經到了單片機里邊了 temp=TWDR;//從數據寄存器中讀取數據 Stop();//發送停止信號 return temp; } 以下是接口函數代碼: delay.h: #ifndef delay_h #define delay_h extern void delay(unsigned int ms); #endif display.h: #define uchar unsigned char #define uint unsigned int #ifndef display_h 24C02.h: #define uchar unsigned char #define uint unsigned int extern void twi_init(); extern uchar IIC_Write(uchar wdata,uchar addr); extern uchar IIC_Read(uchar addr); #define display_h extern void write_com(uchar com); extern void write_dat(uchar dat); extern void LCD_init(); extern void display(); extern uchar table[]; #endif