LPC2294 CAN Module状态寄存器:
1、每个CAN控制器均带有两个在操作状态下(Normal Operation Mode)只读状态寄存器:CANGSR和CANSR;
2、CANGSR包含全局状态包括每个CAN控制器的发送(TBS、TCS、TS)、接收(RBS、RS)、接收过载(DOS)、错误(ES)及CAN-Bus状态(BS),另外有两个8Bits的Rx/Tx错误计数器;
CANSR中的RBS、DOS、RS、ES、BS位与CANGSR中的相同,由于每个CAN控制器带三个发送缓冲区,因此CANSR对每个缓存的状态作出更为细致的反馈:
TBS(发送缓冲区状态)被肢解成三:TBS1,TBS2,TBS3
TCS(发送完成)被肢解成三:TCS1,TCS2,TCS3
TS(正在发送)被肢解成三:TS1,TS2,TS3
2、CANGSR与CANSR中寄存器位之间的关系:
TBS = TBS1 & TBS2 & TBS3 (与操作)
TCS = TCS1 & TCS2 & TCS3 (与操作)
TS = TS1 | TS2 | TS3 (或操作)
3、发送函数中一般应对CANSR查询以决定向某一个空闲的缓冲区写入发送数据;接收函数若采用中断方式应在服务例程末对CANCMR进行操作,以释放接收缓冲区单元同时RBS位清零;
4、发送、接收例程(本例程已通过测试可用):
/*
***************************************************************************************************
*** 函 数 名:CAN_PushMsg
*** 功能描述:CAN数据发送
*** 输入输出:
*** 创建日期:2007-5-7 2:18 by:CANopen
*** 修改日期:2007-5-7 2:18 by:
***************************************************************************************************
*/
void CAN_PushMsg(int8u can_port,CAN_MSG* pTxBuf)
{
int32u* pAddr=0;
int8u tBuf=0;
if(can_port < 1 || can_port > 2) return;
switch(can_port)
{
case 1:
if(CAN1SR & (__1 << 2))
{
pAddr = (int32u *) &(CAN1TFI1);
tBuf = 1;
}
else // tBuf 1 不可用
{
if(CAN1SR & (__1 << 10))
{
pAddr = (int32u *) &(CAN1TFI2);
tBuf = 2;
}
else // tBuf 2 不可用
{
if(CAN1SR & (__1 << 18))
{
pAddr = (int32u *) &(CAN1TFI3);
tBuf = 3;
}
else // tBuf 3 不可用
return; // 所有的tBuf都不可用,则返回
}
}
*pAddr = pTxBuf->Frame;
pAddr++;
*pAddr = pTxBuf->MsgID;
pAddr++;
*pAddr = pTxBuf->DatA;
pAddr++;
*pAddr = pTxBuf->DatB;
switch(tBuf)
{
case 1:
CAN1CMR = 0x21; // 选择tBuf1发送
break;
case 2:
CAN1CMR = 0x41; // 选择tBuf2发送
break;
case 3:
CAN1CMR = 0x81; // 选择tBuf3发送
break;
default :
break;
}
break;
case 2:
if(CAN2SR & (__1 << 2))
{
pAddr = (int32u *) &(CAN2TFI1);
tBuf = 1;
}
else
{
if(CAN2SR & (__1 << 10))
{
pAddr = (int32u *) &(CAN2TFI2);
tBuf = 2;
}
else
{
if(CAN2SR & (__1 << 18))
{
pAddr = (int32u *) &(CAN2TFI3);
tBuf = 3;
}
else
return;
}
}
*pAddr = pTxBuf->Frame; // 相应寄存器装入发送数据Msg
pAddr++;
*pAddr = pTxBuf->MsgID;
pAddr++;
*pAddr = pTxBuf->DatA;
pAddr++;
*pAddr = pTxBuf->DatB;
switch(tBuf) // 置位发送请求
{
case 1:
CAN2CMR = 0x21;
break;
case 2:
CAN2CMR = 0x41;
break;
case 3:
CAN2CMR = 0x81;
break;
default :
break;
}
break;
default :
break;
}
}
/*
***************************************************************************************************
*** 函 数 名:CAN2_Rx_ISR
*** 功能描述:CAN数据接收,中断服务例程,将接收数据装入数据队列,同时Led3闪烁
*** 输入输出:
*** 创建日期:2007-5-7 2:19 by:CANopen
*** 修改日期:2007-5-7 2:19 by:
***************************************************************************************************
*/
__irq void CAN2_Rx_ISR(void)
{
int32u *pAddr;
if(CAN2RFS & 0x00000400) // 查询BP位,1标识该数据为BypassMode下接收
{
pAddr = (int32u *) &(gCAN_RxQ[1][gRxQ_In[1]]);
*pAddr++ = CAN2RFS; // Frame
*pAddr++ = CAN2RID; // ID
*pAddr++ = CAN2RDA; // Data A
*pAddr++ = CAN2RDB; // Data B
gRxQ_In[1]++; // 数据队列指针调整
if (gRxQ_In[1] >= MAX_Q)
{
gRxQ_In[1] = 0;
}
}
CAN2CMR = 0x04; // 释放接收寄存器,同时RBS位清零
VICVectAddr = 0x00U; // acknowledge Interrupt
LedFlash(Led3);
}
5、CANGSR、CANSR寄存器截图:
<<-------CANGSR
<<---------CANSR(1)
<<--------CANSR(2)