• 一种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

  • 相关阅读:
    Linux目录
    find命令
    107. Binary Tree Level Order Traversal II
    grep命令
    110. Balanced Binary Tree
    111. Minimum Depth of Binary Tree
    什么是泛型
    自动装箱与拆箱
    HDU 3001 Travelling (状压DP + BFS)
    POJ 3411 Paid Roads (状态压缩+BFS)
  • 原文地址:https://www.cnblogs.com/huan-huan/p/8488024.html
Copyright © 2020-2023  润新知