初级会员
- 积分
- 56
- 金钱
- 56
- 注册时间
- 2023-3-13
- 在线时间
- 11 小时
|
楼主 |
发表于 2023-3-27 08:24:17
|
显示全部楼层
- /**
- ****************************************************************************************************
- * [url=home.php?mod=space&uid=175224]@file[/url] can.c
- * [url=home.php?mod=space&uid=90321]@Author[/url] 正点原子团队(ALIENTEK)
- * @version V1.0
- * @date 2020-04-24
- * @brief CAN 驱动代码
- * @license Copyright (c) 2020-2032, 广州市星翼电子科技有限公司
- ****************************************************************************************************
- * @attention
- *
- * 实验平台:正点原子 STM32F103开发板
- * 在线视频:www.yuanzige.com
- * 技术论坛:www.openedv.com
- * 公司网址:www.alientek.com
- * 购买地址:openedv.taobao.com
- *
- * 修改说明
- * V1.0 20200424
- * 第一次发布
- *
- ****************************************************************************************************
- */
- #include "./BSP/CAN/can.h"
- #include "./BSP/LED/led.h"
- #include "./SYSTEM/delay/delay.h"
- #include "./SYSTEM/usart/usart.h"
- CAN_HandleTypeDef g_canx_handler; /* CANx句柄 */
- CAN_TxHeaderTypeDef g_canx_txheader; /* 发送参数句柄 */
- CAN_RxHeaderTypeDef g_canx_rxheader; /* 接收参数句柄 */
- /**
- * @brief CAN初始化
- * @param tsjw : 重新同步跳跃时间单元.范围: 1~3;
- * @param tbs2 : 时间段2的时间单元.范围: 1~8;
- * @param tbs1 : 时间段1的时间单元.范围: 1~16;
- * @param brp : 波特率分频器.范围: 1~1024;
- * @note 以上4个参数, 在函数内部会减1, 所以, 任何一个参数都不能等于0
- * CAN挂在APB1上面, 其输入时钟频率为 Fpclk1 = PCLK1 = 36Mhz
- * tq = brp * tpclk1;
- * 波特率 = Fpclk1 / ((tbs1 + tbs2 + 1) * brp);
- * 我们设置 can_init(1, 8, 9, 4, 1), 则CAN波特率为:
- * 36M / ((8 + 9 + 1) * 4) = 500Kbps
- *
- * @param mode : CAN_MODE_NORMAL, 正常模式;
- CAN_MODE_LOOPBACK,回环模式;
- * @retval 0, 初始化成功; 其他, 初始化失败;
- */
- uint8_t can_init(uint32_t tsjw, uint32_t tbs2, uint32_t tbs1, uint16_t brp, uint32_t mode)
- {
- g_canx_handler.Instance = CAN1;
- g_canx_handler.Init.Prescaler = brp; /* 分频系数(Fdiv)为brp+1 */
- g_canx_handler.Init.Mode = mode; /* 模式设置 */
- g_canx_handler.Init.SyncJumpWidth = tsjw; /* 重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1TQ~CAN_SJW_4TQ */
- g_canx_handler.Init.TimeSeg1 = tbs1; /* tbs1范围CAN_BS1_1TQ~CAN_BS1_16TQ */
- g_canx_handler.Init.TimeSeg2 = tbs2; /* tbs2范围CAN_BS2_1TQ~CAN_BS2_8TQ */
- g_canx_handler.Init.TimeTriggeredMode = DISABLE; /* 非时间触发通信模式 */
- g_canx_handler.Init.AutoBusOff = DISABLE; /* 软件自动离线管理 */
- g_canx_handler.Init.AutoWakeUp = DISABLE; /* 睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位) */
- g_canx_handler.Init.AutoRetransmission = ENABLE; /* 禁止报文自动传送 */
- g_canx_handler.Init.ReceiveFifoLocked = DISABLE; /* 报文不锁定,新的覆盖旧的 */
- g_canx_handler.Init.TransmitFifoPriority = DISABLE; /* 优先级由报文标识符决定 */
-
- if (HAL_CAN_Init(&g_canx_handler) != HAL_OK)
- {
- return 1;
- }
- #if CAN_RX0_INT_ENABLE
- /* 使用中断接收 */
- __HAL_CAN_ENABLE_IT(&g_canx_handler, CAN_IT_RX_FIFO0_MSG_PENDING); /* FIFO0消息挂号中断允许 */
- HAL_NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn); /* 使能CAN中断 */
- HAL_NVIC_SetPriority(USB_LP_CAN1_RX0_IRQn, 1, 0); /* 抢占优先级1,子优先级0 */
- #endif
- CAN_FilterTypeDef sFilterConfig;
- /*配置CAN过滤器*/
- sFilterConfig.FilterBank = 0; /* 过滤器0 */
- sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK; /* 标识符屏蔽位模式 */
- sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT; /* 长度32位位宽*/
- sFilterConfig.FilterIdHigh = 0x0000; /* 32位ID */
- sFilterConfig.FilterIdLow = 0x0000;
- sFilterConfig.FilterMaskIdHigh = 0x0000; /* 32位MASK */
- sFilterConfig.FilterMaskIdLow = 0x0000;
- sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0; /* 过滤器0关联到FIFO0 */
- sFilterConfig.FilterActivation = CAN_FILTER_ENABLE; /* 激活滤波器0 */
- sFilterConfig.SlaveStartFilterBank = 14;
- /* 过滤器配置 */
- if (HAL_CAN_ConfigFilter(&g_canx_handler, &sFilterConfig) != HAL_OK)
- {
- return 2;
- }
- /* 启动CAN外围设备 */
- if (HAL_CAN_Start(&g_canx_handler) != HAL_OK)
- {
- return 3;
- }
- return 0;
- }
- /**
- * @brief CAN底层驱动,引脚配置,时钟配置,中断配置
- 此函数会被HAL_CAN_Init()调用
- * @param hcan:CAN句柄
- * @retval 无
- */
- void HAL_CAN_MspInit(CAN_HandleTypeDef *hcan)
- {
- if (CAN1 == hcan->Instance)
- {
- CAN_RX_GPIO_CLK_ENABLE(); /* CAN_RX脚时钟使能 */
- CAN_TX_GPIO_CLK_ENABLE(); /* CAN_TX脚时钟使能 */
- __HAL_RCC_CAN1_CLK_ENABLE(); /* 使能CAN1时钟 */
- GPIO_InitTypeDef gpio_initure;
- gpio_initure.Pin = CAN_TX_GPIO_PIN;
- gpio_initure.Mode = GPIO_MODE_AF_PP;
- gpio_initure.Pull = GPIO_PULLUP;
- gpio_initure.Speed = GPIO_SPEED_FREQ_HIGH;
- HAL_GPIO_Init(CAN_TX_GPIO_PORT, &gpio_initure); /* CAN_TX脚 模式设置 */
- gpio_initure.Pin = CAN_RX_GPIO_PIN;
- gpio_initure.Mode = GPIO_MODE_AF_INPUT;
- HAL_GPIO_Init(CAN_RX_GPIO_PORT, &gpio_initure); /* CAN_RX脚 必须设置成输入模式 */
- }
- }
- #if CAN_RX0_INT_ENABLE /* 使能RX0中断 */
- /**
- * @brief CAN RX0 中断服务函数
- * @note 处理CAN FIFO0的接收中断
- * @param 无
- * @retval 无
- */
- void USB_LP_CAN1_RX0_IRQHandler(void)
- {
- uint8_t rxbuf[8];
- uint32_t id;
- uint8_t ide, rtr, len;
-
- can_receive_msg(id, rxbuf);
- printf("id:%d\r\n", g_canx_rxheader.StdId);
- printf("ide:%d\r\n", g_canx_rxheader.IDE);
- printf("rtr:%d\r\n", g_canx_rxheader.RTR);
- printf("len:%d\r\n", g_canx_rxheader.DLC);
- printf("rxbuf[0]:%d\r\n", rxbuf[0]);
- printf("rxbuf[1]:%d\r\n", rxbuf[1]);
- printf("rxbuf[2]:%d\r\n", rxbuf[2]);
- printf("rxbuf[3]:%d\r\n", rxbuf[3]);
- printf("rxbuf[4]:%d\r\n", rxbuf[4]);
- printf("rxbuf[5]:%d\r\n", rxbuf[5]);
- printf("rxbuf[6]:%d\r\n", rxbuf[6]);
- printf("rxbuf[7]:%d\r\n", rxbuf[7]);
- }
- #endif
- /**
- * @brief CAN 发送一组数据
- * @note 发送格式固定为: 标准ID, 数据帧
- * @param id : 标准ID(11位)
- * @retval 发送状态 0, 成功; 1, 失败;
- */
- uint8_t can_send_msg(uint32_t id, uint8_t *msg, uint8_t len)
- {
- uint32_t TxMailbox = CAN_TX_MAILBOX0;
-
- g_canx_txheader.StdId = id; /* 标准标识符 */
- g_canx_txheader.ExtId = id; /* 扩展标识符(29位) 标准标识符情况下,该成员无效*/
- g_canx_txheader.IDE = CAN_ID_STD; /* 使用标准标识符 */
- g_canx_txheader.RTR = CAN_RTR_DATA; /* 数据帧 */
- g_canx_txheader.DLC = len;
- if (HAL_CAN_AddTxMessage(&g_canx_handler, &g_canx_txheader, msg, &TxMailbox) != HAL_OK) /* 发送消息 */
- {
- return 1;
- }
-
- while (HAL_CAN_GetTxMailboxesFreeLevel(&g_canx_handler) != 3); /* 等待发送完成,所有邮箱(有三个邮箱)为空 */
-
- return 0;
- }
- /**
- * @brief CAN 接收数据查询
- * @note 接收数据格式固定为: 标准ID, 数据帧
- * @param id : 要查询的 标准ID(11位)
- * @param buf : 数据缓存区
- * @retval 接收结果
- * @arg 0 , 无数据被接收到;
- * @arg 其他, 接收的数据长度
- */
- uint8_t can_receive_msg(uint32_t id, uint8_t *buf)
- {
- if (HAL_CAN_GetRxFifoFillLevel(&g_canx_handler, CAN_RX_FIFO0) == 0) /* 没有接收到数据 */
- {
- return 0;
- }
- if (HAL_CAN_GetRxMessage(&g_canx_handler, CAN_RX_FIFO0, &g_canx_rxheader, buf) != HAL_OK) /* 读取数据 */
- {
- return 0;
- }
-
- if (g_canx_rxheader.StdId!= id || g_canx_rxheader.IDE != CAN_ID_STD || g_canx_rxheader.RTR != CAN_RTR_DATA) /* 接收到的ID不对 / 不是标准帧 / 不是数据帧 */
- {
- return 0;
- }
- return g_canx_rxheader.DLC;
- }
复制代码 |
|