野火霸天虎 STM32F407 学习笔记_3 尝试寄存器映射方式点亮 LED 灯
新建工程
寄存器方式
要命啊,一看名字我就不想试。寄存器新建不得麻烦死。
哎算了为了学习原理,干了。
我们尝试自己写一个寄存器的库函数来引用。
首先我们需要引用 st 官方启动文件 stmf4xx.s,具体用途后面章节再展开讲解。然后我们自己新建一个 stm32f4xx.h 文件来映射寄存器。不过只是把这个文件包含进项目,编译会报错:
.\Objects\led_reg.axf: Error: L6218E: Undefined symbol SystemInit (referred from startup_stm32f40xx.o).
进入启动文件后,可以看到这么一个函数:
; Reset handler
Reset_Handler PROCEXPORT Reset_Handler [WEAK]IMPORT SystemInitIMPORT __mainLDR R0, =SystemInitBLX R0LDR R0, =__mainBX R0ENDP
import 的作用相当于 extern,所以没有找到这个函数的定义,需要我们自己去定义。这就是为什么简单引入了启动文件会报错。
而 __main 是当我们定义了 main() 函数后,编译器会自动链接一些c语言库定义好的函数,用于初始化堆栈并且调用我们的 main().
注意,如果想要生成 __main 函数,必须勾选下面这一项。
野火你讲的是真好啊。我之前草草学了学 stm32 单片机用法,比赛的时候自己想移植代码,改了启动文件也不好使,就是报错。原来是这个原因。
那么我们只需要定义这么一个函数,哪怕内容是空都无所谓。
最终我们定义的初步项目框架如下:
stm32f4xx.h:内容为空,有这么个东西就行。
main.c:
#include "stm32f4xx.h"int main(){while(1){}
}void SystemInit(){}
好了,这个程序可以烧录到板子上的。烧录成功之后没有任何反应(因为本来程序也没做什么哈哈),但是这就是一个大进步了。
点灯——51单片机版
51单片机版就是引用 reg51.h 头文件,在其中声明了各个引脚的地址。我们只需要直接给引脚赋值即可。
调用代码:
#include "reg51.h"#ifdef 0
void main(){PA0=0xFE;while(1){}
}
#endif
接下来我们需要定义 LED 灯的寄存器位置。阅读原理图如下:
大致可以看出,板子上的这个 RGB LED 通过三个引脚来控制 RGB 亮度。输出低电平则导通点亮。
具体输出方式是通过 ODR 进行输出。查找 stm32f4xx 中文参考手册可见:
那么我们就要给 0x4002 1400 +14 的地址赋值,让 1<<6 1<<7 1<<8 的位分别赋值为低电平.
int main(){*(unsigned int *)(0x40021400+14)&=~(1<<6); while(1){}
}
然而这样也不亮。亮就怪了,stm32 寄存器是需要先做初始化配置的。
点灯——stm32 版
首先我们要设置 GPIO 模式。
想点灯 输出高低电平,是 01 通用输出模式。
*(unsigned int *)(0x40021400+0)&=~(3<<(6*2));
*(unsigned int *)(0x40021400+0)|=(1<<(6*2));
意思是先把 PF6 模式位置为00,然后赋值为01通用输出。
配置完模式之后,还需要配置时钟,stm32 每个外设都需要配置时钟。
前面提到过 GPIO 是在 AHB1.
全部代码如下:
#include "stm32f4xx.h"int main(){//RCC*(unsigned int *)(0x40023800+0x30)|=(1<<5); //Mode*(unsigned int *)(0x40021400+0)&=~(3<<(6*2)); *(unsigned int *)(0x40021400+0)|=(1<<(6*2)); *(unsigned int *)(0x40021400+0x14)&=~(1<<6); while(1){}
}void SystemInit(){}
接下来,我们把这几个地址值提取出来,宏定义映射寄存器。
//stm32f4xx.h
/* 用来存放寄存器映射相关的代码 */
#define RCC_AHB1_ENR *(unsigned int *)(0x40023800+0x30)
#define GPIOF_MODER *(unsigned int *)(0x40021400+0)
#define GPIOF_ODR *(unsigned int *)(0x40021400+0x14)//main.c
#include "stm32f4xx.h"int main(){//RCCRCC_AHB1_ENR|=(1<<5); //ModeGPIOF_MODER&=~(3<<(6*2)); GPIOF_MODER|=(1<<(6*2)); GPIOF_ODR&=~(1<<6); while(1){}
}void SystemInit(){}
点灯——流水灯闪烁
利用软件延时实现 RGB 流水灯闪烁。很简单,前面已经看了3个 LED 通道 PF678 了。
#include "stm32f4xx.h"void delay_ms(int time);int main(){//RCCRCC_AHB1_ENR|=(1<<5); //ModeGPIOF_MODER&=~(3<<(6*2)); GPIOF_MODER|=(1<<(6*2)); GPIOF_MODER&=~(3<<(7*2)); GPIOF_MODER|=(1<<(7*2)); GPIOF_MODER&=~(3<<(8*2)); GPIOF_MODER|=(1<<(8*2)); while(1){GPIOF_ODR|=(7<<6);GPIOF_ODR&=~(1<<6);delay_ms(1000);GPIOF_ODR|=(7<<6);GPIOF_ODR&=~(1<<7); delay_ms(1000);GPIOF_ODR|=(7<<6);GPIOF_ODR&=~(1<<8);delay_ms(1000);}
}void SystemInit(){}//毫秒级的延时
void delay_ms(int time)
{ int i=0; while(time--){i=4000;while(i--) ; }
}
点灯——GPIO 具体功能框图对应
GPIO:通用输入输出引脚。我们可以通过编程来输出或者读取数据。大部分 GPIO 是已经连接、定义好了一些功能(比如上面尝试过的 PF6 LED),有的引脚有多个功能支持重新映射。
STM32 GPIO 除了 adc 是 3.3v,其他 GPIO 都是 5v 容忍。
GPIO 框图(重点)如下:
先从输出开始看。最右侧的 IO 引脚是连接在芯片周围一圈的144个引脚之一。除了 IO 引脚,此图中其他所有部分都是封装在芯片内部我们看不到的。
往左有两个保护二极管。当电压大于 5V,电流会往上 VDD_FT 走。当电压为负电压,电流会由 VSS 往 IO 引脚走。
上下拉电阻:比武外接一个低电平工作的设备,但是我们不希望一上电外设就工作,可以设置上拉电阻,稳定一段时间。
GPIO 输出的数据来源:复位寄存器 BSRR,或者 ODR 设置(图中的3下路部分)。复位寄存器高16位复位(写1置0)低16位置位(写1置1),置位优先级更高。
配置 GPIO 模式(输入/输出,选择哪一路)通过前面用过的 MODER 配置。
输出模式(图中输出控制部分)配置端口输出类型寄存器 OTYPER,比如推挽输出,开漏输出。
推挽输出:有直接驱动能力,输出0就是低电平,输出1就输出可以工作的高电平。原理是采用了一个放大的电路?
输入(INT)为高电平时,反向后 PMOS 导通,输出高电平。输入为低电平时,反向后 NMOS 导通,输出低电平。我们可以用一个小电流去驱动出来一个大电流。
开漏输出:自己本身没有输出高电平的手段。低电平可以接地,高电平没有 PMOS 管,是浮空状态。需要外接一个电阻。
stm32 输出 5V 电压的方法就是开漏输出外接电阻。通过接两个三极管的方式反向。
框图中的模拟部分输入输出则不用配置这些模式信息,直接由外设接到保护二极管再接到输出引脚。
框图中的输入部分经过保护电压后,还需要施密特触发器调整一下。比如原来电压的数值并非精确的0或 3.3V,施密特触发器将高于 1.8V 的全部视作1,低于的全部视作0后输入芯片。模拟部分则不需要经过施密特触发器。
因此配置 GPIO 输出的步骤如下:
- GPIO 功能,通用输出、复用功能、模拟输入等 MODER;
- 输出推挽 or 开漏 OTYPER;
- 输出速度 OSPEEDR;
- 上下拉电阻是否需要开启 PUPDR;
- 具体输出内容 BSRR or ODR.
输入部分后面输入实验介绍~
按整个流程重新串一遍代码,如下:(其实和前面差不多,就是重新按照流程串了一遍)
/* 用来存放寄存器映射相关的代码 */
#define RCC_BASE (unsigned int *) 0x40023800
#define GPIOF_BASE (unsigned int *) 0x40021400#define RCC_AHB1ENR *(RCC_BASE+0x30)#define GPIOF_MODER *(GPIOF_BASE+0x00)
#define GPIOF_OSPEEDR *(GPIOF_BASE+0x08)
#define GPIOF_PUPDR *(GPIOF_BASE+0x0C)
#define GPIOF_ODR *(GPIOF_BASE+0x14)
#define GPIOF_BSRR *(GPIOF_BASE+0x18)//main.c
#include "stm32f4xx.h"int main()
{RCC_AHB1ENR |= (1<<5);GPIOF_MODER &= ~(3<<(6*2));GPIOF_MODER |= (1<<(6*2));while (1){}
}void SystemInit()
{
}
烧录前记得勾选:use MicroLib.
相关文章:

