当前位置: 首页 > news >正文

【STM32】标准库的引入

一、为什么要会有标志外设库

1、传统单片机软件开发方式

(1)芯片厂商提供数据手册、示例代码、开发环境
(2)单片机软件工程师面向产品功能,查阅数据手册,参考官方示例代码进行开发
(3)硬件操作的方式是用C语言对寄存器进行读写以操作硬件
(4)主要工作量分2块:一是调通各种外设,二是实现产品功能
(5)在简单单片机(如51单片机)上这一套工作的很好,但是随着单片机变复杂就带来一些问题

2、外设库有什么价值

(1)外设库其实就是以前芯片公司提供的示例代码的标准化产物
(2)外设库简化了我们开发产品的2大工作量的第一个
(3)外设库以源码方式提供,这个源码本身写的很标准,可以用作学习素材

3、学习和使用外设库的难点

(1)要有规范化编程的意识和能力
(2)C语言功底要过关
(3)要有一定的框架和层次认识
(4)要会没有外设库时直接C语言操作寄存器的方式(看原理图、查数据手册、位操作等)

二、外设库的结构介绍和之后的学习方法

1.外设库的结构介绍

(1)最新版本库的下载和解压

官方网站:STM32标准外设软件库: 相关产品

(2)建立SourceInsight工程

1)先在盘符中建立一个文件夹,然后再sourceInsight中打开这个文件夹

(3)文件夹结构和主要文件的作用

1.Project

2.Libraries

CMSIS(STM32内部ARM核心相关内容)
    CM3(Cortex-M3)
        CoreSupport
            内核相关的一些设置的寄存器集合及其封装


        DeviceSupport
            ST
                STM32F10x
                    startup(起始文件)

https://www.cnblogs.com/amanlikethis/p/3989989.html
                    stm32f10x.h【STM32常见数据结构的封装】
                    system_stm32f10x.c
                    system_stm32f10x.h


STM32F10x_StdPeriph_Driver(外设驱动)
    inc(include,头文件,.h)
    src(source,源文件, .c)

2.system_stm32f10x.c

在这个文件中定义了2个函数和一个全局变量:时钟相关的

3、后续的学习方法

(1)先搞清楚库对STM32这个硬件的封装和表达方式【对外设进行封装】
(2)再彻底理解库中使用的结构体式访问硬件寄存器的方式
(3)初步建立起面向对象式编程的概念并且去体会
(4)以模块为单位去研究这个模块的库函数,并且用库函数去编程,并且实验结果,并且分析代码,去体会去熟悉库函数使用的方法
(5)最终达到什么程度?眼里有库心中无库。用人话说就是:思维能够穿透库函数直达内部对寄存器的操作。

三、标准库对硬件信息的封装方法

1.寄存器地址的封装

1.手动操作寄存器地址

2.库文件中的寄存器地址(stm32f10x.h)

2.寄存器位定义的封装

1.直接通过移位操作位寄存器

2.使用宏定义进行位寄存器

不用直接写数字,而使用宏定义

3.外设操作的封装

1.自定义函数

2.使用库函数

.c文件对其进行封装

四、使用结构体方式访问寄存器的原理

1.最原始的方法

1)C语言访问寄存器的本质是c语言访问内存,本质思路是:

定义一个指针指向这块内存,然后*p=xx这种方式去解引用指针从而向没有标内存中写入内容。

2)缺陷:当寄存器多了之后每一个寄存器都要定义一套套路,很麻烦

3)解决思路:就是打包,批发式定义,用结构体(为什么不用数组)的方式来进行打包。具体方法:把整个模块的所有寄存器(地址是连续的)打包在一个结构体中,每一个寄存器对应结构体中的一个元素,然后结构体基地址对应寄存器组的基地址,将来就可以通过结构体的各个元素来访问各个寄存器了。

2.使用结构体

结构体方式来访问寄存器和指针式访问寄存器,本质上其实是一样的,区别是c语言的封装不同。

TIM的

GPIO的

五、使用结构体方式访问寄存器的实践

1.原始方式

gpio.h

#define GPIOB_CRH		0x40010C04
#define GPIOB_CRL		0x40010C00
#define GPIOB_ODR		0x40010C0C
#define GPIOB_BSRR	0x40010C10
#define GPIOB_BRR		0x40010C14#define RCC_APB2ENR		0x40021018#define rGPIOB_CRH 		(*((unsigned int *)GPIOB_CRH))
#define rGPIOB_ODR 		(*((unsigned int *)GPIOB_ODR))
#define rGPIOB_BSRR 	(*((unsigned int *)GPIOB_BSRR))
#define rGPIOB_BRR 		(*((unsigned int *)GPIOB_BRR))
#define rRCC_APB2ENR 	(*((unsigned int *)RCC_APB2ENR))void led_flash(void);void led_init();
void delay();

gpio.c

/**点亮led灯
*/#include "gpio.h"void delay(){unsigned int i=0,j=0;for(i=0;i<1000;i++){for(j=0;j<4000;j++){}}
}void led_init(){rRCC_APB2ENR = 0x00000008;rGPIOB_CRH = 0x33333333;rGPIOB_ODR = 0x0000aa00;//全灭}
void led_flash(void){unsigned int i=0;for(i=0;i<3;i++){rGPIOB_ODR = 0x00000000;//全亮delay();rGPIOB_ODR = 0x0000ff00;//全灭delay();} 
}
void main(void){led_init();led_flash();
}

2.使用结构体的方式对寄存器访问

注意点:

我们在定义相关寄存器的结构体的时候要注意顺序问题,一定要按照寄存器偏移量从低到高,要不然会出现问题。

3.两者对比

代码

gpio.h

#define GPIOB_BASE		0x40010C00
#define GPIOC_BASE		0x40011000#define GPIOB_CRH		(GPIOB_BASE + 0x04)
#define GPIOB_ODR		(GPIOB_BASE + 0x0C)
#define GPIOB_BSRR		(GPIOB_BASE + 0x10)
#define GPIOB_BRR		(GPIOB_BASE + 0x14)#define GPIOC_CRL		(GPIOC_BASE + 0x00)
#define GPIOC_ODR		(GPIOC_BASE + 0x0C)
#define GPIOC_BSRR		(GPIOC_BASE + 0x10)
#define GPIOC_BRR		(GPIOC_BASE + 0x14)#define RCC_APB2ENR		0x40021018//-------------------------------------------------#define rGPIOB_CRH 		(*((unsigned int *)GPIOB_CRH))
#define rGPIOB_ODR 		(*((unsigned int *)GPIOB_ODR))
#define rGPIOB_BSRR 	(*((unsigned int *)GPIOB_BSRR))
#define rGPIOB_BRR 		(*((unsigned int *)GPIOB_BRR))#define rGPIOC_CRL 		(*((unsigned int *)GPIOC_CRL))
#define rGPIOC_ODR 		(*((unsigned int *)GPIOC_ODR))
#define rGPIOC_BSRR 	(*((unsigned int *)GPIOC_BSRR))
#define rGPIOC_BRR 		(*((unsigned int *)GPIOC_BRR))#define rRCC_APB2ENR 	(*((unsigned int *)RCC_APB2ENR))//用结构体的方式对寄存器访问
typedef struct{unsigned int CRL;unsigned int CRH;unsigned int IDR;unsigned int ODR;unsigned int BSRR;unsigned int BRR;unsigned int LCKR;
}GPIO_Typedef;void led_flash(void);void led_init();
void delay();

gpio.c

/**点亮led灯
*/#include "gpio.h"void delay(){unsigned int i=0,j=0;for(i=0;i<1000;i++){for(j=0;j<4000;j++){}}
}/*
原始方法
void led_init(){rRCC_APB2ENR = 0x00000008;rGPIOB_CRH = 0x33333333;rGPIOB_ODR = 0x0000aa00;//隔一个亮一个}
void led_flash(void){unsigned int i=0;for(i=0;i<3;i++){rGPIOB_ODR = 0x00000000;//全亮delay();rGPIOB_ODR = 0x0000ff00;//全灭delay();} 
}
*/void led_init(){GPIO_Typedef *p=(GPIO_Typedef *)GPIOB_BASE;//因为RCC部分还没有定义结构体,所以还是按照原来的方式去操作rRCC_APB2ENR = 0x00000008;//结构体只能使用【->】p->CRH=0x33333333;p->ODR=0x0000aa00;
}
void led_flash(void){GPIO_Typedef *p=(GPIO_Typedef *)GPIOB_BASE;unsigned int i=0;for(i=0;i<3;i++){p->ODR = 0x00000000;//全亮delay();p->ODR = 0x0000ff00;//全灭delay();} 
}void main(void){led_init();led_flash();
}

4.小技巧

1.将基地址指针作为全局变量

因为在每一个函数开始之前,都要使用到基地址

2.结构体元素填充

我们前面提到说,在定义结构体的时候一定一定要按照寄存器的偏移量从小到大的顺序定义要不然出错,但是我们在一些地方可能空缺出来,没有寄存器,所以我们需要一个占位,将其补充,要不然后面的其他寄存器可能受到影响。

3.寄存器可操作位数不同

我们在学习RCC时钟的时候遇到一些寄存器可以操作32位,但是有一些只能操作16位。此时我们可以将其直接写入(不用管是否用足32位),也可以分成2个16位写入。

//用结构体的方式对寄存器访问
typedef struct{unsigned int CRL;unsigned int CRH;//unsigned int IDR;//将32位的IDR分为2个16位unsigned short IDR;unsigned short paddingIDR;//此16位用不到unsigned int ODR;unsigned int BSRR;unsigned int BRR;unsigned int LCKR;
}GPIO_Typedef;

六、使用标准库重写LED的程序

1.分析标准库自带的文件模板

1.完整目录

2.User,Driver

3.CMSIS.startup

4.配置注意点:

2.stm32f10x.h

选择芯片类型

在“stm32f10x.h”有可以查看,要修改可以在options--》c/c++中进行修改宏定义

2.宏定义的设置

3.外部晶振时钟设置

3.stm32f10x_conf.h

1.包含所有外设的头文件

这个头文件是标准库的模板中的,将所有需要使用到的头文件包含进去

所以在整个工程中,无论我们创建一个什么类型的.c文件,只要我们定义了

【“stm32f10x.h”】

则就等价于将所有的外设器件的.h文件包含进来了

2.assert_param(断言机制)

4.正式自己搭建文件目录

1.文件结构

2.文件导入

1.startup

2.CMSIS

3.stdperiph_driver

4.user

3.配置

自定义宏定义,在stm32f10x.h,stm32f10_conf.h文件中查找

4.出现问题

将配置中的”断言“去除

5.代码修改

#include "stm32f10x.h"/**使用标准库重写LED的程序
*//*
//原始代码
void led_init(){//GPIO_Typedef *p=(GPIO_Typedef *)GPIOB_BASE;//因为RCC部分还没有定义结构体,所以还是按照原来的方式去操作rRCC_APB2ENR = 0x00000008;//结构体只能使用【->】//p->CRH=0x33333333;pGPIOB->CRH=0x33333333;//p->ODR=0x0000aa00;pGPIOB->ODR=0x0000aa00;
}
*///第一步:先去”stm32f10x.h"文件中查找相关的寄存器
//				比如RCC,GPIO
//第二步:找到相关的寄存器的宏定义,将其直接复制过来//使用HAL库
void led_init(){//GPIO_Typedef *p=(GPIO_Typedef *)GPIOB_BASE;//因为RCC部分还没有定义结构体,所以还是按照原来的方式去操作RCC->APB2ENR = 0x00000008;//结构体只能使用【->】//p->CRH=0x33333333;GPIOB->CRH=0x33333333;//p->ODR=0x0000aa00;GPIOB->ODR=0x0000aa00;
}int main(){led_init();return 0;
}

七、RCC模块的标准库全解析

【STM32】RCC时钟模块(使用HAL库)-CSDN博客

八、CPIO模块的标准库全解析

【STM32】GPIO控制LED(HAL库版)-CSDN博客

九、标准库中的面向对象思想

1、面向对象介绍

(1)一种编程思想(面向过程、面向对象)
(2)什么是对象
(3)面向对象三大特征:封装、继承、多态
(4)面向对象编程思想和面向对象语言是两码事

2、标准库的面向对象特征

(1)各种数据类型结构体就是一种封装
(2)标准库是为了被复用
(3)GPIO的编程模式是典型的面向对象式编程

典型面向对象的编程模式:

第1步:先构建对象(可以理解为定义一个结构体类型)
第2步:用对象构造实例(可以理解为用结构体类型来定义结构体变量)malloc
第3步:填充实例(其实就是给结构体的各个元素赋值)
第4步:使用实例(其实就是把结构体变量作为参数传给某个函数使用)
第5步:销毁实例(其实就是把前面第2步定义的机构体变量给销毁掉)free

相关文章:

【STM32】标准库的引入

一、为什么要会有标志外设库 1、传统单片机软件开发方式 (1)芯片厂商提供数据手册、示例代码、开发环境 (2)单片机软件工程师面向产品功能&#xff0c;查阅数据手册&#xff0c;参考官方示例代码进行开发 (3)硬件操作的方式是用C语言对寄存器进行读写以操作硬件 (4)主要工作量…...

Redis的淘汰策略

Redis是一种基于内存的高性能键值存储数据库&#xff0c;由于内存资源有限&#xff0c;当Redis中的数据量增大时&#xff0c;会导致内存占用过多&#xff0c;可能会影响系统的性能和稳定性。为了解决这个问题&#xff0c;Redis提供了一些淘汰策略来自动清理不再使用的key&#…...

Linux友人帐之日志与备份

一、日志 1.1概述 日志文件是重要的系统信息文件&#xff0c;其中记录了许多重要的系统事件&#xff0c;包括用户的登录信息、系统的启动信息、系统的安全信息、邮件相关信息、各种服务相关信息等。日志对于安全来说也很重要&#xff0c;它记录了系统每天发生的各种事情&#…...

git中如何在父仓库提交子仓库的修改

子仓库在父仓库中进行了修改&#xff0c;你需要按照以下步骤提交子仓库的修改&#xff1a; 切换到子仓库目录&#xff1a;使用cd命令进入子仓库所在的目录。拉取子仓库的最新更改&#xff1a;使用git pull命令拉取子仓库的最新更改&#xff0c;确保你的本地是最新的版本。提交…...

【【萌新的SOC学习之SD卡DMA回路读写大数据的实验】】

萌新的SOC学习之SD卡读写大数据的实验 记得先设定 FIFO 的位宽和深度 还有DMA 的大小 其他基本结构设计参照上一个SD卡读写小数据的实验 #include "xparameters.h" //包含vivado所导出的信息包含vivado的基地址 #include "xil_printf.h" //调用打印函…...

在k8s中 ,数据包是怎么从外部流转进入到pod的?

在 Kubernetes 中&#xff0c;当您创建 NodePort 类型的服务时&#xff0c;流量不会直接从主机的 IP 和端口转发到特定 Pod 的 IP 和端口。相反&#xff0c;流量被转发到集群中的一个节点&#xff0c;然后从那里转发到相应的 Pod。 1、当您创建 NodePort 类型的服务时&#xf…...

微信小程序设置 wx.showModal 提示框中 确定和取消按钮的颜色

wx官方提供的 showModal 无疑是个非常优秀的选择提示工具 但是 我们还可以让他的颜色更贴近整体的小程序风格 cancelColor 可以改变取消按钮的颜色 confirmColor 则可以控制确定按钮的颜色 参考代码如下 wx.showModal({cancelColor: #0000FF,confirmColor: #45B250,content:…...

【Chrome】使用k8s、docker部署无头浏览器Headless,Java调用示例

什么是无头浏览器&#xff1f; 无头浏览器是一种没有图形用户界面的浏览器。无头浏览器不通过其图形用户界面(GUI)控制浏览器的操作&#xff0c;而是使用命令行。 为什么要用Chrome无头&#xff1f; Chrome Headless用于抓取(谷歌)、测试(开发者)和黑客(黑客)。搜索引擎&…...

springmvc http请求,支持get,post,附件传输和参数传输

主要解决http请求支持get,post,put,delete等常规方法&#xff0c;支持RequestParam,RequestBody,PathVariable等参数格式传输&#xff0c;支持传输附件同时传递参数等&#xff0c;主体代码如下&#xff1a; package mes.client.action;import cn.hutool.crypto.digest.DigestUt…...

linux性能分析(七)CPU性能篇(二)怎么理解平均负载

一 怎么理解平均负载 ① 如何查看平均复杂 查看系统负载的命令&#xff1a; top、uptime、w、cat /proc/loadavg、tload /proc/loadavg 思考&#xff1a; uptime每列输出的含义?重点&#xff1a; 当前时间、系统运行时间、正在登录用户数、平均负载 ② 思考&#xff1…...

PostgreSQL12中浮点数输出算法优化带来的小问题

最近碰到同事发来这样两个SQL&#xff0c;开发反馈输出的结果异常。 bill# select 0.1284*100::float;?column? --------------------12.839999999999998 (1 row)bill# select (0.1284*100)::float;float8 --------12.84 (1 row) 乍一看其实能看出明显的区别&#xff0c;由于…...

Hive安装配置笔记

版本说明 hadoop-3.3.6&#xff08;已安装&#xff09; mysql-8&#xff08;已安装&#xff09; hive-3.1.3 将hive解压到对应目录后做如下配置&#xff1a; 基本配置与操作 1、hive-site <configuration><!-- jdbc连接的URL --><property><name>ja…...

前端数据可视化之【Echarts下载使用】

目录 &#x1f31f;下载&#x1f31f;浏览器引入&#x1f31f;模块化引入 &#x1f31f;使用&#x1f31f;基本使用步骤 &#x1f31f;绘制一个简单的图表&#x1f31f;写在最后 &#x1f31f;下载 &#x1f31f;浏览器引入 官网下载界面&#xff1a;官方网站 或 Echarts中文…...

本机计算机上的mysql启动后停止

本机计算机上的mysql启动后停止 原因&#xff1a;mysql5.0和mysql8.0配置不同 把my.ini改成以下设置然后再重新 mysqld --initialize-insecure --usermysql然后再启动 net start mysqlmysql8.0 下面的路劲可自定义 [client] default-character-setutf8 [mysql] default-cha…...

Java中ReentrantLock测试线程的安全

使用场景 当需要在多线程环境下保证共享资源的安全访问时&#xff0c;可以使用Java中的ReentrantLock来实现线程安全。ReentrantLock是一个可重入的互斥锁&#xff0c;它提供了与synchronized关键字类似的功能&#xff0c;但更加灵活和扩展性强。 下面是一个使用ReentrantLoc…...

Vue-dvadmin-d2-crud-plus-常用配置-row-handle-columns-options

文章目录 1.row-handle columnHeader width minWidth fixed align renderHeader edit view remove remove.confirm remove.confirmTitle remove.confirmText custom 范例1 范例2 2.columns title key width minWidth fixed renderHeader sortable sortMethod sortBy sortOrders…...

【OpenCV实现图像的算数运算,性能测试和优化,改变颜色空间】

文章目录 OpenCV功能概要图像的算数运算性能测试和优化改变颜色空间对象追踪 OpenCV功能概要 OpenCV&#xff08;Open Source Computer Vision Library&#xff09;是一个开源的计算机视觉和机器学习库&#xff0c;提供了丰富的图像处理和计算机视觉算法。它支持多种编程语言&…...

多级缓存入门

文章目录 什么是多级缓存JVM进程缓存环境准备安装MySQL导入Demo工程导入商品查询页面 初识Caffeine Lua语法初识Lua第一个lua程序变量和循环Lua的数据类型声明变量循环 条件控制、函数函数条件控制 多级缓存安装OpenRestyOpenResty快速入门反向代理流程OpenResty监听请求编写it…...

CentOS卸载LVM磁盘的方法

在客户环境上遇到一个问题&#xff0c;本身的磁盘满了&#xff0c;需要把没有用的lvm逻辑卷卸载掉&#xff0c;然后挂上去&#xff0c;下面记录一下过程。 卸载原磁盘 umount /data # 如果/data目录正在被其他进程使用中&#xff0c;则使用fuser强制关闭&#xff0c;然后Umou…...

ChatGPT:Spring Boot和Maven——Java应用开发的关键工具和区别

ChatGPT&#xff1a;Spring Boot和Maven——Java应用开发的关键工具和区别 Springboot是什么&#xff1f; ChatGPT&#xff1a; Spring Boot是一个用于构建Java应用程序的开源框架&#xff0c;它是Spring Framework的一部分&#xff0c;但旨在简化Spring应用程序的开发。Sprin…...

谷歌浏览器插件

项目中有时候会用到插件 sync-cookie-extension1.0.0&#xff1a;开发环境同步测试 cookie 至 localhost&#xff0c;便于本地请求服务携带 cookie 参考地址&#xff1a;https://juejin.cn/post/7139354571712757767 里面有源码下载下来&#xff0c;加在到扩展即可使用FeHelp…...

零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?

一、核心优势&#xff1a;专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发&#xff0c;是一款收费低廉但功能全面的Windows NAS工具&#xff0c;主打“无学习成本部署” 。与其他NAS软件相比&#xff0c;其优势在于&#xff1a; 无需硬件改造&#xff1a;将任意W…...

VB.net复制Ntag213卡写入UID

本示例使用的发卡器&#xff1a;https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器

一.自适应梯度算法Adagrad概述 Adagrad&#xff08;Adaptive Gradient Algorithm&#xff09;是一种自适应学习率的优化算法&#xff0c;由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率&#xff0c;适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

Oracle查询表空间大小

1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

3.3.1_1 检错编码(奇偶校验码)

从这节课开始&#xff0c;我们会探讨数据链路层的差错控制功能&#xff0c;差错控制功能的主要目标是要发现并且解决一个帧内部的位错误&#xff0c;我们需要使用特殊的编码技术去发现帧内部的位错误&#xff0c;当我们发现位错误之后&#xff0c;通常来说有两种解决方案。第一…...

解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错

出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上&#xff0c;所以报错&#xff0c;到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本&#xff0c;cu、torch、cp 的版本一定要对…...

select、poll、epoll 与 Reactor 模式

在高并发网络编程领域&#xff0c;高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表&#xff0c;以及基于它们实现的 Reactor 模式&#xff0c;为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。​ 一、I…...

css3笔记 (1) 自用

outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size&#xff1a;0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格&#xff…...

2023赣州旅游投资集团

单选题 1.“不登高山&#xff0c;不知天之高也&#xff1b;不临深溪&#xff0c;不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...