打印
[应用相关]

Renesas瑞萨A4M2和STM32 CAN通信

[复制链接]
489|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
wakayi|  楼主 | 2023-5-29 19:31 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
刚好拿到一块瑞萨开发板,捣鼓玩下CAN,顺便试下固件升级。

A4M2 工程创建
详细可以参考,我之前写的文章 Renesa 瑞萨 A4M2 移植文件系统FAT32

CAN0 配置信息,使能FIFO,接收标准帧 ID为0x50,数据帧。


代码

void can_Init(void)
{
    fsp_err_t err = R_CAN_Open(&g_can0_ctrl, &g_can0_cfg);
}

/* CAN 中断回调函数 */
void can_callback(can_callback_args_t * p_args)
{
    switch (p_args->event)
    {
        case CAN_EVENT_RX_COMPLETE: //接收完成中断
        {
            can_rx_complete_flag = true;    //can接收到数据

            /* 读取接收帧 */
            memcpy(&can_rx_frame, &(p_args->frame), sizeof(can_frame_t));

            break;
        }
        case CAN_EVENT_TX_COMPLETE: //传输完成中断
        {
            can_tx_complete_flag = true;    //can数据发送完成
            break;
        }
        case CAN_EVENT_ERR_BUS_OFF:          /* Bus error event. (bus off) */
        case CAN_EVENT_ERR_PASSIVE:          /* Bus error event. (error passive) */
        case CAN_EVENT_ERR_WARNING:          /* Bus error event. (error warning) */
        case CAN_EVENT_BUS_RECOVERY:         /* Bus error event. (bus recovery) */
        case CAN_EVENT_MAILBOX_MESSAGE_LOST: /* Overwrite/overrun error */
        {
            can_err_status_flag = true;     //设置标志位

            /* 获取错误状态 */
            can_err_status = (can_error_t) p_args->error;

            break;
        }
        default:
        {
            break;
        }
    }
}




发送数据

can_tx_frame.id               = 0x48;//发送ID
can_tx_frame.type             = CAN_FRAME_TYPE_DATA;
can_tx_frame.data_length_code = 8;  //一次最多发送8个字节
memcpy((uint8_t*)&can_tx_frame.data[0], (uint8_t*)"########", 8);
err = R_CAN_Write(&g_can0_ctrl, CAN_MAILBOX_NUMBER_0, &can_tx_frame);
/* Error trap */
if (FSP_SUCCESS != err)
{
                CAN_MSG_PRINTF("CAN Write API FAILED");
                //while(1);
}
/* 等待传输完成 */
while ((true != can_tx_complete_flag) && (--time_out));
can_tx_complete_flag = false;

//typedef struct st_can_frame
//{
//    uint32_t         id;                           ///< CAN ID.
//    can_id_mode_t    id_mode;                      ///< Standard or Extended ID (IDE).
//    can_frame_type_t type;                         ///< Frame type (RTR).
//    uint8_t          data_length_code;             ///< CAN Data Length Code (DLC).
//    uint32_t         options;                      ///< Implementation-specific options.
//    uint8_t          data[CAN_DATA_BUFFER_LENGTH]; ///< CAN data.
//} can_frame_t;

//接收数据
while (false == can_rx_complete_flag);
can_rx_complete_flag = false;
printf("%s",can_rx_frame.data)



STM32 CAN工程
CAN外设初始化

#define TX_CAN_UPDATE 0x50
#define RX_CAN_UPDATE 0x48

