瑞萨单片机之CAN

瑞萨RL78 的CAN设置

  • CAN 设置 --- MCU原理框图
  1. CAN0EN :  控制CAN的输入时钟/控制CAN的唤醒中断
  2. 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.

  1. Settings of IDE/RTR/ID
  2. Setting of messages target for receive rules
  3. Settings to mask IDE/RTR/ID
  4. Setting of values to be compared with DLC values 
  5. Setting of receive rule label
  6. 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;
    }

     

  • 4
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值