天天看点

STM32 f103 实现命令终端

文件说明

uart.c 

实现输入反显及命令识别

cmd.c

实现命令函数及命令查找

main.c

进入shell模式

uart.c

#include "usart.h"

/****************************************************************************
* 名    称:void USART1_Configuration(void)
* 功    能:配置USART1参数
* 入口参数:
* 出口参数:无
* 说    明:
* 调用方法:无 
****************************************************************************/
void USART1_Configuration(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;	         		 //USART1 TX
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;    		 //复用推挽输出
	GPIO_Init(GPIOA, &GPIO_InitStructure);		    		 //A端口 

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;	         	 //USART1 RX
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;   	 //复用开漏输入
	GPIO_Init(GPIOA, &GPIO_InitStructure);		         	 //A端口 

	USART_InitStructure.USART_BaudRate = USART_BAUDRATE;						//波特率250000bps
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;		//数据位8位
	USART_InitStructure.USART_StopBits = USART_StopBits_1;			//停止位1位
	USART_InitStructure.USART_Parity = USART_Parity_No;				//无校验位
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;   //无硬件流控
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;					//收发模式 

	USART_Init(USART1, &USART_InitStructure);							//配置串口参数函数	   

	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);                    //使能接收中断
	//USART_ITConfig(USART1, USART_IT_TXE, ENABLE);						//使能发送缓冲空中断

	USART_Cmd(USART1, ENABLE); //使能 USART1	
}
/****************************************************************************
* 名    称:void USART1_SendByte(uint8_t TxData)
* 功    能:串口1发送函数
* 入口参数:TxData
* 出口参数:无
* 说    明:
* 调用方法:无 
****************************************************************************/
void USART1_SendByte(uint8_t TxData)
{  
   USART_SendData(USART1, TxData);
   while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);     
}
/****************************************************************************
* 名    称:int fputc(int ch, FILE *f)
* 功    能:重定向c库函数printf到串口,重定向后可使用printf函数
* 入口参数:int ch, FILE *f
* 出口参数:int
* 说    明:
* 调用方法:无 
****************************************************************************/
int fputc(int ch, FILE *f)
{
	/* 发送一个字节数据到串口 */
	USART1_SendByte((uint8_t) ch);

	/* 等待发送完毕 */
	while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);		

	return (ch);
}
/****************************************************************************
* 名    称:int fgetc(FILE *f)
* 功    能:重定向c库函数scanf到串口,重写向后可使用scanf、getchar等函数
* 入口参数:FILE *f
* 出口参数:int
* 说    明:
* 调用方法:无 
****************************************************************************/
int fgetc(FILE *f)
{
	/* 等待串口输入数据 */
	while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);

	return (int)USART_ReceiveData(USART1);
}
/****************************************************************************
* 名    称:void uart_putc(uint8_t c)
* 功    能:向终端打印一个字符
* 入口参数:uint8_t c
* 出口参数:void
* 说    明:shell
* 调用方法:无 
****************************************************************************/
void uart_putc(uint8_t c)
{
	USART1_SendByte(c);
    if(c == '\n')
        uart_putc('\r');
}
/****************************************************************************
* 名    称:void uart_puts(uint8_t *str)
* 功    能:向终端打印一个字符串
* 入口参数:uint8_t *str
* 出口参数:无
* 说    明:shell
* 调用方法:无 
****************************************************************************/
void uart_puts(uint8_t *str)
{
    while(*str)
    {
        uart_putc(*str);
        str++;
    }
}
/****************************************************************************
* 名    称:uint8_t uart_getc(void)
* 功    能:从终端获取一个字符
* 入口参数:
* 出口参数:
* 说    明:
* 调用方法:无 
****************************************************************************/
uint8_t uart_getc(void)
{
    while(!rec_f);
		rec_f = 0;
    return (uint8_t)*USART1_RxBuffer;

}
/****************************************************************************
* 名    称:void uart_gets(uint8_t *buf, uint32_t len)
* 功    能:从终端获取一个字符串
* 入口参数:uint8_t *buf, uint32_t len
* 出口参数:无
* 说    明:shell
* 调用方法:无 
****************************************************************************/
void uart_gets(uint8_t *buf, uint32_t len)
{
    int i = 0;
    uint8_t tmp = 0;

    while(i < (len-1))
    {
        tmp = uart_getc();
        if(tmp==0x08 && i==0)
            continue;

        /*回显*/
        uart_putc(tmp);
        buf[i] = tmp;
        /**/
        if(tmp == '\r')
            break;
        if(tmp == 0x08){
            uart_putc(' ');
            uart_putc(0x08);
            i--;
            continue;
        }
        i++;
    }
    buf[i] = '\0';
}



