bs_bcu_app/bsp/bsp_can.c

209 lines
7.1 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "bsp_flash.h"
#include "bsp_can.h"
#include "bsp_delay.h"
#include "drv_sys.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 = 42Mhz
* tq = brp * tpclk1;
* 波特率 = Fpclk1 / ((tbs1 + tbs2 + 1) * brp);
* 我们设置 can_init(1, 6, 7, 6, 1), 则CAN波特率为:
* 42M / ((6 + 7 + 1) * 6) = 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(CAN1_RX0_IRQn); /* 使能CAN中断 */
HAL_NVIC_SetPriority(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;
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_init_struct;
gpio_init_struct.Pin = CAN_TX_GPIO_PIN;
gpio_init_struct.Mode = GPIO_MODE_AF_PP;
gpio_init_struct.Pull = GPIO_PULLUP;
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;
gpio_init_struct.Alternate = GPIO_AF9_CAN1;
HAL_GPIO_Init(CAN_TX_GPIO_PORT, &gpio_init_struct); /* CAN_TX脚 模式设置 */
gpio_init_struct.Pin = CAN_RX_GPIO_PIN;
HAL_GPIO_Init(CAN_RX_GPIO_PORT, &gpio_init_struct); /* 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;
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位)
* @param msg : 数据指针
* @param len : 数据长度
* @retval 发送状态 0, 成功; 1, 失败;
*/
uint8_t can_send_msg(uint32_t id, uint8_t *msg, uint8_t len)
{
uint16_t t = 0;
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) /* 等待发送完成,所有邮箱为空 */
{
t++;
if (t > 0xFFF)
{
HAL_CAN_AbortTxRequest(&g_canx_handler, TxMailbox); /* 超时,直接中止邮箱的发送请求 */
return 1;
}
}
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;
}