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 文件里面重新实现,这
    里只是提前占了一个位置而已。
    如果我们在使用某个外设的时候,开启了某个中断,但是又忘记编写配套的中断服务程序或者函
    数名写错,那当中断来临的时,程序就会跳转到启动文件预先写好的空的中断服务程序中,并且
    在这个空函数中无线循环,即程序就死在这里。
    7、RCC
    编程要点
    编程要点对应着时钟树图中的序号。
    1、开启 HSE/HSI ,并等待 HSE/HSI 稳定
    2、设置 AHB、APB2、APB1 的预分频因子
    3、设置 PLL 的时钟来源,和 PLL 的倍频因子,设置各种频率主要就是在这里设置
    4、开启 PLL,并等待 PLL 稳定
    5、把 PLLCK 切换为系统时钟 SYSCLK
    6、读取时钟切换状态位,确保 PLLCLK 被选为系统时钟
    8、mco

MCO 输出
在 STM32F103 系列中,PA8 可以复用为 MCO 引脚,对外提供时钟输出,在 HAL 库
stm32f1xx_hal_rcc.c 中已经定义了相关函数,我们可以直接调用,用示波器监控该引脚的输出
来判断我们的系统时钟是否设置正确。

F103 在内核水平上搭载了一个异常响应系统,支持为数众多的系统异常和外部中断。其中系统
异常有 8 个(如果把 Reset 和 HardFault 也算上的话就是 10 个),外部中断有 60 个。除了个别异
常的优先级被定死外,其它异常的优先级都是可编程的。有关具体的系统异常和外部中断可在
HAL 库文件 stm32f1xx.h 这个头文件查询到,在 IRQn_Type 这个结构体里面包含了 F103 系列全
部的异常声明。
NVIC 是嵌套向量中断控制器,控制着
整个芯片中断相关的功能,它跟内核紧密耦合,是内核里面的一个外设。但是各个芯片厂商在设
计芯片的时候会对 Cortex-M3 内核里面的 NVIC 进行裁剪,把不需要的部分去掉,所以说 STM32
的 NVIC 是 Cortex-M3 的 NVIC 的一个子集。
在配置中断的时候我们一般只用 ISER、ICER 和 IP 这三个寄存器,ISER 用来使能中断,ICER 用
来失能中断,IP 用来设置中断优先级。
优先级定义
在 NVIC 有一个专门的寄存器:中断优先级寄存器 NVIC_IPRx,用来配置外部中断的优先级,IPR
宽度为 8bit,原则上每个外部中断可配置的优先级为 0~255,数值越小,优先级越高。但是绝大
多数 CM3 芯片都会精简设计,以致实际上支持的优先级数减少,在 F103 中,只使用了高 4bit,
用于表达优先级的这 4bit,又被分组成抢占优先级和子优先级。如果有多个中断同时响应,抢占
优先级高的就会抢占抢占优先级低的优先得到执行,如果抢占优先级相同,就比较子优先级。如
果抢占优先级和子优先级都相同的话,就比较他们的硬件中断编号,编号越小,优先级越高。
优先级分组
优先级的分组由内核外设 SCB 的应用程序中断及复位控制寄存器 AIRCR 的 PRIGROUP[10:8] 位
决定,F103 分为了 5 组,具体如下:主优先级 = 抢占优先级
中断编程
在配置每个中断的时候一般有 3 个编程要点:

  1. 使能外设某个中断,这个具体由每个外设的相关中断使能位控制。比如串口有发送完成中
    断,接收完成中断,这两个中断都由串口控制寄存器的相关中断使能位控制。
  2. 配置 EXTI 中断源、配置中断优先级。
  3. 编写中断服务函数
    在启动文件 startup_stm32f103xe.s 中我们预先为每个中断都写了一个中断服务函数,只是这些中
    断函数都是为空,为的只是初始化中断向量表。实际的中断服务函数都需要我们重新编写,为了
    方便管理我们把中断服务函数统一写在 stm32f1xx_it.c 这个库文件中。
    关于中断服务函数的函数名必须跟启动文件里面预先设置的一样,如果写错,系统就在中断向量
    表中找不到中断服务函数的入口,直接跳转到启动文件里面预先写好的空函数,并且在里面无限
    循环,实现不了中断。
    EXTI 简介
    EXTI(External interrupt/event controller)—外部中断/事件控制器,管理了控制器的 20 个中断/事
    件线。每个中断/事件线都对应有一个边沿检测器,可以实现输入信号的上升沿检测和下降沿的
    检测。EXTI 可以实现对每个中断/事件线进行单独配置,可以单独配置为中断或者事件,以及触
    发事件的属性。
    EXTI 功能框图
    EXTI 的功能框图包含了 EXTI 最核心内容,掌握了功能框图,对 EXTI 就有一个整体的把握,在
    编程时思路就非常清晰。
    EXTI 是在 APB2 总线上的,在编程时候需要注意到这点。
    HAL 库函数的 EXIT 初始化非常简单,只需配置好 IO 口的模式,然后配置中断源、中断优先级、
    使能中断。
  1. HAL_NVIC_SetPriority:该函数负责 EXTI 中断/事件线选择,可选 EXTI0 至 EXTI25,可参
    考表 17_1 选择,配置优先级。
  2. HAL_NVIC_EnableIRQ:该函数负责控制使能中断。
    中断在嵌入式应用中占有非常重要的地位,几乎每个控制器都有中断功能。中断对保证紧急事件
    得到第一时间处理是非常重要的。
    编程要点
  3. 初始化用来产生中断的 GPIO;
  4. 初始化 EXTI;
  5. 配置 NVIC;
  6. 编写中断服务函数;
    SysTick
    编程要点
    1、设置重装载寄存器的值
    2、清除当前数值寄存器的值
    3、配置控制与状态寄存器

