STM32 寄存器操作 GPIO 与中断

news2025/1/21 15:34:00

 一、如何使用stm32寄存器点灯?

1.1 寄存器映射表

寄存器本质就是一个开关,当我们把芯片寄存器配置指定的状态时即可使用芯片的硬件能力。

寄存器映射表则是开关的地址说明。对于我们希望点亮 GPIO_B 的一个灯来说,需要关注以下的两个寄存器:

 

1.2 配置时钟

对于我们实现希望点亮一个灯的需求来说,不仅需要配置配置 GPIO_B 的时钟,首先需要配置 GPIO_B 的时钟。

为什么需要先配置时钟呢?

STM32 外设通常都是给了时钟后才能设置它的寄存器(即才能使用这个外设)。STM32、LPC1XXX 等等都是这样,这么做的目的是为了省电,使用了所谓时钟门控的技术。寄存器是基于触发器的,触发器的赋值是一定需要时钟的,而寄存器的时钟是由总线时钟提供的,就是说没有总线时钟的话,你给寄存器值它是不会读入的。

对于下图中的系统框图来看,GPIO_B 挂载在 AHB 总线下 APB2 时钟。所以我们需要开启 APB2 的总线时钟。

STM32F10xxx 参考手册 6.3.7 告诉我们怎么使能 GPIO_B 的时钟。

 

由 1.1 的寄存器映射表图片来看,寄存器映射表可知

0x40000000(片上外设基地址) + 0x20000(AHB总线基地址) + 0x1000 (RCC外设基地址)

最后我们再加上 RCC_APBENR 的地址 0x18 即可成功访问这个寄存器。

对这个寄存器使用左移三位进行置位 IOPB 操作,这样就成功开启了 GPIO_B 时钟。

int main(void)
{
    //片上外设基地址+AHB总线基地址+RCC外设基地址+RCC的AHB1时钟使能寄存器地址
    *(unsigned int*)(0x40000000+0x20000+0x1000+0x18) |= ((1)<<3);
	while(1);
}

// 函数为空,目的是为了骗过编译器不报错
void SystemInit(void)
{
    
}

 值得注意的是这种写法,相当于向地址 0XFF 写入 0XFE。

*(unsigned int*)0xFE = 0XFF;
//等价于
unsigned int *p = 0xFE;    //无符号 uint32_t 指针类型指向 0XFE 这个地址
*p = 0xFF;                 //解地址符 向这个地址写入0XFF

1.3 配置 GPIOB_0 模式

根据芯片手册提示 如果我们需要把 GPIOB_0 配置为输出高电平,只需要将 GPIO_CRL 第四位寄存器配置成 0001 即可,这代表了通用开漏输出模式,最大输出10MHz。

//片上外设基地址+APB2总线基地址+GPIOB外设基地址+GPIOB_CRL地址
*(unsigned int*)(0x40000000+0x10000+0x0C00+0x00) &= ~( (0xFF)<<(4*0) );    //低四位清零
*(unsigned int*)(0x40000000+0x10000+0x0C00+0x00) |=  ( (1) << (4*0) );    //第四位搞成0001

 1.4 配置 GPIOB_0 使其输出低电平

//片上外设基地址+APB2总线基地址+GPIOB外设基地址+GPIOx_ODR地址
*(unsigned int*)(0x40000000+0x10000+0x0C00+0x0C) &= ~(1<<0);

经过以上我们配置了 RCC_APB2ENR、GPIOB_CRL、GPIOB_ODR寄存器后。GPIOB_0 被配置成了开漏输出低电平。这样就可以点亮我们的灯泡了。

 全部代码如下:

#include "stm32f10x.h"

