欢迎使用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左移4
0位变成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野火教程学习笔记相关推荐

  1. STM32 HAL库学习笔记1-HAL库简介

    STM32 HAL库学习笔记1-HAL库简介 HAL库 SPL 库 和 HAL 库两者相互独立,互不兼容.几种库的比较如下 目前几种库对不同芯片的支持情况如下 ST 中文官网上有一篇<关于ST库 ...

  2. 1、野火freertos学习笔记

    野火freertos学习笔记 1.任务 1.1 栈 1.2 任务的切换 taskYIELD(); 1.3 临界段 2.空闲任务 3.任务优先级 4.任务延时的表现 5.时间片 5.1抢占式.协做式 6 ...

  3. linux磁盘符变化autofs,Linux基础教程学习笔记之Autofs自动挂载

    Linux基础教程学习笔记之Autofs自动挂载 Autofs自动挂载: yum -y install autofs vim /etc/auto.master  在文件中添加下面行 /home/gue ...

  4. 网络存储 linux 访问,Linux基础教程学习笔记28——使用Samba访问网络存储

    Linux基础教程学习笔记28--使用Samba访问网络存储 SMB用于Windows和类Linux系统直接的文件共享 安装samba client包: [root@linuxidc~]# yum i ...

  5. 无敌python爬虫教程学习笔记(一)

    python爬虫系列文章目录 无敌python爬虫教程学习笔记(一) 无敌python爬虫教程学习笔记(二) 无敌python爬虫教程学习笔记(三) 无敌python爬虫教程学习笔记(四) 本文目录 ...

  6. 无敌python爬虫教程学习笔记(二)

    系列文章目录 无敌python爬虫教程学习笔记(一) 无敌python爬虫教程学习笔记(二) 无敌python爬虫教程学习笔记(三) 无敌python爬虫教程学习笔记(四) 手刃一个小爬虫 系列文章目 ...

  7. 黑马程序员最新版JavaWeb基础教程-学习笔记

    da@黑马程序员最新版JavaWeb基础教程-学习笔记 day06-HTML&CSS HTML HTML(HyperTest Markup Language):超文本标记语言 是一门语言,所有 ...

  8. 【从零开始的大数据学习】Flink官方教程学习笔记(一)

    Flink官方教程学习笔记 学习资源 基础Scala语法 Scala数据结构专题 声明变量 代码块 函数(function) 方法(methods) Traits (接口) class(类) tupl ...

  9. STM32 Cube MX学习笔记——TOF 高速单线激光雷达 L10(usart)

    STM32 Cube MX学习笔记--TOF 高速单线激光雷达 L10_串口中断通信 1. TOF 高速单线激光雷达 L10 2. STM32 Cube MX配置 3.代码配置 4.编译 烧录 显示 ...

最新文章

  1. 【Pyhon 3】: 170104:优品课堂: GUI -tkinter
  2. Arcgis10 server安装
  3. kali怎么成为管理员_网站死链是什么、是怎么引起的以及死链对SEO优化的影响?...
  4. 蓝桥杯入门训练Fibonacci数列
  5. 21. 栈的压入、弹出序列
  6. 【王道操作系统笔记】操作系统的运行机制和体系结构
  7. HTML5 桌面通知:Notification API的基础用法
  8. 如何获取 iOS 设备 UDID?
  9. 清理电脑C盘的方法汇总
  10. 给未来的电子工程师nbsp;---电子牛人给…
  11. 物联网毕设选题 - 单片机智能红外测温系统(物联网 stm32 远程wifi)
  12. UVA 487 - Boggle Blitz
  13. 学习Flash制作高射炮游戏
  14. java怎么往list里存int,Java中List、Integer[]、int[] 的相互转换
  15. 2800首无损格式经典歌曲分享
  16. 现代C++新特性 列表初始化
  17. C语言之有符号无符号整数取值范围
  18. TSQL和PLSQL的区别
  19. php刷新热销商品,ecshop首页如何调用指定分类下的推荐热销最新商品
  20. c语言编写s11次方,c语言编程练习题.docx

热门文章

  1. MATLAB 符号表达式与运算全面详细讲解
  2. 图像风格迁移算法学习总结
  3. 分布式定时任务技术选型
  4. Dagger2使用详解
  5. html 合并文件到excel,Excel2013把多个文件合并到一个Excel文档里方法图解
  6. 高中计算机课程事例,高中信息技术课堂教学案例与分析.doc
  7. Linux下对TF卡进行分区
  8. 七彩虹技术服务论坛硬件驱动更新指南(添加Vista支持)
  9. 软件质量保障实践合集
  10. JAVA+TEXT+小说速读训练器