当前位置: 首页> 科技> IT业 > STM32中的shell框架搭建

STM32中的shell框架搭建

时间:2025/7/13 5:02:33来源:https://blog.csdn.net/weixin_40198632/article/details/141336732 浏览次数:0次

STM32和电脑的关系

  •     可以将上位机给下位机发送的信息当做是控制命令
  •     下位机给上位机发送的信息当做是硬件本身的状态 

初始化函数的优化

批量化调用同类型函数,有同样的数据类型,放一块 - 数组 

定义一个数组, 函数指针数组, 数组中包含的都是一个一个的函数指针, 就是函数的首地址 

|--LED_Init--|--BEEP_Init--|--UART_Init--|--...--|--....--|--0--|将近期所有的初始化函数放到一个数组里

回忆知识:函数指针:

C语言指针进阶(一)——深入详解“函数指针”与“指针函数”-CSDN博客

以下变量的类型:

int a;int
int* pa;int*
int a[5];int [5]
int (*p)(void);int (*)(void)

小窍门:把定义中的变量名去除就是变量类型

    typedef  int (*p_t)(void);p_t arr[] = {LED_Init, BEEP_Init, UART_Init};for(int i = 0; i < 3; i++){p_t p;p = arr[i];p();}

代码实现

// @file init.h
#ifndef __INIT_H 
#define __INIT_H#include "stm32f10x.h"// 声明函数指针数据类型 
typedef void (*PINIT_T)(void);// 声明全部硬件的初始化函数 
extern void DEVICE_Init(void);#endif
// @file  init.c
#include "init.h"
#include "led.h"
#include "beep.h"
#include "systick.h"
#include "key.h"
#include "exti.h"
#include "uart.h"// 定义函数指针数组, 存储所有初始化函数的首地址
static PINIT_T init_func[] = {LED_Init,			// led灯初始化BEEP_Init,		// beep初始化 Systick_init,	// 滴答定时器初始化KEY_Init,			// 按键初始化My_EXTI_Init,	// 中断初始化 UART_Init,		// 串口初始化 0
};void DEVICE_Init(void)
{// pfunc存储数组首地址// pfunc存储数组下表为0存储区的首地址PINIT_T* pfunc = init_func;for(; *pfunc; pfunc++){(*pfunc)(); }
}

可将原代码中的

	LED_Init(); // led灯的初始化BEEP_Init(); // BEEP的初始化Systick_init(); // 滴答定时器的初始化 KEY_Init();			// 按键的初始化My_EXTI_Init(); // EXTI初始化 

所有的初始化用init取代

DEVICE_Init();// 所有硬件的初始化

命令匹配优化

		// 字符串匹配 if(!strcmp(buf, "led on")){LED_On(); // 开灯 UART_Puts("LED ON");}else if(!strcmp(buf, "led off")){LED_Off(); // 关灯 UART_Puts("LED OFF");}else if(!strcmp(buf, "beep on")){BEEP_On(); // 打开蜂鸣器 UART_Puts("BEEP ON");}else if(!strcmp(buf, "beep off")){BEEP_Off(); // 关闭蜂鸣器 UART_Puts("BEEP OFF");}else{UART_Puts("invalid command\n");}UART_Puts("\n");

在main函数中,接收来自cpu发送的字符串进行判断,需要单个去进行匹配,这时候新建cmd.h和cmd.c专门优化这部分匹配,适配后期的匹配

cmd.h


#ifndef __CMD_H  
#define __CMD_H#include "stm32f10x.h"// 声明函数指针数据类型 
typedef void (*cb_t)(void); //这里需要注意对函数指针进行typedef的定义方法,而不是typedef void (* )(void) p_t// 声明命令的数据类型 
typedef struct{char* name;cb_t callback; 
}cmd_t;// 用于匹配函数 
extern cmd_t* find_cmd(char* name);//这里要注意返回的cmd_t类型的结构体,需要用地址来取#endif

cmd.c

#include "cmd.h"
#include "led.h"
#include "beep.h"
#include "string.h"// 定义描述所有命令的数组 
cmd_t cmd[] = {{"led on", LED_On},{"led off", LED_Off},{"beep on", BEEP_On},{"beep off", BEEP_Off}
};
// 获取数组长度 
#define  CMD_NUM(x)   (sizeof(x) / sizeof(x[0])) //使用宏的方式进行定义,方便后期调用// 命令匹配函数 
// 参数 - 用户输入的操作命令 
// 和某个命令匹配成功, 需要传递给其它函数什么数据,可以直接调用对应的函数呢?
cmd_t* find_cmd(char* name)
{int i = 0;for(i = 0; i < CMD_NUM(cmd); i++){if(!strcmp(name, cmd[i].name))return &cmd[i];// 返回匹配成功命令的首地址} return 0;
}

main.c

#include "stm32f10x.h"
#include "led.h"
#include "beep.h"
#include "system.h"
#include "systick.h"
#include "key.h"
#include "exti.h"
#include "uart.h"
#include "string.h"  // strcmp函数声明 
#include "init.h"
#include "cmd.h"#define  BUF_LEN   128
static char buf[BUF_LEN]; // 定义数组存储从上位机读取到的字符串 
static cmd_t* pcmd;int main(void){NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //--|--DEVICE_Init();// 所有硬件的初始化while(1){// 下位机->上位机:请输入命令 UART_Puts("please input your command:");// buf = "led on"/"led off"/"beep on"/"beep off"// 上位机发送的命令在buf数组中UART_Gets(buf, BUF_LEN); // 命令匹配, 参数就是上位机输入的命令 pcmd = find_cmd(buf);if(pcmd != 0) // 匹配成功pcmd->callback(); // 调用对应的函数elseUART_Puts("invalid command\n");UART_Puts("\n");}}


实验效果


从上位机给下位机发送led on,STM32主板中的LED会亮,发送led off则会熄灭

关键字:STM32中的shell框架搭建

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: