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

一.背景

曾经玩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

[cpp] view plain copy
 
  1. /*********************************Copyright (c)********************************* 
  2. **                                
  3. **                                 FIVE工作组 
  4. ** 
  5. **---------------------------------File Info------------------------------------ 
  6. ** File Name:               shell_hal.h 
  7. ** Last modified Date:      2014/5/26 14:22:35 
  8. ** Last Version:            V1.0   
  9. ** Description:             本地Shell文件接口 
  10. ** 
  11. **------------------------------------------------------------------------------ 
  12. ** Created By:              wanxuncpx 
  13. ** Created date:            2014/5/26 14:22:34 
  14. ** Version:                 V2 
  15. ** Descriptions:            只适合STM32程序 
  16. **------------------------------------------------------------------------------ 
  17. ** Libraries:               STM32F10x_StdPeriph_Driver 
  18. ** version                  V3.5 
  19. *******************************************************************************/  
  20.   
  21. /****************************************************************************** 
  22. 更新说明: 
  23. ******************************************************************************/  
  24.   
  25. /****************************************************************************** 
  26. *********************************  应 用 资 料 ******************************** 
  27. ******************************************************************************/  
  28.   
  29. #ifndef _SHELL_HAL_  
  30. #define _SHELL_HAL_  
  31. /****************************************************************************** 
  32. ********************************* 文件引用部分 ******************************** 
  33. ******************************************************************************/  
  34. //包含库文件  
  35. #include "stm32f10x.h"  
  36. #include "stm32f10x_gpio.h"  
  37. #include "stm32f10x_rcc.h"  
  38. #include "stm32f10x_tim.h"  
  39.   
  40. /****************************************************************************** 
  41. ******************************** 可 配 置 参 数 ******************************* 
  42. ******************************** MNCS_IMAGE图像板 ***************************** 
  43. ******************************************************************************/  
  44. /*---------------------*  
  45. *     UART端口配置 
  46. *----------------------*/  
  47. //IO配置  
  48. #define CONSOLE                 USART3   
  49. #define CONSOLE_TX_PORT         GPIOB  
  50. #define CONSOLE_TX_PIN          GPIO_Pin_10  
  51. #define CONSOLE_RX_PORT         GPIOB  
  52. #define CONSOLE_RX_PIN          GPIO_Pin_11  
  53.   
  54. //时钟配置  
  55. #define CONSOLE_GPIO_RCC_INIT() RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE)  
  56. #define CONSOLE_UART_RCC_INIT() RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE)  
  57.   
  58. //中断优先级  
  59. #define CONSOLE_UART_PRIO       7       //建议[0..15]  
  60.   
  61. //中断向量配置  
  62. #define CONSOLE_IRQn            USART3_IRQn;  
  63. #define CONSOLE_IRQHandler      USART3_IRQHandler  
  64.   
  65. /*---------------------*  
  66. *     四个LED定义 
  67. *----------------------*/  
  68. #define LED0_VALID              1           //非零表示使能对应的LED,0:无效  
  69. #define LED0_PORT               GPIOB  
  70. #define LED0_PIN                GPIO_Pin_13  
  71.   
  72. #define LED1_VALID              1           //非零表示使能对应的LED,0:无效  
  73. #define LED1_PORT               GPIOB  
  74. #define LED1_PIN                GPIO_Pin_15  
  75.   
  76. #define LED2_VALID              0           //非零表示使能对应的LED,0:无效  
  77. #define LED2_PORT               GPIOA  
  78. #define LED2_PIN                GPIO_Pin_11  
  79.   
  80. #define LED3_VALID              0           //非零表示使能对应的LED,0:无效  
  81. #define LED3_PORT               GPIOA  
  82. #define LED3_PIN                GPIO_Pin_11  
  83.   
  84. #define LED4_VALID              0           //非零表示使能对应的LED,0:无效  
  85. #define LED4_PORT               GPIOA  
  86. #define LED4_PIN                GPIO_Pin_11  
  87.   
  88. #define LED5_VALID              0           //非零表示使能对应的LED,0:无效  
  89. #define LED5_PORT               GPIOA  
  90. #define LED5_PIN                GPIO_Pin_11  
  91.   
  92. /*---------------------*  
  93. *        时基BASE 
  94. *----------------------*/  
  95. #define TIMEDly                 TIM4  
  96. #define TIMEDly_IRQn            TIM4_IRQn  
  97. #define TIMEDly_IRQHandler      TIM4_IRQHandler  
  98.   
  99. //时钟配置              
  100. #define TIMEDly_RCC_INIT()      RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);  
  101.   
  102. //初始化LGPIO口  
  103. #define LEDx_GPIO_RCC_INIT()    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE)  
  104. //------------------------------------------------------------------------------  
  105.   
  106. /****************************************************************************** 
  107. ******************************* 以下参数无需更改 ****************************** 
  108. ******************************************************************************/  
  109. /*---------------------*  
  110. *  注意以下区域无需用户更改 
  111. *----------------------*/  
  112. #if LED0_VALID  
  113.   #define LED0_ON()             (LED0_PORT->BRR  = LED0_PIN)  
  114.   #define LED0_OFF()            (LED0_PORT->BSRR = LED0_PIN)  
  115.   #define LED0_DIV()            (LED0_PORT->ODR  ^= LED0_PIN)  
  116. #else  
  117.   #define LED0_ON()             __NOP()  
  118.   #define LED0_OFF()            __NOP()  
  119.   #define LED0_DIV()            __NOP()  
  120. #endif  
  121.   
  122. #if LED1_VALID  
  123.   #define LED1_ON()             (LED1_PORT->BRR  = LED1_PIN)  
  124.   #define LED1_OFF()            (LED1_PORT->BSRR = LED1_PIN)  
  125.   #define LED1_DIV()            (LED1_PORT->ODR ^= LED1_PIN)  
  126. #else  
  127.   #define LED1_ON()             __NOP()  
  128.   #define LED1_OFF()            __NOP()  
  129.   #define LED1_DIV()            __NOP()  
  130. #endif   
  131.   
  132. #if LED2_VALID  
  133.   #define LED2_ON()             (LED2_PORT->BRR  = LED2_PIN)  
  134.   #define LED2_OFF()            (LED2_PORT->BSRR = LED2_PIN)  
  135.   #define LED2_DIV()            (LED2_PORT->ODR ^= LED2_PIN)  
  136. #else  
  137.   #define LED2_ON()             __NOP()  
  138.   #define LED2_OFF()            __NOP()  
  139.   #define LED2_DIV()            __NOP()  
  140. #endif    
  141.   
  142. #if LED3_VALID  
  143.   #define LED3_ON()             (LED3_PORT->BRR  = LED3_PIN)  
  144.   #define LED3_OFF()            (LED3_PORT->BSRR = LED3_PIN)  
  145.   #define LED3_DIV()            (LED3_PORT->ODR ^= LED3_PIN)  
  146. #else  
  147.   #define LED3_ON()             __NOP()  
  148.   #define LED3_OFF()            __NOP()  
  149.   #define LED3_DIV()            __NOP()  
  150. #endif  
  151.   
  152. #if LED4_VALID  
  153.   #define LED4_ON()             (LED4_PORT->BSRR = LED4_PIN)  
  154.   #define LED4_OFF()            (LED4_PORT->BRR  = LED4_PIN)  
  155.   #define LED4_DIV()            (LED4_PORT->ODR ^= LED4_PIN)  
  156. #else  
  157.   #define LED4_ON()             __NOP()  
  158.   #define LED4_OFF()            __NOP()  
  159.   #define LED4_DIV()            __NOP()  
  160. #endif  
  161.   
  162. #if LED5_VALID  
  163.   #define LED5_ON()             (LED5_PORT->BSRR = LED5_PIN)  
  164.   #define LED5_OFF()            (LED5_PORT->BRR  = LED5_PIN)  
  165.   #define LED5_DIV()            (LED5_PORT->ODR ^= LED5_PIN)  
  166. #else  
  167.   #define LED5_ON()             __NOP()  
  168.   #define LED5_OFF()            __NOP()  
  169.   #define LED5_DIV()            __NOP()  
  170. #endif  
  171. /****************************************************************************** 
  172. ******************************* printf支持文件 ******************************** 
  173. ******************************************************************************/  
  174. /* Private function prototypes -----------------------------------------------*/  
  175. #ifdef __GNUC__  
  176. /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf 
  177.    set to 'Yes') calls __io_putchar() */  
  178. #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)  
  179. #else  
  180. #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)  
  181. #endif /* __GNUC__ */  
  182.   
  183. /****************************************************************************** 
  184. ***********************************   END  ************************************ 
  185. ******************************************************************************/  
  186. #endif  


 

