一.背景
曾經玩Linux時非常喜歡這種基於出串列埠的控制檯, 通過簡單的串列埠TX和RX能實現嵌入式硬體的人機互動,非常實用, 那麼STM32能否實現通過超級終端與使用者互動的構想呢? 答案是肯定的,由於這個UART控制平臺就像應用程式套上一層可訪問的外科(Shell)故而我將這種基於UART的控制平臺簡稱Shell,構架和效果如下圖:
這張圖箭頭指向的是輸入的指令,其餘是STM32串列埠輸出的資訊,, 可以看到通過這些簡單的指令輸入我們通過Shell可以做很多事情:
1. 現場裝置發生故障,可以通過Shell可以檢視裝置的故障狀態統計資訊
2. 能實現串列埠程式升級(需要Shell+IAP驅動程式支援)
3. 能讀寫訪問引數區,實現對裝置引數的本地配置
4. 配置多功能訊號指示燈(LED燈可顯示65535種訊號,同一時刻只能顯示一個.
5. 程式開發階段基於Shell,可以極其方便的除錯編寫的驅動程式(開發極力推薦),非常好用.
二.Shell基礎篇
Shell基礎程式只有三個檔案:
console.h:用於定義STM32用於Shell的實體串列埠
shell.cshell平臺實現主體
shell.h標頭檔案,任意的驅動檔案可呼叫,就像<stdio.h>一樣
shell.c目前包含三個部件:
shell模組(必選)Shell模組初始化時已初始化好Led模組
Led模組(必選)Ledx_on(x),Ledx_off(x),Ledx_div(x),函式是對編碼訊號進行控制,而不是直接對硬體實體控制,這樣每個LED實體就像通道一樣可以選擇非常多的訊號源顯示.
精密延時模組(可選)啟動需要對其初始化,此模組可用於記錄時間點,並判斷時間是否到(再也不用Delayms()這樣的函式浪費效率實現時序了.
三. 程式檔案:
1. console.h
- /*********************************Copyright (c)*********************************
- **
- ** FIVE工作組
- **
- **———————————File Info————————————
- ** File Name: shell_hal.h
- ** Last modified Date: 2014/5/26 14:22:35
- ** Last Version: V1.0
- ** Description: 本地Shell檔案介面
- **
- **——————————————————————————
- ** Created By: wanxuncpx
- ** Created date: 2014/5/26 14:22:34
- ** Version: V2
- ** Descriptions: 只適合STM32程式
- **——————————————————————————
- ** Libraries: STM32F10x_StdPeriph_Driver
- ** version V3.5
- *******************************************************************************/
- /******************************************************************************
- 更新說明:
- ******************************************************************************/
- /******************************************************************************
- ********************************* 應 用 資 料 ********************************
- ******************************************************************************/
- #ifndef _SHELL_HAL_
- #define _SHELL_HAL_
- /******************************************************************************
- ********************************* 檔案引用部分 ********************************
- ******************************************************************************/
- //包含庫檔案
- #include "stm32f10x.h"
- #include "stm32f10x_gpio.h"
- #include "stm32f10x_rcc.h"
- #include "stm32f10x_tim.h"
- /******************************************************************************
- ******************************** 可 配 置 參 數 *******************************
- ******************************** MNCS_IMAGE影象板 *****************************
- ******************************************************************************/
- /*———————*
- * UART埠配置
- *———————-*/
- //IO配置
- #define CONSOLE USART3
- #define CONSOLE_TX_PORT GPIOB
- #define CONSOLE_TX_PIN GPIO_Pin_10
- #define CONSOLE_RX_PORT GPIOB
- #define CONSOLE_RX_PIN GPIO_Pin_11
- //時鐘配置
- #define CONSOLE_GPIO_RCC_INIT() RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE)
- #define CONSOLE_UART_RCC_INIT() RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE)
- //中斷優先順序
- #define CONSOLE_UART_PRIO 7 //建議[0..15]
- //中斷向量配置
- #define CONSOLE_IRQn USART3_IRQn;
- #define CONSOLE_IRQHandler USART3_IRQHandler
- /*———————*
- * 四個LED定義
- *———————-*/
- #define LED0_VALID 1 //非零表示使能對應的LED,0:無效
- #define LED0_PORT GPIOB
- #define LED0_PIN GPIO_Pin_13
- #define LED1_VALID 1 //非零表示使能對應的LED,0:無效
- #define LED1_PORT GPIOB
- #define LED1_PIN GPIO_Pin_15
- #define LED2_VALID 0 //非零表示使能對應的LED,0:無效
- #define LED2_PORT GPIOA
- #define LED2_PIN GPIO_Pin_11
- #define LED3_VALID 0 //非零表示使能對應的LED,0:無效
- #define LED3_PORT GPIOA
- #define LED3_PIN GPIO_Pin_11
- #define LED4_VALID 0 //非零表示使能對應的LED,0:無效
- #define LED4_PORT GPIOA
- #define LED4_PIN GPIO_Pin_11
- #define LED5_VALID 0 //非零表示使能對應的LED,0:無效
- #define LED5_PORT GPIOA
- #define LED5_PIN GPIO_Pin_11
- /*———————*
- * 時基BASE
- *———————-*/
- #define TIMEDly TIM4
- #define TIMEDly_IRQn TIM4_IRQn
- #define TIMEDly_IRQHandler TIM4_IRQHandler
- //時鐘配置
- #define TIMEDly_RCC_INIT() RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
- //初始化LGPIO口
- #define LEDx_GPIO_RCC_INIT() RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE)
- //——————————————————————————
- /******************************************************************************
- ******************************* 以下引數無需更改 ******************************
- ******************************************************************************/
- /*———————*
- * 注意以下區域無需使用者更改
- *———————-*/
- #if LED0_VALID
- #define LED0_ON() (LED0_PORT->BRR = LED0_PIN)
- #define LED0_OFF() (LED0_PORT->BSRR = LED0_PIN)
- #define LED0_DIV() (LED0_PORT->ODR ^= LED0_PIN)
- #else
- #define LED0_ON() __NOP()
- #define LED0_OFF() __NOP()
- #define LED0_DIV() __NOP()
- #endif
- #if LED1_VALID
- #define LED1_ON() (LED1_PORT->BRR = LED1_PIN)
- #define LED1_OFF() (LED1_PORT->BSRR = LED1_PIN)
- #define LED1_DIV() (LED1_PORT->ODR ^= LED1_PIN)
- #else
- #define LED1_ON() __NOP()
- #define LED1_OFF() __NOP()
- #define LED1_DIV() __NOP()
- #endif
- #if LED2_VALID
- #define LED2_ON() (LED2_PORT->BRR = LED2_PIN)
- #define LED2_OFF() (LED2_PORT->BSRR = LED2_PIN)
- #define LED2_DIV() (LED2_PORT->ODR ^= LED2_PIN)
- #else
- #define LED2_ON() __NOP()
- #define LED2_OFF() __NOP()
- #define LED2_DIV() __NOP()
- #endif
- #if LED3_VALID
- #define LED3_ON() (LED3_PORT->BRR = LED3_PIN)
- #define LED3_OFF() (LED3_PORT->BSRR = LED3_PIN)
- #define LED3_DIV() (LED3_PORT->ODR ^= LED3_PIN)
- #else
- #define LED3_ON() __NOP()
- #define LED3_OFF() __NOP()
- #define LED3_DIV() __NOP()
- #endif
- #if LED4_VALID
- #define LED4_ON() (LED4_PORT->BSRR = LED4_PIN)
- #define LED4_OFF() (LED4_PORT->BRR = LED4_PIN)
- #define LED4_DIV() (LED4_PORT->ODR ^= LED4_PIN)
- #else
- #define LED4_ON() __NOP()
- #define LED4_OFF() __NOP()
- #define LED4_DIV() __NOP()
- #endif
- #if LED5_VALID
- #define LED5_ON() (LED5_PORT->BSRR = LED5_PIN)
- #define LED5_OFF() (LED5_PORT->BRR = LED5_PIN)
- #define LED5_DIV() (LED5_PORT->ODR ^= LED5_PIN)
- #else
- #define LED5_ON() __NOP()
- #define LED5_OFF() __NOP()
- #define LED5_DIV() __NOP()
- #endif
- /******************************************************************************
- ******************************* printf支援檔案 ********************************
- ******************************************************************************/
- /* Private function prototypes ———————————————–*/
- #ifdef __GNUC__
- /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
- set to ‘Yes’) calls __io_putchar() */
- #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
- #else
- #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
- #endif /* __GNUC__ */
- /******************************************************************************
- *********************************** END ************************************
- ******************************************************************************/
- #endif
2. shell.h
- /*********************************Copyright (c)*********************************
- **
- ** FIVE工作組
- **
- **———————————File Info————————————
- ** File Name: shell.h
- ** Last modified Date: 2014/3/5 15:42:05
- ** Last Version: V2
- ** Description: none
- **
- **——————————————————————————
- ** Created By: wanxuncpx
- ** Created date: 2014/3/5 15:42:11
- ** Version: V2
- ** Descriptions: none
- **——————————————————————————
- ** Libraries: 無關
- ** version 無關
- *******************************************************************************/
- /******************************************************************************
- 更新說明:
- ******************************************************************************/
- /******************************************************************************
- ********************************* 應 用 資 料 ********************************
- ******************************************************************************/
- #ifndef _SHELL_H_
- #define _SHELL_H_
- /******************************************************************************
- ********************************* 檔案引用部分 ********************************
- ******************************************************************************/
- #include "stdint.h" //包含uint8_t等資料型別
- #include "stdbool.h" //包含Bool型別
- #include "stdio.h" //包含printf支援
- /******************************************************************************
- ********************************* 引數巨集定義 *********************************
- ******************************************************************************/
- //版本定義
- #define SHELL_VER 2 //Shell版本
- #ifndef SHELL_LED_MAX //LED實體數量
- #define SHELL_LED_MAX 4
- #endif
- //緩衝大小配置
- #define SHELL_RX_MAX (256+32) //shell指令接收緩衝大小
- #define SHELL_TX_MAX (512) //shell指令傳送緩衝大小
- /******************************************************************************
- ********************************* 數 據 聲 明 *********************************
- ******************************************************************************/
- /*———————*
- * Shell接收
- *———————-*/
- //接收資料
- extern volatile uint16_t shell_rx_rdy; //0:空閒,非零:忙,使用者讀為非零後清零
- extern volatile uint8_t shell_rx_buff[SHELL_RX_MAX+1]; //接收緩衝
- /******************************************************************************
- ********************************* 函 數 聲 明 *********************************
- ******************************************************************************/
- /*———————*
- * 輸出函式
- *———————-*/
- //除錯Shell的介面數量
- #if (6 == SHELL_LED_MAX)
- extern void shell_GPIO_Config(uint16_t led0_cfg,uint16_t led1_cfg,
- uint16_t led2_cfg,uint16_t led3_cfg,
- uint16_t led4_cfg,uint16_t led5_cfg);
- #elif (5 == SHELL_LED_MAX)
- extern void shell_GPIO_Config(uint16_t led0_cfg,uint16_t led1_cfg,
- uint16_t led2_cfg,uint16_t led3_cfg,
- uint16_t led4_cfg);
- #elif (4 == SHELL_LED_MAX)
- extern void shell_GPIO_Config(uint16_t led0_cfg,uint16_t led1_cfg,
- uint16_t led2_cfg,uint16_t led3_cfg);
- #elif (3 == SHELL_LED_MAX)
- extern void shell_GPIO_Config(uint16_t led0_cfg,uint16_t led1_cfg,
- uint16_t led2_cfg);
- #elif (2 == SHELL_LED_MAX)
- extern void shell_GPIO_Config(uint16_t led0_cfg,uint16_t led1_cfg);
- #elif (1 == SHELL_LED_MAX)
- extern void shell_GPIO_Config(uint16_t led0_cfg);
- #endif
- //檢測引數合法性
- #if ((SHELL_LED_MAX > 6) || (SHELL_LED_MAX == 0))
- #error SHELL_LED_MAX is invaild!
- #endif
- //初始化Shell
- extern void shell_Init(uint32_t baud); //模組初始化
- extern void shell_SendStr(void * ptStr); //傳送以’\0’結束的字串
- extern void shell_SendHex(void * ptHex,uint16_t size); //傳送指定個數的資料
- /*———————*
- * LEDx測試訊號定義
- *———————-*/
- extern void Ledx_config(uint8_t led_id,uint16_t msg_id); //設定LED的配置訊號
- extern uint16_t Ledx_read(uint8_t led_id); //讀取LED的配置訊號(失敗返回0)
- extern void Ledx_on (uint16_t msg_id); //傳送LED開訊息
- extern void Ledx_off(uint16_t msg_id); //傳送LED關訊息
- extern void Ledx_div(uint16_t msg_id); //傳送LED取反訊息
- /*———————*
- * 時基延時函式
- *———————-*/
- extern void Delay_LibInit(void);
- extern void DlyTime_us(uint16_t us);
- extern void DlyTime_ms(uint16_t ms);
- extern void DlyWait_base(volatile uint64_t * ptCnt); //標記為等待的基點時間
- extern uint32_t DlyWait_lost(volatile uint64_t * ptCnt);//判斷逝去的時間(us)
- /*———————*
- * 輔助判斷指令
- *———————-*/
- extern bool StrComp(void * buffer,void * StrCmd); //字串匹配比較函式
- /*———————*
- * Shell服務
- *———————-*/
- //在main.c函式while()中判斷shell_rx_rdy是否為非零,為非零才執行以下程式
- extern void Shell_Invalid_Service(void); //指令未處理服務(會處理shell_rx_rdy訊號)
- /******************************************************************************
- *********************************** END ************************************
- ******************************************************************************/
- #endif
3.shell.c
- /*********************************Copyright (c)*********************************
- **
- ** FIVE工作組
- **
- **———————————File Info————————————
- ** File Name: shell.c
- ** Last modified Date: 2014/3/5 16:43:59
- ** Last Version: V2
- ** Description: none
- **
- **——————————————————————————
- ** Created By: wanxuncpx
- ** Created date: 2014/3/5 16:43:58
- ** Version: V2
- ** Descriptions: 適合於STM32
- **——————————————————————————
- ** Libraries: STM32F10x_StdPeriph_Driver
- ** version V3.5
- *******************************************************************************/
- /******************************************************************************
- 更新說明:
- ******************************************************************************/
- /******************************************************************************
- ********************************* 應 用 資 料 ********************************
- ******************************************************************************/
- /******************************************************************************
- ********************************* 檔案引用部分 ********************************
- ******************************************************************************/
- #include "shell.h" //包含Shell介面檔案
- //是否使用擴充套件的Shell介面
- #ifdef SHELL_HAL_EXT
- #include "shell_hal.h" //本地的Shell檔案
- #else
- #include "console.h" //標準的Shell檔案
- #endif
- /******************************************************************************
- ********************************* Shell.h定義 *********************************
- ******************************************************************************/
- /*———————*
- * Shell 收發標記
- *———————-*/
- volatile uint16_t shell_rx_rdy = 0; //0:空閒,非零:忙
- volatile uint8_t shell_rx_buff[SHELL_RX_MAX+1]="\0"; //接收緩衝
- /******************************************************************************
- ********************************* 本 地 數 據 *********************************
- ******************************************************************************/
- /*———————*
- * Shell緩衝定義
- *———————-*/
- //接收
- static volatile uint16_t shell_rx_index = 0; //資料接收標記
- //傳送
- static volatile uint8_t shell_tx_buff[SHELL_TX_MAX+1]="\0";
- static volatile uint16_t shell_tx_size = 0; //0:空閒,非零:忙
- static volatile uint16_t shell_tx_index = 0; //傳送資料標記
- /*———————*
- * LED控制訊號
- *———————-*/
- static volatile uint16_t msg_led_cfg[SHELL_LED_MAX]; //配置訊號
- /*———————*
- * 延時模組定義
- *———————-*/
- static volatile uint64_t TimeDlyCnt = 0; //用於輔助的延時計數值
- /******************************************************************************
- ********************************* 函 數 聲 明 *********************************
- ******************************************************************************/
- /******************************************************************************
- / 函式功能:初始化GPIO口(串列埠和四個LED燈配置)
- / 修改日期:none
- / 輸入引數:none
- / 輸出引數:none
- / 使用說明:none
- ******************************************************************************/
- #if (6 == SHELL_LED_MAX)
- void shell_GPIO_Config( uint16_t led0_cfg,uint16_t led1_cfg,
- uint16_t led2_cfg,uint16_t led3_cfg,
- uint16_t led4_cfg,uint16_t led5_cfg)
- #elif (5 == SHELL_LED_MAX)
- void shell_GPIO_Config( uint16_t led0_cfg,uint16_t led1_cfg,
- uint16_t led2_cfg,uint16_t led3_cfg,
- uint16_t led4_cfg)
- #elif (4 == SHELL_LED_MAX)
- void shell_GPIO_Config( uint16_t led0_cfg,uint16_t led1_cfg,
- uint16_t led2_cfg,uint16_t led3_cfg)
- #elif (3 == SHELL_LED_MAX)
- void shell_GPIO_Config( uint16_t led0_cfg,uint16_t led1_cfg,
- uint16_t led2_cfg)
- #elif (2 == SHELL_LED_MAX)
- void shell_GPIO_Config(uint16_t led0_cfg,uint16_t led1_cfg)
- #elif (1 == SHELL_LED_MAX)
- void shell_GPIO_Config(uint16_t led0_cfg)
- #endif
- {
- GPIO_InitTypeDef GPIO_InitStruct;
- /* 配置串列埠 ———————————————————*/
- // 開啟在APB2上的GPIO口外設時鐘
- CONSOLE_GPIO_RCC_INIT(); //開啟GPIO口的時鐘
- // 配置TX引腳
- GPIO_InitStruct.GPIO_Pin = CONSOLE_TX_PIN;
- GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(CONSOLE_TX_PORT, &GPIO_InitStruct);
- // 配置RX引腳
- GPIO_InitStruct.GPIO_Pin = CONSOLE_RX_PIN;
- GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
- GPIO_Init(CONSOLE_RX_PORT, &GPIO_InitStruct);
- //鎖定GPIO口,防止其他更改
- GPIO_PinLockConfig(CONSOLE_TX_PORT,CONSOLE_TX_PIN);
- GPIO_PinLockConfig(CONSOLE_RX_PORT,CONSOLE_RX_PIN);
- /* 配置LEDx ———————————————————*/
- LEDx_GPIO_RCC_INIT();
- GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
- GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;
- //根據定義配置四個LED
- #if (SHELL_LED_MAX > 0)
- GPIO_InitStruct.GPIO_Pin = LED0_PIN;
- GPIO_Init(LED0_PORT, &GPIO_InitStruct);
- GPIO_PinLockConfig(LED0_PORT,LED0_PIN);
- msg_led_cfg[0] = led0_cfg;
- LED0_OFF();
- #endif
- #if (SHELL_LED_MAX > 1)
- GPIO_InitStruct.GPIO_Pin = LED1_PIN;
- GPIO_Init(LED1_PORT, &GPIO_InitStruct);
- GPIO_PinLockConfig(LED1_PORT,LED1_PIN);
- msg_led_cfg[1] = led1_cfg;
- LED1_OFF();
- #endif
- #if (SHELL_LED_MAX > 2)
- GPIO_InitStruct.GPIO_Pin = LED2_PIN;
- GPIO_Init(LED2_PORT, &GPIO_InitStruct);
- GPIO_PinLockConfig(LED2_PORT,LED2_PIN);
- msg_led_cfg[2] = led2_cfg;
- LED2_OFF();
- #endif
- #if (SHELL_LED_MAX > 3)
- GPIO_InitStruct.GPIO_Pin = LED3_PIN;
- GPIO_Init(LED3_PORT, &GPIO_InitStruct);
- GPIO_PinLockConfig(LED3_PORT,LED3_PIN);
- msg_led_cfg[3] = led3_cfg;
- LED3_OFF();
- #endif
- #if (SHELL_LED_MAX > 4)
- GPIO_InitStruct.GPIO_Pin = LED4_PIN;
- GPIO_Init(LED4_PORT, &GPIO_InitStruct);
- GPIO_PinLockConfig(LED4_PORT,LED4_PIN);
- msg_led_cfg[4] = led4_cfg;
- LED4_OFF();
- #endif
- #if (SHELL_LED_MAX > 5)
- GPIO_InitStruct.GPIO_Pin = LED5_PIN;
- GPIO_Init(LED5_PORT, &GPIO_InitStruct);
- GPIO_PinLockConfig(LED5_PORT,LED5_PIN);
- msg_led_cfg[5] = led5_cfg;
- LED5_OFF();
- #endif
- }
- /******************************************************************************
- / 函式功能:串列埠初始化,使用中斷單位元組接收資料
- / 修改日期:none
- / 輸入引數:baud 波特率
- / 輸出引數:none
- / 使用說明:none
- ******************************************************************************/
- void shell_Init(uint32_t baud)
- {
- USART_InitTypeDef USART_InitStructure;
- NVIC_InitTypeDef NVIC_UART_Cfg; //UART中斷向量
- //————————— 先定義好資料結構 —————————
- //定義好USART結構體
- USART_InitStructure.USART_BaudRate = baud;
- USART_InitStructure.USART_WordLength = USART_WordLength_8b;
- USART_InitStructure.USART_StopBits = USART_StopBits_1;
- USART_InitStructure.USART_Parity = USART_Parity_No ;
- USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
- USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
- USART_InitStructure.USART_BaudRate = USART_InitStructure.USART_BaudRate; //防止編譯報錯
- //定義好NVIC:UART中斷
- NVIC_UART_Cfg.NVIC_IRQChannel = CONSOLE_IRQn;
- NVIC_UART_Cfg.NVIC_IRQChannelPreemptionPriority = 1;
- NVIC_UART_Cfg.NVIC_IRQChannelSubPriority = CONSOLE_UART_PRIO;
- NVIC_UART_Cfg.NVIC_IRQChannelCmd = ENABLE;
- NVIC_UART_Cfg.NVIC_IRQChannel = NVIC_UART_Cfg.NVIC_IRQChannel; //防止編譯報錯
- //模式配置
- //————————— 中斷方式收發資料 —————————-
- CONSOLE_UART_RCC_INIT(); //開啟USART的時鐘
- USART_Cmd(CONSOLE, DISABLE); //關閉UART
- USART_Init(CONSOLE, &USART_InitStructure); //初始化串列埠
- USART_ITConfig(CONSOLE, USART_IT_RXNE, ENABLE);
- USART_ITConfig(CONSOLE, USART_IT_IDLE, ENABLE);
- USART_Cmd(CONSOLE, ENABLE);
- NVIC_Init(&NVIC_UART_Cfg); //配置好NVIC
- }
- /******************************************************************************
- / 函式功能:Delay延時庫初始化(需要1us的計數精度,和50ms的溢位計數)
- / 修改日期:2014/5/1 21:02:58
- / 輸入引數:none
- / 輸出引數:none
- / 使用說明:(限STM32F40X的TIM2,TIM3,TIM4,TIM5)
- ******************************************************************************/
- void Delay_LibInit(void)
- {
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
- NVIC_InitTypeDef NVIC_InitStructure;
- //開啟TIM2時鐘
- TIMEDly_RCC_INIT();
- /* Enable the TIMx gloabal Interrupt */
- NVIC_InitStructure.NVIC_IRQChannel = TIMEDly_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 0;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //由於是時基,需要使用最高優先順序
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStructure);
- /* Time base configuration */
- TIM_TimeBaseStructure.TIM_Period = 65000;
- TIM_TimeBaseStructure.TIM_Prescaler = (SystemCoreClock/1000000)-1;
- TIM_TimeBaseStructure.TIM_ClockDivision = 0;
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
- TIM_TimeBaseInit(TIMEDly, &TIM_TimeBaseStructure);
- /* TIM Interrupts enable */
- TIM_ITConfig(TIMEDly,TIM_IT_Update, ENABLE);
- /* TIMx enable counter */
- TIM_Cmd(TIMEDly, ENABLE);
- }
- /******************************************************************************
- / 函式功能:等待一個us延時
- / 修改日期:2014/5/1 21:02:58
- / 輸入引數:none
- / 輸出引數:none
- / 使用說明:none
- ******************************************************************************/
- void DlyTime_us(uint16_t us)
- {
- uint64_t this_cnt,over_cnt,tmp_val;
- //得到當前的準確時間
- do
- {
- this_cnt = TIMEDly->CNT + TimeDlyCnt;
- if( (TIMEDly->SR & TIM_IT_Update) &&
- (TIMEDly->SR & TIM_IT_Update) &&
- (TIMEDly->SR & TIM_IT_Update) )
- {
- TIMEDly->SR = (uint16_t)~TIM_IT_Update;
- TimeDlyCnt += 65000;
- }
- tmp_val = TIMEDly->CNT + TimeDlyCnt;
- }
- while(this_cnt != tmp_val);
- over_cnt = this_cnt + us; //得到目標延時時間
- //延時函式
- do
- {
- if( (TIMEDly->SR & TIM_IT_Update) &&
- (TIMEDly->SR & TIM_IT_Update) &&
- (TIMEDly->SR & TIM_IT_Update) )
- {
- TIMEDly->SR = (uint16_t)~TIM_IT_Update;
- TimeDlyCnt += 65000;
- }
- this_cnt = TIMEDly->CNT + TimeDlyCnt;
- }
- while(this_cnt < over_cnt);
- }
- /******************************************************************************
- / 函式功能:等待一個ms延時
- / 修改日期:2014/5/1 21:02:58
- / 輸入引數:none
- / 輸出引數:none
- / 使用說明:none
- ******************************************************************************/
- void DlyTime_ms(uint16_t ms)
- {
- uint64_t this_cnt,over_cnt,tmp_val;
- //得到當前的準確時間
- do
- {
- this_cnt = TIMEDly->CNT + TimeDlyCnt;
- if( (TIMEDly->SR & TIM_IT_Update) &&
- (TIMEDly->SR & TIM_IT_Update) &&
- (TIMEDly->SR & TIM_IT_Update) )
- {
- TIMEDly->SR = (uint16_t)~TIM_IT_Update;
- TimeDlyCnt += 65000;
- }
- tmp_val = TIMEDly->CNT + TimeDlyCnt;
- }
- while(this_cnt != tmp_val);
- over_cnt = this_cnt + (uint32_t)ms*1000;
- //延時函式
- do
- {
- if( (TIMEDly->SR & TIM_IT_Update) &&
- (TIMEDly->SR & TIM_IT_Update) &&
- (TIMEDly->SR & TIM_IT_Update) )
- {
- TIMEDly->SR = (uint16_t)~TIM_IT_Update;
- TimeDlyCnt += 65000;
- }
- this_cnt = TIMEDly->CNT + TimeDlyCnt;
- }
- while(this_cnt < over_cnt);
- }
- /******************************************************************************
- / 函式功能:標記時間起點
- / 修改日期:2014/5/1 21:02:58
- / 輸入引數:none
- / 輸出引數:none
- / 使用說明:none
- ******************************************************************************/
- void DlyWait_base(volatile uint64_t * ptCnt)
- {
- uint64_t this_cnt,tmp_val;
- //得到當前的準確時間
- do
- {
- this_cnt = TIMEDly->CNT + TimeDlyCnt;
- if( (TIMEDly->SR & TIM_IT_Update) &&
- (TIMEDly->SR & TIM_IT_Update) &&
- (TIMEDly->SR & TIM_IT_Update) )
- {
- TIMEDly->SR = (uint16_t)~TIM_IT_Update;
- TimeDlyCnt += 65000;
- }
- tmp_val = TIMEDly->CNT + TimeDlyCnt;
- }
- while(this_cnt != tmp_val);
- *ptCnt = this_cnt;
- }
- /******************************************************************************
- / 函式功能:檢測從起點開始已逝去的時間(最大1個小時)
- / 修改日期:2014/5/1 21:02:58
- / 輸入引數:none
- / 輸出引數:返回0表示時間到,返回非零表示時間未到
- / 使用說明:none
- ******************************************************************************/
- uint32_t DlyWait_lost(volatile uint64_t * ptCnt)
- {
- uint64_t this_cnt,tmp_val;
- //得到當前的準確時間
- do
- {
- this_cnt = TIMEDly->CNT + TimeDlyCnt;
- if( (TIMEDly->SR & TIM_IT_Update) &&
- (TIMEDly->SR & TIM_IT_Update) &&
- (TIMEDly->SR & TIM_IT_Update) )
- {
- TIMEDly->SR = (uint16_t)~TIM_IT_Update;
- TimeDlyCnt += 65000;
- }
- tmp_val = TIMEDly->CNT + TimeDlyCnt;
- }
- while(this_cnt != tmp_val);
- //計算已逝去的時間
- if(*ptCnt <= this_cnt)
- {
- tmp_val = this_cnt – *ptCnt;
- if(tmp_val > (65536UL*65536UL-1))
- return (uint32_t)(65536UL*65536UL-1);
- else return (uint32_t)tmp_val;
- }
- else
- {
- *ptCnt = this_cnt;
- return 0;
- }
- }
- /******************************************************************************
- / 函式功能:中斷支援函式(限STM32F40X的TIM2,TIM3,TIM4,TIM5)
- / 修改日期:2014/5/1 21:02:58
- / 輸入引數:none
- / 輸出引數:none
- / 使用說明:none
- ******************************************************************************/
- void TIMEDly_IRQHandler(void)
- {
- //簡單寫法
- if( TIMEDly->SR & TIM_IT_Update )
- {
- TIMEDly->SR = (uint16_t)~TIM_IT_Update;
- TimeDlyCnt += 65000;
- //Ledx_div(3); //時基訊號
- }
- }
- /******************************************************************************
- / 函式功能:printf支援函式
- / 修改日期:none
- / 輸入引數:none
- / 輸出引數:none
- / 使用說明:none
- ******************************************************************************/
- PUTCHAR_PROTOTYPE
- {
- Ledx_on(11);
- /* Loop until the end of transmission */
- while( (CONSOLE->SR & USART_FLAG_TXE) == RESET );
- /* Place your implementation of fputc here */
- /* e.g. write a character to the USART */
- CONSOLE->DR = ch;
- /* Loop until the end of transmission */
- //while( (CONSOLE->SR & USART_FLAG_TC) == RESET );
- Ledx_off(11);
- return ch;
- }
- /******************************************************************************
- / 函式功能:字串傳送函式
- / 修改日期:none
- / 輸入引數:none
- / 輸出引數:none
- / 使用說明:none
- ******************************************************************************/
- void shell_SendStr(void * ptAsc)
- { //中斷方式
- //————————— 中斷方式收發資料 —————————-
- uint16_t i,size;
- uint8_t *ptDst;
- uint8_t const *ptSrc; //源資料只讀不寫
- //計算字串的長度
- ptSrc = (uint8_t const *)ptAsc;
- size = 0;
- while(*ptSrc++){size++;}
- //判斷字串是否超過緩衝
- Ledx_on(11);
- if(size > SHELL_TX_MAX)
- {
- //關閉中斷髮送方式
- shell_tx_index = 0;
- shell_tx_size = 0;
- CONSOLE->CR1 &= ~USART_CR1_TXEIE; //關閉傳送完畢中斷
- ptSrc = (uint8_t const *)ptAsc;
- while(size–)
- {
- while( (CONSOLE->SR & USART_FLAG_TXE) == RESET );
- CONSOLE->DR = *ptSrc++;
- }
- Ledx_off(11);
- }
- else if( !(CONSOLE->CR1 & USART_CR1_TXEIE) )
- {
- //如果未啟用非空中斷則,啟用非空中斷髮送資料
- //複製資料
- ptDst = (uint8_t *)shell_tx_buff;
- ptSrc = (uint8_t const *)ptAsc;
- for(i=0; i<size; i++)
- *ptDst++ = *ptSrc++;
- //啟動傳送中斷
- shell_tx_index = 0;
- shell_tx_size = size;
- CONSOLE->CR1 |= USART_CR1_TXEIE; //啟動傳送非空中斷
- }
- }
- /******************************************************************************
- / 函式功能:傳送Hex資料函式
- / 修改日期:none
- / 輸入引數:none
- / 輸出引數:none
- / 使用說明:none
- ******************************************************************************/
- void shell_SendHex(void * ptHex,uint16_t size)
- { //中斷方式
- //————————— 中斷方式收發資料 —————————-
- uint16_t i;
- uint8_t *ptDst;
- uint8_t const *ptSrc; //源資料只讀不寫
- Ledx_on(11);
- if(size > SHELL_TX_MAX)
- {
- //關閉中斷髮送方式
- shell_tx_index = 0;
- shell_tx_size = 0;
- CONSOLE->CR1 &= ~USART_CR1_TXEIE; //關閉傳送完畢中斷
- //直接傳送資料
- ptSrc = (uint8_t const *)ptHex;
- while(size–)
- {
- while( (CONSOLE->SR & USART_FLAG_TXE) == RESET );
- CONSOLE->DR = *ptSrc++;
- }
- Ledx_off(11);
- }
- else if( !(CONSOLE->CR1 & USART_CR1_TXEIE) )
- {
- //如果未啟用非空中斷則,啟用非空中斷髮送資料
- //複製資料
- ptDst = (uint8_t *)shell_tx_buff;
- ptSrc = (uint8_t const *)ptHex;
- for(i=0; i<size; i++)
- *ptDst++ = *ptSrc++;
- //啟動傳送中斷
- shell_tx_index = 0;
- shell_tx_size = size;
- CONSOLE->CR1 |= USART_CR1_TXEIE; //啟動傳送非空中斷
- }
- }
- /******************************************************************************
- / 函式功能:中斷服務程式
- / 修改日期:none
- / 輸入引數:none
- / 輸出引數:none
- / 使用說明:none
- ******************************************************************************/
- void CONSOLE_IRQHandler(void)
- {
- uint8_t rxd_reg,txd_reg;
- uint16_t isr_reg;
- //中斷配置
- //————————— 中斷方式收發資料 —————————-
- isr_reg = CONSOLE->SR;
- //接收中斷
- if( (CONSOLE->CR1 & USART_CR1_RXNEIE) && (isr_reg & USART_SR_RXNE) )
- {
- rxd_reg = CONSOLE->DR;
- Ledx_on(12);
- if(shell_rx_rdy)shell_rx_index = 0; //忙模式收到位元組,重置接收指標
- else
- {
- if( shell_rx_index < SHELL_RX_MAX)
- {
- shell_rx_buff[shell_rx_index] = rxd_reg;
- shell_rx_index++;
- }
- else
- {
- shell_rx_index = 0;
- Ledx_off(12);
- }
- }
- }
- if( (CONSOLE->CR1 & USART_CR1_IDLEIE) && (isr_reg & USART_SR_IDLE) )
- {
- CONSOLE->SR;
- CONSOLE->DR;
- if(shell_rx_rdy)shell_rx_index = 0; //忙模式收到空閒,重置接收指標
- else
- {
- if( (shell_rx_index >=2) && (‘\r’ == shell_rx_buff[shell_rx_index-2]) &&
- (‘\n’ == shell_rx_buff[shell_rx_index-1]) ) //以"\r\n"結尾
- {
- shell_rx_rdy = shell_rx_index;
- shell_rx_index = 0;
- Ledx_off(12);
- }
- else if( (shell_rx_index > 0) && (‘\b’ == shell_rx_buff[shell_rx_index-1]) ) //以\b結尾
- {
- shell_rx_index = shell_rx_index <2? 0:shell_rx_index-2;
- printf(" \b"); //傳送輔助刪除
- }
- }
- }
- //傳送非空中斷
- if( (CONSOLE->CR1 & USART_CR1_TXEIE) && (isr_reg & USART_SR_TXE ) )
- {
- if(shell_tx_size && (shell_tx_index < shell_tx_size) )
- {
- txd_reg = shell_tx_buff[shell_tx_index++];
- CONSOLE->DR = txd_reg; //傳送資料
- }
- else
- {
- //關閉非空中斷
- shell_tx_index = 0;
- shell_tx_size = 0;
- CONSOLE->CR1 &= ~USART_CR1_TXEIE; //關閉傳送完畢中斷
- Ledx_off(11);
- }
- }
- }
- /******************************************************************************
- / 函式功能:指令(ASCII或HEX指令)未處理訊息回執
- / 修改日期:2013/9/12 20:25:45
- / 輸入引數:none
- / 輸出引數:none
- / 使用說明:一位元組一位元組接收資料,拼裝為指令
- ******************************************************************************/
- void Shell_Invalid_Service(void)
- {
- int tx_len,i,led_id,msg_id;
- uint8_t * ptSrc;
- uint8_t * ptDst;
- uint8_t tmp_buff[64];
- //指令識別
- if(2 > shell_rx_rdy)
- {
- shell_rx_buff[0] = 0;
- return;
- }
- else if( (‘\r’ == shell_rx_buff[shell_rx_rdy-2]) && (‘\n’ == shell_rx_buff[shell_rx_rdy-1]) )
- {
- ptSrc = (uint8_t *)shell_rx_buff;
- if(2 == shell_rx_rdy)
- {
- //填寫資料
- tx_len = (uint16_t)sprintf((void *)tmp_buff,"\r\nAT:OK!\r\n");
- //傳送資料
- shell_SendHex(tmp_buff,tx_len); //傳送資料
- }
- else if(StrComp(ptSrc,"led rd\r\n")) //顯示LED的訊號配置
- {
- //填寫資料
- tx_len = (uint16_t)sprintf((void *)tmp_buff,
- #if (6 == SHELL_LED_MAX)
- "->LED0=%d LED1=%d tLED2=%d LED3=%d LED4=%d LED5=%d\r\n",
- msg_led_cfg[0],msg_led_cfg[1],msg_led_cfg[2],
- msg_led_cfg[3],msg_led_cfg[4],msg_led_cfg[5]);
- #elif (5 == SHELL_LED_MAX)
- "->LED0=%d LED1=%d tLED2=%d LED3=%d LED4=%d\r\n",
- msg_led_cfg[0],msg_led_cfg[1],msg_led_cfg[2],
- msg_led_cfg[3],msg_led_cfg[4]);
- #elif (4 == SHELL_LED_MAX)
- "->LED0=%d LED1=%d tLED2=%d LED3=%d\r\n",
- msg_led_cfg[0],msg_led_cfg[1],msg_led_cfg[2],
- msg_led_cfg[3]);
- #elif (3 == SHELL_LED_MAX)
- "->LED0=%d LED1=%d tLED2=%d\r\n",
- msg_led_cfg[0],msg_led_cfg[1],msg_led_cfg[2]);
- #elif (2 == SHELL_LED_MAX)
- "->LED0=%d LED1=%d\r\n",
- msg_led_cfg[0],msg_led_cfg[1]);
- #elif (1 == SHELL_LED_MAX)
- "->LED0=%d\r\n",
- msg_led_cfg[0]);
- #endif
- //傳送資料
- shell_SendHex(tmp_buff,tx_len); //傳送資料
- }
- else if(StrComp(ptSrc,"led wr ")) //設定LED的訊號配置
- {
- if(2 != sscanf((void *)ptSrc,"%*s%*s%d=%d",&led_id,&msg_id) )goto ERROR_LOOP;
- if( (led_id>(SHELL_LED_MAX-1)) || (msg_id >65535) )goto ERROR_LOOP;
- Ledx_config((uint8_t)led_id,(uint16_t)msg_id); //配置訊號
- //填寫資料
- tx_len = (uint16_t)sprintf((void *)tmp_buff,
- "->LED[%d]_Msg=%d\r\n",led_id,msg_led_cfg[led_id]);
- //傳送資料
- shell_SendHex(tmp_buff,tx_len); //傳送資料
- }
- else goto ERROR_LOOP;
- }
- else
- {
- ERROR_LOOP:
- //填寫指令碼
- tx_len = (uint16_t)sprintf((void *)tmp_buff,"\r\nAT: Cmd Error:\t\"");
- //計算地址,填寫資料,填寫尾部
- ptDst = tmp_buff + tx_len;
- ptSrc = (uint8_t *)shell_rx_buff;
- if(shell_rx_rdy > 32)
- {
- for(i=0; i<32; i++)
- {
- if( (*ptSrc > 126) || (*ptSrc < 32) )
- {
- *ptDst++ = ‘?’;
- ptSrc++;
- }
- else
- {
- *ptDst++ = *ptSrc++;
- }
- }
- *(ptDst-2) = ‘-‘;
- *(ptDst-1) = ‘>’;
- tx_len += 32;
- }
- else
- {
- for(i=0; i<shell_rx_rdy; i++)
- {
- *ptDst++ = *ptSrc++;
- tx_len++;
- }
- *(ptDst-2) = ‘<‘;
- *(ptDst-1) = ‘-‘;
- }
- tx_len += (uint16_t)sprintf((void *)ptDst,"\"\r\n");
- //傳送資料
- shell_SendHex(tmp_buff,tx_len); //傳送資料
- }
- //清除資料返回程式
- shell_rx_buff[0] = 0;
- shell_rx_rdy = 0;
- }
- /******************************************************************************
- / 函式功能:字串測試匹配指令
- / 修改日期:2014/3/5 19:30:22
- / 輸入引數:none
- / 輸出引數:none
- / 使用說明:none
- ******************************************************************************/
- bool StrComp(void * buffer,void * StrCmd)
- {
- uint8_t i;
- uint8_t * ptBuf;
- uint8_t * ptCmd;
- ptBuf = (uint8_t *)buffer;
- ptCmd = (uint8_t *)StrCmd;
- for(i=0; i<255; i++)
- {
- if(ptCmd[i])
- {
- if(ptBuf[i] != ptCmd[i])return false;
- }
- else
- {
- if(i)return i;
- else return false;
- }
- }
- return false;
- }
- /******************************************************************************
- / 函式功能:開啟LED訊號
- / 修改日期:none
- / 輸入引數:none
- / 輸出引數:none
- / 使用說明:none
- ******************************************************************************/
- void Ledx_on(uint16_t msg_id)
- {
- #if (SHELL_LED_MAX > 0)
- if(msg_id == msg_led_cfg[0])LED0_ON();
- #endif
- #if (SHELL_LED_MAX > 1)
- if(msg_id == msg_led_cfg[1])LED1_ON();
- #endif
- #if (SHELL_LED_MAX > 2)
- if(msg_id == msg_led_cfg[2])LED2_ON();
- #endif
- #if (SHELL_LED_MAX > 3)
- if(msg_id == msg_led_cfg[3])LED3_ON();
- #endif
- #if (SHELL_LED_MAX > 4)
- if(msg_id == msg_led_cfg[4])LED4_ON();
- #endif
- #if (SHELL_LED_MAX > 5)
- if(msg_id == msg_led_cfg[5])LED5_ON();
- #endif
- }
- /******************************************************************************
- / 函式功能:關閉LED訊號
- / 修改日期:none
- / 輸入引數:none
- / 輸出引數:none
- / 使用說明:none
- ******************************************************************************/
- void Ledx_off(uint16_t msg_id)
- {
- #if (SHELL_LED_MAX > 0)
- if(msg_id == msg_led_cfg[0])LED0_OFF();
- #endif
- #if (SHELL_LED_MAX > 1)
- if(msg_id == msg_led_cfg[1])LED1_OFF();
- #endif
- #if (SHELL_LED_MAX > 2)
- if(msg_id == msg_led_cfg[2])LED2_OFF();
- #endif
- #if (SHELL_LED_MAX > 3)
- if(msg_id == msg_led_cfg[3])LED3_OFF();
- #endif
- #if (SHELL_LED_MAX > 4)
- if(msg_id == msg_led_cfg[4])LED4_OFF();
- #endif
- #if (SHELL_LED_MAX > 5)
- if(msg_id == msg_led_cfg[5])LED5_OFF();
- #endif
- }
- /******************************************************************************
- / 函式功能:取反LED訊號
- / 修改日期:none
- / 輸入引數:none
- / 輸出引數:none
- / 使用說明:none
- ******************************************************************************/
- void Ledx_div(uint16_t msg_id)
- {
- #if (SHELL_LED_MAX > 0)
- if(msg_id == msg_led_cfg[0])LED0_DIV();
- #endif
- #if (SHELL_LED_MAX > 1)
- if(msg_id == msg_led_cfg[1])LED1_DIV();
- #endif
- #if (SHELL_LED_MAX > 2)
- if(msg_id == msg_led_cfg[2])LED2_DIV();
- #endif
- #if (SHELL_LED_MAX > 3)
- if(msg_id == msg_led_cfg[3])LED3_DIV();
- #endif
- #if (SHELL_LED_MAX > 4)
- if(msg_id == msg_led_cfg[4])LED4_DIV();
- #endif
- #if (SHELL_LED_MAX > 5)
- if(msg_id == msg_led_cfg[5])LED5_DIV();
- #endif
- }
- /******************************************************************************
- / 函式功能:配置LED訊號
- / 修改日期:none
- / 輸入引數:none
- / 輸出引數:none
- / 使用說明:none
- ******************************************************************************/
- void Ledx_config(uint8_t led_id,uint16_t msg_id)
- {
- if(0 == led_id) {LED0_OFF();msg_led_cfg[0]=msg_id;}
- #if(SHELL_LED_MAX > 1)
- else if(1 == led_id){LED1_OFF();msg_led_cfg[1]=msg_id;}
- #endif
- #if(SHELL_LED_MAX > 2)
- else if(2 == led_id){LED2_OFF();msg_led_cfg[2]=msg_id;}
- #endif
- #if(SHELL_LED_MAX > 3)
- else if(3 == led_id){LED3_OFF();msg_led_cfg[3]=msg_id;}
- #endif
- #if(SHELL_LED_MAX > 4)
- else if(4 == led_id){LED4_OFF();msg_led_cfg[4]=msg_id;}
- #endif
- #if(SHELL_LED_MAX > 5)
- else if(5 == led_id){LED5_OFF();msg_led_cfg[5]=msg_id;}
- #endif
- }
- /******************************************************************************
- / 函式功能:讀取LED的配置訊號
- / 修改日期:none
- / 輸入引數:none
- / 輸出引數:none
- / 使用說明:none
- ******************************************************************************/
- uint16_t Ledx_read(uint8_t led_id)
- {
- if(0 == led_id) return msg_led_cfg[0];
- #if(SHELL_LED_MAX > 1)
- else if(1 == led_id)return msg_led_cfg[1];
- #endif
- #if(SHELL_LED_MAX > 2)
- else if(2 == led_id)return msg_led_cfg[2];
- #endif
- #if(SHELL_LED_MAX > 3)
- else if(3 == led_id)return msg_led_cfg[3];
- #endif
- #if(SHELL_LED_MAX > 4)
- else if(4 == led_id)return msg_led_cfg[4];
- #endif
- #if(SHELL_LED_MAX > 5)
- else if(5 == led_id)return msg_led_cfg[5];
- #endif
- else return 0;
- }
- /******************************************************************************
- *********************************** END ************************************
- ******************************************************************************/
四. shell使用
1. 將shell.c等檔案加入工程