TTL 标准及 RS-232 标准

STM32 的 USART 简介
通用同步异步收发器 (Universal Synchronous Asynchronous Receiver and Transmitter) 是一个串行通
信设备,可以灵活地与外部设备进行全双工数据交换。有别于 USART 还有一个 UART(Universal
Asynchronous Receiver and Transmitter),它是在 USART 基础上裁剪掉了同步通信功能,只有异步
通信。简单区分同步和异步就是看通信时需不需要对外提供时钟输出,我们平时用的串口通信基
本都是 UART。
串行通信一般是以帧格式传输数据,即是一帧一帧的传输,每帧包含有起始信号、数据信息、停
止信息,可能还有校验信息。USART 就是对这些传输参数有具体规定,当然也不是只有唯一一
个参数值,很多参数值都可以自定义设置,只是增强它的兼容性。
USART 满足外部设备对工业标准 NRZ 异步串行数据格式的要求,并且使用了小数波特率发生
器,可以提供多种波特率,使得它的应用更加广泛。USART 支持同步单向通信和半双工单线通
信;还支持局域互连网络 LIN、智能卡 (SmartCard) 协议与 lrDA(红外线数据协会) SIR ENDEC 规
范。
USART 支持使用 DMA,可实现高速数据通信,有关 DMA 具体应用将在 DMA 章节作具体讲解。
USART 在 STM32 应用最多莫过于“打印”程序信息,一般在硬件设计时都会预留一个 USART通信接口连接电脑,用于在调试程序是可以把一些调试信息“打印”在电脑端的串口调试助手工
具上,从而了解程序运行是否正确、如果出错哪具体哪里出错等等。
USART 的功能框图包含了 USART 最核心内容,掌握了功能框图,对 USART 就有一个整体的把
握,在编程时就思路就非常清晰。
初始化结构体和初始化库函数配合使用是 HAL 库精髓所在,理解了初始化结构体每个成员意义
基本上就可以对该外设运用自如了。初始化结构体定义在 stm32f1xx_hal_usart.h 文件中,初始化
库函数定义在 stm32f1xx_hal_usart.c 文件中,编程时我们可以结合这两个文件内注释使用。
USART 只需两根信号线即可完成双向通信,对硬件要求低,使得很多模块都预留 USART 接口来
实现与其他模块或者控制器进行数据传输,比如 GSM 模块,WIFI 模块、蓝牙模块等等。在硬件
设计时,注意还需要一根“共地线”。
我们经常使用 USART 来实现控制器与电脑之间的数据传输。这使得我们调试程序非常方便,比
如我们可以把一些变量的值、函数的返回值、寄存器标志位等等通过 USART 发送到串口调试助
手,这样我们可以非常清楚程序的运行状态,当我们正式发布程序时再把这些调试信息去除即
可。
我们不仅仅可以将数据发送到串口调试助手,我们还可以在串口调试助手发送数据给控制器,控
制器程序根据接收到的数据进行下一步工作。
首先,我们来编写一个程序实现开发板与电脑通信,在开发板上电时通过 USART 发送一串字符
串给电脑,然后开发板进入中断接收等待状态,如果电脑有发送数据过来,开发板就会产生中断,
我们在中断服务函数接收数据,并马上把数据返回发送给电脑。
为利用 USART 实现开发板与电脑通信,需要用到一个 USB 转 USART 的 IC,我们选择 CH340G
芯片来实现这个功能,CH340G 是一个 USB 总线的转接芯片,实现 USB 转 USART、USB 转 lrDA
红外或者 USB 转打印机接口,我们使用其 USB 转 USART 功能。
编程要点

  1. 使能 RX 和 TX 引脚 GPIO 时钟和 USART 时钟;
  2. 初始化 GPIO,并将 GPIO 复用到 USART 上;
  3. 配置 USART 参数;
  4. 配置中断控制器并使能 USART 接收中断;
  5. 使能 USART;
  6. 在 USART 接收中断服务函数实现数据接收和发送。

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

  1. [野火]STM32 F103 HAL库开发实战指南笔记之基础总结

    1.本书配套的仿真器为 Fire-Debugger,遵循 ARM 公司的 CMSIS-DAP 标准,支持所有基于 Cortex-M 内核的单片机,常见的 M3.M4 和 M7 都可以完美支持.Fire ...

  2. 蓝桥杯嵌入式STM32 G431 HAL库开发速成指南(1)LED

    本教程适用于报名参加蓝桥杯嵌入式用新开发板(G431)且想要快速开发的小白,不具体讲解复杂的原理,只讲Cubemx初始化配置以及在KEIL里面使用相应的库函数功能对外设进行编程. CUBEMX配置流程 ...

  3. 《STM32库开发实战指南:基于STM32F103(第2版)》——2.1节仿真器简介

    本节书摘来自华章社区<STM32库开发实战指南:基于STM32F103(第2版)>一书中的第2章,第2.1节仿真器简介,作者刘火良 杨森,更多章节内容可以访问云栖社区"华章社区& ...

  4. 【野火】《i.MX RT 库开发实战指南》连载一

    [野火]<i.MX RT 库开发实战指南>更新了,欢迎下载. 完成<自己写库-构建库函数雏形>章节,告诉大家什么是固件库,教会大家官方的固件库是怎么从寄存器映射开始,再到寄存器 ...

  5. 配置CLion进行嵌入式STM32的HAL库开发

    前言 时不可以苟遇,道不可以虚行. 一.准备 1.软件 CLion-2020:百度网盘提取链接放在文章最后. STM32CubeMX:使用 6.5.0 版本的,不要使用最新版本的 CubeMX,不然没 ...

  6. 【STM32+cubemx】0030 HAL库开发:DDS芯片AD9833实现简单的波形发生器

    大家好,我是学电子的小白白,今天带大家了解一款波形发生器芯片--AD9833. AD9833是AD公司出品的一款DDS波形发生器,能够产生正弦波.三角波和方波输出. 1)什么是DDS 通俗来讲,DDS ...

  7. STM32CUBEMX F103 HAL库开发 两路定时器的Encoder编码器模式

    机器人开发过程中,对于直流电机来说,编码器至关重要,它不仅可以使我们对电极进行精确的速度闭环,位置闭环,还可以通过时间积分,根据运动学关系,获得速度.位置等信息 STM32的定时器有编码器模式,大大的 ...

  8. 【STM32】HAL库开发之开启STM32L4系列单片机的FPU

    STM32L4 属于 Cortex M4F 架构,带有 32 位单精度硬件 FPU,支持浮点指令集,相对于Cortex M0 和 Cortex M3 等,高出数十倍甚至上百倍的运算性能. 而我们在处理 ...

  9. STM32 HAL库开发学习笔记: USART1串口通讯(中断方式) IDE-STM32CubeIDE

    STM32串口通讯有三种方式,分别为阻塞(轮询).中断.DMA.这里将用中断的方式开发. 笔者也是刚入门STM32 HAL库开发,该笔记致希望于能帮到初学者,文中配置步骤.代码.实验现象均是笔者实践可 ...

