一、串口SHELL模式配置分析解读

本文探讨串口SHELL模式的配置,基于定时器中断计数,检查串口接收数据,涉及串口和定时器的设置。
摘要由CSDN通过智能技术生成

一、串口SHELL模式:
配置串口shell的原理:该配置是通过定时器中断进行计数操作,同时在定时器计数中对串口的中断收到的数据进行检查。

串口头文件配置:

#define USART_REC_LEN  			200  	//定义最大接收字节数 200
#define EN_USART1_RX 			1		//使能(1)/禁止(0)串口1接收
	  	
extern uint8_t  USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符 
extern uint16_t USART_RX_STA;         		//接收状态标记	

用户配置参数	  
#define MAX_FNAME_LEN 		30	//函数名最大长度,应该设置为不小于最长函数名的长度。											   
#define MAX_PARM 			10	//最大为10个参数 ,修改此参数,必须修改usmart_exe与之对应.
#define PARM_LEN 			200	//所有参数之和的长度不超过PARM_LEN个字节,注意串口接收部分要与之对应(不小于PARM_LEN)

#define USMART_OK 			0  //无错误
#define USMART_FUNCERR 		1  //函数错误
#define USMART_PARMERR 		2  //参数错误
#define USMART_PARMOVER 	3  //参数溢出
#define USMART_NOFUNCFIND 	4  //未找到匹配函数

#define SP_TYPE_DEC      	0  //10进制参数显示
#define SP_TYPE_HEX       	1  //16进制参数显示

#define USMART_USE_HELP		1	//使用帮助,该值设为0,可以节省近700个字节,但是将导致无法显示帮助信息。
#define USMART_USE_WRFUNS	1	//使用读写函数,使能这里,可以读取任何地址的值,还可以写寄存器的值.
#define USMART_ENTIMX_SCAN 	1	//使用TIM的定时中断来扫描SCAN函数,如果设置为0,需要自己实现隔一段时间扫描一次scan函数.

 //函数名列表	 
struct _m_usmart_nametab
{
   
	void* func;			//函数指针
	const uint8_t* name;		//函数名(查找串)	 
};
//usmart控制管理器
struct _m_usmart_dev
{
   
	struct _m_usmart_nametab *funs;	//函数名指针

	void (*init)(uint8_t);				//初始化
	uint8_t (*cmd_rec)(uint8_t*str);			//识别函数名及参数
	void (*exe)(void); 				//执行 
	void (*scan)(void);             //扫描
	uint8_t fnum; 				  		//函数数量
	uint8_t pnum;                        //参数数量
	uint8_t id;							//函数id
	uint8_t sptype;						//参数显示类型(非字符串参数):0,10进制;1,16进制;
	uint16_t parmtype;					//参数的类型
	uint8_t  plentbl[MAX_PARM];  		//每个参数的长度暂存表
	uint8_t  parm[PARM_LEN];  			//函数的参数
	uint8_t runtimeflag;					//0,不统计函数执行时间;1,统计函数执行时间,注意:此功能必须在USMART_ENTIMX_SCAN使能的时候,才有用
	uint32_t runtime;					//运行时间,单位:0.1ms,最大延时时间为定时器CNT值的2倍*0.1ms
};
extern struct _m_usmart_nametab usmart_nametab[];	
extern struct _m_usmart_dev usmart_dev;	

uint8_t usmart_get_parmpos(uint8_t num);						//得到某个参数在参数列里面的起始位置
uint8_t usmart_strcmp(uint8_t*str1,uint8_t *str2);					//对比两个字符串是否相等
uint32_t usmart_pow(uint8_t m,uint8_t n);							//M^N次方
uint8_t usmart_str2num(uint8_t*str,uint32_t *res);					//字符串转为数字
uint8_t usmart_get_cmdname(uint8_t*str,uint8_t*cmdname,uint8_t *nlen,uint8_t maxlen);//从str中得到指令名,并返回指令长度
uint8_t usmart_get_fname(uint8_t*str,uint8_t*fname,uint8_t *pnum,uint8_t *rval);		//从str中得到函数名
uint8_t usmart_get_aparm(uint8_t *str,uint8_t *fparm,uint8_t *ptype); 	//从str中得到一个函数参数
uint8_t usmart_get_fparam(uint8_t*str,uint8_t *parn);  			//得到str中所有的函数参数.	

