登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

谦杰

宁静致远

 
 
 

日志

 
 

AVR TWI总线驱动程序  

2011-06-02 20:10:04|  分类: 默认分类 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
AVR TWI总线驱动程序 - Jeary - 谦杰
/*==============================================================================
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
  评论这张
 
阅读(3923)| 评论(2)

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018