目录
一、CubeMX配置
1、时钟设置
最高频率:216MHz
APB1:54MHz
2、CAN1设置
1)引脚修改
STM32F767IGT默认使用PI9作为接收引脚,为好了使用开发板做实验,手动将接收引脚改为PA11
2)中断使能
3)波特率计算
波特率=peripheral clocks/((TQ1+TQ2+SJW)*prescaler)
即:54MHz/((11+6+1)*6)=0.5MHz
设置波特率为:500KHz
3、SYS设置
4、GPIO设置
用于两个LED的控制
5、软件包版本
二、手动添加代码
1、添加屏蔽器设置代码
static void mx_CAN_Filter_Config(void)
{
CAN_FilterTypeDef CAN1_FilerConf;
CAN1_FilerConf.FilterIdHigh=0X0000; //32位ID
CAN1_FilerConf.FilterIdLow=0X0000;
CAN1_FilerConf.FilterMaskIdHigh=0X0000; //32位MASK
CAN1_FilerConf.FilterMaskIdLow=0X0000;
CAN1_FilerConf.FilterFIFOAssignment=CAN_FILTER_FIFO0;//过滤器0关联到FIFO0
CAN1_FilerConf.FilterBank=0; //过滤器0
CAN1_FilerConf.FilterMode=CAN_FILTERMODE_IDMASK;
CAN1_FilerConf.FilterScale=CAN_FILTERSCALE_32BIT;
CAN1_FilerConf.FilterActivation=ENABLE; //激活滤波器0
CAN1_FilerConf.SlaveStartFilterBank=14;
if(HAL_CAN_ConfigFilter(&hcan1,&CAN1_FilerConf)!=HAL_OK)//滤波器初始化
{
Error_Handler();
}
#if 0
uint32_t FilterIdHigh;
uint32_t FilterIdLow;
uint32_t FilterMaskIdHigh;
uint32_t FilterMaskIdLow;
uint32_t FilterFIFOAssignment;
uint32_t FilterBank;
uint32_t FilterMode;
uint32_t FilterScale;
uint32_t FilterActivation;
uint32_t SlaveStartFilterBank;
#endif
}
2、添加CAN发送代码
typedef struct CAN_s_Rx_Temp_t
{
CAN_RxHeaderTypeDef can_rx_temp;
uint8_t can_rx_arry[8];
}CAN_s_Rx_Temp;
typedef struct CAN_s_Tx_Temp_t
{
CAN_TxHeaderTypeDef can_tx_temp;
uint8_t can_tx_arry[8];
uint32_t mailbox;
}CAN_s_Tx_Temp;
extern CAN_s_Rx_Temp hcan1_rx_temp;
extern CAN_s_Tx_Temp hcan1_tx_temp;
void CAN1_Send_Msg_Init(uint32_t a_StdId, uint32_t a_ExtId, uint32_t a_IDE, uint32_t a_RTR, uint8_t len)
{
hcan1_tx_temp.can_tx_temp.StdId = a_StdId;
hcan1_tx_temp.can_tx_temp.ExtId = a_ExtId;
hcan1_tx_temp.can_tx_temp.IDE = a_IDE;//CAN_ID_STD;
hcan1_tx_temp.can_tx_temp.RTR = a_RTR;//CAN_RTR_DATA;
hcan1_tx_temp.can_tx_temp.DLC = len;
hcan1_tx_temp.can_tx_temp.TransmitGlobalTime = DISABLE;
}
void CAN1_Send_Msg(uint32_t a_StdId, uint32_t a_ExtId, uint8_t len)
{
uint8_t i=0;
CAN1_Send_Msg_Init(a_StdId, a_ExtId, CAN_ID_STD, CAN_RTR_DATA, len);
for(i=0;i<len;i++)
{
hcan1_tx_temp.can_tx_arry[i] = i+2;
}
if(HAL_CAN_AddTxMessage(&hcan1, &hcan1_tx_temp.can_tx_temp,
hcan1_tx_temp.can_tx_arry, &hcan1_tx_temp.mailbox) != HAL_OK)
{
Error_Handler();
}
}
3、添加CAN代码的初始化函数
void can_init_fun(void)
{
MX_CAN1_Init();
/* USER CODE BEGIN 2 */
mx_CAN_Filter_Config();
if(HAL_CAN_Start(&hcan1)!=HAL_OK)
{
Error_Handler();
}
if(HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING)!=HAL_OK) // 使能CAN接收中断
{
Error_Handler();
}
if(HAL_CAN_ActivateNotification(&hcan1, CAN_IT_TX_MAILBOX_EMPTY)!=HAL_OK) // 使能CAN发送中断
{
Error_Handler();
}
for(uint8_t i=0;i<8;i++)
{
hcan1_tx_temp.can_tx_arry[i] = 0;
}
}
4、添加CAN接收回调函数与发送回调函数
/*__weak */void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
// CAN数据接收
if (hcan->Instance == hcan1.Instance)
{
if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &hcan1_rx_temp.can_rx_temp, hcan1_rx_temp.can_rx_arry) == HAL_OK) // 获得接收到的数据头和数据
{
if(hcan1_rx_temp.can_rx_temp.StdId == 0x2F1)
{
HAL_GPIO_WritePin(LED_DS0_GPIO_Port, LED_DS0_Pin, 0);
}
HAL_CAN_ActivateNotification(hcan, CAN_IT_RX_FIFO0_MSG_PENDING); // 再次使能FIFO0接收中断
}
}
}
CAN接收回调函数功能,在回调函数中,判断接收到的数据中,有ID为2F1的数据时,点亮LED0。
/*__weak */void HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef *hcan)
{
/* Prevent unused argument(s) compilation warning */
//UNUSED(hcan);
if (hcan->Instance == hcan1.Instance)
{
static uint8_t i_index = 0;
if(i_index < 99)
{
i_index++;
if(i_index >= 99)
{
HAL_GPIO_TogglePin(LED_DS1_GPIO_Port, LED_DS1_Pin);
i_index = 0;
}
}
HAL_CAN_ActivateNotification(&hcan1, CAN_IT_TX_MAILBOX_EMPTY);
}
/* NOTE : This function Should not be modified, when the callback is needed,
the HAL_CAN_TxMailbox0CompleteCallback could be implemented in the
user file
*/
}
CAN发送回调函数功能,该回调函数是在CAN数据发送完成后进行调用,由于发送函数在100ms TASK中调用,如下:
void Task_For_100ms(void)
{
CAN1_Send_Msg(0X15F, 0X15F, 8);
}
CAN发送回调函数完成后,每发送完一次后,在回调函数中计数器加1,100*100ms,即10秒翻转一次LED1。
代码记录:
STM32_Deal_A003
以上,仅为本人自用。