IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> STM32F407用USB和串口烧写程序 -> 正文阅读

[嵌入式]STM32F407用USB和串口烧写程序

系统bootloader

STM32的系统存储区自带bootloader,此程序是ST在芯片出厂时烧录进去的,主要用于将用户应用程序下载到芯片内部Flash。支持USB、SPI、I2C、CAN、UART等接口方式下载。
我使用的是407,所以用bootloader下载程序的话只能是USB,USART1,USART3和CAN
在这里插入图片描述
在这里插入图片描述

如何进入系统bootloader

有两种方式可以进入系统的boot loader
一种是通过设置BOOT0引脚,将该引脚置高可以上电后直接进入系统boot loader。
令一种方法是通过程序跳转到系统bootloader。
跳转前需要注意以下问题
1、禁止所有外设时钟
2、禁止使用PLL
3、禁止所有中断
4、清除所有中断挂起标志。

以上部分内容在芯片参考手册的2.4章节,自举配置这一部分也有简单说明。

用串口和USB更新程序

用串口烧写程序 (需要使用RS232接口)

1、首先将BOOT0置高,进入系统bootloader
2、打开软件 STM32CubeProgrammer,如下图所示,选择UART,设置串口、波特率、以及偶检验(因为上电后串口默认是偶校验),点击 connect按钮,下面的信息框里会显示是否连接 成功。
在这里插入图片描述
3、选择烧写文件,点击Start Programm…,就开始烧写程序了。

在这里插入图片描述

USB烧写程序

1、同样需要将BOOT0置高进入系统bootloader
2、打开软件 STM32CubeProgrammer,选择USB,点击2处的刷新可以看到USB接口(必须先进入系统bootloader才可以),点击connect连接。后面的烧写方式与UART方式相同。
在这里插入图片描述

通过程序跳转到系统bootloader

如果我们的硬件电路不方便引出BOOT脚,那么就可以使用程序跳转的方式。
1、我们可以在自己的APP程序中,加入一个跳转程序,例如按下某一个按钮就跳转到系统bootloader,然后就可以用以上两种方式烧写程序,但是这种方式有一个弊端,就是如果升级程序的时候突然断开连接了,那么单片机中就没有程序了,必须再重新用SW的方式烧写一遍才行。
2、我们可以写两个程序,一个引导程序,一个APP程序,这两个程序在flash中的位置是不一样的,这样在更新APP程序的时候,即便发送异常,也不会破坏引导程序。
主要程序如下所示

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */
  

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
		if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_1)==GPIO_PIN_RESET)
		{
			JumpToBootloader();
		}
		else
		{
			JumpToApp();
		}
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage 
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  /** Initializes the CPU, AHB and APB busses clocks 
  */
  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.PLLM = 4;
  RCC_OscInitStruct.PLL.PLLN = 168;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB busses clocks 
  */
  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_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */
#define DISABLE_INT()	__set_PRIMASK(1)
#define ENABLE_INT()	__set_PRIMASK(0)