野火霸天虎 STM32F407 学习笔记_3 尝试寄存器映射方式点亮 LED 灯
新建工程 寄存器方式 要命啊,一看名字我就不想试。寄存器新建不得麻烦死。 哎算了为了学习原理,干了。 我们尝试自己写一个寄存器的库函数来引用。 首先我们需要引用 st 官方启动文件 stmf4xx.s,具体用途后面章节再展开讲解。然后我们自…...

ZZ308 物联网应用与服务赛题第F套
2023年全国职业院校技能大赛 中职组 物联网应用与服务 任 务 书 (F卷) 赛位号:______________ 竞赛须知 一、注意事项 1.检查硬件设备、电脑设备是否正常。检查竞赛所需的各项设备、软件和竞赛材料等; 2.竞赛任务中所使用…...

怎样选择文件外发控制系统,让数据实现高效安全交换?
制造型企业都非常重视其知识产权(IP)的安全性,尤其是其最有价值的产品设计数据的安全问题。基于复杂的供应链生态,每天可能要与几十家甚至上百家供应商及合作伙伴进行数据交换。不管是一级还是二级供应商,合作伙伴还是…...

专访 SPACE ID:通往 Web3 无许可域名服务协议之路
Web3 行业发展风起云涌,对于初创项目而言,如何寻找适合自己的赛道是首要问题。当前伴随用户交互和跨平台操作需求日渐兴起,如何更迅速地使用一站式域名实现便捷验证成为大众的心头期盼。 这一背景下,SPACE ID 于众星林立的 Web3 …...