2. 包含Shell.h,並外部宣告shell服務程式
- /******************************************************************************
- *********************************Shell 函式聲 明 ******************************
- ******************************************************************************/
- extern void Shell_SPI_Service(void);
- extern void Shell_RTC_Service(void);
- extern void Shell_WIZ_Service(void);
- extern void Shell_UPAN_Service(void);
- extern void Shell_IAP_Service(uint8_t const this_ver);
- shell_GPIO_Config(30,10,46,1); //shell介面和四個LED燈的訊號配置
- shell_Init(460800); //初始化shell控制檯
3. 在main,c的大迴圈中新增以下程式碼
- //Shell構架的控制檯服務
- if(shell_rx_rdy)
- {
- Shell_IAP_Service(SOFT_VER); //IAP模組指令處理
- Shell_SPI_Service(); //SPI_FLASH模組指令處理
- Shell_WIZ_Service(); //網絡卡模組的指令處理
- Shell_RTC_Service(); //RTC模組的指令處理
- Shell_MCU_Service(); //MCU雜項功能指令處理
- Shell_VLSI_Service(); //音效卡模組的指令處理
- Shell_UPAN_Service(); //U盤模組的指令處理
- Shell_Invalid_Service(); //指令無效的預設處理
- }
4. 編譯下載檔案到STM32,完成後位元組在超級終端上敲擊Enter就會顯示AT:OK!的字樣表示可以正常通訊
五. RTC Shell服務檔案示例
這裡展示一個Shell服務的檔案模板寫法:
- /*********************************Copyright (c)*********************************
- **
- ** FIVE工作組
- **
- **———————————File Info————————————
- ** File Name: rtc_shell.c
- ** Last modified Date: 2014/3/5 9:27:49
- ** Last Version: V2.0
- ** Description: 檔案操作命令解釋,需要Console Shell V2以上支援
- **
- **——————————————————————————
- ** Created By: wanxuncpx
- ** Created date: 2014/3/5 9:28:31
- ** Version: V2.0
- ** Descriptions: none
- **——————————————————————————
- ** HW_CMU: ANSIC
- ** Libraries: NONE
- ** version NONE
- *******************************************************************************/
- /******************************************************************************
- 更新說明:
- ******************************************************************************/
- /******************************************************************************
- ********************************* 編 譯 控 制 ********************************
- ******************************************************************************/
- #define RTC_SHELL //註釋掉時遮蔽iap shell功能
- /******************************************************************************
- ********************************* 檔案引用部分 ********************************
- ******************************************************************************/
- /*———————*
- * 檔案包含
- *———————-*/
- //基礎支援檔案
- #include "shell.h" //Shell支援檔案,含bool,uint8_t..以及串列埠資料收發操作
- #include "rtc.h" //命令控制支援檔案
- /*———————*
- * Shell版本判斷
- *———————-*/
- #ifdef SHELL_VER
- #if (SHELL_VER < 2)
- #error "shell版本太低"
- #endif
- #else
- #error "未找到Shell檔案,或shell版本資訊"
- #endif
- /******************************************************************************
- ********************************* 輸出函式功能 ********************************
- ******************************************************************************/
- /*———————*
- * 輸出函式功能
- *———————-*/
- #ifdef RTC_SHELL
- extern void Shell_RTC_Service(void);
- #else
- void Shell_RTC_Service(void){;}
- #endif
- /*———————*
- * 輸入函式
- *———————-*/
- //none
- /******************************************************************************
- ********************************* 數 據 聲 明 *********************************
- ******************************************************************************/
- #ifdef RTC_SHELL
- /*———————*
- *
- *———————-*/
- //命令幫助檔案
- const char RTC_HelpMsg[] =
- "[RTC contorls]\r\n"
- " rtc help\t\t- help.\r\n"
- " rtc rd info\t\t- Read RTC info.\r\n"
- " rtc rd time\t\t- Read RTC date and time.\r\n"
- " rtc wr time <Hour>:<Minute>:<Second> – Write time.\r\n"
- " rtc wr date <Year>-<Month>-<Day> <Week> – Warning Week=[1..7]\r\n"
- "\r\n";
- /******************************************************************************
- ********************************* 函 數 聲 明 *********************************
- ******************************************************************************/
- /******************************************************************************
- / 函式功能:檔案系統Shel指令處理
- / 修改日期:2013/9/10 19:04:15
- / 輸入引數:輸入當前的程式版本
- / 輸出引數:none
- / 使用說明:none
- ******************************************************************************/
- void Shell_RTC_Service(void)
- {
- uint8_t *ptRxd; //用於接收指令處理
- //uint8_t *ptTxd; //方便用於指令傳送
- int i,j,k,l;
- //int tx_len,drv;
- //uint32_t u32_arg[4];
- uint16_t retval;
- uint8_t arg[32];
- uint32_t tmp_time;
- //指令初級過濾
- //————————————————————————–
- //格式:<->[cmd bytes]<CRLF> 即"-[cmd bytes]\r\n"
- //指令必須以"-"開始, 以"\r\n"結束
- i = shell_rx_rdy;
- if( (i < 2) || (‘\r’ != shell_rx_buff[i-2]) || (‘\n’ != shell_rx_buff[i-1]))return;
- //長度和字首過濾
- ptRxd = (uint8_t *)shell_rx_buff;
- if( (‘ ‘ != shell_rx_buff[3]) || (‘r’ != shell_rx_buff[0]) || (i < 6) ||
- (‘t’ != shell_rx_buff[1]) || (‘c’ != shell_rx_buff[2]) ) return;
- //處理指令
- //————————————————————————–
- ptRxd += 4;
- if(StrComp(ptRxd,"rd time")) //按包讀取指令
- {
- RTC_Sprintf_CurrTime((void *)arg);
- printf("Time:%s\r\n",arg);
- }
- else if(StrComp(ptRxd,"rd info\r\n")) //讀取RTC資訊
- {
- //列印當前時間和上次復位時間
- RTC_Sprintf_CurrTime((void *)arg);
- printf("->Time:%s\tResetCounter:%d\r\n",arg,RESET_CNT);
- RTC_Sprintf_ResetCurr((void *)arg,&tmp_time);
- printf("\tCurrReset:%s\tRun: %d Days, %d hour, %d minute\r\n",
- arg,tmp_time/(24*60),(tmp_time%(24*60))/60,tmp_time%60 );
- RTC_Sprintf_ResetLast((void *)arg,&tmp_time);
- printf("\tNextReset:%s\tRun: %d Days, %d hour, %d minute\r\n",
- arg,tmp_time/(24*60),(tmp_time%(24*60))/60,tmp_time%60 );
- }
- else if(StrComp(ptRxd,"wr time ")) //寫時間
- {
- retval = sscanf((void*)shell_rx_buff,"%*s%*s%*s%d:%d:%d",&i,&j,&k);
- if(3 != retval)return; //沒有接收到3個輸入資料,直接退出
- if(RTC_TimeWrite((uint8_t)i,(uint8_t)j,(uint8_t)k) )
- {
- RTC_Sprintf_CurrTime((void *)arg);
- printf("->CurrTime:%s\r\n",arg);
- }
- else
- {
- printf("->Error Time Input!\r\n");
- shell_rx_rdy = 0; //不用觸發錯誤指令顯示
- return;
- }
- }
- else if(StrComp(ptRxd,"wr date ")) //寫日期
- {
- retval = sscanf((void*)shell_rx_buff,"%*s%*s%*s%d-%d-%d %d",&i,&j,&k,&l);
- if(4 != retval)return; //沒有接收到4個輸入資料,直接退出
- if(RTC_DateWrite((uint16_t)i,(uint8_t)j,(uint8_t)k,(uint8_t)l))
- {
- RTC_Sprintf_CurrTime((void *)arg);
- printf("->CurrTime:%s\r\n",arg);
- }
- else
- {
- printf("->Error Date Input!\r\n");
- shell_rx_rdy = 0; //shell_rx_rdy為0,表示指令已被處理完畢,否者下個Shell服務繼續呼叫
- return;
- }
- }
- else if(StrComp(ptRxd,"help\r\n")) //指令幫助
- {
- shell_SendStr((void *)RTC_HelpMsg);
- }
- else return;
- //退出處理
- //————————————————————————–
- shell_rx_rdy = 0; //shell_rx_rdy為0,表示指令已被處理完畢,否者下個Shell服務繼續呼叫
- }
- /******************************************************************************
- *********************************** END ************************************
- ******************************************************************************/
- #endif
写评论
很抱歉,必須登入網站才能發佈留言。