/*==============================================================================
AVR TWI模块相关函数库 TWI_IIC.h
编译环境:IAR 4.30
开发:L_jeary SEU
日期:2010-6-2
说明:在开发过程中参考了ATmega128 手册
本程序已经过本人验证
主要借鉴了微雪电子的程序 在此表示感谢!
为了方便大家学习现挂在blog上 如有不足之处敬请留言指正
==============================================================================*/
#ifndef __TWI_IIC_h
#define __TWI_IIC_h
#define Uchar unsigned char
#define Uint unsigned int
/**************************TWI各种模式状态码***********************************/
#define TWI_START 0x08 //Start已发送
#define TWI_RESTART 0x10 //重复Start已发送
//Master Transmitter MT:主机发送模式状态码
#define TWI_MT_SLA_ACK 0x18 //SLA+W已发送,接收到ACK
#define TWI_MT_SLA_NACK 0x20 //SLA+W已发送,接收到NOT ACK
#define TWI_MT_DATA_ACK 0x28 //数据已发送,接收到ACK
#define TWI_MT_DATA_NACK 0x30 //数据已发送,接收到NOT ACK
#define TWI_MT_ARB_LOST 0x38 //SLA+W或数据的仲裁失败
//Master Receiver MR:主机接收模式状态码
#define TWI_MR_ARB_LOST 0x38 //SLA+R或NOT ACK的仲裁失败
#define TWI_MR_SLA_ACK 0x40 //SLA+R已发送接收到ACK
#define TWI_MR_SLA_NACK 0x48 //SLA+R已发送接收到NOT ACK
#define TWI_MR_DATA_ACK 0x50 //接收到数据 ACK已返回
#define TWI_MR_DATA_NACK 0x58 //接收到数据 NOT ACK已返回
//Slaver Receiver SR:从机接收模式状态码
#define TWI_SR_SLA_ACK 0x60 //自己的SLA+W已被接收 ACK已返回
#define TWI_SR_ARB_LOST_SLA_ACK 0x68 //SLA+R/W作为主机的仲裁失败 己的SLA+W已被接收 ACK已返回
#define TWI_SR_GCALL_ACK 0x70 //接收到广播哦地址 ACK已返回
#define TWI_SR_ARB_LOST_GCALL_ACK 0x78 //SLA+R/W作为主机的仲裁失败 接收到广播地址 ACK已返回
#define TWI_SR_DATA_ACK 0x80 //以前自己的SLA+W被寻址 数据已经被接收到 ACK已返回
#define TWI_SR_DATA_NACK 0x88 //以前自己的SLA+W被寻址 数据已经被接收到 NOT ACK已返回
#define TWI_SR_GCALL_DATA_ACK 0x90 //以前的广播地址被寻址 数据已经被接收到 ACK已返回
#define TWI_SR_GCALL_DATA_NACK 0x98 //前的广播地址被寻址 数据已经被接收到 NOT ACK已返回
#define TWI_SR_STOP 0xA0 //在以从机工作时收到STOP或重复Start
//Slaver Transmitter ST:从机发送模式状态码
#define TWI_ST_SLA_ACK 0xA8 //自己的SLA+W已被接收 ACK已返回
#define TWI_ST_ARB_LOST_SLA_ACK 0xB0 //SLA+R/W作为主机的仲裁失败 己的SLA+W已被接收 ACK已返回
#define TWI_ST_DATA_ACK 0xB8 //TWDR中的数据已经发送 接收到ACK
#define TWI_ST_DATA_NACK 0xC0 //TWDR中的数据已经发送 接收到NOT ACK
#define TWI_ST_LAST_DATA 0xC8 //TWDR的一字节数据已经发送 接收到ACK
//Misc 其他状态码
#define TWI_NO_INFO 0xF8 //没有相关的状态信息 TWINT=0
#define TWI_BUS_ERROR 0x00 //由于非法的Start或Stop引起的总线错误
//宏定义函数
#define TWIWaitAck() {while((TWCR&0x80)==0x00);} //等待ACK应答函数
#define TWIChkAck() (TWSR&0xf8) //读取TWSR的状态码
#define TWIStop() TWCR =0x94; //停止
//TWI Config
#define Wr 0 //发送地址标识
#define Rv 1 //接收地址标识
#define Ds 3 //单纯的发送数据标识
#define TWI_ERR 2 //错误标识
#define TWI_CRR 1 //正确标识
//读写
#define R_N 8 //读取数据字节个数
#define W_N 8 //写入数据字节个数
//TWI(IIC)模块 函数声明
void TWI_init(void); //TWI initial
Uchar TWI_Start(void); //start
Uchar TWI_SendDat(Uchar DAdr,Uchar D_STATUS,Uchar WR);//send data
Uchar TWI_TWI_RecDat(Uchar D_STATUS,Uchar NA); //recieve data
Uchar TWI_MT(Uchar Addr,Uchar num); //MT
Uchar TWI_MR(Uchar Addr,Uchar num); //MR
Uchar TWI_MR_ARB(Uchar Addr,Uchar num); //MR容错处理程序
Uchar TWI_ST(Uchar Addr,Uchar num); //ST
Uchar TWI_SR(Uchar Addr,Uchar num); //SR
//全局变量声明
extern Uchar Array_RdDat[R_N];//读取的数据
extern Uchar Array_WrDat[W_N];//要写的数据
/*==============================================================================
程序名称:TWI_init()
程序功能:TWI初始化函数
注意事项:
提示说明:
输 入:
返 回:
==============================================================================*/
void TWI_init(void)
{
TWBR=0x20;//baund rate set 100KHz
TWCR=0x04;//使能TWI
}
/*==============================================================================
程序名称:TWI Start
程序功能:包括启动和重启动
注意事项:
提示说明:
输 入:
返 回:正确 TWI_CRR 错误 TWI_CRR
==============================================================================*/
Uchar TWI_Start(void)
{
TWCR =0xa4; //启动Start
TWIWaitAck(); //等待ACK应答
if((TWIChkAck()==TWI_START)||(TWIChkAck()==TWI_RESTART)) //判断是否正确
{
return TWI_CRR;
}
else
return TWI_ERR;
}
/*==============================================================================
程序名称:TWI(TWI)发送 7位写地址: XXXX XXX0 7位读地址: XXXX XXX1 或纯粹的数据
程序功能:SLA+W/R
注意事项:
提示说明:
输 入:DAdr:SLA或数据 D_STATUS:状态码 WR: 发送或接受的代码
返 回:正确 TWI_CRR 错误 TWI_CRR
==============================================================================*/
Uchar TWI_SendDat(Uchar DAdr,Uchar D_STATUS,Uchar WR)
{
if(WR==Wr)
TWDR=(DAdr&0xfe); //设置 SLA+W
else if(WR==Rv)
TWDR=(DAdr|0x01); //设置 SLA+R
else if(WR==Ds)
TWDR=DAdr; //如果发送数据直接赋值
else
return TWI_ERR; //如果三者都不是则返回错误标识
TWCR |=0x84; //TWINT=0 TWEN=1
TWIWaitAck(); //等待
if(TWIChkAck()!=D_STATUS) //判断状态码
{
return TWI_ERR;
}
return TWI_CRR;
}
/*==============================================================================
程序名称:TWI_RecDat()
程序功能:TWI(TWI)接收数据
注意事项:
提示说明:
输 入:D_STATUS:状态码 NA: 应答与非应答标识 0不应答 1应答
返 回:正确 TWI_CRR 错误 TWI_CRR
==============================================================================*/
Uchar TWI_TWI_RecDat(Uchar D_STATUS,Uchar NA)
{
if(NA==1) //应答
TWCR = 0xc4;
else if(NA==0)//非应答
TWCR = 0x84;
else
return TWI_ERR;
TWIWaitAck(); //等待
if(TWIChkAck()!=D_STATUS) //判断状态码
{
return TWI_ERR;
}
return TWI_CRR;
}
/*==============================================================================
程序名称:TWI_MT()
程序功能:TWI(TWI)主机发送模式
注意事项:
提示说明:
输 入:Addr:从机地址 num:发送字节个数
返 回:正确 TWI_CRR 错误 TWI_CRR
==============================================================================*/
Uchar TWI_MT(Uchar Addr,Uchar num)
{
Uchar i=0;
if(TWI_Start()==TWI_ERR) //启动或重启动
return TWIChkAck();
//发送从机地址
if(TWI_SendDat(Addr,TWI_MT_SLA_ACK,Wr)==TWI_ERR)
{
return TWIChkAck(); //返回错误状态码
}
//发送数据
while(i<num)
{
if(TWI_SendDat(Array_WrDat[i],TWI_MT_DATA_ACK,Ds)==TWI_ERR)
{
return TWIChkAck(); //返回错误状态码
}
i++;
}
//停止
TWIStop();
return TWI_CRR;
}
/*==============================================================================
程序名称:TWI_MR()
程序功能:TWI(TWI)主机接收模式
注意事项:
提示说明:
输 入:Addr:从机地址 num:接收字节个数
返 回:正确 TWI_CRR 错误 TWI_CRR
==============================================================================*/
Uchar TWI_MR(Uchar Addr,Uchar num)
{
Uchar i=0;
if(TWI_Start()==TWI_ERR) //启动或重启动
return TWIChkAck();
//发送从机地址
if(TWI_SendDat(Addr,TWI_MR_SLA_ACK,Rv)==TWI_ERR)
{
return TWIChkAck(); //返回错误状态码
}
//读取数据
while(i<num-1)
{
if(TWI_TWI_RecDat(TWI_MR_DATA_ACK,1)==TWI_ERR)
{
return TWIChkAck(); //返回错误状态码
}
Array_RdDat[i]=TWDR; //读取接收到的数据
i++;
}
if(TWI_TWI_RecDat(TWI_MR_DATA_NACK,0)==TWI_ERR)
{
return TWIChkAck(); //返回错误状态码
}
Array_RdDat[i]=TWDR; //读取接收到的数据
//停止
TWIStop();
return TWI_CRR;
}
/*==============================================================================
程序名称:TWI_MR_ARB()
程序功能:TWI(TWI)主机接收模式
注意事项:
提示说明:
输 入:Addr:从机地址 num:接收字节个数
返 回:正确 TWI_CRR 错误 TWI_CRR
==============================================================================*/
Uchar TWI_MR_ARB(Uchar Addr,Uchar num)
{
Uchar stat;
stat=TWSR;
switch(stat)
{
case TWI_MR_ARB_LOST:
TWCR|=0x80;
case TWI_CRR:
case TWI_NO_INFO:
case TWI_MR_SLA_NACK:
stat=TWI_MR(Addr,num);
if(stat==1)
{
return 0x55;//如果完成MR模式,则返回完成标志0x55
}
break;
case TWI_BUS_ERROR:
TWCR &=0xc0;
TWCR |=0x80;
//stat=1;
break;
default:
TWCR&=0xc0;
TWCR|=0x80;
//stat=1;
break;
}
return 0xaa; //如果未完成MR模式则返回未完成标志0xaa
}
/*==============================================================================
程序名称:TWI_ST()
程序功能:TWI(TWI)从机发送模式
注意事项:
提示说明:
输 入:Addr:从机地址 num:发送字节个数
返 回:正确 TWI_CRR 错误 TWI_CRR
==============================================================================*/
Uchar TWI_ST(Uchar Addr,Uchar num)
{
Uchar i=0;
TWAR=Addr&0xfe;//从机地址
if(TWI_TWI_RecDat(TWI_ST_SLA_ACK,1)==TWI_ERR)//接收主机发送的从机地址并匹配
{
return TWIChkAck(); //返回错误状态码
}
//发送数据
while(i<num-1)
{
if(TWI_SendDat(Array_WrDat[i],TWI_ST_DATA_ACK,Ds)==TWI_ERR)
{
return TWIChkAck(); //返回错误状态码
}
i++;
}
if(TWI_SendDat(Array_WrDat[i],TWI_ST_DATA_NACK,Ds)==TWI_ERR)
{
return TWIChkAck(); //返回错误状态码
}
return TWI_CRR;
}
/*==============================================================================
程序名称:TWI_SR()
程序功能:TWI(TWI)从机接收模式
注意事项:
提示说明:
输 入:Addr:从机地址 num:接收字节个数
返 回:正确 TWI_CRR 错误 TWI_CRR
==============================================================================*/
Uchar TWI_SR(Uchar Addr,Uchar num)
{
Uchar i=0;
TWAR=Addr&0xfe;//从机地址
if(TWI_TWI_RecDat(TWI_SR_SLA_ACK,1)==TWI_ERR)//接收主机发送的从机地址并匹配
{
return TWIChkAck(); //返回错误状态码
}
//
//读取数据
while(i<num)
{
TWCR |=0xa4; //置应答位
TWIWaitAck(); //等待TWINT置位
switch(TWIChkAck())
{
case TWI_SR_STOP:
return TWI_SR_STOP;
//break;
case TWI_SR_DATA_ACK:
Array_RdDat[i]=TWDR; //存取数据
i++;
break;
case TWI_SR_DATA_NACK:
Array_RdDat[i]=TWDR;
return TWI_SR_DATA_NACK;
//break;
default:
return TWIChkAck();
//break;
}
}
TWCR |=0xa4; //置应答位
TWIWaitAck(); //等待TWINT置位
if(TWIChkAck()!=TWI_SR_STOP)
return TWIChkAck();
return TWI_CRR;
}
#endif
评论