[MM32硬件] 【灵动微电子MM32F5330测评】3.通过USART和上位机通信,向SPI_FLASH写入接收的数据

[复制链接]
 楼主| sujingliang 发表于 2024-6-25 16:22 | 显示全部楼层 |阅读模式
本帖最后由 sujingliang 于 2024-6-25 19:44 编辑

前言
MM32F5330评估板上搭载有25q80是一个1M BYTE的flash,还有多个UART、USART、LPUART资源。所以可以实现串口和PC机通讯,然后将获得的信息写入FLASH。用框图示意如下: 图片1.png

所有示例中printf重定向到UART1(PB6),所以UART1做DEBUG UART再好不过。USART1中用到了RX(PA10)。

PYTHON上位机
  1. import serial
  2. import struct
  3. import time
  4.   
  5. # 串口配置  
  6. SERIAL_PORT = 'COM14'  # 或者 '/dev/ttyUSB0' 在Linux/Mac上  
  7. BAUDRATE = 115200  
  8.   
  9. # 创建串口连接  
  10. ser = serial.Serial(SERIAL_PORT, BAUDRATE, timeout=1)  
  11.   
  12. # 固定的4位字符  
  13. fixed_header = bytes([0xAA, 0x55, 0xAA, 0x55])

  14. fixed_tailer = bytes([0x0D, 0x0A])

  15. #发送批次
  16. transmission_count=0
  17. #发送长度
  18. data_length=0



  19. # 打开二进制文件  
  20. with open('gb2312_80.bin', 'rb') as file:  
  21.     # 读取并发送数据,直到文件结束  
  22.     while True:  
  23.         # 读取128字节(如果文件末尾不足128字节,则读取剩余部分)  
  24.         data = file.read(128)
  25.         data_length=len(data)
  26.         # 如果没有数据可读(文件结束),则退出循环  
  27.         if not data:  
  28.             break  
  29.          
  30.         # 拼装message
  31.         message = struct.pack('!4sHH128s2s', fixed_header, transmission_count, data_length, data,fixed_tailer)
  32.          
  33.         # 通过串口发送数据
  34.         print(data)
  35.         ser.write(message)  
  36.         transmission_count+=1
  37.         # 休眠0.1秒  
  38.         time.sleep(0.1)  
  39.   
  40. # 关闭串口连接  
  41. ser.close()  
  42. file.close()
  43. print("Data sending completed.")
PYTHON程序读取gb2312_80.bin文件,按照自定义报文格式发送给MCU。
1、报文格式
95309667a79894a143.png

2、用了struct.pack进行打包
3、import serial,用serial负责串口


MCU端程序
0、接收数据结构体
  1. typedef struct
  2. {
  3.     uint8_t Buffer[138];        //4+2+2+128+2
  4.     uint16_t Length;
  5.     uint16_t CurrentCount;
  6.     uint8_t CompleteFlag;
  7. } USART_RxTx_TypeDef;

