01:(寄存器开发)点亮一个LED灯
寄存器开发
- 1、单片机的简介
- 1.1、什么是单片机
- 1.2、F1系列内核和芯片的系统架构
- 1.3、存储器映像
- 1.4、什么是寄存器
- 2、寄存器开发模板工程
- 3、使用寄存器点亮一个LED
- 4、代码改进1
- 5、代码改进2
本教程使用的是STM32F103C8T6最小系统板,教程来源B站up“嵌入式那些事”。
1、单片机的简介
1.1、什么是单片机
单片机(Single-Chip Microcomputer)单片机微型计算机,是一种集成电路芯片,把具有数据处理能力的中央处理器CPU、随机存储器RAM、闪存flash、多种l/O口和中断系统、定时器/计数器等功能(可能还包括显示驱动电路、脉宽调制电路、模拟多路转换器、A/D转换器等电路)集成到一块硅片上构成的一个小而完善的微型计算机系统,在工业控制领域广泛应用。
STM32F103C8T6又被称为32位单片机,那么这个32代表着什么意思喃?
——其中32代表着地址总线有32位,即最小存储单元(1字节B)的地址编号是32位二进制构成的。所以stm32的存储空间位2^32B = 4GB(地址:0x0000 0000~0xFFFF FFFF)
①FLASH:FLAS又称闪存,它是ROM的一部分(只读存储器,现在往里面写数据),用于存放向单片机烧录的代码。而ROM的另外一部分为系统存储器和字节选项。一般情况下单片机读取FLASH里面的数据要通过FLASH接口,所以读取FLASH的数据比较慢。
②RAM:临时存储器,掉电里面的数据会丢失,读写速度比ROM快。主要存储代码运行时的临时变量,内核和片上外设寄存器的配置参数。
③总线:就像是桥梁,用于CPU与外设之间的连接,DMA与外设之间的连接等,进行数据从传输
④时钟:由内部晶振或者外部晶振产生的时钟频率脉冲信号,时钟频率决定了CPU处理0/1的快慢程度(单片机执行代码的快慢程度),除了CPU需要时钟频率脉冲信号,片上外设也需要时钟信号时钟频率脉冲信号,其作用是启动边沿触发器。而像定时器这样的片上外设需要时钟频率脉冲信号来进行计数。
⑤外设:单片机除了CPU还有很多的片上外设,比如GPIO,定时器TIM等,只有CPU和这些片上外设共同作用才能完成我们想要的功能
1.2、F1系列内核和芯片的系统架构
如上图为F1系列单片机内核和芯片的系统架构,其中分为4个主动单元和4个被动单元。
-
四个主动单元
——能够主动的发起请求,主动的访问数据。
①Dcode总线,②System总线,③DMA1,④DMA2(stm32f103c8t6没有DMA2) -
四个被动单元
——不能够主动的发起请求,被动的访问数据。
①FLASH,②SRAM,③FSMC,④桥接1和桥接2上面连接的片上外设
1.3、存储器映像
由前面得知stm32单片机里面有4GB的存储空间,人们将这4GB的空间进行了地址编号就叫存储器映像。划分为8个区域,不同区域代表存储不同功能的信息。如下图所示:
由上图存储器映像得出如下结论:
1.4、什么是寄存器
寄存器的本质就是内存,若通过给某个内存a里面写入数据来控制外设A,那么这个内存a就是外设A的控制寄存器。若某个内存b里面的数据来表示此时外设B的状态,那么这个内存b就是外设B的状态寄存器。我们知晓stm32里面由很多的外设,那么这些外设的寄存器怎么寻找喃?答案:通过地址,我们由前面得知外设寄存器的起始地址为0x4000 0000,即之后的地址就代表着寄存器地址,不同的寄存器的地址不同。 如下图为部分外设的寄存器地址
而寄存器开发就是找到外设的寄存器,通过给这些寄存器里面写入数据来进行对外设配置,进而完成我们想要实现的功能,一般情况下单片机使用寄存器开发的执行效率比使用库函数开发的执行效率更高,但是人们的寄存器代码开发效率会比使用库函数的代码开发效率低。
2、寄存器开发模板工程
开发环境安装和创建工程请参考stm32标准库入门教程的第1章和第2章。寄存器开发必要文件如下图所示:
模板资料链接: link
3、使用寄存器点亮一个LED
实物按照如下图所示连接好。创建好工程模板后,我们在模板中的main()函数里面按照如下步骤编写代码:
1、开启时钟
如图LED引脚连接着A0,则开启片上外设GPIOA的时钟——RCC寄存器(与外设的时钟有关)
① 打开参考手册找到存储器映像如下图所示:
如图所示:地址0x4002 1000——0x4002 13FF这段的内存是与RCC有关的寄存器。
②打开参考手册找到RCC寄存器描述如下图所示:
如图RCC的第一个寄存器为RCC_CR(时钟控制寄存器),它的地址偏移为0x00,则这个寄存器的地址就是0x4002 1000。RCC的第二个寄存器为RCC_CFGR(时钟配置寄存器),它的地址偏移为0x04,那为什么第二个寄存器的地址偏移是0x04喃?
如图:寄存器的地址其实是所包含4个字节中的首字节的地址,一个寄存器中包含4个字节,所以每增加一个寄存器,地址就偏移0x04。
③GPIOA挂载在APPB2时钟总线上面,我们找到APB2使能寄存器如下图所示:
如图RCC_APB2ENR寄存器的地址偏移为0x18,而与GPIOA时钟的位在32位中的第3位,只需要在这一位写入1,即开启了片上外设GPIOA的时钟。那如何用代码表示喃?
*(uint32_t *)(0x40021000 + 0x18) = 0x04;//指针代表地址
将十六进制的数值通过类型转换为指针类型,然后通过*取内容给其赋值。
2、配置IO口的输出模式
①打开参考手册找到存储器映像如下图所示:
如图:地址0x4001 0800——0x4001 0BFF这段的内存是与GPIOA引脚有关的寄存器。
②打开参考手册找到GPIO寄存器描述如下图所示:
如上图:配置低引脚IO(IO0~IO7)的寄存器的地址偏移为0x00,那么配置高引脚IO(IO8 ~ IO15)的寄存器的地址偏移为0x04。而我们的LED负极连接着A0,所以我们需要对低寄存器进行配置。那如何用代码配置喃?
*(uint32_t *)(0x40010800 + 0x00) = 0x03;//MODE0 = 11,CNF0 = 00
MODE0 = 11,表示配置为输出模式,且输出速度为50MHz
CNF0 = 00,表示配置为通用推挽输出模式(能输出低电平0和高电平1)
地址为0x4001 0800如何进行地址偏移,若需要配置GPIOB0则地址为0x4001 0C00进行地址偏移
3、IO输出逻辑电平
①打开参考手册找到GPIO寄存器描述如下图所示:
如图:给ODR0写入1则对应的IO0引脚则输出高电平1,若写入0,则引脚输出低电平0
由实物连接图可知,LED的正极连接着VCC,负极连接着IO引脚,所以引脚输出低电平,LED点亮,输出高电平,LED熄灭。代码如下:
*(uint32_t *)(0x40010800 + 0x0C) = 0xFFFE;//1111 1111 1111 1110
IO1引脚~IO15引脚输出高电平,IO0引脚输出低电平
综上:使用寄存器编程点亮一个LED灯完整的代码如下:
int main(void)
{//1、开启对应的GPIOA的时钟*(uint32_t *)(0x40021000 + 0x18) = 0x04;//2、给IO口设置工作模式:PA0配置为通用推挽输出模式*(uint32_t *)(0x40010800 + 0x00) = 0x03;//3、对应的IO口设置值:1/0,PA0输出0,点亮LED*(uint32_t *)(0x40010800 + 0x0C) = 0xFFFE;while(1){}
}
4、代码改进1
从上面的代码开发步骤中,我们每次需要配置某个片上外设的寄存器时,我们都需要打开存储器映像来找到这个片上外设的寄存器初始地址(基地址),然后在通过寄存器的地址偏移,然后通过基地址+偏移地址最终定位到我们需要的那个寄存器的地址。使用这种开发方式大大降低了我们开发的效率,而st公司也想到了这一点。
所示它在stm32f10x.h这个文件里面已经将每个片上外设的寄存器基地址用#define定义好了,如下图所示:RCC的基地址就用RCC这个字符串来表示了(即RCC = (uint32_t *)(0x40021000))
我们以外设RCC为例,查看它的代码是如何定义的,如下图所示:
如图:RCC的基地址 =RCC_BASE = 0x4000 0000 + 0x20000 +0x1000 = 0x4002 1000,正好和存储器映像里面的一样。
而RCC_TypeDef *(RCC_BASE)将基地址转换为结构体的指针类型,我们转到这个结构体的定义看看,如下图所示:
如上图所示:这个结构体里面的变量全是RCC的寄存器,且都是按照参考手册的顺序一比一排列的,且都是定义的和参考手册一样的32位(方便地址偏移)。则由C语言结构体的如下的基础知识
P->a :结构体的基地址偏移了1个字节,P->b:结构体的基地址偏移了5个字节。
既然RCC就是结构体的地址,那么通过地址表示结构体的变量如下:
RCC->CR:RCC寄存器的基地址偏移了0位
RCC->CFGR:RCC寄存器的绝对值偏移了32位
RCC->CIR:RCC寄存器的绝对值偏移了64位…
综上:通过上面的基础知识,我们进行如下的代码改进
int main(void)
{//1、开启对应的GPIOA的时钟//*(uint32_t *)(0x40021000 + 0x18) = 0x04;//2、给IO口设置工作模式:PA0配置为通用推挽输出模式//*(uint32_t *)(0x40010800 + 0x00) = 0x03;//3、对应的IO口设置值:1/0,PA0输出0,点亮LED//*(uint32_t *)(0x40010800 + 0x0C) = 0xFFFE;/*改进1:地址换为st公司定义好的宏
*///1、开启对应的GPIOA的时钟RCC->APB2ENR = 0x04;//2、给IO口设置工作模式:PA0配置为通用推挽输出模式GPIOA->CRL = 0x03;//3、对应的IO口设置值:1/0,PA0输出0,点亮LEDGPIOA->ODR = 0xFFFE;//1111 1111 1111 1110while(1){}
}
5、代码改进2
1、为了提高程序员开发的效率,st公司早已经将需要写入寄存器里面的值使用宏定义好了。
例如:开启对应的GPIOA的时钟,我们需要给RCC_APB2ENR寄存器里面写入数值0x04,而我们则可以通过RCC_APB2ENR_IOPAEN这段字符串来代替0x40这个数值。
RCC->APB2ENR = 0x04;//开启对应的GPIOA的时钟
改进为:
RCC->APB2ENR = RCC_APB2ENR_IOPAEN; //开启对应的GPIOA的时钟
2、前面给寄存器写入数据的时候,都是通过某某寄存器 = 数值。这样写入数据必然会影响寄存器中的其他位置的数据,例如GPIOA->ODR = 0xFFFE;//1111 1111 1111 1110这段代码,我只需要个IO0口输出低电平0,虽然我们成功写入了0,但是其他的IO引脚却因为我们写入的数据写入了高电平1。为了解决这种现象,我们可以通过位运算<<, >>, |, &, ~来解决我们的问题。
RCC->APB2ENR = RCC_APB2ENR_IOPAEN; //开启对应的GPIOA的时钟
改进为:
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; //开启对应的GPIOA的时钟
综上:改进的代码如下:
int main(void)
{
/*改进2:地址换为st公司定义好的宏,且使用位运算
*///1、开启对应的GPIOA的时钟RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;//2、给IO口设置工作模式:PA0配置为通用推挽输出模式,即MODE0 = 11,CNF0 = 00GPIOA->CRL |= GPIO_CRL_MODE0;GPIOA->CRL &= ~GPIO_CRL_CNF0;//3、对应的IO口设置值:1/0,PA0输出0,点亮LEDGPIOA->ODR &= ~GPIO_ODR_ODR0;//PA0引脚输出0while(1){}
}
改进代码总结:
①寄存器使用结构体指针来进行表示
②写入寄存器的值使用通过定义好的宏
③为了不影响寄存器的其他位的值最好使用位运算
④位运算时:若需要写入寄存器的值为1则用 |=,若需要写入寄存器的值为0则用 &=(其中数值则需要取反)。
相关文章:
01:(寄存器开发)点亮一个LED灯
寄存器开发 1、单片机的简介1.1、什么是单片机1.2、F1系列内核和芯片的系统架构1.3、存储器映像1.4、什么是寄存器 2、寄存器开发模板工程3、使用寄存器点亮一个LED4、代码改进15、代码改进2 本教程使用的是STM32F103C8T6最小系统板,教程来源B站up“嵌入式那些事”。…...
.Net 6.0 Windows平台如何判断当前电脑是否联网
最近在工作中开发需要判断当前电脑是否联网的需求,在网上找了一个调用window API来判断本机是否联网。具体请看下面介绍: 1.方法一(调用winAPI) [DllImport("wininet")] public static extern bool InternetGetConnec…...
微软准备了 Windows 11 24H2 ISO “OOBE/BypassNRO“命令依然可用
Windows 11 24H2 可能在未来几周内开始推出。 微软已经要求 OEM 遵循新的指南准备好 Windows 11 24H2 就绪的驱动程序,并且现在已经开始准备媒体文件 (.ISO)。 OEM ISO 的链接已在微软服务器上发布。 一个标有"X23-81971_26100.1742.240906-0331.ge_release_sv…...
MacOS 终端执行安装 Brew
在配置新的 Mac 环境时,如果你发现终端中无法识别 brew 命令,可以按照以下步骤进行解决。 步骤 1:确保网络稳定 为了避免安装过程中出现中断,建议使用 Wi-Fi 或有线连接,不推荐使用移动网络。 步骤 2:打…...
【设计模式-解释模式】
定义 解释器模式是一种行为设计模式,用于定义一种语言的文法,并提供一个解释器来处理该语言的句子。它通过为每个语法规则定义一个类,使得可以将复杂的表达式逐步解析和求值。这种模式适用于需要解析和执行语法规则的场景。 UML图 组成角色…...
51单片机应用开发(进阶)---数码管+按键+蜂鸣器(电磁炉显示模拟)
实现目标 1、加强数码管、按键的学习,实现数码显示变量数据(四位数的显示); 2、4位数码2个按键无源蜂鸣器实现模拟电磁炉功率调节及显示; 一、内容描述 功能描述:1、开机显示电磁炉功率300,每…...
Emergency Stop (ES)
文章目录 1. 介绍2. Feature List3. 紧急停止信号触发方式3.1 Port触发紧急停止信号3.2 SMU事件触发紧急停止信号3.3 软件触发紧急停止信号 4. 应用场景4.1 Port4.2 MSC 1. 介绍 Emergency Stop (ES)是Ifx System Control Units (SCU)六大模块之一。详细信息可以参考Infineon-…...
[C++][第三方库][gtest]详细讲解
目录 1.介绍2.安装3.使用1.头文件包含2.框架初始化接口3.调用测试样例4.TEST宏5.断言宏6.示例 1.介绍 gtest是一个跨平台的C单元测试框架,由Google公司发布gtest是为了在不同平台上为编写C单元测试而生成的,它提供了丰富的断言、致命和非致命判断、参数…...
【Java数据结构】 链表
【本节目标】 1. ArrayList 的缺陷 2. 链表 3. 链表相关 oj题目 一. ArrayList的缺陷 上节课已经熟悉了ArrayList 的使用,并且进行了简单模拟实现。通过源码知道, ArrayList 底层使用数组来存储元素: public class ArrayList<E>…...
前端——Ajax和jQuery
一、Ajax Ajax即“Asynchronous Javascript And XML”(异步 JavaScript 和 XML), 通过 JS 异步的向服务器发送请 求并接收响应数据。 同步访问:当客户端向服务器发送请求时,服务器在处理的过程中,浏览器…...
C++-vector模拟实现
###vector底层相当于是数组,查看源码可以发现,这个类的私有成员变量是三个迭代器;在实现时迭代器就可以当作是vector里面的元素的指针类型; ###vector是一个类模板,实现时也应当按照这样的写法用一个模板去实现&#…...
Activity
69[toc] 1.启停活动页面 1.Activity启动和结束 从当前页面跳到新页面 startActivity(new Intent(this, ActFinishActivity.class));从当前页面返回上一个页面,相当于关闭当前页面 finish();2.Activity生命周期 官方描述生命周期 onCreate:创建活…...
【力扣 | SQL题 | 每日四题】力扣1581, 1811, 1821, 1831
今天的题目就1811这个比较难,其他非常的基础。 1. 力扣1581:进店却未进行过交易的顾客 1.1 题目: 表:Visits ---------------------- | Column Name | Type | ---------------------- | visit_id | int | | customer…...
洛谷【P1955 [NOI2015] 程序自动分析】
反思: 这道题一眼就是并查集 但是数据太大 mle和re都是有可能的我看了题解才知道是离散化数组加并查集离散化再两个月前我觉得好难啊 那道题跟本看不懂 现在觉得还行 离散化思路: 需要一个离散记录数组----ls[N]用来记录下出现的数 步骤: …...
Swift并发笔记
1.同步和异步 说到线程的执行方式,最基本的一组概念是同步和异步。所谓同步,就是在操作执行完成之前,运行操作的这个线程都会被占用,直到函数最终被抛出或返回。Swift5.5之前,func关键字声明的所有的函数都是同步的。…...
React 组件命名规范
在 React 项目中,如果希望保持组件命名的一致性,并防止在引入时出现不同名称的问题,可以遵循以下的组件规范: 1、默认导出组件: 所有特殊要求的组件(如页面组件或根组件)应该使用 export defau…...
eNSP网络配置指南:IP设置、DNS、Telnet、DHCP与路由表管理
1.eNSP基本操作和路由器IP配置命令 登录设备:通过Console口或通过eNSP的Telnet/SSH客户端登录到设备。进入特权模式:输入system-view进入系统视图。接口配置: 进入接口视图,例如interface GigabitEthernet0/0/0。配置IP地址和子网…...
初步认识产品经理
产品经理 思考问题的维度 1️⃣为什么要抓住核心用户? 所有和产品有关系的群体就是用户,存在共性和差异了解用户的付费点,更好的优化产品是否使用:(目标用户-已使用产品:种子用户-尝鲜;核心用…...
web前端面试中拍摄的真实js面试题(真图)
web前端面试中拍摄的真实js面试题(真图) WechatIMG258.jpeg WechatIMG406.jpeg WechatIMG407.jpeg WechatIMG922.jpeg WechatIMG1063.jpeg © 著作权归作者所有,转载或内容合作请联系作者 喜欢的朋友记得点赞、收藏、关注哦!!…...
python 人工智能 机器学习 当损失函数的数值变成 `nan` 时,这通常意味着在模型训练过程中出现了数值不稳定性以及解决办法,数据分析
当损失函数的数值变成 nan 时,这通常意味着在模型训练过程中出现了数值不稳定性。以下是一些可能导致这个问题的原因以及相应的解决方法: 1. **学习率过高**:如果学习率设置得过高,可能会导致梯度爆炸,从而导致损失函…...
Kafka快速实战与基本原理详解
笔记:https://note.youdao.com/ynoteshare/index.html?id=b0357bdb4821ed2e35ecdbdacd65aa06&type=note&_time=1727570043631 启动kafka之前先启动zookper 看看ZK里面都有什么数据 : 刚开始什么数据都没有 接下来启动kafka,启动好后,日志在这里看: 启动好了kaf…...
tftp传文件被服务器拒绝进入tftp: server error: (768) Access to staonline.pcap denied
环境:测试一个ac下挂ap,ap下的抓包文件传出时,出现问题: ac的wan口ip是192.168.186.167/24,gw是192.168.186.1,下挂ap的ip是192.168.202.199/24,ac上开子接口192.168.202.1/24,ac上开…...
express,生成用户登录后的 token
在 Node.js 中使用 Express 框架生成用户登录后的 token,通常会涉及到以下几个步骤: 设置 Express 应用:首先,你需要有一个基本的 Express 应用。安装必要的中间件:例如 jsonwebtoken(JWT)用于…...
银河麒麟桌面操作系统修改默认Shell为Bash
银河麒麟桌面操作系统修改默认Shell为Bash 💐The Begin💐点点关注,收藏不迷路💐 在银河麒麟桌面操作系统(ARM版)中,若要将默认Shell从Dash改为Bash,可执行以下步骤: 打开…...
卷积神经网络(Convolutional Neural Networks, CNN)
卷积神经网络(Convolutional Neural Networks, CNN)是深度学习领域中用于处理具有网格结构的输入(如图像和视频)的神经网络模型。下面以最简单、直观的方式概述CNN的主要流程及其基本概念: 1. 输入层 概念:…...
SpringBoot系列 启动流程
文章目录 SpringApplicationSpringApplication#run 启动流程BootstrapContextSpringApplicationRunListenersprepareEnvironmentconfigureEnvironmentconfigurePropertySourcesconfigureProfiles 上下文初始化prepareContextrefreshContextprepareRefreshobtainFreshBeanFactor…...
vgg19提取特征
一般来说,大家使用VGG16,用的是第四列的网络架构,而使用VGG19,使用的就是第六列的网络架构。 使用vgg进行提取特征,在这个项目中,使用的就是每一块卷积层的第一层。 import torch.nn as nn from torchvis…...
Qt 中的 QChartView
深入理解 Qt 的 QChartView:图表展示与交互 QChartView 是 Qt Charts 模块中的一个核心类,它用于在 Qt 应用程序中显示图表,并支持多种用户交互方式。它继承自 QGraphicsView,通过封装 QChart,为用户提供了强大的图表…...
cheese安卓版纯本地离线文字识别插件
目的 cheese自动化平台是一款可以模拟鼠标和键盘操作的自动化工具。它可以帮助用户自动完成一些重复的、繁琐的任务,节省大量人工操作的时间。可以采用Vscode、IDEA编写,支持Java、Python、nodejs、GO、Rust、Lua。cheese也包含图色功能,识别…...
【C++】多肽
目录 一 多肽定义 1. 多肽的构成条件 1 例一 2 例二 2. 虚函数 3. 虚函数重写的两个意外 1 协变 2 析构函数的重写 二 关键字override 和 final 1. final 2.override 三 三重对比 1. 练习 四 多肽的原理 1. 多肽调用和普通调用 2.虚函数表 3. 分析 4. 原理 …...
做暧暧暖网站欧美/网络推广要求
!/bin/bashfor a in seq 1 9dofor b in seq 1 9doif [ $a -ge $b ];thenecho -en "$a x $b $(expr $a * $b) "fidoneecho ""##shell脚本中echo ""的作用done如上 脚本中:echo ""shell脚本中echo ""的作用不加入…...
做软件的网站php/网络营销的五大特点
一、在yum安装或者升级的过程中可能会遇到这个问题Could not open/read file:///etc/pki/rpm-gpg/RPM-GPG-KEY-puias参看这个网页里面的(http://linuxsysconfig.com/2013/03/running-multiple-python-versions-on-centos6rhel6sl6/):download…...
连锁会员管理系统/首页优化排名
关于验证大致分为两个方面: 用户登录时的验证;用户登录后每次访问时的权限认证主要解决方法:使用自定义的Shiro Filter 项目搭建: 这是一个spring-boot 的web项目,不了解spring-boot的项目搭建,请google。 …...
什么是网站建设公司/广告网站推荐
1月2日,NVIDIA正式发布了旗下显卡Linux操作系统最新的295.09版本,此次更新最大的改动就是在Linux下不需要Quadro专业显卡也可以实现10bit色深输出了(VGA、DVI-I、DisplayPort)。遗憾的是目前Windows操作系统下还是需要使用支持DX10以上规格的Quadro专业卡…...
免费申请网站永久域名/淘宝运营培训班
ItemsControl是一个基础类型,控件本身没有内置滚动条。如果不喜欢ListBox默认的复制样式,只是需要一个简单的可滚动Items Control,可以给ItemsControl的Template加一个ScrollViewer: <ItemsControl.Template> …...
建筑企业登录哪个网站/公众号软文推广
2019独角兽企业重金招聘Python工程师标准>>> 使用场景:适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。 引用网上的一个例子:笔记本电脑电源一般用的都…...