2. shell.h

[cpp] view plain copy
 
  1. /*********************************Copyright (c)********************************* 
  2. **                                
  3. **                                 FIVE工作组 
  4. ** 
  5. **---------------------------------File Info------------------------------------ 
  6. ** File Name:               shell.h 
  7. ** Last modified Date:      2014/3/5 15:42:05 
  8. ** Last Version:            V2    
  9. ** Description:             none 
  10. ** 
  11. **------------------------------------------------------------------------------ 
  12. ** Created By:              wanxuncpx 
  13. ** Created date:            2014/3/5 15:42:11 
  14. ** Version:                 V2 
  15. ** Descriptions:            none 
  16. **------------------------------------------------------------------------------ 
  17. ** Libraries:               无关 
  18. ** version                  无关 
  19. *******************************************************************************/  
  20.   
  21. /****************************************************************************** 
  22. 更新说明: 
  23. ******************************************************************************/  
  24.   
  25. /****************************************************************************** 
  26. *********************************  应 用 资 料 ******************************** 
  27. ******************************************************************************/  
  28.   
  29. #ifndef _SHELL_H_  
  30. #define _SHELL_H_  
  31. /****************************************************************************** 
  32. ********************************* 文件引用部分 ******************************** 
  33. ******************************************************************************/  
  34. #include "stdint.h"         //包含uint8_t等数据类型  
  35. #include "stdbool.h"        //包含Bool类型  
  36. #include "stdio.h"          //包含printf支持  
  37.   
  38. /****************************************************************************** 
  39. ********************************* 参数宏定义 ********************************* 
  40. ******************************************************************************/  
  41. //版本定义  
  42. #define SHELL_VER           2       //Shell版本  
  43. #ifndef SHELL_LED_MAX               //LED实体数量  
  44.   #define SHELL_LED_MAX     4  
  45. #endif  
  46.   
  47. //缓冲大小配置  
  48. #define SHELL_RX_MAX        (256+32)        //shell指令接收缓冲大小  
  49. #define SHELL_TX_MAX        (512)           //shell指令发送缓冲大小  
  50.   
  51. /****************************************************************************** 
  52. ********************************* 数 据 声 明 ********************************* 
  53. ******************************************************************************/  
  54. /*---------------------*  
  55. *     Shell接收 
  56. *----------------------*/  
  57. //接收数据  
  58. extern volatile uint16_t   shell_rx_rdy;                    //0:空闲,非零:忙,用户读为非零后清零  
  59. extern volatile uint8_t    shell_rx_buff[SHELL_RX_MAX+1];   //接收缓冲  
  60.   
  61. /****************************************************************************** 
  62. ********************************* 函 数 声 明 ********************************* 
  63. ******************************************************************************/  
  64. /*---------------------*  
  65. *    输出函数 
  66. *----------------------*/  
  67. //调试Shell的接口数量  
  68. #if     (6 == SHELL_LED_MAX)  
  69.   extern void shell_GPIO_Config(uint16_t led0_cfg,uint16_t led1_cfg,  
  70.                                 uint16_t led2_cfg,uint16_t led3_cfg,  
  71.                                 uint16_t led4_cfg,uint16_t led5_cfg);  
  72. #elif   (5 == SHELL_LED_MAX)  
  73.   extern void shell_GPIO_Config(uint16_t led0_cfg,uint16_t led1_cfg,  
  74.                                 uint16_t led2_cfg,uint16_t led3_cfg,  
  75.                                 uint16_t led4_cfg);  
  76. #elif   (4 == SHELL_LED_MAX)  
  77.   extern void shell_GPIO_Config(uint16_t led0_cfg,uint16_t led1_cfg,  
  78.                                 uint16_t led2_cfg,uint16_t led3_cfg);  
  79. #elif   (3 == SHELL_LED_MAX)  
  80.   extern void shell_GPIO_Config(uint16_t led0_cfg,uint16_t led1_cfg,  
  81.                                 uint16_t led2_cfg);  
  82. #elif   (2 == SHELL_LED_MAX)  
  83.   extern void shell_GPIO_Config(uint16_t led0_cfg,uint16_t led1_cfg);  
  84. #elif   (1 == SHELL_LED_MAX)  
  85.   extern void shell_GPIO_Config(uint16_t led0_cfg);  
  86. #endif  
  87.   
  88. //检测参数合法性  
  89. #if ((SHELL_LED_MAX > 6) || (SHELL_LED_MAX == 0))  
  90.   #error SHELL_LED_MAX is invaild!  
  91. #endif  
  92.   
  93. //初始化Shell  
  94. extern void shell_Init(uint32_t baud);          //模块初始化  
  95. extern void shell_SendStr(void * ptStr);        //发送以''结束的字符串  
  96. extern void shell_SendHex(void * ptHex,uint16_t size);  //发送指定个数的数据  
  97.   
  98. /*---------------------*  
  99. *    LEDx测试信号定义 
  100. *----------------------*/  
  101. extern void Ledx_config(uint8_t led_id,uint16_t msg_id);    //设置LED的配置信号  
  102. extern uint16_t Ledx_read(uint8_t led_id);                  //读取LED的配置信号(失败返回0)  
  103. extern  void Ledx_on (uint16_t msg_id);             //发送LED开消息  
  104. extern  void Ledx_off(uint16_t msg_id);             //发送LED关消息  
  105. extern  void Ledx_div(uint16_t msg_id);             //发送LED取反消息  
  106.   
  107. /*---------------------*  
  108. *     时基延时函数 
  109. *----------------------*/  
  110. extern void Delay_LibInit(void);  
  111. extern void DlyTime_us(uint16_t us);  
  112. extern void DlyTime_ms(uint16_t ms);  
  113. extern void DlyWait_base(volatile uint64_t * ptCnt);    //标记为等待的基点时间  
  114. extern uint32_t DlyWait_lost(volatile uint64_t * ptCnt);//判断逝去的时间(us)  
  115.   
  116. /*---------------------*  
  117. *     辅助判断指令 
  118. *----------------------*/  
  119. extern bool StrComp(void * buffer,void * StrCmd);   //字符串匹配比较函数  
  120.   
  121. /*---------------------*  
  122. *       Shell服务 
  123. *----------------------*/  
  124. //在main.c函数while()中判断shell_rx_rdy是否为非零,为非零才执行以下程序  
  125. extern void Shell_Invalid_Service(void); //指令未处理服务(会处理shell_rx_rdy信号)  
  126.   
  127. /****************************************************************************** 
  128. ***********************************   END  ************************************ 
  129. ******************************************************************************/  
  130. #endif  


3.shell.c

