微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 51单片机移植ALIENTEK的USMART调试组件

51单片机移植ALIENTEK的USMART调试组件

时间:10-02 整理:3721RD 点击:

     USMART 调试组件由ALIENTEK 开发提供,功能类似 linux 的 shell(RTT 的 finsh 也属于此类)。
     USMART 最主要的功能就是通过串口调用单片机里面的任何函数,并执行。因此,你可以随意更
改函数的输入参数(支持数字 (10/16进制,支持负数)、字符串、函数入口地址等作为参数),单个
函数最多支持 10 个输入参数,并支持函数返回值显示,对我们调试代码是很有帮助的。
     USMART是用于STM32上的,由于其方便调试,小编将其移植到51单片机中,使用的单片机为
STC12C5A60S2,晶振为11.0592MHZ。在此写下移植过程分享给大家。
     先上图,串口调试助手发送函数让单片机控制继电器吸合与断开。
                                      


                                      


                                      


                                      


    代码工程结构如下图(感谢原子对我学习stm32的帮助,有些习惯受其影响较大):
                                      

   第一步:新建delay.c和delay.h文件。
                delay.c里主要为定时器0初始化和中断函数。定时器0主要作USMART的扫描函数的100ms的定时。
                delay.c里还写里一个简单的延时函数。delay.c里的#include "usmart.h"为原子的usmart提供的文件。
                delay.h里主要是函数声明,还有u8 u16等类型定义。
                delay.c具体代码如下(由于中文编码方式不一样,代码放过来中文注释全是乱码,就删掉了):

  1. #include "delay.h"
  2. #include "usmart.h"

  3. u32 timer0_num=0;
  4. /**********************************************************************
  5. ***********************************************************************/
  6. void Timer0_init()
  7. {
  8.     TMOD |= 0x02;            //?¨ê±?÷0?£ê?2
  9.     TH0=148;                 //0.1ms
  10.     TL0=148;
  11.     ET0=1;                   //?¨ê±?÷0?a???D??
  12.     TR0=1;                          //?a???¨ê±?÷
  13.     EA=1;                    //?a??×ü?D??
  14. }
  15. /**********************************************************************
  16. ***********************************************************************/
  17. void delayms(u16 x)
  18. {
  19.     u16 j;   
  20.     while(x--)   
  21.     {   
  22.         for(j = 0;j < 85;j ++);                             
  23.     }   
  24. }
  25. /**********************************************************************
  26. ***********************************************************************/
  27. void Timer0_isr() interrupt 1
  28. {
  29.     timer0_num++;
  30.     if(timer0_num==1000)
  31.     {
  32.         usmart_dev.scan();        //?′DDusmarté¨?è       
  33.         timer0_num=0;
  34.     }
  35. }

复制代码

              delay.h具体代码如下:

  1. #ifndef __DELAY_H__
  2. #define __DELAY_H__

  3. #include "STC12C5A60S2.H"
  4. #include <intrins.h>

  5. /* exact-width unsigned integer types */
  6. typedef unsigned          char u8;
  7. typedef unsigned           int u16;
  8. typedef unsigned          long u32;

  9. /* exact-width signed integer types */
  10. typedef   signed          char int8_t;
  11. typedef   signed           int int16_t;
  12. typedef   signed          long int32_t;

  13. void Timer0_init();
  14. void delayms(u16 x);

  15. #endif

