搜索
bottom↓
回复: 6

I2C(TWI/SMBUS)LPC213X主机通讯例程

[复制链接]

出0入0汤圆

发表于 2006-10-29 07:32:58 | 显示全部楼层 |阅读模式
hotpower 发表于 2006-10-28 11:32 ZLG-ARM ←返回版面   



I2C(TWI/SMBUS)LPC213X主机通讯例程  



void TwiObj::TWStart(void)

{

  Busy = true;

  Status = 0;//主机准备发送启始位

  Count = 0;//发送数据个数

  I2C0->I2C_CONSET = (1 << I2EN) | (1 << STA);

}



void TwiObj::TWREStart(void)

{

  Busy = true;

  Status = 0x55;//主机准备发送启始位

  Count = 0;//接收数据个数

  I2C0->I2C_CONCLR = (1 << STA) | (1 << SI) | (1 << AA);

  I2C0->I2C_CONSET = (1 << I2EN) | (1 << STA);

}

//__inline

void TwiObj::TWStop(void)

{

  Busy = false;

  Status = 0x88;//通讯成功

  I2C0->I2C_CONSET = (1 << I2EN) | (1 << STO);

  I2C0->I2C_CONCLR = (1 << STA) | (1 << SI) | (1 << AA);

}



void TwiObj::TWExit(void)

{

  Busy = false;//通讯失败

  I2C0->I2C_CONSET = (1 << I2EN) | (1 << STO);

  I2C0->I2C_CONCLR = (1 << STA) | (1 << SI) | (1 << AA);

}



void TwiObj::Exec(void)

{

  switch(I2C0->I2C_STAT & 0xf8) {

    case I2C_START://主机收到自己发送的开始信号

           if (Status == 0) {//本次中断应该接收TW_START信号//pwy

             I2C0->I2C_DAT = SubAddr & 0xfe;//发送子机地址(写)

             Status = 1;//Status下次主发为1,主收为2

             I2C0->I2C_CONCLR = (1 << STA) | (1 << SI) | (1 << AA);//清除中断标志

           }

           else TWExit();//通讯失败

           break;

    case I2C_REP_START://主机收到自己发送的重新开始信号

           if ((Status == 0x55) && (SubAddr & 0xfe)) {//本次中断应该接收TW_START信号//pwy

             I2C0->I2C_DAT = SubAddr;//发送子机地址(读)

             Status = 2;//Status下次主发为1,主收为2

             I2C0->I2C_CONCLR = (1 << STA) | (1 << SI) | (1 << AA);//清除中断标志

           }

           else TWExit();//通讯失败

           break;

    case I2C_MT_SLA_ACK://主发机接收到从机的地址应答信号后发送命令

           if (Status == 1) {//本次中断应该接收TW_MT_SLA_ACK信号

             Status = 3;//Status下次应该收TW_MT_DATA_ACK

             I2C0->I2C_DAT = SubComm;//发送子机命令

             I2C0->I2C_CONCLR = (1 << STA) | (1 << SI) | (1 << AA);//清除中断标志

           }

           else TWExit();//通讯失败

           break;

    case I2C_MR_SLA_ACK://主收机接收到从机的地址应答信号

           if (SubCount && (Status == 2)) {//本次中断应该接收TW_MR_SLA_ACK信号

             Status = 4;//Status下次应该收TW_MR_DATA_ACK

             I2C0->I2C_CONCLR = (1 << STA) | (1 << SI);//清除中断标志,主机转入接收状态

             I2C0->I2C_CONSET = (1 << AA);

           }

           else TWExit();//通讯失败

           break;

    case I2C_MT_DATA_ACK:

           if ((Count < MainCount) && (Status == 3)) {//本次中断应该接收TW_MT_DATA_ACK信号

             I2C0->I2C_DAT = TxBuffer[Count ++];//发送子机数据

             I2C0->I2C_CONCLR = (1 << STA) | (1 << SI) | (1 << AA);//清除中断标志

           }

           else {

             if ((Count == MainCount) && (Status == 3) && (SubAddr & 1)) {//本次中断应该接收TW_MT_DATA_ACK信号

               TWREStart();//

             }

             else TWExit();//通讯失败

           }

           break;

//    case I2C_MT_DATA_NACK://数据发送结束

//         TWExit();//通讯失败

//           break;

    case I2C_MR_DATA_ACK:

           if ((Count < SubCount) && (Status == 4)) {

             RxBuffer[Count ++] = I2C0->I2C_DAT;//接收子机数据

             if (Count < SubCount) {

               I2C0->I2C_CONCLR = (1 << STA) | (1 << SI);//主机转入接收状态

               I2C0->I2C_CONSET = (1 << AA);//

             }

             else {

               I2C0->I2C_CONCLR = (1 << STA) | (1 << SI) | (1 << AA);//清除中断标志,主机转入接收状态

               Status = 6;//下次进入I2C_MR_DATA_NACK,接收数据准备完成

             }

           }

           else TWExit();//通讯失败

           break;

    case I2C_MR_DATA_NACK://数据接收结束

           if ((Count == SubCount) && (Status == 6)) {

             SetDataBuff();//取出接收字节

             TWStop();//通讯成功

           }

           else TWExit();//通讯失败

           break;

    default:

           TWExit();//通讯失败

  }

}

出0入0汤圆

发表于 2006-12-31 16:06:58 | 显示全部楼层
有中断处理的写法吗?

出0入0汤圆

 楼主| 发表于 2006-12-31 16:21:39 | 显示全部楼层
这就是个主机中断处理函数.



extern "C" void IRQ_I2C0 (void) __irq

{

  Twi.Exec();//TWI的内联函数

  VIC->VectAddr = 0x00;                /* 通知VIC中断处理结束                                                        */

}



这是由于C++的中断服务程序isr()必须是1个标准的普通函数.

它不允许类中的成员函数为isr().



故我将其嵌入到isr()中并声明:



class TwiObj {

public:

  __inline void Exec(void);

//.........................

};



故这是1个C++在MCU中的1个实际应用,这个程序源码是我在做WINAVR菜鸟时

用GCC C++编写的,所以类名为Twi而不是I2C.



WINAVR的源码我也在网上发过...



出0入0汤圆

发表于 2007-1-7 21:10:21 | 显示全部楼层
倒塌性的回帖

出0入0汤圆

发表于 2007-8-17 23:12:20 | 显示全部楼层
顶你!

出0入0汤圆

发表于 2007-12-25 13:19:31 | 显示全部楼层
能详细说下AVR做TWI的从机的方法吗?
能简单说过程吗?  谢谢~

出0入0汤圆

发表于 2011-5-8 11:13:00 | 显示全部楼层
收藏
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-6 12:33

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表