本帖最后由 micro_聽海 于 2012-11-24 19:58 編輯
這幾天一直在搞AVR的twi(twi就是i2c)雙機通信程序,使用的是兩塊arduino開發板。因為最總要這個通信程序最總是要放在winavr的編譯環境中,所以沒有使用arduino自帶的庫函數。但是這沒關系,因為arduino IDE和winavr編譯器的內核都是開源gcc,所以在arduino ide上同樣可以使用winavr的語言,贊ARDUINO!
硬件上就是arduino的SCL(A5引腳)和SDA(A4引腳)互聯,當然還有GND。
下面上程序
先上發送端
#define??uchar??unsigned char
#define??STATUS??(TWSR&0xf8)
#define??SLA_W? ? 0x32
#define??SLA_R? ? 0x33
#define??SLAVER_ADDRESS? ???0x32
#define??START? ?? ?? ?? ???0x08
#define??RE_START? ?? ?? ???0x10
#define??MT_SLA_WRITE_ACK? ?0x18
#define??MT_SLA_READ_ACK? ? 0x40
#define??MT_DATA_ACK? ?? ???0x28
#define??MT_READ_ACK? ?? ???0x58
void Start(void)//主機向從機發送i2c起始信號
{
TWCR=(1<
while(!(TWCR&(1<
}
void Stop(void)//主機發送i2c停止信號
{
TWCR=(1<
}
void Load(uchar i)//主機發送一個字節數據或地址
{
TWDR=i;
TWCR=(1<
while(!(TWCR&(1<
}
uchar SendByte(uchar data)//主機以廣播方式向從機發送一個字節數據data
{
Start();//開始
Load(0);//發送廣播地址0
Load(data);//發送數據
Stop();//停止
return 1;//發送成功,返回1;
}
void Init_Io(void)//io口初始化函數
{
DDRC&=~((1<<4)&(1<<5)&(1<<2));
PORTC|= (1<<4)|(1<<5)|(1<<2);//使能scl,sda引腳內部上拉電阻
TWCR=(1<
TWBR=32;//波特率 200k
}
uchar temp;
void setup( )
{
Init_Io();
Serial.begin(9600);
}
void loop( )
{
for(temp=0;temp<10;temp++)
{
SendByte(temp);??//向從機發送0到9的數據
delay(8);
}
}
接收端程序
#define??uchar??unsigned char
#define??STATUS??(TWSR&0xf8)
#define??SLA_W? ? 0x32
#define??SLA_R? ? 0x33
#define??TWI_ADDRESS? ?? ???0x32
#define??START? ?? ?? ?? ???0x08
#define??RE_START? ?? ?? ???0x10
#define??MT_SLA_WRITE_ACK? ?0x18
#define??MT_SLA_READ_ACK? ? 0x40
#define??MT_DATA_ACK? ?? ???0x28
#define??MT_READ_ACK? ?? ???0x58
#define TW_SR_DATA_ACK? ? ? ? ? ? ? ? 0x80
void Init_Io(void)
{
DDRC&=~((1<<4)&(1<<5)&(1<<2));
PORTC|= (1<<4)|(1<<5)|(1<<2);
TWAR=TWI_ADDRESS|(1<
TWCR=(1<
asm("CLI");//關閉全局中斷,采用輪詢方式接受數據
}
void setup( )
{
Init_Io();
Serial.begin(9600);
}
void loop( )
{
uchar temp1,temp2;
TWCR=(1<
while((TWCR&(1<
temp1=STATUS;
temp2=TWDR;
if(temp1==0x90)
{
Serial.println(temp2,DEC);//打印接收數據
}
}
上述程序已被驗證,打開接受端arduino自帶的串口監控器可以看到0到9的不斷重復數據。
程序中沒用到的宏可自行刪除,不影響最后結果。