当前位置: 首页 > news >正文

野火霸天虎 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 函数,必须勾选下面这一项。

image-20231102200243099

野火你讲的是真好啊。我之前草草学了学 stm32 单片机用法,比赛的时候自己想移植代码,改了启动文件也不好使,就是报错。原来是这个原因。

那么我们只需要定义这么一个函数,哪怕内容是空都无所谓。

最终我们定义的初步项目框架如下:

1698926683862

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 灯的寄存器位置。阅读原理图如下:

1698939342199

大致可以看出,板子上的这个 RGB LED 通过三个引脚来控制 RGB 亮度。输出低电平则导通点亮。

具体输出方式是通过 ODR 进行输出。查找 stm32f4xx 中文参考手册可见:

1698940158585

1698940257044

那么我们就要给 0x4002 1400 +14 的地址赋值,让 1<<6 1<<7 1<<8 的位分别赋值为低电平.

int main(){*(unsigned int *)(0x40021400+14)&=~(1<<6); while(1){}
}

然而这样也不亮。亮就怪了,stm32 寄存器是需要先做初始化配置的。

点灯——stm32 版

首先我们要设置 GPIO 模式。

1698940961543

想点灯 输出高低电平,是 01 通用输出模式。

*(unsigned int *)(0x40021400+0)&=~(3<<(6*2)); 
*(unsigned int *)(0x40021400+0)|=(1<<(6*2)); 

意思是先把 PF6 模式位置为00,然后赋值为01通用输出。

配置完模式之后,还需要配置时钟,stm32 每个外设都需要配置时钟。

前面提到过 GPIO 是在 AHB1.

1699103516061

1699103724261

全部代码如下:

#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 框图(重点)如下:

image-20231104221140325

先从输出开始看。最右侧的 IO 引脚是连接在芯片周围一圈的144个引脚之一。除了 IO 引脚,此图中其他所有部分都是封装在芯片内部我们看不到的。

往左有两个保护二极管。当电压大于 5V,电流会往上 VDD_FT 走。当电压为负电压,电流会由 VSS 往 IO 引脚走。

上下拉电阻:比武外接一个低电平工作的设备,但是我们不希望一上电外设就工作,可以设置上拉电阻,稳定一段时间。

GPIO 输出的数据来源:复位寄存器 BSRR,或者 ODR 设置(图中的3下路部分)。复位寄存器高16位复位(写1置0)低16位置位(写1置1),置位优先级更高。

配置 GPIO 模式(输入/输出,选择哪一路)通过前面用过的 MODER 配置。

输出模式(图中输出控制部分)配置端口输出类型寄存器 OTYPER,比如推挽输出,开漏输出。

推挽输出:有直接驱动能力,输出0就是低电平,输出1就输出可以工作的高电平。原理是采用了一个放大的电路?

1699356797818

输入(INT)为高电平时,反向后 PMOS 导通,输出高电平。输入为低电平时,反向后 NMOS 导通,输出低电平。我们可以用一个小电流去驱动出来一个大电流。

开漏输出:自己本身没有输出高电平的手段。低电平可以接地,高电平没有 PMOS 管,是浮空状态。需要外接一个电阻。

1699357078909

stm32 输出 5V 电压的方法就是开漏输出外接电阻。通过接两个三极管的方式反向。

1699357296750

框图中的模拟部分输入输出则不用配置这些模式信息,直接由外设接到保护二极管再接到输出引脚。

框图中的输入部分经过保护电压后,还需要施密特触发器调整一下。比如原来电压的数值并非精确的0或 3.3V,施密特触发器将高于 1.8V 的全部视作1,低于的全部视作0后输入芯片。模拟部分则不需要经过施密特触发器。

因此配置 GPIO 输出的步骤如下:

  1. GPIO 功能,通用输出、复用功能、模拟输入等 MODER;
  2. 输出推挽 or 开漏 OTYPER;
  3. 输出速度 OSPEEDR;
  4. 上下拉电阻是否需要开启 PUPDR;
  5. 具体输出内容 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 灯

新建工程 寄存器方式 要命啊&#xff0c;一看名字我就不想试。寄存器新建不得麻烦死。 哎算了为了学习原理&#xff0c;干了。 我们尝试自己写一个寄存器的库函数来引用。 首先我们需要引用 st 官方启动文件 stmf4xx.s&#xff0c;具体用途后面章节再展开讲解。然后我们自…...

ZZ308 物联网应用与服务赛题第F套

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

怎样选择文件外发控制系统,让数据实现高效安全交换?

制造型企业都非常重视其知识产权&#xff08;IP&#xff09;的安全性&#xff0c;尤其是其最有价值的产品设计数据的安全问题。基于复杂的供应链生态&#xff0c;每天可能要与几十家甚至上百家供应商及合作伙伴进行数据交换。不管是一级还是二级供应商&#xff0c;合作伙伴还是…...

