本帖最后由 sujingliang 于 2024-6-25 19:44 编辑
前言
MM32F5330评估板上搭载有25q80是一个1M BYTE的flash,还有多个UART、USART、LPUART资源。所以可以实现串口和PC机通讯,然后将获得的信息写入FLASH。用框图示意如下:
所有示例中printf重定向到UART1(PB6),所以UART1做DEBUG UART再好不过。USART1中用到了RX(PA10)。
PYTHON上位机
- import serial
- import struct
- import time
-
- # 串口配置
- SERIAL_PORT = 'COM14' # 或者 '/dev/ttyUSB0' 在Linux/Mac上
- BAUDRATE = 115200
-
- # 创建串口连接
- ser = serial.Serial(SERIAL_PORT, BAUDRATE, timeout=1)
-
- # 固定的4位字符
- fixed_header = bytes([0xAA, 0x55, 0xAA, 0x55])
- fixed_tailer = bytes([0x0D, 0x0A])
- #发送批次
- transmission_count=0
- #发送长度
- data_length=0
- # 打开二进制文件
- with open('gb2312_80.bin', 'rb') as file:
- # 读取并发送数据,直到文件结束
- while True:
- # 读取128字节(如果文件末尾不足128字节,则读取剩余部分)
- data = file.read(128)
- data_length=len(data)
- # 如果没有数据可读(文件结束),则退出循环
- if not data:
- break
-
- # 拼装message
- message = struct.pack('!4sHH128s2s', fixed_header, transmission_count, data_length, data,fixed_tailer)
-
- # 通过串口发送数据
- print(data)
- ser.write(message)
- transmission_count+=1
- # 休眠0.1秒
- time.sleep(0.1)
-
- # 关闭串口连接
- ser.close()
- file.close()
- print("Data sending completed.")
PYTHON程序读取gb2312_80.bin文件,按照自定义报文格式发送给MCU。
1、报文格式
2、用了struct.pack进行打包
3、import serial,用serial负责串口
MCU端程序
0、接收数据结构体- typedef struct
- {
- uint8_t Buffer[138]; //4+2+2+128+2
- uint16_t Length;
- uint16_t CurrentCount;
- uint8_t CompleteFlag;
- } USART_RxTx_TypeDef;
1、USART阻塞式接收上位机信息
- void USART_Polling_Sample(void)
- {
- uint8_t Data = 0;
- uint16_t i = 0;
- uint8_t offset;
- uint8_t buff[128];
- memset(buff,0,128);
- //printf("\r\nTest %s", __FUNCTION__);
- USART_Configure(115200);
- while (1)
- {
- if (SET == USART_GetFlagStatus(USART1, USART_FLAG_RXNE))
- {
- Data = USART_ReceiveData(USART1);
- USART_RxStruct.Buffer[USART_RxStruct.CurrentCount++] = Data;
- if(USART_RxStruct.Buffer[USART_RxStruct.CurrentCount-2]=='\xd'&& \
- USART_RxStruct.Buffer[USART_RxStruct.CurrentCount-1]=='\xa')
- {
- if(strncmp((char*)USART_RxStruct.Buffer,"test",4)==0){
- printf("received test\r\n");
- SPI_Master_FLASH_Polling_Sample();
- }
- else if(strncmp((char*)USART_RxStruct.Buffer,"help",4)==0){
- //向UART1输出
- printf("help command list\r\n");
- printf("1.abc\r\n");
- }
- else if(strncmp((char*)USART_RxStruct.Buffer,"\xAA\x55\xAA\x55",4)==0){
- //输入为0xAA55AA55时,为写flash命令
- processFlashCommand((uint8_t*)(USART_RxStruct.Buffer+4)); //传递第5个字节指针地址
- }
- else if(strncmp((char*)USART_RxStruct.Buffer,"read",4)==0){
- offset=USART_RxStruct.Buffer[4]-48; //ASCII->数字
- memset(buff,0,128);
-
- SPI_FLASH_FastRead(offset*128,buff,128);
- for(i=0;i<128;i++)
- {
- if (0 == (i % 8))
- {
- printf("\r\n");
- }
- printf("0x%02x ",buff[i]);
- }
- }
- else{
- //向UART1输出
- printf("Not Command! you can send help\r\n");
- }
-
- USART_RxStruct.CurrentCount=0;
- USART_RxStruct_ClearBuffer();
- }
- }
- }
- }
接收的信息如果末尾是0x0D,0x0A(回车换行),判断是否带有命令字段:test、help、\xAA\x55\xAA\x55、read
如果头4个字符为0xAA,0x55,0xAA,0x55,即为PYTHON上位机发来的信息,跳转到processFlashCommand处理
2、processFlashCommand处理程序
- void processFlashCommand(uint8_t* rxData)
- {
- uint16_t offset,length;
- uint16_t i=0;
-
- uint8_t *pBuff=rxData;
- offset=pBuff[0];
- offset=offset<<8;
- offset|=pBuff[1];
-
- length=pBuff[2];
- length=length<<8;
- length|=pBuff[3];
- //每次发送128个字节,发送32次为4k,1个扇区4k,需要先擦除扇区在写入
- if(offset%32==0) SPI_FLASH_SectorErase(offset/32);
- //写flash
- SPI_FLASH_PageProgram(offset*128,pBuff+4,length);
- printf("write flash:offset:%d,length:%d\r\n",offset*128,length);
- }
写flash用了SPI_FLASH_PageProgram函数,在SPI例程里有这个函数。
注意写之前一定要先对扇区做擦除操作,由于一个扇区是4k,而每次传过来的数据是128,所以每32次接收执行一次擦除扇区。
总结
1、还提供了接收串口"read"命令,格式是:
read0:可以显示flash中0-127地址的数据;
read1:可以显示flash中128-255地址的数据;
以此类推,用来查看写的数据是否正确。下面演示的是PC通过USART1发送read0,通过UART1接收read命令的返回结果,通过结果与原文件比对,可知写flash是否成功。
2、前面所做,相当于在FLASH中烧录了一个字库文件gb2312_80.bin,为以后用LCD显示汉字做好准备。
|