本帖最后由 Mr.Bluyee 于 2017-4-4 10:37 编辑
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具体代码如下(由于中文编码方式不一样,代码放过来中文注释全是乱码,就删掉了):
- #include "delay.h"
- #include "usmart.h"
- u32 timer0_num=0;
- /**********************************************************************
- ***********************************************************************/
- void Timer0_init()
- {
- TMOD |= 0x02; //¶¨Ê±Æ÷0ģʽ2
- TH0=148; //0.1ms
- TL0=148;
- ET0=1; //¶¨Ê±Æ÷0¿ªÆôÖжÏ
- TR0=1; //¿ªÆô¶¨Ê±Æ÷
- EA=1; //¿ªÆô×ÜÖжÏ
- }
- /**********************************************************************
- ***********************************************************************/
- void delayms(u16 x)
- {
- u16 j;
- while(x--)
- {
- for(j = 0;j < 85;j ++);
- }
- }
- /**********************************************************************
- ***********************************************************************/
- void Timer0_isr() interrupt 1
- {
- timer0_num++;
- if(timer0_num==1000)
- {
- usmart_dev.scan(); //Ö´ÐÐusmartɨÃè
- timer0_num=0;
- }
- }
复制代码
delay.h具体代码如下:
- #ifndef __DELAY_H__
- #define __DELAY_H__
- #include "STC12C5A60S2.H"
- #include
- /* exact-width unsigned integer types */
- typedef unsigned char u8;
- typedef unsigned int u16;
- typedef unsigned long u32;
- /* exact-width signed integer types */
- typedef signed char int8_t;
- typedef signed int int16_t;
- typedef signed long int32_t;
- void Timer0_init();
- void delayms(u16 x);
- #endif
复制代码
第二步:新建uart.c和uart.h文件。
uart.c里主要是串口的初始化和串口中断函数。这里串口使用的是STC12C5A60S2的串口1,
工作模式1,BRT独立波特率发生器(把定时器1节省出来以备以后使用)。串口中断函数
结构参照usmart接口要求来写。
uart.h里主要是参数设定和函数声明。
uart.c具体代码如下:
- #include "uart.h"
- u8 UART_RX_BUF[UART_REC_LEN]={0}; //½ÓÊÕ»º³å,×î´óUSART_REC_LEN¸ö×Ö½Ú
- u16 UART_RX_STA=0; //½ÓÊÕ״̬±ê¼Ç
- //bit15£¬ ½ÓÊÕÍê³É±êÖ¾
- //bit14£¬ ½ÓÊÕµ½0x0d
- //bit13~0£¬ ½ÓÊÕµ½µÄÓÐЧ×Ö½ÚÊýÄ¿
- /**********************************************************************
- ***********************************************************************/
- void uart_init(u32 bound)
- {
- SCON=0X50;
- BRT=-(FOSC/bound/32);
- AUXR=0X15;
- ES=1;
- EA=1;
- }
- void uart_isr() interrupt 4 //(½ÓÊÕµ½µÄÊý¾Ý±ØÐëÊÇ0x0d 0x0a½áβ)
- {
- u8 Res;
- if(RI)
- {
- Res=SBUF;
- if((UART_RX_STA&0x8000)==0)//½ÓÊÕδÍê³É
- {
- if(UART_RX_STA&0x4000)//½ÓÊÕµ½ÁË0x0d
- {
- if(Res!=0x0a)UART_RX_STA=0;//½ÓÊÕ´íÎó,ÖØпªÊ¼
- else UART_RX_STA|=0x8000; //½ÓÊÕÍê³ÉÁË
- }
- else //»¹Ã»ÊÕµ½0X0D
- {
- if(Res==0x0d)UART_RX_STA|=0x4000;
- else
- {
- UART_RX_BUF[UART_RX_STA&0X3FFF]=Res ;
- UART_RX_STA++;
- if(UART_RX_STA>(UART_REC_LEN-1))UART_RX_STA=0;
- }
- }
- }
- RI=0;
- }
- }
复制代码
uart.h具体代码如下:
- #ifndef __UART_H__
- #define __UART_H__
- #include "delay.h"
- #include
- #define FOSC 11059200L //system frequency
- #define BAUD 9600
- #define UART_REC_LEN 200 //¶¨Òå×î´ó½ÓÊÕ×Ö½ÚÊý 200
- void uart_init(u32 bound);
- #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是用户自定义,用户添加自己需要调试的函数。下面附上楼主修改后的。
- #include "usmart.h"
- #include "usmart_str.h"
- ////////////////////////////Óû§ÅäÖÃÇø///////////////////////////////////////////////
- //ÕâÏÂÃæÒª°üº¬ËùÓõ½µÄº¯ÊýËùÉêÃ÷µÄÍ·Îļþ(Óû§×Ô¼ºÌí¼Ó)
- #include "delay.h"
- #include "IO.h"
- //º¯ÊýÃûÁбí³õʼ»¯(Óû§×Ô¼ºÌí¼Ó)
- //Óû§Ö±½ÓÔÚÕâÀïÊäÈëÒªÖ´Ðеĺ¯ÊýÃû¼°Æä²éÕÒ´®
- struct _m_usmart_nametab usmart_nametab[]=
- {
- (void*)delayms,"void delayms(u16 x);",
- (void*)set_output,"void set_output(u8 i);",
- (void*)reset_output,"void reset_output(u8 i);"
- };
- ///////////////////////////////////END///////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////////////////////
- //º¯Êý¿ØÖƹÜÀíÆ÷³õʼ»¯
- //µÃµ½¸÷¸öÊܿغ¯ÊýµÄÃû×Ö
- //µÃµ½º¯Êý×ÜÊýÁ¿
- struct _m_usmart_dev usmart_dev=
- {
- usmart_nametab,
- usmart_init,
- usmart_cmd_rec,
- usmart_exe,
- usmart_scan,
- sizeof(usmart_nametab)/sizeof(struct _m_usmart_nametab),//º¯ÊýÊýÁ¿
- 0, //²ÎÊýÊýÁ¿
- 0, //º¯ÊýID
- 1, //²ÎÊýÏÔʾÀàÐÍ,0,10½øÖÆ;1,16½øÖÆ
- 0, //²ÎÊýÀàÐÍ.bitx:,0,Êý×Ö;1,×Ö·û´®
- 0, //ÿ¸ö²ÎÊýµÄ³¤¶ÈÔÝ´æ±í,ÐèÒªMAX_PARM¸ö0³õʼ»¯
- 0, //º¯ÊýµÄ²ÎÊý,ÐèÒªPARM_LEN¸ö0³õʼ»¯
- };
复制代码
重点是对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; //·µ»Ø¼ÆÊýÖµ
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文件函数声明里做对应修改。
- void usmart_init()
- {
- #if USMART_ENTIMX_SCAN==1
- Timer0_init();
- #endif
- usmart_dev.sptype=1;
- }
复制代码
7.修改void usmart_exe(void)函数。主要注意这里:
- switch(usmart_dev.pnum)
- {
- case 0://ÎÞ²ÎÊý(voidÀàÐÍ)
- res=(*(u32(*)())usmart_dev.funs[id].func)();
- break;
- case 1://ÓÐ1¸ö²ÎÊý
- res=(*(u32(*)())usmart_dev.funs[id].func)(temp[0]);
- break;
- case 2://ÓÐ2¸ö²ÎÊý
- res=(*(u32(*)())usmart_dev.funs[id].func)(temp[0],temp[1]);
- break;
- case 3://ÓÐ3¸ö²ÎÊý
- res=(*(u32(*)())usmart_dev.funs[id].func)(temp[0],temp[1],temp[2]);
- break;
- case 4://ÓÐ4¸ö²ÎÊý
- res=(*(u32(*)())usmart_dev.funs[id].func)(temp[0],temp[1],temp[2],temp[3]);
- break;
- case 5://ÓÐ5¸ö²ÎÊý
- res=(*(u32(*)())usmart_dev.funs[id].func)(temp[0],temp[1],temp[2],temp[3],temp[4]);
- break;
- case 6://ÓÐ6¸ö²ÎÊý
- res=(*(u32(*)())usmart_dev.funs[id].func)(temp[0],temp[1],temp[2],temp[3],temp[4],
- temp[5]);
- break;
- case 7://ÓÐ7¸ö²ÎÊý
- res=(*(u32(*)())usmart_dev.funs[id].func)(temp[0],temp[1],temp[2],temp[3],temp[4],
- temp[5],temp[6]);
- break;
- case 8://ÓÐ8¸ö²ÎÊý
- res=(*(u32(*)())usmart_dev.funs[id].func)(temp[0],temp[1],temp[2],temp[3],temp[4],
- temp[5],temp[6],temp[7]);
- break;
- case 9://ÓÐ9¸ö²ÎÊý
- res=(*(u32(*)())usmart_dev.funs[id].func)(temp[0],temp[1],temp[2],temp[3],temp[4],
- temp[5],temp[6],temp[7],temp[8]);
- break;
- case 10://ÓÐ10¸ö²ÎÊý
- res=(*(u32(*)())usmart_dev.funs[id].func)(temp[0],temp[1],temp[2],temp[3],temp[4],
- temp[5],temp[6],temp[7],temp[8],temp[9]);
- break;
- }
复制代码
如果不作修改直接编译的话会出现错误:
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时,不需要每句都加,例:
- TI=1;
- printf("rn");
- printf("USMART has 7 system commandsrn");
- printf("?: get help informationrn");
- printf("help: get help informationrn");
- printf("list: available function listrn");
- printf("id: available function IDrn");
- printf("hex: argument display in hex,hex+space+numberrn");
- printf("dec: argument display in dec,dec+space+numberrn");
- printf("runtime:1,enable caculate function runtime;0,disable caculate function runtimern");
- printf("please input the right fuctions with arguments and end with enter!rn");
- TI=0;
复制代码
这个问题请自行在usmart.c文件里修改。如有需要,楼主可以提供全部改好的一个工程模版。 4.串口printf输出长串中文字符串时,容易出现一些字符乱码,不是全部(迷之问题,知道原因的请赐教)
楼主只是把中文的全部改成英文的,如上代码所示。
3
|
|
|
|