专访 SPACE ID:通往 Web3 无许可域名服务协议之路

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

合并分支--将自己的分支合并到master分支

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

力扣:153. 寻找旋转排序数组中的最小值(Python3)

题目&#xff1a; 已知一个长度为 n 的数组&#xff0c;预先按照升序排列&#xff0c;经由 1 到 n 次 旋转 后&#xff0c;得到输入数组。例如&#xff0c;原数组 nums [0,1,2,4,5,6,7] 在变化后可能得到&#xff1a; 若旋转 4 次&#xff0c;则可以得到 [4,5,6,7,0,1,2]若旋转…...

matlab中实现画函数图像添加坐标轴

大家好&#xff0c;我是带我去滑雪&#xff01; 主函数matlab代码&#xff1a; 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又是一个完全平方数,请问该数是多少?

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

AtCoder abc148

C题 求GCD D题 顺序遍历 E题 trailing zero只与5的个数有关&#xff0c;因此算一下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以上版本&#xff0c;请先单独卸载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.内建命令 四、完整代码&#xff1a; 0.准备工作 1.大体框架 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h> #include <u…...

Kafka -- 架构、分区、副本

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

CSS特效001:鼠标放div上,实现旋转、放大、移动等效果

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

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&#xff0c;并让单点mongodb支持事务&#xff0c;mongodb5以上时才支持事务&#xff0c;所以必须时mongodb5及以上版本才支持。 1、下载mongodb安装文件 &#xff08;1&#xff09; 下载mongodb msi 安装文件 地址&#xff1a;mongocommunity &…...

【通信原理】第三章 随机过程——例题

一、随机过程 1. 数学特征 ① 随机信号&#xff08;三角函数表达式&#xff09; ② 随机信号&#xff08;求和表达式&#xff09; 2. 功率谱密度 ① 相位确定&#xff0c;求功率谱密度 ② 已知相位分布&#xff0c;求功率谱密度 ③ 信号为两信号之和&#xff0c;求功率谱密度…...

线性【SVM】数学原理和算法实现

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

R语言中的函数26:polyroot多项式求根函数

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

2023年辽宁省数学建模竞赛A题铁路车站的安全标线

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

半导体工厂将应用哪些制造创新技术?

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

深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录

ASP.NET Core 是一个跨平台的开源框架&#xff0c;用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录&#xff0c;以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具

文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

从零实现STL哈希容器:unordered_map/unordered_set封装详解

本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...

leetcodeSQL解题:3564. 季节性销售分析

leetcodeSQL解题&#xff1a;3564. 季节性销售分析 题目&#xff1a; 表&#xff1a;sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...

听写流程自动化实践,轻量级教育辅助

随着智能教育工具的发展&#xff0c;越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式&#xff0c;也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建&#xff0c;…...

Python 包管理器 uv 介绍

Python 包管理器 uv 全面介绍 uv 是由 Astral&#xff08;热门工具 Ruff 的开发者&#xff09;推出的下一代高性能 Python 包管理器和构建工具&#xff0c;用 Rust 编写。它旨在解决传统工具&#xff08;如 pip、virtualenv、pip-tools&#xff09;的性能瓶颈&#xff0c;同时…...

搭建DNS域名解析服务器(正向解析资源文件)

正向解析资源文件 1&#xff09;准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2&#xff09;服务端安装软件&#xff1a;bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...

【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)

前言&#xff1a; 双亲委派机制对于面试这块来说非常重要&#xff0c;在实际开发中也是经常遇见需要打破双亲委派的需求&#xff0c;今天我们一起来探索一下什么是双亲委派机制&#xff0c;在此之前我们先介绍一下类的加载器。 目录 ​编辑 前言&#xff1a; 类加载器 1. …...

用神经网络读懂你的“心情”:揭秘情绪识别系统背后的AI魔法

用神经网络读懂你的“心情”:揭秘情绪识别系统背后的AI魔法 大家好,我是Echo_Wish。最近刷短视频、看直播,有没有发现,越来越多的应用都开始“懂你”了——它们能感知你的情绪,推荐更合适的内容,甚至帮客服识别用户情绪,提升服务体验。这背后,神经网络在悄悄发力,撑起…...

AWS vs 阿里云:功能、服务与性能对比指南

在云计算领域&#xff0c;Amazon Web Services (AWS) 和阿里云 (Alibaba Cloud) 是全球领先的提供商&#xff0c;各自在功能范围、服务生态系统、性能表现和适用场景上具有独特优势。基于提供的引用[1]-[5]&#xff0c;我将从功能、服务和性能三个方面进行结构化对比分析&#…...