打印
[51单片机]

STC单片机串口下载的灵活运用

[复制链接]
900|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 逍遥派掌门 于 2015-11-26 23:57 编辑

STC单片机的串口下载无疑是非常方便的,既节省了专用下载器的花费,又不占用资源,这点秒杀AVR单片机。

但它有一个稍麻烦的地方:每次下载前需要对单片机进行手动复位。

我们利用STC提供的寄存器ISP_CONTR (有的型号是 IAP_CONTR,这个寄存器的定义要参看具体的datasheet)搞点花样,把手动的复位变成自动的复位。

这个只要在单片机的软件上增加一定的代码就可以实现了,不用改动任何的硬件,安全可靠哦。

先上Turbo51的代码:
Program main;

{$IDATA}    { 申请使用IDATA}

Const
{与STC12C5604AD有关}
      SWBS  = $40;
      SWRST = $20;


     
      BaudRate           = 9600;                {通信用的波特率}
      oscll              = 11059200;           {晶振频率}

      BaudRateTimerValue = Byte (- oscll div 12 div 32 div BaudRate);

      Header             = $7E;                {起始字}
      Address            = $01;                {单片机地址}
      TX_Length_limit    = 10 ;                {按照协议,发送的字节数}
      RX_Length_limit    = 10 ;                {按照协议,接收的字节数}
      RX_min             =  3 ;         
      
      command_list_0  = $00;     { 程序下载}
      command_list_1  = $01;     

type      
     TSerialRecord = Record
                       RX_Buffer: Array [1..RX_Length_limit] of Byte;  { 接收缓冲区,一个字节的字模 + 规定的字节}
                       RX_Count : byte;                                { 接收到的数量}
                       RX_Sum   : byte;                                { 接收校验}
                       TX_Buffer: Array [1..TX_Length_limit] of byte;  { 发送缓冲区}
                       TX_Number: byte;                                { 需要发送的总数量}
                       TX_Sum   : byte;                                { 发送校验和}
                       TX_Count : byte;                                { 发送的计数}
                       TX_Length: byte;                                {发送的长度限制}
                       RX_Length: byte;                                { 接收的长度限制}
                       RX_finish : byteBool;
                       TX_finish : byteBool;
                       TX_need  : byteBool;
                     end;      


var  
      serial_0: TSerialRecord IDATA;  
      
{与STC12C5604AD有关}
P2M0        : byte absolute $95;Volatile;
P2M1        : byte absolute $96;Volatile;
P3M0        : byte absolute $B1;Volatile;
P3M1        : byte absolute $B2;Volatile;   
AUXR        : byte absolute $8E;Volatile;   
ISP_CONTR   : byte absolute $E7;Volatile;

{************************************************************************}
{接收处理}
Procedure Do_receive;         
var
   number   : byte;
begin
  with serial_0 do
  begin
    if (RX_finish = True) then
    begin
      RX_Sum := 0;
      for number := 1 to (RX_Count-1) do RX_Sum:= RX_Sum + RX_Buffer[number];   
      if (RX_Sum = RX_Buffer[RX_Length]) then                                    
      begin
        case  RX_Buffer[3] of     {判断命令}
        command_list_0:                    
                begin
                ISP_CONTR := SWBS or SWRST ;    {关键!将复位指令送到寄存器 ISP_CONTR}
                end;
        command_list_1:
                begin

                end;  
        command_list_2:
                begin

                end;  
        command_error:
                begin

                end;        
        end;
        TX_Buffer[3] := RX_buffer[3];
        TX_Number := RX_Count;
        TX_need := True;                           {发送应答}
      end;           

      RX_Count := 1;         
      RX_finish := False;         
    end;
  end;
end;

{************************************************************************}
{发送处理}
Procedure Do_send;           
var
   number  : byte;
begin
  with serial_0 do
  begin
    if  (TX_need = True)  and (TX_finish = True) then
    begin
      TX_Sum := 0;
      for number := 1 to (TX_Number -1) do TX_Sum := TX_Sum + TX_Buffer[number];   
      TX_Buffer[TX_Number] := TX_Sum;
      TX_Count := 1;
      TX_finish := False;
      TX_need  := False ;   
      TI       := True;                      {开启发送}
    end;
  end;
end;

{************************************************************************}
{串行中断}   
Procedure RS232; Interrupt Serial;
begin
  with serial_0 do
  begin
  
    If (RI = True) then          {接收中断}
    begin
      RI := False;
      if (RX_finish = False) then
      begin
        RX_Buffer[RX_Count] := SBUF;       {接收字节}
        inc(RX_Count);
        if (RX_Count > RX_min) then            
        begin
          if ((RX_Buffer[1]= Header) and (RX_Buffer[2]= Address)) then
          begin
            if (RX_Count > (3 + RX_Buffer[3] + 2)) then
                                          begin
                                            RX_finish := True;  
                                          end                           
          end
          else begin      
                 RX_Count :=1;   
               end;
        end;
      end;
  end;

  If (TI =True) then          {发送中断}
  begin
    TI := False;
    if TX_Count < (TX_Number + 1) then    {判断是否已经发送完毕}
    begin
      SBUF := TX_Buffer[TX_Count];       {发送字节}
      Inc (TX_Count);
    end
    else TX_finish := True;
   end;
end;

end;
      
{************************************************************************}      
{初始化}      
procedure init;
begin
  with serial_0 do
  begin
    TX_Buffer[1] := HEADER;
    TX_Buffer[2] := ADDRESS;
    TX_Length := TX_Length_limit;
    RX_Length := RX_Length_limit;
    TX_Sum := 0;
    RX_Sum := 0;
    RX_Count :=1;
    RX_finish := False;
    TX_finish := True;
    TX_need := False;
  end;
  
        P2M0 := $00;
        P2M1 := $00;
        
        P3M0 := $FF;
        P3M1 := $FF;
  
        PCON := PCON and $7f;               
        SCON := $50;               
        AUXR := AUXR and $bf;               
        AUXR := AUXR and $fe;               
        TMOD := TMOD and $0f;               
        TMOD := TMOD or $20;               
        TL1 :=  BaudRateTimerValue;
        TH1 :=  BaudRateTimerValue;
        ET1 := False;               
        TR1 := True;               
        ES :=True;
  EA :=True;   
end;

{************************************************************************}
{主程序}      
begin
  init;
  Repeat
    Do_receive;
    Do_send;
  until False;  
end.


上面的代码,是通过串口接收指定的协议串,然后改变单片机特殊寄存器的值,从而达到复位单片机的目的。

通讯协议部分稍微复杂,主要的核心是第71行的代码。

同时要在STC的下载软件里做如下(红色框)的设置:


这样,你就不用再每次手动复位单片机,只需要第一次下载本程序时,手动复位一下,以后就可以专注于代码的编写。


完整代码文件: stc_isp.rar (1.68 KB)

相关帖子

沙发
coody| | 2015-11-24 11:43 | 只看该作者
STC本来就有这方面的说明啊,程序开发时我都是用这个功能来刷程序(当然,现在还可以仿真)

使用特权

评论回复
评论
逍遥派掌门 2015-11-24 11:50 回复TA
是参考STC的说明做的。这里把它的说明实例化了。 
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

14

主题

524

帖子

2

粉丝