int main(void)
{
    //片上外设基地址+AHB总线基地址+RCC外设基地址+RCC的AHB1时钟使能寄存器地址
    *(unsigned int*)(0x40000000+0x20000+0x1000+0x18) |= ((1)<<3);
    
    //片上外设基地址+APB2总线基地址+GPIOB外设基地址+GPIOB_CRL地址
    *(unsigned int*)(0x40000000+0x10000+0x0C00+0x00) &= ~( (0xFF)<<(4*0) );
    *(unsigned int*)(0x40000000+0x10000+0x0C00+0x00) |=  ( (1) << (4*0) );
    
    //片上外设基地址+APB2总线基地址+GPIOB外设基地址+GPIOx_ODR地址
    *(unsigned int*)(0x40000000+0x10000+0x0C00+0x0C) &= ~(1<<0);
    
	while(1);
}

// 函数为空,目的是为了骗过编译器不报错
void SystemInit(void)
{
    
}

二、配置输入模式

 

 我们希望将 GPIOA_0 配置成浮空输入,根据上表来配置寄存器。

/* PA0 key1引脚 */
//片上外设基地址+AHB总线基地址+RCC外设基地址+RCC的AHB1时钟使能PA寄存器地址
*(unsigned int*)(0x40000000+0x20000+0x1000+0x18) |= ((1)<<2);

//片上外设基地址+APB2总线基地址+GPIOA外设基地址+GPIOA_CRL地址
*(unsigned int*)(0x40000000+0x10000+0x0800+0x00) &= ~( (0xFF) << (4*0) );
*(unsigned int*)(0x40000000+0x10000+0x0800+0x00) |=  ( (0X04) << (4*0) );

在最后一行,我们将GPIOA_CRL 寄存器低四位配置成 0100 是浮空输入。

全部代码如下:

#include "stm32f10x.h"

int main(void)
{
    /* PB1 点灯引脚  */
    //片上外设基地址+AHB总线基地址+RCC外设基地址+RCC的AHB1时钟使能PB寄存器地址
    //打开PB时钟
    *(unsigned int*)(0x40000000+0x20000+0x1000+0x18) |= ((1)<<3);
    
    //片上外设基地址+APB2总线基地址+GPIOB外设基地址+GPIOB_CRL地址
    //配置成PB1开漏输出
    *(unsigned int*)(0x40000000+0x10000+0x0C00+0x00) &= ~( (0xFF)<<(4*0) );
    *(unsigned int*)(0x40000000+0x10000+0x0C00+0x00) |=  ( (1) << (4*0) );
    
    //片上外设基地址+APB2总线基地址+GPIOB外设基地址+GPIOx_ODR地址
    //默认给一个PB1高电平 灯灭
    *(unsigned int*)(0x40000000+0x10000+0x0C00+0x0C) = 1;
    
    /* PA0 key1引脚 */
    //片上外设基地址+AHB总线基地址+RCC外设基地址+RCC的AHB1时钟使能PA寄存器地址
    //打开PA时钟
    *(unsigned int*)(0x40000000+0x20000+0x1000+0x18) |= ((1)<<2);
    
    //片上外设基地址+APB2总线基地址+GPIOA外设基地址+GPIOA_CRL地址
    //配置成PA0浮空输入
    *(unsigned int*)(0x40000000+0x10000+0x0800+0x00) &= ~( (0xFF) << (4*0) );
    *(unsigned int*)(0x40000000+0x10000+0x0800+0x00) |=  ( (0X04) << (4*0) );
        
    
	while(1){
        //片上外设基地址+APB2总线基地址+GPIOB外设基地址+GPIOB_IDR地址
        //读取是否按下按钮
        if(*(unsigned int*)(0x40000000+0x10000+0x0800+0x08) & 1 != 0)
            //片上外设基地址+APB2总线基地址+GPIOB外设基地址+GPIOx_ODR地址
            //低电平 灯灭
            *(unsigned int*)(0x40000000+0x10000+0x0C00+0x0C) &= ~(1<<0);
        else
            //片上外设基地址+APB2总线基地址+GPIOB外设基地址+GPIOx_ODR地址
            //高电平 灯灭
            *(unsigned int*)(0x40000000+0x10000+0x0C00+0x0C) = 1;
    }
}