static void JumpToBootloader(void)
{
	/*除了使用boot引脚控制运行系统bootloader,也可以使用程序跳转,跳转前需要注意以下问题
	1、禁止所有外设时钟
	2、禁止使用PLL
	3、禁止所有中断
	4、清除所有中断挂起标志
	以上操作执行完毕后,直接使用跳转指令,跳转到System Memory地址即可。这个地址可以在数据手册中找到
	
	如果觉得关闭外设时钟等操作太复杂,也可以通过另外一种方式来实现上述操作,即:软件复位
	芯片复位后,外设时钟、中断等默认都是关闭的,只要在初始化前完成跳转即可。我们知道,stm32
	在运行main.c函数之前会先执行system_stm32f4xx.c中的SystemInit函数,在HAL库中,该函数只是配置了中断向量,
	因此可以直接在main.c函数的开始添加跳转代码。具体流程如下
	1、需要升级时,首先在flash某个地址将一个标志置1  (没有测试这种方法)
	2、产生软件复位
	3、判断标志位为1,需要升级,标志位清零,执行跳转程序。
	4、判断标志位为0,直接运行程序 DFU*/
	uint32_t i=0;
	void (*SysMemBootJump)(void); /* 声明一个函数指针*/
	__IO uint32_t BootAddr =  0x1FFF0000;//0x1FFF0000; /* STM32F4 的系统 BootLoader 地址 */
	
	/* 关闭全局中断 */
	DISABLE_INT();//CPU_IntDis();  
	
	/* 关闭滴答定时器,复位到默认值 */
	SysTick->CTRL = 0;
	SysTick->LOAD = 0;
	SysTick->VAL = 0;
	
	/* 设置所有时钟到默认状态,使用 HSI 时钟 */
	HAL_RCC_DeInit();
	
	/* 关闭所有中断,清除所有中断挂起标志 */
	for (i = 0; i < 8; i++)
	{
		NVIC->ICER[i]=0xFFFFFFFF;
		NVIC->ICPR[i]=0xFFFFFFFF;
	}
	
	/* 使能全局中断 */
	ENABLE_INT();//CPU_Init();
	
	/* 设置重映射到系统 Flash */
	__HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH();
	
	/* 跳转到系统 BootLoader,首地址是 MSP,地址+4 是复位中断服务程序地址 */
	SysMemBootJump = (void (*)(void)) (*((uint32_t *) (BootAddr + 4)));
	
	/* 设置主堆栈指针 */
	__set_MSP(*(uint32_t *)BootAddr);
	
	/*在 RTOS 工程,这条语句很重要,设置为特权级模式,使用 MSP 指针 */
	__set_CONTROL(0);
	
	/* 跳转到系统 BootLoader */
	SysMemBootJump();
	
//	/* 跳转成功的话,不会执行到这里,用户可以在这里添加代码 */
//	while (1)
//	{
//		
//	}
}

static void JumpToApp(void)
{
	uint32_t i=0;
	void (*SysMemBootJump)(void);        /* 声明一个函数指针 */
	__IO uint32_t BootAddr = 0x8004000; /* 系统的APP地址 */	
	

	/* 关闭全局中断 */
	DISABLE_INT(); 

	/* 关闭滴答定时器,复位到默认值 */
	SysTick->CTRL = 0;
  SysTick->LOAD = 0;
  SysTick->VAL = 0;

	/* 设置所有时钟到默认状态,使用HSI时钟 */
	HAL_RCC_DeInit();

	/* 关闭所有中断,清除所有中断挂起标志*/
	for (i = 0; i < 8; i++)
	{
		NVIC->ICER[i]=0xFFFFFFFF;
		NVIC->ICPR[i]=0xFFFFFFFF;
	}	

	/* 使能全局中断 */
	ENABLE_INT();

	/* 跳转到系统BootLoader,首地址是MSP,地址+4是复位中断复位程序地址 */
	SysMemBootJump = (void (*)(void)) (*((uint32_t *) (BootAddr + 4)));

	/* 设置主堆栈指针 */
	__set_MSP(*(uint32_t *)BootAddr);
	
	/*在 RTOS 工程,这条语句很重要,设置为特权级模式,使用 MSP 指针 */
	__set_CONTROL(0);

	/* 跳转到系统 BootLoader */
	SysMemBootJump(); 
}
/* USER CODE END 4 */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

在JumpToApp函数中,系统的APP地址定义的是0x8004000,为什么选这个地址呢,因为在把引导程序烧进去之后,用J-Flash软件读取了一下Read back–>Selected sectors; 读取完毕之后发现引导程序大概占用了0xE70左右的大小。于是APP程序的地址就从第二个扇区开始了。
同时APP程序还要设置一下,如下图所示:0x7C00是大小,就是芯片的Flash大小减去第一个扇区的大小。
在这里插入图片描述
然后同时也要在APP程序里面修改中断向量表的位置,在文件system_stm32f4xx.c文件中。
在这里插入图片描述

这样就完成了,仅对USB烧写程序进行了程序跳转到系统bootloader方法的实验,UART仅用BOOT脚的方式做了实验。但是应该都是可行的。

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-07-15 16:21:57  更:2021-07-15 16:22:26 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/27 9:47:58-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计