本帖最后由 raoxianbin 于 2013-12-15 14:34 编辑
https://bbs.21ic.com/icview-36610-1-1.html
背景:在ti的测试例程中,采用查询方式发送消息,一次将所有的TRS位置1,采用中断方式接收发送的数据。(所有邮箱中断使能,中断等级0)。主函数中
for(;;){
ECannaRegs.CANTRS.all = 0x0000FFFF; //0——15信箱全部发送
while(ECanaRegs.CANTA.all != 0x0000FFFF);//等待所有消息发送完毕
ECanaRegs.CANTA.all = 0x0000FFFF;//清发送响应位
}
中断程序中:
interrupt void ECAN0INTA_ISR(void) // eCAN-A
{
Uint16 j;
for(j = 16; j < 32; j++){
mailbox_read(j);
mailbox_check(TestMbox1,TestMbox2,TestMbox3);
}
EINT;
}
void mailbox_read(int16 MBXnbr)
{
volatile struct MBOX *Mailbox;
Mailbox = &ECanaMboxes.MBOX0 + MBXnbr;
TestMbox1 = Mailbox->MDRL.all; // = 0x9555AAAn (n is the MBX number)
TestMbox2 = Mailbox->MDRH.all; // = 0x89ABCDEF (a constant)
TestMbox3 = Mailbox->MID.all;// = 0x9555AAAn (n is the MBX number)
}
我的疑问:手册上明确说明,一个接收邮箱接收到一条消息或者一个发送邮箱成功发送一条消息将产生一个中断,也就是说任何发送和接收完成都会产生一个中断。为便于分析,从第1个消息发送完成开始考虑:
问题1:第1个消息发送完之后,将会产生一个中断,这时接收有可能还没完成,就不应该在中断程序里读接收邮箱的数据寄存器。更不要说一下子读16个接收邮箱的数据(后面的15个消息都还没开始发呢)。
问题2:在此后的中断中,应该需要判断是发送中断还是接收中断。如果不判断,怎么样知道发生的是接收中断还是发送中断。
很奇怪的是,这样的程序没有问题。在第一次发生中断后读出的16个数据全都正确!
对于这个问题,还有一个疑问
void InitECan(void)
{
struct ECAN_REGS ECanaShadow;
DINT;
EALLOW;//asm(" EALLOW");
GpioMuxRegs.GPFMUX.bit.CANTXA_GPIOF6 = 1;//选择相应的功能位
GpioMuxRegs.GPFMUX.bit.CANRXA_GPIOF7 = 1;
ECanaShadow.CANTIOC.all = ECanaRegs.CANTIOC.all;
ECanaShadow.CANTIOC.bit.TXFUNC = 1;//设置为can发送操作
ECanaRegs.CANTIOC.all = ECanaShadow.CANTIOC.all;
ECanaShadow.CANRIOC.all = ECanaRegs.CANRIOC.all;
ECanaShadow.CANRIOC.bit.RXFUNC = 1;//接受操作
ECanaRegs.CANRIOC.all = ECanaShadow.CANRIOC.all;
ECanaShadow.CANMC.all = ECanaRegs.CANMC.all;//can主控寄存器
ECanaShadow.CANMC.bit.SCB = 1; //=1,ECAN模式;=0正常模式
ECanaRegs.CANMC.all = ECanaShadow.CANMC.all;
/* Initialize all bits of 'Master Control Field' to zero */
ECanaMboxes.MBOX0.MSGCTRL.all = 0x00000000;//对控制寄存器进行初始化
ECanaMboxes.MBOX1.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX2.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX3.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX4.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX5.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX6.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX7.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX8.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX9.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX10.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX11.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX12.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX13.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX14.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX15.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX16.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX17.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX18.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX19.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX20.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX21.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX22.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX23.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX24.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX25.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX26.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX27.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX28.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX29.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX30.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX31.MSGCTRL.all = 0x00000000;
// TAn, RMPn, GIFn bits are all zero upon reset and are cleared again
// as a matter of precaution.
/* Clear all TAn bits ,发送响应寄存器,清除*/
ECanaRegs.CANTA.all = 0xFFFFFFFF;
/* Clear all RMPn bits,接收消息挂起寄存器 */
ECanaRegs.CANRMP.all = 0xFFFFFFFF;
/* Clear all interrupt flag bits,全局中断标志寄存器0,1 */
ECanaRegs.CANGIF0.all = 0xFFFFFFFF;//清除所有的中断标志位
ECanaRegs.CANGIF1.all = 0xFFFFFFFF;
/* Configure bit timing parameters,NMC=主控寄存器,CCR=改变配置请求 */
ECanaShadow.CANMC.all = ECanaRegs.CANMC.all;
ECanaShadow.CANMC.bit.CCR = 1 ; // Set CCR = 1
ECanaRegs.CANMC.all = ECanaShadow.CANMC.all;
ECanaShadow.CANES.all = ECanaRegs.CANES.all;
// Wait until the CPU has been granted permission to change the configuration registers
CAN_Loop_Num=0;
do
{
ECanaShadow.CANES.all = ECanaRegs.CANES.all;
CAN_Loop_Num++;
}
while((ECanaShadow.CANES.bit.CCE != 1 )&&(CAN_Loop_Num<20)); // 与CCR呼应,必须等CCE,Wait for CCE bit to be set..
ECanaShadow.CANBTC.all = 0; //位时序配置寄存器 赋初值
ECanaShadow.CANBTC.bit.BRPREG = 39; //0.25 Mbps @ 120 MHz SYSCLKOUT,通信波特率预设置 通信频率为0.25MHZ
ECanaShadow.CANBTC.bit.TSEG2REG = 3; //设置波特率,120MHz
ECanaShadow.CANBTC.bit.TSEG1REG = 6; //Baud rate=SYSCLKOUT/BRP*Bit_time
ECanaShadow.CANBTC.bit.SAM = 1; //Bit_time=(TSEG1reg+1)+(TSEG2reg+1)+1,SAM=1,CAN模块采样三次,BRP>4
ECanaRegs.CANBTC.all = ECanaShadow.CANBTC.all; //TSEG1(1~16)>=TSEG2;BRP=(BRPreg+1):1~256
ECanaShadow.CANMC.all = ECanaRegs.CANMC.all;
ECanaShadow.CANMC.bit.CCR = 0 ; // Set CCR = 0,配置波特率完成
ECanaRegs.CANMC.all = ECanaShadow.CANMC.all;
ECanaShadow.CANES.all = ECanaRegs.CANES.all;
// Wait until the CPU no longer has permission to change the configuration registers
CAN_Loop_Num=0;
do
{
ECanaShadow.CANES.all = ECanaRegs.CANES.all;
CAN_Loop_Num++;
}
while((ECanaShadow.CANES.bit.CCE != 0 )&&(CAN_Loop_Num<20)); // Wait for CCE bit to be cleared..
/* Disable all Mailboxes */
// Since this write is to the entire register (instead of a bit
// field) a shadow register is not required.
ECanaRegs.CANME.all = 0; // Required before writing the MSGIDs,相关邮箱被屏蔽
EDIS;
EINT;
}
// This function reads out the contents of the indicated
// by the Mailbox number (MBXnbr).
void mailbox_read(int16 MBXnbr)
{
volatile struct MBOX *Mailbox;
Mailbox = &ECanaMboxes.MBOX16 + MBXnbr;//也可以通过做逻辑或运算,实现加上相应的偏移地址
TestMbox1 = Mailbox->MDL.all; // = 0x9555AAAn (n is the MBX number)
TestMbox2 = Mailbox->MDH.all; // = 0x89ABCDEF (a constant)
TestMbox3 = Mailbox->MSGID.all;// = 0x9555AAAn (n is the MBX number)
} // MSGID of a rcv MBX is transmitted as the MDL data.
void mailbox_check(int32 T1, int32 T2, int32 T3)
{
if((T1 != T3) || ( T2 != 0x89ABCDEF))
{
ErrorCount++;
}
}
interrupt void ECAN0_ISR(void) // eCAN-A
{
DINT;
PieCtrl.PIEACK.bit.ACK9 = 1;
for(Ecan_num=0; Ecan_num<16; Ecan_num++) // Read & check 16 mailboxes
{
mailbox_read(Ecan_num); // This func reads the indicated mailbox data
RX_eCAN_buffer[Ecan_num]=TestMbox1;
RX_eCAN_buffer[Ecan_num+1]=TestMbox2;
mailbox_check(TestMbox1,TestMbox2,TestMbox3); // Checks the received data
}
ECanaRegs.CANRMP.bit.RMP16=1;//
EINT;
//发送
ECanaMboxes.MBOX15.MDL.all = TestMbox1;
ECanaMboxes.MBOX15.MDH.all = TestMbox2;
ECanaRegs.CANTRS.all = 0x0000FFFF; // Set TRS for all transmit mailboxes
CAN_Loop_Num=0;
while((ECanaRegs.CANTA.all != 0x0000FFFF )&&(CAN_Loop_Num<20))
{
CAN_Loop_Num++;
} // Wait for all TAn bits to be set..
ECanaRegs.CANTA.all = 0x0000FFFF; // Clear all TAn
EINT;
}
对于这个中断中的数据读取,也即中断子函数中的mailbox_read() 不是说在读数据之前必须把标志位RMP进行复位吗,不复位能读取数据吗,麻烦各位解答一下。。
|