STM32中的shell框架搭建

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) |

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

objectivec 复制代码
    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();
	}

代码实现

objectivec 复制代码
// @file init.h
#ifndef __INIT_H 
#define __INIT_H

#include "stm32f10x.h"

// 声明函数指针数据类型 
typedef void (*PINIT_T)(void);

// 声明全部硬件的初始化函数 
extern void DEVICE_Init(void);


#endif
objectivec 复制代码
// @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)(); 
	}
}

可将原代码中的

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

所有的初始化用init取代

objectivec 复制代码
DEVICE_Init();// 所有硬件的初始化

命令匹配优化

objectivec 复制代码
		// 字符串匹配 
		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

objectivec 复制代码
#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

objectivec 复制代码
#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

objectivec 复制代码
#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(); // 调用对应的函数
		else
			UART_Puts("invalid command\n");
		UART_Puts("\n");
	}

}

实验效果

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

相关推荐
智商偏低2 小时前
单片机之helloworld
单片机·嵌入式硬件
青牛科技-Allen4 小时前
GC3910S:一款高性能双通道直流电机驱动芯片
stm32·单片机·嵌入式硬件·机器人·医疗器械·水泵、
森焱森6 小时前
无人机三轴稳定控制(2)____根据目标俯仰角,实现俯仰稳定化控制,计算出升降舵输出
c语言·单片机·算法·架构·无人机
白鱼不小白6 小时前
stm32 USART串口协议与外设(程序)——江协教程踩坑经验分享
stm32·单片机·嵌入式硬件
S,D6 小时前
MCU引脚的漏电流、灌电流、拉电流区别是什么
驱动开发·stm32·单片机·嵌入式硬件·mcu·物联网·硬件工程
芯岭技术9 小时前
PY32F002A单片机 低成本控制器解决方案,提供多种封装
单片机·嵌入式硬件
youmdt10 小时前
Arduino IDE ESP8266连接0.96寸SSD1306 IIC单色屏显示北京时间
单片机·嵌入式硬件
嘿·嘘10 小时前
第七章 STM32内部FLASH读写
stm32·单片机·嵌入式硬件
Meraki.Zhang10 小时前
【STM32实践篇】:I2C驱动编写
stm32·单片机·iic·驱动·i2c
几个几个n12 小时前
STM32-第二节-GPIO输入(按键,传感器)
单片机·嵌入式硬件