// 函数为空,目的是为了骗过编译器不报错
void SystemInit(void)
{
    
}

这样我们就实现了按下按钮点灯的操作。

本质上是等待 PA0 低电平后就把 PB1 拉低的程序。

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1446823.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux---网络套接字

端口号 端口号 端口号是一个2字节16位的整数; 端口号用来标识一个进程, 告诉操作系统, 当前的这个数据要交给哪一个进程来处理; IP地址 端口号能够标识网络上的某一台主机的某一个进程; 一个端口号只能被一个进程占用 在公网上&#xff0c;IP地址能表示唯一的一台主机&…

大模型激活函数知识

FFN块 计算公式 在Transformer模型中&#xff0c;FFN&#xff08;Feed-Forward Network&#xff09;块通常指的是在编码器&#xff08;Encoder&#xff09;和解码器&#xff08;Decoder&#xff09;中的一个全连接前馈网络子结构。FFN块位于自注意力层&#xff08;Self-Attent…

C语言第二十三弹---指针(七)

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】 指针 1、sizeof和strlen的对比 1.1、sizeof 1.2、strlen 1.3、sizeof 和 strlen的对比 2、数组和指针笔试题解析 2.1、⼀维数组 2.2、二维数组 总结 1、si…

Java 基于微信小程序的私家车位共享系统

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

WebSocket原理详解

目录 1.引言 1.1.使用HTTP不断轮询 1.2.长轮询 2.websocket 2.1.概述 2.2.websocket建立过程 2.3.抓包分析 2.4.websocket的消息格式 3.使用场景 4.总结 1.引言 平时我们打开网页&#xff0c;比如购物网站某宝。都是点一下列表商品&#xff0c;跳转一下网页就到了商品…

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Marquee组件

鸿蒙&#xff08;HarmonyOS&#xff09;项目方舟框架&#xff08;ArkUI&#xff09;之Marquee组件 一、操作环境 操作系统: Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1 二、Marquee组件 跑马灯组件&#xff0c;用于滚动展示一段单行文本&#xff0c;仅当…

【Effective Objective - C 2.0】——读书笔记(三)

文章目录 十五、用前缀避免命名空间冲突十六、提供全能初始化方法十七、实现description方法十八、尽量使用不可变对象十九、使用清晰而协调的命名方式二十、为私有方法名加前缀二十一、理解Objective-C错误模型二十二、理解NSCopying协议 十五、用前缀避免命名空间冲突 OC语言…

WSL外部SSH连接有效方法

前言 wsl作为windows下使用linux平台有效的手段之一&#xff0c;本文可以让win作为工作站&#xff0c;外部系统用来连接win下的wsl系统。 自动启动服务脚本 https://zhuanlan.zhihu.com/p/47733615 开机自启端口转发 wslname "Ubuntu-20.04" 要转发端口的Linux…

不懂编程?节点包来凑——Dynamo常用节点包推荐(上)

由于篇幅有限&#xff0c;本次文章我们分上、下两篇&#xff0c;来分享给大家。 Dynamo作为一款辅助三维设计工具&#xff0c;他可以通过图形化的编程&#xff0c;帮我们解决很多在设计或者建模过程中遇到的小问题&#xff1b;同时他作为一款可视化编程软件&#xff0c;学起来…

Spring Boot 笔记 006 创建接口_注册

1.1 由于返回数据都是以下这种格式&#xff0c;那么久再编写一个result实体类 报错了&#xff0c;原因是没有构造方法 可以使用lombok的注解自动生成&#xff0c;添加无参的构造器和全参的构造器 package com.geji.pojo;import lombok.AllArgsConstructor; import lombok.NoArg…

【C语言】【力扣】7.整数反转和9.回文数