void usmart_init(uint8_t sysclk);//初始化
uint8_t usmart_cmd_rec(uint8_t*str);	//识别
void usmart_exe(void);		//执行
void usmart_scan(void);     //扫描
uint32_t read_addr(uint32_t addr);	//读取指定地址的值
void write_addr(uint32_t addr,uint32_t val);//在指定地址写入指定的值
uint32_t usmart_get_runtime(void);	//获取运行时间
void usmart_reset_runtime(void);//复位运行时间

串口文件配置:

struct _m_usmart_nametab usmart_nametab[]=
{
   
#if USMART_USE_WRFUNS==1 	//如果使能了读写操作
	(void*)read_addr,"u32 read_addr(u32 addr)",
	(void*)write_addr,"void write_addr(u32 addr,u32 val)",	 
#endif	
	(void*)ti_i,"void ti_i(uint8_t on)",
	(void*)ti_o,"void ti_o(uint8_t on)",				
};

//函数控制管理器初始化
//得到各个受控函数的名字
//得到函数总数量
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初始化
};   

uint8_t *sys_cmd_tab[]=
{
   
	"?",
	"help",
	"list",
	"id",
	"hex",
	"dec",
	"runtime",	   
};	

uint8_t USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
uint16_t USART_RX_STA=0;       //接收状态标记	
uint8_t aRxBuffer[RXBUFFERSIZE];//HAL库使用的串口接收缓冲

int fputc(int ch, FILE *f)
{
    	
	while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   
	USART1->DR = (uint8_t) ch;      
	return ch;
}

//串口初始化中添加
	HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, RXBUFFERSIZE);//该函数会开启接收中断:标志位UART_IT_RXNE,并且设置接收缓冲以及接收缓冲接收最大数据量

//初始化串口调试配置
void usmart_init(uint8_t sysclk)
{
   
#if USMART_ENTIMX_SCAN==1
	Timer4_Init(1000,(uint32_t)sysclk*100-1);//分频,时钟为10K ,100ms中断一次,注意,计数频率必须为10Khz,以和runtime单位(0.1ms)同步.
#endif	
	usmart_dev.sptype=1;	//十六进制显示参数
}	


void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
   
	if(huart->Instance==USART1)//如果是串口1
	{
   
		if((USART_RX_STA&0x8000)==0)//接收未完成
		{
   
			if(USART_RX_STA&0x4000)//接收到了0x0d
			{
   
				if(aRxBuffer[0]!=0x0a)USART_RX_STA=0;//接收错误,重新开始
				else USART_RX_STA|=0x8000;	//接收完成了 
			}
			else //还没收到0X0D
			{
   	
				if(aRxBuffer[0]==0x0d)USART_RX_STA|=0x4000;
				else
				{
   
					USART_RX_BUF[USART_RX_STA&0X3FFF]=aRxBuffer[0] ;
					USART_RX_STA++;
					if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收	  
				}		 
			}
		}

	}
}



//对比字符串str1和str2
//*str1:字符串1指针
//*str2:字符串2指针
//返回值:0,相等;1,不相等;
uint8_t usmart_strcmp(uint8_t *str1,uint8_t *str2)
{
   
	while(1)
	{
   
		if(*str1!=*str2)return 1;//不相等
		if(*str1=='\0')break;//对比完成了.
		str1++;
		str2++;
	}
	return 0;//两个字符串相等
}
//把str1的内容copy到str2
//*str1:字符串1指针
//*str2:字符串2指针			   
void usmart_strcopy(uint8_t*str1,uint8_t *str2)
{
   
	while(1)
	{
   										   
		*str2=*str1;	//拷贝
		if(*str1=='\0')break;//拷贝完成了.
		str1++;
		str2++;
	}
}
//得到字符串的长度(字节)
//*str:字符串指针
//返回值:字符串的长度		   
uint8_t usmart_strlen(uint8_t*str)
{
   
	uint8_t len=0;
	while(1)
	{
   							 
		if(*str=='\0')break;//拷贝完成了.
		len++;
		str++;
	}
	return len
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值