一种STM32的串口控制台的实现(非常实用)

来源:互联网 发布:棋牌类游戏源码 编辑:程序博客网 时间:2024/05/30 21:58

一.背景

曾经玩Linux时非常喜欢这种基于出串口的控制台, 通过简单的串口TX和RX能实现嵌入式硬件的人机交互,非常实用,  那么STM32能否实现通过超级终端与用户互动的构想呢? 答案是肯定的,由于这个UART控制平台就像应用程序套上一层可访问的外科(Shell)故而我将这种基于UART的控制平台简称Shell,构架和效果如下图:




这张图箭头指向的是输入的指令,其余是STM32串口输出的信息,, 可以看到通过这些简单的指令输入我们通过Shell可以做很多事情:

1. 现场设备发生故障,可以通过Shell可以查看设备的故障状态统计信息

2. 能实现串口程序升级(需要Shell+IAP驱动程序支持)

3. 能读写访问参数区,实现对设备参数的本地配置

4. 配置多功能信号指示灯(LED灯可显示65535种信号,同一时刻只能显示一个.

5. 程序开发阶段基于Shell,可以极其方便的调试编写的驱动程序(开发极力推荐),非常好用.


二.Shell基础篇

Shell基础程序只有三个文件:

console.h:用于定义STM32用于Shell的实体串口

shell.cshell平台实现主体

shell.h头文件,任意的驱动文件可调用,就像<stdio.h>一样


shell.c目前包含三个部件:

shell模块(必选)Shell模块初始化时已初始化好Led模块

Led模块(必选)Ledx_on(x),Ledx_off(x),Ledx_div(x),函数是对编码信号进行控制,而不是直接对硬件实体控制,这样每个LED实体就像通道一样可以选择非常多的信号源显示.

精密延时模块(可选)启动需要对其初始化,此模块可用于记录时间点,并判断时间是否到(再也不用Delayms()这样的函数浪费效率实现时序了.


三. 程序文件:

1. console.h

/*********************************Copyright (c)***********************************                               **                                 FIVE工作组****---------------------------------File Info------------------------------------** File Name:               shell_hal.h** Last modified Date:      2014/5/26 14:22:35** Last Version:            V1.0  ** Description:             本地Shell文件接口****------------------------------------------------------------------------------** Created By:              wanxuncpx** Created date:            2014/5/26 14:22:34** Version:                 V2** Descriptions:            只适合STM32程序**------------------------------------------------------------------------------** Libraries:               STM32F10x_StdPeriph_Driver** version                  V3.5*******************************************************************************//******************************************************************************更新说明:******************************************************************************//***************************************************************************************************************  应 用 资 料 **************************************************************************************************************/#ifndef _SHELL_HAL_#define _SHELL_HAL_/*************************************************************************************************************** 文件引用部分 **************************************************************************************************************///包含库文件#include "stm32f10x.h"#include "stm32f10x_gpio.h"#include "stm32f10x_rcc.h"#include "stm32f10x_tim.h"/************************************************************************************************************** 可 配 置 参 数 *************************************************************** MNCS_IMAGE图像板 ***********************************************************************************************************//*---------------------* *     UART端口配置*----------------------*///IO配置#define CONSOLE                 USART3 #define CONSOLE_TX_PORT         GPIOB#define CONSOLE_TX_PIN          GPIO_Pin_10#define CONSOLE_RX_PORT         GPIOB#define CONSOLE_RX_PIN          GPIO_Pin_11//时钟配置#define CONSOLE_GPIO_RCC_INIT() RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE)#define CONSOLE_UART_RCC_INIT() RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE)//中断优先级#define CONSOLE_UART_PRIO       7       //建议[0..15]//中断向量配置#define CONSOLE_IRQn            USART3_IRQn;#define CONSOLE_IRQHandler      USART3_IRQHandler/*---------------------* *     四个LED定义*----------------------*/#define LED0_VALID              1           //非零表示使能对应的LED,0:无效#define LED0_PORT               GPIOB#define LED0_PIN                GPIO_Pin_13#define LED1_VALID              1           //非零表示使能对应的LED,0:无效#define LED1_PORT               GPIOB#define LED1_PIN                GPIO_Pin_15#define LED2_VALID              0           //非零表示使能对应的LED,0:无效#define LED2_PORT               GPIOA#define LED2_PIN                GPIO_Pin_11#define LED3_VALID              0           //非零表示使能对应的LED,0:无效#define LED3_PORT               GPIOA#define LED3_PIN                GPIO_Pin_11#define LED4_VALID              0           //非零表示使能对应的LED,0:无效#define LED4_PORT               GPIOA#define LED4_PIN                GPIO_Pin_11#define LED5_VALID              0           //非零表示使能对应的LED,0:无效#define LED5_PORT               GPIOA#define LED5_PIN                GPIO_Pin_11/*---------------------* *        时基BASE*----------------------*/#define TIMEDly                 TIM4#define TIMEDly_IRQn            TIM4_IRQn#define TIMEDly_IRQHandler      TIM4_IRQHandler//时钟配置            #define TIMEDly_RCC_INIT()      RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);//初始化LGPIO口#define LEDx_GPIO_RCC_INIT()    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE)//------------------------------------------------------------------------------/************************************************************************************************************* 以下参数无需更改 ************************************************************************************************************//*---------------------* *  注意以下区域无需用户更改*----------------------*/#if LED0_VALID  #define LED0_ON()             (LED0_PORT->BRR  = LED0_PIN)  #define LED0_OFF()            (LED0_PORT->BSRR = LED0_PIN)  #define LED0_DIV()            (LED0_PORT->ODR  ^= LED0_PIN)#else  #define LED0_ON()             __NOP()  #define LED0_OFF()            __NOP()  #define LED0_DIV()            __NOP()#endif#if LED1_VALID  #define LED1_ON()             (LED1_PORT->BRR  = LED1_PIN)  #define LED1_OFF()            (LED1_PORT->BSRR = LED1_PIN)  #define LED1_DIV()            (LED1_PORT->ODR ^= LED1_PIN)#else  #define LED1_ON()             __NOP()  #define LED1_OFF()            __NOP()  #define LED1_DIV()            __NOP()#endif #if LED2_VALID  #define LED2_ON()             (LED2_PORT->BRR  = LED2_PIN)  #define LED2_OFF()            (LED2_PORT->BSRR = LED2_PIN)  #define LED2_DIV()            (LED2_PORT->ODR ^= LED2_PIN)#else  #define LED2_ON()             __NOP()  #define LED2_OFF()            __NOP()  #define LED2_DIV()            __NOP()#endif  #if LED3_VALID  #define LED3_ON()             (LED3_PORT->BRR  = LED3_PIN)  #define LED3_OFF()            (LED3_PORT->BSRR = LED3_PIN)  #define LED3_DIV()            (LED3_PORT->ODR ^= LED3_PIN)#else  #define LED3_ON()             __NOP()  #define LED3_OFF()            __NOP()  #define LED3_DIV()            __NOP()#endif#if LED4_VALID  #define LED4_ON()             (LED4_PORT->BSRR = LED4_PIN)  #define LED4_OFF()            (LED4_PORT->BRR  = LED4_PIN)  #define LED4_DIV()            (LED4_PORT->ODR ^= LED4_PIN)#else  #define LED4_ON()             __NOP()  #define LED4_OFF()            __NOP()  #define LED4_DIV()            __NOP()#endif#if LED5_VALID  #define LED5_ON()             (LED5_PORT->BSRR = LED5_PIN)  #define LED5_OFF()            (LED5_PORT->BRR  = LED5_PIN)  #define LED5_DIV()            (LED5_PORT->ODR ^= LED5_PIN)#else  #define LED5_ON()             __NOP()  #define LED5_OFF()            __NOP()  #define LED5_DIV()            __NOP()#endif/************************************************************************************************************* printf支持文件 **************************************************************************************************************//* Private function prototypes -----------------------------------------------*/#ifdef __GNUC__/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf   set to 'Yes') calls __io_putchar() */#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)#else#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)#endif /* __GNUC__ *//*****************************************************************************************************************   END  ******************************************************************************************************************/#endif



2. shell.h

/*********************************Copyright (c)***********************************                               **                                 FIVE工作组****---------------------------------File Info------------------------------------** File Name:               shell.h** Last modified Date:      2014/3/5 15:42:05** Last Version:            V2   ** Description:             none****------------------------------------------------------------------------------** Created By:              wanxuncpx** Created date:            2014/3/5 15:42:11** Version:                 V2** Descriptions:            none**------------------------------------------------------------------------------** Libraries:               无关** version                  无关*******************************************************************************//******************************************************************************更新说明:******************************************************************************//***************************************************************************************************************  应 用 资 料 **************************************************************************************************************/#ifndef _SHELL_H_#define _SHELL_H_/*************************************************************************************************************** 文件引用部分 **************************************************************************************************************/#include "stdint.h"         //包含uint8_t等数据类型#include "stdbool.h"        //包含Bool类型#include "stdio.h"          //包含printf支持/*************************************************************************************************************** 参数宏定义 ***************************************************************************************************************///版本定义#define SHELL_VER           2       //Shell版本#ifndef SHELL_LED_MAX               //LED实体数量  #define SHELL_LED_MAX     4#endif//缓冲大小配置#define SHELL_RX_MAX        (256+32)        //shell指令接收缓冲大小#define SHELL_TX_MAX        (512)           //shell指令发送缓冲大小/*************************************************************************************************************** 数 据 声 明 ***************************************************************************************************************//*---------------------* *     Shell接收*----------------------*///接收数据extern volatile uint16_t   shell_rx_rdy;                    //0:空闲,非零:忙,用户读为非零后清零extern volatile uint8_t    shell_rx_buff[SHELL_RX_MAX+1];   //接收缓冲/*************************************************************************************************************** 函 数 声 明 ***************************************************************************************************************//*---------------------* *    输出函数*----------------------*///调试Shell的接口数量#if     (6 == SHELL_LED_MAX)  extern void shell_GPIO_Config(uint16_t led0_cfg,uint16_t led1_cfg,                                uint16_t led2_cfg,uint16_t led3_cfg,                                uint16_t led4_cfg,uint16_t led5_cfg);#elif   (5 == SHELL_LED_MAX)  extern void shell_GPIO_Config(uint16_t led0_cfg,uint16_t led1_cfg,                                uint16_t led2_cfg,uint16_t led3_cfg,                                uint16_t led4_cfg);#elif   (4 == SHELL_LED_MAX)  extern void shell_GPIO_Config(uint16_t led0_cfg,uint16_t led1_cfg,                                uint16_t led2_cfg,uint16_t led3_cfg);#elif   (3 == SHELL_LED_MAX)  extern void shell_GPIO_Config(uint16_t led0_cfg,uint16_t led1_cfg,                                uint16_t led2_cfg);#elif   (2 == SHELL_LED_MAX)  extern void shell_GPIO_Config(uint16_t led0_cfg,uint16_t led1_cfg);#elif   (1 == SHELL_LED_MAX)  extern void shell_GPIO_Config(uint16_t led0_cfg);#endif//检测参数合法性#if ((SHELL_LED_MAX > 6) || (SHELL_LED_MAX == 0))  #error SHELL_LED_MAX is invaild!#endif//初始化Shellextern void shell_Init(uint32_t baud);          //模块初始化extern void shell_SendStr(void * ptStr);        //发送以'\0'结束的字符串extern void shell_SendHex(void * ptHex,uint16_t size);  //发送指定个数的数据/*---------------------* *    LEDx测试信号定义*----------------------*/extern void Ledx_config(uint8_t led_id,uint16_t msg_id);    //设置LED的配置信号extern uint16_t Ledx_read(uint8_t led_id);                  //读取LED的配置信号(失败返回0)extern  void Ledx_on (uint16_t msg_id);             //发送LED开消息extern  void Ledx_off(uint16_t msg_id);             //发送LED关消息extern  void Ledx_div(uint16_t msg_id);             //发送LED取反消息/*---------------------* *     时基延时函数*----------------------*/extern void Delay_LibInit(void);extern void DlyTime_us(uint16_t us);extern void DlyTime_ms(uint16_t ms);extern void DlyWait_base(volatile uint64_t * ptCnt);    //标记为等待的基点时间extern uint32_t DlyWait_lost(volatile uint64_t * ptCnt);//判断逝去的时间(us)/*---------------------* *     辅助判断指令*----------------------*/extern bool StrComp(void * buffer,void * StrCmd);   //字符串匹配比较函数/*---------------------* *       Shell服务*----------------------*///在main.c函数while()中判断shell_rx_rdy是否为非零,为非零才执行以下程序extern void Shell_Invalid_Service(void); //指令未处理服务(会处理shell_rx_rdy信号)/*****************************************************************************************************************   END  ******************************************************************************************************************/#endif


3.shell.c

/*********************************Copyright (c)***********************************                               **                                 FIVE工作组****---------------------------------File Info------------------------------------** File Name:               shell.c** Last modified Date:      2014/3/5 16:43:59** Last Version:            V2  ** Description:             none****------------------------------------------------------------------------------** Created By:              wanxuncpx** Created date:            2014/3/5 16:43:58** Version:                 V2** Descriptions:            适合于STM32**------------------------------------------------------------------------------** Libraries:               STM32F10x_StdPeriph_Driver** version                  V3.5*******************************************************************************//******************************************************************************更新说明:******************************************************************************//***************************************************************************************************************  应 用 资 料 **************************************************************************************************************//*************************************************************************************************************** 文件引用部分 **************************************************************************************************************/#include "shell.h"      //包含Shell接口文件//是否使用扩展的Shell接口#ifdef SHELL_HAL_EXT  #include "shell_hal.h"    //本地的Shell文件#else  #include "console.h"      //标准的Shell文件#endif/*************************************************************************************************************** Shell.h定义 ***************************************************************************************************************//*---------------------* *     Shell 收发标记*----------------------*/volatile uint16_t   shell_rx_rdy = 0;                       //0:空闲,非零:忙volatile uint8_t    shell_rx_buff[SHELL_RX_MAX+1]="\0";   //接收缓冲/*************************************************************************************************************** 本 地 数 据 ***************************************************************************************************************//*---------------------* *     Shell缓冲定义*----------------------*///接收static volatile uint16_t    shell_rx_index = 0;             //数据接收标记//发送static volatile uint8_t     shell_tx_buff[SHELL_TX_MAX+1]="\0";static volatile uint16_t    shell_tx_size  = 0;             //0:空闲,非零:忙static volatile uint16_t    shell_tx_index = 0;             //发送数据标记/*---------------------* *     LED控制信号*----------------------*/static volatile uint16_t    msg_led_cfg[SHELL_LED_MAX];     //配置信号/*---------------------* *    延时模块定义*----------------------*/static volatile uint64_t    TimeDlyCnt = 0;                 //用于辅助的延时计数值/*************************************************************************************************************** 函 数 声 明 ***************************************************************************************************************//******************************************************************************/ 函数功能:初始化GPIO口(串口和四个LED灯配置)/ 修改日期:none/ 输入参数:none/ 输出参数:none/ 使用说明:none******************************************************************************/#if     (6 == SHELL_LED_MAX)    void shell_GPIO_Config( uint16_t led0_cfg,uint16_t led1_cfg,                            uint16_t led2_cfg,uint16_t led3_cfg,                            uint16_t led4_cfg,uint16_t led5_cfg)#elif   (5 == SHELL_LED_MAX)    void shell_GPIO_Config( uint16_t led0_cfg,uint16_t led1_cfg,                            uint16_t led2_cfg,uint16_t led3_cfg,                            uint16_t led4_cfg)#elif   (4 == SHELL_LED_MAX)    void shell_GPIO_Config( uint16_t led0_cfg,uint16_t led1_cfg,                            uint16_t led2_cfg,uint16_t led3_cfg)#elif   (3 == SHELL_LED_MAX)    void shell_GPIO_Config( uint16_t led0_cfg,uint16_t led1_cfg,                            uint16_t led2_cfg)#elif   (2 == SHELL_LED_MAX)    void shell_GPIO_Config(uint16_t led0_cfg,uint16_t led1_cfg)#elif   (1 == SHELL_LED_MAX)    void shell_GPIO_Config(uint16_t led0_cfg)#endif{GPIO_InitTypeDef GPIO_InitStruct;    /* 配置串口 ---------------------------------------------------------*/// 打开在APB2上的GPIO口外设时钟CONSOLE_GPIO_RCC_INIT();    //打开GPIO口的时钟// 配置TX引脚GPIO_InitStruct.GPIO_Pin    = CONSOLE_TX_PIN;GPIO_InitStruct.GPIO_Mode   = GPIO_Mode_AF_PP;GPIO_InitStruct.GPIO_Speed  = GPIO_Speed_50MHz;GPIO_Init(CONSOLE_TX_PORT,  &GPIO_InitStruct);// 配置RX引脚GPIO_InitStruct.GPIO_Pin    = CONSOLE_RX_PIN;GPIO_InitStruct.GPIO_Mode   = GPIO_Mode_IPU;GPIO_Init(CONSOLE_RX_PORT,  &GPIO_InitStruct);    //锁定GPIO口,防止其他更改    GPIO_PinLockConfig(CONSOLE_TX_PORT,CONSOLE_TX_PIN);    GPIO_PinLockConfig(CONSOLE_RX_PORT,CONSOLE_RX_PIN);        /* 配置LEDx ---------------------------------------------------------*/    LEDx_GPIO_RCC_INIT();    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;//根据定义配置四个LED  #if (SHELL_LED_MAX > 0)    GPIO_InitStruct.GPIO_Pin    = LED0_PIN;GPIO_Init(LED0_PORT,   &GPIO_InitStruct);GPIO_PinLockConfig(LED0_PORT,LED0_PIN);    msg_led_cfg[0] = led0_cfg;LED0_OFF();  #endif  #if (SHELL_LED_MAX > 1)    GPIO_InitStruct.GPIO_Pin    = LED1_PIN;GPIO_Init(LED1_PORT,   &GPIO_InitStruct);GPIO_PinLockConfig(LED1_PORT,LED1_PIN);msg_led_cfg[1] = led1_cfg;LED1_OFF();  #endif  #if (SHELL_LED_MAX > 2)    GPIO_InitStruct.GPIO_Pin    = LED2_PIN;GPIO_Init(LED2_PORT,   &GPIO_InitStruct);GPIO_PinLockConfig(LED2_PORT,LED2_PIN);msg_led_cfg[2] = led2_cfg;LED2_OFF();  #endif  #if (SHELL_LED_MAX > 3)    GPIO_InitStruct.GPIO_Pin    = LED3_PIN;GPIO_Init(LED3_PORT,   &GPIO_InitStruct);GPIO_PinLockConfig(LED3_PORT,LED3_PIN);msg_led_cfg[3] = led3_cfg;LED3_OFF();  #endif   #if (SHELL_LED_MAX > 4)    GPIO_InitStruct.GPIO_Pin    = LED4_PIN;GPIO_Init(LED4_PORT,   &GPIO_InitStruct);GPIO_PinLockConfig(LED4_PORT,LED4_PIN);msg_led_cfg[4] = led4_cfg;LED4_OFF();  #endif   #if (SHELL_LED_MAX > 5)    GPIO_InitStruct.GPIO_Pin    = LED5_PIN;GPIO_Init(LED5_PORT,   &GPIO_InitStruct);GPIO_PinLockConfig(LED5_PORT,LED5_PIN);msg_led_cfg[5] = led5_cfg;LED5_OFF();  #endif }/******************************************************************************/ 函数功能:串口初始化,使用中断单字节接收数据/ 修改日期:none/ 输入参数:baud 波特率/ 输出参数:none/ 使用说明:none******************************************************************************/void shell_Init(uint32_t baud){    USART_InitTypeDef   USART_InitStructure;    NVIC_InitTypeDef    NVIC_UART_Cfg;  //UART中断向量        //--------------------------- 先定义好数据结构 ---------------------------    //定义好USART结构体    USART_InitStructure.USART_BaudRate      = baud;    USART_InitStructure.USART_WordLength    = USART_WordLength_8b;    USART_InitStructure.USART_StopBits      = USART_StopBits_1;    USART_InitStructure.USART_Parity        = USART_Parity_No ;    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;    USART_InitStructure.USART_Mode          = USART_Mode_Tx | USART_Mode_Rx;    USART_InitStructure.USART_BaudRate = USART_InitStructure.USART_BaudRate;    //防止编译报错        //定义好NVIC:UART中断    NVIC_UART_Cfg.NVIC_IRQChannel = CONSOLE_IRQn;    NVIC_UART_Cfg.NVIC_IRQChannelPreemptionPriority = 1;    NVIC_UART_Cfg.NVIC_IRQChannelSubPriority = CONSOLE_UART_PRIO;    NVIC_UART_Cfg.NVIC_IRQChannelCmd = ENABLE;    NVIC_UART_Cfg.NVIC_IRQChannel = NVIC_UART_Cfg.NVIC_IRQChannel;              //防止编译报错        //模式配置    //--------------------------- 中断方式收发数据 ----------------------------    CONSOLE_UART_RCC_INIT();                                //打开USART的时钟    USART_Cmd(CONSOLE, DISABLE);                            //关闭UART        USART_Init(CONSOLE, &USART_InitStructure);              //初始化串口        USART_ITConfig(CONSOLE, USART_IT_RXNE, ENABLE);    USART_ITConfig(CONSOLE, USART_IT_IDLE, ENABLE);        USART_Cmd(CONSOLE, ENABLE);        NVIC_Init(&NVIC_UART_Cfg);                              //配置好NVIC}/******************************************************************************/ 函数功能:Delay延时库初始化(需要1us的计数精度,和50ms的溢出计数)/ 修改日期:2014/5/1 21:02:58/ 输入参数:none/ 输出参数:none/ 使用说明:(限STM32F40X的TIM2,TIM3,TIM4,TIM5)******************************************************************************/void Delay_LibInit(void){    TIM_TimeBaseInitTypeDef     TIM_TimeBaseStructure;    NVIC_InitTypeDef            NVIC_InitStructure;        //开启TIM2时钟    TIMEDly_RCC_INIT();    /* Enable the TIMx gloabal Interrupt */    NVIC_InitStructure.NVIC_IRQChannel                  = TIMEDly_IRQn;    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 0;    NVIC_InitStructure.NVIC_IRQChannelSubPriority       = 0;    //由于是时基,需要使用最高优先级    NVIC_InitStructure.NVIC_IRQChannelCmd               = ENABLE;    NVIC_Init(&NVIC_InitStructure);      /* Time base configuration */    TIM_TimeBaseStructure.TIM_Period    = 65000;    TIM_TimeBaseStructure.TIM_Prescaler     = (SystemCoreClock/1000000)-1;    TIM_TimeBaseStructure.TIM_ClockDivision = 0;    TIM_TimeBaseStructure.TIM_CounterMode    = TIM_CounterMode_Up;    TIM_TimeBaseInit(TIMEDly, &TIM_TimeBaseStructure);       /* TIM Interrupts enable */    TIM_ITConfig(TIMEDly,TIM_IT_Update, ENABLE);    /* TIMx enable counter */    TIM_Cmd(TIMEDly, ENABLE);}/******************************************************************************/ 函数功能:等待一个us延时/ 修改日期:2014/5/1 21:02:58/ 输入参数:none/ 输出参数:none/ 使用说明:none******************************************************************************/void DlyTime_us(uint16_t us){   uint64_t this_cnt,over_cnt,tmp_val;       //得到当前的准确时间    do    {        this_cnt = TIMEDly->CNT + TimeDlyCnt;        if( (TIMEDly->SR    & TIM_IT_Update)    &&            (TIMEDly->SR    & TIM_IT_Update)    &&            (TIMEDly->SR    & TIM_IT_Update)    )        {            TIMEDly->SR =   (uint16_t)~TIM_IT_Update;            TimeDlyCnt  +=  65000;          }        tmp_val = TIMEDly->CNT + TimeDlyCnt;     }    while(this_cnt != tmp_val);    over_cnt = this_cnt + us;       //得到目标延时时间        //延时函数    do    {        if( (TIMEDly->SR    & TIM_IT_Update)    &&            (TIMEDly->SR    & TIM_IT_Update)    &&            (TIMEDly->SR    & TIM_IT_Update)    )        {            TIMEDly->SR =   (uint16_t)~TIM_IT_Update;            TimeDlyCnt  +=  65000;          }                this_cnt = TIMEDly->CNT + TimeDlyCnt;    }    while(this_cnt < over_cnt);}/******************************************************************************/ 函数功能:等待一个ms延时/ 修改日期:2014/5/1 21:02:58/ 输入参数:none/ 输出参数:none/ 使用说明:none******************************************************************************/void DlyTime_ms(uint16_t ms){   uint64_t this_cnt,over_cnt,tmp_val;       //得到当前的准确时间    do    {        this_cnt = TIMEDly->CNT + TimeDlyCnt;        if( (TIMEDly->SR    & TIM_IT_Update)    &&            (TIMEDly->SR    & TIM_IT_Update)    &&            (TIMEDly->SR    & TIM_IT_Update)    )        {            TIMEDly->SR =   (uint16_t)~TIM_IT_Update;            TimeDlyCnt  +=  65000;          }        tmp_val = TIMEDly->CNT + TimeDlyCnt;     }    while(this_cnt != tmp_val);    over_cnt = this_cnt + (uint32_t)ms*1000;        //延时函数    do    {        if( (TIMEDly->SR    & TIM_IT_Update)    &&            (TIMEDly->SR    & TIM_IT_Update)    &&            (TIMEDly->SR    & TIM_IT_Update)    )        {            TIMEDly->SR =   (uint16_t)~TIM_IT_Update;            TimeDlyCnt  +=  65000;          }        this_cnt = TIMEDly->CNT + TimeDlyCnt;    }    while(this_cnt < over_cnt);}/******************************************************************************/ 函数功能:标记时间起点/ 修改日期:2014/5/1 21:02:58/ 输入参数:none/ 输出参数:none/ 使用说明:none******************************************************************************/void DlyWait_base(volatile uint64_t * ptCnt){    uint64_t this_cnt,tmp_val;        //得到当前的准确时间    do    {        this_cnt = TIMEDly->CNT + TimeDlyCnt;        if( (TIMEDly->SR    & TIM_IT_Update)    &&            (TIMEDly->SR    & TIM_IT_Update)    &&            (TIMEDly->SR    & TIM_IT_Update)    )        {            TIMEDly->SR =   (uint16_t)~TIM_IT_Update;            TimeDlyCnt  +=  65000;          }        tmp_val = TIMEDly->CNT + TimeDlyCnt;     }    while(this_cnt != tmp_val);    *ptCnt = this_cnt;}/******************************************************************************/ 函数功能:检测从起点开始已逝去的时间(最大1个小时)/ 修改日期:2014/5/1 21:02:58/ 输入参数:none/ 输出参数:返回0表示时间到,返回非零表示时间未到/ 使用说明:none******************************************************************************/uint32_t DlyWait_lost(volatile uint64_t * ptCnt){    uint64_t this_cnt,tmp_val;        //得到当前的准确时间    do    {        this_cnt = TIMEDly->CNT + TimeDlyCnt;        if( (TIMEDly->SR    & TIM_IT_Update)    &&            (TIMEDly->SR    & TIM_IT_Update)    &&            (TIMEDly->SR    & TIM_IT_Update)    )        {            TIMEDly->SR =   (uint16_t)~TIM_IT_Update;            TimeDlyCnt  +=  65000;         }        tmp_val = TIMEDly->CNT + TimeDlyCnt;     }    while(this_cnt != tmp_val);        //计算已逝去的时间    if(*ptCnt <= this_cnt)    {        tmp_val = this_cnt - *ptCnt;        if(tmp_val > (65536UL*65536UL-1))                return (uint32_t)(65536UL*65536UL-1);        else    return (uint32_t)tmp_val;    }    else    {        *ptCnt = this_cnt;        return 0;           }}/******************************************************************************/ 函数功能:中断支持函数(限STM32F40X的TIM2,TIM3,TIM4,TIM5)/ 修改日期:2014/5/1 21:02:58/ 输入参数:none/ 输出参数:none/ 使用说明:none******************************************************************************/ void TIMEDly_IRQHandler(void){    //简单写法    if( TIMEDly->SR & TIM_IT_Update )    {        TIMEDly->SR = (uint16_t)~TIM_IT_Update;        TimeDlyCnt += 65000;        //Ledx_div(3);        //时基信号    }}/******************************************************************************/ 函数功能:printf支持函数/ 修改日期:none/ 输入参数:none/ 输出参数:none/ 使用说明:none******************************************************************************/PUTCHAR_PROTOTYPE{    Ledx_on(11);    /* Loop until the end of transmission */    while( (CONSOLE->SR & USART_FLAG_TXE) == RESET );        /* Place your implementation of fputc here */    /* e.g. write a character to the USART */    CONSOLE->DR = ch;        /* Loop until the end of transmission */    //while( (CONSOLE->SR & USART_FLAG_TC) == RESET );    Ledx_off(11);    return ch;}/******************************************************************************/ 函数功能:字符串发送函数/ 修改日期:none/ 输入参数:none/ 输出参数:none/ 使用说明:none******************************************************************************/void shell_SendStr(void * ptAsc){                                   //中断方式    //--------------------------- 中断方式收发数据 ----------------------------    uint16_t        i,size;    uint8_t         *ptDst;    uint8_t const   *ptSrc;     //源数据只读不写        //计算字符串的长度    ptSrc = (uint8_t const *)ptAsc;    size  = 0;    while(*ptSrc++){size++;}        //判断字符串是否超过缓冲    Ledx_on(11);    if(size > SHELL_TX_MAX)    {        //关闭中断发送方式        shell_tx_index = 0;        shell_tx_size  = 0;        CONSOLE->CR1 &= ~USART_CR1_TXEIE;        //关闭发送完毕中断                ptSrc = (uint8_t const *)ptAsc;        while(size--)        {            while( (CONSOLE->SR & USART_FLAG_TXE) == RESET );            CONSOLE->DR = *ptSrc++;        }        Ledx_off(11);    }    else if( !(CONSOLE->CR1 & USART_CR1_TXEIE) )    {        //如果未启用非空中断则,启用非空中断发送数据        //复制数据        ptDst = (uint8_t *)shell_tx_buff;        ptSrc = (uint8_t const *)ptAsc;        for(i=0; i<size; i++)            *ptDst++ = *ptSrc++;                //启动发送中断        shell_tx_index = 0;        shell_tx_size  = size;        CONSOLE->CR1 |= USART_CR1_TXEIE;        //启动发送非空中断            }}/******************************************************************************/ 函数功能:发送Hex数据函数/ 修改日期:none/ 输入参数:none/ 输出参数:none/ 使用说明:none******************************************************************************/void shell_SendHex(void * ptHex,uint16_t size){                                  //中断方式    //--------------------------- 中断方式收发数据 ----------------------------    uint16_t        i;    uint8_t         *ptDst;    uint8_t const   *ptSrc;     //源数据只读不写    Ledx_on(11);    if(size > SHELL_TX_MAX)    {        //关闭中断发送方式        shell_tx_index = 0;        shell_tx_size  = 0;        CONSOLE->CR1 &= ~USART_CR1_TXEIE;        //关闭发送完毕中断                //直接发送数据        ptSrc = (uint8_t const *)ptHex;        while(size--)        {            while( (CONSOLE->SR & USART_FLAG_TXE) == RESET );            CONSOLE->DR = *ptSrc++;        }        Ledx_off(11);     }    else if( !(CONSOLE->CR1 & USART_CR1_TXEIE) )    {        //如果未启用非空中断则,启用非空中断发送数据        //复制数据        ptDst = (uint8_t *)shell_tx_buff;        ptSrc = (uint8_t const *)ptHex;           for(i=0; i<size; i++)            *ptDst++ = *ptSrc++;                //启动发送中断        shell_tx_index = 0;        shell_tx_size  = size;        CONSOLE->CR1 |= USART_CR1_TXEIE;        //启动发送非空中断         }}/******************************************************************************/ 函数功能:中断服务程序/ 修改日期:none/ 输入参数:none/ 输出参数:none/ 使用说明:none******************************************************************************/void CONSOLE_IRQHandler(void){    uint8_t     rxd_reg,txd_reg;    uint16_t    isr_reg;                                       //中断配置    //--------------------------- 中断方式收发数据 ----------------------------    isr_reg = CONSOLE->SR;    //接收中断    if( (CONSOLE->CR1 & USART_CR1_RXNEIE) && (isr_reg & USART_SR_RXNE) )    {        rxd_reg = CONSOLE->DR;        Ledx_on(12);        if(shell_rx_rdy)shell_rx_index = 0;     //忙模式收到字节,重置接收指针        else        {            if( shell_rx_index < SHELL_RX_MAX)            {                shell_rx_buff[shell_rx_index] = rxd_reg;                shell_rx_index++;            }            else            {                shell_rx_index = 0;                Ledx_off(12);                }        }    }        if( (CONSOLE->CR1 & USART_CR1_IDLEIE) && (isr_reg & USART_SR_IDLE) )    {        CONSOLE->SR;        CONSOLE->DR;        if(shell_rx_rdy)shell_rx_index = 0;     //忙模式收到空闲,重置接收指针        else        {            if( (shell_rx_index >=2) && ('\r' == shell_rx_buff[shell_rx_index-2]) &&                ('\n' == shell_rx_buff[shell_rx_index-1])   )       //以"\r\n"结尾            {                shell_rx_rdy = shell_rx_index;                shell_rx_index = 0;                Ledx_off(12);            }            else if( (shell_rx_index > 0) && ('\b' == shell_rx_buff[shell_rx_index-1]) )  //以\b结尾            {                shell_rx_index = shell_rx_index <2? 0:shell_rx_index-2;                printf(" \b");      //发送辅助删除                    }         }     }        //发送非空中断        if( (CONSOLE->CR1 & USART_CR1_TXEIE) && (isr_reg & USART_SR_TXE ) )    {        if(shell_tx_size && (shell_tx_index < shell_tx_size) )        {            txd_reg = shell_tx_buff[shell_tx_index++];            CONSOLE->DR = txd_reg;  //发送数据        }        else        {            //关闭非空中断            shell_tx_index = 0;            shell_tx_size = 0;            CONSOLE->CR1 &= ~USART_CR1_TXEIE;        //关闭发送完毕中断             Ledx_off(11);         }             }}/******************************************************************************/ 函数功能:指令(ASCII或HEX指令)未处理消息回执/ 修改日期:2013/9/12 20:25:45/ 输入参数:none/ 输出参数:none/ 使用说明:一字节一字节接收数据,拼装为指令******************************************************************************/void Shell_Invalid_Service(void){    int         tx_len,i,led_id,msg_id;    uint8_t *   ptSrc;    uint8_t *   ptDst;    uint8_t     tmp_buff[64];        //指令识别    if(2 > shell_rx_rdy)    {        shell_rx_buff[0]  = 0;        return;    }    else if( ('\r' == shell_rx_buff[shell_rx_rdy-2]) && ('\n' == shell_rx_buff[shell_rx_rdy-1]) )    {        ptSrc = (uint8_t *)shell_rx_buff;        if(2 == shell_rx_rdy)        {            //填写数据            tx_len = (uint16_t)sprintf((void *)tmp_buff,"\r\nAT:OK!\r\n");                    //发送数据            shell_SendHex(tmp_buff,tx_len);     //发送数据            }        else if(StrComp(ptSrc,"led rd\r\n"))   //显示LED的信号配置        {            //填写数据            tx_len = (uint16_t)sprintf((void *)tmp_buff,          #if     (6 == SHELL_LED_MAX)                "->LED0=%d  LED1=%d  tLED2=%d  LED3=%d  LED4=%d  LED5=%d\r\n",                msg_led_cfg[0],msg_led_cfg[1],msg_led_cfg[2],                msg_led_cfg[3],msg_led_cfg[4],msg_led_cfg[5]);          #elif   (5 == SHELL_LED_MAX)                "->LED0=%d  LED1=%d  tLED2=%d  LED3=%d  LED4=%d\r\n",                msg_led_cfg[0],msg_led_cfg[1],msg_led_cfg[2],                msg_led_cfg[3],msg_led_cfg[4]);          #elif   (4 == SHELL_LED_MAX)                "->LED0=%d  LED1=%d  tLED2=%d  LED3=%d\r\n",                msg_led_cfg[0],msg_led_cfg[1],msg_led_cfg[2],                msg_led_cfg[3]);          #elif   (3 == SHELL_LED_MAX)                "->LED0=%d  LED1=%d  tLED2=%d\r\n",                msg_led_cfg[0],msg_led_cfg[1],msg_led_cfg[2]);          #elif   (2 == SHELL_LED_MAX)                "->LED0=%d  LED1=%d\r\n",                msg_led_cfg[0],msg_led_cfg[1]);          #elif   (1 == SHELL_LED_MAX)                "->LED0=%d\r\n",                msg_led_cfg[0]);          #endif                    //发送数据            shell_SendHex(tmp_buff,tx_len);     //发送数据                }        else if(StrComp(ptSrc,"led wr "))      //设置LED的信号配置        {            if(2 != sscanf((void *)ptSrc,"%*s%*s%d=%d",&led_id,&msg_id) )goto ERROR_LOOP;            if( (led_id>(SHELL_LED_MAX-1)) || (msg_id >65535) )goto ERROR_LOOP;            Ledx_config((uint8_t)led_id,(uint16_t)msg_id);  //配置信号             //填写数据            tx_len = (uint16_t)sprintf((void *)tmp_buff,                "->LED[%d]_Msg=%d\r\n",led_id,msg_led_cfg[led_id]);            //发送数据            shell_SendHex(tmp_buff,tx_len);     //发送数据           }        else goto ERROR_LOOP;    }    else    {ERROR_LOOP:        //填写指令码        tx_len = (uint16_t)sprintf((void *)tmp_buff,"\r\nAT: Cmd Error:\t\"");                //计算地址,填写数据,填写尾部        ptDst = tmp_buff + tx_len;        ptSrc = (uint8_t *)shell_rx_buff;        if(shell_rx_rdy > 32)        {            for(i=0; i<32; i++)            {                 if( (*ptSrc > 126) || (*ptSrc < 32) )                {                    *ptDst++ = '?';                     ptSrc++;                   }                else                {                    *ptDst++ = *ptSrc++;                 }             }            *(ptDst-2) = '-';            *(ptDst-1) = '>';            tx_len += 32;        }        else        {            for(i=0; i<shell_rx_rdy; i++)            {                 *ptDst++ = *ptSrc++;                tx_len++;             }            *(ptDst-2) = '<';            *(ptDst-1) = '-';        }        tx_len += (uint16_t)sprintf((void *)ptDst,"\"\r\n");          //发送数据        shell_SendHex(tmp_buff,tx_len);  //发送数据    }        //清除数据返回程序    shell_rx_buff[0]  = 0;    shell_rx_rdy      = 0;}/******************************************************************************/ 函数功能:字符串测试匹配指令/ 修改日期:2014/3/5 19:30:22/ 输入参数:none/ 输出参数:none/ 使用说明:none******************************************************************************/bool StrComp(void * buffer,void * StrCmd){    uint8_t i;    uint8_t * ptBuf;    uint8_t * ptCmd;        ptBuf = (uint8_t *)buffer;    ptCmd = (uint8_t *)StrCmd;    for(i=0; i<255; i++)    {        if(ptCmd[i])        {            if(ptBuf[i] != ptCmd[i])return false;        }        else         {            if(i)return i;            else return false;            }    }    return false;}/******************************************************************************/ 函数功能:打开LED信号/ 修改日期:none/ 输入参数:none/ 输出参数:none/ 使用说明:none******************************************************************************/void Ledx_on(uint16_t msg_id){  #if (SHELL_LED_MAX > 0)    if(msg_id == msg_led_cfg[0])LED0_ON();  #endif  #if (SHELL_LED_MAX > 1)    if(msg_id == msg_led_cfg[1])LED1_ON();  #endif  #if (SHELL_LED_MAX > 2)    if(msg_id == msg_led_cfg[2])LED2_ON();  #endif  #if (SHELL_LED_MAX > 3)    if(msg_id == msg_led_cfg[3])LED3_ON();  #endif  #if (SHELL_LED_MAX > 4)    if(msg_id == msg_led_cfg[4])LED4_ON();  #endif  #if (SHELL_LED_MAX > 5)    if(msg_id == msg_led_cfg[5])LED5_ON();  #endif}/******************************************************************************/ 函数功能:关闭LED信号/ 修改日期:none/ 输入参数:none/ 输出参数:none/ 使用说明:none******************************************************************************/void Ledx_off(uint16_t msg_id){  #if (SHELL_LED_MAX > 0)    if(msg_id == msg_led_cfg[0])LED0_OFF();  #endif  #if (SHELL_LED_MAX > 1)    if(msg_id == msg_led_cfg[1])LED1_OFF();  #endif  #if (SHELL_LED_MAX > 2)    if(msg_id == msg_led_cfg[2])LED2_OFF();  #endif  #if (SHELL_LED_MAX > 3)    if(msg_id == msg_led_cfg[3])LED3_OFF();  #endif  #if (SHELL_LED_MAX > 4)    if(msg_id == msg_led_cfg[4])LED4_OFF();  #endif  #if (SHELL_LED_MAX > 5)    if(msg_id == msg_led_cfg[5])LED5_OFF();  #endif}/******************************************************************************/ 函数功能:取反LED信号/ 修改日期:none/ 输入参数:none/ 输出参数:none/ 使用说明:none******************************************************************************/void Ledx_div(uint16_t msg_id){  #if (SHELL_LED_MAX > 0)    if(msg_id == msg_led_cfg[0])LED0_DIV();  #endif  #if (SHELL_LED_MAX > 1)    if(msg_id == msg_led_cfg[1])LED1_DIV();  #endif  #if (SHELL_LED_MAX > 2)    if(msg_id == msg_led_cfg[2])LED2_DIV();  #endif  #if (SHELL_LED_MAX > 3)    if(msg_id == msg_led_cfg[3])LED3_DIV();  #endif  #if (SHELL_LED_MAX > 4)    if(msg_id == msg_led_cfg[4])LED4_DIV();  #endif  #if (SHELL_LED_MAX > 5)    if(msg_id == msg_led_cfg[5])LED5_DIV();  #endif}/******************************************************************************/ 函数功能:配置LED信号/ 修改日期:none/ 输入参数:none/ 输出参数:none/ 使用说明:none******************************************************************************/void Ledx_config(uint8_t led_id,uint16_t msg_id){    if(0 == led_id)     {LED0_OFF();msg_led_cfg[0]=msg_id;}  #if(SHELL_LED_MAX > 1)         else if(1 == led_id){LED1_OFF();msg_led_cfg[1]=msg_id;}  #endif  #if(SHELL_LED_MAX > 2)    else if(2 == led_id){LED2_OFF();msg_led_cfg[2]=msg_id;}  #endif  #if(SHELL_LED_MAX > 3)    else if(3 == led_id){LED3_OFF();msg_led_cfg[3]=msg_id;}  #endif  #if(SHELL_LED_MAX > 4)    else if(4 == led_id){LED4_OFF();msg_led_cfg[4]=msg_id;}  #endif  #if(SHELL_LED_MAX > 5)    else if(5 == led_id){LED5_OFF();msg_led_cfg[5]=msg_id;}  #endif }/******************************************************************************/ 函数功能:读取LED的配置信号/ 修改日期:none/ 输入参数:none/ 输出参数:none/ 使用说明:none******************************************************************************/uint16_t Ledx_read(uint8_t led_id){    if(0 == led_id)     return msg_led_cfg[0];  #if(SHELL_LED_MAX > 1)    else if(1 == led_id)return msg_led_cfg[1];  #endif  #if(SHELL_LED_MAX > 2)    else if(2 == led_id)return msg_led_cfg[2];  #endif  #if(SHELL_LED_MAX > 3)    else if(3 == led_id)return msg_led_cfg[3];  #endif  #if(SHELL_LED_MAX > 4)    else if(4 == led_id)return msg_led_cfg[4];  #endif  #if(SHELL_LED_MAX > 5)    else if(5 == led_id)return msg_led_cfg[5];  #endif     else return 0;}/*****************************************************************************************************************   END  ******************************************************************************************************************/


四. shell使用

以MDK为例:

1. 将shell.c等文件加入工程



2. 包含Shell.h,并外部声明shell服务程序


/***************************************************************************************************************Shell 函数声 明 ************************************************************************************************************/extern void Shell_SPI_Service(void);extern void Shell_RTC_Service(void);extern void Shell_WIZ_Service(void);extern void Shell_UPAN_Service(void);extern void Shell_IAP_Service(uint8_t const this_ver);

shell_GPIO_Config(30,10,46,1);  //shell接口和四个LED灯的信号配置shell_Init(460800);     //初始化shell控制台



3. 在main,c的大循环中添加以下代码

        //Shell构架的控制台服务        if(shell_rx_rdy)        {            Shell_IAP_Service(SOFT_VER);    //IAP模块指令处理            Shell_SPI_Service();            //SPI_FLASH模块指令处理            Shell_WIZ_Service();            //网卡模块的指令处理             Shell_RTC_Service();            //RTC模块的指令处理            Shell_MCU_Service();            //MCU杂项功能指令处理            Shell_VLSI_Service();           //声卡模块的指令处理            Shell_UPAN_Service();           //U盘模块的指令处理            Shell_Invalid_Service();        //指令无效的缺省处理        }

4. 编译下载文件到STM32,完成后字节在超级终端上敲击Enter就会显示AT:OK!的字样表示可以正常通讯

注意事项: 
1. 打开超级终端的本地回显功能
2. 有些终端工具输入Enter'时只输出(\r码) 如SecureCRT,这时需要将Enter映射按键(\r\n),winXP的超级终端输入Enter是输出(\r\n两个码值的)


五. RTC Shell服务文件示例

这里展示一个Shell服务的文件模板写法:

/*********************************Copyright (c)***********************************                               **                                 FIVE工作组****---------------------------------File Info------------------------------------** File Name:               rtc_shell.c** Last modified Date:      2014/3/5 9:27:49** Last Version:            V2.0  ** Description:             文件操作命令解释,需要Console Shell V2以上支持****------------------------------------------------------------------------------** Created By:              wanxuncpx** Created date:            2014/3/5 9:28:31** Version:                 V2.0** Descriptions:            none**------------------------------------------------------------------------------** HW_CMU:                  ANSIC** Libraries:               NONE** version                  NONE*******************************************************************************//******************************************************************************更新说明:******************************************************************************//***************************************************************************************************************  编 译 控 制 **************************************************************************************************************/#define RTC_SHELL       //注释掉时屏蔽iap shell功能/*************************************************************************************************************** 文件引用部分 **************************************************************************************************************//*---------------------* *     文件包含*----------------------*///基础支持文件#include "shell.h"          //Shell支持文件,含bool,uint8_t..以及串口数据收发操作#include "rtc.h"         //命令控制支持文件/*---------------------* *     Shell版本判断*----------------------*/#ifdef SHELL_VER  #if (SHELL_VER < 2)    #error "shell版本太低"  #endif#else    #error "未找到Shell文件,或shell版本信息"#endif/*************************************************************************************************************** 输出函数功能 **************************************************************************************************************//*---------------------* *       输出函数功能*----------------------*/#ifdef RTC_SHELL  extern void Shell_RTC_Service(void);#else  void Shell_RTC_Service(void){;}#endif/*---------------------* *       输入函数*----------------------*///none/*************************************************************************************************************** 数 据 声 明 ***************************************************************************************************************/#ifdef RTC_SHELL/*---------------------* *       *----------------------*///命令帮助文件const char RTC_HelpMsg[] ="[RTC contorls]\r\n"" rtc help\t\t- help.\r\n"" rtc rd info\t\t- Read RTC info.\r\n"" rtc rd time\t\t- Read RTC date and time.\r\n"" rtc wr time <Hour>:<Minute>:<Second>    - Write time.\r\n"" rtc wr date <Year>-<Month>-<Day> <Week> - Warning Week=[1..7]\r\n""\r\n";/*************************************************************************************************************** 函 数 声 明 ***************************************************************************************************************//******************************************************************************/ 函数功能:文件系统Shel指令处理/ 修改日期:2013/9/10 19:04:15/ 输入参数:输入当前的程序版本/ 输出参数:none/ 使用说明:none******************************************************************************/void Shell_RTC_Service(void){    uint8_t     *ptRxd;         //用于接收指令处理    //uint8_t     *ptTxd;         //方便用于指令发送    int         i,j,k,l;    //int         tx_len,drv;    //uint32_t    u32_arg[4];    uint16_t    retval;    uint8_t     arg[32];    uint32_t    tmp_time;    //指令初级过滤    //--------------------------------------------------------------------------    //格式:<->[cmd bytes]<CRLF>  即"-[cmd bytes]\r\n"    //指令必须以"-"开始, 以"\r\n"结束    i = shell_rx_rdy;    if( (i < 2) || ('\r' != shell_rx_buff[i-2]) || ('\n' != shell_rx_buff[i-1]))return;        //长度和前缀过滤    ptRxd = (uint8_t *)shell_rx_buff;    if( (' ' != shell_rx_buff[3]) || ('r' != shell_rx_buff[0]) || (i < 6) ||         ('t' != shell_rx_buff[1]) || ('c' != shell_rx_buff[2]) )  return;            //处理指令    //--------------------------------------------------------------------------    ptRxd += 4;    if(StrComp(ptRxd,"rd time"))    //按包读取指令    {        RTC_Sprintf_CurrTime((void *)arg);          printf("Time:%s\r\n",arg);     }    else if(StrComp(ptRxd,"rd info\r\n"))      //读取RTC信息    {        //打印当前时间和上次复位时间        RTC_Sprintf_CurrTime((void *)arg);         printf("->Time:%s\tResetCounter:%d\r\n",arg,RESET_CNT);        RTC_Sprintf_ResetCurr((void *)arg,&tmp_time);         printf("\tCurrReset:%s\tRun: %d Days, %d hour, %d minute\r\n",            arg,tmp_time/(24*60),(tmp_time%(24*60))/60,tmp_time%60 );         RTC_Sprintf_ResetLast((void *)arg,&tmp_time);         printf("\tNextReset:%s\tRun: %d Days, %d hour, %d minute\r\n",            arg,tmp_time/(24*60),(tmp_time%(24*60))/60,tmp_time%60 );        }    else if(StrComp(ptRxd,"wr time "))      //写时间    {        retval = sscanf((void*)shell_rx_buff,"%*s%*s%*s%d:%d:%d",&i,&j,&k);        if(3 != retval)return;   //没有接收到3个输入数据,直接退出        if(RTC_TimeWrite((uint8_t)i,(uint8_t)j,(uint8_t)k) )        {            RTC_Sprintf_CurrTime((void *)arg);            printf("->CurrTime:%s\r\n",arg);            }        else        {            printf("->Error Time Input!\r\n");            shell_rx_rdy = 0;       //不用触发错误指令显示             return;           }    }    else if(StrComp(ptRxd,"wr date "))      //写日期    {        retval = sscanf((void*)shell_rx_buff,"%*s%*s%*s%d-%d-%d %d",&i,&j,&k,&l);        if(4 != retval)return;   //没有接收到4个输入数据,直接退出        if(RTC_DateWrite((uint16_t)i,(uint8_t)j,(uint8_t)k,(uint8_t)l))        {            RTC_Sprintf_CurrTime((void *)arg);            printf("->CurrTime:%s\r\n",arg);            }        else        {            printf("->Error Date Input!\r\n");            shell_rx_rdy = 0;       //shell_rx_rdy为0,表示指令已被处理完毕,否者下个Shell服务继续调用            return;            }    }    else if(StrComp(ptRxd,"help\r\n"))      //指令帮助    {        shell_SendStr((void *)RTC_HelpMsg);    }    else return;        //退出处理    //--------------------------------------------------------------------------    shell_rx_rdy = 0;   //shell_rx_rdy为0,表示指令已被处理完毕,否者下个Shell服务继续调用}/*****************************************************************************************************************   END  ******************************************************************************************************************/#endif







1 0
原创粉丝点击