?? twi.c
字號(hào):
/*函數(shù)的使用說(shuō)明:
1.該twi模塊包含四種工作模式,主發(fā),主收,從收,從發(fā),其中主發(fā)由
twiWriteByte(從機(jī)地址,要發(fā)送的數(shù)據(jù))實(shí)現(xiàn),主收由twiReadByte(從機(jī)地址)實(shí)現(xiàn),從機(jī)
的發(fā)送與接收均通過(guò)中斷實(shí)現(xiàn)
2.在從機(jī)模式下,需調(diào)用twi_init()來(lái)使能并初始化twi總線
3.在主機(jī)模式下,調(diào)用twiWriteByte(從機(jī)地址,要發(fā)送的數(shù)據(jù))向指定的從機(jī)寫入數(shù)據(jù),
調(diào)用twiReadByte(從機(jī)地址)從指定的從機(jī)讀取數(shù)據(jù),然后可通過(guò)查詢錯(cuò)誤狀態(tài)error_state
的值決定下一步如何操作。
*/
//************************* 頭文件 ******************************************
#include "twi.h"
//TWI同程序的接口參數(shù)
//receive_data,error_state不用設(shè)置
extern char receive_data; // 接收到的數(shù)據(jù)
extern char error_state; // twi錯(cuò)誤狀態(tài)
//以下三個(gè)參數(shù)根據(jù)需求進(jìn)行設(shè)置
extern char slave_address; // 設(shè)置從機(jī)地址,Bits 7..1:存放從機(jī)地址,Bit 0:最低位為廣播識(shí)別使能位
extern char bit_race; // 設(shè)置主機(jī)模式的比特率,SCL=CPU頻率/(16+2*(TWBR)*4TWPS),TWPS在4的指數(shù)位置
extern char send_data; // 從機(jī)發(fā)送模式下從機(jī)向主機(jī)發(fā)送的數(shù)據(jù)
//*************************** twi錯(cuò)誤狀態(tài)說(shuō)明*********************************
// 0:twi傳送無(wú)錯(cuò)誤
// 1:在主發(fā)模式下,SLA+W已發(fā)送,返回NOT ACK
// 2:在主發(fā)模式下,DATA已發(fā)送,返回NOT ACK
// 3:在主發(fā)模式下,SLA+W或者數(shù)據(jù)的仲裁失敗
// 4:在主收模式下,SLA+R或者數(shù)據(jù)的仲裁失敗
// 5:在主收模式下,SLA+R已發(fā)送,返回NOT ACK
// 6:在主發(fā)模式下,START信號(hào)發(fā)送不成功
// 7:在主收模式下,START信號(hào)發(fā)送不成功
// 8:在主收模式下,數(shù)據(jù)接受完成
// 9:在主收模式下,數(shù)據(jù)接受不成功
//*****************************************************************************
//*************************** twi stop 信號(hào)延時(shí)時(shí)間 ****************************
//******************************************************************************
void StopDelay(void)
{
unsigned int i;
for(i = 0;i < 20;i ++);
}
//******************************* twi 啟動(dòng)總線*********************************
//******************************************************************************
void start(void)
{
TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); //發(fā)出start信號(hào)
_NOP();
_NOP();
}
//************************** twi 釋放總線************************************
//***************************************************************************
void stop(void)
{
TWCR = (1 << TWINT) |(1 << TWEN)|(1 << TWSTO); //發(fā)出stop信號(hào)
StopDelay(); //等待總線恢復(fù)
TWCR= 0x45;
}
//****************************** twi 初始化*************************************
// TWCR: 控制寄存器,用來(lái)控制TWI操作,說(shuō)明如下:
// Bit 7-TWINT:中斷標(biāo)志位,Bit 6-TWEA:使能應(yīng)答位,Bit 5-TWSTA:START狀態(tài)位
// Bit 4-TWSTO:STOP狀態(tài)位,Bit 3-TWWC: 寫沖突標(biāo)志,Bit 2-TWEN:TWI使能位
// Bit 1-RES:保留,Bit 0-TWIE:中斷使能
// TWSR: 狀態(tài)寄存器,Bits 7..3:表示了TWI總線的當(dāng)前狀態(tài),讀取時(shí)需屏蔽低三位的值,Bits 1..0-TWPS:TWI預(yù)分頻位
// TWBR: 比特率寄存器,用來(lái)設(shè)置TWI的工作頻率,計(jì)算公式為:SCL=CPU頻率/(16+2*(TWBR)*4TWPS),TWPS在4的指數(shù)位置
// TWAR: 從機(jī)地址寄存器,Bits 7..1:存放從機(jī)地址,Bit 0:最低位為廣播識(shí)別使能位
// TWDR: 數(shù)據(jù)寄存器,用來(lái)存放接收或要發(fā)送的地址和數(shù)據(jù)
//******************************************************************************
void twi_init(void)
{
TWCR= 0x00; //disable twi
TWBR= bit_race; //set bit rate
TWSR= 0x00; //set prescale為1
TWAR= slave_address; //set slave address
TWCR= 0x45; //enable twi
}
//************************** 檢測(cè)發(fā)送時(shí)的狀態(tài)碼 ****************************
//**************************************************************************
void checkstate(void)
{
unsigned char TWSR_state;
TWSR_state = TWSR & 0xf8; //屏蔽第三位讀取狀態(tài)
switch(TWSR_state)
{
case 0x08:error_state=0;break; // START已發(fā)送
case 0x18:error_state=0;break; // SLA+W已發(fā)送,接收到ACK
case 0x20:error_state=1;break; // SLA+W已發(fā)送,接收到NOT ACK
case 0x28:error_state=0;break; // 數(shù)據(jù)已發(fā)送,接收到ACK
case 0x30:error_state=2;break; // 數(shù)據(jù)已發(fā)送,接收到NOT ACK
case 0x38:error_state=3;break; // SLA+W或數(shù)據(jù)的仲裁失敗
default: break;
}
TWCR=0x45;
}
//********** twi主機(jī)發(fā)送,向地址為WriteAddress的從機(jī)發(fā)送1個(gè)字節(jié)數(shù)據(jù)************
// 入口參數(shù)1:WriteAddress:從機(jī)地址
// TWDR中存放的高七位為地址,最低位表示讀寫控制,0為寫,1為讀
// 入口參數(shù)2:data,向從機(jī)寫的數(shù)據(jù)
//******************************************************************************
void twiWriteByte(unsigned char WriteAddress,char data)
{
unsigned char TWCR_state;
char i=0;
error_state=0;
//初始化 twi
twi_init();
//發(fā)送START信號(hào)
start();
TWCR_state = TWCR & 0x80;
while((TWCR_state == 0x00))
{
i++;
if(i>=10){error_state=6;break;}
TWCR_state = TWCR & 0x80; //輪循等待START信號(hào)發(fā)送完成
}
//若START發(fā)送成功,發(fā)送從機(jī)地址
if(error_state==0)
{
TWDR = WriteAddress; //發(fā)地址
_NOP();
_NOP();
TWCR = (1 << TWINT) | (1 << TWEN);
TWCR_state = TWCR & 0x80;
while(TWCR_state == 0x00)
{TWCR_state = TWCR & 0x80;} //輪循查詢地址是否發(fā)送
checkstate();
}
//若從機(jī)地址發(fā)送成功,向從機(jī)發(fā)送數(shù)據(jù)
if(error_state==0)
{
TWDR = data; //發(fā)數(shù)據(jù)
_NOP();
_NOP();
TWCR = (1 << TWINT) | (1 << TWEN);
TWCR_state = TWCR & 0x80;
while(TWCR_state == 0x00) TWCR_state = TWCR & 0x80; //輪循查詢數(shù)據(jù)是否發(fā)送
checkstate();
}
//發(fā)送STOP,退出總線控制
stop();
}
//************** twi主機(jī)接收,從地址為ReadAaddress的從機(jī)接收1個(gè)字節(jié)*************
// 入口參數(shù)1:ReadAaddress:從機(jī)地址
// TWDR中存放的高七位為地址,最低位表示讀寫控制,0為寫,1為讀
//******************************************************************************
void twiReadByte(unsigned char ReadAaddress)
{
unsigned char TWCR_state;
char i=0;
error_state=0;
//初始化 twi
twi_init();
//發(fā)送START信號(hào)
start();
TWCR_state = TWCR & 0x80;
while((TWCR_state == 0x00))
{
i++;
if(i>=10){error_state=7;break;}
TWCR_state = TWCR & 0x80; //輪循等待START信號(hào)發(fā)送完成
}
//若START信號(hào)發(fā)送完成,發(fā)送讀地址,并讀取數(shù)據(jù)
if(error_state==0)
{
TWDR = ReadAaddress; //發(fā)地址
_NOP();
_NOP();
TWCR = (1 << TWINT) | (1 << TWEN)|( 1<<TWIE )|(1 << TWEA);
while(error_state==0)
{i++;if(i>150){error_state=9;break;}};
}
//發(fā)送STOP,退出總線控制
stop();
}
//************** twi 中斷例程,接收數(shù)據(jù) ****************************************
//******************************************************************************
//twi中斷服務(wù)程序
char twi_isr(void)
{
unsigned char TWSR_state;
TWSR_state = TWSR & 0xf8;
switch(TWSR_state)
{
//從機(jī)接收模式下的中斷程序
case 0x60: TWCR=0xc5;break; // SLA+W已經(jīng)接收,ACK已返回(從機(jī)被尋址,等待主機(jī)發(fā)送數(shù)據(jù))
case 0x80: receive_data = TWDR;TWCR=0xc5;break; // 數(shù)據(jù)已接收,ACK已返回(接收數(shù)據(jù))
case 0x88: TWCR=0xc5;break; // 數(shù)據(jù)已接收,NOT ACK已返回(下一步:退出總線)
case 0xA0: TWCR=0xc5;break; // 接收到STOP或重復(fù)的START信號(hào)(停止接收數(shù)據(jù))
//主機(jī)接收模式下的中斷程序
case 0x38: error_state=4;TWCR=0xc5;break; // SLA+R或NOT ACK仲裁失敗(下一步:退出總線)
case 0x40: TWCR=0xc5; break; // SLA+R已發(fā)送,接收到ACK(從機(jī)被尋址,主機(jī)等待接收數(shù)據(jù))
case 0x48: error_state=5;TWCR=0xc5;break; // SLA+R已發(fā)送,接收到NOT ACK(下一步:退出總線)
case 0x50: receive_data = TWDR;_NOP();_NOP();error_state=8;TWCR = 0xc4;break; // 接收到數(shù)據(jù),ACK已返回(接收數(shù)據(jù))
case 0x58: receive_data = TWDR;_NOP();_NOP();error_state=8;TWCR = 0xc4;break; // 接收到數(shù)據(jù),NOT ACK已返回(下一步:退出總線)
//從機(jī)發(fā)送模式
case 0xA8: TWDR= send_data;_NOP();_NOP();TWCR= 0x85; break; // SLA+R已接收,ACK已返回(從機(jī)被尋址,開(kāi)送發(fā)送數(shù)據(jù))
case 0xB8: TWCR= 0xc5;break; // TWDR里的數(shù)據(jù)已發(fā)送,接受到ACK(主機(jī)接收到數(shù)據(jù),繼續(xù)發(fā)送數(shù)據(jù))
case 0xC0: TWCR= 0xc5;break; // TWDR里的數(shù)據(jù)已發(fā)送,接受到NOT ACK(下一步:退出總線)
case 0xC8: TWCR= 0xc5;break; // TWEA=0,接收到ACK(停止發(fā)送數(shù)據(jù),退出發(fā)送)
//其他狀態(tài)碼
case 0xf8: break; // 等待或進(jìn)行當(dāng)前傳輸
case 0x00: TWCR= 0x95;break; // 非法的START或STOP引起的總線錯(cuò)誤(釋放總線)
default: break;
}
return receive_data; // 返回接收到的數(shù)據(jù)
}
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -