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

[复制链接]
1282|2
 楼主| 逍遥派掌门 发表于 2015-11-24 11:27 | 显示全部楼层 |阅读模式
本帖最后由 逍遥派掌门 于 2015-11-26 23:57 编辑

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

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

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

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

先上Turbo51的代码:
  1. Program main;

  2. {$IDATA}    { 申请使用IDATA}

  3. Const
  4. {与STC12C5604AD有关}
  5.       SWBS  = $40;
  6.       SWRST = $20;


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

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

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

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


  34. var  
  35.       serial_0: TSerialRecord IDATA;  
  36.       
  37. {与STC12C5604AD有关}
  38. P2M0        : byte absolute $95;Volatile;
  39. P2M1        : byte absolute $96;Volatile;
  40. P3M0        : byte absolute $B1;Volatile;
  41. P3M1        : byte absolute $B2;Volatile;   
  42. AUXR        : byte absolute $8E;Volatile;   
  43. ISP_CONTR   : byte absolute $E7;Volatile;

  44. {************************************************************************}
  45. {接收处理}
  46. Procedure Do_receive;         
  47. var
  48.    number   : byte;
  49. begin
  50.   with serial_0 do
  51.   begin
  52.     if (RX_finish = True) then
  53.     begin
  54.       RX_Sum := 0;
  55.       for number := 1 to (RX_Count-1) do RX_Sum:= RX_Sum + RX_Buffer[number];   
  56.       if (RX_Sum = RX_Buffer[RX_Length]) then                                    
  57.       begin
  58.         case  RX_Buffer[3] of     {判断命令}
  59.         command_list_0:                    
  60.                 begin
  61.                 ISP_CONTR := SWBS or SWRST ;    {关键!将复位指令送到寄存器 ISP_CONTR}
  62.                 end;
  63.         command_list_1:
  64.                 begin

  65.                 end;  
  66.         command_list_2:
  67.                 begin

  68.                 end;  
  69.         command_error:
  70.                 begin

  71.                 end;        
  72.         end;
  73.         TX_Buffer[3] := RX_buffer[3];
  74.         TX_Number := RX_Count;
  75.         TX_need := True;                           {发送应答}
  76.       end;           

  77.       RX_Count := 1;         
  78.       RX_finish := False;         
  79.     end;
  80.   end;
  81. end;

  82. {************************************************************************}
  83. {发送处理}
  84. Procedure Do_send;           
  85. var
  86.    number  : byte;
  87. begin
  88.   with serial_0 do
  89.   begin
  90.     if  (TX_need = True)  and (TX_finish = True) then
  91.     begin
  92.       TX_Sum := 0;
  93.       for number := 1 to (TX_Number -1) do TX_Sum := TX_Sum + TX_Buffer[number];   
  94.       TX_Buffer[TX_Number] := TX_Sum;
  95.       TX_Count := 1;
  96.       TX_finish := False;
  97.       TX_need  := False ;   
  98.       TI       := True;                      {开启发送}
  99.     end;
  100.   end;
  101. end;

  102. {************************************************************************}
  103. {串行中断}   
  104. Procedure RS232; Interrupt Serial;
  105. begin
  106.   with serial_0 do
  107.   begin
  108.   
  109.     If (RI = True) then          {接收中断}
  110.     begin
  111.       RI := False;
  112.       if (RX_finish = False) then
  113.       begin
  114.         RX_Buffer[RX_Count] := SBUF;       {接收字节}
  115.         inc(RX_Count);
  116.         if (RX_Count > RX_min) then            
  117.         begin
  118.           if ((RX_Buffer[1]= Header) and (RX_Buffer[2]= Address)) then
  119.           begin
  120.             if (RX_Count > (3 + RX_Buffer[3] + 2)) then
  121.                                           begin
  122.                                             RX_finish := True;  
  123.                                           end                           
  124.           end
  125.           else begin      
  126.                  RX_Count :=1;   
  127.                end;
  128.         end;
  129.       end;
  130.   end;

  131.   If (TI =True) then          {发送中断}
  132.   begin
  133.     TI := False;
  134.     if TX_Count < (TX_Number + 1) then    {判断是否已经发送完毕}
  135.     begin
  136.       SBUF := TX_Buffer[TX_Count];       {发送字节}
  137.       Inc (TX_Count);
  138.     end
  139.     else TX_finish := True;
  140.    end;
  141. end;

  142. end;
  143.       
  144. {************************************************************************}      
  145. {初始化}      
  146. procedure init;
  147. begin
  148.   with serial_0 do
  149.   begin
  150.     TX_Buffer[1] := HEADER;
  151.     TX_Buffer[2] := ADDRESS;
  152.     TX_Length := TX_Length_limit;
  153.     RX_Length := RX_Length_limit;
  154.     TX_Sum := 0;
  155.     RX_Sum := 0;
  156.     RX_Count :=1;
  157.     RX_finish := False;
  158.     TX_finish := True;
  159.     TX_need := False;
  160.   end;
  161.   
  162.         P2M0 := $00;
  163.         P2M1 := $00;
  164.         
  165.         P3M0 := $FF;
  166.         P3M1 := $FF;
  167.   
  168.         PCON := PCON and $7f;               
  169.         SCON := $50;               
  170.         AUXR := AUXR and $bf;               
  171.         AUXR := AUXR and $fe;               
  172.         TMOD := TMOD and $0f;               
  173.         TMOD := TMOD or $20;               
  174.         TL1 :=  BaudRateTimerValue;
  175.         TH1 :=  BaudRateTimerValue;
  176.         ET1 := False;               
  177.         TR1 := True;               
  178.         ES :=True;
  179.   EA :=True;   
  180. end;

  181. {************************************************************************}
  182. {主程序}      
  183. begin
  184.   init;
  185.   Repeat
  186.     Do_receive;
  187.     Do_send;
  188.   until False;  
  189. end.


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

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

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


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


完整代码文件:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
coody 发表于 2015-11-24 11:43 | 显示全部楼层
STC本来就有这方面的说明啊,程序开发时我都是用这个功能来刷程序(当然,现在还可以仿真)

评论

是参考STC的说明做的。这里把它的说明实例化了。  发表于 2015-11-24 11:50
您需要登录后才可以回帖 登录 | 注册

本版积分规则

14

主题

528

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部