瑞萨RL78 的CAN设置
- CAN 设置 --- MCU原理框图
- CAN0EN : 控制CAN的输入时钟/控制CAN的唤醒中断
- CAN0MCKE: Enables CAN X1 clock (fx) supply.
MCU
- CAN 设置 --- CAN channel number 0
发送缓冲区 4个
独立buffer : 4个Buffer 只能作为发送Buffer
---------发送buffer :4 buffer (每个channel 4个buffer)
共享buffer :16 buffer 可作为与以下功能共享
--------接收buffer :0~16buffer
--------接收FIFO buffer;2个FIFO ( 每个FIFO最多可分配到16个buffer)
--------发送/接收 FIFO buffer0:每个channel有一个FIFO( 每个FIFO最多可分配到16个buffer)
发送/接收 FIFO作为 发送FIFO时候,使用的是共享buffer,然后使用独立发送Buffe链接
- CAN 设置 --- MCU引脚设置
当GPIO作为CAN功能时候,需要设置为高电平,否者无法通讯
- CAN 设置 --- CAN时钟/CAN唤醒使能
void R_CAN_Create(void)
{
PER2 |= 0x01; // Enable the CAN module. CAN0EN = 1;
}
- CAN 设置 --- CAN初始化 流程 R_CAN_Init()
- CAN设置 --- CAN驱动初始化
-
void CanDriver_Init(void) { Can_RtnType retval; R_CAN_Create(); /* CAN0EN = 1 */ /* CAN Initialize */ retval = CAN_RTN_RAM_INIT; while (retval != CAN_RTN_OK) { retval = R_CAN_Init(); } /* Set global operating mode */ retval = CAN_RTN_MODE_WAIT; while (retval == CAN_RTN_MODE_WAIT) { retval = R_CAN_GlobalStart(); } /* CH0 -> Channel communication mode */ retval = CAN_RTN_MODE_WAIT; while (retval == CAN_RTN_MODE_WAIT) { retval = R_CAN_ChStart(CAN_CH0); } CanDriver_ClearFlag(); }
接收规则
-
The number of receive rules for the entire CAN module is 16 in total.
- Settings of IDE/RTR/ID
- Setting of messages target for receive rules
- Settings to mask IDE/RTR/ID
- Setting of values to be compared with DLC values
- Setting of receive rule label
- Setting of buffers to store messages
-
IDL和IDH 请查阅寄存器 GAFLIDLj, GAFLIDHj,当帧小于 0x7FF 默认为标准帧 ,不做说明
-
IDL_MASK和IDH_MASK,掩码,1表示有效,0 表示无效。请查看 GAFLMLj,GAFLMHj,不做说明
-
Store 查看寄存器 GAFLPL,将对应的数据存储到对应的FIFO 和buffer 中
-
data Filter查看寄存器 GAFLPH
const uint16_t g_rxrule_table[CAN_RX_RULE_NUM][6] = {
/*IDL , IDH , IDL_MASK , IDH_MASK , Store , data filter */
{ 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0001U, 0x0000U },
{ 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0001U, 0x0000U },
{ 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0001U, 0x0000U },
{ 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0001U, 0x0000U }
};
/* ---- Copy Rx rule one by one ---- */
p_RxRuleSfr = (volatile __near can_rxrule_sfr_t *)&GAFLIDL0;
for (rxrule_idx = 0U; rxrule_idx < CAN_RX_RULE_NUM; rxrule_idx++)
{
/* Set a single Rx rule */
p_RxRuleSfr->IDL = g_rxrule_table[rxrule_idx][0];
p_RxRuleSfr->IDH = g_rxrule_table[rxrule_idx][1];
p_RxRuleSfr->ML = g_rxrule_table[rxrule_idx][2];
p_RxRuleSfr->MH = g_rxrule_table[rxrule_idx][3];
p_RxRuleSfr->PL = g_rxrule_table[rxrule_idx][4];
p_RxRuleSfr->PH = g_rxrule_table[rxrule_idx][5];
/* Next sfr */
p_RxRuleSfr++;
}
GAFLRMDP :接受Buffer序号选择 ;表示接收Buffer的序号,若GAFLRMDP=0x03 表示 3号 buffer接收数据
GAFLFDP4 : 发送/接收FIFO 选择 ;当发送和接收 FIFO 作为 接收时候 使能
接受数据 -> 中断中接收到数据
-
/* ---- CAN frame ----- */ typedef struct { uint16_t IDL:16; /* ID Data (low) */ uint16_t IDH:13; /* ID Data (high) */ uint16_t THDSE :1; /* Transmit History Data Store Enable */ uint16_t RTR :1; /* RTR 0:Data 1:Remote */ uint16_t IDE :1; /* IDE 0:Standard 1:Extend */ uint16_t TS :16; /* Timestamp Data */ uint16_t LBL :12; /* Label Data */ uint16_t DLC :4; /* DLC Data */ uint8_t DB[8]; /* Data Byte */ } can_frame_t; #pragma interrupt can_INTCANGREC_interrupt(vect=INTCANGRFR) typedef void (*pvIntEventFunc)(void); // 定义函数指针 void can_INTCANGREC_interrupt(void) // 中断函数 { pvIntEventFunc prxCANCallback = CanSchm_CanBusRxMsgCallBack; prxCANCallback(); } void CanSchm_CanBusRxMsgCallBack(void) // 回调函数 { can_frame_t umrxFrame; uint32_t u8state; if((RFSTS0 & 0x0008) != 0) //RFIF = 1 FIF0接受到数据, RFIF标志位变为1 { RFSTS0 &= 0xFFF7; //clear RFIF u8state = R_CAN_ReadRxFIFO(0,&umrxFrame); // receive msg IDL IDH if((u8state == CAN_RTN_OK_WITH_LOST )||(u8state == CAN_RTN_OK ))//recive msg { g_umRxFrame = umrxFrame; g_umSchmState.RxSucCnt++; //success receive } } } void RxFrame(CanFrame_t *pCanRxFrame) // 接收到的参数拆包 { uint8_t i; pCanRxFrame -> u32Id = (uint32_t)(((uint32_t)(g_umRxFrame.IDH&0x7fff)<<16)|(g_umRxFrame.IDL&0xffff)); pCanRxFrame -> u8Ide = g_umRxFrame.IDE; pCanRxFrame -> u8Rtr = g_umRxFrame.RTR; pCanRxFrame -> u8Dlc = g_umRxFrame.DLC; for(i = 0; i < g_umRxFrame.DLC ;++i) { pCanRxFrame ->DataBuff[i]= g_umRxFrame.DB[i]; } }
发送数据 -> 将接收/发送FIFO 作为发送FIFO
-
-
注意点
-
Note 9: Set 0 to the TMIEp bit corresponding to the transmit buffer linked to the transmit FIFO buffer.,对应的TMIE位被设置为0,这发送缓冲区与发送FIFO缓冲区连接
-
Std_RtnType TxFrame(uint32_t u32MsgId, uint8_t *u8Data,uint8_t u8Len) { int i=0; if(u32MsgId <= 0x7FF) // stand ID { g_umTxFrame.IDE = 0; } else //extend ID { g_umTxFrame.IDE = 1; } g_umTxFrame.IDL = u32MsgId&0xFFFF; g_umTxFrame.IDH = (uint16_t)((u32MsgId>>16)&0x7FFF); g_umTxFrame.RTR = 0; g_umTxFrame.DLC = u8Len; for(i=0; i<u8Len; i++) { g_umTxFrame.DB[i] = u8Data[i]; } if(CAN_RTN_OK == R_CAN_TrmByTRFIFO0_CH0((const can_frame_t *)&g_umTxFrame))//send message { g_umSchmState.TxSucCnt++; // send successful return STD_E_OK; } return STD_E_NOK; }