最新文章

  1. 计算机基础知识易错,事业单位考试计算机基础知识易错试题.doc
  2. linux 大文件切割和合并 tar分割和合并
  3. 【转】ABAP的坑4
  4. 笔记-中项案例题-2020年下-立项管理
  5. html5基础知识点表单
  6. python db2 linux 安装,python安装DB2模块
  7. android studio卡顿解决办法
  8. 为什么腾讯云要自研云原生数据库 CynosDB?
  9. 晶体管开关电路的设计以及如何提高其开关速度
  10. 【Windows】VMware虚拟机安装Windows 10 教程
  11. 预告 | PGCon 2022(PostgreSQL全球开发者大会)开幕,IvorySQL受邀参加
  12. html5如何引用百度地图api,WebApp如何调用百度地图API
  13. chip-seq三个生物学重复样品处理——IDR
  14. Ubuntu18安装截图工具flameshot
  15. 港科夜闻|2022年香港科大气候适应及复原力大会圆满闭幕,政经领袖研讨香港气候政策与绿色金融发展...
  16. linux移植街机模拟器,gngeo 游戏模拟器(街机)移植CE3100
  17. Codeforces Round #429 (Div. 2) B. Godsend
  18. 阿里云oss部署静态网页
  19. 函数式编程:Python 调用迅雷下载
  20. linux下聊天工具的安装

热门文章

  1. 【f1c200s/f1c100s】FT5426触摸屏驱动适配
  2. C#对磁盘路径字符串的相关操作
  3. MySql进阶-间隙锁(gap-key)
  4. CentOS安装Bumblebee驱动
  5. SD卡 TF卡 接口引脚定义
  6. c#实现打印快递单-提供源码
  7. CodeGear2007到CodeGear2009全系列自动破解工具
  8. 如何让android软件隐形,如何将Dock栏的微信App设置为隐形状态
  9. 陈力:传智播客古代 珍宝币 泡泡龙游戏开发第48讲:PHP绘图技术
  10. hpoem系统服务器,hp(惠普)Windows 7 32/64位-OEM版