STM32开发基础知识入门
C语言基础
位操作
对基本类型变量可以在位级别进行操作。
1) 不改变其他位的值的状况下,对某几个位进行设值。
先对需要设置的位用&操作符进行清零操作,然后用|操作符设值。
2) 移位操作提高代码的可读性。
3) ~取反操作使用技巧
可用于对某一位取0,也是为了提高可读性。
define宏定义
常见格式:#define 标识符 字符串
ifdef条件编译
常见格式:
#ifdef 标识符
程序段1
#else
程序段2
#endif
它的作用是:当标识符已经被定义过一般是用 #define 命令定义 )),则对程序段 1 进行编译,否则编译程序段 2 。
extern变量申明
C语言中extern 可以置于变量或者函数前,以表示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义 。 这里面要注意,对于extern申明变量可以多次,但定义只有一次。
就是说变量只能定义一次,如果重复定义了需要用extern声明。
typedef类型别名
typedef用于为现有类型创建一个新的名字,或称为类型别名,用来简化变量的定义。
结构体
结构体就是将多个变量组合为一个有机的整体。
声明结构体类型:
Struct 结构体名{
成员列表;
}变量名列表;
在结构体申明的时候可以定义变量,也可以申明之后定义,方法是:
Struct 结构体名字 结构体变量列表 ;
结构体成员变量的引用方法是:(结构体指针成员变量引用方法是通过“->”符号实现)
结构体变量名字.成员名
STM32系统架构
STM32主系统主要由四个驱动单元和四个被动单元构成。
四个驱动单元是:内核DCode 总线;系统总线;通用 DMA1;通用DMA2。
四个被动单元是:AHB到 APB 的桥:连接所有的 APB 设备;内部FlASH 闪存;内部SRAM;FSMC。
总线:
① ICode 总线:该总线将 M3 内核指令总线和闪存指令接口相连,指令的预取在该总线上面完成。
② DCode 总线:该总线将 M3 内核的 DCode 总线与闪存存储器的数据接口相连接 ,常量加载和调试访问在该总线上面完成。
③ 系统总线:该总线连接 M3 内核的系统总线到总线矩阵,总线矩阵协调内核和 DMA 间访问。
④ DMA 总线:该总线将 DMA 的 AHB 主控接口与总线矩阵相连,总线矩阵协调 CPU 的DCode 和 DMA 到 SRAM, 闪存和外设的访问。
⑤ 总线矩阵:总线矩阵协调内核系统总线和 DMA 主控总线之间的访问仲裁,仲裁利用轮换算法。
⑥ AHB/APB 桥:这两个桥在 AHB 和 2 个 APB 总线间提供同步连接, APB1 操作速度限于36MHz ,APB2 操作速度全速。
STM32时钟系统
简单的说,时钟是单片机的脉搏,是单片机的驱动源,使用任何一个外设都必须打开相应的时钟。这样的好处是,如果不使用一个外设的时候,就把它的时钟关掉,从而可以降低系统的功耗,达到节能,实现低功耗的效果。
首先,任何外设都需要时钟,因为寄存器是由D触发器组成的,往触发器里面写东西,前提条件是有时钟输入。
51单片机不需要配置时钟,是因为一个时钟开了之后所有的功能都可以用了,而这个时钟是默认开启的。stm32之所以是低功耗,他将所有的门都默认设置为disable,在你需要用哪个门的时候,开哪个门就可以,也就是说用到什么外设,只要打开对应外设的时钟就可以,其他的没用到的可以还是disable,这样耗能就会减少。
在51单片机中一个时钟把所有的都包了,而stm32的时钟是有分工的,并且每类时钟的频率不一样,因为没必要所有的时钟都是最高频率,只要够用就行,所以不同的时钟也会有频率差别,或者在配置的时候可以配置时钟分频。
在STM32 中,有五个时钟源,为 HSI 、 HSE 、 LSI 、 LSE 、 PLL 。 从时钟频率来分可以分为高速时钟源和低速时钟源,在这 5 个中 HIS,HSE 以及 PLL 是高速时钟, LSI 和 LSE 是低速时钟。从来源可分为外部时钟源和内部时钟源,外部时钟源就是从外部通过接晶振的方式获取时钟源,其中 HSE 和 LSE 是外部时钟源,其他的是内部时钟源。
① 、 HSI 是高速内部时钟, RC 振荡器, 频率 为 8MHz 。
② 、 HSE 是高速外部时钟, 可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~16MHz 。 我们的开发板接的是 8M 的晶振。
③ 、 LSI 是低速内部时钟, RC 振荡器,频率为 40kHz 。 独立看门狗的时钟源只能是 LSI ,同时LSI 还可以作为 RTC 的时钟源。
④ 、 LSE 是低速外部时钟,接频率为 32.768kHz 的 石英晶体。 这个主要是 RTC 的时钟源。
⑤ 、 PLL 为锁相环倍频输出 ,其时钟输入源可选择为 HSI/2 、 HSE 或者 HSE/2 。倍频可选择为2~16倍,但是其输出频率最大不得超过 72MHz 。
时钟源给外设以及系统提供时钟:
A. MCO 是 STM32 的一个时钟输出 IO(PA8),它可以选择一个时钟信号输出可以选择为 PLL 输出的 2 分频、 HSI 、 HSE 、或者系统时钟 。这个时钟可以用来给外部其他系统提供时钟源。
B. 这里是 RTC 时钟源,从图上可以看出, RTC 的时钟源可以选择 LSI,LSE ,以及HSE 的 128 分频。
C. 从图中可以看出 C 处 USB 的时钟是来自 PLL 时钟源。 STM32 中有一个全速功能的 USB 模块 ,其串行接口引擎需要一个频率为 48MHz 的时钟源。该时钟源只能从 PLL 输出端获取,可以选择为 1.5 分频或者 1 分频,也就是,当需要使用 USB模块时, PLL 必须使能,并且时钟频率配置为 48MHz 或 72MHz 。
D. D 处就是 STM32 的系统时钟 SYSCLK ,它是供 STM32 中绝大部分部件工作 的时钟源 。 系统时钟可选择为 PLL 输出、 HSI 或者 HSE 。系统时钟最大频率 为 72MHz当然你也可以超频,不过一般情况为了系统稳定性是没有必要 冒风险去超频的。
E. 这里的E 处是指其他所有外设了。从时钟图上可以 看出,其他所有外设的时钟最终来源都是 SYSCLK 。 SYSCLK 通过 AHB 分频器分频后送给各模块使用 。这些模块包括:
①、 AHB 总线、内核、内存和DMA 使用的 HCLK 时钟。
② 、通过 8 分频后送给 Cortex 的系统 定时器时钟 ,也就是 systick 了 。
③ 、直接送给 Cortex 的空闲运行时钟 FCLK 。
④ 、送给 APB1 分频器。 APB1 分频器输出一路供 APB1 外设使用 (PCLK1 ,最大频率 36MHz),另一路送给定时器 (Timer)2 、 3 、4 倍频器使用。
⑤、送给 APB2 分频器。 APB2 分频器 分频输出一路供 APB2 外设使用 (PCLK2最大频率 72MHz),另一路送给定时器 (Timer)1 倍频器使用。
其中需要理解的是APB1 和 APB2 的 区别, APB1 上面连接的是低速外设,包括电源接口、备份接口、 CAN 、 USB 、 I2C1 、 I2C2 、 UART2 、 UART3 等等, APB2 上面连接的是高速外设包括 UART1 、 SPI1 、 Timer1 、 ADC1 、 ADC2 、所有普通 IO 口 (PA~ PE)、第二功能 IO 口等。
端口复用和重映射
端口复用功能
一个 GPIO如果可以复用为内置外设的功能引脚,那么当这个 GPIO 作为内置外设使用的时候,就叫做复用。(既是引脚也是内置外设的引脚)
复用端口初始化:
GPIO 端口时钟使能;
复用的外设时钟使能;
端口模式配置,在 IO 复用位内置外设功能引脚的时候,必须设置 GPIO 端口的模式。
端口重映射
一个外设的引脚除了具有默认的端口外,还可以通过设置重映射寄存器的方式,把这个外设的引脚映射到其它的端口 。
重映射步骤:
使能重映射的GPIO时钟;
使能外设时钟;
使能AFIO时钟;
开启重映射;
STM32 NVIC中断优先级管理
CM3内核支持 256 个中断,其中包含了 16 个内核中断和 240 个外部中断,并且具有 256级的可编程中断设置。但 STM32 并没有使用 CM3 内核的全部东西,而是只用了它的一部分。STM32 有 84 个中断,包括 16 个内核中断和 6 8 个可屏蔽中断,具有 16 级可编程的中断优先级。而我们常用的就是这 6 8 个可屏蔽中断, 但是 STM32 的 68 个可屏蔽中断,在STM32F103 系列上面,又只有 60 个(在 107 系列才有 68 个)。
typedef struct
__IO uint32_t ISER[8]; /*!< Interrupt Set Enable Register
uint32_t RESERVED0[24];
__IO uint32_t ICER[8]; /*!< Interrupt Clear Enabl e Regi ster */
uint32_t RSERVED1[24];
__IO uint32_t ISPR[8]; /*!< Interrupt Set Pending Register
uint32_t RESERVED2[24];
__IO uint32_t ICPR[8]; /*!< Interrupt Clear Pending Register
uint3 2_t RESERVED3[24];
__IO uint32_t IABR[8]; /*!< Interrupt Active bit Register
uint32_t RESERVED4[56];
__IO uint8_t IP[240]; /*!< Interrupt Priority Register, 8Bit wide
uint32_t RESERVED5[644];
__O uint32_t STIR; /*!< Software Trigger Interrupt Register
} NVIC_
ISER:全称是: Interrupt Set Enable Registers ,这是一个中断使能寄存器组。有用的就是两个 ISER [0]和 ISER [1]总共可以表示 64 个中断。而 STM32F103 只用了其中的前 60 位。 ISER[0] 的 bit0~ bit31 分别对应中断 0~ 31 。 ISER[1] 的 bit0~ 27 对应中断 32~59 ;这样总共 60 个中断就分别对应上了。 你要使能某个中断,必须设置相应的 ISER 位为 1 ,使该中断被使能 这里仅仅是使能,还要配合中断分组、屏蔽、 IO 口映射等设置才算是一个完整的中断设置 。
ICER:全称是 Interrupt Clear Enable Registers ,是一个中断除能寄存器组。该寄存器组与 ISER 的作用恰好相反,是用来清除某个中断的使能的。其对应位的功能,也和 ICER 一样。这里要专门设置一个 ICER 来清除中断位,而不是向 ISER 写 0 来清除,是因为 NVIC 的这些寄存器都是写 1 有效的,写 0 是无效的。
ISPR:全称是 Interr upt Set Pending Register s ,是一个中断挂起控制寄存器组。每个位对应的中断和 ISER 是一样的。通过置 1 ,可以将正在进行的中断挂起,而执行同级或更高级别的中断。写 0 是无效的。
ICPR:全称是 Interrupt Clear Pending Register s ,是一个中断解挂控制寄存器组。其作用与 ISPR 相反,对应位也和 ISER 是一样的。通过设置 1 ,可以将挂起的中断接挂。写 0 无效。
IABR:全称是 Interrupt Active Bit Registers ,是 一个中断激活 标志位寄存器 组。对应位所代表的中断和 ISER 一样,如果为 1 ,则表示该位所对应的中断正在被执行。这是一个只读寄存器,通过它可以知道当前在执行的中断是哪一个。在中断执行完了由硬件自动清零。
IP:全称是 Interrupt Priority Registers ,是一个中断优先级控制的寄存器组。 IP 寄存器组由 240 个 8 bit 的寄存器组成,每个可屏蔽中断占用 8bit ,这样总共可以表示 240 个可屏蔽中断。 而 STM32 只用到了其中的 前 60 个 。 I P[ 59 ]~IP[0] 分别对应中断 59 ~0 。 而每个可屏蔽中断占用的 8bit 并没有全部使用,而是 只用了高 4 位。这 4 位,又分为抢占优先级和子优先级。抢占优先级在前,子优先级在后。而这两个优先级各占几个位又要根据 SCB -->AIRCR 中的 中断分组设置来决定。
第一,如果两个中断的抢占优先级和响应优先级都是一样的话,则看哪个中断先发生就先执行;
第二,高优先级的抢占优先级是可以打断正在进行的低抢占优先级中断的。而抢占优先级相同的中断,高优先级的响应优先级不可以打断低响应优先级的中断。
中断分组设置和中断优先级管理:
中断优先级分组函数NVIC_PriorityGroupConfig,这个函数的作用是对中断的优先级进行分组,这个函数在系统中只能被调用一次,一旦分组确定就最好不要更改。
void NVIC_ Priori tyGroupConfig(uint32_t NVIC_PriorityGroup);
中断初始化函数NVIC_Init
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)
typedef struct
uint8_t NVIC_IRQChannel;//:定义初始化的是哪个中断,这个我们可以在 stm32f10x.h 中找到每个中断对应的名字。例如 USART1_IRQn 。
uint8 _t NVI C_IRQChannelPreemptionPriority;//定义这个中断的抢占优先级别。
uint8_t NVIC_IRQChannelSubPriority;//定义这个中断的子优先级别。
FunctionalState NVIC_IRQChannelCmd;//该中断是否使能。
} NVIC_InitTypeDef;
中断优先级设置的步骤:
- 系统运行开始的时候设置中断分组 。 确定组号,也就是确定抢占优先级和子优先级的分配位数。 调用函数为 NVIC_PriorityGroupConfig
- 设置 所用到的中断的中断优先级别。 对每个中断调用函数为 NVIC_Init();
MDK 中寄存器地址名称映射分析
MDK 采用的方式是通过结构体来将寄存器组织在一起。
相关文章:

STM32开发基础知识入门
C语言基础 位操作 对基本类型变量可以在位级别进行操作。 1) 不改变其他位的值的状况下,对某几个位进行设值。 先对需要设置的位用&操作符进行清零操作,然后用|操作符设值。 2) 移位操作提高代码的可读性。 3) ~取反操作使用技巧 可用于对某…...

学习操作系统的必备教科书《操作系统:原理与实现》| 文末赠书4本
使用了6年的实时操作系统,是时候梳理一下它的知识点了 摘要: 本文简单介绍了博主学习操作系统的心路历程,同时还给大家总结了一下当下流行的几种实时操作系统,以及在工程中OSAL应该如何设计。希望对大家有所启发和帮助。 文章目录…...
大数据的常用算法(分类、回归分析、聚类、关联规则、神经网络方法、web数据挖掘)
在大数据时代,数据挖掘是最关键的工作。大数据的挖掘是从海量、不完全的、有噪声的、模糊的、随机的大型数据库中发现隐含在其中有价值的、潜在有用的信息和知识的过程,也是一种决策支持过程。其主要基于人工智能,机器学习,模式学…...

【数据结构】详解二叉树与堆与堆排序的关系
🌇个人主页:平凡的小苏 📚学习格言:别人可以拷贝我的模式,但不能拷贝我不断往前的激情 🛸C语言专栏:https://blog.csdn.net/vhhhbb/category_12174730.html 🚀数据结构专栏ÿ…...

【Pandas】数据分析入门
文章目录前言一、Pandas简介1.1 什么是Pandas1.2 Pandas应用二、Series结构2.1 Series简介2.2 基本使用三、DataFrame结构3.1 DataFrame简介3.2 基本使用四、Pandas-CSV4.1 CSV简介4.2 读取CSV文件4.3 数据处理五、数据清洗5.1 数据清洗的方法5.2 清洗案例总结前言 大家好&…...

【c++】:list模拟实现“任意位置插入删除我最强ƪ(˘⌣˘)ʃ“
文章目录 前言一.list的基本功能的使用二.list的模拟实现总结前言 1. list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。2. list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中࿰…...

QT表格控件实例(Table Widget 、Table View)
欢迎小伙伴的点评✨✨,相互学习🚀🚀🚀 博主🧑🧑 本着开源的精神交流Qt开发的经验、将持续更新续章,为社区贡献博主自身的开源精神👩🚀 文章目录前言一、图示实例二、列…...

第二章Vue组件化编程
文章目录模块与组件、模块化与组件化模块组件模块化组件化Vue中的组件含义非单文件组件基本使用组件注意事项使用 kebab-case使用 PascalCase组件的嵌套模板templateVueComponent一个重要的内置功能单文件组件Vue脚手架使用Vue CLI脚手架先配置环境初始化脚手架分析脚手架结构实…...

面试官:vue2和vue3的区别有哪些
目录 多根节点,fragment(碎片) Composition API reactive 函数是用来创建响应式对象 Ref toRef toRefs 去除了管道 v-model的prop 和 event 默认名称会更改 vue2写法 Vue 3写法 vue3组件需要使用v-model时的写法 其他语法 1. 创…...
【TopK问题】——用堆实现
文章目录一、TopK问题是什么二、解决方法三、时间复杂度一、TopK问题是什么 TopK问题就是从1000个数中找出前K个最大的数或者最小的数这样的类似问题。 不过并不要求这k个数字必须是有序的,如果题目有要求,则进行堆排序即可。 还有比如求出全国玩韩信…...

【Spring从成神到升仙系列 四】从源码分析 Spring 事务的来龙去脉
👏作者简介:大家好,我是爱敲代码的小黄,独角兽企业的Java开发工程师,CSDN博客专家,阿里云专家博主📕系列专栏:Java设计模式、数据结构和算法、Kafka从入门到成神、Kafka从成神到升仙…...
使用Nginx反向代理OpenAI API
由于OpenAI的API在国内无法访问,所以可以通过海外服务器利用Nginx实现反向代理。 安装Nginx 这一步就不赘述了,不同的Linux系统安装方式略有不同,根据自己的服务器的系统自行百度即可。 OpenSSL创建证书 因为OpenAI的接口是https协议的&a…...
USB键盘实现——字符串描述符(四)
字符串描述符 字符串描述符内容解析和 HID鼠标 一致。 获取字符串描述符请求 标准设备请求 typedef struct __attribute__ ((packed)){union {struct __attribute__ ((packed)) {uint8_t recipient : 5; ///< Recipient type usb_request_recipient_t.uint8_t type …...

STM32的中断
目录 一、STM32中断概述 二、外部中断控制器EXTI 三、按键中断 四、串口中断 一、STM32中断概述 处理器中的中断在处理器中,中断是一个过程,即CPU在正常执行程序的过程中,遇到外部/内部的紧急事件需要处理,暂时中止当前程序的…...

Flink进阶篇-CDC 原理、实践和优化采集到Doris中
简介 基于doris官方用doris构建实时仓库的思路,从flinkcdc到doris实时数仓的实践。 原文 Apache Flink X Apache Doris 构建极速易用的实时数仓架构 (qq.com) 前提-Flink CDC 原理、实践和优化 CDC 是什么 CDC 是变更数据捕获(Change Data Captur…...

看完这篇 教你玩转渗透测试靶机vulnhub——My File Server: 1
Vulnhub靶机My File Server: 1渗透测试详解Vulnhub靶机介绍:Vulnhub靶机下载:Vulnhub靶机安装:Vulnhub靶机漏洞详解:①:信息收集:②:FTP匿名登入:③:SMB共享服务…...

OpenHarmony实战STM32MP157开发板 “控制” Hi3861开发板 -- 中篇
一、前言 我们在 OpenHarmony实战STM32MP157开发板 “控制” Hi3861开发板 – 上篇 中介绍到了,App面板的开发,以及JS API接口的开发和调用。 那么本篇文章,会详解:BearPi-HM Nano开发板,如何实现数据上报和指令接收响应的。 看到这里,可能有同学可能已经知道思路了,因…...

【数据结构初阶】单链表
目录一、思路>>>>>>>>>>>>过程<<<<<<<<<<<<<<<1.打印2.尾插3.尾删4.头插5.头删6.查找7.指定位置后插入8.指定位置后删除9.链表的销毁二、整个程序1.SLTlist.c2.SLTlist.c一、思路 #define …...

多线程代码案例-阻塞队列
hi,大家好,今天为大家带来多线程案例--阻塞队列 这块知识点也很重要,要好好掌握呀~~~ 🌸🌸🌸🌸🌸🌸🌸🌸🌸🌸🌸🌸🌸&#x…...

mysql的limit查询竟然有坑?
背景 最近项目联调的时候发现了分页查询的一个bug,分页查询总有数据查不出来或者重复查出。 数据库一共14条记录。 如果按照一页10条。那么第一页和第二页的查询SQL和和结果如下。 .png) 那么问题来了,查询第一页和第二页的时候都出现了11,12,13的记录…...

深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...

springboot 百货中心供应链管理系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...

.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

使用分级同态加密防御梯度泄漏
抽象 联邦学习 (FL) 支持跨分布式客户端进行协作模型训练,而无需共享原始数据,这使其成为在互联和自动驾驶汽车 (CAV) 等领域保护隐私的机器学习的一种很有前途的方法。然而,最近的研究表明&…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...
浅谈不同二分算法的查找情况
二分算法原理比较简单,但是实际的算法模板却有很多,这一切都源于二分查找问题中的复杂情况和二分算法的边界处理,以下是博主对一些二分算法查找的情况分析。 需要说明的是,以下二分算法都是基于有序序列为升序有序的情况…...
基于matlab策略迭代和值迭代法的动态规划
经典的基于策略迭代和值迭代法的动态规划matlab代码,实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...

学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”
2025年#高考 将在近日拉开帷幕,#AI 监考一度冲上热搜。当AI深度融入高考,#时间同步 不再是辅助功能,而是决定AI监考系统成败的“生命线”。 AI亮相2025高考,40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕,江西、…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA
浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求,本次涉及的主要是收费汇聚交换机的配置,浪潮网络设备在高速项目很少,通…...