合并分支--将自己的分支合并到master分支
在版本控制系统(例如Git)中,将自己的分支合并到master(或者主分支)通常需要以下步骤: ### 1. 切换到主分支 首先,确保你的本地仓库当前处于主分支。你可以使用以下命令切换到主分支࿱…...

力扣:153. 寻找旋转排序数组中的最小值(Python3)
题目: 已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums [0,1,2,4,5,6,7] 在变化后可能得到: 若旋转 4 次,则可以得到 [4,5,6,7,0,1,2]若旋转…...

matlab中实现画函数图像添加坐标轴
大家好,我是带我去滑雪! 主函数matlab代码: function PlotAxisAtOrigin(x,y); if nargin 2 plot(x,y);hold on; elsedisplay( Not 2D Data set !) end; Xget(gca,Xtick); Yget(gca,Ytick); XLget(gca,XtickLabel); YLget(gca,YtickLabel)…...

C语言求解一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请问该数是多少?
完整代码: /* 一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请问 该数是多少?*/ #include<stdio.h>int main(){//num为最终所求那个数int num;//i*i为第一个完全平方数for (int i 10; …...

AtCoder abc148
C题 求GCD D题 顺序遍历 E题 trailing zero只与5的个数有关,因此算一下5/25/125…的倍数 # -*- coding: utf-8 -*- # time : 2023/6/2 13:30 # file : atcoder.py # software : PyCharmimport bisect import copy import sys from itertools import perm…...

