[野火]STM32 F103 HAL库开发实战指南笔记之简单外设总结

news2025/7/11 18:26:01

1、GPIO编程总结

  1. 使能 GPIO 端口时钟;
  2. 初始化 GPIO 目标引脚为推挽输出模式;
  3. 编写简单测试程序,控制 GPIO 引脚输出高、低电平。
    这部分宏控制 LED 亮灭的操作是直接向 BSRR 寄存器写入控制指令来实现的,对 BSRR 低 16 位 写 1 输出高电平,对 BSRR 高 16 位写 1 输出低电平,对 ODR 寄存器某位进行异或操作可反转位
    的状态。
    HAL_GPIO_Init 函数向寄存器写入参数,完成 GPIO 的初始化。
    所有程序都必须设置好系统的时钟再进行其他操作。
    库自带基于滴答时钟延时 HAL_Delay 单位为 ms,直接调用即可。
    __HAL_RCC_GPIOB_CLK_ENABLE() 开始GPIOB外设时钟。
    SystemInit 函数在 STM32 HAL 库的“system_stm32f1xx.c”文件中定义了,而我们的工程已经包含该文
    件。
    “assert_param”实际是一个宏,在库函数中它用于检查输入参数是否符合要求,若不符合要求则执行某个函数输出警告。
    这段代码的意思是,假如我们不定义“USE_FULL_ASSERT”宏,那么“assert_param”就是一个
    空的宏 (#else 与 #endif 之间的语句生效),没有任何操作。从而所有库函数中的 assert_param 实际
    上都无意义,我们就当看不见好了。
    假如我们定义了“USE_FULL_ASSERT”宏,那么“assert_param”就是一个有操作的语句 (#if 与
    #else 之间的语句生效),该宏对参数 expr 使用 C 语言中的问号表达式进行判断,若 expr 值为
    真,则无操作 (void 0),若表达式的值为假,则调用“assert_failed”函数,且该函数的输入参数为
    FILE”及“LINE”,这两个参数分别代表“assert_param”宏被调用时所在的“文件名”
    及“行号”。

    但库文件只对“assert_failed”写了函数声明,没有写函数定义,实际用时需要用户来定义,我们
    一般会用 printf 函数来输出这些信息,
    %p打印的是指针的地址,%s打印的是指针指向的值。
    #include<stdio.h>

char a[] = “Hello World”;
void test(char* b)
{
printf(“%p\n”,b);
printf(“%p\n”,&b);
}

int main()
{
printf(“%p\n”,a);
printf(“%p\n”,&a[0]);
printf(“%p\n”,&a);
test(a);
return 0;
}

2、这 是 一 种 名 为 “Doxygen” 的 注 释 规 范, 如 果 在 工 程 文 件 中 按 照 这 种 规 范 去 注 释, 可以使用 Doxygen 软件自动根据注释生成帮助文档。我们所说非常重要的库帮助文档
《STM32F103xx_User_Manual.chm》,就是由该软件根据库文件的注释生成的。关于 Doxygen 注
释规范本教程不作讲解。
3、#ifndef __LED_H
#define __LED_H
/* 此处省略头文件的具体内容 /
#endif /
end of __LED_H */
在头文件的开头,使用“#ifndef”关键字,判断标号“__LED_H”是否被定义,若没有被定义,则从
“#ifndef”至“#endif”关键字之间的内容都有效,也就是说,这个头文件若被其它文件“#include”,
它就会被包含到其该文件中了,且头文件中紧接着使用“#define”关键字定义上面判断的标号
“__LED_H”。当这个头文件被同一个文件第二次“#include”包含的时候,由于有了第一次包含中
的“#define __LED_H”定义,这时再判断“#ifndef __LED_H”,判断的结果就是假了,从“#ifndef”至加粗样式“#endif”之间的内容都无效,从而防止了同一个头文件被包含多次,编译时就不会出现“redefine
(重复定义)”的错误了。
一般来说,我们不会直接在 C 的源文件写两个“#include”来包含同一个头文件,但可能因为头文
件内部的包含导致重复,这种代码主要是避免这样的问题。如“bsp_led.h”文件中使用了“#include
“stm32F103xx.h””语句,按习惯,可能我们写主程序的时候会在 main 文件写“#include“bsp_led.h” 及 #include“stm32F103xx.h””,这个时候“stm32F103xx.h”文件就被包含两次了,如果没有这种
机制,就会出错。
至于为什么要用两个下划线来定义“__LED_H”标号,其实这只是防止它与其它普通宏定义
重复了,如我们用“GPIO_PIN_0”来代替这个判断标号,就会因为 stm32F103xx.h 已经定义了
GPIO_PIN_0,结果导致“bsp_led.h”文件无效了,“bsp_led.h”文件一次都没被包含。
4、GPIO 输入—按键检测
按键机械触点断开、闭合时,由于触点的弹性作用,按键开关不会马上稳定接通或一下子断开,
使用按键时会产生图 13_1 中的带波纹信号,需要用软件消抖处理滤波,不方便输入检测。本实
验板连接的按键带硬件消抖功能,见图 13_2a 和图 13_2b,它利用电容充放电的延时,消除了波
纹,从而简化软件的处理,软件只需要直接检测引脚的电平即可。
从按键的原理图可知,这些按键在没有被按下的时候,GPIO 引脚的输入状态为低电平 (按键所在
的电路不通,引脚接地),当按键按下时,GPIO 引脚的输入状态为高电平 (按键所在的电路导通,
引脚接到电源)。只要我们检测引脚的输入电平,即可判断按键是否被按下。
编程要点

  1. 使能 GPIO 端口时钟;
  2. 初始化 GPIO 目标引脚为输入模式 (浮空输入);
  3. 编写简单测试程序,检测按键的状态,实现按键控制 LED 灯。
    在这里我们定义了一个 Key_Scan 函数用于扫描指定按键的状态。GPIO 引脚的输入电平可通过读
    取 IDR 寄存器对应的数据位来感知,而 STM32 HAL 库提供了库函数 HAL_GPIO_ReadPin 来获取
    位状态,该函数输入 GPIO 端口及引脚号,函数返回该引脚的电平状态,高电平返回 1,低电平
    返回 0。Key_Scan 函数中以 HAL_GPIO_ReadPin 的返回值与自定义的宏“KEY_ON”对比,若检
    测到按键按下,则使用 while 循环持续检测按键状态,直到按键释放,按键释放后 Key_Scan 函数
    返回一个“KEY_ON”值;若没有检测到按键按下,则函数直接返回“KEY_OFF”。若按键的硬
    件没有做消抖处理,需要在这个 Key_Scan 函数中做软件滤波,防止波纹抖动引起误触发。
    5、启动文件简介
    启动文件由汇编编写,是系统上电复位后第一个执行的程序。主要做了以下工作:
  4. 初始化堆栈指针 SP(__initial_sp)
  5. 初始化 PC 指针(Reset_Handler)
  6. 初始化中断向量表(__Vectors)
  7. 配置系统时钟(SystemInit)
  8. 调用 C 库函数 _main 初始化用户堆栈,从而最终调用 main 函数去到 C 的世界。
    启动文件使用的 ARM 汇编指令汇总
    IF,ELSE,ENDIF 汇编条件分支语句,跟 C 语言的 if else 类似
    在这里插入图片描述
    栈的作用是用于局部变量,函数调用,函数形参等的开销,栈的大小不能超过内部 SRAM 的大
    小。如果编写的程序比较大,定义的局部变量很多,那么就需要修改栈的大小。如果某一天,你
    写的程序出现了莫名奇怪的错误,并进入了硬 fault 的时候,这时你就要考虑下是不是栈不够大,
    溢出了。栈是由高向低生长的。
    堆主要用来动态内存的分配,像 malloc() 函数申请的内存就在堆上面。这个在 STM32 里面用的
    比较少。堆是由低向高生长的,跟栈的生长方向相反。
    在这里插入图片描述
    6、中断服务程序
    在启动文件里面已经帮我们写好所有中断的中断服务函数,跟我们平时写的中断服务函数不一
    样的就是这些函数都是空的,真正的中断复服务程序需要我们在外部的 C 文件里面重新实现,这
    里只是提前占了一个位置而已。
    如果我们在使用某个外设的时候,开启了某个中断,但是又忘记编写配套的中断服务程序或者函
    数名写错,那当中断来临的时,程序就会跳转到启动文件预先写好的空的中断服务程序中,并且
    在这个空函数中无线循环,即程序就死在这里。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/5611.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

大学生静态HTML网页源码 我的校园网页设计成品 学校班级网页制作模板 web课程设计 dreamweaver网页作业

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

从0实现线性回归

编码题&#xff1a; 按要求完成下面的内容 1请用python完成从0实现线性回归&#xff0c;尝试使用不同的训练参数&#xff08;学习率&#xff0c;迭代次数&#xff09;&#xff0c; 以及不同的评价方法&#xff08;MSE,MAE,RMSE,R2&#xff09;等。 2比较说明sklearn的线性模…

断言(assert)的用法

参考&#xff1a;https://www.runoob.com/w3cnote/c-assert.html 目录作用总结与注意事项Demo作用 assert 是个宏&#xff0c;并且作用并非"报错"。 assert() 的用法像是一种"契约式编程"&#xff0c;程序满足我的假设条件&#xff0c;才能正常良好的运作…

做视频素材资源(free视频,音频,图片)

素材资源 一、视频 Videezy &#xff1a;https://www.videezy.com/ Videovo&#xff1a;https://www.videvo.net/ mixkit&#xff1a;https://mixkit.co/&#xff0c;可以 distill&#xff1a;https://wedistill.io/ splitshire&#xff1a;https://www.splitshire.com/ pixa…

Mysql常见指令以及用法(保姆级)

文章目录基础篇通用语法及分类DDL&#xff08;数据定义语言&#xff09;数据库操作注意事项表操作DML&#xff08;数据操作语言&#xff09;添加数据注意事项更新和删除数据DQL&#xff08;数据查询语言&#xff09;基础查询条件查询聚合查询&#xff08;聚合函数&#xff09;分…

前端性能-首次加载优化70%

前言 本篇文章&#xff0c;我们来总结归纳下万恶的this以及衍生出来的call/apply/bind对this进行绑定&#xff0c;想了很久&#xff0c;决定用实例演示的方式来讲解this&#xff0c;这样才能够理解this&#xff0c;因为this确实变化莫测&#xff0c;只靠概念&#xff0c;是不能…

【JS 构造|原型|原型链|继承(圣杯模式)|ES6类语法】下篇

⌚️⌚️⌚️个人格言&#xff1a;时间是亳不留情的&#xff0c;它真使人在自己制造的镜子里照见自己的真相! &#x1f4d6;Git专栏&#xff1a;&#x1f4d1;Git篇&#x1f525;&#x1f525;&#x1f525; &#x1f4d6;JavaScript专栏&#xff1a;&#x1f4d1;js实用技巧篇…

【数据结构】带头双向循环链表基本操作的实现(C语言)

&#x1f680; 作者简介&#xff1a;一名在后端领域学习&#xff0c;并渴望能够学有所成的追梦人。 &#x1f40c; 个人主页&#xff1a;蜗牛牛啊 &#x1f525; 系列专栏&#xff1a;&#x1f6f9;初出茅庐C语言、&#x1f6f4;数据结构 &#x1f4d5; 学习格言&#xff1a;博…

峰会实录 | StarRocks PMC Chair 赵纯:数据分析的极速统一3.0 时代

作者&#xff1a;StarRocks PMC Chair 赵纯&#xff08;本文为作者在 StarRocks Summit Asia 2022 上的分享&#xff09; 一年前&#xff0c;StarRocks 源码开放&#xff0c;StarRocks 社区也正式成立。经过一年发展&#xff0c;社区已经获得了 3400 个 Star&#xff0c;7500 …

如何用windows上架ios到苹果商城

1.苹果账号 1.你需要申请苹果账号 官网有提示&#xff1a;Sign In - Apple 2.登录 登录后店家 account&#xff0c;进入account。 点击证书&#xff0c;进入。 2.开始上架步骤 1.注册标识符&#xff08;Bundle ID&#xff09; 进入这个界面后&#xff0c;点击 Identifiers …

Elasticsearch快照备份

目录 1、Repositories 1、配置路径 2、注册快照存储库 2、查看注册的库 3、创建快照 1、为全部索引创建快照 2、为指定索引创建快照 4、查看备份完成的列表 5、删除快照 6、从快照恢复 1、恢复指定索引 2、恢复所有索引&#xff08;除.开头的系统索引&#xff09; …

【Redis】 数据结构:Redis对象与编码(底层结构)对应关系详解

【Redis】 数据结构&#xff1a;Redis对象与编码(底层结构)对应关系详解 文章目录【Redis】 数据结构&#xff1a;Redis对象与编码(底层结构)对应关系详解Redis对象与编码(底层结构)对应关系引入Redis数据结构-RedisObjectredisObject数据结构Redis的编码方式五种数据结构Redis…

2022年深信服杯四川省大学生信息安全技术大赛-CTF-Reverse复现(部分)

Rush B 开始先设置一下数字以16进制格式显示 看主函数 __int64 __fastcall main(int a1, char **a2, char **a3) {int v3; // eaxsize_t v4; // raxint v5; // ecxchar v6; // alint v7; // ecxint v9; // [rsp3Ch] [rbp-404h]char s[1000]; // [rsp40h] [rbp-400h] BYREFchar …

免杀技术(详细)

恶意软件 ● 病毒、木马、蠕虫、键盘记录、僵尸程序、流氓软件、勒索软件、广告程序 ● 在用户非资源的情况下执行安装 ● 出于某种恶意的目的&#xff1a;控制、窃取、勒索、偷窥、推送、攻击。。。。。 恶意程序最重要的防护手段 ● 杀毒软件 / 防病毒软件 ● 客户端 / 服…

c# .net MAUI基础篇 环境安装、新建项目、安卓模拟器安装、项目运行

c# .net MAUI基础篇 环境安装、新建项目、安卓模拟器安装、项目运行 免费教学视频地址由趣编程ACE老师提供&#xff1a; 1..NET MAUI优势及安装和创建_哔哩哔哩_bilibili 一、介绍 .NET 多平台应用 UI (.NET MAUI) 是一个跨平台框架&#xff0c;用于使用 C# 和 XAML 创建本机移…

【面经】之小鼠喝药问题

题目 现在有 10 只小白鼠和 1000 支药水&#xff0c;1000 支药水中有且仅有一支药水有毒&#xff0c;如果小白鼠喝下毒药&#xff0c;那么毒发的时间是两小时。 现在只给你两小时的时间&#xff0c;请问如何用这 10 只小白鼠测出哪支药水有毒&#xff1f;&#xff08;忽略小白…

【Java编程进阶】标识符和关键字

在学习Java程序设计基础的时候&#xff0c;主要有标识符&#xff0c;变量&#xff0c;数据类型&#xff0c;流程控制这些主要的内容。 推荐学习专栏&#xff1a;Java 编程进阶之路【从入门到精通】 文章目录1. 标识符2. 关键字1. 标识符 什么是标识符&#xff1f; 标识符是用…

linux下的PPPOE设置

1.打开终端 #sudo pppoeconf 进入配置,输入用户名和密码. 2.建立连接 #sudo pon dsl-provider 3.断开连接 #sudo poff dsl-provider Welcome to the ADSL client setup. First, I will run some checks on your system to make sure the PPPoE client is installed properly.…

The 2022 CCPC Guangzhou Onsite M. XOR Sum(数位dp 数位背包)

题目 给定n,m,k(0<n<1e15,0<m<1e12,1<k<18)&#xff0c; 求长度为k的数组a&#xff0c;ai为[0,m]的整数&#xff0c; 满足的方案数 答案对1e97取模 题解 第一反应想起了hdu3693&#xff0c;但比对了一下&#xff0c;感觉那个题难很多&#xff0c; 两年…

一看就会的Java方法

文章目录一、方法的定义和使用&#x1f351;1、为什么引入方法&#xff1f;&#x1f351;2、方法的定义&#x1f351;3、方法调用的执行过程&#x1f351;4、实参和形参的关系二、方法重载&#x1f351;1、为什么需要方法重载&#x1f351;2、方法重载的概念和特点&#x1f351…