1、USART阻塞式接收上位机信息
  1. void USART_Polling_Sample(void)
  2. {
  3.     uint8_t Data = 0;
  4.     uint16_t i = 0;
  5.     uint8_t offset;
  6.     uint8_t buff[128];
  7.     memset(buff,0,128);

  8.     //printf("\r\nTest %s", __FUNCTION__);

  9.     USART_Configure(115200);

  10.     while (1)
  11.     {
  12.         if (SET == USART_GetFlagStatus(USART1, USART_FLAG_RXNE))
  13.         {
  14.             Data = USART_ReceiveData(USART1);

  15.             USART_RxStruct.Buffer[USART_RxStruct.CurrentCount++] = Data;

  16.             if(USART_RxStruct.Buffer[USART_RxStruct.CurrentCount-2]=='\xd'&&  \
  17.             USART_RxStruct.Buffer[USART_RxStruct.CurrentCount-1]=='\xa')
  18.              {

  19.                    if(strncmp((char*)USART_RxStruct.Buffer,"test",4)==0){
  20.                      printf("received test\r\n");
  21.                      SPI_Master_FLASH_Polling_Sample();
  22.                    }
  23.                    else if(strncmp((char*)USART_RxStruct.Buffer,"help",4)==0){
  24.                      //向UART1输出
  25.                      printf("help command list\r\n");
  26.                       printf("1.abc\r\n");
  27.                    }
  28.                    else if(strncmp((char*)USART_RxStruct.Buffer,"\xAA\x55\xAA\x55",4)==0){
  29.                       //输入为0xAA55AA55时,为写flash命令
  30.                       processFlashCommand((uint8_t*)(USART_RxStruct.Buffer+4));                //传递第5个字节指针地址
  31.                    }
  32.                    else if(strncmp((char*)USART_RxStruct.Buffer,"read",4)==0){
  33.                        offset=USART_RxStruct.Buffer[4]-48;        //ASCII->数字
  34.                        memset(buff,0,128);
  35.                                                                
  36.                       SPI_FLASH_FastRead(offset*128,buff,128);
  37.                       for(i=0;i<128;i++)
  38.                       {
  39.                            if (0 == (i % 8))
  40.                           {
  41.                                 printf("\r\n");
  42.                           }
  43.                           printf("0x%02x ",buff[i]);
  44.                        }
  45.                      }
  46.                      else{
  47.                           //向UART1输出
  48.                           printf("Not Command! you can send help\r\n");
  49.                      }
  50.                                                         
  51.                           USART_RxStruct.CurrentCount=0;
  52.                           USART_RxStruct_ClearBuffer();
  53.                   }
  54.           }

  55.      }
  56. }

接收的信息如果末尾是0x0D,0x0A(回车换行),判断是否带有命令字段:test、help、\xAA\x55\xAA\x55、read
如果头4个字符为0xAA,0x55,0xAA,0x55,即为PYTHON上位机发来的信息,跳转到processFlashCommand处理


2、processFlashCommand处理程序
  1. void processFlashCommand(uint8_t* rxData)
  2. {
  3.         uint16_t offset,length;
  4.         uint16_t i=0;
  5.         
  6.         uint8_t *pBuff=rxData;
  7.         offset=pBuff[0];
  8.         offset=offset<<8;
  9.         offset|=pBuff[1];
  10.         
  11.         length=pBuff[2];
  12.         length=length<<8;
  13.         length|=pBuff[3];

  14.         //每次发送128个字节,发送32次为4k,1个扇区4k,需要先擦除扇区在写入
  15.         if(offset%32==0) SPI_FLASH_SectorErase(offset/32);        
  16.         //写flash
  17.         SPI_FLASH_PageProgram(offset*128,pBuff+4,length);
  18.         printf("write flash:offset:%d,length:%d\r\n",offset*128,length);

  19. }


写flash用了SPI_FLASH_PageProgram函数,在SPI例程里有这个函数。
注意写之前一定要先对扇区做擦除操作,由于一个扇区是4k,而每次传过来的数据是128,所以每32次接收执行一次擦除扇区。


总结
1、还提供了接收串口"read"命令,格式是:
read0:可以显示flash中0-127地址的数据;
read1:可以显示flash中128-255地址的数据;
以此类推,用来查看写的数据是否正确。下面演示的是PC通过USART1发送read0,通过UART1接收read命令的返回结果,通过结果与原文件比对,可知写flash是否成功。
土.png
2、前面所做,相当于在FLASH中烧录了一个字库文件gb2312_80.bin,为以后用LCD显示汉字做好准备。







评论

赞  发表于 2024-6-25 17:10
forgot 发表于 2024-6-25 17:11 | 显示全部楼层
我的板子也收到了,还没来得及测试
Bowclad 发表于 2024-6-27 18:08 | 显示全部楼层
还有板载flash不错嘛
地瓜patch 发表于 2024-6-28 14:44 | 显示全部楼层
片内有几个flash分区,
您需要登录后才可以回帖 登录 | 注册

本版积分规则

84

主题

147

帖子

3

粉丝
快速回复 返回顶部 返回列表