一种STM32的串口控制台的实现(非常实用)
来源:互联网 发布:棋牌类游戏源码 编辑:程序博客网 时间:2024/05/30 21:58
一.背景
曾经玩Linux时非常喜欢这种基于出串口的控制台, 通过简单的串口TX和RX能实现嵌入式硬件的人机交互,非常实用, 那么STM32能否实现通过超级终端与用户互动的构想呢? 答案是肯定的,由于这个UART控制平台就像应用程序套上一层可访问的外科(Shell)故而我将这种基于UART的控制平台简称Shell,构架和效果如下图:
这张图箭头指向的是输入的指令,其余是STM32串口输出的信息,, 可以看到通过这些简单的指令输入我们通过Shell可以做很多事情:
1. 现场设备发生故障,可以通过Shell可以查看设备的故障状态统计信息
2. 能实现串口程序升级(需要Shell+IAP驱动程序支持)
3. 能读写访问参数区,实现对设备参数的本地配置
4. 配置多功能信号指示灯(LED灯可显示65535种信号,同一时刻只能显示一个.
5. 程序开发阶段基于Shell,可以极其方便的调试编写的驱动程序(开发极力推荐),非常好用.
二.Shell基础篇
Shell基础程序只有三个文件:
console.h:用于定义STM32用于Shell的实体串口
shell.cshell平台实现主体
shell.h头文件,任意的驱动文件可调用,就像<stdio.h>一样
shell.c目前包含三个部件:
shell模块(必选)Shell模块初始化时已初始化好Led模块
Led模块(必选)Ledx_on(x),Ledx_off(x),Ledx_div(x),函数是对编码信号进行控制,而不是直接对硬件实体控制,这样每个LED实体就像通道一样可以选择非常多的信号源显示.
精密延时模块(可选)启动需要对其初始化,此模块可用于记录时间点,并判断时间是否到(再也不用Delayms()这样的函数浪费效率实现时序了.
三. 程序文件:
1. console.h
/*********************************Copyright (c)*********************************** ** FIVE工作组****---------------------------------File Info------------------------------------** File Name: shell_hal.h** Last modified Date: 2014/5/26 14:22:35** Last Version: V1.0 ** Description: 本地Shell文件接口****------------------------------------------------------------------------------** Created By: wanxuncpx** Created date: 2014/5/26 14:22:34** Version: V2** Descriptions: 只适合STM32程序**------------------------------------------------------------------------------** Libraries: STM32F10x_StdPeriph_Driver** version V3.5*******************************************************************************//******************************************************************************更新说明:******************************************************************************//*************************************************************************************************************** 应 用 资 料 **************************************************************************************************************/#ifndef _SHELL_HAL_#define _SHELL_HAL_/*************************************************************************************************************** 文件引用部分 **************************************************************************************************************///包含库文件#include "stm32f10x.h"#include "stm32f10x_gpio.h"#include "stm32f10x_rcc.h"#include "stm32f10x_tim.h"/************************************************************************************************************** 可 配 置 参 数 *************************************************************** MNCS_IMAGE图像板 ***********************************************************************************************************//*---------------------* * UART端口配置*----------------------*///IO配置#define CONSOLE USART3 #define CONSOLE_TX_PORT GPIOB#define CONSOLE_TX_PIN GPIO_Pin_10#define CONSOLE_RX_PORT GPIOB#define CONSOLE_RX_PIN GPIO_Pin_11//时钟配置#define CONSOLE_GPIO_RCC_INIT() RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE)#define CONSOLE_UART_RCC_INIT() RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE)//中断优先级#define CONSOLE_UART_PRIO 7 //建议[0..15]//中断向量配置#define CONSOLE_IRQn USART3_IRQn;#define CONSOLE_IRQHandler USART3_IRQHandler/*---------------------* * 四个LED定义*----------------------*/#define LED0_VALID 1 //非零表示使能对应的LED,0:无效#define LED0_PORT GPIOB#define LED0_PIN GPIO_Pin_13#define LED1_VALID 1 //非零表示使能对应的LED,0:无效#define LED1_PORT GPIOB#define LED1_PIN GPIO_Pin_15#define LED2_VALID 0 //非零表示使能对应的LED,0:无效#define LED2_PORT GPIOA#define LED2_PIN GPIO_Pin_11#define LED3_VALID 0 //非零表示使能对应的LED,0:无效#define LED3_PORT GPIOA#define LED3_PIN GPIO_Pin_11#define LED4_VALID 0 //非零表示使能对应的LED,0:无效#define LED4_PORT GPIOA#define LED4_PIN GPIO_Pin_11#define LED5_VALID 0 //非零表示使能对应的LED,0:无效#define LED5_PORT GPIOA#define LED5_PIN GPIO_Pin_11/*---------------------* * 时基BASE*----------------------*/#define TIMEDly TIM4#define TIMEDly_IRQn TIM4_IRQn#define TIMEDly_IRQHandler TIM4_IRQHandler//时钟配置 #define TIMEDly_RCC_INIT() RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);//初始化LGPIO口#define LEDx_GPIO_RCC_INIT() RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE)//------------------------------------------------------------------------------/************************************************************************************************************* 以下参数无需更改 ************************************************************************************************************//*---------------------* * 注意以下区域无需用户更改*----------------------*/#if LED0_VALID #define LED0_ON() (LED0_PORT->BRR = LED0_PIN) #define LED0_OFF() (LED0_PORT->BSRR = LED0_PIN) #define LED0_DIV() (LED0_PORT->ODR ^= LED0_PIN)#else #define LED0_ON() __NOP() #define LED0_OFF() __NOP() #define LED0_DIV() __NOP()#endif#if LED1_VALID #define LED1_ON() (LED1_PORT->BRR = LED1_PIN) #define LED1_OFF() (LED1_PORT->BSRR = LED1_PIN) #define LED1_DIV() (LED1_PORT->ODR ^= LED1_PIN)#else #define LED1_ON() __NOP() #define LED1_OFF() __NOP() #define LED1_DIV() __NOP()#endif #if LED2_VALID #define LED2_ON() (LED2_PORT->BRR = LED2_PIN) #define LED2_OFF() (LED2_PORT->BSRR = LED2_PIN) #define LED2_DIV() (LED2_PORT->ODR ^= LED2_PIN)#else #define LED2_ON() __NOP() #define LED2_OFF() __NOP() #define LED2_DIV() __NOP()#endif #if LED3_VALID #define LED3_ON() (LED3_PORT->BRR = LED3_PIN) #define LED3_OFF() (LED3_PORT->BSRR = LED3_PIN) #define LED3_DIV() (LED3_PORT->ODR ^= LED3_PIN)#else #define LED3_ON() __NOP() #define LED3_OFF() __NOP() #define LED3_DIV() __NOP()#endif#if LED4_VALID #define LED4_ON() (LED4_PORT->BSRR = LED4_PIN) #define LED4_OFF() (LED4_PORT->BRR = LED4_PIN) #define LED4_DIV() (LED4_PORT->ODR ^= LED4_PIN)#else #define LED4_ON() __NOP() #define LED4_OFF() __NOP() #define LED4_DIV() __NOP()#endif#if LED5_VALID #define LED5_ON() (LED5_PORT->BSRR = LED5_PIN) #define LED5_OFF() (LED5_PORT->BRR = LED5_PIN) #define LED5_DIV() (LED5_PORT->ODR ^= LED5_PIN)#else #define LED5_ON() __NOP() #define LED5_OFF() __NOP() #define LED5_DIV() __NOP()#endif/************************************************************************************************************* printf支持文件 **************************************************************************************************************//* Private function prototypes -----------------------------------------------*/#ifdef __GNUC__/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf set to 'Yes') calls __io_putchar() */#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)#else#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)#endif /* __GNUC__ *//***************************************************************************************************************** END ******************************************************************************************************************/#endif
2. shell.h
/*********************************Copyright (c)*********************************** ** FIVE工作组****---------------------------------File Info------------------------------------** File Name: shell.h** Last modified Date: 2014/3/5 15:42:05** Last Version: V2 ** Description: none****------------------------------------------------------------------------------** Created By: wanxuncpx** Created date: 2014/3/5 15:42:11** Version: V2** Descriptions: none**------------------------------------------------------------------------------** Libraries: 无关** version 无关*******************************************************************************//******************************************************************************更新说明:******************************************************************************//*************************************************************************************************************** 应 用 资 料 **************************************************************************************************************/#ifndef _SHELL_H_#define _SHELL_H_/*************************************************************************************************************** 文件引用部分 **************************************************************************************************************/#include "stdint.h" //包含uint8_t等数据类型#include "stdbool.h" //包含Bool类型#include "stdio.h" //包含printf支持/*************************************************************************************************************** 参数宏定义 ***************************************************************************************************************///版本定义#define SHELL_VER 2 //Shell版本#ifndef SHELL_LED_MAX //LED实体数量 #define SHELL_LED_MAX 4#endif//缓冲大小配置#define SHELL_RX_MAX (256+32) //shell指令接收缓冲大小#define SHELL_TX_MAX (512) //shell指令发送缓冲大小/*************************************************************************************************************** 数 据 声 明 ***************************************************************************************************************//*---------------------* * Shell接收*----------------------*///接收数据extern volatile uint16_t shell_rx_rdy; //0:空闲,非零:忙,用户读为非零后清零extern volatile uint8_t shell_rx_buff[SHELL_RX_MAX+1]; //接收缓冲/*************************************************************************************************************** 函 数 声 明 ***************************************************************************************************************//*---------------------* * 输出函数*----------------------*///调试Shell的接口数量#if (6 == SHELL_LED_MAX) extern void shell_GPIO_Config(uint16_t led0_cfg,uint16_t led1_cfg, uint16_t led2_cfg,uint16_t led3_cfg, uint16_t led4_cfg,uint16_t led5_cfg);#elif (5 == SHELL_LED_MAX) extern void shell_GPIO_Config(uint16_t led0_cfg,uint16_t led1_cfg, uint16_t led2_cfg,uint16_t led3_cfg, uint16_t led4_cfg);#elif (4 == SHELL_LED_MAX) extern void shell_GPIO_Config(uint16_t led0_cfg,uint16_t led1_cfg, uint16_t led2_cfg,uint16_t led3_cfg);#elif (3 == SHELL_LED_MAX) extern void shell_GPIO_Config(uint16_t led0_cfg,uint16_t led1_cfg, uint16_t led2_cfg);#elif (2 == SHELL_LED_MAX) extern void shell_GPIO_Config(uint16_t led0_cfg,uint16_t led1_cfg);#elif (1 == SHELL_LED_MAX) extern void shell_GPIO_Config(uint16_t led0_cfg);#endif//检测参数合法性#if ((SHELL_LED_MAX > 6) || (SHELL_LED_MAX == 0)) #error SHELL_LED_MAX is invaild!#endif//初始化Shellextern void shell_Init(uint32_t baud); //模块初始化extern void shell_SendStr(void * ptStr); //发送以'\0'结束的字符串extern void shell_SendHex(void * ptHex,uint16_t size); //发送指定个数的数据/*---------------------* * LEDx测试信号定义*----------------------*/extern void Ledx_config(uint8_t led_id,uint16_t msg_id); //设置LED的配置信号extern uint16_t Ledx_read(uint8_t led_id); //读取LED的配置信号(失败返回0)extern void Ledx_on (uint16_t msg_id); //发送LED开消息extern void Ledx_off(uint16_t msg_id); //发送LED关消息extern void Ledx_div(uint16_t msg_id); //发送LED取反消息/*---------------------* * 时基延时函数*----------------------*/extern void Delay_LibInit(void);extern void DlyTime_us(uint16_t us);extern void DlyTime_ms(uint16_t ms);extern void DlyWait_base(volatile uint64_t * ptCnt); //标记为等待的基点时间extern uint32_t DlyWait_lost(volatile uint64_t * ptCnt);//判断逝去的时间(us)/*---------------------* * 辅助判断指令*----------------------*/extern bool StrComp(void * buffer,void * StrCmd); //字符串匹配比较函数/*---------------------* * Shell服务*----------------------*///在main.c函数while()中判断shell_rx_rdy是否为非零,为非零才执行以下程序extern void Shell_Invalid_Service(void); //指令未处理服务(会处理shell_rx_rdy信号)/***************************************************************************************************************** END ******************************************************************************************************************/#endif
3.shell.c
/*********************************Copyright (c)*********************************** ** FIVE工作组****---------------------------------File Info------------------------------------** File Name: shell.c** Last modified Date: 2014/3/5 16:43:59** Last Version: V2 ** Description: none****------------------------------------------------------------------------------** Created By: wanxuncpx** Created date: 2014/3/5 16:43:58** Version: V2** Descriptions: 适合于STM32**------------------------------------------------------------------------------** Libraries: STM32F10x_StdPeriph_Driver** version V3.5*******************************************************************************//******************************************************************************更新说明:******************************************************************************//*************************************************************************************************************** 应 用 资 料 **************************************************************************************************************//*************************************************************************************************************** 文件引用部分 **************************************************************************************************************/#include "shell.h" //包含Shell接口文件//是否使用扩展的Shell接口#ifdef SHELL_HAL_EXT #include "shell_hal.h" //本地的Shell文件#else #include "console.h" //标准的Shell文件#endif/*************************************************************************************************************** Shell.h定义 ***************************************************************************************************************//*---------------------* * Shell 收发标记*----------------------*/volatile uint16_t shell_rx_rdy = 0; //0:空闲,非零:忙volatile uint8_t shell_rx_buff[SHELL_RX_MAX+1]="\0"; //接收缓冲/*************************************************************************************************************** 本 地 数 据 ***************************************************************************************************************//*---------------------* * Shell缓冲定义*----------------------*///接收static volatile uint16_t shell_rx_index = 0; //数据接收标记//发送static volatile uint8_t shell_tx_buff[SHELL_TX_MAX+1]="\0";static volatile uint16_t shell_tx_size = 0; //0:空闲,非零:忙static volatile uint16_t shell_tx_index = 0; //发送数据标记/*---------------------* * LED控制信号*----------------------*/static volatile uint16_t msg_led_cfg[SHELL_LED_MAX]; //配置信号/*---------------------* * 延时模块定义*----------------------*/static volatile uint64_t TimeDlyCnt = 0; //用于辅助的延时计数值/*************************************************************************************************************** 函 数 声 明 ***************************************************************************************************************//******************************************************************************/ 函数功能:初始化GPIO口(串口和四个LED灯配置)/ 修改日期:none/ 输入参数:none/ 输出参数:none/ 使用说明:none******************************************************************************/#if (6 == SHELL_LED_MAX) void shell_GPIO_Config( uint16_t led0_cfg,uint16_t led1_cfg, uint16_t led2_cfg,uint16_t led3_cfg, uint16_t led4_cfg,uint16_t led5_cfg)#elif (5 == SHELL_LED_MAX) void shell_GPIO_Config( uint16_t led0_cfg,uint16_t led1_cfg, uint16_t led2_cfg,uint16_t led3_cfg, uint16_t led4_cfg)#elif (4 == SHELL_LED_MAX) void shell_GPIO_Config( uint16_t led0_cfg,uint16_t led1_cfg, uint16_t led2_cfg,uint16_t led3_cfg)#elif (3 == SHELL_LED_MAX) void shell_GPIO_Config( uint16_t led0_cfg,uint16_t led1_cfg, uint16_t led2_cfg)#elif (2 == SHELL_LED_MAX) void shell_GPIO_Config(uint16_t led0_cfg,uint16_t led1_cfg)#elif (1 == SHELL_LED_MAX) void shell_GPIO_Config(uint16_t led0_cfg)#endif{GPIO_InitTypeDef GPIO_InitStruct; /* 配置串口 ---------------------------------------------------------*/// 打开在APB2上的GPIO口外设时钟CONSOLE_GPIO_RCC_INIT(); //打开GPIO口的时钟// 配置TX引脚GPIO_InitStruct.GPIO_Pin = CONSOLE_TX_PIN;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(CONSOLE_TX_PORT, &GPIO_InitStruct);// 配置RX引脚GPIO_InitStruct.GPIO_Pin = CONSOLE_RX_PIN;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;GPIO_Init(CONSOLE_RX_PORT, &GPIO_InitStruct); //锁定GPIO口,防止其他更改 GPIO_PinLockConfig(CONSOLE_TX_PORT,CONSOLE_TX_PIN); GPIO_PinLockConfig(CONSOLE_RX_PORT,CONSOLE_RX_PIN); /* 配置LEDx ---------------------------------------------------------*/ LEDx_GPIO_RCC_INIT(); GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;//根据定义配置四个LED #if (SHELL_LED_MAX > 0) GPIO_InitStruct.GPIO_Pin = LED0_PIN;GPIO_Init(LED0_PORT, &GPIO_InitStruct);GPIO_PinLockConfig(LED0_PORT,LED0_PIN); msg_led_cfg[0] = led0_cfg;LED0_OFF(); #endif #if (SHELL_LED_MAX > 1) GPIO_InitStruct.GPIO_Pin = LED1_PIN;GPIO_Init(LED1_PORT, &GPIO_InitStruct);GPIO_PinLockConfig(LED1_PORT,LED1_PIN);msg_led_cfg[1] = led1_cfg;LED1_OFF(); #endif #if (SHELL_LED_MAX > 2) GPIO_InitStruct.GPIO_Pin = LED2_PIN;GPIO_Init(LED2_PORT, &GPIO_InitStruct);GPIO_PinLockConfig(LED2_PORT,LED2_PIN);msg_led_cfg[2] = led2_cfg;LED2_OFF(); #endif #if (SHELL_LED_MAX > 3) GPIO_InitStruct.GPIO_Pin = LED3_PIN;GPIO_Init(LED3_PORT, &GPIO_InitStruct);GPIO_PinLockConfig(LED3_PORT,LED3_PIN);msg_led_cfg[3] = led3_cfg;LED3_OFF(); #endif #if (SHELL_LED_MAX > 4) GPIO_InitStruct.GPIO_Pin = LED4_PIN;GPIO_Init(LED4_PORT, &GPIO_InitStruct);GPIO_PinLockConfig(LED4_PORT,LED4_PIN);msg_led_cfg[4] = led4_cfg;LED4_OFF(); #endif #if (SHELL_LED_MAX > 5) GPIO_InitStruct.GPIO_Pin = LED5_PIN;GPIO_Init(LED5_PORT, &GPIO_InitStruct);GPIO_PinLockConfig(LED5_PORT,LED5_PIN);msg_led_cfg[5] = led5_cfg;LED5_OFF(); #endif }/******************************************************************************/ 函数功能:串口初始化,使用中断单字节接收数据/ 修改日期:none/ 输入参数:baud 波特率/ 输出参数:none/ 使用说明:none******************************************************************************/void shell_Init(uint32_t baud){ USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_UART_Cfg; //UART中断向量 //--------------------------- 先定义好数据结构 --------------------------- //定义好USART结构体 USART_InitStructure.USART_BaudRate = baud; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No ; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; USART_InitStructure.USART_BaudRate = USART_InitStructure.USART_BaudRate; //防止编译报错 //定义好NVIC:UART中断 NVIC_UART_Cfg.NVIC_IRQChannel = CONSOLE_IRQn; NVIC_UART_Cfg.NVIC_IRQChannelPreemptionPriority = 1; NVIC_UART_Cfg.NVIC_IRQChannelSubPriority = CONSOLE_UART_PRIO; NVIC_UART_Cfg.NVIC_IRQChannelCmd = ENABLE; NVIC_UART_Cfg.NVIC_IRQChannel = NVIC_UART_Cfg.NVIC_IRQChannel; //防止编译报错 //模式配置 //--------------------------- 中断方式收发数据 ---------------------------- CONSOLE_UART_RCC_INIT(); //打开USART的时钟 USART_Cmd(CONSOLE, DISABLE); //关闭UART USART_Init(CONSOLE, &USART_InitStructure); //初始化串口 USART_ITConfig(CONSOLE, USART_IT_RXNE, ENABLE); USART_ITConfig(CONSOLE, USART_IT_IDLE, ENABLE); USART_Cmd(CONSOLE, ENABLE); NVIC_Init(&NVIC_UART_Cfg); //配置好NVIC}/******************************************************************************/ 函数功能:Delay延时库初始化(需要1us的计数精度,和50ms的溢出计数)/ 修改日期:2014/5/1 21:02:58/ 输入参数:none/ 输出参数:none/ 使用说明:(限STM32F40X的TIM2,TIM3,TIM4,TIM5)******************************************************************************/void Delay_LibInit(void){ TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; NVIC_InitTypeDef NVIC_InitStructure; //开启TIM2时钟 TIMEDly_RCC_INIT(); /* Enable the TIMx gloabal Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = TIMEDly_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //由于是时基,需要使用最高优先级 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); /* Time base configuration */ TIM_TimeBaseStructure.TIM_Period = 65000; TIM_TimeBaseStructure.TIM_Prescaler = (SystemCoreClock/1000000)-1; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIMEDly, &TIM_TimeBaseStructure); /* TIM Interrupts enable */ TIM_ITConfig(TIMEDly,TIM_IT_Update, ENABLE); /* TIMx enable counter */ TIM_Cmd(TIMEDly, ENABLE);}/******************************************************************************/ 函数功能:等待一个us延时/ 修改日期:2014/5/1 21:02:58/ 输入参数:none/ 输出参数:none/ 使用说明:none******************************************************************************/void DlyTime_us(uint16_t us){ uint64_t this_cnt,over_cnt,tmp_val; //得到当前的准确时间 do { this_cnt = TIMEDly->CNT + TimeDlyCnt; if( (TIMEDly->SR & TIM_IT_Update) && (TIMEDly->SR & TIM_IT_Update) && (TIMEDly->SR & TIM_IT_Update) ) { TIMEDly->SR = (uint16_t)~TIM_IT_Update; TimeDlyCnt += 65000; } tmp_val = TIMEDly->CNT + TimeDlyCnt; } while(this_cnt != tmp_val); over_cnt = this_cnt + us; //得到目标延时时间 //延时函数 do { if( (TIMEDly->SR & TIM_IT_Update) && (TIMEDly->SR & TIM_IT_Update) && (TIMEDly->SR & TIM_IT_Update) ) { TIMEDly->SR = (uint16_t)~TIM_IT_Update; TimeDlyCnt += 65000; } this_cnt = TIMEDly->CNT + TimeDlyCnt; } while(this_cnt < over_cnt);}/******************************************************************************/ 函数功能:等待一个ms延时/ 修改日期:2014/5/1 21:02:58/ 输入参数:none/ 输出参数:none/ 使用说明:none******************************************************************************/void DlyTime_ms(uint16_t ms){ uint64_t this_cnt,over_cnt,tmp_val; //得到当前的准确时间 do { this_cnt = TIMEDly->CNT + TimeDlyCnt; if( (TIMEDly->SR & TIM_IT_Update) && (TIMEDly->SR & TIM_IT_Update) && (TIMEDly->SR & TIM_IT_Update) ) { TIMEDly->SR = (uint16_t)~TIM_IT_Update; TimeDlyCnt += 65000; } tmp_val = TIMEDly->CNT + TimeDlyCnt; } while(this_cnt != tmp_val); over_cnt = this_cnt + (uint32_t)ms*1000; //延时函数 do { if( (TIMEDly->SR & TIM_IT_Update) && (TIMEDly->SR & TIM_IT_Update) && (TIMEDly->SR & TIM_IT_Update) ) { TIMEDly->SR = (uint16_t)~TIM_IT_Update; TimeDlyCnt += 65000; } this_cnt = TIMEDly->CNT + TimeDlyCnt; } while(this_cnt < over_cnt);}/******************************************************************************/ 函数功能:标记时间起点/ 修改日期:2014/5/1 21:02:58/ 输入参数:none/ 输出参数:none/ 使用说明:none******************************************************************************/void DlyWait_base(volatile uint64_t * ptCnt){ uint64_t this_cnt,tmp_val; //得到当前的准确时间 do { this_cnt = TIMEDly->CNT + TimeDlyCnt; if( (TIMEDly->SR & TIM_IT_Update) && (TIMEDly->SR & TIM_IT_Update) && (TIMEDly->SR & TIM_IT_Update) ) { TIMEDly->SR = (uint16_t)~TIM_IT_Update; TimeDlyCnt += 65000; } tmp_val = TIMEDly->CNT + TimeDlyCnt; } while(this_cnt != tmp_val); *ptCnt = this_cnt;}/******************************************************************************/ 函数功能:检测从起点开始已逝去的时间(最大1个小时)/ 修改日期:2014/5/1 21:02:58/ 输入参数:none/ 输出参数:返回0表示时间到,返回非零表示时间未到/ 使用说明:none******************************************************************************/uint32_t DlyWait_lost(volatile uint64_t * ptCnt){ uint64_t this_cnt,tmp_val; //得到当前的准确时间 do { this_cnt = TIMEDly->CNT + TimeDlyCnt; if( (TIMEDly->SR & TIM_IT_Update) && (TIMEDly->SR & TIM_IT_Update) && (TIMEDly->SR & TIM_IT_Update) ) { TIMEDly->SR = (uint16_t)~TIM_IT_Update; TimeDlyCnt += 65000; } tmp_val = TIMEDly->CNT + TimeDlyCnt; } while(this_cnt != tmp_val); //计算已逝去的时间 if(*ptCnt <= this_cnt) { tmp_val = this_cnt - *ptCnt; if(tmp_val > (65536UL*65536UL-1)) return (uint32_t)(65536UL*65536UL-1); else return (uint32_t)tmp_val; } else { *ptCnt = this_cnt; return 0; }}/******************************************************************************/ 函数功能:中断支持函数(限STM32F40X的TIM2,TIM3,TIM4,TIM5)/ 修改日期:2014/5/1 21:02:58/ 输入参数:none/ 输出参数:none/ 使用说明:none******************************************************************************/ void TIMEDly_IRQHandler(void){ //简单写法 if( TIMEDly->SR & TIM_IT_Update ) { TIMEDly->SR = (uint16_t)~TIM_IT_Update; TimeDlyCnt += 65000; //Ledx_div(3); //时基信号 }}/******************************************************************************/ 函数功能:printf支持函数/ 修改日期:none/ 输入参数:none/ 输出参数:none/ 使用说明:none******************************************************************************/PUTCHAR_PROTOTYPE{ Ledx_on(11); /* Loop until the end of transmission */ while( (CONSOLE->SR & USART_FLAG_TXE) == RESET ); /* Place your implementation of fputc here */ /* e.g. write a character to the USART */ CONSOLE->DR = ch; /* Loop until the end of transmission */ //while( (CONSOLE->SR & USART_FLAG_TC) == RESET ); Ledx_off(11); return ch;}/******************************************************************************/ 函数功能:字符串发送函数/ 修改日期:none/ 输入参数:none/ 输出参数:none/ 使用说明:none******************************************************************************/void shell_SendStr(void * ptAsc){ //中断方式 //--------------------------- 中断方式收发数据 ---------------------------- uint16_t i,size; uint8_t *ptDst; uint8_t const *ptSrc; //源数据只读不写 //计算字符串的长度 ptSrc = (uint8_t const *)ptAsc; size = 0; while(*ptSrc++){size++;} //判断字符串是否超过缓冲 Ledx_on(11); if(size > SHELL_TX_MAX) { //关闭中断发送方式 shell_tx_index = 0; shell_tx_size = 0; CONSOLE->CR1 &= ~USART_CR1_TXEIE; //关闭发送完毕中断 ptSrc = (uint8_t const *)ptAsc; while(size--) { while( (CONSOLE->SR & USART_FLAG_TXE) == RESET ); CONSOLE->DR = *ptSrc++; } Ledx_off(11); } else if( !(CONSOLE->CR1 & USART_CR1_TXEIE) ) { //如果未启用非空中断则,启用非空中断发送数据 //复制数据 ptDst = (uint8_t *)shell_tx_buff; ptSrc = (uint8_t const *)ptAsc; for(i=0; i<size; i++) *ptDst++ = *ptSrc++; //启动发送中断 shell_tx_index = 0; shell_tx_size = size; CONSOLE->CR1 |= USART_CR1_TXEIE; //启动发送非空中断 }}/******************************************************************************/ 函数功能:发送Hex数据函数/ 修改日期:none/ 输入参数:none/ 输出参数:none/ 使用说明:none******************************************************************************/void shell_SendHex(void * ptHex,uint16_t size){ //中断方式 //--------------------------- 中断方式收发数据 ---------------------------- uint16_t i; uint8_t *ptDst; uint8_t const *ptSrc; //源数据只读不写 Ledx_on(11); if(size > SHELL_TX_MAX) { //关闭中断发送方式 shell_tx_index = 0; shell_tx_size = 0; CONSOLE->CR1 &= ~USART_CR1_TXEIE; //关闭发送完毕中断 //直接发送数据 ptSrc = (uint8_t const *)ptHex; while(size--) { while( (CONSOLE->SR & USART_FLAG_TXE) == RESET ); CONSOLE->DR = *ptSrc++; } Ledx_off(11); } else if( !(CONSOLE->CR1 & USART_CR1_TXEIE) ) { //如果未启用非空中断则,启用非空中断发送数据 //复制数据 ptDst = (uint8_t *)shell_tx_buff; ptSrc = (uint8_t const *)ptHex; for(i=0; i<size; i++) *ptDst++ = *ptSrc++; //启动发送中断 shell_tx_index = 0; shell_tx_size = size; CONSOLE->CR1 |= USART_CR1_TXEIE; //启动发送非空中断 }}/******************************************************************************/ 函数功能:中断服务程序/ 修改日期:none/ 输入参数:none/ 输出参数:none/ 使用说明:none******************************************************************************/void CONSOLE_IRQHandler(void){ uint8_t rxd_reg,txd_reg; uint16_t isr_reg; //中断配置 //--------------------------- 中断方式收发数据 ---------------------------- isr_reg = CONSOLE->SR; //接收中断 if( (CONSOLE->CR1 & USART_CR1_RXNEIE) && (isr_reg & USART_SR_RXNE) ) { rxd_reg = CONSOLE->DR; Ledx_on(12); if(shell_rx_rdy)shell_rx_index = 0; //忙模式收到字节,重置接收指针 else { if( shell_rx_index < SHELL_RX_MAX) { shell_rx_buff[shell_rx_index] = rxd_reg; shell_rx_index++; } else { shell_rx_index = 0; Ledx_off(12); } } } if( (CONSOLE->CR1 & USART_CR1_IDLEIE) && (isr_reg & USART_SR_IDLE) ) { CONSOLE->SR; CONSOLE->DR; if(shell_rx_rdy)shell_rx_index = 0; //忙模式收到空闲,重置接收指针 else { if( (shell_rx_index >=2) && ('\r' == shell_rx_buff[shell_rx_index-2]) && ('\n' == shell_rx_buff[shell_rx_index-1]) ) //以"\r\n"结尾 { shell_rx_rdy = shell_rx_index; shell_rx_index = 0; Ledx_off(12); } else if( (shell_rx_index > 0) && ('\b' == shell_rx_buff[shell_rx_index-1]) ) //以\b结尾 { shell_rx_index = shell_rx_index <2? 0:shell_rx_index-2; printf(" \b"); //发送辅助删除 } } } //发送非空中断 if( (CONSOLE->CR1 & USART_CR1_TXEIE) && (isr_reg & USART_SR_TXE ) ) { if(shell_tx_size && (shell_tx_index < shell_tx_size) ) { txd_reg = shell_tx_buff[shell_tx_index++]; CONSOLE->DR = txd_reg; //发送数据 } else { //关闭非空中断 shell_tx_index = 0; shell_tx_size = 0; CONSOLE->CR1 &= ~USART_CR1_TXEIE; //关闭发送完毕中断 Ledx_off(11); } }}/******************************************************************************/ 函数功能:指令(ASCII或HEX指令)未处理消息回执/ 修改日期:2013/9/12 20:25:45/ 输入参数:none/ 输出参数:none/ 使用说明:一字节一字节接收数据,拼装为指令******************************************************************************/void Shell_Invalid_Service(void){ int tx_len,i,led_id,msg_id; uint8_t * ptSrc; uint8_t * ptDst; uint8_t tmp_buff[64]; //指令识别 if(2 > shell_rx_rdy) { shell_rx_buff[0] = 0; return; } else if( ('\r' == shell_rx_buff[shell_rx_rdy-2]) && ('\n' == shell_rx_buff[shell_rx_rdy-1]) ) { ptSrc = (uint8_t *)shell_rx_buff; if(2 == shell_rx_rdy) { //填写数据 tx_len = (uint16_t)sprintf((void *)tmp_buff,"\r\nAT:OK!\r\n"); //发送数据 shell_SendHex(tmp_buff,tx_len); //发送数据 } else if(StrComp(ptSrc,"led rd\r\n")) //显示LED的信号配置 { //填写数据 tx_len = (uint16_t)sprintf((void *)tmp_buff, #if (6 == SHELL_LED_MAX) "->LED0=%d LED1=%d tLED2=%d LED3=%d LED4=%d LED5=%d\r\n", msg_led_cfg[0],msg_led_cfg[1],msg_led_cfg[2], msg_led_cfg[3],msg_led_cfg[4],msg_led_cfg[5]); #elif (5 == SHELL_LED_MAX) "->LED0=%d LED1=%d tLED2=%d LED3=%d LED4=%d\r\n", msg_led_cfg[0],msg_led_cfg[1],msg_led_cfg[2], msg_led_cfg[3],msg_led_cfg[4]); #elif (4 == SHELL_LED_MAX) "->LED0=%d LED1=%d tLED2=%d LED3=%d\r\n", msg_led_cfg[0],msg_led_cfg[1],msg_led_cfg[2], msg_led_cfg[3]); #elif (3 == SHELL_LED_MAX) "->LED0=%d LED1=%d tLED2=%d\r\n", msg_led_cfg[0],msg_led_cfg[1],msg_led_cfg[2]); #elif (2 == SHELL_LED_MAX) "->LED0=%d LED1=%d\r\n", msg_led_cfg[0],msg_led_cfg[1]); #elif (1 == SHELL_LED_MAX) "->LED0=%d\r\n", msg_led_cfg[0]); #endif //发送数据 shell_SendHex(tmp_buff,tx_len); //发送数据 } else if(StrComp(ptSrc,"led wr ")) //设置LED的信号配置 { if(2 != sscanf((void *)ptSrc,"%*s%*s%d=%d",&led_id,&msg_id) )goto ERROR_LOOP; if( (led_id>(SHELL_LED_MAX-1)) || (msg_id >65535) )goto ERROR_LOOP; Ledx_config((uint8_t)led_id,(uint16_t)msg_id); //配置信号 //填写数据 tx_len = (uint16_t)sprintf((void *)tmp_buff, "->LED[%d]_Msg=%d\r\n",led_id,msg_led_cfg[led_id]); //发送数据 shell_SendHex(tmp_buff,tx_len); //发送数据 } else goto ERROR_LOOP; } else {ERROR_LOOP: //填写指令码 tx_len = (uint16_t)sprintf((void *)tmp_buff,"\r\nAT: Cmd Error:\t\""); //计算地址,填写数据,填写尾部 ptDst = tmp_buff + tx_len; ptSrc = (uint8_t *)shell_rx_buff; if(shell_rx_rdy > 32) { for(i=0; i<32; i++) { if( (*ptSrc > 126) || (*ptSrc < 32) ) { *ptDst++ = '?'; ptSrc++; } else { *ptDst++ = *ptSrc++; } } *(ptDst-2) = '-'; *(ptDst-1) = '>'; tx_len += 32; } else { for(i=0; i<shell_rx_rdy; i++) { *ptDst++ = *ptSrc++; tx_len++; } *(ptDst-2) = '<'; *(ptDst-1) = '-'; } tx_len += (uint16_t)sprintf((void *)ptDst,"\"\r\n"); //发送数据 shell_SendHex(tmp_buff,tx_len); //发送数据 } //清除数据返回程序 shell_rx_buff[0] = 0; shell_rx_rdy = 0;}/******************************************************************************/ 函数功能:字符串测试匹配指令/ 修改日期:2014/3/5 19:30:22/ 输入参数:none/ 输出参数:none/ 使用说明:none******************************************************************************/bool StrComp(void * buffer,void * StrCmd){ uint8_t i; uint8_t * ptBuf; uint8_t * ptCmd; ptBuf = (uint8_t *)buffer; ptCmd = (uint8_t *)StrCmd; for(i=0; i<255; i++) { if(ptCmd[i]) { if(ptBuf[i] != ptCmd[i])return false; } else { if(i)return i; else return false; } } return false;}/******************************************************************************/ 函数功能:打开LED信号/ 修改日期:none/ 输入参数:none/ 输出参数:none/ 使用说明:none******************************************************************************/void Ledx_on(uint16_t msg_id){ #if (SHELL_LED_MAX > 0) if(msg_id == msg_led_cfg[0])LED0_ON(); #endif #if (SHELL_LED_MAX > 1) if(msg_id == msg_led_cfg[1])LED1_ON(); #endif #if (SHELL_LED_MAX > 2) if(msg_id == msg_led_cfg[2])LED2_ON(); #endif #if (SHELL_LED_MAX > 3) if(msg_id == msg_led_cfg[3])LED3_ON(); #endif #if (SHELL_LED_MAX > 4) if(msg_id == msg_led_cfg[4])LED4_ON(); #endif #if (SHELL_LED_MAX > 5) if(msg_id == msg_led_cfg[5])LED5_ON(); #endif}/******************************************************************************/ 函数功能:关闭LED信号/ 修改日期:none/ 输入参数:none/ 输出参数:none/ 使用说明:none******************************************************************************/void Ledx_off(uint16_t msg_id){ #if (SHELL_LED_MAX > 0) if(msg_id == msg_led_cfg[0])LED0_OFF(); #endif #if (SHELL_LED_MAX > 1) if(msg_id == msg_led_cfg[1])LED1_OFF(); #endif #if (SHELL_LED_MAX > 2) if(msg_id == msg_led_cfg[2])LED2_OFF(); #endif #if (SHELL_LED_MAX > 3) if(msg_id == msg_led_cfg[3])LED3_OFF(); #endif #if (SHELL_LED_MAX > 4) if(msg_id == msg_led_cfg[4])LED4_OFF(); #endif #if (SHELL_LED_MAX > 5) if(msg_id == msg_led_cfg[5])LED5_OFF(); #endif}/******************************************************************************/ 函数功能:取反LED信号/ 修改日期:none/ 输入参数:none/ 输出参数:none/ 使用说明:none******************************************************************************/void Ledx_div(uint16_t msg_id){ #if (SHELL_LED_MAX > 0) if(msg_id == msg_led_cfg[0])LED0_DIV(); #endif #if (SHELL_LED_MAX > 1) if(msg_id == msg_led_cfg[1])LED1_DIV(); #endif #if (SHELL_LED_MAX > 2) if(msg_id == msg_led_cfg[2])LED2_DIV(); #endif #if (SHELL_LED_MAX > 3) if(msg_id == msg_led_cfg[3])LED3_DIV(); #endif #if (SHELL_LED_MAX > 4) if(msg_id == msg_led_cfg[4])LED4_DIV(); #endif #if (SHELL_LED_MAX > 5) if(msg_id == msg_led_cfg[5])LED5_DIV(); #endif}/******************************************************************************/ 函数功能:配置LED信号/ 修改日期:none/ 输入参数:none/ 输出参数:none/ 使用说明:none******************************************************************************/void Ledx_config(uint8_t led_id,uint16_t msg_id){ if(0 == led_id) {LED0_OFF();msg_led_cfg[0]=msg_id;} #if(SHELL_LED_MAX > 1) else if(1 == led_id){LED1_OFF();msg_led_cfg[1]=msg_id;} #endif #if(SHELL_LED_MAX > 2) else if(2 == led_id){LED2_OFF();msg_led_cfg[2]=msg_id;} #endif #if(SHELL_LED_MAX > 3) else if(3 == led_id){LED3_OFF();msg_led_cfg[3]=msg_id;} #endif #if(SHELL_LED_MAX > 4) else if(4 == led_id){LED4_OFF();msg_led_cfg[4]=msg_id;} #endif #if(SHELL_LED_MAX > 5) else if(5 == led_id){LED5_OFF();msg_led_cfg[5]=msg_id;} #endif }/******************************************************************************/ 函数功能:读取LED的配置信号/ 修改日期:none/ 输入参数:none/ 输出参数:none/ 使用说明:none******************************************************************************/uint16_t Ledx_read(uint8_t led_id){ if(0 == led_id) return msg_led_cfg[0]; #if(SHELL_LED_MAX > 1) else if(1 == led_id)return msg_led_cfg[1]; #endif #if(SHELL_LED_MAX > 2) else if(2 == led_id)return msg_led_cfg[2]; #endif #if(SHELL_LED_MAX > 3) else if(3 == led_id)return msg_led_cfg[3]; #endif #if(SHELL_LED_MAX > 4) else if(4 == led_id)return msg_led_cfg[4]; #endif #if(SHELL_LED_MAX > 5) else if(5 == led_id)return msg_led_cfg[5]; #endif else return 0;}/***************************************************************************************************************** END ******************************************************************************************************************/
四. shell使用
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
- 一种STM32的串口控制台的实现(非常实用)
- 一种STM32的串口控制台的实现(非常实用)
- 一种串口控制台(命令行)的实现
- 实用STM32的串口控制平台的实现(建议收藏)
- STM32串口配置的一种方法
- js实现一种非常酷而又实用的图片显示效果
- 比较实用的三个字符串处理函数(STM32串口)
- 一种简单实用的双向电平转换电路(非常实用!)3.3V--5V
- 一种简单实用的双向电平转换电路(非常实用!)3.3V--5V
- 一种简单实用的双向电平转换电路(非常实用!)3.3V--5V
- 非常实用的网址
- 非常实用的拒酒词
- STM32的串口通信
- 关于stm32的串口
- 实现静态页面的一种非常简单的方法
- 一种非常简便的实现Android多线程池的方法
- 项目正在用 非常实用的 maven的构件实现
- 两步实现Log4j记录java控制台输出的系统所有异常信息和自定义记录日志---->非常实用,强烈推荐阅读
- javascript注册事件-addEventListener和attachEvent
- Linux中后缀名为ko、o、a、so、la的文件介绍
- Qt on Android: http下载与Json解析
- python mysql 常见问题汇总
- 解决_CRT_SECURE_NO_WARNINGS 警告
- 一种STM32的串口控制台的实现(非常实用)
- 克隆类(克隆出一个一摸一样的对象)
- java 几种基本类型的长度值
- 用unix socket加速php-fpm、mysql、redis的连接
- 如何判断Unix系统及库文件是32位还是64位的
- 关于json_decode的两点
- 青岛朗讯面试经历
- C++拷贝构造函数详解
- linux下不解压tar.gz文件查看文件大小