复制代码

  第二步:新建uart.c和uart.h文件。
                 uart.c里主要是串口的初始化和串口中断函数。这里串口使用的是STC12C5A60S2的串口1,
                 工作模式1,BRT独立波特率发生器(把定时器1节省出来以备以后使用)。串口中断函数
                 结构参照usmart接口要求来写。
                 uart.h里主要是参数设定和函数声明。
                 uart.c具体代码如下:

  1. #include "uart.h"

  2. u8 UART_RX_BUF[UART_REC_LEN]={0};    //?óê??o3?,×?′óUSART_REC_LEN??×??ú
  3. u16 UART_RX_STA=0;                   //?óê?×′ì?±ê??       
  4. //bit15£?        ?óê?íê3é±ê??
  5. //bit14£?        ?óê?μ?0x0d
  6. //bit13~0£?        ?óê?μ?μ?óDD§×??úêy??
  7. /**********************************************************************
  8. ***********************************************************************/
  9. void uart_init(u32 bound)
  10. {
  11.      SCON=0X50;
  12.      BRT=-(FOSC/bound/32);
  13.      AUXR=0X15;
  14.      ES=1;
  15.      EA=1;               
  16. }

  17. void uart_isr() interrupt 4        //(?óê?μ?μ?êy?Y±?D?ê?0x0d 0x0a?á?2)
  18. {
  19.      u8 Res;
  20.      if(RI)
  21.      {
  22.           Res=SBUF;
  23.           if((UART_RX_STA&0x8000)==0)//?óê??′íê3é
  24.           {
  25.               if(UART_RX_STA&0x4000)//?óê?μ?á?0x0d
  26.               {
  27.                    if(Res!=0x0a)UART_RX_STA=0;//?óê?′í?ó,??D??aê?
  28.                       else UART_RX_STA|=0x8000;        //?óê?íê3éá?
  29.               }
  30.               else //?1??ê?μ?0X0D
  31.               {       
  32.                    if(Res==0x0d)UART_RX_STA|=0x4000;
  33.                    else
  34.                    {
  35.                         UART_RX_BUF[UART_RX_STA&0X3FFF]=Res ;
  36.                         UART_RX_STA++;
  37.                         if(UART_RX_STA>(UART_REC_LEN-1))UART_RX_STA=0;
  38.                    }                 
  39.               }
  40.          }                                  
  41.         RI=0;
  42.     }       
  43. }

复制代码

                uart.h具体代码如下:

  1. #ifndef __UART_H__
  2. #define __UART_H__

  3. #include "delay.h"
  4. #include <stdio.h>

  5. #define FOSC 11059200L         //system frequency
  6. #define BAUD 9600
  7. #define UART_REC_LEN          200          //?¨ò?×?′ó?óê?×??úêy 200

  8. void uart_init(u32 bound);

  9. #endif

复制代码

第三步:添加usmart源码,原子提供的共有5个文件,分别为usmart.c、usmart.h、usmart_config.c、
              usmart_str.c和usmart_str.h。
              usmart.h、usmart_str.c基本不需要改动。
              usmart_str.h里把#include "stm32f4xx.h"删掉,替换为#include "delay.h"即可。
              usmart_config.c是用户自定义,用户添加自己需要调试的函数。下面附上小编修改后的。

  1. #include "usmart.h"
  2. #include "usmart_str.h"
  3. ////////////////////////////ó??§??????///////////////////////////////////////////////
  4. //?a????òa°üo??ùó?μ?μ?oˉêy?ùéê?÷μ?í·???t(ó??§×??oìí?ó)
  5. #include "delay.h"               
  6. #include "IO.h"                                                                                                 
  7. //oˉêy??áD±í3?ê??ˉ(ó??§×??oìí?ó)
  8. //ó??§?±?ó?ú?aà?ê?è?òa?′DDμ?oˉêy???°??2é?ò′?
  9. struct _m_usmart_nametab usmart_nametab[]=
  10. {  
  11.          (void*)delayms,"void delayms(u16 x);",
  12.          (void*)set_output,"void set_output(u8 i);",
  13.    (void*)reset_output,"void reset_output(u8 i);"
  14. };                                                  
  15. ///////////////////////////////////END///////////////////////////////////////////////
  16. /////////////////////////////////////////////////////////////////////////////////////
  17. //oˉêy????1üàí?÷3?ê??ˉ
  18. //μ?μ??÷??êü??oˉêyμ???×?
  19. //μ?μ?oˉêy×üêyá?
  20. struct _m_usmart_dev usmart_dev=
  21. {
  22.         usmart_nametab,
  23.         usmart_init,
  24.         usmart_cmd_rec,
  25.         usmart_exe,
  26.         usmart_scan,
  27.         sizeof(usmart_nametab)/sizeof(struct _m_usmart_nametab),//oˉêyêyá?
  28.         0,                  //2?êyêyá?
  29.         0,                 //oˉêyID
  30.         1,                //2?êy??ê?ààDí,0,10????;1,16????
  31.         0,                //2?êyààDí.bitx:,0,êy×?;1,×?·?′?            
  32.         0,                  //????2?êyμ?3¤?è?Y′?±í,DèòaMAX_PARM??03?ê??ˉ
  33.         0,                //oˉêyμ?2?êy,DèòaPARM_LEN??03?ê??ˉ
  34. };   

