嵌入式到机器人开发一(硬件编)

本文档是记录嵌入式到机器人开发技术编,为便记录如何从电子电路到自己开发一个机器人的流程,

第一部份   

嵌入式基础
什么是嵌入式,就是将软件硬件嵌入到一个微型控制中,嵌入嘛,就是将软件硬 件全嵌入在一块小块子中,我们的台式机和笔记本呢,他们软件是可以自由安装的,但是嵌入的发展也会功能越来越强,走到ai ,所以可能以后会糊模定义,

目前特点:

  • 固化在设备里、不能随便拆
  • 功能固定:只做控制、显示、采集、联网
  • 体积小、低成本、省电、专用系统
  • 如:平板、电视、盒子、投影仪、音箱、手环手表智能设备,智能门锁、门禁、烟雾报警器、温湿度传感器、PLC、工业触摸屏、变频器、伺服驱动器、工业网关、
  • 数据采集器、机床控制器。全是嵌入式。

    按算力类型业区别,可能有精简功能的stm32   连网方便的 esp32    算力并发的gpu类型的jetson nano    rk系统   还有支持实时,高并发的比如华为的路由 , 基站   ,

 

开发前必烦知道的理伦
我们开发嵌入式,实际就是操作gpio引脚 ,但是引脚的通信需要通信的频率,需要晶振,晶振就是时钟,比如说多少时间内发出脉冲,都 要需要配置的,还是配置高电平通信还是低电平通信,在距离较远的电路中,电路会衰减,本应高电平的可能都 不高了,所以通信有很多方式,最直接就是一会高电平,一下低电平来代表01    但是可能是受电压响,复杂的要用来传数据的 ,用其它方式,比如差分信号,就是一根高电平,一根低电,用有没有差别来表示0.1 所以嵌入式的通信才为为很多种 ,对于更复杂的需要配置的,我们还用at 配置信息,然后在信号中每次带上配置信号,来完成加密。

还有最后一个就是变量,为了开发方便,核心板产商开发编程工个。,,在里面对一个固定的gpio  串口,很多硬 件都 命 了名,我们直接拿来用,所以与代码时不需要问,这些变量那儿来的,专业术语叫   向量表

 

 

 

 

引脚功能:

GPIO_MODE_INPUT          浮空输入:   引脚电平完全由外部决定,悬空时电平乱跳。用于按键、传感器、外部信号输入。
GPIO_MODE_OUTPUT_PP      推挽输出:   能直接输出强高低电平,驱动能力强。用于LED、蜂鸣器、继电器、普通控制。
GPIO_MODE_OUTPUT_OD      开漏输出:   只能拉低电平,高电平要靠外部上拉,可多芯片共用总线。用于I2C、1-Wire、电平转换。
GPIO_MODE_AF_PP          复用推挽:   给串口、PWM、SPI等外设用,强驱动输出。用于串口TX、PWM输出、SPI时钟。
GPIO_MODE_AF_OD          复用开漏:   给外设开漏用,只能拉低,需上拉。用于硬件I2C的SDA/SCL。
GPIO_MODE_AF_INPUT       复用输入:   给外设专用输入口。用于串口RX、SPI输入、定时器捕获。
GPIO_MODE_ANALOG         模拟模式:   只测电压,不走数字信号。用于ADC采样、模拟信号输入。

1. 什么是 MSP?

MSP 全称是MCU Support Package,可以直接理解成:单片机外设的「底层初始化工具人」。 
它的核心工作,就是给单片机的各种外设(比如串口、定时器、GPIO、中断这些)做最基础的初始化: 
  • 给外设开时钟(相当于给外设通电,不通电外设没法干活)
  • 配置外设用到的 GPIO 引脚(比如串口要用到 TX/RX 两个引脚,得先把这俩脚设成串口模式)
  • 配置外设相关的中断(比如串口接收数据要触发中断,得先把中断打开、设好优先级) 
它是 HAL 库的核心组成部分,用 HAL 库开发时,必须写好 MSP 函数,外设初始化的时候会自动调用它。 
举个例子:你要用串口(USART)发数据,HAL 库会先自动调用串口的 MSP 函数,把串口的时钟、引脚、中断都配置好,再执行发数据的功能,不用你手动去管这些底层操作。
 

 

2. MSP 的调用逻辑 

