stm32 hal can

can协议的硬件有非常强大的容错率,解决各种冲突。没有主从关系,单纯的发送数据和匹配id再接收。数据是高位先发。

数据以帧/包为单位,每帧数据里含有许多字节。数据分为两种,标准和扩展,主要区别是标准帧的id标识部分有11bit,扩展的id标识部分有29bit,其它方面有略微不同。

数据接收的配置是要配置“过滤器(filter)”,也叫数据过滤器。实际上是配置数据匹配规则,只有符合过滤器的配置的数据才会被硬件接收。

有两种工作模式,分为完全匹配(标识符列表)模式和不完全匹配(掩码/屏蔽位)模式,完全匹配是id完全相同才会接收,不完全匹配是只匹配id其中部分位,只要匹配的那几位相同就接收。

数据线为双线,由CANH和CANL组成,逻辑0称为显性电平,逻辑1称为隐性电平。0是CANH为高,CANL为低,1是总线呈中电平状态,约为高电平的一半。

总线仲裁方法:总线上的can设备在发送id时也同时监控着总线上正在发的id数据,1bit、1bit的匹配,谁id先为0,谁就获得发送权。

标准帧的格式的组成:SOF:1bit、ID:11bit、RTR:1bit、IDE:1bit、r0:1bit、DLC:4bit、Data:0~64bit、CRC:15bit、间隔符:1bit、ACK:1bit、间隔符:1bit、EOF:7bit。

id禁止高7位全部为1。

每bit数据的发送和接收分为4段时间,这是和硬件相关的含义,分别是同步段(SS)、传播时间段(PTS)、相位缓存段1(PBS1)、相位缓存段2(PBS2),它们由一个或多个“时间量(Time Quantum)”组成,简称Tq。

每段Tq数量的规定:SS:1Tq、PTS:1~8Tq、PBS1:1~8Tq、PBS2:2~8Tq。SS~PBS2需有8~25Tq。但未规定再同步补偿补偿宽度(SJW),其可为1~4Tq。

stm32只有SJW、PBS1、PBS2。

数据在PBS1结束后立刻被采样,PBS2结束后立刻开始发送下一位,所以其它的时间段不是很重要,只要总Tq相同,速率就是相同的,只在开始和结束的前后时间不一样。

波特率计算:APB2(36M)/4/(1+9+8) = 500K。

stm32有很多组过滤器,每个过滤器对应一个规则,数据会轮流匹配这些过滤器,成功的就会通过。过滤器在大小上两种模式,16bit和32bit模式,16bit只能用于标准帧,32bit两个都能。

邮箱是用来缓冲的,避免因总线略微阻塞就丢失数据,同时防止系统一直等待数据发送完毕。can的RX0和RX1中断对应的是FIFO0和FIFO1,一般只用一个FIFO缓冲器,两个更适合于有两个can。

 

stm32cubemx的配置只要打开CAN和CAN的RX0中断即可,详细配置在程序里改。

 

enum board_can_id_t
{
    main_can_id_v = 1,
    storage_mechanical_arm_can_id_v,
    take_out_mechanical_arm_can_id_v,
    take_in_mechanical_arm_can_id_v
};

CAN_TxHeaderTypeDef can_tx_header_v; //CAN1发送消息的配置信息
CAN_RxHeaderTypeDef can_rx_header_v; //CAN1接收消息的过滤信息

void my_MX_CAN_Init(enum board_can_id_t id_va)
{

    /* USER CODE BEGIN CAN_Init 0 */

    /* USER CODE END CAN_Init 0 */

    /* USER CODE BEGIN CAN_Init 1 */

    /* USER CODE END CAN_Init 1 */
    hcan.Instance = CAN1;
    hcan.Init.Prescaler = 4;
    hcan.Init.Mode = CAN_MODE_NORMAL;
    hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;
    hcan.Init.TimeSeg1 = CAN_BS1_9TQ;
    hcan.Init.TimeSeg2 = CAN_BS2_8TQ;
    hcan.Init.TimeTriggeredMode = DISABLE;
    hcan.Init.AutoBusOff = DISABLE;
    hcan.Init.AutoWakeUp = DISABLE;
    hcan.Init.AutoRetransmission = ENABLE;
    hcan.Init.ReceiveFifoLocked = DISABLE;
    hcan.Init.TransmitFifoPriority = DISABLE;
    if (HAL_CAN_Init(&hcan) != HAL_OK)
    {
        Error_Handler();
    }
    /* USER CODE BEGIN CAN_Init 2 */
    CAN_FilterTypeDef CAN_FilterTypeDef_v;
    /*配置 CAN 过滤器*/
    CAN_FilterTypeDef_v.FilterIdHigh = (uint32_t)id_va << 5; //32 位 ID在16位里的高11位 id由这两个FilterId的低16位组成
    CAN_FilterTypeDef_v.FilterIdLow = 0;
    CAN_FilterTypeDef_v.FilterFIFOAssignment = CAN_RX_FIFO0; //过滤器 0 关联到 FIFO0
    CAN_FilterTypeDef_v.FilterBank = 0;                      //过滤器 0
    CAN_FilterTypeDef_v.FilterMode = CAN_FILTERMODE_IDLIST;  //模式
    CAN_FilterTypeDef_v.FilterScale = CAN_FILTERSCALE_32BIT;
    CAN_FilterTypeDef_v.FilterActivation = ENABLE; //激活滤波器 0
    CAN_FilterTypeDef_v.SlaveStartFilterBank = 0;
    //过滤器配置
    if (HAL_CAN_ConfigFilter(&hcan, &CAN_FilterTypeDef_v) != HAL_OK)
    {
        Error_Handler();
    }
    //启动 CAN 外围设备
    if (HAL_CAN_Start(&hcan) != HAL_OK)
    {
        Error_Handler();
    }
    //激活可以 RX 通知
    if (HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK)
    {
        Error_Handler();
    }
    //配置发送
    can_tx_header_v.StdId = (uint32_t)id_va;
    can_tx_header_v.RTR = CAN_RTR_DATA; //数据帧
    can_tx_header_v.IDE = CAN_ID_STD;   //标准帧
    can_tx_header_v.TransmitGlobalTime = DISABLE;
    /* USER CODE END CAN_Init 2 */
}

//发送函数,message_pa是8字节的数组,len_va <= 8
uint8_t CAN1_Send_Msg(uint8_t *message_pa, uint8_t len_va)
{
    uint32_t mail_box_v;
    can_tx_header_v.DLC = len_va;
    if (HAL_CAN_AddTxMessage(&hcan, &can_tx_header_v, message_pa, &mail_box_v) != HAL_OK) //发送
    {
        return 1;
    }
    return 0;
}

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
    static uint8_t rx_buff_v[8];
    HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &can_rx_header_v, rx_buff_v);
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值