复制代码

             重点是对usmart.c的修改。
              1.删掉#include "usart.h"和 #include "sys.h" ,添加#include "uart.h"
              2.添加外部参数声明:
                                               extern u8 UART_RX_BUF[UART_REC_LEN];  
                                               extern u16 UART_RX_STA;           
                                               extern u32 timer0_num;
              3.替换void usmart_reset_runtime(void)函数里的内容
                 替换为:
                                timer0_num=0;
                                usmart_dev.runtime=0;       
              4.替换u32 usmart_get_runtime(void)函数里的内容
                 替换为:
                               usmart_dev.runtime+=timer0_num;
                               return usmart_dev.runtime;                //·μ????êy?μ
              5.删掉void TIM4_IRQHandler(void)函数(usmart_dev.scan();已写在delay.c定时器0中断里),
                 删掉void Timer4_Init(u16 arr,u16 psc)函数。
              6.修改void usmart_init(u8 sysclk)函数,要去掉形参,要记得在h文件函数声明里做对应修改。

  1. void usmart_init()
  2. {
  3.      #if USMART_ENTIMX_SCAN==1
  4.      Timer0_init();
  5.      #endif
  6.      usmart_dev.sptype=1;
  7. }               

复制代码

             7.修改void usmart_exe(void)函数。主要注意这里:

  1. switch(usmart_dev.pnum)
  2.         {
  3.                 case 0://?T2?êy(voidààDí)                                                                                          
  4.                         res=(*(u32(*)())usmart_dev.funs[id].func)();
  5.                         break;
  6.             case 1://óD1??2?êy
  7.                         res=(*(u32(*)())usmart_dev.funs[id].func)(temp[0]);
  8.                         break;
  9.             case 2://óD2??2?êy
  10.                         res=(*(u32(*)())usmart_dev.funs[id].func)(temp[0],temp[1]);
  11.                         break;
  12.             case 3://óD3??2?êy
  13.                         res=(*(u32(*)())usmart_dev.funs[id].func)(temp[0],temp[1],temp[2]);
  14.                         break;
  15.             case 4://óD4??2?êy
  16.                         res=(*(u32(*)())usmart_dev.funs[id].func)(temp[0],temp[1],temp[2],temp[3]);
  17.                         break;
  18.             case 5://óD5??2?êy
  19.                         res=(*(u32(*)())usmart_dev.funs[id].func)(temp[0],temp[1],temp[2],temp[3],temp[4]);
  20.                         break;
  21.             case 6://óD6??2?êy
  22.                         res=(*(u32(*)())usmart_dev.funs[id].func)(temp[0],temp[1],temp[2],temp[3],temp[4],\
  23.                         temp[5]);
  24.                         break;
  25.             case 7://óD7??2?êy
  26.                         res=(*(u32(*)())usmart_dev.funs[id].func)(temp[0],temp[1],temp[2],temp[3],temp[4],\
  27.                         temp[5],temp[6]);
  28.                         break;
  29.             case 8://óD8??2?êy
  30.                         res=(*(u32(*)())usmart_dev.funs[id].func)(temp[0],temp[1],temp[2],temp[3],temp[4],\
  31.                         temp[5],temp[6],temp[7]);
  32.                         break;
  33.             case 9://óD9??2?êy
  34.                         res=(*(u32(*)())usmart_dev.funs[id].func)(temp[0],temp[1],temp[2],temp[3],temp[4],\
  35.                         temp[5],temp[6],temp[7],temp[8]);
  36.                         break;
  37.             case 10://óD10??2?êy
  38.                         res=(*(u32(*)())usmart_dev.funs[id].func)(temp[0],temp[1],temp[2],temp[3],temp[4],\
  39.                         temp[5],temp[6],temp[7],temp[8],temp[9]);
  40.                         break;
  41.         }

