当前位置: 首页 > 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…...

【Oracle APEX开发小技巧12】

有如下需求&#xff1a; 有一个问题反馈页面&#xff0c;要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据&#xff0c;方便管理员及时处理反馈。 我的方法&#xff1a;直接将逻辑写在SQL中&#xff0c;这样可以直接在页面展示 完整代码&#xff1a; SELECTSF.FE…...

Opencv中的addweighted函数

一.addweighted函数作用 addweighted&#xff08;&#xff09;是OpenCV库中用于图像处理的函数&#xff0c;主要功能是将两个输入图像&#xff08;尺寸和类型相同&#xff09;按照指定的权重进行加权叠加&#xff08;图像融合&#xff09;&#xff0c;并添加一个标量值&#x…...

vue3 字体颜色设置的多种方式

在Vue 3中设置字体颜色可以通过多种方式实现&#xff0c;这取决于你是想在组件内部直接设置&#xff0c;还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法&#xff1a; 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...

CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云

目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...

Android15默认授权浮窗权限

我们经常有那种需求&#xff0c;客户需要定制的apk集成在ROM中&#xff0c;并且默认授予其【显示在其他应用的上层】权限&#xff0c;也就是我们常说的浮窗权限&#xff0c;那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...

Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理

引言 Bitmap&#xff08;位图&#xff09;是Android应用内存占用的“头号杀手”。一张1080P&#xff08;1920x1080&#xff09;的图片以ARGB_8888格式加载时&#xff0c;内存占用高达8MB&#xff08;192010804字节&#xff09;。据统计&#xff0c;超过60%的应用OOM崩溃与Bitm…...

SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)

上一章用到了V2 的概念&#xff0c;其实 Fiori当中还有 V4&#xff0c;咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务)&#xff0c;代理中间件&#xff08;ui5-middleware-simpleproxy&#xff09;-CSDN博客…...

动态 Web 开发技术入门篇

一、HTTP 协议核心 1.1 HTTP 基础 协议全称 &#xff1a;HyperText Transfer Protocol&#xff08;超文本传输协议&#xff09; 默认端口 &#xff1a;HTTP 使用 80 端口&#xff0c;HTTPS 使用 443 端口。 请求方法 &#xff1a; GET &#xff1a;用于获取资源&#xff0c;…...

莫兰迪高级灰总结计划简约商务通用PPT模版

莫兰迪高级灰总结计划简约商务通用PPT模版&#xff0c;莫兰迪调色板清新简约工作汇报PPT模版&#xff0c;莫兰迪时尚风极简设计PPT模版&#xff0c;大学生毕业论文答辩PPT模版&#xff0c;莫兰迪配色总结计划简约商务通用PPT模版&#xff0c;莫兰迪商务汇报PPT模版&#xff0c;…...

RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill

视觉语言模型&#xff08;Vision-Language Models, VLMs&#xff09;&#xff0c;为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展&#xff0c;机器人仍难以胜任复杂的长时程任务&#xff08;如家具装配&#xff09;&#xff0c;主要受限于人…...