MSP 函数不用你手动调用,CubeMX 会自动生成代码,程序运行时会自动调用,整个流程是这样的: 
    1. 程序从main()函数开始运行
    2. 先执行HAL_Init(),初始化 HAL 库的基础环境
    3. 自动调用HAL_MspInit(),这就是全局的 MSP 初始化入口
    4. 后续你初始化某个具体外设(比如串口、SPI)时,HAL 库会自动调用对应外设的 MSP 函数,完成该外设的底层配置

编写第一个示例,点亮一个灯,首先打开stmcubeMx 选中芯片型号 ,选择我们当下用的是gpio8,和9   开发板是立创星空学习板

image

 

需要用stmcubeMx 创立工程, 选中型号    然后配置引脚  gpio 8    gpio 9    ,因为我们要做点亮灯,默认要高电平,所以要配置为高电平  ,推换推出,由于是输出,下上拉无意义,这儿不用管,  如果设低电平,默认灯就亮了,好像也不是不行,这儿其实任意哈,,,

关于stmcubeMx 要下载6.14.1,老版有很多坑,传说6.15也有乱码的坑,所以还是选6.14.1   老版本的坑比如中文乱码问题 ,配置的时钟与实际硬件运行频率不一致(差一半、翻倍),如果用低本遇到需要解决中文乱码可以先增加一个环境变量,

选择新建,在变量名和变量值如下如下内容
变量名称: JAVA_TOOL_OPTIONS
变量值:-Dfile.ecoding=UTF-8       修改完成后,全部点确定。然后重启stm32CubeMX软件即可。

 

配置好工程后,可以用kial 或vscode 找开项目,在maian.c 写引脚 代码,完成第一个示例

  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET);   // led1 熄灭
		HAL_Delay(500); // 延时500ms 
		HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET); // led1 点亮
		HAL_Delay(500);  // 延时500ms 

  }
  /* U

  这儿我们可以看到软件工作文件目录,需要介绍一下, stm32f1xx.it  是中断函数的编写地方,

       stm32f1xx.hal.map.c 是核心底层配置的地方,stm32f1xx_hal_msp.c。 是 STM32CubeMX 自动生成, MSP = MCU Support Package,MCU 底层支撑配置
专门存放所有外设的底层硬件初始化:比如以下配置
 

  • 开启外设时钟(GPIO、UART、ADC、TIM 等)
  • 配置引脚复用功能
  • 配置 NVIC 中断
  • 配置 DMA(如果用到)
     
    所有 HAL_XXX_MspInit() 统一放在这里。以下这个文件的代码片断,可能总结为main.c  虽然也有配置,他是基于这个文件的配置,这个文件才是操作硬 件的配置
void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{
  __HAL_RCC_USART1_CLK_ENABLE();  // 开时钟
  // 配置GPIO、NVIC等
}

 其它文件的分布,如下,

 

image

 

常见方法介绍:

main.c 文件中常用方法介绍:

HAL_Init()                         初始化项目和初始化hal 库 ,项目第一句代码,不要在HAL_Init()之前调用任何外设相关的代码,否则会出奇怪的 bug。

SystemClock_Config()     配置时钟,CubeMX 生成的工程里,这个函数会自动写好,一般不用自己改。时钟  配置对,外设波特率、定时器、延时都会出错。

MX_GPIO_Init()               这个函数是 CubeMX 生成的,里面会调用HAL_GPIO_Init()。帮你一次性配置好所有引脚的输入 / 输出模式、上下拉电阻、速度等。不要在这个函数里手动写引脚操作代码,                                            否则重新生成工程会被覆盖。

HAL_GPIO_WritePin()        控制 GPIO 引脚输出高 / 低电平。给引脚 “发信号”,比如让 LED 亮 / 灭、给模块发指令。

HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);   // PA5输出高电平       参数介绍,第一个参数,那一组引脚 ,第二个参数,这组引脚中那个编号  第三个参数,高还是低电平
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET); // PA5输出低电平

HAL_Delay()          毫秒级延时函数,让程序 “等一会儿再往下走”        这个延时是阻塞的,延时期间程序什么都做不了,游戏里用多了会卡顿。高优先级中断会打断延时,导致实际延时时间变长

HAL_Delay_Us()(或自定义微秒延时)       功能同上,只是时间不同

其它以后才用到的函数   

HAL_GPIO_ReadPin()             读取 GPIO 引脚的电平状态,判断按键是否按下。

HAL_GPIO_TogglePin()           翻转 GPIO 引脚的电平状态(高变低、低变高)。

HAL_TIM_Base_Start() / HAL_TIM_Base_Start_IT()     启动定时器,用来做定时任务、PWM、游戏帧率控制。   

HAL_TIM_PWM_Start()          启动定时器的 PWM 输出,用来驱动蜂鸣器、电机、LED 呼吸灯。

在正式写代码前,先了解一下软件环境 ,比如中文支持,界面样式,在kail5 的 edit 有一个 Configuration菜单,里面有软件相关配置

image

 编译流程:

我们在写代码的时候,有部份代码是给编译器看的,比如以下的注解:

image

 

 一个完成的功能包装封,包括功能封装,示例 我们要点灯,并且要把功能封装成来。

第一步,核心代码是

HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);   // PA5输出高电平       参数介绍,第一个参数,那一组引脚 ,第二个参数,这组引脚中那个编号  第三个参数,高还是低电平
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET); // PA5输出低电平

封装:
我们们gpio.c  写函数本身 在gpio.h 需要爆露出宏定义和函数名,方便主函数据调用
gpio.c 新增二个函数功能代码,一个是功能函数,一个是测试函数

void LED_Control(uint8_t device, uint8_t cmd)
{
    GPIO_PinState state = cmd ? GPIO_PIN_RESET : GPIO_PIN_SET;

    if(device == LED1)
        HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, state);
    else if(device == LED2)
        HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, state);
}

测试函数:

void LED_Test(void)
{
        LED_Control(LED1,ON); 
        LED_Control(LED2,OFF); 
        HAL_Delay(500); 
        LED_Control(LED1,OFF); 
        LED_Control(LED2,ON); 
        HAL_Delay(500); 
}

载图如下 :

image

 其它写法参考:

void LED_Control(uint8_t device, uint8_t cmd)
{
    switch(device)
    {
        case LED1: HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, cmd ? 0 : 1); break;
        case LED2: HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, cmd ? 0 : 1); break;
    }
} 

 

 最后主函数调用:

image

 

 以下功能通常  蜂鸣器   接触器   开发都是一样,通过调节电平来控制,所以基础控制电位的的功能先不介结了,以下开始研究按健扫描

 

 

中断模式

要使中断的话,意思是事件,比如我们要绑定在gpio  让这个按扭中低变平或高电平发生时,运行一个函数就叫中断,中断还可以帮在定时器到点,按健被 按下等场

核心点中断

第一在stm32cubeMx中  将一下gpio绑定于引脚 为中断模式 

 

 

image

 然后在gpio 的配置中配置一下什么条件触发

image

 

 还差一步,使其使能,这一步完成后就可以ai 可以写代码了

  • EXTI line[9:5] interrupts:对应 GPIO 引脚 5~9 的外部中断(共用一个中断服务函数)
  • EXTI line[15:10] interrupts:对应 GPIO 引脚 10~15 的外部中断(共用一个中断服务函数)
     
    STM32F103 把多个 EXTI 线合并到同一个中断向量,比如 EXTI5~9 共享 EXTI9_5_IRQHandler,EXTI10~15 共享 EXTI15_10_IRQHandler,这就是这里配置的本质。

image

 

 

  • 第一步将对应的 GPIO 引脚(比如 PB5、PC13 这类)配置成了外部中断模式,并设置了触发方式(上升 / 下降沿 / 双边沿)。这样的话,当这个事件发生时会产生中断,其实就是对方的中断函数会运行
  • 还得配置中断优化,告诉内核 “这些中断我要用,优先级设为最高”,让 MCU 收到引脚电平变化时,能正确响应并跳转到对应的中断服务函数里执行你的代码。不能在延时器中配中断,好像好出问题 ,除非中断的时序较高
  • 后续你需要在 HAL 库中,用 HAL_GPIO_EXTI_Callback() 回调函数来写中断触发后的处理逻辑,还要清除中断标志位,不可我们用ai 写代码可以让ai 来写,至此中断就这点东西。嵌入式会了中断,时钟,通信,入门的话差不多就可以学其它的了,因为更高级的东西,直接上框架吧,先做出产品,再来优化细节,如是想要做好产品,肯定要自己会写寄存器,才能优化性能,但是作为新手我们做图做出成品, 下一章,我们直接开始通信

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

000000000000000000000

posted @ 2026-04-11 08:00  谢双元小号  阅读(67)  评论(0)    收藏  举报