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