u8 CAN1_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode)
{

          GPIO_InitTypeDef GPIO_InitStructure;
          CAN_InitTypeDef        CAN_InitStructure;
          CAN_FilterInitTypeDef  CAN_FilterInitStructure;
           NVIC_InitTypeDef  NVIC_InitStructure;
          RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//使能PORTA时钟                                                                                                                    

          RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);//使能CAN1时钟       
       
    //初始化GPIO
          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11| GPIO_Pin_12;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
    GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化PA11,PA12
       
          //引脚复用映射配置
          GPIO_PinAFConfig(GPIOA,GPIO_PinSource11,GPIO_AF_CAN1); //GPIOA11复用为CAN1
          GPIO_PinAFConfig(GPIOA,GPIO_PinSource12,GPIO_AF_CAN1); //GPIOA12复用为CAN1
          
          //CAN单元设置
           CAN_InitStructure.CAN_TTCM=DISABLE;        //非时间触发通信模式   
          CAN_InitStructure.CAN_ABOM=DISABLE;        //软件自动离线管理          
          CAN_InitStructure.CAN_AWUM=DISABLE;//睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)
          CAN_InitStructure.CAN_NART=ENABLE;        //禁止报文自动传送
          CAN_InitStructure.CAN_RFLM=DISABLE;        //报文不锁定,新的覆盖旧的  
          CAN_InitStructure.CAN_TXFP=DISABLE;        //优先级由报文标识符决定
          CAN_InitStructure.CAN_Mode= mode;         //模式设置
          CAN_InitStructure.CAN_SJW=tsjw;        //重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1tq~CAN_SJW_4tq
          CAN_InitStructure.CAN_BS1=tbs1; //Tbs1范围CAN_BS1_1tq ~CAN_BS1_16tq
          CAN_InitStructure.CAN_BS2=tbs2;//Tbs2范围CAN_BS2_1tq ~        CAN_BS2_8tq
          CAN_InitStructure.CAN_Prescaler=brp;  //分频系数(Fdiv)为brp+1       
          CAN_Init(CAN1, &CAN_InitStructure);   // 初始化CAN1

                //配置过滤器
          CAN_FilterInitStructure.CAN_FilterNumber=0;          //过滤器0

         u32 ID1 = RX_CAN_UPDATE;
         u32 ID2 = TX_CAN_UPDATE;

    CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdList;
    CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
    ID1 %= (1 << 11);
    ID2%= (1 << 11);
    //标准帧的帧ID长度是11位,帧ID的范围是000-7FF。
    //扩展帧的帧ID长度是29位,帧ID的范围是0000 0000-1FFF FFFF
    CAN_FilterInitStructure.CAN_FilterIdHigh = ID1  << 5;
    CAN_FilterInitStructure.CAN_FilterIdLow = CAN_ID_STD | CAN_RTR_DATA;
    CAN_FilterInitStructure.CAN_FilterMaskIdHigh = ID2 << 5;
    CAN_FilterInitStructure.CAN_FilterMaskIdLow = CAN_ID_STD | CAN_RTR_DATA;
    CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_FIFO0;
    CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
    CAN_FilterInit(&CAN_FilterInitStructure);
               

         CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);//FIFO0消息挂号中断允许.                    

          NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;
          NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;     // 主优先级为1
          NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;            // 次优先级为0
          NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
          NVIC_Init(&NVIC_InitStructure);
        return 0;
}   

void CAN1_RX0_IRQHandler(void)
{
        u8 i =0;
        CanRxMsg msg;
        CAN_Receive(CAN1, CAN_FIFO0, &msg);

        if(msg.IDE == CAN_ID_STD && msg.StdId == RX_CAN_UPDATE)
        {
                for(i=0;i<msg.DLC;i++){
                        Rx_Buffer = msg.Data;
                }
        }



以上配置只会收到数据帧的ID为0x50和0x48,其他都会被过滤掉。
关于这部分,可以看我之前写 STM32 CAN通信理解(是半双工还是全双工?)

开发版间CAN通信发送和接收都正常。


OTA也正常。

使用CAN通信,主要是想为固件升级教程,使用CAN做通信升级做些准备。后面有空持续更新这个系列教程 MCU固件升级系列1(STM32)

————————————————
版权声明:本文为CSDN博主「小昭dedug」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_43746325/article/details/130463682

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

85

主题

4084

帖子

1

粉丝