[cpp] view plain copy
 
  1. /*********************************Copyright (c)********************************* 
  2. **                                
  3. **                                 FIVE工作组 
  4. ** 
  5. **---------------------------------File Info------------------------------------ 
  6. ** File Name:               shell.c 
  7. ** Last modified Date:      2014/3/5 16:43:59 
  8. ** Last Version:            V2   
  9. ** Description:             none 
  10. ** 
  11. **------------------------------------------------------------------------------ 
  12. ** Created By:              wanxuncpx 
  13. ** Created date:            2014/3/5 16:43:58 
  14. ** Version:                 V2 
  15. ** Descriptions:            适合于STM32 
  16. **------------------------------------------------------------------------------ 
  17. ** Libraries:               STM32F10x_StdPeriph_Driver 
  18. ** version                  V3.5 
  19. *******************************************************************************/  
  20.   
  21. /****************************************************************************** 
  22. 更新说明: 
  23. ******************************************************************************/  
  24.   
  25. /****************************************************************************** 
  26. *********************************  应 用 资 料 ******************************** 
  27. ******************************************************************************/  
  28.   
  29. /****************************************************************************** 
  30. ********************************* 文件引用部分 ******************************** 
  31. ******************************************************************************/  
  32. #include "shell.h"      //包含Shell接口文件  
  33.   
  34. //是否使用扩展的Shell接口  
  35. #ifdef SHELL_HAL_EXT  
  36.   #include "shell_hal.h"    //本地的Shell文件  
  37. #else  
  38.   #include "console.h"      //标准的Shell文件  
  39. #endif  
  40.   
  41. /****************************************************************************** 
  42. ********************************* Shell.h定义 ********************************* 
  43. ******************************************************************************/  
  44. /*---------------------*  
  45. *     Shell 收发标记 
  46. *----------------------*/  
  47. volatile uint16_t   shell_rx_rdy = 0;                       //0:空闲,非零:忙  
  48. volatile uint8_t    shell_rx_buff[SHELL_RX_MAX+1]="";   //接收缓冲  
  49.   
  50. /****************************************************************************** 
  51. ********************************* 本 地 数 据 ********************************* 
  52. ******************************************************************************/  
  53. /*---------------------*  
  54. *     Shell缓冲定义 
  55. *----------------------*/  
  56. //接收  
  57. static volatile uint16_t    shell_rx_index = 0;             //数据接收标记  
  58.   
  59. //发送  
  60. static volatile uint8_t     shell_tx_buff[SHELL_TX_MAX+1]="";  
  61. static volatile uint16_t    shell_tx_size  = 0;             //0:空闲,非零:忙  
  62. static volatile uint16_t    shell_tx_index = 0;             //发送数据标记  
  63.   
  64. /*---------------------*  
  65. *     LED控制信号 
  66. *----------------------*/  
  67. static volatile uint16_t    msg_led_cfg[SHELL_LED_MAX];     //配置信号  
  68.   
  69. /*---------------------*  
  70. *    延时模块定义 
  71. *----------------------*/  
  72. static volatile uint64_t    TimeDlyCnt = 0;                 //用于辅助的延时计数值  
  73.   
  74. /****************************************************************************** 
  75. ********************************* 函 数 声 明 ********************************* 
  76. ******************************************************************************/  
  77. /****************************************************************************** 
  78. / 函数功能:初始化GPIO口(串口和四个LED灯配置) 
  79. / 修改日期:none 
  80. / 输入参数:none 
  81. / 输出参数:none 
  82. / 使用说明:none 
  83. ******************************************************************************/  
  84. #if     (6 == SHELL_LED_MAX)  
  85.     void shell_GPIO_Config( uint16_t led0_cfg,uint16_t led1_cfg,  
  86.                             uint16_t led2_cfg,uint16_t led3_cfg,  
  87.                             uint16_t led4_cfg,uint16_t led5_cfg)  
  88. #elif   (5 == SHELL_LED_MAX)  
  89.     void shell_GPIO_Config( uint16_t led0_cfg,uint16_t led1_cfg,  
  90.                             uint16_t led2_cfg,uint16_t led3_cfg,  
  91.                             uint16_t led4_cfg)  
  92. #elif   (4 == SHELL_LED_MAX)  
  93.     void shell_GPIO_Config( uint16_t led0_cfg,uint16_t led1_cfg,  
  94.                             uint16_t led2_cfg,uint16_t led3_cfg)  
  95. #elif   (3 == SHELL_LED_MAX)  
  96.     void shell_GPIO_Config( uint16_t led0_cfg,uint16_t led1_cfg,  
  97.                             uint16_t led2_cfg)  
  98. #elif   (2 == SHELL_LED_MAX)  
  99.     void shell_GPIO_Config(uint16_t led0_cfg,uint16_t led1_cfg)  
  100. #elif   (1 == SHELL_LED_MAX)  
  101.     void shell_GPIO_Config(uint16_t led0_cfg)  
  102. #endif  
  103. {  
  104.     GPIO_InitTypeDef GPIO_InitStruct;  
  105.       
  106.     /* 配置串口 ---------------------------------------------------------*/  
  107.     // 打开在APB2上的GPIO口外设时钟  
  108.     CONSOLE_GPIO_RCC_INIT();    //打开GPIO口的时钟  
  109.   
  110.     // 配置TX引脚  
  111.     GPIO_InitStruct.GPIO_Pin    = CONSOLE_TX_PIN;  
  112.     GPIO_InitStruct.GPIO_Mode   = GPIO_Mode_AF_PP;  
  113.     GPIO_InitStruct.GPIO_Speed  = GPIO_Speed_50MHz;  
  114.     GPIO_Init(CONSOLE_TX_PORT,  &GPIO_InitStruct);  
  115.   
  116.     // 配置RX引脚  
  117.     GPIO_InitStruct.GPIO_Pin    = CONSOLE_RX_PIN;  
  118.     GPIO_InitStruct.GPIO_Mode   = GPIO_Mode_IPU;  
  119.     GPIO_Init(CONSOLE_RX_PORT,  &GPIO_InitStruct);  
  120.   
  121.     //锁定GPIO口,防止其他更改  
  122.     GPIO_PinLockConfig(CONSOLE_TX_PORT,CONSOLE_TX_PIN);  
  123.     GPIO_PinLockConfig(CONSOLE_RX_PORT,CONSOLE_RX_PIN);  
  124.       
  125.     /* 配置LEDx ---------------------------------------------------------*/  
  126.     LEDx_GPIO_RCC_INIT();  
  127.     GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;  
  128.     GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;  
  129.       
  130.     //根据定义配置四个LED  
  131.   #if (SHELL_LED_MAX > 0)  
  132.     GPIO_InitStruct.GPIO_Pin    = LED0_PIN;  
  133.     GPIO_Init(LED0_PORT,   &GPIO_InitStruct);  
  134.     GPIO_PinLockConfig(LED0_PORT,LED0_PIN);  
  135.     msg_led_cfg[0] = led0_cfg;  
  136.     LED0_OFF();  
  137.   #endif  
  138.   #if (SHELL_LED_MAX > 1)  
  139.     GPIO_InitStruct.GPIO_Pin    = LED1_PIN;  
  140.     GPIO_Init(LED1_PORT,   &GPIO_InitStruct);  
  141.     GPIO_PinLockConfig(LED1_PORT,LED1_PIN);  
  142.     msg_led_cfg[1] = led1_cfg;  
  143.     LED1_OFF();  
  144.   #endif  
  145.   #if (SHELL_LED_MAX > 2)  
  146.     GPIO_InitStruct.GPIO_Pin    = LED2_PIN;  
  147.     GPIO_Init(LED2_PORT,   &GPIO_InitStruct);  
  148.     GPIO_PinLockConfig(LED2_PORT,LED2_PIN);  
  149.     msg_led_cfg[2] = led2_cfg;  
  150.     LED2_OFF();  
  151.   #endif  
  152.   #if (SHELL_LED_MAX > 3)  
  153.     GPIO_InitStruct.GPIO_Pin    = LED3_PIN;  
  154.     GPIO_Init(LED3_PORT,   &GPIO_InitStruct);  
  155.     GPIO_PinLockConfig(LED3_PORT,LED3_PIN);  
  156.     msg_led_cfg[3] = led3_cfg;  
  157.     LED3_OFF();  
  158.   #endif   
  159.   #if (SHELL_LED_MAX > 4)  
  160.     GPIO_InitStruct.GPIO_Pin    = LED4_PIN;  
  161.     GPIO_Init(LED4_PORT,   &GPIO_InitStruct);  
  162.     GPIO_PinLockConfig(LED4_PORT,LED4_PIN);  
  163.     msg_led_cfg[4] = led4_cfg;  
  164.     LED4_OFF();  
  165.   #endif   
  166.   #if (SHELL_LED_MAX > 5)  
  167.     GPIO_InitStruct.GPIO_Pin    = LED5_PIN;  
  168.     GPIO_Init(LED5_PORT,   &GPIO_InitStruct);  
  169.     GPIO_PinLockConfig(LED5_PORT,LED5_PIN);  
  170.     msg_led_cfg[5] = led5_cfg;  
  171.     LED5_OFF();  
  172.   #endif   
  173. }  
  174.   
  175. /****************************************************************************** 
  176. / 函数功能:串口初始化,使用中断单字节接收数据 
  177. / 修改日期:none 
  178. / 输入参数:baud 波特率 
  179. / 输出参数:none 
  180. / 使用说明:none 
  181. ******************************************************************************/  
  182. void shell_Init(uint32_t baud)  
  183. {  
  184.     USART_InitTypeDef   USART_InitStructure;  
  185.     NVIC_InitTypeDef    NVIC_UART_Cfg;  //UART中断向量  
  186.       
  187.     //--------------------------- 先定义好数据结构 ---------------------------  
  188.     //定义好USART结构体  
  189.     USART_InitStructure.USART_BaudRate      = baud;  
  190.     USART_InitStructure.USART_WordLength    = USART_WordLength_8b;  
  191.     USART_InitStructure.USART_StopBits      = USART_StopBits_1;  
  192.     USART_InitStructure.USART_Parity        = USART_Parity_No ;  
  193.     USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;  
  194.     USART_InitStructure.USART_Mode          = USART_Mode_Tx | USART_Mode_Rx;  
  195.     USART_InitStructure.USART_BaudRate = USART_InitStructure.USART_BaudRate;    //防止编译报错  
  196.       
  197.     //定义好NVIC:UART中断  
  198.     NVIC_UART_Cfg.NVIC_IRQChannel = CONSOLE_IRQn;  
  199.     NVIC_UART_Cfg.NVIC_IRQChannelPreemptionPriority = 1;  
  200.     NVIC_UART_Cfg.NVIC_IRQChannelSubPriority = CONSOLE_UART_PRIO;  
  201.     NVIC_UART_Cfg.NVIC_IRQChannelCmd = ENABLE;  
  202.     NVIC_UART_Cfg.NVIC_IRQChannel = NVIC_UART_Cfg.NVIC_IRQChannel;              //防止编译报错  
  203.       
  204.     //模式配置  
  205.     //--------------------------- 中断方式收发数据 ----------------------------  
  206.     CONSOLE_UART_RCC_INIT();                                //打开USART的时钟  
  207.     USART_Cmd(CONSOLE, DISABLE);                            //关闭UART  
  208.       
  209.     USART_Init(CONSOLE, &USART_InitStructure);              //初始化串口  
  210.       
  211.     USART_ITConfig(CONSOLE, USART_IT_RXNE, ENABLE);  
  212.     USART_ITConfig(CONSOLE, USART_IT_IDLE, ENABLE);  
  213.       
  214.     USART_Cmd(CONSOLE, ENABLE);  
  215.       
  216.     NVIC_Init(&NVIC_UART_Cfg);                              //配置好NVIC  
  217. }  
  218.   
  219. /****************************************************************************** 
  220. / 函数功能:Delay延时库初始化(需要1us的计数精度,和50ms的溢出计数) 
  221. / 修改日期:2014/5/1 21:02:58 
  222. / 输入参数:none 
  223. / 输出参数:none 
  224. / 使用说明:(限STM32F40X的TIM2,TIM3,TIM4,TIM5) 
  225. ******************************************************************************/  
  226. void Delay_LibInit(void)  
  227. {  
  228.     TIM_TimeBaseInitTypeDef     TIM_TimeBaseStructure;  
  229.     NVIC_InitTypeDef            NVIC_InitStructure;  
  230.       
  231.     //开启TIM2时钟  
  232.     TIMEDly_RCC_INIT();  
  233.   
  234.     /* Enable the TIMx gloabal Interrupt */  
  235.     NVIC_InitStructure.NVIC_IRQChannel                  = TIMEDly_IRQn;  
  236.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 0;  
  237.     NVIC_InitStructure.NVIC_IRQChannelSubPriority       = 0;    //由于是时基,需要使用最高优先级  
  238.     NVIC_InitStructure.NVIC_IRQChannelCmd               = ENABLE;  
  239.     NVIC_Init(&NVIC_InitStructure);  
  240.     
  241.     /* Time base configuration */  
  242.     TIM_TimeBaseStructure.TIM_Period    = 65000;  
  243.     TIM_TimeBaseStructure.TIM_Prescaler     = (SystemCoreClock/1000000)-1;  
  244.     TIM_TimeBaseStructure.TIM_ClockDivision = 0;  
  245.     TIM_TimeBaseStructure.TIM_CounterMode    = TIM_CounterMode_Up;  
  246.   
  247.     TIM_TimeBaseInit(TIMEDly, &TIM_TimeBaseStructure);  
  248.      
  249.     /* TIM Interrupts enable */  
  250.     TIM_ITConfig(TIMEDly,TIM_IT_Update, ENABLE);  
  251.   
  252.     /* TIMx enable counter */  
  253.     TIM_Cmd(TIMEDly, ENABLE);  
  254. }  
  255.   
  256. /****************************************************************************** 
  257. / 函数功能:等待一个us延时 
  258. / 修改日期:2014/5/1 21:02:58 
  259. / 输入参数:none 
  260. / 输出参数:none 
  261. / 使用说明:none 
  262. ******************************************************************************/  
  263. void DlyTime_us(uint16_t us)  
  264. {  
  265.    uint64_t this_cnt,over_cnt,tmp_val;  
  266.      
  267.     //得到当前的准确时间  
  268.     do  
  269.     {  
  270.         this_cnt = TIMEDly->CNT + TimeDlyCnt;  
  271.         if( (TIMEDly->SR    & TIM_IT_Update)    &&  
  272.             (TIMEDly->SR    & TIM_IT_Update)    &&  
  273.             (TIMEDly->SR    & TIM_IT_Update)    )  
  274.         {  
  275.             TIMEDly->SR =   (uint16_t)~TIM_IT_Update;  
  276.             TimeDlyCnt  +=  65000;    
  277.         }  
  278.         tmp_val = TIMEDly->CNT + TimeDlyCnt;   
  279.     }  
  280.     while(this_cnt != tmp_val);  
  281.     over_cnt = this_cnt + us;       //得到目标延时时间  
  282.       
  283.     //延时函数  
  284.     do  
  285.     {  
  286.         if( (TIMEDly->SR    & TIM_IT_Update)    &&  
  287.             (TIMEDly->SR    & TIM_IT_Update)    &&  
  288.             (TIMEDly->SR    & TIM_IT_Update)    )  
  289.         {  
  290.             TIMEDly->SR =   (uint16_t)~TIM_IT_Update;  
  291.             TimeDlyCnt  +=  65000;    
  292.         }  
  293.           
  294.         this_cnt = TIMEDly->CNT + TimeDlyCnt;  
  295.     }  
  296.     while(this_cnt < over_cnt);  
  297. }  
  298.   
  299. /****************************************************************************** 
  300. / 函数功能:等待一个ms延时 
  301. / 修改日期:2014/5/1 21:02:58 
  302. / 输入参数:none 
  303. / 输出参数:none 
  304. / 使用说明:none 
  305. ******************************************************************************/  
  306. void DlyTime_ms(uint16_t ms)  
  307. {  
  308.    uint64_t this_cnt,over_cnt,tmp_val;  
  309.      
  310.     //得到当前的准确时间  
  311.     do  
  312.     {  
  313.         this_cnt = TIMEDly->CNT + TimeDlyCnt;  
  314.         if( (TIMEDly->SR    & TIM_IT_Update)    &&  
  315.             (TIMEDly->SR    & TIM_IT_Update)    &&  
  316.             (TIMEDly->SR    & TIM_IT_Update)    )  
  317.         {  
  318.             TIMEDly->SR =   (uint16_t)~TIM_IT_Update;  
  319.             TimeDlyCnt  +=  65000;    
  320.         }  
  321.         tmp_val = TIMEDly->CNT + TimeDlyCnt;   
  322.     }  
  323.     while(this_cnt != tmp_val);  
  324.     over_cnt = this_cnt + (uint32_t)ms*1000;  
  325.       
  326.     //延时函数  
  327.     do  
  328.     {  
  329.         if( (TIMEDly->SR    & TIM_IT_Update)    &&  
  330.             (TIMEDly->SR    & TIM_IT_Update)    &&  
  331.             (TIMEDly->SR    & TIM_IT_Update)    )  
  332.         {  
  333.             TIMEDly->SR =   (uint16_t)~TIM_IT_Update;  
  334.             TimeDlyCnt  +=  65000;    
  335.         }  
  336.         this_cnt = TIMEDly->CNT + TimeDlyCnt;  
  337.     }  
  338.     while(this_cnt < over_cnt);  
  339. }  
  340.   
  341. /****************************************************************************** 
  342. / 函数功能:标记时间起点 
  343. / 修改日期:2014/5/1 21:02:58 
  344. / 输入参数:none 
  345. / 输出参数:none 
  346. / 使用说明:none 
  347. ******************************************************************************/  
  348. void DlyWait_base(volatile uint64_t * ptCnt)  
  349. {  
  350.     uint64_t this_cnt,tmp_val;  
  351.       
  352.     //得到当前的准确时间  
  353.     do  
  354.     {  
  355.         this_cnt = TIMEDly->CNT + TimeDlyCnt;  
  356.         if( (TIMEDly->SR    & TIM_IT_Update)    &&  
  357.             (TIMEDly->SR    & TIM_IT_Update)    &&  
  358.             (TIMEDly->SR    & TIM_IT_Update)    )  
  359.         {  
  360.             TIMEDly->SR =   (uint16_t)~TIM_IT_Update;  
  361.             TimeDlyCnt  +=  65000;    
  362.         }  
  363.         tmp_val = TIMEDly->CNT + TimeDlyCnt;   
  364.     }  
  365.     while(this_cnt != tmp_val);  
  366.     *ptCnt = this_cnt;  
  367. }  
  368.   
  369. /****************************************************************************** 
  370. / 函数功能:检测从起点开始已逝去的时间(最大1个小时) 
  371. / 修改日期:2014/5/1 21:02:58 
  372. / 输入参数:none 
  373. / 输出参数:返回0表示时间到,返回非零表示时间未到 
  374. / 使用说明:none 
  375. ******************************************************************************/  
  376. uint32_t DlyWait_lost(volatile uint64_t * ptCnt)  
  377. {  
  378.     uint64_t this_cnt,tmp_val;  
  379.       
  380.     //得到当前的准确时间  
  381.     do  
  382.     {  
  383.         this_cnt = TIMEDly->CNT + TimeDlyCnt;  
  384.         if( (TIMEDly->SR    & TIM_IT_Update)    &&  
  385.             (TIMEDly->SR    & TIM_IT_Update)    &&  
  386.             (TIMEDly->SR    & TIM_IT_Update)    )  
  387.         {  
  388.             TIMEDly->SR =   (uint16_t)~TIM_IT_Update;  
  389.             TimeDlyCnt  +=  65000;   
  390.         }  
  391.         tmp_val = TIMEDly->CNT + TimeDlyCnt;   
  392.     }  
  393.     while(this_cnt != tmp_val);  
  394.       
  395.     //计算已逝去的时间  
  396.     if(*ptCnt <= this_cnt)  
  397.     {  
  398.         tmp_val = this_cnt - *ptCnt;  
  399.         if(tmp_val > (65536UL*65536UL-1))  
  400.                 return (uint32_t)(65536UL*65536UL-1);  
  401.         else    return (uint32_t)tmp_val;  
  402.     }  
  403.     else  
  404.     {  
  405.         *ptCnt = this_cnt;  
  406.         return 0;         
  407.     }  
  408. }  
  409.   
  410. /****************************************************************************** 
  411. / 函数功能:中断支持函数(限STM32F40X的TIM2,TIM3,TIM4,TIM5) 
  412. / 修改日期:2014/5/1 21:02:58 
  413. / 输入参数:none 
  414. / 输出参数:none 
  415. / 使用说明:none 
  416. ******************************************************************************/   
  417. void TIMEDly_IRQHandler(void)  
  418. {  
  419.     //简单写法  
  420.     if( TIMEDly->SR & TIM_IT_Update )  
  421.     {  
  422.         TIMEDly->SR = (uint16_t)~TIM_IT_Update;  
  423.         TimeDlyCnt += 65000;  
  424.         //Ledx_div(3);        //时基信号  
  425.     }  
  426. }  
  427.   
  428. /****************************************************************************** 
  429. / 函数功能:printf支持函数 
  430. / 修改日期:none 
  431. / 输入参数:none 
  432. / 输出参数:none 
  433. / 使用说明:none 
  434. ******************************************************************************/  
  435. PUTCHAR_PROTOTYPE  
  436. {  
  437.     Ledx_on(11);  
  438.     /* Loop until the end of transmission */  
  439.     while( (CONSOLE->SR & USART_FLAG_TXE) == RESET );  
  440.       
  441.     /* Place your implementation of fputc here */  
  442.     /* e.g. write a character to the USART */  
  443.     CONSOLE->DR = ch;  
  444.       
  445.     /* Loop until the end of transmission */  
  446.     //while( (CONSOLE->SR & USART_FLAG_TC) == RESET );  
  447.     Ledx_off(11);  
  448.     return ch;  
  449. }  
  450.   
  451. /****************************************************************************** 
  452. / 函数功能:字符串发送函数 
  453. / 修改日期:none 
  454. / 输入参数:none 
  455. / 输出参数:none 
  456. / 使用说明:none 
  457. ******************************************************************************/  
  458. void shell_SendStr(void * ptAsc)  
  459. {                                   //中断方式  
  460.     //--------------------------- 中断方式收发数据 ----------------------------  
  461.     uint16_t        i,size;  
  462.     uint8_t         *ptDst;  
  463.     uint8_t const   *ptSrc;     //源数据只读不写  
  464.       
  465.     //计算字符串的长度  
  466.     ptSrc = (uint8_t const *)ptAsc;  
  467.     size  = 0;  
  468.     while(*ptSrc++){size++;}  
  469.       
  470.     //判断字符串是否超过缓冲  
  471.     Ledx_on(11);  
  472.     if(size > SHELL_TX_MAX)  
  473.     {  
  474.         //关闭中断发送方式  
  475.         shell_tx_index = 0;  
  476.         shell_tx_size  = 0;  
  477.         CONSOLE->CR1 &= ~USART_CR1_TXEIE;        //关闭发送完毕中断  
  478.           
  479.         ptSrc = (uint8_t const *)ptAsc;  
  480.         while(size--)  
  481.         {  
  482.             while( (CONSOLE->SR & USART_FLAG_TXE) == RESET );  
  483.             CONSOLE->DR = *ptSrc++;  
  484.         }  
  485.         Ledx_off(11);  
  486.     }  
  487.     else if( !(CONSOLE->CR1 & USART_CR1_TXEIE) )  
  488.     {  
  489.         //如果未启用非空中断则,启用非空中断发送数据  
  490.         //复制数据  
  491.         ptDst = (uint8_t *)shell_tx_buff;  
  492.         ptSrc = (uint8_t const *)ptAsc;  
  493.         for(i=0; i<size; i++)  
  494.             *ptDst++ = *ptSrc++;  
  495.           
  496.         //启动发送中断  
  497.         shell_tx_index = 0;  
  498.         shell_tx_size  = size;  
  499.         CONSOLE->CR1 |= USART_CR1_TXEIE;        //启动发送非空中断          
  500.     }  
  501. }  
  502.   
  503. /****************************************************************************** 
  504. / 函数功能:发送Hex数据函数 
  505. / 修改日期:none 
  506. / 输入参数:none 
  507. / 输出参数:none 
  508. / 使用说明:none 
  509. ******************************************************************************/  
  510. void shell_SendHex(void * ptHex,uint16_t size)  
  511. {                                  //中断方式  
  512.     //--------------------------- 中断方式收发数据 ----------------------------  
  513.     uint16_t        i;  
  514.     uint8_t         *ptDst;  
  515.     uint8_t const   *ptSrc;     //源数据只读不写  
  516.   
  517.     Ledx_on(11);  
  518.     if(size > SHELL_TX_MAX)  
  519.     {  
  520.         //关闭中断发送方式  
  521.         shell_tx_index = 0;  
  522.         shell_tx_size  = 0;  
  523.         CONSOLE->CR1 &= ~USART_CR1_TXEIE;        //关闭发送完毕中断  
  524.           
  525.         //直接发送数据  
  526.         ptSrc = (uint8_t const *)ptHex;  
  527.         while(size--)  
  528.         {  
  529.             while( (CONSOLE->SR & USART_FLAG_TXE) == RESET );  
  530.             CONSOLE->DR = *ptSrc++;  
  531.         }  
  532.         Ledx_off(11);   
  533.     }  
  534.     else if( !(CONSOLE->CR1 & USART_CR1_TXEIE) )  
  535.     {  
  536.         //如果未启用非空中断则,启用非空中断发送数据  
  537.         //复制数据  
  538.         ptDst = (uint8_t *)shell_tx_buff;  
  539.         ptSrc = (uint8_t const *)ptHex;     
  540.         for(i=0; i<size; i++)  
  541.             *ptDst++ = *ptSrc++;  
  542.           
  543.         //启动发送中断  
  544.         shell_tx_index = 0;  
  545.         shell_tx_size  = size;  
  546.         CONSOLE->CR1 |= USART_CR1_TXEIE;        //启动发送非空中断       
  547.     }  
  548. }  
  549.   
  550. /****************************************************************************** 
  551. / 函数功能:中断服务程序 
  552. / 修改日期:none 
  553. / 输入参数:none 
  554. / 输出参数:none 
  555. / 使用说明:none 
  556. ******************************************************************************/  
  557. void CONSOLE_IRQHandler(void)  
  558. {  
  559.     uint8_t     rxd_reg,txd_reg;  
  560.     uint16_t    isr_reg;  
  561.                                        //中断配置  
  562.     //--------------------------- 中断方式收发数据 ----------------------------  
  563.     isr_reg = CONSOLE->SR;  
  564.     //接收中断  
  565.     if( (CONSOLE->CR1 & USART_CR1_RXNEIE) && (isr_reg & USART_SR_RXNE) )  
  566.     {  
  567.         rxd_reg = CONSOLE->DR;  
  568.         Ledx_on(12);  
  569.         if(shell_rx_rdy)shell_rx_index = 0;     //忙模式收到字节,重置接收指针  
  570.         else  
  571.         {  
  572.             if( shell_rx_index < SHELL_RX_MAX)  
  573.             {  
  574.                 shell_rx_buff[shell_rx_index] = rxd_reg;  
  575.                 shell_rx_index++;  
  576.             }  
  577.             else  
  578.             {  
  579.                 shell_rx_index = 0;  
  580.                 Ledx_off(12);      
  581.             }  
  582.         }  
  583.     }  
  584.       
  585.     if( (CONSOLE->CR1 & USART_CR1_IDLEIE) && (isr_reg & USART_SR_IDLE) )  
  586.     {  
  587.         CONSOLE->SR;  
  588.         CONSOLE->DR;  
  589.         if(shell_rx_rdy)shell_rx_index = 0;     //忙模式收到空闲,重置接收指针  
  590.         else  
  591.         {  
  592.             if( (shell_rx_index >=2) && (' ' == shell_rx_buff[shell_rx_index-2]) &&  
  593.                 (' ' == shell_rx_buff[shell_rx_index-1])   )       //以" "结尾  
  594.             {  
  595.                 shell_rx_rdy = shell_rx_index;  
  596.                 shell_rx_index = 0;  
  597.                 Ledx_off(12);  
  598.             }  
  599.             else if( (shell_rx_index > 0) && ('' == shell_rx_buff[shell_rx_index-1]) )  //以结尾  
  600.             {  
  601.                 shell_rx_index = shell_rx_index <2? 0:shell_rx_index-2;  
  602.                 printf(" ");      //发送辅助删除          
  603.             }   
  604.         }   
  605.     }  
  606.       
  607.     //发送非空中断      
  608.     if( (CONSOLE->CR1 & USART_CR1_TXEIE) && (isr_reg & USART_SR_TXE ) )  
  609.     {  
  610.         if(shell_tx_size && (shell_tx_index < shell_tx_size) )  
  611.         {  
  612.             txd_reg = shell_tx_buff[shell_tx_index++];  
  613.             CONSOLE->DR = txd_reg;  //发送数据  
  614.         }  
  615.         else  
  616.         {  
  617.             //关闭非空中断  
  618.             shell_tx_index = 0;  
  619.             shell_tx_size = 0;  
  620.             CONSOLE->CR1 &= ~USART_CR1_TXEIE;        //关闭发送完毕中断   
  621.             Ledx_off(11);   
  622.         }           
  623.     }  
  624. }  
  625.   
  626.   
  627. /****************************************************************************** 
  628. / 函数功能:指令(ASCII或HEX指令)未处理消息回执 
  629. / 修改日期:2013/9/12 20:25:45 
  630. / 输入参数:none 
  631. / 输出参数:none 
  632. / 使用说明:一字节一字节接收数据,拼装为指令 
  633. ******************************************************************************/  
  634. void Shell_Invalid_Service(void)  
  635. {  
  636.     int         tx_len,i,led_id,msg_id;  
  637.     uint8_t *   ptSrc;  
  638.     uint8_t *   ptDst;  
  639.     uint8_t     tmp_buff[64];  
  640.       
  641.     //指令识别  
  642.     if(2 > shell_rx_rdy)  
  643.     {  
  644.         shell_rx_buff[0]  = 0;  
  645.         return;  
  646.     }  
  647.     else if( (' ' == shell_rx_buff[shell_rx_rdy-2]) && (' ' == shell_rx_buff[shell_rx_rdy-1]) )  
  648.     {  
  649.         ptSrc = (uint8_t *)shell_rx_buff;  
  650.         if(2 == shell_rx_rdy)  
  651.         {  
  652.             //填写数据  
  653.             tx_len = (uint16_t)sprintf((void *)tmp_buff," AT:OK! ");  
  654.           
  655.             //发送数据  
  656.             shell_SendHex(tmp_buff,tx_len);     //发送数据      
  657.         }  
  658.         else if(StrComp(ptSrc,"led rd "))   //显示LED的信号配置  
  659.         {  
  660.             //填写数据  
  661.             tx_len = (uint16_t)sprintf((void *)tmp_buff,  
  662.           #if     (6 == SHELL_LED_MAX)  
  663.                 "->LED0=%d  LED1=%d  tLED2=%d  LED3=%d  LED4=%d  LED5=%d ",  
  664.                 msg_led_cfg[0],msg_led_cfg[1],msg_led_cfg[2],  
  665.                 msg_led_cfg[3],msg_led_cfg[4],msg_led_cfg[5]);  
  666.           #elif   (5 == SHELL_LED_MAX)  
  667.                 "->LED0=%d  LED1=%d  tLED2=%d  LED3=%d  LED4=%d ",  
  668.                 msg_led_cfg[0],msg_led_cfg[1],msg_led_cfg[2],  
  669.                 msg_led_cfg[3],msg_led_cfg[4]);  
  670.           #elif   (4 == SHELL_LED_MAX)  
  671.                 "->LED0=%d  LED1=%d  tLED2=%d  LED3=%d ",  
  672.                 msg_led_cfg[0],msg_led_cfg[1],msg_led_cfg[2],  
  673.                 msg_led_cfg[3]);  
  674.           #elif   (3 == SHELL_LED_MAX)  
  675.                 "->LED0=%d  LED1=%d  tLED2=%d ",  
  676.                 msg_led_cfg[0],msg_led_cfg[1],msg_led_cfg[2]);  
  677.           #elif   (2 == SHELL_LED_MAX)  
  678.                 "->LED0=%d  LED1=%d ",  
  679.                 msg_led_cfg[0],msg_led_cfg[1]);  
  680.           #elif   (1 == SHELL_LED_MAX)  
  681.                 "->LED0=%d ",  
  682.                 msg_led_cfg[0]);  
  683.           #endif          
  684.             //发送数据  
  685.             shell_SendHex(tmp_buff,tx_len);     //发送数据          
  686.         }  
  687.         else if(StrComp(ptSrc,"led wr "))      //设置LED的信号配置  
  688.         {  
  689.             if(2 != sscanf((void *)ptSrc,"%*s%*s%d=%d",&led_id,&msg_id) )goto ERROR_LOOP;  
  690.             if( (led_id>(SHELL_LED_MAX-1)) || (msg_id >65535) )goto ERROR_LOOP;  
  691.   
  692.             Ledx_config((uint8_t)led_id,(uint16_t)msg_id);  //配置信号   
  693.             //填写数据  
  694.             tx_len = (uint16_t)sprintf((void *)tmp_buff,  
  695.                 "->LED[%d]_Msg=%d ",led_id,msg_led_cfg[led_id]);  
  696.   
  697.             //发送数据  
  698.             shell_SendHex(tmp_buff,tx_len);     //发送数据     
  699.         }  
  700.         else goto ERROR_LOOP;  
  701.     }  
  702.     else  
  703.     {  
  704. ERROR_LOOP:  
  705.         //填写指令码  
  706.         tx_len = (uint16_t)sprintf((void *)tmp_buff," AT: Cmd Error: "");  
  707.           
  708.         //计算地址,填写数据,填写尾部  
  709.         ptDst = tmp_buff + tx_len;  
  710.         ptSrc = (uint8_t *)shell_rx_buff;  
  711.         if(shell_rx_rdy > 32)  
  712.         {  
  713.             for(i=0; i<32; i++)  
  714.             {   
  715.                 if( (*ptSrc > 126) || (*ptSrc < 32) )  
  716.                 {  
  717.                     *ptDst++ = '?';  
  718.                      ptSrc++;     
  719.                 }  
  720.                 else  
  721.                 {  
  722.                     *ptDst++ = *ptSrc++;   
  723.                 }   
  724.             }  
  725.             *(ptDst-2) = '-';  
  726.             *(ptDst-1) = '>';  
  727.             tx_len += 32;  
  728.         }  
  729.         else  
  730.         {  
  731.             for(i=0; i<shell_rx_rdy; i++)  
  732.             {   
  733.                 *ptDst++ = *ptSrc++;  
  734.                 tx_len++;   
  735.             }  
  736.             *(ptDst-2) = '<';  
  737.             *(ptDst-1) = '-';  
  738.         }  
  739.         tx_len += (uint16_t)sprintf((void *)ptDst,"" ");  
  740.     
  741.         //发送数据  
  742.         shell_SendHex(tmp_buff,tx_len);  //发送数据  
  743.     }  
  744.       
  745.     //清除数据返回程序  
  746.     shell_rx_buff[0]  = 0;  
  747.     shell_rx_rdy      = 0;  
  748. }  
  749.   
  750. /****************************************************************************** 
  751. / 函数功能:字符串测试匹配指令 
  752. / 修改日期:2014/3/5 19:30:22 
  753. / 输入参数:none 
  754. / 输出参数:none 
  755. / 使用说明:none 
  756. ******************************************************************************/  
  757. bool StrComp(void * buffer,void * StrCmd)  
  758. {  
  759.     uint8_t i;  
  760.     uint8_t * ptBuf;  
  761.     uint8_t * ptCmd;  
  762.       
  763.     ptBuf = (uint8_t *)buffer;  
  764.     ptCmd = (uint8_t *)StrCmd;  
  765.     for(i=0; i<255; i++)  
  766.     {  
  767.         if(ptCmd[i])  
  768.         {  
  769.             if(ptBuf[i] != ptCmd[i])return false;  
  770.         }  
  771.         else   
  772.         {  
  773.             if(i)return i;  
  774.             else return false;      
  775.         }  
  776.     }  
  777.     return false;  
  778. }  
  779.   
  780. /****************************************************************************** 
  781. / 函数功能:打开LED信号 
  782. / 修改日期:none 
  783. / 输入参数:none 
  784. / 输出参数:none 
  785. / 使用说明:none 
  786. ******************************************************************************/  
  787. void Ledx_on(uint16_t msg_id)  
  788. {  
  789.   #if (SHELL_LED_MAX > 0)  
  790.     if(msg_id == msg_led_cfg[0])LED0_ON();  
  791.   #endif  
  792.   #if (SHELL_LED_MAX > 1)  
  793.     if(msg_id == msg_led_cfg[1])LED1_ON();  
  794.   #endif  
  795.   #if (SHELL_LED_MAX > 2)  
  796.     if(msg_id == msg_led_cfg[2])LED2_ON();  
  797.   #endif  
  798.   #if (SHELL_LED_MAX > 3)  
  799.     if(msg_id == msg_led_cfg[3])LED3_ON();  
  800.   #endif  
  801.   #if (SHELL_LED_MAX > 4)  
  802.     if(msg_id == msg_led_cfg[4])LED4_ON();  
  803.   #endif  
  804.   #if (SHELL_LED_MAX > 5)  
  805.     if(msg_id == msg_led_cfg[5])LED5_ON();  
  806.   #endif  
  807. }  
  808.   
  809. /****************************************************************************** 
  810. / 函数功能:关闭LED信号 
  811. / 修改日期:none 
  812. / 输入参数:none 
  813. / 输出参数:none 
  814. / 使用说明:none 
  815. ******************************************************************************/  
  816. void Ledx_off(uint16_t msg_id)  
  817. {  
  818.   #if (SHELL_LED_MAX > 0)  
  819.     if(msg_id == msg_led_cfg[0])LED0_OFF();  
  820.   #endif  
  821.   #if (SHELL_LED_MAX > 1)  
  822.     if(msg_id == msg_led_cfg[1])LED1_OFF();  
  823.   #endif  
  824.   #if (SHELL_LED_MAX > 2)  
  825.     if(msg_id == msg_led_cfg[2])LED2_OFF();  
  826.   #endif  
  827.   #if (SHELL_LED_MAX > 3)  
  828.     if(msg_id == msg_led_cfg[3])LED3_OFF();  
  829.   #endif  
  830.   #if (SHELL_LED_MAX > 4)  
  831.     if(msg_id == msg_led_cfg[4])LED4_OFF();  
  832.   #endif  
  833.   #if (SHELL_LED_MAX > 5)  
  834.     if(msg_id == msg_led_cfg[5])LED5_OFF();  
  835.   #endif  
  836. }  
  837.   
  838. /****************************************************************************** 
  839. / 函数功能:取反LED信号 
  840. / 修改日期:none 
  841. / 输入参数:none 
  842. / 输出参数:none 
  843. / 使用说明:none 
  844. ******************************************************************************/  
  845. void Ledx_div(uint16_t msg_id)  
  846. {  
  847.   #if (SHELL_LED_MAX > 0)  
  848.     if(msg_id == msg_led_cfg[0])LED0_DIV();  
  849.   #endif  
  850.   #if (SHELL_LED_MAX > 1)  
  851.     if(msg_id == msg_led_cfg[1])LED1_DIV();  
  852.   #endif  
  853.   #if (SHELL_LED_MAX > 2)  
  854.     if(msg_id == msg_led_cfg[2])LED2_DIV();  
  855.   #endif  
  856.   #if (SHELL_LED_MAX > 3)  
  857.     if(msg_id == msg_led_cfg[3])LED3_DIV();  
  858.   #endif  
  859.   #if (SHELL_LED_MAX > 4)  
  860.     if(msg_id == msg_led_cfg[4])LED4_DIV();  
  861.   #endif  
  862.   #if (SHELL_LED_MAX > 5)  
  863.     if(msg_id == msg_led_cfg[5])LED5_DIV();  
  864.   #endif  
  865. }  
  866.   
  867. /****************************************************************************** 
  868. / 函数功能:配置LED信号 
  869. / 修改日期:none 
  870. / 输入参数:none 
  871. / 输出参数:none 
  872. / 使用说明:none 
  873. ******************************************************************************/  
  874. void Ledx_config(uint8_t led_id,uint16_t msg_id)  
  875. {  
  876.     if(0 == led_id)     {LED0_OFF();msg_led_cfg[0]=msg_id;}  
  877.   #if(SHELL_LED_MAX > 1)       
  878.     else if(1 == led_id){LED1_OFF();msg_led_cfg[1]=msg_id;}  
  879.   #endif  
  880.   #if(SHELL_LED_MAX > 2)  
  881.     else if(2 == led_id){LED2_OFF();msg_led_cfg[2]=msg_id;}  
  882.   #endif  
  883.   #if(SHELL_LED_MAX > 3)  
  884.     else if(3 == led_id){LED3_OFF();msg_led_cfg[3]=msg_id;}  
  885.   #endif  
  886.   #if(SHELL_LED_MAX > 4)  
  887.     else if(4 == led_id){LED4_OFF();msg_led_cfg[4]=msg_id;}  
  888.   #endif  
  889.   #if(SHELL_LED_MAX > 5)  
  890.     else if(5 == led_id){LED5_OFF();msg_led_cfg[5]=msg_id;}  
  891.   #endif   
  892. }  
  893.   
  894. /****************************************************************************** 
  895. / 函数功能:读取LED的配置信号 
  896. / 修改日期:none 
  897. / 输入参数:none 
  898. / 输出参数:none 
  899. / 使用说明:none 
  900. ******************************************************************************/  
  901. uint16_t Ledx_read(uint8_t led_id)  
  902. {  
  903.     if(0 == led_id)     return msg_led_cfg[0];  
  904.   #if(SHELL_LED_MAX > 1)  
  905.     else if(1 == led_id)return msg_led_cfg[1];  
  906.   #endif  
  907.   #if(SHELL_LED_MAX > 2)  
  908.     else if(2 == led_id)return msg_led_cfg[2];  
  909.   #endif  
  910.   #if(SHELL_LED_MAX > 3)  
  911.     else if(3 == led_id)return msg_led_cfg[3];  
  912.   #endif  
  913.   #if(SHELL_LED_MAX > 4)  
  914.     else if(4 == led_id)return msg_led_cfg[4];  
  915.   #endif  
  916.   #if(SHELL_LED_MAX > 5)  
  917.     else if(5 == led_id)return msg_led_cfg[5];  
  918.   #endif   
  919.     else return 0;  
  920. }  
  921.   
  922. /****************************************************************************** 
  923. ***********************************   END  ************************************ 
  924. ******************************************************************************/  


四. shell使用

以MDK为例:

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

 

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

 
[cpp] view plain copy
 
  1. /****************************************************************************** 
  2. *********************************Shell 函数声 明 ****************************** 
  3. ******************************************************************************/  
  4. extern void Shell_SPI_Service(void);  
  5. extern void Shell_RTC_Service(void);  
  6. extern void Shell_WIZ_Service(void);  
  7. extern void Shell_UPAN_Service(void);  
  8. extern void Shell_IAP_Service(uint8_t const this_ver);  
 
[cpp] view plain copy
 
  1. shell_GPIO_Config(30,10,46,1);  //shell接口和四个LED灯的信号配置  
  2. shell_Init(460800);     //初始化shell控制台  



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

[cpp] view plain copy
 
  1. //Shell构架的控制台服务  
  2. if(shell_rx_rdy)  
  3. {  
  4.     Shell_IAP_Service(SOFT_VER);    //IAP模块指令处理  
  5.     Shell_SPI_Service();            //SPI_FLASH模块指令处理  
  6.     Shell_WIZ_Service();            //网卡模块的指令处理   
  7.     Shell_RTC_Service();            //RTC模块的指令处理  
  8.     Shell_MCU_Service();            //MCU杂项功能指令处理  
  9.     Shell_VLSI_Service();           //声卡模块的指令处理  
  10.     Shell_UPAN_Service();           //U盘模块的指令处理  
  11.     Shell_Invalid_Service();        //指令无效的缺省处理  
  12. }  

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

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

五. RTC Shell服务文件示例

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

[cpp] view plain copy
 
  1. /*********************************Copyright (c)********************************* 
  2. **                                
  3. **                                 FIVE工作组 
  4. ** 
  5. **---------------------------------File Info------------------------------------ 
  6. ** File Name:               rtc_shell.c 
  7. ** Last modified Date:      2014/3/5 9:27:49 
  8. ** Last Version:            V2.0   
  9. ** Description:             文件操作命令解释,需要Console Shell V2以上支持 
  10. ** 
  11. **------------------------------------------------------------------------------ 
  12. ** Created By:              wanxuncpx 
  13. ** Created date:            2014/3/5 9:28:31 
  14. ** Version:                 V2.0 
  15. ** Descriptions:            none 
  16. **------------------------------------------------------------------------------ 
  17. ** HW_CMU:                  ANSIC 
  18. ** Libraries:               NONE 
  19. ** version                  NONE 
  20. *******************************************************************************/  
  21.   
  22. /****************************************************************************** 
  23. 更新说明: 
  24. ******************************************************************************/  
  25.   
  26. /****************************************************************************** 
  27. *********************************  编 译 控 制 ******************************** 
  28. ******************************************************************************/  
  29. #define RTC_SHELL       //注释掉时屏蔽iap shell功能  
  30.   
  31. /****************************************************************************** 
  32. ********************************* 文件引用部分 ******************************** 
  33. ******************************************************************************/  
  34. /*---------------------*  
  35. *     文件包含 
  36. *----------------------*/  
  37. //基础支持文件  
  38. #include "shell.h"          //Shell支持文件,含bool,uint8_t..以及串口数据收发操作  
  39. #include "rtc.h"         //命令控制支持文件  
  40.   
  41. /*---------------------*  
  42. *     Shell版本判断 
  43. *----------------------*/  
  44. #ifdef SHELL_VER  
  45.   #if (SHELL_VER < 2)  
  46.     #error "shell版本太低"  
  47.   #endif  
  48. #else  
  49.     #error "未找到Shell文件,或shell版本信息"  
  50. #endif  
  51.   
  52. /****************************************************************************** 
  53. ********************************* 输出函数功能 ******************************** 
  54. ******************************************************************************/  
  55. /*---------------------*  
  56. *       输出函数功能 
  57. *----------------------*/  
  58. #ifdef RTC_SHELL  
  59.   extern void Shell_RTC_Service(void);  
  60. #else  
  61.   void Shell_RTC_Service(void){;}  
  62. #endif  
  63.   
  64. /*---------------------*  
  65. *       输入函数 
  66. *----------------------*/  
  67. //none  
  68.   
  69. /****************************************************************************** 
  70. ********************************* 数 据 声 明 ********************************* 
  71. ******************************************************************************/  
  72. #ifdef RTC_SHELL  
  73. /*---------------------*  
  74. *        
  75. *----------------------*/  
  76. //命令帮助文件  
  77. const char RTC_HelpMsg[] =  
  78.     "[RTC contorls] "  
  79.     " rtc help - help. "  
  80.     " rtc rd info - Read RTC info. "  
  81.     " rtc rd time - Read RTC date and time. "  
  82.     " rtc wr time <Hour>:<Minute>:<Second>    - Write time. "  
  83.     " rtc wr date <Year>-<Month>-<Day> <Week> - Warning Week=[1..7] "  
  84.     " ";  
  85.       
  86. /****************************************************************************** 
  87. ********************************* 函 数 声 明 ********************************* 
  88. ******************************************************************************/  
  89.   
  90. /****************************************************************************** 
  91. / 函数功能:文件系统Shel指令处理 
  92. / 修改日期:2013/9/10 19:04:15 
  93. / 输入参数:输入当前的程序版本 
  94. / 输出参数:none 
  95. / 使用说明:none 
  96. ******************************************************************************/  
  97. void Shell_RTC_Service(void)  
  98. {  
  99.     uint8_t     *ptRxd;         //用于接收指令处理  
  100.     //uint8_t     *ptTxd;         //方便用于指令发送  
  101.     int         i,j,k,l;  
  102.     //int         tx_len,drv;  
  103.     //uint32_t    u32_arg[4];  
  104.     uint16_t    retval;  
  105.     uint8_t     arg[32];  
  106.     uint32_t    tmp_time;  
  107.   
  108.     //指令初级过滤  
  109.     //--------------------------------------------------------------------------  
  110.     //格式:<->[cmd bytes]<CRLF>  即"-[cmd bytes] "  
  111.     //指令必须以"-"开始, 以" "结束  
  112.     i = shell_rx_rdy;  
  113.     if( (i < 2) || (' ' != shell_rx_buff[i-2]) || (' ' != shell_rx_buff[i-1]))return;  
  114.       
  115.     //长度和前缀过滤  
  116.     ptRxd = (uint8_t *)shell_rx_buff;  
  117.     if( (' ' != shell_rx_buff[3]) || ('r' != shell_rx_buff[0]) || (i < 6) ||   
  118.         ('t' != shell_rx_buff[1]) || ('c' != shell_rx_buff[2]) )  return;  
  119.           
  120.     //处理指令  
  121.     //--------------------------------------------------------------------------  
  122.     ptRxd += 4;  
  123.     if(StrComp(ptRxd,"rd time"))    //按包读取指令  
  124.     {  
  125.         RTC_Sprintf_CurrTime((void *)arg);    
  126.         printf("Time:%s ",arg);   
  127.     }  
  128.     else if(StrComp(ptRxd,"rd info "))      //读取RTC信息  
  129.     {  
  130.         //打印当前时间和上次复位时间  
  131.         RTC_Sprintf_CurrTime((void *)arg);   
  132.         printf("->Time:%s ResetCounter:%d ",arg,RESET_CNT);  
  133.         RTC_Sprintf_ResetCurr((void *)arg,&tmp_time);   
  134.         printf(" CurrReset:%s Run: %d Days, %d hour, %d minute ",  
  135.             arg,tmp_time/(24*60),(tmp_time%(24*60))/60,tmp_time%60 );   
  136.         RTC_Sprintf_ResetLast((void *)arg,&tmp_time);   
  137.         printf(" NextReset:%s Run: %d Days, %d hour, %d minute ",  
  138.             arg,tmp_time/(24*60),(tmp_time%(24*60))/60,tmp_time%60 );      
  139.     }  
  140.     else if(StrComp(ptRxd,"wr time "))      //写时间  
  141.     {  
  142.         retval = sscanf((void*)shell_rx_buff,"%*s%*s%*s%d:%d:%d",&i,&j,&k);  
  143.         if(3 != retval)return;   //没有接收到3个输入数据,直接退出  
  144.         if(RTC_TimeWrite((uint8_t)i,(uint8_t)j,(uint8_t)k) )  
  145.         {  
  146.             RTC_Sprintf_CurrTime((void *)arg);  
  147.             printf("->CurrTime:%s ",arg);      
  148.         }  
  149.         else  
  150.         {  
  151.             printf("->Error Time Input! ");  
  152.             shell_rx_rdy = 0;       //不用触发错误指令显示   
  153.             return;     
  154.         }  
  155.     }  
  156.     else if(StrComp(ptRxd,"wr date "))      //写日期  
  157.     {  
  158.         retval = sscanf((void*)shell_rx_buff,"%*s%*s%*s%d-%d-%d %d",&i,&j,&k,&l);  
  159.         if(4 != retval)return;   //没有接收到4个输入数据,直接退出  
  160.         if(RTC_DateWrite((uint16_t)i,(uint8_t)j,(uint8_t)k,(uint8_t)l))  
  161.         {  
  162.             RTC_Sprintf_CurrTime((void *)arg);  
  163.             printf("->CurrTime:%s ",arg);      
  164.         }  
  165.         else  
  166.         {  
  167.             printf("->Error Date Input! ");  
  168.             shell_rx_rdy = 0;       //shell_rx_rdy为0,表示指令已被处理完毕,否者下个Shell服务继续调用  
  169.             return;      
  170.         }  
  171.     }  
  172.     else if(StrComp(ptRxd,"help "))      //指令帮助  
  173.     {  
  174.         shell_SendStr((void *)RTC_HelpMsg);  
  175.     }  
  176.     else return;  
  177.       
  178.     //退出处理  
  179.     //--------------------------------------------------------------------------  
  180.     shell_rx_rdy = 0;   //shell_rx_rdy为0,表示指令已被处理完毕,否者下个Shell服务继续调用  
  181. }  
  182.   
  183. /****************************************************************************** 
  184. ***********************************   END  ************************************ 
  185. ******************************************************************************/  
  186. #endif  


     更多全新视频: www.makeru.com.cn/?t=12                      嵌入式学习交流群:561213221

原文地址:https://www.cnblogs.com/huan-huan/p/8488024.html