k8s、docker 卸载
k8s卸载 k8s 重置 kubeadm reset -f如果kubernets是1.24以上版本,请先单独卸载containerd sudo apt purge containerd.iok8s软件卸载 ubuntu #apt卸载 apt purge kubelet kubeadm kubectlcentos yum erase -y kubelet kubectl kubeadm 删除kubelet相关信息&am…...

【Linux】Shell命令行的简易实现(C语言实现)内键命令,普通命令
文章目录 0.准备工作1.大体框架 一、获取命令行二、解析命令行三、进程执行1.普通命令2.内建命令 四、完整代码: 0.准备工作 1.大体框架 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h> #include <u…...

Kafka -- 架构、分区、副本
1、Kafka的架构: 1、producer:消息的生产者 2、consumer:消息的消费者 3、broker:kafka集群的服务者,一个broker就是一个节点,主要是负责处理消息的读、写的请求和存储消息。在kafka cluster中包含很多的br…...

CSS特效001:鼠标放div上,实现旋转、放大、移动等效果
GPT能够很好的应用到我们的代码开发中,能够提高开发速度。你可以利用其代码,做出一定的更改,然后实现效能。 css实战中,经常会看到这样的场景,鼠标放到一个图片或者一个div块状时候,会出现旋转、放大、移动…...

gin 快速入门手册
文章目录 安装URL和路由分组2. 带参数的url3. 获取路由分组的参数 获取参数1. 获取get参数2. 获取post参数3. get、post混合 JSON 、 ProtoBuf渲染1. 输出json和protobuf2. PureJSON 表单验证1. 表单的基本验证 中间件和next函数1. 无中间件启动2. 使用中间件3. 自定义组件 设置…...

Window下安装 Mongodb,并实现单点事务
在window操作系统下安装Mongodb,并让单点mongodb支持事务,mongodb5以上时才支持事务,所以必须时mongodb5及以上版本才支持。 1、下载mongodb安装文件 (1) 下载mongodb msi 安装文件 地址:mongocommunity &…...

【通信原理】第三章 随机过程——例题
一、随机过程 1. 数学特征 ① 随机信号(三角函数表达式) ② 随机信号(求和表达式) 2. 功率谱密度 ① 相位确定,求功率谱密度 ② 已知相位分布,求功率谱密度 ③ 信号为两信号之和,求功率谱密度…...

线性【SVM】数学原理和算法实现
一. 数学原理 SVM是一类有监督的分类算法,它的大致思想是:假设样本空间上有两类点,如下图所示,我们希望找到一个划分超平面,将这两类样本分开,我们希望这个间隔能够最大化来使得模型泛化能力最强。 如上图所…...

R语言中的函数26:polyroot多项式求根函数
目录 介绍函数介绍参数含义 示例 介绍 R语言中的base::polyroot()可以用于对多项式求根,求根的多项式可以是复数域上的。 函数介绍 polyroot(z)该函数利用Jenkins-Traub算法对多项式 p ( x ) p(x) p(x)进行求根,其中 p ( x ) z 1 z 2 x ⋯ z n x…...