/****************************************************************************
* 名    称:void Shell_Mode(void)
* 功    能:进入Shell模式
* 入口参数:无
* 出口参数:无
* 说    明:shell
* 调用方法:无 
****************************************************************************/
void Shell_Mode(void)
{
	uint8_t cmd_buf[32];
	_cmd *ptr = (_cmd *)0;
	
	
	/*判断是否输入进入Shell的命令*/	
	uart_gets(cmd_buf,sizeof(cmd_buf));			//等待输入"shell"命令
	
	if(!strcmp((char *)cmd_buf,"shell"))		
		printf("\nTANG Shell!\n");
	else 
		return;

	/*Shell模式*/
	while(1)
	{
		uart_puts("\nTANG(M3)# ");
	
		uart_gets(cmd_buf,sizeof(cmd_buf));
		
		if(!strcmp((char *)cmd_buf,"quit")){	//退出Shell模式
			printf("\nQuit Shell!\n\r");
			break;
		}
		
		ptr = find_cmd(cmd_buf);				//查找命令是否存在
		if(ptr) {
			printf("\r\n");
			ptr->cmd_func();					//命令处理函数
			printf("\r\n");
		}
		else{
			uart_puts("\nUnkonwn command ");
			uart_puts(cmd_buf);
		}
	}
	
}
/****************************************************************************
* 名    称:uint8_t Kill(void)
* 功    能:杀掉当前函数
* 入口参数:无
* 出口参数:被杀返回1 无操作返回0
* 说    明:shell
* 调用方法:无 
****************************************************************************/
uint8_t Kill(void)
{
	uint8_t cmd_buf[32];
	
	if(rec_f){
		rec_f = 0;
				
		uart_gets(cmd_buf,sizeof(cmd_buf));

		if(!strcmp((char *)cmd_buf,"kill")){		//结束函数执行
			printf("\nFunction terminated+\n");
			return 1;
		}
		else 
			return 0;
		
	}
	return 0;
}



           

uart.h

#ifndef _USART_H_
#define _USART_H_

#include "global.h"

#define USART_BAUDRATE (9600)

extern uint8_t  USART1_RxBuffer[25];		//串口接收缓冲区
extern uint8_t  USART1_TxBuffer[3];		//串口发送缓冲区
extern __IO uint8_t rec_f;

void USART1_Configuration(void);
void USART1_SendByte(uint8_t TxData);
void uart_gets(uint8_t *buf, uint32_t len);
void uart_puts(uint8_t *str);
void Shell_Mode(void);
uint8_t Kill(void);

#endif //_USART_H_
           

串口中断处理

/**
  * @brief  This function handles NMI exception.
  * @param  None
  * @retval : None
  */
void USART1_IRQHandler(void)      //串口1 中断服务程序
{
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)	   //判断读寄存器是否非空
	{	
		USART1_RxBuffer[0] = USART_ReceiveData(USART1);         //将读寄存器的数据缓存到接收缓冲区里
		rec_f=1;
		USART1_RxCounter++;  
		LED_Control(GPIOC,GPIO_Pin_15,0);
		//printf("IRQ串口发生中断!\n");
	}

	if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET)                   //这段是为了避免STM32 USART 第一个字节发不出去的BUG 
	{ 
		USART_ITConfig(USART1, USART_IT_TXE, DISABLE);					     //禁止发缓冲器空中断, 
	}	
}
           

cmd.c

解释一下cmd_list[] 这是一个命令列表  支持的所有命令都在这里边  如下边hello是命令  输入之后会执行Hello这个函数 

#include "cmd.h"

_cmd cmd_list[]=
{
	{"hello,Hello},
};
/****************************************************************************
* 名    称:_cmd *find_cmd(char *user_cmd)
* 功    能:查找命令对应的执行函数
* 入口参数:char *user_cmd
* 出口参数:_cmd *
* 说    明:
* 调用方法:无 
****************************************************************************/ 
_cmd *find_cmd(uint8_t *user_cmd)
{
    uint32_t i = 0;

    for(i = 0; i<sizeof(cmd_list)/sizeof(cmd_list[0]); i++){
        if(strcmp((char *)user_cmd, cmd_list[i].cmd_name) == 0)
            return &(cmd_list[i]);       
    }

    return (_cmd *)0;
}

static void Hello(void)
{
	printf("Hello,this is my shell!");
}
           

cmd.h

#ifndef __CMD_H__
#define __CMD_H__

#include "global.h"

typedef struct cmd
{
    char *cmd_name;//命令
    void (*cmd_func)(void);//对应处理函数
}_cmd;

extern _cmd *find_cmd(uint8_t *user_cmd);

/*支持的命令处理函数*/
static void Hello(void);
#endif	//__CMD_H__
           

main.c

int main(void)
{	
	RCC_Configuration();						   	//系统时钟设置及外设时钟使能	
	NVIC_Configuration();						   	//中断源配置	  
	GPIO_Configuration();						   	//LED控制初始化	 
	USART1_Configuration();
	

	printf("If you want to enter the shell mode, press \'Enter\' key and input \"shell\"! And then you can try input \"help\" commnd.\r\n");

 
	while (1)
	{	 	
		/*串口中断*/
		if(rec_f)	  //串口接收标志
		{  
			rec_f=0;
		
			Shell_Mode();    //输入"shell"即可进入shell模式
		}
		
	
	
}
           

继续阅读