STM32野火教程学习笔记
欢迎使用STM32
虽然经历了疫情期间的价格起飞,但是STM32系列的单片机仍然是各个控制领域内主流的微控制器。它是控制人的必修课之一。
STM32的编程方法
我们在学习51单片机的时候,通常是通过编写程序直接对其输入输出(i/o)口进行操作。而STM32单片机更加高级,它有更复杂的底层。因此我们对STM32单片机的编程方法有两种。一个是类似于51单片机的直接控制片内寄存器和i/o口的寄存器编程,一个是为了降低开发难度给开发者提供了巨大帮助的固件库编程。今天所学习的是更加底层的寄存器编程。尽管在开发的时候,我们用的基本上都是固件库编程,但是学习寄存器编程有利于我们了解STM32的底层,学一门技术只有掌握了牢固的底层才是打了一个好的基础。
前言
本人使用板子是野火STM32103指南者,型号是STM32VET6,兼容野火STM32f103霸道,型号是STM32ZET6。本笔记是在学习了野火官方教程的第11节课之后写下的。如何安装keilMDK,使用烧录器,如何新建工程模板,请观看野火stm32f103教程入门篇的前9节课。十分简单这里不再赘述。
用寄存器编程点亮第一个LED灯的地址定义
单片机的点灯是所有微控制器的入门标志,就好比C语言的Hello World!。这里我们类比一下51单片机的点灯方式。如图
可以看到我们直接对LED连接的P2.0口进行位操作拉低电平使其点亮。为何如此简单,奥妙就在于图中第一行REG52.H当中。这是一个C语言中叫做头文件的东西,它用来存放一些已经定义好的东西,比如在经典的stdio.h中有各种数学运算,REG52.H中就有定义每一个寄存器控制的i/o口也叫外设。
我们只要对这些定义好的东西操作,就可以通过单片机来控制各种电子器件了。
现在我们把目光转移到stm32上来,想要学会寄存器编程就要自己写头文件。先给头文件起个名,非常好起就叫它stm32f103.h好了。在里面我们开始写定义寄存器,从而方便我们控制STM32的i/o口即GPIO口(外设)的代码,这种方法叫寄存器映射。
//用来存放STM32寄存器映射的代码
// 外设 periphral
#define PERIPH_BASE ((unsigned int)0X40000000)
#define APB1PERIPH_BASE PERIPH_BASE
#define APB2PERIPH_BASE (PERIPH_BASE + 0X10000)
#define AHBPERIPH_BASE (PERIPH_BASE + 0X20000)
#define RCC_BASE (AHBPERIPH_BASE + 0X1000)
#define GPIOB_BASE (APB2PERIPH_BASE + 0X0C00)
既然要控制寄存器,那么我们要知道寄存器的在单片机内的地址,就如同警察叔叔找人要知道他的身份证号码知道他住哪一样。根据STM32官方给出的技术手册,外设的基地址(第一个地址,也叫起始位)是0x40000000,用C语言的unsigned int关键字将0x40000000转化为地址位(16进制数)。其名称根据外设的英语单词periphral定义为PERIPH_BASE。注意到这里我们还只是知道了寄存器的地址位还未对寄存器操作。
现在我们看第二行代码,“#define APB1PERIPH_BASE PERIPH_BASE” 它的意思是定义在APB1上面的外设基地址,就是整个单片机的外设的基地址:0x40000000。至于APB1是什么,野火教程前面的课程有讲解,简单点说就是一块放置外设的地方。STM32的外设就分别放在APB1和APB2上,因此第三行是定义APB2上的外设地址,它的地址在APB1基地址上增加0x10000(16进制数)。第四行定义AHB的基地址,AHB在之前的野火课程中也有讲解,这里简单说一下它是桥接控制单片机外设,时钟和单片机内核的部分,单片机想要工作必须打开它从而打开单片机的时钟。因此第四行代码“#define AHBPERIPH_BASE (PERIPH_BASE + 0X20000)”就是对AHB的地址定义了。
定义完外设地址以后,我们还不能着急去定义寄存器实现寄存器映射。还有两个重要的东西需要准备。第一个东西:时钟。单片机的时钟就好像一个人的心脏,时钟打开,单片机的心脏才开始跳动,所以时钟的地址就是AHB的初始地址上+0x1000。如第五行代码所示。第二个东西:我们要控制的GPIO口。野火stm32单片机的LED灯在B号GPIO上,所以我们要控制GPIOB。GPIO就属于单片机上的外设了,它的基地址就是APB2的基地址上+0x0C00。到这里点灯所有所需的地址位已经准备好了,我们要开始通过这些地址位访问内存来控制寄存器点灯了。
用寄存器编程点亮第一个LED灯的寄存器操作
代码如下
#define RCC_APB2ENR (unsigned int)(RCC_BASE + 0x18)//时钟使能
#define GPIOB_CRL (unsigned int)(GPIOB_BASE + 0x00)
#define GPIOB_CRH (unsigned int)(GPIOB_BASE + 0x04)
#define GPIOB_ODR (unsigned int)(GPIOB_BASE + 0x0C)
首先我们要打开时钟,那么就要启动时钟使能位,时钟使能寄存器我们把它的名字叫做RCC_APB2ENR,它的地址是时钟基地址上+0x18。
这里有一个难理解的点,我们为什么要进行一个指针强制类型转换这个操作?原因很简单,目前定义的那些地址例如APB1PERIPH_BASE,它还只是反映地址的立即数。打个比方,警察要找你,知道了你的身份证号。但是这不代表找到你了,只是知道了你的一个代号,要找到你还得去线下你的住址找你。这样的行为就像指针强制类型转换的作用了,把代表寄存器地址的立即数,强制转化位指针,这样它就是一个真正的地址了。真正的地址就可以访问寄存器来控制外设GPIO了。(指针不懂的去补补C语言指针,其实指针就是一个地址)
回到寄存器控制上来,我们配置完时钟后,下一步就是配置控制GPIO(外设)的寄存器。点灯操作我们需要至少控制3个。端口配置低寄存器(CRL)、端口配置高寄存器(CRH)、端口输出数据寄存器(ODR)最后3行就是这些寄存器的位和强制类型转换的操作。
用寄存器编程点亮第一个LED灯
C语言控制微控制器的程序基本上都是在main函数里的,因此我们在main函数里开始写如下代码
#include “stm32f10x.h”
int main(void)
{
//打开GPIOB的时钟RCC_APB2ENR |=((1)<<3);//清空控制PB0的端口位GPIOB_CRL &= ~( (0x0F)<< (4*0));// 配置IO口为输出GPIOB_CRL |=((1)<<(4*0)// 控制ODR寄存器GPIOB_ODR &= ~(1<<0); //GPIOB_ODR |= (1<<0);关闭}
void SystemInit(void)
{
//函数体为空,目的是为了骗过编译器不报错
}
这里我们看到我们可以类似操作51单片机那样直接对外设地址操作从而打开时钟,拉低GPIO口的电平点亮LED灯了。最后面那个骗过编译器不报错是前面几节课的内容,打上就行,不用太深入了解,以后用不到。
我们发现stm32对寄存器的操作不像51单片机可以直接赋值0或1,而是采用C语言里特殊的|=和&=~,|=是用于置1某一位而不改变其他位(一个寄存器上有好几位,stm32单片机的一个寄存器有32位),比如这里的打开时钟是GPIOB的时钟。根据数据手册GPIOB的时钟在RCC_APB2ENR寄存器的第三位,把他第三位置1就单独打开了GPIOB的时钟,这里我把数据手册的截图给大家看一下。
另一个&=~是置0操作,置0寄存器某一位而不改变其他位例如主程序的第二行程序 GPIOB_CRL &= ~( (0x0F)<< (40));它的操作是将端口配置低寄存器初始4位全部置0,而不改变其他位。
第三行代码是控制GPIO口位为10MHz通用推挽输出模式。将1左移40位变成0001(此寄存器每4位控制一个GPIO位的输出模式)。
第四行就是将野火stm32指南者的LED绿灯点亮的操作,将ODR寄存器第1位置0(1左移0位)拉低电平。
主要我们就完成了点灯,入门成功!
野火教程B站链接
https://www.bilibili.com/video/BV1yW411Y7Gw/?p=6&spm_id_from=333.880.my_history.page.click&vd_source=16419a44923b86308e680f95ec76193a
STM32野火教程学习笔记相关推荐
- STM32 HAL库学习笔记1-HAL库简介
STM32 HAL库学习笔记1-HAL库简介 HAL库 SPL 库 和 HAL 库两者相互独立,互不兼容.几种库的比较如下 目前几种库对不同芯片的支持情况如下 ST 中文官网上有一篇<关于ST库 ...
- 1、野火freertos学习笔记
野火freertos学习笔记 1.任务 1.1 栈 1.2 任务的切换 taskYIELD(); 1.3 临界段 2.空闲任务 3.任务优先级 4.任务延时的表现 5.时间片 5.1抢占式.协做式 6 ...
- linux磁盘符变化autofs,Linux基础教程学习笔记之Autofs自动挂载
Linux基础教程学习笔记之Autofs自动挂载 Autofs自动挂载: yum -y install autofs vim /etc/auto.master 在文件中添加下面行 /home/gue ...
- 网络存储 linux 访问,Linux基础教程学习笔记28——使用Samba访问网络存储
Linux基础教程学习笔记28--使用Samba访问网络存储 SMB用于Windows和类Linux系统直接的文件共享 安装samba client包: [root@linuxidc~]# yum i ...
- 无敌python爬虫教程学习笔记(一)
python爬虫系列文章目录 无敌python爬虫教程学习笔记(一) 无敌python爬虫教程学习笔记(二) 无敌python爬虫教程学习笔记(三) 无敌python爬虫教程学习笔记(四) 本文目录 ...
- 无敌python爬虫教程学习笔记(二)
系列文章目录 无敌python爬虫教程学习笔记(一) 无敌python爬虫教程学习笔记(二) 无敌python爬虫教程学习笔记(三) 无敌python爬虫教程学习笔记(四) 手刃一个小爬虫 系列文章目 ...
- 黑马程序员最新版JavaWeb基础教程-学习笔记
da@黑马程序员最新版JavaWeb基础教程-学习笔记 day06-HTML&CSS HTML HTML(HyperTest Markup Language):超文本标记语言 是一门语言,所有 ...
- 【从零开始的大数据学习】Flink官方教程学习笔记(一)
Flink官方教程学习笔记 学习资源 基础Scala语法 Scala数据结构专题 声明变量 代码块 函数(function) 方法(methods) Traits (接口) class(类) tupl ...
- STM32 Cube MX学习笔记——TOF 高速单线激光雷达 L10(usart)
STM32 Cube MX学习笔记--TOF 高速单线激光雷达 L10_串口中断通信 1. TOF 高速单线激光雷达 L10 2. STM32 Cube MX配置 3.代码配置 4.编译 烧录 显示 ...
最新文章
- 【Pyhon 3】: 170104:优品课堂: GUI -tkinter
- Arcgis10 server安装
- kali怎么成为管理员_网站死链是什么、是怎么引起的以及死链对SEO优化的影响?...
- 蓝桥杯入门训练Fibonacci数列
- 21. 栈的压入、弹出序列
- 【王道操作系统笔记】操作系统的运行机制和体系结构
- HTML5 桌面通知:Notification API的基础用法
- 如何获取 iOS 设备 UDID?
- 清理电脑C盘的方法汇总
- 给未来的电子工程师nbsp;---电子牛人给…
- 物联网毕设选题 - 单片机智能红外测温系统(物联网 stm32 远程wifi)
- UVA 487 - Boggle Blitz
- 学习Flash制作高射炮游戏
- java怎么往list里存int,Java中List、Integer[]、int[] 的相互转换
- 2800首无损格式经典歌曲分享
- 现代C++新特性 列表初始化
- C语言之有符号无符号整数取值范围
- TSQL和PLSQL的区别
- php刷新热销商品,ecshop首页如何调用指定分类下的推荐热销最新商品
- c语言编写s11次方,c语言编程练习题.docx