复制代码

            如果不作修改直接编译的话会出现错误:
                                     warning C209: 'function': too few actual parameters
                                          error C208: 'function': too many actual parameters
            或者是函数未符合A什么标准的,意思就是未找到定义的函数。
            这里修改方式就是屏蔽掉没有在usmart_config.c里用户自定义区里函数的类型,例如小编的
            usmart_config.c里的用户自定义区有三个函数
                                                        (void*)delayms,"void delayms(u16 x);",
                                                        (void*)set_output,"void set_output(u8 i);",
                                                        (void*)reset_output,"void reset_output(u8 i);"
            这三个函数都只有1个形参,那么对于switch case里面例举的函数类型,只留下case 1,其他全注释掉。
            用户区里有什么样结构的函数,case里就保留什么样的结构。
            
            usmart.c修改细节部分:
            1.删掉u32 read_addr(u32 addr)和void write_addr(u32 addr,u32 val)函数,直接从#if删到#endif,注意
              对应的h文件里函数声明要删掉。不删的话,还可以在usmart.h里将USMART_USE_WRFUNS宏定义为0就                 行了。
            2.使用printf输出16进制时,为了输出正确,参数要强制类型转换一下,例:
                                                        printf("0X%X",(u16)temp);
               u16在delay.h里声明的是unsigned int类型。
            3.51单片机串口printf输出时,前后要给TI信号。例:
                                                        TI=1;
                                                        printf("0X%X",(u16)temp);
                                                        TI=0;
               一大段printf时,不需要每句都加,例:

  1. TI=1;
  2.                   printf("\r\n");
  3.                         printf("USMART has 7 system commands\r\n");
  4.                   printf("?:      get help information\r\n");
  5.                         printf("help:   get help information\r\n");
  6.                         printf("list:   available function list\r\n");       
  7.                         printf("id:     available function ID\r\n");               
  8.                         printf("hex:    argument display in hex,hex+space+number\r\n");               
  9.                         printf("dec:    argument display in dec,dec+space+number\r\n");               
  10.                         printf("runtime:1,enable caculate function runtime;0,disable caculate function runtime\r\n");
  11.                         printf("please input the right fuctions with arguments and end with enter!\r\n");  
  12.                   TI=0;

复制代码

              这个问题请自行在usmart.c文件里修改。如有需要,小编可以提供全部改好的一个工程模版。               4.串口printf输出长串中文字符串时,容易出现一些字符乱码,不是全部(迷之问题,知道原因的请赐教)
                  小编只是把中文的全部改成英文的,如上代码所示。
              

好材料,先收藏了。

方便留下联系方式吗?可以交流一下吗?最近也想将usmart移植到其他单片机上。

小编,注释乱码是因为编译器编码问题。像keil4的注释在keil5上就乱码,反正我的是这样,不知道你们的。c文件可以先用记事本打开,然后再复制就不会乱码了。

专业PCB快板制造!打样30元起,加急24小时只要50元!^_^有需要可以和我联系,QQ269175760,谢谢!

我把它移植到STC15W4K48S4,也出现了显示长串汉字是会出现乱码,你找到原因了没?

好像是很牛的样子?

大神,你来知道一下呗

我不是什么大神啊

就是一水军而已,

知道谈不上了,互相学习

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top