上位机 C#
下位机 STM32F407
实现目标 将.bin文件下载到片外flash中
实现原理 上位机一次性将.bin读入buf 然后分包串口下载 等待下位机返回继续下一包
下位机部分代码
/*
************************************
*GB2312中文字库下载 下位机部分
*描述 通过串口接收上位机发送的字库数据校验通过后写入外置flash
***********************************
*/
#include "fontsLoad.h"
#include "delay.h"
#include "w25qxx.h"
#include "GUI.h"
#include "led.h"
#include "usart.h"
#include "USART6.h"
#include "EmWinHZFont.h"
#include "str.h"
#include "ExtRamConfig.h"
//字库存放起始地址
#define FONT_INFO_ADDR 1024*1024*12
//#define FONTS_BUF_SIZE 4096
//uint8_t FontsRXBuf0[FONTS_BUF_SIZE];
//uint8_t FontsRXBuf1[FONTS_BUF_SIZE];
static uint8_t buf_select=0;
static uint8_t err=0;
static uint32_t buf0data_size=0;
static uint32_t buf0Start=0;
static uint32_t buf0p=0;
static uint32_t buf0End=0;
static uint32_t buf1data_size=0;
static uint32_t buf1Start=0;
static uint32_t buf1p=0;
static uint32_t buf1End=0;
/*串口接收中断中调用*/
void FontsDataInBuf(uint8_t data)
{
if(buf_select==0)
{
if(0==buf0Start)
{
if(data==0xfe)
{
buf0Start = 1;
buf0p = 0;
FontsRXBuf0[buf0p++] = data;
}
}
else
{
if(buf0data_size==0)
{
buf0data_size = 1;
FontsRXBuf0[buf0p++] = data;
}
else if(buf0data_size==1)
{
FontsRXBuf0[buf0p++] = data;
buf0data_size = FontsRXBuf0[2]<<8| FontsRXBuf0[1];
}
else
{
if(buf0p<buf0data_size)
{
FontsRXBuf0[buf0p++] = data;
}
if(buf0p>=buf0data_size)
{
buf0End = 1;
buf_select = 1;
if(err==0)
{
USART6_sendonebyte(0x55);
}
else
{
USART6_sendonebyte(0xAA);
}
}
}
}
}
else
{
if(0==buf1Start)
{
if(data==0xfe)
{
buf1Start = 1;
buf1p = 0;
FontsRXBuf1[buf1p++] = data;
}
}
else
{
if(buf1data_size==0)
{
buf1data_size = 1;
FontsRXBuf1[buf1p++] = data;
}
else if(buf1data_size==1)
{
FontsRXBuf1[buf1p++] = data;
buf1data_size = FontsRXBuf1[2]<<8| FontsRXBuf1[1];;
}
else
{
if(buf1p<buf1data_size)
{
FontsRXBuf1[buf1p++] = data;
}
if(buf1p>=buf1data_size)
{
buf1End = 1;
buf_select = 0;
if(err==0)
{
USART6_sendonebyte(0x55);
}
else
{
USART6_sendonebyte(0xaa);
}
}
}
}
}
}
/*擦除外部flash准备保存字库的区域*/
void ClearFontFlashRoom()
{
u16 i,j;
u8 percent=0;
u32 FontSecSize=0;
FontSecSize = (ftinfo.ugbksize+ftinfo.gbk12size+ftinfo.gbk16size+ftinfo.gbk24size)/4096+1;
for(i=0;i<FontSecSize;i++) //先擦除字库区域,提高写入速度
{
W25QXX_Read(FontsRXBuf0,((FONT_INFO_ADDR/4096)+i)*4096,4096);
for(j=0;j<4096;j++)
{
if(FontsRXBuf0[j]!=0XFF)break;
}
if(j!=4096)W25QXX_Erase_Sector((FONT_INFO_ADDR/4096)+i);
percent = 100*i/FontSecSize+1;
GUI_DispDecAt(percent,10,40,3);
}
}
u8 font_init(void)
{
u8 t=0;
//W25QXX_Init();
while(t<10)
{
t++;
W25QXX_Read((u8*)&ftinfo,FONT_INFO_ADDR,sizeof(ftinfo));
if(ftinfo.fontok==0XAA)break;
delay_ms(20);
}
if(ftinfo.fontok!=0XAA)return 1;
return 0;
}
u32 flashaddr = 0;
u32 offx=0;
_font_info ftinfo;
uint8_t FontUpdata()
{
u8 LoadEnd=0;
u32 allbtyes=0;
usart6_init(115200);
Usart6CallBack = FontsDataInBuf;
GUI_SetFont(&GUI_Font20_ASCII);
GUI_SetColor(GUI_WHITE);
GUI_SetBkColor(GUI_BLUE);
GUI_SetTextMode(GUI_TEXTMODE_NORMAL);
GUI_Clear();
ftinfo.ugbksize = 174344;
ftinfo.gbk12size = 574560;
ftinfo.gbk16size = 766080;
ftinfo.gbk24size = 1723680;
ftinfo.ugbkaddr=FONT_INFO_ADDR+sizeof(ftinfo);
flashaddr = ftinfo.ugbkaddr;
ftinfo.f12addr=ftinfo.ugbkaddr+ftinfo.ugbksize;
ftinfo.f16addr=ftinfo.f12addr+ftinfo.gbk12size;
ftinfo.f24addr=ftinfo.f16addr+ftinfo.gbk16size;
allbtyes = ftinfo.ugbksize+ftinfo.gbk12size+ftinfo.gbk16size +ftinfo.gbk24size;
GUI_DispStringAt("%",50,40);
GUI_DispStringAt("ClearFlash...",10,10);
ClearFontFlashRoom();
GUI_DispStringAt("Clear End ,Now You Can Start the Load APP!",10,70);
GUI_DispStringAt("%",50,130);
buf0data_size=0;
buf0Start=0;
buf0p=0;
buf0End=0;
buf1data_size=0;
buf1Start=0;
buf1p=0;
buf1End=0;
offx = 0;
buf_select = 0;
while(1)
{
delay_ms(10);
if(LoadEnd==0&&err==0)
{
if(buf0End==1)
{
if(0==Crc16_Modbus(FontsRXBuf0,buf0data_size))//CRC16校验 modbus
{
switch(FontsRXBuf0[3])
{
case 0x01:
W25QXX_Write(FontsRXBuf0+4,offx+flashaddr,buf0data_size-6);
offx +=buf0data_size-6;
buf0data_size=0;
buf0Start=0;
buf0p=0;
buf0End=0;
break;
case 0x02:
LoadEnd = 1;
break;
}
GUI_DispDecAt(100*offx/allbtyes,10,130,3);
}
else
{
err = 1;
}
}
if(buf1End==1)
{
if(0==Crc16_Modbus(FontsRXBuf1,buf1data_size))
{
switch(FontsRXBuf1[3])
{
case 0x01:
W25QXX_Write(FontsRXBuf1+4,offx+flashaddr,buf1data_size-6);
offx +=buf1data_size-6;
buf1data_size=0;
buf1Start=0;
buf1p=0;
buf1End=0;
break;
case 0x02:
LoadEnd = 1;
break;
}
GUI_DispDecAt(100*offx/allbtyes,10,130,3);
}
else
{
err = 1;
}
}
}
else
{
if(err==0)
{
ftinfo.fontok=0XAA;
W25QXX_Write((u8*)&ftinfo,FONT_INFO_ADDR,sizeof(ftinfo)); //保存字库信息
delay_ms(200);
GUI_SetBkColor(GUI_BLUE);
GUI_Clear();
GUI_SetColor(GUI_YELLOW);
GUI_SetFont(&GUI_FontHZ12);
GUI_DispStringAt("hello word",10,10);
GUI_DispStringAt("落霞与孤鹜齐飞",10,22);
GUI_DispStringAt("秋水共长天一色",10,34);
GUI_SetFont(&GUI_FontHZ16);
GUI_DispStringAt("hello word",10,50);
GUI_DispStringAt("中智胜安",10,66);
GUI_DispStringAt("娃哈哈哈哈",10,82);
GUI_SetFont(&GUI_FontHZ24);
GUI_DispStringAt("hello word",10,106);
GUI_DispStringAt("显示正常",10,130);
GUI_DispStringAt("康熙字典",10,154);
return 0;
}
else
{
GUI_DispStringAt("error!! please restart",10,150);
while(1);
}
}
}
}
上位机部分
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.IO.Ports;
using System.Text.RegularExpressions;
using System.Threading;
namespace FontDownload
{
public partial class Form1 : Form
{
private string PortName = "";
private int Baud = 9600;
private bool portStatus = true;
private byte[] SendBuffer = new byte[4096];
private byte[] ReciveBuffer = new byte[1024];
private int ReciveDataLen = 0;
/*CRC校验*/
public UInt32 crc16(byte[] data, int len)
{
UInt32 i = 0;
UInt32 j = 0;
UInt32 crc16 = 0xFFFF;
for (i = 0; i < len; i++)
{
crc16 ^= data[i];//CRC = BYTE xor CRC
for (j = 0; j < 8; j++)
{
//如果CRC最后一位为1,右移一位后carry=1,则将CRC右移一位后,再与POLY16=0xA001进行xor预算
if ((crc16 & 0x01) == 1)
{
crc16 = (crc16 >> 1) ^ 0xA001;
}
else//如果CRC最后一位为0,则只将CRC右移一位
{
crc16 = crc16 >> 1;
}
}
}
return crc16;
}
public Form1()
{
InitializeComponent();
}
private void comboBox1_Click(object sender, EventArgs e)
{
comboBox1.Items.Clear();
comboBox1.Items.AddRange(System.IO.Ports.SerialPort.GetPortNames());
}
/*串口号*/
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
PortName = comboBox1.Text;
}
/*波特率*/
private void comboBox2_SelectedIndexChanged(object sender, EventArgs e)
{
Baud = Convert.ToInt32( comboBox2.Text);
}
/*打开关闭串口*/
private void button1_Click(object sender, EventArgs e)
{
try
{
if (portStatus)
{
if (serialPort1.IsOpen)
{
serialPort1.Close();
}
serialPort1.BaudRate = Baud;
serialPort1.PortName = PortName;
serialPort1.StopBits = StopBits.One;
serialPort1.Parity = Parity.None;
serialPort1.DataBits = 8;
serialPort1.Open();
portStatus = false;
button2.Enabled = true;
}
else
{
serialPort1.Close();
portStatus = true;
}
if (portStatus)
{
button1.Text = "打开串口";
button1.ForeColor = Color.Black;
}
else
{
button1.Text = "关闭串口";
button1.ForeColor = Color.Red;
}
}
catch (Exception ee)
{
MessageBox.Show(ee.ToString());
}
}
/*串口接收*/
bool next = true;
bool loadstatus = false;
bool loadover = false;
bool err = true;
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
byte[] _data = new byte[serialPort1.BytesToRead];
serialPort1.Read(_data, 0, _data.Length);
for (int i = 0; i < _data.Length; i++)
{
ReciveBuffer[i] = _data[i];
}
ReciveDataLen = _data.Length;
if (_data[0] == 0x55)
{
next = true;
err = true;
}
else
{
next = false;
err = false;
}
}
/****************************************************
*
*
*
* ***********************************************/
private void Form1_Load(object sender, EventArgs e)
{
}
private void timer1_Tick(object sender, EventArgs e)
{
if (loadstatus)
{
if (offx > 1000)
{
progressBar1.Value = (int)((long)toffset * 1000 / offx);
label4.Text = toffset.ToString();
}
}
if (loadover == true)
{
loadover = false;
button2.Text = "开始下载";
button1.Enabled = true;
comboBox1.Enabled = true;
comboBox2.Enabled = true;
label4.Text = "";
loadstatus = false;
label4.Text = "下载完成 观察显示结果";
}
}
private void button2_Click(object sender, EventArgs e)
{
if (serialPort1.IsOpen)
{
if (loadstatus)
{
loadstatus = false;
button2.Text = "开始下载";
button1.Enabled = true;
comboBox1.Enabled = true;
comboBox2.Enabled = true;
label4.Text = "";
}
else
{
loadstatus = true;
loadover = false;
button2.Text = "停止下载";
button1.Enabled = false;
comboBox1.Enabled = false;
comboBox2.Enabled = false;
label4.Text = "开始进行中...";
Thread t = new Thread(new ThreadStart(FontUrtLoad));
t.Start();
timer1.Enabled = true;
}
}
else
{
MessageBox.Show("串口未打开");
}
}
private byte[] bytes = new byte[3500000];
private byte[] tbyte = new byte[2048];
private int toffset = 0;
private int offx = 0;
private void FontUrtLoad()
{
int len = 0;
UInt32 crcvalue = 0;
toffset = 0;
offx = 0;
FileStream stream0 = new FileStream("UN", FileMode.Open);
if (null != stream0)
{
int size = Convert.ToInt32(stream0.Length);
len = stream0.Read(bytes, offx, size);
offx += len;
}
FileStream stream1 = new FileStream("12", FileMode.Open);
if (null != stream1)
{
int size = Convert.ToInt32(stream1.Length);
len = stream1.Read(bytes, offx, size);
offx += len;
}
FileStream stream2 = new FileStream("16", FileMode.Open);
if (null != stream2)
{
int size = Convert.ToInt32(stream2.Length);
len = stream2.Read(bytes, offx, size);
offx += len;
}
FileStream stream3 = new FileStream("24", FileMode.Open);
if (null != stream3)
{
int size = Convert.ToInt32(stream3.Length);
len = stream3.Read(bytes, offx, size);
offx += len;
}
serialPort1.DiscardInBuffer();
serialPort1.DiscardOutBuffer();
while (toffset != offx)
{
if (toffset + 2042 < offx)
{
tbyte[0] = 0xfe;
tbyte[1] = Convert.ToByte(2048 & 0xff);
tbyte[2] = Convert.ToByte(2048>>8);
tbyte[3] = 0x01;
for (int i = 0; i < 2042; i++)
{
tbyte[i+4] = bytes[toffset + i];
}
crcvalue = crc16(tbyte, 2046);
tbyte[2046] = Convert.ToByte(crcvalue & 0xff);
tbyte[2047] = Convert.ToByte(crcvalue>>8);
serialPort1.Write(tbyte, 0, 2048);
toffset += 2042;
next = false;
while (!next)
{
if (!loadstatus)
{
loadover = true;
stream0.Close();
stream1.Close();
stream2.Close();
stream3.Close();
return;
}
Thread.Sleep(10);
}
}
else
{
int lse = offx - toffset;
tbyte[0] = 0xfe;
tbyte[1] = Convert.ToByte((lse+6)&0xff);
tbyte[2] = Convert.ToByte((lse+6)>>8);
tbyte[3] = 0x01;
for (int i = 0; i < lse; i++)
{
tbyte[i+4] = bytes[toffset + i];
}
crcvalue = crc16(tbyte, lse + 4);
tbyte[lse+4] = Convert.ToByte(crcvalue & 0xff);
tbyte[lse+5] = Convert.ToByte(crcvalue>> 8);
serialPort1.Write(tbyte, 0, lse + 6);
next = false;
while (!next)
{
if (!loadstatus)
{
loadover = true;
stream0.Close();
stream1.Close();
stream2.Close();
stream3.Close();
return;
}
Thread.Sleep(10);
}
toffset = offx;
//结束消息
Thread.Sleep(100);
tbyte[0] = 0xfe;
tbyte[1] = 6;
tbyte[2] = 0;
tbyte[3] = 0x02;
crcvalue = crc16(tbyte,4);
tbyte[4] = Convert.ToByte(crcvalue & 0xff);
tbyte[5] = Convert.ToByte(crcvalue >> 8);
serialPort1.Write(tbyte, 0, 6);
while (!next)
{
if (!loadstatus)
{
loadover = true;
stream0.Close();
stream1.Close();
stream2.Close();
stream3.Close();
return;
}
Thread.Sleep(10);
}
loadover = true;
}
}
stream0.Close();
stream1.Close();
stream2.Close();
stream3.Close();
}
}
}
代码包https://download.csdn.net/download/suxingtian/10408699