基于STM32F103的CAN bootload程序源码实践分享
基于STM32F103的CAN bootload程序源码包含boot和app两个工程,已应用到实际项目并量产在嵌入式开发领域,CAN bootload程序对于设备的远程升级以及灵活更新有着至关重要的意义。今天就来给大家分享基于STM32F103的CAN bootload程序源码,这可是包含boot和app两个工程,并且已经成功应用到实际项目甚至实现量产啦。
基于STM32F103的CAN bootload程序源码 包含boot和app两个工程,已应用到实际项目并量产
在嵌入式开发领域,CAN bootload程序对于设备的远程升级以及灵活更新有着至关重要的意义。今天就来给大家分享基于STM32F103的CAN bootload程序源码,这可是包含boot和app两个工程,并且已经成功应用到实际项目甚至实现量产啦。
Boot工程
Boot工程主要负责初始化系统、检测是否有更新请求,并引导程序跳转到APP区域运行。先来看看初始化部分代码:
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
// 这里配置HSE,使用外部高速时钟
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct)!= HAL_OK)
{
Error_Handler();
}
// 配置系统时钟,AHB、APB1、APB2等总线时钟
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2)!= HAL_OK)
{
Error_Handler();
}
}
这段代码主要进行了系统时钟的配置,我们选择了HSE作为PLL的时钟源,并通过PLLMUL配置将时钟倍频到72MHz,这是STM32F103常用的工作频率。之后配置了各个总线时钟的分频,以满足不同外设的工作需求。
在检测更新请求方面,CAN接收中断处理函数是关键:
void CAN_RX0_IRQHandler(void)
{
CAN_RxHeaderTypeDef RxHeader;
uint8_t RxData[8];
HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &RxHeader, RxData);
// 假设更新请求的CAN ID为0x123
if (RxHeader.StdId == 0x123)
{
// 设置标志位,表明有更新请求
update_flag = 1;
}
}
这里当CAN接收到ID为0x123的报文时,就会设置更新标志位update_flag,后续程序检测到这个标志位就会进行相应的更新操作。
基于STM32F103的CAN bootload程序源码 包含boot和app两个工程,已应用到实际项目并量产
当检测到更新并且完成数据接收后,就要跳转到APP区域运行了:
typedef void (*pFunction)(void);
pFunction Jump_To_Application;
uint32_t JumpAddress;
// APP起始地址假设为0x08005000
JumpAddress = *(__IO uint32_t*) (0x08005000 + 4);
Jump_To_Application = (pFunction) JumpAddress;
// 设置主堆栈指针
__set_MSP(*(__IO uint32_t*) 0x08005000);
Jump_To_Application();
这里通过先获取APP起始地址处存放的栈顶指针设置主堆栈指针,再获取复位向量地址并强制转换为函数指针,最后调用该函数实现跳转到APP运行。
APP工程
APP工程就是设备正常运行的主体程序了,这里以一个简单的LED闪烁代码为例:
int main(void)
{
// 初始化GPIO,假设LED连接在PA5
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
while (1)
{
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
HAL_Delay(500);
}
}
这段代码很简单,先使能GPIOA的时钟,然后配置PA5为推挽输出模式,速度为高速。在主循环中通过HALGPIOTogglePin函数实现LED的闪烁,每500毫秒翻转一次电平。
基于STM32F103的CAN bootload程序就是这样两个工程相互配合,实现设备的正常运行以及远程更新功能。在实际项目中,通过这种方式大大提高了产品的维护性和可升级性,这也是它能够成功应用并量产的重要原因。希望这篇分享对大家在相关开发工作中有所帮助。

更多推荐
所有评论(0)