?? twi.c
字號:
#include "includes.h"
/*-----------------------------------變量定義---------------------------------*/
/* 發送緩沖區 */
INT8U TWI_SendData[TWI_SEND_DATA_BUFFER_SIZE];
INT8U TWI_SendDataIndex;
INT8U TWI_SendDataLength;
/* 接收緩沖區 */
INT8U TWI_ReceiveData[TWI_RECEIVE_DATA_BUFFER_SIZE];
INT8U TWI_ReceiveDataIndex;
INT8U TWI_ReceiveDataLength;
/*----------------------------------TWI初始化---------------------------------*/
void TWI_Init(void)
{
/*設置總線上拉 */
#ifndef __iom128_h
//#ifndef __iom64v_h
PORTD |= 0x03; // TWI SCL SDA on ATmega128,64
#else
PORTC|= 0x03; // TWI SCL SDA on ATmega163,323,16,32,等
#endif
/*設置 TWI 波特率為 100KHz; TWI標準波特率: 低速 100KHz ;高速 400KHz */
TWI_SetBitrate(100);
/*TWI總線使能*/
TWCR|=1<<TWEN;
/*開TWI中斷和回應*/
TWCR|=1<<TWIE;
TWCR|=1<<TWEA;
}
/*---------------------------------設置總線速率-------------------------------*/
void TWI_SetBitrate(INT8U bitrateKHz)
{
INT8U bitrate_div;
// SCL freq = Crystal/(16+2*TWBR))
#ifdef TWPS0
/* 對于用速率分頻的AVR (mega128)
SCL freq = Crystal/(16+2*TWBR*4^TWPS)
set TWPS to zero
TWSR&=~(1<<TWPS0);
TWSR&=~(1<<TWPS1); */
#endif
/*計算分頻*/
bitrate_div = ((Crystal/1000l)/bitrateKHz);
if(bitrate_div >= 16)
{
bitrate_div = (bitrate_div-16)/2;
}
TWBR = bitrate_div;
}
/*---------------------------------TWI發送開始--------------------------------*/
void TWI_SendStart(void)
{
TWCR=TWCR&TWCR_CMD_MASK|(1<<TWINT)|(1<<TWSTA);
}
/*-----------------------發送停止條件,保持TWEA以便從接收---------------------*/
void TWI_SendStop(void)
{
TWCR=TWCR&TWCR_CMD_MASK|(1<<TWINT)|(1<<TWEA)|(1<<TWSTO);
}
/*------------------------------等待TWI 總線操作完成--------------------------*/
void TWI_WaitForComplete(void)
{
while( !(TWCR&(1<<TWINT)) )WDR();
}
/*-------------------------------返回接收到的數據-----------------------------*/
INT8U TWI_GetReceivedByte(void)
{
return( TWDR );
}
/*--------------------------------TWI單字節發送-------------------------------*/
void TWI_SendByte(INT8U data)
{
TWDR=data; // 裝載數據到 TWDR
TWCR=TWCR&TWCR_CMD_MASK|(1<<TWINT); // 發送開始
}
/*--------------------------------TWI單字節接收-------------------------------*/
void TWI_ReceiveByte(INT8U ackFlag)
{
if( ackFlag ) // 開始通過 TWI 接收
{
TWCR=TWCR&TWCR_CMD_MASK|(1<<TWINT)|(1<<TWEA); // ackFlag = TRUE: 數據接收后回應ACK
}
else
{
TWCR=TWCR&TWCR_CMD_MASK|(1<<TWINT); // ackFlag = FALSE: 數據接收后無回應
}
}
/*-----------------------TWI主機發送,用于I2C器件讀寫-------------------------*/
INT8U TWI_MasterSendNI(INT8U deviceAddr, INT8U length, INT8U* data)
{
INT8U retval = TWI_OK;
//CLI();
/*關TWI中斷*/
TWCR&=~(1<<TWIE);
/*發送開始條件*/
TWI_SendStart();
TWI_WaitForComplete();
/*發送器件寫地址*/
TWI_SendByte( deviceAddr & 0xFE );
TWI_WaitForComplete();
/*檢查器件是否可用*/
if( TWSR == TW_MT_SLA_ACK)
{
/*發送數據*/
while(length)
{
WDR();
TWI_SendByte( *data++ );
TWI_WaitForComplete();
length--;
}
}
else
{
/*如未回應器件地址,停止發送,返回錯誤*/
retval = TWI_ERROR_NODEV;
}
/*發送停止條件,保持TWEA以便從接收*/
TWI_SendStop();
while( !(TWCR&(1<<TWSTO)) )WDR();
/*開TWI中斷*/
TWCR|=(1<<TWIE);
//SEI();
return retval;
}
/*-----------------------TWI主機接收,用于I2C器件讀寫-------------------------*/
INT8U TWI_MasterReceiveNI(INT8U deviceAddr, INT8U length, INT8U *data)
{
INT8U retval = TWI_OK;
//CLI();
/*關TWI中斷*/
TWCR&=~(1<<TWIE);
/*發送開始條件*/
TWI_SendStart();
TWI_WaitForComplete();
/*發送器件讀地址*/
TWI_SendByte(deviceAddr| 0x01 );
TWI_WaitForComplete();
/*檢查器件是否可用*/
if( TWSR == TW_MR_SLA_ACK)
{
/*接收數據并回應*/
while(length > 1)
{
WDR();
TWI_ReceiveByte(TRUE);
TWI_WaitForComplete();
*data++ = TWI_GetReceivedByte();
length--;
}
/*接收數據無回應 (末位信號)*/
TWI_ReceiveByte(FALSE);
TWI_WaitForComplete();
*data++ = TWI_GetReceivedByte();
}
else
{
/*如未回應器件地址,停止發送,返回錯誤*/
retval = TWI_ERROR_NODEV;
}
/*發送停止條件,保持TWEA以便從接收*/
TWI_SendStop();
/*開TWI中斷*/
TWCR|=TWIE;
//SEI();
return retval;
}
/*---------------------------------TWI中斷服務程序----------------------------*/
void TWI_ISR(void)
{
INT8U status;
//CLI();
/*讀狀態位*/
status = TWSR & TWSR_STATUS_MASK;
switch(status)
{
/*-------------------主方式-----------------*/
case TW_START: // 0x08: START 已發送
case TW_REP_START: // 0x10: 重復START 已發送
break;
/*主發送,主接收狀態碼*/
case TW_MT_SLA_ACK: // 0x18: SLA+W 已發送;接收到ACK
case TW_MT_DATA_ACK: // 0x28: 數據已發送;接收到ACK
if(TWI_SendDataIndex < TWI_SendDataLength)
{
TWI_SendByte( TWI_SendData[TWI_SendDataIndex++] ); // 發送數據
}
else
{
TWI_SendStop(); // 發送停止條件,保持TWEA以便從接收
}
break;
case TW_MR_DATA_NACK: // 0x58: 接收到數據;NOT ACK 已返回
TWI_ReceiveData[TWI_ReceiveDataIndex++] = TWDR; // 保存最終數據
/*繼續發送條件*/
case TW_MR_SLA_NACK: // 0x48: SLA+R 已發送,接收到NOT ACK
case TW_MT_SLA_NACK: // 0x20: SLA+W 已發送,接收到NOT ACK
case TW_MT_DATA_NACK: // 0x30: 數據已發送,接收到NOT ACK
TWI_SendStop(); // 發送停止條件,保持TWEA以便從接收
break;
case TW_MT_ARB_LOST: // 0x38: SLA+W 或數據的仲裁失敗
TWCR=TWCR&TWCR_CMD_MASK|(1<<TWINT); // 釋放總線
break;
case TW_MR_DATA_ACK: // 0x50: 接收到數據,ACK 已返回
TWI_ReceiveData[TWI_ReceiveDataIndex++] = TWDR; // 保存接收到的數據位
/*檢查是否接收完*/
case TW_MR_SLA_ACK: // 0x40: SLA+R 已發送,接收到ACK
if(TWI_ReceiveDataIndex < (TWI_ReceiveDataLength-1))
{
TWI_ReceiveByte(TRUE); // 數據位將接收 , 回復 ACK (傳送更多字節)
}
else
{
TWI_ReceiveByte(FALSE); // 數據位將接收 , 回復 NACK (傳送最后字節)
}
break;
case TW_NO_INFO: // 0xF8: 沒有相關的狀態信息;TWINT = “0”
; // 無操作
break;
case TW_BUS_ERROR: // 0x00: 由于非法的START 或STOP 引起的總線錯誤
TWCR=TWCR&TWCR_CMD_MASK|(1<<TWINT)|(1<<TWSTO)|(1<<TWEA); // 內部硬件復位,釋放總線
break;
}
//SEI();
}
/*------------------------------------------------------------------------------
0ooo
ooo0 ( )
( ) ) /
\ ( (_/
\_)
------------------------------------------------------------------------------*/
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -