

完整代碼下載地址: http://m.raoushi.com/f/2402avr.rar
main函數(shù):
/*
程序功能:ATMEGA16讀寫24C02
作者:朱波
時間:2012年1月30日
說明:程序運行后會從0開始自動計數(shù)到256(對字節(jié)操作的結果)
當復位或者斷電時24C02保存斷電時的數(shù)據(jù),當重新啟動后
計數(shù)值會從斷電時的值開始計數(shù)
*/
#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中的數(shù)值,注意必須為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();
}
}
延時函數(shù)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++);
}
}
顯示函數(shù)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;//主函數(shù)中的值
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液晶中顯示數(shù)值的方法
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有區(qū)別
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
//主機模式啟動狀態(tài)碼
#define I2C_START 0x08 //啟動總線
#define I2C_RESTART 0x10 //重新啟動總線
//主機發(fā)送模式狀態(tài)碼
#define I2C_MT_SLA_ACK 0x18 //SLA+W寫地址已發(fā)送,收到應答位
#define I2C_MT_SLA_NACK 0x20 //SLA+W寫地址已發(fā)送,收到非應答位
#define I2C_MT_DATA_ACK 0x28 //寫入數(shù)據(jù)已發(fā)送,收到應答位
#define I2C_MT_DATA_NACK 0x30 //寫入數(shù)據(jù)已發(fā)送,收到應答位
#define I2C_MT_ARB_LOST 0x38 //SLA+W或數(shù)據(jù)仲裁失敗
//主機接收模式狀態(tài)碼
#define I2C_MR_ARB_LOST 0x38 //SLA+R或NOT ACK的仲裁失敗
#define I2C_MR_SLA_ACK 0x40 //SLA+R已發(fā)送,收到應答位
#define I2C_MR_SLA_NACK 0x48 //SLA+R已發(fā)送,收到非應答位
#define I2C_MR_DATA_ACK 0x50 //接收到數(shù)據(jù),應答位已返回
#define I2C_MR_DATA_NACK 0x58 //接收到數(shù)據(jù),非應答位已返回
//從機接收模式狀態(tài)碼
#define I2C_SR_SLA_ACK 0x60 //自己的SLA+W已經(jīng)被接收ACK已返回
#define I2C_SR_ARB_LOST_SLA_ACK 0x68 //SLA+R/W作為主機的仲裁失敗,自己的SLA+W已經(jīng)被接收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被尋址,數(shù)據(jù)已經(jīng)被接收ACK已返回
#define I2C_SR_DATA_NACK 0x88 //以前以自己的SLA+W被尋址,數(shù)據(jù)已經(jīng)被接收NOT ACK已返回
#define I2C_SR_GCALL_DATA_ACK 0x90 //以前以廣播方式被尋址,數(shù)據(jù)已經(jīng)被接收ACK已返回
#define I2C_SR_GCALL_DATA_NACK 0x98 //以前以廣播方式被尋址,數(shù)據(jù)已經(jīng)被接收NOT ACK已返回
#define I2C_SR_STOP 0xA0 //在以從機工作時接收到STOP或重復START
//從機發(fā)送模式狀態(tài)碼
#define I2C_ST_SLA_ACK 0xA8 //自己的SLA+R已經(jīng)被接收ACK已返回
#define I2C_ST_ARB_LOST_SLA_ACK 0xB0 //SLA+R/W作為主機的仲裁失敗,自己的SLA+R已經(jīng)被接收ACK已返回
#define I2C_ST_DATA_ACK 0xB8 //TWDR里數(shù)據(jù)已經(jīng)被發(fā)送接收到ACK
#define I2C_ST_DATA_NACK 0xC0 //TWDR里數(shù)據(jù)已經(jīng)被發(fā)送接收到NOT ACK
#define I2C_ST_LAST_DATA 0xC8 //TWDR的一字節(jié)數(shù)據(jù)已經(jīng)發(fā)送(TWAE='0'),接收到ACK
//其他狀態(tài)碼
#define I2C_NO_INFO 0xF8 //沒有相關的狀態(tài)信息,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))//重新啟動發(fā)送數(shù)據(jù)
#define Write8Bit(x) {TWDR=(x);TWCR=(1<<TWINT)|(1<<TWEN);}//裝入SLA_W到TWDR
//寄存器,TWINT位清零,啟動發(fā)送地址
//定義運行狀態(tài)返回值極性
#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)//字節(jié)寫操作
{
//按照時序來寫
Start();//開始
Wait();//等待
if(TestAck()!=I2C_START)//測試
return 1;// 如果出錯則返回1
Write8Bit(WD_DEVICE_ADDR);//寫器件地址(SLAVE ADDRESS)
Wait();//等待
if(TestAck()!=I2C_MT_SLA_ACK )//檢驗TWI狀態(tài)寄存器,屏蔽
return 1;//預分頻位,如果狀態(tài)字不是SLA+R已發(fā)送,收到應答位
//轉出錯處理 ,(SLA針對的是器件地址)此時時序中第一個ACK結束
Write8Bit(addr);//寫數(shù)據(jù)地址(要存儲到哪個字節(jié)上BYTE ADDRESS)
Wait();//等待
if(TestAck()!=I2C_MT_DATA_ACK )//檢驗TWI狀態(tài)寄存器,屏蔽
return 1;//預分頻位,如果狀態(tài)字不是寫入數(shù)據(jù)已發(fā)送,收到應答位
//轉出錯,到此時序中第二個ACK結束
Write8Bit(wdata);//寫數(shù)據(jù)(DATA)
Wait();//等待
if(TestAck()!=I2C_MT_DATA_ACK)//DATA和ADDRESS是EEPROM內(nèi)部的就用
return 1; //I2C_MT_DATA_ACK
Stop();
return 0;//運行到STOP處都沒有出錯就返回0
}
uchar IIC_Read(uchar addr)//根據(jù)選擇讀時序來寫的
{
uchar temp;//定義此變量從單片機中讀取數(shù)據(jù)
//此段與上個函數(shù)相同
Start();
Wait();
if(TestAck()!=I2C_START)//測試
return 1;
//此段與上個函數(shù)相同
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)//器件內(nèi)部用I2C_MT_DATA_ACK
return 1;//此處時序下方的第二個ACK完成
Start();//根據(jù)時序又出現(xiàn)了START
Wait();
if(TestAck()!=I2C_RESTART)//判斷是否是重復START出現(xiàn)
return 1;//如果出錯則返回1
Write8Bit(RD_DEVICE_ADDR);//讀器件地址(SLAVE ADDRESS)
Wait();
if(TestAck()!=I2C_MR_SLA_ACK)//現(xiàn)在是主機接收所以不是T而是R
return 1;//此處時序下方的第三個ACK完成
Twi();//重新啟動TWI總線
Wait();
if(TestAck()!=I2C_MR_DATA_NACK)//向器件里讀數(shù)據(jù),時序中為NO ACK
return 1;//程序到了這里數(shù)據(jù)已經(jīng)到了單片機里邊了
temp=TWDR;//從數(shù)據(jù)寄存器中讀取數(shù)據(jù)
Stop();//發(fā)送停止信號
return temp;
}
以下是接口函數(shù)代碼:
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