2023年辽宁省数学建模竞赛A题铁路车站的安全标线
2023年辽宁省数学建模竞赛 A题 铁路车站的安全标线 原题再现: 在火车站或地铁站台上,离站台边缘 1 米左右的地方都画有一条黄线(或白线),这是为什么呢? 这条线称为安全线(业内称之为安全标线),人们在候车时必须站在安全线以…...

半导体工厂将应用哪些制造创新技术?
半导体工厂是高科技产业的结晶,汇聚了世界上最新的技术。 在半导体的原料硅晶片上绘制设计图纸,不产生误差,准确切割并包装,然后用芯片生产出我们使用的电脑、智能手机、手表等各种电子产品。绝大多数半导体厂都采用一贯的工艺&a…...

[unity]深色模式/浅色模式
这里用的是Windows版的unity,具体版本号如下: 选项的路径如下:Edit—Preferences—General—Editor Theme 然后就可以选是dark还是light了:...

在react中组件间过渡动画如何实现?
一、是什么 在日常开发中,页面切换时的转场动画是比较基础的一个场景 当一个组件在显示与消失过程中存在过渡动画,可以很好的增加用户的体验 在react中实现过渡动画效果会有很多种选择,如react-transition-group,react-motion&…...

解析找不到msvcr100.dll文件的解决方法,4个方法修复msvcr100.dll
msvcr100.dll是Microsoft Visual C 2010运行库的组成部分,一些基于Visual C开发的软件运行时会依赖这个dll文件。出现“找不到msvcr100.dll”的错误提示,往往意味着这个文件在你的计算机系统中丢失或损坏,导致相关程序无法正常运行。以下是找…...

达梦主备部署
达梦主备部署 一.概括1)环境软件下载2)集群规划 二.安装1)安装前2)安装数据库 三.主备机器部署1)初始化数据库(1)主库配置(2)备库配置 2)脱机备份(1)主服务器…...

后期混音效果全套插件Waves 14 Complete mac中文版新增功能
Waves 14 Complete for Mac是一款后期混音效果全套插件,Waves音频插件,内置混响,压缩,降噪和EQ等要素到建模的模拟硬件,环绕声和后期制作工具,包含全套音频效果器,是可以让你使用所有功能。Waves 14 Comple…...

HTML5笔记
前端学习笔记专栏区别于官网中全面的知识讲解,主要记录学习技术栈时对于重点内容的提炼,便于对技术栈知识的快速回顾以及使用 1.canvas元素 内部坐标:坐标均以左上角为(0, 0),单一坐标均作为起始坐标创建对象: <c…...

前端架构师需要解决那些问题
假设你是一个大型后台管理系统的前端架构师,你需要解决那些问题? 1、Ui设计规范 大型系统UI得统一吧?各个业务模块的UI设计得高效吧?那就得有规范,直观的说就是原子设计那套东西。加一堆推荐设计稿。 2、基础组件库…...

使用python快速搭建接口自动化测试脚本实战总结
导读 本文将介绍如何使用python快速进行http/https接口自动化测试脚本搭建,实现自动请求、获取结果、数据对比分析,导出结果到Excel等功能,包括python的requests、pandas、openpyxl等库的基本使用方法。 测试需求介绍 通常,在我…...

android studio 字节码查看工具jclasslib bytecode viewer
jclasslib bytecode viewer 是一款非常好用的.class文件查看工具; jclasslib bytecode editor is a tool that visualizes all aspects of compiled Java class files and the contained bytecode. Many aspects of class files can be edited in the UI. In addit…...

Ubuntu上搭建FTP服务
要在Ubuntu上搭建FTP服务器,可以使用常见的FTP服务器软件如vsftpd(Very Secure FTP Daemon)或ProFTPD。以下是使用vsftpd在Ubuntu上设置FTP服务器的基本步骤: 步骤 1: 安装 vsftpd 打开终端并运行以下命令安装 vsftpd:…...