專注電子技術(shù)學(xué)習(xí)與研究
當(dāng)前位置:單片機(jī)教程網(wǎng) >> MCU設(shè)計(jì)實(shí)例 >> 瀏覽文章

AVR片內(nèi)TWI總線(I2C總線協(xié)議)

作者:我行天下   來源:本站原創(chuàng)   點(diǎn)擊數(shù):  更新時(shí)間:2014年03月31日   【字體:


/*本程序?yàn)榘宋还碴帢O數(shù)碼管且有兩個(gè)573控制的動(dòng)態(tài)掃描*/
/*此程序?yàn)殚_機(jī)記憶,可以每次開機(jī)分自動(dòng)加一。如果加了,說明操作成功*/
/*本程序把24C08的SCL和SDA分別接在MCU的SCL(PC0第22腳)和SDA(PC1第23腳)*/
//24C08的第7腳WP接地
#include <iom16v.h>
#include <macros.h>//這里面有BIT(),所以要包含
#define uchar unsigned char
#define uint unsigned int
#pragma data:code //注code的功能是把后面的數(shù)據(jù)存在程序存貯器中,不用code就放到了隨機(jī)存貯器中.
uchar const table[]={0x3f,0x06,0x5b,0x4f,0x66,
0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00} ;
/*如果用uchar table[]就放到了數(shù)據(jù)存貯器中。決不要這樣用,這樣占用空間多。*/
/*兩個(gè)573,段碼PA3,位碼PA4*/
/****************************
 I2C 狀態(tài)定義
 MT 主方式傳輸 MR 主方式接受
***************************/
#define START   0x08
#define RE_START  0x10
#define MT_SLA_ACK  0x18
#define MT_SLA_NOACK  0x20
#define MT_DATA_ACK  0x28
#define MT_DATA_NOACK 0x30
#define MR_SLA_ACK  0x40
#define MR_SLA_NOACK 0x48
#define MR_DATA_ACK  0x50
#define MR_DATA_NOACK 0x58
#define RD_24C08_add 0xaf 
//讀24C08的地址,前4位器件固定,后三位看連線(本機(jī)全接高),最后1位是1讀指令位
#define WD_24C08_add 0xae
//寫24C08的地址,前4位器件固定,后三位看連線(本機(jī)全接高),最后1位是0寫指令位
//上述定義中,MT為主機(jī)發(fā)送,MR為主機(jī)接收
//上述定義中,SLA是對(duì)地址操作,DATA是對(duì)數(shù)據(jù)操作
/*常用TWI操作(主模式寫和讀)*/
#define Start()   TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN)  //啟動(dòng)I2C
#define Stop()   TWCR=(1<<TWINT)|(1<<TWSTO)|(1<<TWEN)  //停止I2C
#define Wait()   while(!(TWCR&(1<<TWINT)))    //等待中斷發(fā)生
#define TestAck()  TWSR&0xf8        //觀察返回狀態(tài)
#define SetAck   TWCR|=(1<<TWEA)       //做出ACK應(yīng)答
#define SetNoAck  TWCR&=~(1<<TWEA)       //做出Not Ack應(yīng)答
#define Twi()  TWCR=(1<<TWINT)|(1<<TWEN)    //啟動(dòng)I2C
#define Write8Bit(x) TWDR=(x);TWCR=(1<<TWINT)|(1<<TWEN)  //寫數(shù)據(jù)到TWDR
/*延時(shí)子程序*/
void delay_ms(int time)
{
 int i;
 for(;time>0;time--)
  for(i=0;i<1000;i++);
}
 
void show(uchar dat,uchar wei)
{
   DDRA|=BIT(3);//把PA3設(shè)為輸出
   DDRA|=BIT(4);//把PA4設(shè)為輸出
   DDRB=0XFF;//把PB口設(shè)為輸出型,全為高
    PORTA|=BIT(3);
 PORTB=table[dat];
 PORTA&=~BIT(3);
 
 PORTB=0XFF;
 PORTB&=~BIT(wei);
 PORTA|=BIT(4);
 PORTA&=~BIT(4);
 delay_ms(1);
}
void TWI_init()//初始化TWI總線
{
TWBR=0X20;//TWIA 工作在主機(jī)模式下,TWRB的值不小于10,0X20一定大于10
TWCR=0X04;//把TWCR中,TWEN使能打開,所以是0X04
TWSR=0;//只用1分頻就可以了,就是不用分頻,就用晶振頻率
}

/*********************************************
I2C總線寫一個(gè)字節(jié)  返回0:寫成功  返回1:寫失敗
**********************************************/

uchar  IIC_write(uchar add,uchar dat)
{
Start();//發(fā)送啟始位
Wait();//等待
if(TestAck()!=START)//也可寫成if(TestAck!=0X80)
return 1;
Write8Bit(WD_24C08_add);//告訴24C08,現(xiàn)在要寫操作,也可寫成Write8bit(0xA0);
Wait();//等待
if(TestAck()!=MT_SLA_ACK)//也可寫成if(TestAck!=0X18)
return 1;
//LSA是對(duì)器件的應(yīng)答
Write8Bit(add);//寫入要寫入數(shù)據(jù)的地址
Wait();//等待
if(TestAck()!=MT_DATA_ACK)//也可寫成if(TestACK()!=0X28)
return 1;
//DATA是對(duì)數(shù)據(jù)應(yīng)答
Write8Bit(dat);
Wait();//等待
if(TestAck()!=MT_DATA_ACK)//也可寫成if(TestACK()!=0X28)
return 1;
Stop();//送出停止信號(hào)
return 0;
}

uchar IIC_rd(uchar add)
{
uchar temp;
Start();//發(fā)送啟始位
Wait();//等待
if(TestAck()!=START)//也可寫成if(TestAck!=0X80)
return 1;
Write8Bit(WD_24C08_add);//告訴24C08,現(xiàn)在要寫操作,也可寫成Write8bit(0xA0);
Wait();//等待
if(TestAck()!=MT_SLA_ACK)//也可寫成if(TestAck!=0X18)
return 1;
//SLA是對(duì)器件的應(yīng)答

Write8Bit(add);//寫入要讀出數(shù)據(jù)的地址
Wait();//等待
if(TestAck()!=MT_DATA_ACK)//也可寫成if(TestACK()!=0X28)
return 1;
//DATA是對(duì)數(shù)據(jù)應(yīng)答
Start();//重復(fù)發(fā)送啟始位
Wait();//等待
if(TestAck()!=RE_START)//也可寫成if(TestAck!=0X10)
return 1;
Write8Bit(RD_24C08_add);//告訴24C08,現(xiàn)在要讀操作,也可寫成Write8bit(0xA1);
Wait();//等待
if(TestAck()!=MR_SLA_ACK)//主機(jī)接收判斷,也可寫成if(TestAck!=0X40)
return 1;
Twi(); //須要重新啟動(dòng)
Wait();//等待
if(TestAck()!=MR_DATA_NOACK)
return 1;
 
temp=TWDR;
Stop();//送出停止信號(hào)
return temp;
}
void main()
{
uchar i;
TWI_init();
i=IIC_rd(2);
if(i>9)
i=0;
i++;
IIC_write(2,i);
  while(1)
     {
   show(i,2);
  }
}
 

關(guān)閉窗口

相關(guān)文章