⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2c.cpp

📁 LPCARM之I2C中断读写CAT1025C++程序祥解 LPCARM之I2C中断读写CAT1025C++程序祥解
💻 CPP
字号:
#include "LPC213XDEF.h"
#include "main.h"
#include "i2c.h"

extern "C" void IRQ_I2C0 (void) __irq;

//__inline
I2cObj::I2cObj(void)
{
  I2cInit();
}

void I2cObj::I2cInit(void)
{
  PINSEL->PIN_SEL0 |= (P0_2_SCL0 << P0_2_PINSEL) | (P0_3_SDA0 << P0_3_PINSEL);
  I2C0->I2C_SCLH = (Fpclk / Fi2c + 1) /2;
  I2C0->I2C_SCLL = (Fpclk / Fi2c) /2;
  I2C0->I2C_CONCLR = (1 << STA) | (1 << SI);
  I2C0->I2C_CONSET = (1 << I2EN);
  for (int i = 0; i < 16; i ++) {
    TxBuffer[i] = 0;
	RxBuffer[i] = 0;
  }
  Stop();//pwy
  state = I2C_BUS_ERROR;//通讯失败
  VIC->VectAddrs[1] = (unsigned int)IRQ_I2C0;
  VIC->VectCntls[1]   = VICIntSel_Enable//使能IRQ中断
                      | VICIntSel_I2C0;//获取I2C0的IRQ级别
  VIC->IntEnable |= (1 << VICIntSel_I2C0);
}

void I2cObj::Start(void)
{
  Busy = true;
  state = I2C_START;//主机准备发送启始位
  Count = 0;//发送数据个数
  I2C0->I2C_CONSET = (1 << I2EN) | (1 << STA);
}

void I2cObj::REStart(void)
{
  Busy = true;
  state = I2C_REP_START;//主机准备发送启始位
  Count = 0;//接收数据个数
  I2C0->I2C_CONCLR = (1 << STA) | (1 << SI) | (1 << AA);
  I2C0->I2C_CONSET = (1 << I2EN) | (1 << STA);
}
//__inline
void I2cObj::Stop(void)
{
  Busy = false;
  state = I2C_BUS_OK;//通讯成功
  I2C0->I2C_CONSET = (1 << I2EN) | (1 << STO);
  I2C0->I2C_CONCLR = (1 << STA) | (1 << SI) | (1 << AA);
}

void I2cObj::Exit(void)
{
  Busy = false;
  state = I2C_BUS_ERROR;//通讯失败
  I2C0->I2C_CONSET = (1 << I2EN) | (1 << STO);
  I2C0->I2C_CONCLR = (1 << STA) | (1 << SI) | (1 << AA);
}

