文件说明
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模式
}
}