datasheet

STM32串口IAP(YModem)

2019-06-14来源: eefocus关键字:STM32  串口IAP  YModem

在之前的《STM32串口IAP》一文中,通过传输数据流来升级程序,但是这种"裸"数据的传输方式存在这许多的问题,比如它没有容错机制,不能保证数据的正确传输,还比如说它无法获知升级文件的信息,导致它在判断何时停止接收数据上“犹豫不决”。正式为了解决上面的问题,才引进了YModem协议。

在《YModem协议简介》一文中,已经详细介绍了YModem的协议,这里就不再赘述,这篇文章就来讲讲如何将YModem协议转换成代码,并应用到串口升级的功能中。

还是以我自己的规范工程为例,讲讲走YModem协议的IAP工程的的实现。

1、工程的修改

1)串口升级当然需要用到USART与FLASH了,我的原工程已经添加了串口的库文件stm32f10x_usart.c与stm32f10x_flash.c,所以就不需要在添加这两个文件了。

2)新建IAP.c和IAP.h两个文件分别保存到BSP文件夹下的src与inc两个文件中。并将IAP.c文件添加到BSP工程组中。

3)新建YMoem.c和YMoem.h两个文件分别保存到BSP文件夹下的src与inc两个文件中。并将YModem.c文件添加到BSP工程组中。

4)新建Download.c和Download.h两个文件分别保存到BSP文件夹下的src与inc两个文件中。并将Download.c文件添加到BSP工程组中。

5)新建Upload.c和Upload.h两个文件分别保存到BSP文件夹下的src与inc两个文件中。并将Upload.c文件添加到BSP工程组中。

也就是说在BSP的工程组中有:BSP.c、IAP.c、YModem.c、Download.c、Upload.c这几个文件,如下:

STM32串口IAP(YModem) - ziye334 - ziye334的博客

 

2、IAP.c与IAP.h的编写

这个文件与之前在《STM32串口IAP》一文中的IAP.c与IAP.h文件代码相似,只是做了细微的一些调整,不过这里还是仔细讲述下。

同样的考虑到开发板资源,我采用串口1作为升级的通道,所以原先在规范工程中作为调试接口的串口1的相关代码需要从BSP.c与BSP.h两个文件中完全删除掉,出现此之外还要打开stm32f10x_it.c文件中将串口中断服务程序的相关代码删除掉。

与完成一样,IAP.c中第一个函数就是IAP_Init(),在这个函数中,配置串口相关的代码,如配置串口引脚,串口时钟,串口属性,串口中断等,具体的代码如下:

/*************************************************************  Function   : IAP_Init   Description: IAP初始化函数,初始化串口1  Input      : none          return     : none    *************************************************************/void IAP_Init(void){	GPIO_InitTypeDef GPIO_InitStructure;	USART_InitTypeDef USART_InitStructure;	RCC_APB2PeriphClockCmd(COM1_RCC, ENABLE);//使能 USART2 时钟	RCC_APB2PeriphClockCmd(COM1_GPIO_RCC, ENABLE);//使能串口2引脚时钟	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//配置 USART2 的Tx 引脚类型为推挽式的	GPIO_InitStructure.GPIO_Pin = COM1_TX_PIN;        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	GPIO_Init(COM1_GPIO_PORT, &GPIO_InitStructure);        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//配置 USART2 的Rx 为输入悬空        GPIO_InitStructure.GPIO_Pin = COM1_RX_PIN;        GPIO_Init(COM1_GPIO_PORT, &GPIO_InitStructure);	USART_InitStructure.USART_BaudRate = 115200;//设置波特率为115200	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//设置数据位为8位	USART_InitStructure.USART_StopBits = USART_StopBits_1;//设置停止位为1位	USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验    	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //没有硬件流控	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//发送与接收	USART_Init(COM1,&USART_InitStructure);//串口2相关寄存器的配置	USART_Cmd(COM1,ENABLE);//使能串口2	}

上面的代码中可以看出,这次我没有打开串口中断,而是使用查询法来接收串口数据。

接下去在编写串口的发送接收程序,代码如下:

/*************************************************************  Function   : IAP_SerialSendByte   Description: 串口发送字节  Input      : c-要发送的字节          return     : none    *************************************************************/void IAP_SerialSendByte(u8 c){	USART_SendData(COM1, c);	while (USART_GetFlagStatus(COM1, USART_FLAG_TXE) == RESET) {}}/*************************************************************  Function   : IAP_SerialSendStr   Description: 串口发送字符串  Input      : none          return     : none    *************************************************************/void IAP_SerialSendStr(u8 *s){	while(*s != '')	{		IAP_SerialSendByte(*s);		s++;	}}/*************************************************************  Function   : IAP_SerialGetByte   Description: 接收一个字节数据  Input      : none          return     : 返回结果值,0-没有接收到数据;1-接收到数据    *************************************************************/u8 IAP_SerialGetByte(u8 *c){	if(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) != RESET)	{		*c = USART_ReceiveData(USART1);		return 1;	}  	return 0;}

