📄 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 + -