STM32使用QT上位机下载程序,bootload+app

说明

使用qt编写上位机,电脑通过USB转串口工具与单片机连接,使用自定义协议进行bin文件传送image.png

协议

image.png总共有四帧协议:
type1:上位机点击“下载文件”按钮后,会连续发送这帧命令,查询STM32是否准备好
type10:上位机下发文件,一帧最多下发4096字节数据
type10:在APP程序中STM32接受到type1帧后软件复位进入bootload程序,bootload程序接收到type1帧后发送type2帧告诉上位机准备完成,等待下发文件
type20:STM32接收到一帧数据后写入到FLASH,返回成功或失败响应

STM32程序部分

bootload程序

程序跳转部分代码

#define  APP_ADDR  0x8020000   /* 应用程序首地址定义 */ 

static void iap_load_app(void) 
{
	void (*AppMemBootJump)(void); /* 声明一个函数指针 */
	
	/* 关闭全局中断 */
	DISABLE_INT();
	
	/* 关闭滴答定时器,复位到默认值 */
	SysTick->CTRL = 0;
	SysTick->LOAD = 0;
	SysTick->VAL = 0;
	
	/* 设置所有时钟到默认状态,使用 HSI 时钟 */
	HAL_RCC_DeInit();
	
	/* 关闭所有中断,清除所有中断挂起标志 */
	for (int i = 0; i < 8; i++)
	{
		NVIC->ICER[i]=0xFFFFFFFF;
		NVIC->ICPR[i]=0xFFFFFFFF;
	}
	
	/* 使能全局中断 */
	ENABLE_INT();
	
	/* 设置重映射到系统 Flash */
	__HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH();

	/* 跳转到APP程序,首地址是 MSP,地址+4 是复位中断服务程序地址 */
	AppMemBootJump =  (void (*)(void)) (*((uint32_t *) (APP_ADDR + 4)));
	
	/* 设置朱堆栈指针 */
	__set_MSP(*(uint32_t *)APP_ADDR);
	
	/* 在 RTOS 工程,这条语句很重要,设置为特权级模式,使用 MSP 指针 */
	__set_CONTROL(0);
	
	/* 跳转至APP */
	AppMemBootJump();
	
	/* 跳转成功的话,不会执行到这里,用户可以在这里添加代码 */
	while (1)
	{
		
	}
}

协议解析和程序写入

/* 进入主程序循环体 */
	while (1)
	{
		static int tim_100ms = 0;
		static int mode = 0;
		static int tim_1000ms = 0;
		uint8_t com6_rx_data = 0;
		uint16_t crc = 0;
		
		if (tim_1ms_flag == 1)  /* 1ms执行一次 */
		{
			tim_1ms_flag = 0;
			
			if (mode == 0) 
			{
				if (++tim_1000ms > 1000) iap_load_app(); /* 超时未进入下载模式,跳转到APP */
			}
			
			if (++tim_100ms > 100)  /* 指示灯闪缩 */
			{
				tim_100ms = 0;
				HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);
			}
		}
		
		while(comGetChar(COM6, (uint8_t*)&com6_rx_data)) 
		{
			tRx.buf[tRx.cnt++] = com6_rx_data;

			switch (tRx.cnt) 
			{
				case 1: {
					if (com6_rx_data != 0xEE) tRx.cnt = 0;
				} break;
				
				case 2: {
					if (com6_rx_data != 0xAA) tRx.cnt = 0;
				} break;
				
				case 7: {
					tRx.type = tRx.buf[2];
					tRx.num = (tRx.buf[3] << 8) + tRx.buf[4];
					tRx.lenght = (tRx.buf[5] << 8) + tRx.buf[6];
				} break;
			}
			
			if (tRx.cnt == tRx.lenght + 9)  /* 一帧数据 */
			{
				tRx.cnt = 0;
				crc = CRC16_Modbus(tRx.buf, tRx.lenght + 7); /* 校验帧头+帧类型+帧号+数据长度+数据 */
				
				if (crc == (tRx.buf[tRx.lenght + 9 - 2] << 8) + tRx.buf[tRx.lenght + 9 - 1]) /* 校验成功 */
				{
					if (tRx.type == 0x01)
					{
						mode = 1; /* 进入下载模式 */ 
						send_ack(0x10, 0x00, 0x00, 0x00); /* boot程序接收准备应答 */
					}
					else if (tRx.type == 0x02)
					{
						if (bsp_WriteCpuFlash(add, tRx.buf + 7, tRx.lenght) == 0)
						{
							add += tRx.lenght;
							send_ack(0x20, tRx.num, 0x01, 0x01); /* 文件下载成功应答 */
						}
						else 
						{
							send_ack(0x20, tRx.num, 0x01, 0x02); /* 文件下载失败应答 */
						}
						
						if (tRx.num == 0xffff) 
						{
							tim_1000ms = 0;
							mode = 0;
						}
					}
				}
			}
		}
	}

协议应答

/*
*********************************************************************************************************
*    功能说明: 应答
*********************************************************************************************************
*/
static void send_ack(uint8_t type, uint16_t num, uint16_t length, uint8_t data) 
{
	uint8_t send_buf[20] = {0};
	uint8_t i =0;
	
	send_buf[i++] = 0xEE;
	send_buf[i++] = 0xAA;
	send_buf[i++] = type;
	send_buf[i++] = num>>8;
	send_buf[i++] = num;
	send_buf[i++] = length>>8;
	send_buf[i++] = length;
	
	for (int a=0; a<length; a++)
	{
		send_buf[i++] = data;
	}

	uint16_t crc = CRC16_Modbus(send_buf, i);

	send_buf[i++] = crc>>8;
	send_buf[i++] = crc;

	comSendBuf(COM6, (uint8_t *)&send_buf, i);
}

APP程序

接收进入b

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值