可以看到串口接收函数IAP_SerialGetByte()仅仅是查询下是否有数据接收到,但无论是否接收到数据,程序都不会在这个函数上阻塞。所以为了实现阻塞的效果,还需要稍微做下文章,下面就提前讲讲如何在IAP_SerialGetByte()的基础上修改成阻塞的功能,如下获取一个用户输入键值的函数:

/*************************************************************  Function   : IAP_GetKey   Description: 获取键入值  Input      : none          return     : 返回键值    *************************************************************/u8 IAP_GetKey(void){	u8 data;	while(!IAP_SerialGetByte(&data)){ }	return data;}

然后再设计Bootload的界面,更《STM32串口IAP》一文给出的界面基本上一样,如下:

/*************************************************************  Function   : IAP_ShowMenu   Description: 显示菜单界面  Input      : none          return     : none    *************************************************************/void IAP_ShowMenu(void){	IAP_SerialSendStr("rn+================(C) COPYRIGHT 2014 Ziye334 ================+");	IAP_SerialSendStr("rn|    In-Application Programing Application (Version 1.0)    |");	IAP_SerialSendStr("rn+----command----+-----------------function------------------+");	IAP_SerialSendStr("rn|  1: FWUPDATA  | Update the firmware to flash by YModem    |");	IAP_SerialSendStr("rn|  2: FWDWLOAD  | Download the firmware from Flash by YModem|");	IAP_SerialSendStr("rn|  3: FWERASE   | Erase the current firmware                |");	IAP_SerialSendStr("rn|  4: BOOT      | Excute the current firmware               |");	IAP_SerialSendStr("rn|  5:REBOOT    | Reboot                                    |");	IAP_SerialSendStr("rn|  ?: HELP      | Display this help                         |");	IAP_SerialSendStr("rn+===========================================================+");	IAP_SerialSendStr("rnrn");	IAP_SerialSendStr("STM32-IAP>>");}

界面与之前相比,唯一的区别在于多了一个FWDWLOAD的选项,提供用户从STM32上下载升

[1] [2] [3] [4] [5] [6] [7] [8]

关键字:STM32  串口IAP  YModem

编辑:什么鱼 引用地址:http://www.eeworld.com.cn/mcu/ic464672.html
本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:stm32 Bootloader设计(YModem协议)
下一篇:STM32定时器的预装寄存器以及影子寄存器话题

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

用于stm32Discovery的图像转代码取模小工具

最近拿着st的官方板子在开发图形界面,看了下代码是直接把整个像素32bit拷贝到控制器中Graphic RAM(就是一块SDRAM)中的,所以以往遇到的生成器都不能用,在内部则又是转换费时费力,占用内存所以针对stm32的discovery lcd显示写了个图像代码生成的程序,可以直接生成32bit的ARGB格式代码等后面发一个成熟点的版本,目前还是有些容易遇到的bug
发表于 2019-06-15
用于stm32Discovery的图像转代码取模小工具