void I2cObj::Exec(void)
{
  switch(I2C0->I2C_STAT & 0xf8) {
    case I2C_START://主机收到自己发送的开始信号
	       if (state == I2C_START) {//本次中断应该接收TW_START信号//pwy
	         I2C0->I2C_DAT = SubAddr & 0xfe;//发送子机地址(写)
			 state = I2C_MT_SLA_ACK;//下次主机接收从机的地址应答信号
             I2C0->I2C_CONCLR = (1 << STA) | (1 << SI) | (1 << AA);//清除中断标志
		   }
		   else Exit();//通讯失败
	       break;
	case I2C_REP_START://主机收到自己发送的重新开始信号
	       if ((state == I2C_REP_START) && (SubAddr & 0xfe)) {//本次中断应该接收TW_START信号//pwy
	         I2C0->I2C_DAT = SubAddr;//发送子机地址(读)
		     state = I2C_MR_SLA_ACK;
             I2C0->I2C_CONCLR = (1 << STA) | (1 << SI) | (1 << AA);//清除中断标志
		   }
		   else Exit();//通讯失败
	       break;
	case I2C_MT_SLA_ACK://主发机接收到从机的地址应答信号后发送命令
	       if (state == I2C_MT_SLA_ACK) {//本次中断应该接收TW_MT_SLA_ACK信号
		     state = I2C_MT_DATA_ACK;//下次主机接收从机的数据应答信号
             I2C0->I2C_DAT = SubComm;//发送子机命令
             I2C0->I2C_CONCLR = (1 << STA) | (1 << SI) | (1 << AA);//清除中断标志
		   }
		   else Exit();//通讯失败
	       break;
	case I2C_MR_SLA_ACK://主收机接收到从机的地址应答信号
	       if ((state == I2C_MR_SLA_ACK) && SubCount) {//本次中断应该接收TW_MR_SLA_ACK信号
		     state = I2C_MR_DATA_ACK;
             I2C0->I2C_CONCLR = (1 << STA) | (1 << SI);//清除中断标志,主机转入接收状态
			 I2C0->I2C_CONSET = (1 << AA);
		   }
		   else Exit();//通讯失败
		   break;
	case I2C_MT_DATA_ACK://主收机接收到从机的数据应答信号
	       if ((state == I2C_MT_DATA_ACK) && (Count < MainCount)) {//本次中断应该接收TW_MT_DATA_ACK信号
	         I2C0->I2C_DAT = TxBuffer[Count ++];//发送子机数据
             I2C0->I2C_CONCLR = (1 << STA) | (1 << SI) | (1 << AA);//清除中断标志
		   }
		   else {
	         if ((Count == MainCount) && (state == I2C_MT_DATA_ACK)) {//本次中断应该接收TW_MT_DATA_ACK信号
			   if (SubAddr & 1) {
		         REStart();//
			   }
			   else Stop();//通讯成功
			 }
             else Exit();//通讯失败
		   }
		   break;
	case I2C_MR_DATA_ACK:
	       if ((state == I2C_MR_DATA_ACK) && (Count < SubCount)) {
	         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);//清除中断标志,主机转入接收状态
			   state = I2C_MR_DATA_NACK;//下次进入I2C_MR_DATA_NACK,接收数据准备完成
			 }
		   }
		   else Exit();//通讯失败
		   break;
	case I2C_MR_DATA_NACK://数据接收结束
	       if ((state == I2C_MR_DATA_NACK) && (Count == SubCount)) {
		     Stop();//通讯成功
		   }
		   else Exit();//通讯失败
		   break;
//	case I2C_MT_DATA_NACK://数据发送结束
//         Exit();//通讯失败
//		   break;
	default:
		   Exit();//通讯失败
  }
}

unsigned char I2cObj::ReadByte(unsigned char Address, unsigned char & Data)
{
  SubAddr = 0xa1;//CAT1025地址(读)
  MainCount = 0;//发送0个数据(只读)
//本程序为通用I2C,故发送器件后一般为命令,对EEPROM来说,命令实际是EEPROM地址
  SubComm = Address;//读出地址
  SubCount = 1;//接收1个数据
  Start();
  while (Busy);
  Data = RxBuffer[0];
  return state;
}

unsigned char I2cObj::ReadBlock(unsigned char Address, unsigned int length)
{
  SubAddr = 0xa1;//CAT1025地址(读)
  MainCount = 0;//发送0个数据(只读)
//本程序为通用I2C,故发送器件后一般为命令,对EEPROM来说,命令实际是EEPROM地址
  SubComm = Address & 0xf0;//读出页地址
  SubCount = length;//接收16个数据
  Start();
  while (Busy);
  return state;
}

unsigned char I2cObj::WriteByte(unsigned char Address, unsigned char Data)
{
  SubAddr = 0xa0;//CAT1025地址(写)
  MainCount = 1;//发送1个数据
//本程序为通用I2C,故发送器件后一般为命令,对EEPROM来说,命令实际是EEPROM地址
  SubComm = Address;//写入地址
  TxBuffer[0] = Data;//写入数据
  SubCount = 0;//接收0个数据
  Start();
  while (Busy);
  for(int i = 0;i < 200000; i ++) __nop();//延时
  return state;//(读出数据在RxBuffer[0]~RxBuffer[15])
}

unsigned char I2cObj::WriteBlock(unsigned char Address, unsigned int length)
{
  SubAddr = 0xa0;//CAT1025地址(写)
  MainCount = length;//发送16个数据(数据在TxBuffer[0]~TxBuffer[15])
//本程序为通用I2C,故发送器件后一般为命令,对EEPROM来说,命令实际是EEPROM地址
  SubComm = Address;//写入地址
  SubCount = 0;//接收0个数据
  Start();
  while (Busy);
  for(int i = 0;i < 200000; i ++) __nop();//延时
  return state;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -