STM32 无线下载程序(非IAP)

来源:互联网 发布:js map参数传递 编辑:程序博客网 时间:2024/06/05 10:40

        STM32利用串口下载是最便宜的一种下载方式,但是利用串口下载需要操作STM32的RST、Boot0两个引脚,在此需要单独加一个下载辅助控制器(STC15F104)。  要无线下载STM32程序需知道在有线情况下串口如何下载程序,简要来说下载完整过程简要如下:

   1.将Boot0拉高,接着复位STM32

   2.PC端串口会不断发送0x7F,与STM32握手(STM32自适应波特率),STM32收到7F后,会返回 0x79 0xF1

   3.串口下载软件识别返回的字节会会接着进一步发送其他控制指令,就这样PC端与STM端不断收发即完成了下载程序。

   4.在下载完后,将Boot0置低,接着RST复位STM32.

无线下载时只需注意到两次复位即Boot0电平变化即可,所以简单来说只需:辅助单片机STC监测串口中有无连续5个以上的 0x7F(也可以多几个),将Boot0拉高,立即复位STM32,接着STC等待串口中无数据后再将Boot0拉低,接着复位STM32即可。

  无线串口利用ESP8266  的透传模式,即A端发什么,B端就收什么(A、B两者能互发),由于ESP8266断电后会自动关闭透传模式,故每次上电时需要STC单片机初始化下ESP8266为透传模式。无线下载机构如下(PC端也需上电初始化为透传模式):

STC主要电路:

 

PC端串口下载软件:

 

STC程序部分:

// STC15F104  程序  for STM32 Download
//   STM32下载串口为偶校验
// 模拟串口设置为115200bps  偶校验
// ESP8266wifi为STA模式

// PC端8266为AP模式,需首次设置AT+CWSAP="STM32Download","Download01",7,3    掉电仍保存

//PC端的8266需AT+CIPSTART="UDP","192.168.4.2",40000,40000,0  设置目标的发送地址,不一定时192.168.4.2,需先看下对方IP,一般无第三者加入此地址不会变的

// PC端再发送: AT+CIPMODE=1     AT+CIPSEND  两个指令即完成PC端的设置
//  从站端,下载目标端程序
//  目标开发板Boot0需下拉,否则初始开机时程序非正常启动,且无法正常发送初始指令给8266模块
#include "reg51.h"
#include"intrins.h"
#define BAUD  0xFFA0 // 115200 @33.1776Mhz,下载时需注意勾选此频率
//0xFE80   // 9600bps @ 11.0592MHz

 

sfr AUXR = 0x8E;   //辅助寄存器,设定T0工作速度,0--1/12,1--1T

sbit RXB = P3^0;   //define UART TX/RX port

sbit TXB = P3^1;

sbit RST = P3^4;  //复位 低电平有效

sbit Boot0 =P3^5; //启动选择,高 下载程序,低 正常运行程序

//sbit SW = P3^3;  //开关,判断是否需初始化wifi

typedef bit BOOL;

typedef unsigned char BYTE;

typedef unsigned int WORD;

 

BYTE TBUF,RBUF;//发送/接收 寄存器

BYTE TDAT,RDAT;//发送/接收 数据

BYTE TCNT,RCNT;//发送/接收 计数器

BYTE TBIT,RBIT;//发送/接收 位数

BOOL TING,RING;//发送/接收 开始标志

BOOL TEND,REND; //发送/接收 结束标志

BYTE  Parity; //计算校验位

void UART_INIT();
void UART_SENDBYTE(BYTE);
 void  UART_SENDSTRING( BYTE *str);
 
BYTE t, r;

BYTE buf[16];

void Delay1ms()  //@33.1776Mhz
{
 unsigned char i, j;

 _nop_();
 _nop_();
 _nop_();
 i = 17;
 j = 150;
 do
 {
  while (--j);
 } while (--i);
}

void Delayms(unsigned char i)
{
   while(i--)
   {
   Delay1ms();
   }

}
void main()

{
   BYTE Download=0;
   BYTE Dend_CNT=0;//下载结束判断计数 
  TMOD = 0x00;    //T0 16bit reaload Mode   

      AUXR = 0x80;    //T0--1T    

 

      TL0 = BAUD;

      TH0 = BAUD>>8;  

 

 TR0 = 1;  //T0计时开始  

   ET0 = 1;  //T0开中断  

 PT0 = 1;  //T0高优先级  

 EA = 1;

 RST=1;Boot0=0; //IO初始化

 UART_INIT();

 //while(1)
 //{
//   TEND = 0;   TBUF = 0x7F;   TING = 1;   //发送0x7F
//   TEND = 0;   TBUF = 0x7E;   TING = 1;   //发送0x7F
//   TEND = 0;   TBUF = 0x7D;   TING = 1;   //发送0x7F
//   TEND = 0;   TBUF = 0x7C;   TING = 1;   //发送0x7F
//   Delayms(50);
//if( REND)
//{ REND = 0;
// TEND = 0;   TBUF = RBUF;   TING = 1;   //发送0x7F
// while(!TEND);}
//}
 

 
 //AT+UART=115200,8,1,2,0    偶校验
 //如果一组给定数据位中 1 的个数是奇数,那么偶校验位就置为 1,从而使得总的 1 的个数是偶数。如果给定一组数据位中 1 的个数是偶数,那么奇校验位就置为 1,使得总的 1 的个数是奇数。偶校验实际上是循环冗余校验的一个特例,通过多项式 x + 1 得到 1 位 CRC

 
 //将8266建立透传:CIPMUX=0 单链接模式  CIPMODE=1 透传模式,8266设置透传后重启后为0,有时AT指令不能被识别,需发送“+++”终止透传
 //  CWMODE=2   CWSAP="STM32Download","Download01",7,3      网络建立只需初次设定即可,在此不再上电设置
 //ATE0 
 //AT+CIPSTART="UDP","192.168.4.2",40000,40000,0
 //AT+CIPSTART="UDP","192.168.4.1",40000,40000,0
 //AT+CIPMODE=1
 //AT+CIPSEND

 Delayms(250); Delayms(250); Delayms(250); Delayms(250);
 Delayms(250); Delayms(250); Delayms(250); Delayms(250);
Delayms(250); Delayms(250); Delayms(250); Delayms(250);
Delayms(250); Delayms(250); Delayms(250); Delayms(250);
Delayms(250); Delayms(250); Delayms(250); Delayms(250);

 UART_SENDSTRING("AT+CIPSTART=\"UDP\",\"192.168.4.1\",40000,40000,0");//UART_SENDBYTE(0x0D);UART_SENDBYTE(0x0A);//换行符
 Delayms(30);
 UART_SENDSTRING("AT+CIPMODE=1");//UART_SENDBYTE(0x0D);UART_SENDBYTE(0x0A);//换行符
 Delayms(30);
 UART_SENDSTRING("AT+CIPSEND");//UART_SENDBYTE(0x0D);UART_SENDBYTE(0x0A);//换行符


      while (1)

      {                                     
//检测串口发送连续的 0x7F   当有连续收到5个时则开启下载:置Boot0为1,延时10ms,100ms RST复位低电平
//下载完:等待100ms无收到数据则认为下载完毕,Boot0=0,RST复位MCU

           if (REND)

           {

                REND = 0;
    Dend_CNT=0;
    if( RBUF == 0x7F && !Download )  {
     r++;
     if(r>5) //大于5个 0x7F  开启下载
     {
      Download=1;
      Boot0=1;Delayms(10); //置Boot0为1
      RST=0;Delayms(100);RST=1;  //复位延时100ms
     }
    }
     else r=0;
    
              //  buf[r++ & 0x0f] = RBUF;

           }
   else if( Download ) //无数据接收  则循环等待200ms,再无数据则判断下载完成
   {
     Delayms(10);
     Dend_CNT++;
     if(Dend_CNT >80) {Download=0; Dend_CNT=0;
     Boot0=0;
     RST=0;Delayms(100);RST=1;  //复位延时100ms
     }
   }
/*           if (TEND)

           {

                if (t != r)

                {

                    TEND = 0;
if( buf[t++ & 0x0f] ==0x7F ) TBUF =0x91;
 else TBUF = buf[(t-1) & 0x0f];
                    //TBUF = buf[t++ & 0x0f];

                    TING = 1;

                }

           }
*/
      }

/*  while(1)

 {

 if(TEND)

{

TEND = 0;

TBUF = 0xba;

TING = 1;

}

 }*/

}

//-----------------------------------------

//Timer interrupt routine for UART

void tm0() interrupt 1 using 1

{

      if (RING)

      {

           if (--RCNT == 0)

           {

                RCNT = 3;                   //reset send baudrate counter

                if (--RBIT == 0)

                {

                    RBUF = RDAT;              //save the data to RBUF

     RING = 0;

     REND = 1;

    }

   else

   {

   if( RBIT != 1 )
     {
   RDAT >>= 1;

   if(RXB)RDAT|=0x80;
     }
    else{//检查校验位
     
      }
   }

  }

 }

else if(!RXB)

{

RING = 1;

RCNT = 4;

RBIT = 10;

}

if (--TCNT == 0)

{

    TCNT = 3;                         //reset send baudrate counter

    if (TING)                         //judge whether sending

    {

         if (TBIT == 0)

         {

             TXB = 0;                  //send start bit

             TDAT = TBUF;      //load data from TBUF to TDAT

             TBIT = 10;                //initial send bit number (8 data bits + 1 stop bit+1 parity bit)

    Parity = 0;
         }

     else

         {

             TDAT >>= 1;             //shift data to CY

             if (--TBIT == 0)

             {

                  TXB = 1;

                  TING = 0;           //stop send

                  TEND = 1;           //set send completed flag

              }
              else

              {

                  TXB = CY;           //write CY to TX port

          Parity += (CY&0xFF);    //校验位
     
      if( TBIT ==2 ) TDAT = Parity;
               }

          }

 }

}

}

 //--------------------------------------

 //initial UART module variable

 

 void UART_INIT()

 {

 TING = 0;

RING = 0;

TEND = 1;

REND = 0;

TCNT = 0;

RCNT = 0;

Parity = 0;

 }

 
 void UART_SENDBYTE(BYTE Ch)
 {
 
  while(!TEND);  //等待发送完
 
  TEND = 0;   TBUF = Ch;   TING = 1; //准备数据
   
 }
 
 void  UART_SENDSTRING( BYTE *str)
 {
  while(*str !=0)
  {UART_SENDBYTE(*str);
  str++;}
  UART_SENDBYTE(0x0D);UART_SENDBYTE(0x0A);
 }

 

0 0
原创粉丝点击