STM32L0xx_HAL_Driver库的使用——UART

单片机型号:STM32L051C8T6开发环境MDK5.12库版本:STM32L0xx_HAL_Driver V1.1.0主机环境:Windows XP之前一直使用的STM32F030C8T6单片机来做开发,因需求更改更换了一个新型号STM32L051C8T6,主要是用到了其低功耗特性,本以为直接把代码拷贝一下就可以使用了,结果是太天真了,STM32F030C8T6使用的库是STM32F0_StdPeriph_Lib而STM32L051C8T6使用的库是STM32L0xx_HAL_Driver两者的差别还是很大的,而且官方也推荐使用后者,没办法,重新学习一下吧。。。参考其例程磕磕绊绊的勉强可以写一个工程了,这里写一下有关UART
发表于 2019-06-15

STM32CubeMx之串行通信

前言我的板子是:STM32ZGT6配置1.打开STM32CubeMX新建工程,选择STM32ZGT62.配置外部高速时钟RCC设置,选择HSE(外部高速时钟)为Crystal/Ceramic Resonator(晶振/陶瓷谐振器),我的开发板外部时钟是25MHZ。 3.配置串行通信选择Asynchronous异步通信。  串口配置设置波特率为115200 Bits/s。传输数据长度为8 Bit。奇偶检验无,停止位1.其他参数默认。 生成报告以及代码,编译程序(最好单独生成.c和.h文件)。在usart.c文件中可看到串口1的初始化函数MX_USART1_UART_Init(void
发表于 2019-06-15

stm32 不断进入串口中断的bug解决方法

在使用stm32的时候,发现usart会莫名的卡在串口中断里,然而串口初始化只配置了RXNE中断,打断点发现不断进入中断却没不是RXNE中断引起的,经过查找资料发现是ORE的问题,2篇博文解决方案如下:http://bbs.21ic.com/icview-160999-1-1.html及http://blog.csdn.net/origin333/article/details/49992383大致原因为开启了RXNE中断之后 ORE也开启了,但是使用USART_GetITStatus却无法读取到ORE的标志位(未使能ERR时),这样也无法消除中断申请,自然一直进入串口中断,如果要消除ORE需要
发表于 2019-06-15

STM32串口USART用法的进阶(HAL库版本)

句话是绑定DMA,来源数USART1,目的是数组,定义好的。第二句是打开空闲中断it.c里面找到void USART1_IRQHandler(void){ UsartReceive_IDLE(&huart1);//自己添加一个函数,这就是中断,搬完以后,空闲中断 自己完成它  HAL_UART_IRQHandler(&huart1);}void UsartReceive_IDLE(UART_HandleTypeDef *huart)  {      uint32_t temp;      if
发表于 2019-06-15

STM32CubeMX学习教程之五:PWM实现呼吸灯效果

软件:STM32CubeMX V4.25.0  System Workbench V2.4固件库版本:STM32Cube FW_F1 V1.6.1硬件:OneNet 麒麟座V2.3在STM32CubeMX中新建项目,选择正确的MCU型号 首先设置RCC和SYS,如下图 然后根据板子实际情况设置时钟(麒麟座外部晶振是12M,STM32F103x的最高主频是72M),如下图设置PC7 管脚为TIM3_CH2, 即定时器TIM3的Channel2然后设置TIM3的Channel2为PWM Generation CH2 从上一篇博文我们知道TIM3是挂在APB1总线上的,看时钟树我们知道
发表于 2019-06-15
STM32CubeMX学习教程之五:PWM实现呼吸灯效果

小广播

何立民专栏

单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2019 EEWORLD.com.cn, Inc. All rights reserved