完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
单片机需要显示多张图片,以及显示中文,但数据量太大,单片机内部的ROM不够,只能存在外部flash中,所以需要将大量的数据写入flash中。最近一直在查阅资料,怎么更新外部flash中的数据。
方法一:将数据存入ROM中,程序执行时,读取ROM中的数据,写入flash。这种方法一次性写入的数据比较少,若是下载一次程序,写入一次,再改动flash地址,再下载程序,再写入~~~~~说不下去了。 方法二:使用串口调试助手,将图片数据制作成bin文件,发送给单片机,单片机在串口中断中写入flash。当STM32的串口总线被其他设备占用时,这种方法就行不通了。 方法三:使用USB模拟串口,再如方法二的步骤刷新flash数据。 本次内容讲述的就是串口总线被其他设备占用,使用方法三刷新flash数据。我也会简单介绍一下怎么使用USB模拟串口回显数据。 W25XXX写入数据 flash内部只能由1变为0,所以每次写入数据时,需要先将flash擦除。 扇区擦除:每个扇区4K大小,擦除的最小单位。 块擦除:每个块64K大小。 片擦除:将整个flash擦除。 步骤如下 1.打开cube软件 2.配置USB 3.配置USB_DEVICE 4.时钟那些不作介绍,直接生成文件。 打开工程 1.打开u***s_cdc_if.c文件 2.在接收函数里加上发送数据函数,贴上代码 static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len) { /* USER CODE BEGIN 6 */ USBD_CDC_SetRxBuffer(&hU***DeviceFS, &Buf[0]); USBD_CDC_ReceivePacket(&hU***DeviceFS); USBD_CDC_SetTxBuffer(&hU***DeviceFS, &Buf[0], *Len); USBD_CDC_TransmitPacket(&hU***DeviceFS); return (USBD_OK); /* USER CODE END 6 */ } 3.如果使用串口回显,就不需要更改其他的了,下载程序。打开串口调试助手发送数据,结果如下图 64字节以内,发送什么数据,返回的也是什么数据。因为USB一次性只能接收64字节数据,所以我发送70字节的数据,只返回了64字节。发送一大串数据,也会返回,只不过我没有仔细核对。 改动程序,可以返回大量数据 1.改动接收缓冲区大小 #define APP_RX_DATA_SIZE 256 //将1000改为256 #define APP_TX_DATA_SIZE 1000 2.修改CDC_Receive_FS函数 uint16_t Data_Len, temp, timeout; //定义的全局变量 static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len) { Data_Len +=*Len; if(Data_Len { USBD_CDC_SetRxBuffer(&hU***DeviceFS, UserRxBufferFS + Data_Len); //设置下一次接收数据的位置 USBD_CDC_ReceivePacket(&hU***DeviceFS); //准备接收数据 } else //接收缓冲区已满 { timeout = 0xffff; temp = !(Data_Len%64); //判断长度是否为64整数倍 while( CDC_Transmit_FS(UserRxBufferFS, Data_Len - temp) != USBD_OK && timeout--); if(temp) //当发送数据为64整数倍时,无法发送成功,故分成2次发送 { while( CDC_Transmit_FS(UserRxBufferFS + Data_Len -1, temp) != USBD_OK && timeout--); } //发送完毕,再次设置 Data_Len = 0; USBD_CDC_SetRxBuffer(&hU***DeviceFS, UserRxBufferFS + Data_Len); //设置下一次接收数据的位置 USBD_CDC_ReceivePacket(&hU***DeviceFS); //准备接收数据 } return (USBD_OK); /* USER CODE END 6 */ } 当发送的数据为64的整数倍时,需要将数据分为两次发送(经其他博主验证) 3.下载程序,查看结果 设置的缓冲区大小为256,当缓冲区存满了数据,才会输出。 步入正题,使用USB虚拟串口刷新flash数据 1.每次上电,初始化时,就将flash整片擦除。 2.每满256字节时,就写入一次数据。 3.修改CDC_Receive_FS函数 uint32_t FlashAdd = 0x00000; static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len) { //将已接收数据长度赋值给USB_S.ReLen USB_S.ReLen += *Len; //判断是否有结束标志以及接收数据长度是否达到UserRxBufferFS长度上限 if( USB_S.ReLen { //设置下一次接收数据的位置 USBD_CDC_SetRxBuffer(&hU***DeviceFS, UserRxBufferFS + USB_S.ReLen); USBD_CDC_ReceivePacket(&hU***DeviceFS); //准备接收数据 } else //长度达到,或者检测到标志位,触发数据输出 { SPI_FLASH_PageWrite(UserRxBufferFS, FlashAdd, 256); FlashAdd += 256; USB_S.ReLen = 0; USBD_CDC_SetRxBuffer(&hU***DeviceFS, UserRxBufferFS); USBD_CDC_ReceivePacket(&hU***DeviceFS); } return (USBD_OK); } 4.打开Image2LCD制作bin文件 5.打开串口调试助手,写入数据 换了个串口调试助手,这个是正点原子的,这一个串口调试助手末尾会发0X0D,0X0A,如有需要可以以这两个数据写协议,或者自己写一个协议,并在程序中进行校验数据是否写入正确。 flash驱动文件在上一篇文章,也可以直接找野火的例程。 结尾 发送数据时,有时候开头的数据写不进flash,暂未找到原因。 |
|
|
|
只有小组成员才能发言,加入小组>>
3280 浏览 9 评论
2958 浏览 16 评论
3460 浏览 1 评论
9004 浏览 16 评论
4052 浏览 18 评论
1115浏览 3评论
573浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
571浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2303浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1859浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-25 15:17 , Processed in 1.209124 second(s), Total 80, Slave 60 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号