打印
[应用相关]

STM32 CAN总线收发-中断方式接收

[复制链接]
1573|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
配置CAN
CAN的波特率最大为1Mbps。
波特率计算方法:时钟主频 / 分频 / (tq1 + tq2 + swj)
stm32f103的CAN的时钟主频是36M,分9频就是4M,在除以(5 + 2 + 1)得到500K的波特率。
注意:stm32cubemx生成的CAN代码是不带过滤器的,需要自己手动添加。




使用特权

评论回复
沙发
renzheshengui|  楼主 | 2021-8-4 15:28 | 只看该作者
代码修改
STM32CUBEMX生成的CAN配置代码是没有过滤器设置的,需要手动添加。

typedef struct
{
        uint32_t mailbox;
        CAN_TxHeaderTypeDef hdr;
        uint8_t payload[8];
}CAN_TxPacketTypeDef;

typedef struct
{
        CAN_RxHeaderTypeDef hdr;
        uint8_t payload[8];
}CAN_RxPacketTypeDef;



使用特权

评论回复
板凳
renzheshengui|  楼主 | 2021-8-4 15:28 | 只看该作者
/// CAN过滤器寄存器位宽类型定义
typedef union
{
    __IO uint32_t value;
    struct
    {
        uint8_t REV : 1;                        ///< [0]    :未使用
        uint8_t RTR : 1;                        ///< [1]    : RTR(数据帧或远程帧标志位)
        uint8_t IDE : 1;                        ///< [2]    : IDE(标准帧或扩展帧标志位)
        uint32_t EXID : 18;                        ///< [21:3] : 存放扩展帧ID
        uint16_t STID : 11;                        ///< [31:22]: 存放标准帧ID
    } Sub;
} CAN_FilterRegTypeDef;


#define CAN_BASE_ID 0                                                ///< CAN标准ID,最大11位,也就是0x7FF

#define CAN_FILTER_MODE_MASK_ENABLE 1                ///< CAN过滤器模式选择:=0:列表模式  =1:屏蔽模式

#define CAN_ID_TYPE_STD_ENABLE      1       ///< CAN过滤ID类型选择:=1:标准ID,=0:扩展ID

void CAN_Filter_Config(void)
{
    CAN_FilterTypeDef sFilterConfig;
    CAN_FilterRegTypeDef IDH = {0};
    CAN_FilterRegTypeDef IDL = {0};

#if CAN_ID_TYPE_STD_ENABLE
    IDH.Sub.STID = (CAN_BASE_ID >> 16) & 0xFFFF;                // 标准ID高16位
    IDL.Sub.STID = (CAN_BASE_ID & 0xFFFF);                                // 标准ID低16位
#else
    IDH.Sub.EXID = (CAN_BASE_ID >> 16) & 0xFFFF;                // 扩展ID高16位
    IDL.Sub.EXID = (CAN_BASE_ID & 0xFFFF);                                // 扩展ID低16位
    IDL.Sub.IDE  = 1;                                                                        // 扩展帧标志位置位
#endif
    sFilterConfig.FilterBank           = 0;                                                                                                // 设置过滤器组编号
#if CAN_FILTER_MODE_MASK_ENABLE
    sFilterConfig.FilterMode           = CAN_FILTERMODE_IDMASK;                                                        // 屏蔽位模式
#else
    sFilterConfig.FilterMode           = CAN_FILTERMODE_IDLIST;                                                        // 列表模式
#endif
    sFilterConfig.FilterScale          = CAN_FILTERSCALE_32BIT;                                                        // 32位宽
    sFilterConfig.FilterIdHigh         = IDH.value;                                                                                // 标识符寄存器一ID高十六位,放入扩展帧位
    sFilterConfig.FilterIdLow          = IDL.value;                                                                                // 标识符寄存器一ID低十六位,放入扩展帧位
    sFilterConfig.FilterMaskIdHigh     = IDH.value;                                                                                // 标识符寄存器二ID高十六位,放入扩展帧位
    sFilterConfig.FilterMaskIdLow      = IDL.value;                                                                                // 标识符寄存器二ID低十六位,放入扩展帧位
    sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;                                                                        // 过滤器组关联到FIFO0
    sFilterConfig.FilterActivation     = ENABLE;                                                                                // 激活过滤器
    sFilterConfig.SlaveStartFilterBank = 14;                                                                                        // 设置从CAN的起始过滤器编号,本单片机只有一个CAN,顾此参数无效
    if (HAL_CAN_ConfigFilter(&hcan, &sFilterConfig) != HAL_OK)
    {
        Error_Handler();
    }
}

uint8_t CAN_Transmit(CAN_TxPacketTypeDef* packet)
{
        if(HAL_CAN_AddTxMessage(&hcan, &packet->hdr, packet->payload, &packet->mailbox) != HAL_OK)
                return 1;
        return 0;
}

void CAN_Init(void)
{
    MX_CAN_Init();
    CAN_Filter_Config();
    HAL_CAN_Start(&hcan);
    HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING);                                        // 使能CAN接收中断
}

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *canHandle)
{
        static CAN_RxPacketTypeDef packet;
       
    // CAN数据接收
    if (canHandle->Instance == hcan.Instance)
    {
        if (HAL_CAN_GetRxMessage(canHandle, CAN_RX_FIFO0, &packet.hdr, packet.payload) == HAL_OK)                // 获得接收到的数据头和数据
        {
                        printf("\r\n\r\n\r\n################### CAN RECV ###################\r\n");
                        printf("STID:0x%X\r\n",packet.hdr.StdId);
                        printf("EXID:0x%X\r\n",packet.hdr.ExtId);
                        printf("DLC :%d\r\n", packet.hdr.DLC);
                        printf("DATA:");
                        for(int i = 0; i < packet.hdr.DLC; i++)
                        {
                                printf("0x%02X ", packet.payload[i]);
                        }
           HAL_CAN_ActivateNotification(canHandle, CAN_IT_RX_FIFO0_MSG_PENDING);                                                // 再次使能FIFO0接收中断
        }
    }
}


使用特权

评论回复
地板
renzheshengui|  楼主 | 2021-8-4 15:28 | 只看该作者
CAN_TxPacketTypeDef g_CanTxPacket;

void CAN_SetTxPacket(void)
{
        g_CanTxPacket.hdr.StdId = 0x321;                        // 标准ID
//        g_CanTxPacket.hdr.ExtId = 0x10F01234;                // 扩展ID
        g_CanTxPacket.hdr.IDE = CAN_ID_STD;                        // 标准ID类型
//        g_CanTxPacket.hdr.IDE = CAN_ID_EXT;                        // 扩展ID类型
        g_CanTxPacket.hdr.DLC = 8;                                        // 数据长度
        g_CanTxPacket.hdr.RTR = CAN_RTR_DATA;                // 数据帧
//        g_CanTxPacket.hdr.RTR = CAN_RTR_REMOTE;                // 远程帧
        g_CanTxPacket.hdr.TransmitGlobalTime = DISABLE;
       
        for(int i = 0; i < 8; i++)
        {
                g_CanTxPacket.payload[i] = i;
        }
}

int main()
{
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_USART1_UART_Init();
    CAN_Init();
        printf("----------------------------------------\r\n");

        CAN_SetTxPacket();
       
    while(1)
    {
                if(CAN_Transmit(&g_CanTxPacket) != 0)
                        printf("failed\r\n");
                HAL_Delay(1000);
    }
}



使用特权

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

本版积分规则

78

主题

4079

帖子

2

粉丝