📄 can.c
字号:
* Note: Care is not taken if buffer is full
********************************************************************/
void CANGetMessage(void);
/*********************************************************************
* Function: char CANPutMessage(void)
*
* PreCondition: <WIN2:WIN0> in the CANCON register has to set
* to reflect the desired TXB registers
*
* Input: None
*
* Output: 0 -> A new message has been put in the transmit queue
* 1 -> There was no messages in the TX buffer to send
*
* Side Effects: Will modify the TX buffer磗 Read pointer (TXRPtr)
*
* Overview: Checks if there is any messages to transmit and if so
* place it in the registers reflected by <WIN2:WIN0>
*
* Note: None
********************************************************************/
char CANPutMessage(void);
/*********************************************************************
* Function: char CANOpen(void)
*
* PreCondition: None
*
* Input: Values to be written into BRGCON1 -> BRGCON3
*
* Output: 0 -> Initialasation succeeded
*
* Side Effects: None
*
* Overview: Sets up the appropriate register for the device to act
* as a CAN node
*
* Note: Input values 0x03, 0xAA, 0x05 at Fosc = 16MHz works with
* the default firmware at nodeB on the CAN I/O expander board.
********************************************************************/
char CANOpen(unsigned char CONFIG1, unsigned char CONFIG2, unsigned char CONFIG3)
{
TRISB2 = 0;
TRISB3 = 1;
PIE3 = 0; //Disable all CAN interrupts
PIR3 = 0; //and clear all CAN interrupt flags
CANCON = (CONFIG_MODE & MODE_MASK) | (CANCON & 0x3F); //Set configuration mode//进入配制模式
while((CANSTAT & MODE_MASK) != (CONFIG_MODE & MODE_MASK)); //Wait until config mode is set
BRGCON1 = CONFIG1; //TQ=2*4/16=0.5us |___________ 一比特位____________________| sync=1TQ
BRGCON2 = CONFIG2; // |sync | propagation | phase1 | phase2|
BRGCON3 = CONFIG3; // Tbit=16*TQ=8us | 1TQ | 3TQ | 6TQ | 6TQ |=16TQ
//波特率=125k
//RXB0CON = 0x04; //Receive all valid messages receive buffer overflow 接收所有正确的消息并准许溢出到(buff0)->buffer1
RXB0CON = 0x24; //rxf1 接收标准格式的消息
//RXB1CON = 0x00; //writes to RXB1 接收缓冲1接收所有消息并用RXF0过滤
RXB1CON = 0x24; //rxf4 接收标准格式的消息
//Set the acceptance filters for all the filters
#ifdef ACCEPT_STANDARD_FILTER_0 //11BIT标准格式 ACCEPTANCE_FILTER_0= int 型
RXF0SIDL = (unsigned char)(ACCEPTANCE_FILTER_0 << 5);//EXIDEN=0 标准ID=BIT(2--0) EXIDEN=1 扩展ID(20-16) 只取低3位装入bit(7-5)
RXF0SIDH = (unsigned char)(ACCEPTANCE_FILTER_0 >> 3);//EXIDEN=0 标准ID=BIT(10-3) EXIDEN=1 扩展ID(28-21)
#else //29比特扩展格式
RXF0EIDL = (unsigned char)(ACCEPTANCE_FILTER_0 & 0xFF); //扩展ID(7-0)
RXF0EIDH = (unsigned char)((ACCEPTANCE_FILTER_0 >> 8) & 0xFF); //扩展ID(15-8)
RXF0SIDL = (unsigned char)((ACCEPTANCE_FILTER_0 >> 16) & 0x03) | (unsigned char)((ACCEPTANCE_FILTER_0 >> 13) & 0xE0) | 0x08;
RXF0SIDH = (unsigned char)((ACCEPTANCE_FILTER_0 >> 21) & 0xFF);
#endif
#ifdef ACCEPT_STANDARD_FILTER_1
RXF1SIDL = (unsigned char)(ACCEPTANCE_FILTER_1 << 5);
RXF1SIDH = (unsigned char)(ACCEPTANCE_FILTER_1 >> 3);
#else
RXF1EIDL = (unsigned char)(ACCEPTANCE_FILTER_1 & 0xFF);
RXF1EIDH = (unsigned char)((ACCEPTANCE_FILTER_1 >> 8) & 0xFF);
RXF1SIDL = (unsigned char)((ACCEPTANCE_FILTER_1 >> 16) & 0x03) | (unsigned char)((ACCEPTANCE_FILTER_1 >> 13) & 0xE0) | 0x08;
RXF1SIDH = (unsigned char)((ACCEPTANCE_FILTER_1 >> 21) & 0xFF);
#endif
#ifdef ACCEPT_STANDARD_FILTER_2
RXF2SIDL = (unsigned char)(ACCEPTANCE_FILTER_2 << 5);
RXF2SIDH = (unsigned char)(ACCEPTANCE_FILTER_2 >> 3);
#else
RXF2EIDL = (unsigned char)(ACCEPTANCE_FILTER_2 & 0xFF);
RXF2EIDH = (unsigned char)((ACCEPTANCE_FILTER_2 >> 8) & 0xFF);
RXF2SIDL = (unsigned char)((ACCEPTANCE_FILTER_2 >> 16) & 0x03) | (unsigned char)((ACCEPTANCE_FILTER_2 >> 13) & 0xE0) | 0x08;
RXF2SIDH = (unsigned char)((ACCEPTANCE_FILTER_2 >> 21) & 0xFF);
#endif
#ifdef ACCEPT_STANDARD_FILTER_3
RXF3SIDL = (unsigned char)(ACCEPTANCE_FILTER_3 << 5);
RXF3SIDH = (unsigned char)(ACCEPTANCE_FILTER_3 >> 3);
#else
RXF3EIDL = (unsigned char)(ACCEPTANCE_FILTER_3 & 0xFF);
RXF3EIDH = (unsigned char)((ACCEPTANCE_FILTER_3 >> 8) & 0xFF);
RXF3SIDL = (unsigned char)((ACCEPTANCE_FILTER_3 >> 16) & 0x03) | (unsigned char)((ACCEPTANCE_FILTER_3 >> 13) & 0xE0) | 0x08;
RXF3SIDH = (unsigned char)((ACCEPTANCE_FILTER_3 >> 21) & 0xFF);
#endif
#ifdef ACCEPT_STANDARD_FILTER_4
RXF4SIDL = (unsigned char)(ACCEPTANCE_FILTER_4 << 5);
RXF4SIDH = (unsigned char)(ACCEPTANCE_FILTER_4 >> 3);
#else
RXF4EIDL = (unsigned char)(ACCEPTANCE_FILTER_4 & 0xFF);
RXF4EIDH = (unsigned char)((ACCEPTANCE_FILTER_4 >> 8) & 0xFF);
RXF4SIDL = (unsigned char)((ACCEPTANCE_FILTER_4 >> 16) & 0x03) | (unsigned char)((ACCEPTANCE_FILTER_4 >> 13) & 0xE0) | 0x08;
RXF4SIDH = (unsigned char)((ACCEPTANCE_FILTER_4 >> 21) & 0xFF);
#endif
#ifdef ACCEPT_STANDARD_FILTER_5
RXF5SIDL = (unsigned char)(ACCEPTANCE_FILTER_5 << 5);
RXF5SIDH = (unsigned char)(ACCEPTANCE_FILTER_5 >> 3);
#else
RXF5EIDL = (unsigned char)(ACCEPTANCE_FILTER_5 & 0xFF);
RXF5EIDH = (unsigned char)((ACCEPTANCE_FILTER_5 >> 8) & 0xFF);
RXF5SIDL = (unsigned char)((ACCEPTANCE_FILTER_5 >> 16) & 0x03) | (unsigned char)((ACCEPTANCE_FILTER_4 >> 13) & 0xE0) | 0x08;
RXF5SIDH = (unsigned char)((ACCEPTANCE_FILTER_5 >> 21) & 0xFF);
#endif
//Set the acceptance masks
#ifdef MY_ADDRESS_IS_STANDARD //接收标准格式的掩码
RXM0SIDL = (unsigned char)(ACCEPTANCE_MASK_0_1 <<5); // 标准ID=BIT(2--0) 扩展ID(20-16)
RXM0SIDH = (unsigned char)((ACCEPTANCE_MASK_0_1 >>3) & 0xFF);
RXM1SIDL = (unsigned char)(ACCEPTANCE_MASK_2_5 <<5);
RXM1SIDH = (unsigned char)((ACCEPTANCE_MASK_2_5 >> 3) & 0xFF);
RXM0EIDL =0xff;
RXM0EIDH =0xff;
RXM1EIDL =0xff;
RXM1EIDH =0xff;
#else //接收扩展格式的掩码
RXM0EIDL = (unsigned char)(ACCEPTANCE_MASK_0_1 & 0xFF); //mark0 扩展ID(7--0)
RXM0EIDH = (unsigned char)((ACCEPTANCE_MASK_0_1 >> 8) & 0xFF);//mark0 扩展ID(15-8)
RXM0SIDL = (unsigned char)((ACCEPTANCE_MASK_0_1 >> 16) & 0x03) | (unsigned char)((ACCEPTANCE_MASK_0_1 >> 13) & 0xE0) | 0x08;//mark0 标准ID=BIT(2--0) 扩展ID(20-16)
RXM0SIDH = (unsigned char)((ACCEPTANCE_MASK_0_1 >> 21) & 0xFF); //mark0 标准ID=BIT(10--3) 扩展ID(28-21)
RXM1EIDL = (unsigned char)(ACCEPTANCE_MASK_2_5 & 0xFF); //mark1 扩展ID(7--0)
RXM1EIDH = (unsigned char)((ACCEPTANCE_MASK_2_5 >> 8) & 0xFF);//mark1 扩展ID(15-8)
RXM1SIDL = (unsigned char)((ACCEPTANCE_MASK_2_5 >> 16) & 0x03) | (unsigned char)((ACCEPTANCE_MASK_2_5 >> 13) & 0xE0) | 0x08;
RXM1SIDH = (unsigned char)((ACCEPTANCE_MASK_2_5 >> 21) & 0xFF); //mark1 标准ID=BIT(10--3) 扩展ID(28-21)
#endif
CIOCON = 0x20; //Drive TX pin Vdd when recessive, disable capture//使隐性时输出=vdd 接收禁止
#ifdef CAN_LOW_INT //设置can中断优先级
IPR3 = 0x00;
#else
IPR3 = 0xFF; //高优先级
#endif
#ifdef USE_LOOPBACK_MODE //设置工作模式和接收buf
CANCON = (LOOPBACK_MODE & MODE_MASK) | (CANCON & (MODE_MASK ^ 0xFF));//Set loopback mode for debug purposes only
while((CANSTAT & MODE_MASK) != (LOOPBACK_MODE & MODE_MASK)); //Wait until loopback mode is set
#else
CANCON = (NORMAL_MODE & MODE_MASK) | (CANCON & (MODE_MASK ^ 0xFF)); //Set normal mode
while((CANSTAT & MODE_MASK) != (NORMAL_MODE & MODE_MASK)); //Wait until normal mode is set
//CANCON=0x60;
//while(CANSTAT !=0x60);
#endif
PIE3 = CAN_INT_BITS & 0xE3; //Enable CAN interrupts except TX interrupts //始能can接收
PIR3 = 0x18; //Set TXB1 & TXB2 int flags //设置发送but1,2 为空的中断
//Send my address to notify our presence
#ifdef MY_ADDRESS_IS_STANDARD //标准格式 非中断方式发送数据
TXB0SIDL = (unsigned char)(MY_ADDRESS_IDENTIFIER << 5); //装载1d指示位
TXB0SIDH = (unsigned char)(MY_ADDRESS_IDENTIFIER >> 3); //Load address with MY_ADDRESS_IDENTIFIER standard identifier
TXB0DLC = 0x06;//0x00; //0 data bytes to send //数据长度=0
TXB0D0='C';
TXB0D1='A';
TXB0D2='N';
TXB0D3='2';
TXB0D4='.';
TXB0D5='0';
TXB0CON = 0x00; //Initiate transmission //发送
TXB0REQ = 1; //设置此bit后说明发送准备就绪如bus可用将发送高优先级的消息传送完成后设置TXBn(0)IF=1, TXB0REQ=0,
#else //扩展格式
TXB0EIDL = (unsigned char)(MY_ADDRESS_IDENTIFIER & 0xFF); //Load address with MY_ADDRESS_IDENTIFIER extended identifier
TXB0EIDH = (unsigned char)((MY_ADDRESS_IDENTIFIER >> 8) & 0xFF);
TXB0SIDL = (unsigned char)((MY_ADDRESS_IDENTIFIER >> 16) & 0x03) | (unsigned char)((ACCEPTANCE_FILTER_2 >> 13) & 0xE0) | 0x08;
TXB0SIDH = (unsigned char)((MY_ADDRESS_IDENTIFIER >> 21) & 0xFF);
TXB0DLC = 0x00; //0 data bytes to send
TXB0CON = 0x00; //Initiate transmission
TXB0REQ = 1; //TXB0CON。3
#endif
return 0;
}
/*********************************************************************
* Function: void CANISR(void)
*
* PreCondition: None
*
* Input: None
*
* Output: None
*
* Side Effects: Will modify the RX/TX interrupt flags
* and interrupt enable bits
*
* Overview: Checks if a CAN reception/transmission was complete
* and if so write/read to the CAN RX/TX FIFO buffers
*
* Note: This function is supposed to be called from the ISR
********************************************************************/
void CANISR(void)
{
unsigned char TempCANCON;
if(PIR3 & PIE3) // 有tx--rx中断请求 & tx-rx使能
{
TempCANCON = CANCON;
if(RXB0IF && RXB0IE) //接收buf0
{
RXB0IF = 0; //Clear interrupt flag
CANCON = CANCON & 0xF0 | RXB0Interrupt; //1100 RXbuf0->可访区
CANGetMessage(); //从寄存器读数据到缓存区
}
else if(RXB1IF && RXB1IE) //接收buf1
{
RXB1IF = 0; //Clear interrupt flag
CANCON = CANCON & 0xF0 | RXB1Interrupt; //1010 RXbuf1->可访区
CANGetMessage();
}
else if(TXB0IF && TXB0IE) //发送buf0 缓存有数据时,TXB0IE=1
{
CANCON = CANCON & 0xF0 | TXB0Interrupt; //1000 TXbuf0->可访区
if(CANPutMessage()) //缓存数据写寄存器
TXB0IE = 0; //写入不成功(无数据可写)禁中断
else
TXB0IF = 0; //写入成功
}
else if(TXB1IF && TXB1IE) //发送buf1
{
CANCON = CANCON & 0xF0 | TXB1Interrupt; //0100 TXbuf1->可访区
if(CANPutMessage())
TXB1IE = 0;
else
TXB1IF = 0;
}
else if(TXB2IF && TXB2IE) //发送buf2
{
CANCON = CANCON & 0xF0 | TXB2Interrupt; //0100 TXbuf2->可访区
if(CANPutMessage()) //if there wasn't any more messages to send
TXB2IE = 0; //disable interrupts for TXB2 and leave TXB2IF
else //still on so PutCAN() can reenable the interrupt and instantly vector to ISR
TXB2IF = 0; //message was sent, just clear the interrupt flag.
}
else if(ERRIF && ERRIE)
{
ERRIF = 0; //Clear interrupt flag
#ifdef CAN_ERROR_HANDLER_ENABLE
CANErrorHandler();
#endif
//No error handler implemented!!!
}
else if(WAKIF && WAKIE)
{
WAKIF = 0; //Clear interrupt flag
}
CANCON = TempCANCON;
}
}
/*********************************************************************
* Function: void CANGetMessage(void)
*
* PreCondition: <WIN2:WIN0> in the CANCON register has to set
* to reflect the desired RXB registers
* //通过 <WIN2:WIN0> 设置可访问的寄存器
* Input: None
*
* Output: None
*
* Side Effects: Will modify the RX FIFO Write pointer (RXWPtr)
*
* Overview: Gets the registers for a RXB and puts them in the
* CAN Receive buffer
*
* Note: Care is not taken if buffer is full
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -