(mcu) 嵌入式基础简单入门(程序架构分析)

2024-08-27 09:52

本文主要是介绍(mcu) 嵌入式基础简单入门(程序架构分析),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 💽前言
  • 💽软件框架
    • 📀工具环境
    • 📀模板工程
    • 📀编译后
    • 📀Code
    • 📀典例举例
  • 💽Keil 使用notes
  • ⭐END
    • 🌟关注我

💽前言

本文为一份简单入门笔记,以 stm32 单片机为例。

**声明:**由于笔者不是专业人员,仅作为入门初学者,因此本文避免不了的有专业性错误,请自行甄别。

完全以一位纯应用型软件工程师的角度进行学习和思考。

嵌入式软件还是遵循软件的本质:基于下层的支持为上层提供应用服务。

只是我们目前互联网上的大多数软件是基于操作系统或者虚拟机或解释器等等基础。

而单片机是直接操作硬件,是直接基于硬件提供的功能。

💽软件框架

**声明:**本文以软件架构分析为核心。

📀工具环境

关键和工具不是本文重点。

基于 STM32CubeMX 图形化配置硬件。

使用 Keil 进行软件开发。

📀模板工程

使用 CubeMX 生成的框架架构

工程名:20240824

  • .ioc & .mxproject
    • CubeMX 工程文件
  • Core
    • 硬件信息生成的代码框架
    • 特别注意 system_stm32f4xx.c 在 Keil 中是显示在 Drivers 文件夹中
  • Drivers
    • 具体对应硬件的驱动代码
      • CMSIS
        - 基于硬件芯片原厂架构的文件(基于芯片的最底层)
        - STM32 xxx
        - 基于 CMSIS 的二次开发
        - 一般属于暴露给用户开发的接口
  • MDK-ARM
    • .uvprojx & .uvoptx
      • 对用 Keil 的工程文件
    • startup_stm32f407xx .s
      • 默认配置的汇编文件
C:.
│  .mxproject
│  20240824.ioc
│  
├─Core
│  ├─Inc
│  │      gpio.h
│  │      main.h
│  │      stm32f4xx_hal_conf.h
│  │      stm32f4xx_it.h
│  │      
│  └─Src
│          gpio.c
│          main.c
│          stm32f4xx_hal_msp.c
│          stm32f4xx_it.c
│          system_stm32f4xx.c
│          
├─Drivers
│  ├─CMSIS
│  │  ├─Core
│  │  ├─Core_A
│  │  ├─DAP
│  │  ├─Device
│  │  ├─Documentation
│  │  ├─DSP
│  │  ├─Include
│  │  ├─NN
│  │  ├─RTOS
│  │  └─RTOS2
│  │       LICENSE.txt
│  └─STM32F4xx_HAL_Driver
│              
└─MDK-ARM20240824.uvoptx20240824.uvprojxstartup_stm32f407xx.s

📀编译后

在编译后会在 MDK-ARM 文件夹下生成编译的中间文件:

其中 20240824 是项目名。其中同名文件夹下的是最核心的中间文件,其中包含可烧文件

C:.
│  20240824.uvguix.windows
│  20240824.uvoptx
│  20240824.uvprojx
│  startup_stm32f407xx.lst
│  startup_stm32f407xx.s
│
├─20240824
│
├─DebugConfig
│
└─RTE

可烧入文件

  • axf:包含数据,地址,代码,debug调试等信息,可以用下载器直接烧到板子上

  • hex:包含数据,地址信息

  • bin:包含数据(最终都是转到bin)

因此一般文件大小为 .bin < .hex < .axf

在这里插入图片描述

📀Code

注意:由于是使用 CubeMX 生成的,因此可能后续会有硬件的修改,因此 CubeMX 会在代码中注入注释表示。

即在下面形式的代码区间内编写代码才不会被下次重新生成框架代码所移除。

/* USER CODE BEGIN Includes */
// 自己的代码
/* USER CODE END Includes */

但由于本文是初学的学习笔记,因此本篇文章中展示的内容无视该规则。

main

下面是 main 的主题逻辑,核心就是 初始化-服务轮询 架构。

int main(void) {/*** Reset of all peripherals, Initializes the Flash interface and the Systick.* 重置所有外设,初始化Flash接口和系统棒。* =========================================================================* hal是stm32的三种不同应用库的一种**/HAL_Init();/*** Configure the system clock* 配置系统时钟* ==========================* 系统(硬件)总体(所有)的时钟* 相关的配置和初始化,相当于一个总开关* 保证芯片是正常能跑起来的*/SystemClock_Config();/*** Initialize all configured peripherals* 初始化所有配置的外设* =====================================* 在 CubeMX 中进行配置的外设专门的定制化初始化* 如:定时器,串口等*/MX_GPIO_Init();MX_TIM1_Init();MX_USART1_UART_Init();MX_USART2_UART_Init();/* USER CODE BEGIN 2 *//*** 业务代码* 一般为业务的初始化*/myservice_init();/*** 执行 while(1) 轮询* 一般为业务的状态机*/while (1) {myservice_state();}
}

中断

stm32f4xx_it.c/h 文件中,是中断处理的函数,如下面的形式:

#ifndef __STM32F4xx_IT_H
#define __STM32F4xx_IT_H#ifdef __cplusplus
extern "C" {
#endifvoid NMI_Handler(void);
void HardFault_Handler(void);
void MemManage_Handler(void);
void BusFault_Handler(void);
void UsageFault_Handler(void);
void SVC_Handler(void);
void DebugMon_Handler(void);
void PendSV_Handler(void);
void SysTick_Handler(void);
void USART2_IRQHandler(void);#ifdef __cplusplus
}
#endif#endif /* __STM32F4xx_IT_H */

MDK-ARM/startup_stm32f407xx.s 文件中可看到映射,也就是说这些是框架直接帮我们做了,不用我们考虑链接的问题。

__Vectors       DCD     __initial_sp               ; Top of StackDCD     Reset_Handler              ; Reset HandlerDCD     NMI_Handler                ; NMI HandlerDCD     HardFault_Handler          ; Hard Fault HandlerDCD     MemManage_Handler          ; MPU Fault HandlerDCD     BusFault_Handler           ; Bus Fault HandlerDCD     UsageFault_Handler         ; Usage Fault HandlerDCD     0                          ; ReservedDCD     0                          ; ReservedDCD     0                          ; ReservedDCD     0                          ; ReservedDCD     SVC_Handler                ; SVCall HandlerDCD     DebugMon_Handler           ; Debug Monitor HandlerDCD     0                          ; ReservedDCD     PendSV_Handler             ; PendSV HandlerDCD     SysTick_Handler            ; SysTick Handler

📀典例举例

通过 MX_GPIO_Init() 了解嵌入式的本质,就是配置硬件操作。

void MX_GPIO_Init(void) {GPIO_InitTypeDef GPIO_InitStruct = {0};/*** GPIO Ports Clock Enable* GPIO端口时钟使能* ======================* 开了C H A 三个组的时钟* 仅是启动open,还没用* 如果没开,即使下面初始化成功了,硬件还是没反应*/__HAL_RCC_GPIOC_CLK_ENABLE();__HAL_RCC_GPIOH_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();/*** Configure GPIO pin Output Level* 配置GPIO引脚输出电平* ================================* GPIOC           引脚*组*的地址(C组)* GPIO_PIN_14     引脚号* GPIO_PIN_RESET  表示低电平*/HAL_GPIO_WritePin(GPIOC, GPIO_PIN_14, GPIO_PIN_RESET);/*** Configure GPIO pin : PC14* 配置GPIO引脚:PC14* =========================* 配置这个引脚的基本参数*/GPIO_InitStruct.Pin   = GPIO_PIN_14;GPIO_InitStruct.Mode  = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull  = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
}

然后具体的业务操作,一个典型的应用就是:

  • myservice_init(); 对串口的buffer进行初始化,

  • myservice_state(); 对缓冲区进行状态机的处理。

这段数据业务逻辑,不做具体展示了。一般来说串口接受数据就是靠上文中介绍的中断函数。(当然也有办法不通过中断操作)

💽Keil 使用notes

添加头文件路径

默认配置下是无头文件相关的内容的

在这里插入图片描述

添加头文件

在这里插入图片描述

字符集设置

在这里插入图片描述

添加一个组

这个组是只针对工程,而不是外部的具体文件和文件夹(不会自动识别)

在这里插入图片描述

配置烧写器

在这里插入图片描述




⭐END

🌟关注我

关注我,学习更多C/C++,算法,计算机知识

B站:

👨‍💻主页:天赐细莲 bilibili

这篇关于(mcu) 嵌入式基础简单入门(程序架构分析)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1111331

相关文章

Go标准库常见错误分析和解决办法

《Go标准库常见错误分析和解决办法》Go语言的标准库为开发者提供了丰富且高效的工具,涵盖了从网络编程到文件操作等各个方面,然而,标准库虽好,使用不当却可能适得其反,正所谓工欲善其事,必先利其器,本文将... 目录1. 使用了错误的time.Duration2. time.After导致的内存泄漏3. jsO

Spring Boot + MyBatis Plus 高效开发实战从入门到进阶优化(推荐)

《SpringBoot+MyBatisPlus高效开发实战从入门到进阶优化(推荐)》本文将详细介绍SpringBoot+MyBatisPlus的完整开发流程,并深入剖析分页查询、批量操作、动... 目录Spring Boot + MyBATis Plus 高效开发实战:从入门到进阶优化1. MyBatis

Mysql表的简单操作(基本技能)

《Mysql表的简单操作(基本技能)》在数据库中,表的操作主要包括表的创建、查看、修改、删除等,了解如何操作这些表是数据库管理和开发的基本技能,本文给大家介绍Mysql表的简单操作,感兴趣的朋友一起看... 目录3.1 创建表 3.2 查看表结构3.3 修改表3.4 实践案例:修改表在数据库中,表的操作主要

springboot简单集成Security配置的教程

《springboot简单集成Security配置的教程》:本文主要介绍springboot简单集成Security配置的教程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录集成Security安全框架引入依赖编写配置类WebSecurityConfig(自定义资源权限规则

Spring事务中@Transactional注解不生效的原因分析与解决

《Spring事务中@Transactional注解不生效的原因分析与解决》在Spring框架中,@Transactional注解是管理数据库事务的核心方式,本文将深入分析事务自调用的底层原理,解释为... 目录1. 引言2. 事务自调用问题重现2.1 示例代码2.2 问题现象3. 为什么事务自调用会失效3

Java异常架构Exception(异常)详解

《Java异常架构Exception(异常)详解》:本文主要介绍Java异常架构Exception(异常),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1. Exception 类的概述Exception的分类2. 受检异常(Checked Exception)

C#基础之委托详解(Delegate)

《C#基础之委托详解(Delegate)》:本文主要介绍C#基础之委托(Delegate),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1. 委托定义2. 委托实例化3. 多播委托(Multicast Delegates)4. 委托的用途事件处理回调函数LINQ

找不到Anaconda prompt终端的原因分析及解决方案

《找不到Anacondaprompt终端的原因分析及解决方案》因为anaconda还没有初始化,在安装anaconda的过程中,有一行是否要添加anaconda到菜单目录中,由于没有勾选,导致没有菜... 目录问题原因问http://www.chinasem.cn题解决安装了 Anaconda 却找不到 An

Spring定时任务只执行一次的原因分析与解决方案

《Spring定时任务只执行一次的原因分析与解决方案》在使用Spring的@Scheduled定时任务时,你是否遇到过任务只执行一次,后续不再触发的情况?这种情况可能由多种原因导致,如未启用调度、线程... 目录1. 问题背景2. Spring定时任务的基本用法3. 为什么定时任务只执行一次?3.1 未启用

如何使用Python实现一个简单的window任务管理器

《如何使用Python实现一个简单的window任务管理器》这篇文章主要为大家详细介绍了如何使用Python实现一个简单的window任务管理器,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起... 任务管理器效果图完整代码import tkinter as tkfrom tkinter i