一、整数反转 1.1 个人思考过程 初解&#xff1a;出现ERROR&#xff0c;数据溢出的情况下应该返回0。&#xff08;错误&#xff09; int reverse(int x){int y0;while(x!0){yy*10x%10;x/10; }return y; } 再解&#xff1a;加上数据溢出判断条件。&#xff08;正确&#…

JS逆向进阶篇【去哪儿旅行登录】【上篇】

目标url: aHR0cHM6Ly91c2VyLnF1bmFyLmNvbS9wYXNzcG9ydC9sb2dpbi5qc3A 实现难点&#xff1a; 逆向滑块请求发送短信登录 目录 每篇前言&#xff1a;0、前置技术栈&#xff08;1&#xff09;JS实现页面滑动&#xff08;2&#xff09;JS实现记录滑动轨迹&#xff08;3&#xff…

二、ClickHouse简介

ClickHouse简介 前言一、行式存储二、DBMS功能三、多样化引擎四、高吞吐写入能力五、数据分区与线程级并行六、场景七、特定版本 前言 ClickHouse 是俄罗斯的 Yandex 于 2016 年开源的列式存储数据库&#xff08;DBMS&#xff09;&#xff0c;使用 C 语言编写&#xff0c;主要…

2024年教师资格证认定报名完整流程

&#x1f49a;网上报名流程概览 一、进入教资认定网报入口&#xff1b; 二、进行实名核验&#xff1b; 三、申请网报时间查询&#xff1b; 四、个人信息维护&#xff1b; 五、认定申请报名&#xff1b; &#x1f49a;认定所需材料 1、 身份证&#xff1b; 2 、户口本/居住证…

【Java程序设计】【C00249】基于Springboot的私人健身与教练预约管理系统(有论文)

基于Springboot的私人健身与教练预约管理系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的私人健身与教练预约管理系统 本系统分为系统功能模块、管理员功能模块、教练功能模块以及用户功能模块。 系统功能模…

计算机网络——08应用层原理

应用层原理 创建一个新的网络 编程 在不同的端系统上运行通过网络基础设施提供的服务&#xff0c;应用进程批次通信如Web Web服务器软件与浏览器软件通信 网络核心中没有应用层软件 网络核心没有应用层功能网络应用只能在端系统上存在 快速网络应用开发和部署 网络应用…

ChatGPT4 教你如何完成SQL的实践应用

对数据库的各项应用与操作都离不开SQL来对数据进行增删改查。 例如 &#xff1a; 有一张某公司职员信息表如下&#xff1a; 需求1&#xff1a;在公司职员信息表中&#xff0c;请统计各部门&#xff0c;各岗位下的员工人数。 如果这个SQL语句不会写或者不知道怎么操作可以交给…

【C基础刷题】第九讲

本系列博客为个人刷题思路分享&#xff0c;有需要借鉴即可。 1.目录大纲&#xff1a; 2.题目链接&#xff1a; 统计成绩 00&#xff1a;00&#xff1a;00⸺00&#xff1a;09&#xff1a;00题号&#xff1a;BC33 链接&#xff1a;https://www.nowcoder.com/practice/ cad8d94…

【VTKExamples::PolyData】第二十七期 KochanekSpline

很高兴在雪易的CSDN遇见你 VTK技术爱好者 QQ:870202403 前言 本文分享VTK样例KochanekSpline & KochanekSplineDemo,并解析接口vtkParametricSpline & vtkParametricFunctionSource,希望对各位小伙伴有所帮助! 感谢各位小伙伴的点赞+关注,小易会继续努力分享,…

过河卒(洛谷)

题目 原题 题目描述 棋盘上 A A A 点有一个过河卒&#xff0c;需要走到目标 B B B 点。卒行走的规则&#xff1a;可以向下、或者向右。同时在棋盘上 C C C 点有一个对方的马&#xff0c;该马所在的点和所有跳跃一步可达的点称为对方马的控制点。因此称之为“马拦过河卒”。…