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