一、串口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