【STM32】GPIO控制LED(寄存器版)

news2024/11/19 5:33:19

 在开始之前记得先准备好环境:

STM32F103核心板下载教程.pdf · 林何/STM32F103C8 - 码云 - 开源中国 (gitee.com)

一、STM32的GPIO模块数据手册详解

每个GPIO端口对应16个引脚,例GPIOA(PA0~PA15)
内核cpu就可以通过APB2总线对寄存器读写,完成输出电平和读取电平的功能

 1.GPIO和APIO

GPIO:通用输入/输出IO

APIO:备用输入/输出IO

2.GPIO功能描述

3.配置模式

【STM32】GPIO工作原理(八种工作方式超详细分析,附电路图)-CSDN博客

1.输入浮动,输入上拉,输入下拉(数字状态)

都是数字模式,数字IO,只关心电平是1还是0

输入浮空:就是当电平输入进来后,直接输入到寄存器中【不对其进行操作】

输入上拉:在内部有一个上拉电阻(将电平拉高),只能外部接地,才能将电平拉低,如果TTL肖特基触发器:输入的是高电平或者干扰信号,则会将其过滤调。

2.模拟输入(模拟状态)

AD转换

可以工作在模拟电路或者数字电路

3.输出

开漏输出

推挽输出

4.备用

将不用的引脚配置成备用引脚(GPIO)才可以被使用

4.输出字节数控制

1)输出32位字:使用GPIO_CRL---效率低,但是兼容性好

2)输入小于32位字:使用CPIOx_BSRR--效率高,但是兼容性差

5.I/O 端口位框图

6.端口位配置表

7.输出模式位

8.外部中断/唤醒线

将IO口和相对应的中断映射起来

9.GPIO寄存器描述

1. 端口配置低寄存器(GPIOx_CRL)

由于每个GPIO口需要4位来进行配置输入输出模式(2位配置MODE,2位配置CNF),这样的话每组16个GPIO口则需要64位,这也就表明需要两个32位寄存器。于是GPIOx_CRL用于配置GPIO0-GPIO7的输入输出模式。同理GPIOx_CRH则用于配置GPIO8-GPIO15的输入输出模式。

控制PX0---PX7引脚工作模式

四个位控制一个引脚

2. 端口配置高寄存器(GPIOx_CRH)

控制PX8---PX15引脚工作模式

3.端口输入数据寄存器(GPIOx_IDR) 

4. 端口输出数据寄存器(GPIOx_ODR)

5. 端口位设置/复位寄存器(GPIOx_BSRR)

如果想要将bit7和bit6置为0,则表示要将bit7和bit6写为1,其他位置为0

对复位上写1表示复位

对置位上写1表示置为

如果置位和复位同时设置,则置位起作用。

6.端口位复位寄存器(GPIOx_BRR)

7.端口配置锁定寄存器(GPIOx_LCKR)

8.复用功能I/O和调试配置(AFIO)

二、原理图分析

1.硬件接线

1)杜邦线连接到P0端口到LCD的J19接口,这样相当于8个LED分别对应PB8-PB15

2)因为GPIO接到LCD的负极,所以输入0亮,输入1暗

三、MDK工程建立

与前面51建立工程是一样的

1.注意点1:

2.注意点2:

单片机中用到的c语言其实不是原始c语言,而是有点定制性c语言

之前认识:整个程序从main函数开始执行,main执行完整个程序就结束

起始代码:从CPU复位开始执行的第一句指令,到main函数之前所做的事情就是起始代码

3.起始代码

1)起始代码是从哪里来的:编译环境提高的,STM32CPU提供的

2)不同CPU的起始代码一般是不同的

3)起始代码是用汇编写的

四、写代码控制GPIO点亮和熄灭

1.寄存器现象确认

我们使用的是P0端口(对应PB8-PB15),所以我们要去对应查找PB的寄存器起始地址

1)STM32 PortB的起始是0x4001 0c00

2.有可能使用到的GPIO的地址:

因为我们是PB8-PB15,所以我们只使用CRH

3.C语言操作寄存器

1)ARM是内存与IO统一编址的,所以ARM中的所有外设都是通过寄存器的方式来操作的

2)每一个寄存器都有地址,c语言通过这些地址来操作这些寄存器位,用到的c语言的技巧主要是c与的位操作和c语言指针

3)常见面试题:用c语言向内存地址0x3000 0004写入16

        *(unsigned int *)0x3000 0004=16;

等价于

        unsigned int *p=(unsigned int *)0x3000 0004;

        *p=16;

4.解析寄存器

1.端口配置高寄存器(GPIOx_CRH)-高8位

	//向CRH寄存器写内容,将GPIO_GPB15配置为输出模式【此时高位有用】
	//推挽输出模式,输出的速率为50MHZ【0011 0011 0011 0011.。。】
	*((unsigned int *)GPIOB_CRH)=0x33333333;//表示将GPIO_CRH的值设置为0x33333333

2.端口输出数据寄存器(GPIOx_ODR)

	//向CRH寄存器写内容,将GPIO_GPB15配置为输出模式【此时高位有用】
	//推挽输出模式,输出的速率为50MHZ【0011 0011 0011 0011.。。】
	*((unsigned int *)GPIOB_CRH)=0x33333333;//表示将GPIO_CRH的值设置为0x33333333

5.注意点:

记得在操作GPIO的时候要先打开时钟

#define GPIOB_CRH		0x40010C04
#define GPIOB_ODR		0x40010C0C

#define RCC_APB2ENR		0x40021018

void main(void){
	
	//STM32所有外设默认关闭
	//所以我们在打开时钟
	*((unsigned int *)RCC_APB2ENR)=0x00000008;

	//向CRH寄存器写内容,将GPIO_GPB15配置为输出模式
	//推挽输出模式,输出的速率为50MHZ【0011 0011 0011 0011.。。】
	*((unsigned int *)GPIOB_CRH)=0x33333333;//表示将GPIO_CRH的值设置为0x33333333
	
	//输出1,点亮LED
	//ff:对应15-8位
	*((unsigned int *)GPIOB_ODR)=0x0000f000;
	
	while(1);
	
}

五、其他寄存器的测试

1.端口位设置/清除寄存器(GPIOx_BSRR)

将bit8-bit15置0(变亮),因为我们前面是使用了GPIO_GRH(所以只能控制8-15个引脚),所以此时改变0-7是无效的

	//使用寄存器【GPIOB_BSRR】:将bit8-bit15置0(此时表示全亮) 
	//*((unsigned int *)GPIOB_BSRR)=0x00000000;
	//因为前面我们是控制GPIOB_CRH,所以只有8-15位才起效果,0-7无论设置什么都无所谓
	//*((unsigned int *)GPIOB_BSRR)=0x000000ff;//此时全亮,与上面效果一样
	
	//0101 0101
	//*((unsigned int *)GPIOB_BSRR)=0x00005500;//此时2,4,6,8亮
	
	//此时led1,led3不亮,其他亮
	//使用置位
	*((unsigned int *)GPIOB_BSRR)=0x00005500;//此时2,4,6,8亮
	//使用复位:将高4位全部复位
	*((unsigned int *)GPIOB_BSRR)=0xf0000000;

2.端口位清除寄存器(GPIOx_BRR)

只能操作bit0-bit15

BRR:只能用来复位,不能置位(所以只能将其置为0,而不能置为1)

    //使用寄存器【GPIOB_BRR】:将bit8-bit15置0(此时表示全亮) 
	//GPIOB_BRR:只能进行复位(意思是只能将电平置为0)
	//前面16-32是无效位
	*((unsigned int *)GPIOB_BRR)=0x00000000;//全亮
	*((unsigned int *)GPIOB_BRR)=0x0000ffff;//全亮
	//*((unsigned int *)GPIOB_BRR)=0x0000ff00;//只亮高4位(led的4-7)
	

六、总结

对数据操作的三种方法:

ODR:可以进行任何操作,但是只能一次性操作32位,效率低,但是移植性高【其次考虑】

BSRR:原子操作,效率高;移植性差【优先考虑】

BRR:只能进行复位,不能置位,原子操作,效率高;移植性差

1.代码

#define GPIOB_CRH		0x40010C04
#define GPIOB_CRL		0x40010C00
#define GPIOB_ODR		0x40010C0C
#define GPIOB_BSRR	0x40010C10
#define GPIOB_BRR		0x40010C14

#define RCC_APB2ENR		0x40021018

void main(void){
	
	//STM32所有外设默认关闭
	//所以我们在打开时钟
	*((unsigned int *)RCC_APB2ENR)=0x00000008;

	//向CRH寄存器写内容,将GPIO_GPB15配置为输出模式【此时高位有用】
	//推挽输出模式,输出的速率为50MHZ【0011 0011 0011 0011.。。】
	*((unsigned int *)GPIOB_CRH)=0x33333333;//表示将GPIO_CRH的值设置为0x33333333
	
	//输出0,点亮LED
	//ff:对应15-8位
	//*((unsigned int *)GPIOB_ODR)=0x00000000;
	
	
	//使用寄存器【GPIOB_BSRR】:将bit8-bit15置0(此时表示全亮) 
	//*((unsigned int *)GPIOB_BSRR)=0x00000000;
	//因为前面我们是控制GPIOB_CRH,所以只有8-15位才起效果,0-7无论设置什么都无所谓
	//*((unsigned int *)GPIOB_BSRR)=0x000000ff;//此时全亮,与上面效果一样
	
	//0101 0101
	//*((unsigned int *)GPIOB_BSRR)=0x00005500;//此时2,4,6,8亮
	
	//此时led1,led3不亮,其他亮
	//使用置位
	//*((unsigned int *)GPIOB_BSRR)=0x00005500;//此时2,4,6,8亮
	//使用复位:将高4位全部复位
	//*((unsigned int *)GPIOB_BSRR)=0xf0000000;
	
	//使用寄存器【GPIOB_BRR】:将bit8-bit15置0(此时表示全亮) 
	//GPIOB_BRR:只能进行复位(意思是只能将电平置为0)
	//前面16-32是无效位
	*((unsigned int *)GPIOB_BRR)=0x00000000;//全亮
	*((unsigned int *)GPIOB_BRR)=0x0000ffff;//全亮
	//*((unsigned int *)GPIOB_BRR)=0x0000ff00;//只亮高4位(led的4-7)
	
	while(1);
	
}

2.对宏定义的封装

#define GPIOB_CRH		0x40010C04
#define GPIOB_CRL		0x40010C00
#define GPIOB_ODR		0x40010C0C
#define GPIOB_BSRR	0x40010C10
#define GPIOB_BRR		0x40010C14

#define RCC_APB2ENR		0x40021018

#define rGPIOB_CRH 		(*((unsigned int *)GPIOB_CRH))
#define rGPIOB_ODR 		(*((unsigned int *)GPIOB_ODR))
#define rGPIOB_BSRR 	(*((unsigned int *)GPIOB_BSRR))
#define rGPIOB_BRR 		(*((unsigned int *)GPIOB_BRR))
#define rRCC_APB2ENR 	(*((unsigned int *)RCC_APB2ENR))

void main(void){
	rRCC_APB2ENR = 0x00000008;

	rGPIOB_CRH = 0x33333333;
	rGPIOB_ODR = 0x0000aa00;
}

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

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

相关文章

电路电子技术3 电位的计算受控源在电路分析中的作用

1.计算电压 思路:注意到这个串联电路,有两个电压源,所以我们首先可以将两个电压源串联等效为一个电压源。 即: 故可得答案选B. 2.计算点位 思路:题目说明了B点开路,所以没有流过电阻R的电流,…

光学配件简介

光学配件简介 延长管介绍 延长管,是加在镜头和相机之间的一根通心的环状管,但里面没有任何光学部件,也没有放大作用。它不会改变光圈值,但因为延长了镜头,光线会减弱。延长管可以使镜头的对焦距离缩短,也就…

Uniapp 酷炫钱包页面模板 直接引用

使用教程 直接引用Vue页面 即可 <template><view><TCqianbao></TCqianbao></view> </template> <script>import TCqianbao from /uni_modules/TC-qianbao/pages/index.vueexport default {components:{TCqianbao},} </script&…

【斗破年番】彩鳞送老公新挂,薰儿霸气回归,萧炎招揽古河,邀请美杜莎战魂殿

【侵权联系删除】【文/郑尔巴金】 斗破苍穹年番动画已经更新了&#xff0c;萧炎与美杜莎女王一起回娘家&#xff0c;并且也与小医仙制定了同盟计划&#xff0c;准备对金雁宗与慕兰谷斩草除根。从官方公布的第69集预告来看&#xff0c;慕兰三老与雁落天已经陨落&#xff0c;美杜…

Warning: [antd: Switch] `value` is not a valid prop, do you mean `checked`?

解决方案&#xff1a; <Form.Item label"更多设置" name"moreSetting" valuePropName"checked"><Switch onChange{handleMoreSetting} /></Form.Item> 参考链接&#xff1a; https://chat.xutongbao.top/

医药保健品经营小程序商城的作用是什么

互联网经济下&#xff0c;线上线下商家难以生存&#xff0c;自营平台成为各行业商家的选择&#xff0c;摆脱平台限制及线下门店地域的限制&#xff0c;多渠道线上获客引流转化营销、留存复购裂变等&#xff0c;更利于直接触达消费者&#xff0c;无其它商家夺流及坑位费、流量费…

最详细STM32,cubeMX 定时器

这篇文章将详细介绍 STM32,cubeMX 定时器的配置和使用。 文章目录 前言一、定时器基础知识二、cubeMX 配置三、定时时长四、自动生成代码讲解五、实验程序总结 前言 实验开发板&#xff1a;STM32F103C8T6。所需软件&#xff1a;keil5 &#xff0c; cubeMX 。实验目的&#xff…

探索未来的视觉革命:卷积神经网络的崭新时代(二)

&#x1f497;&#x1f497;&#x1f497;欢迎来到我的博客&#xff0c;你将找到有关如何使用技术解决问题的文章&#xff0c;也会找到某个技术的学习路线。无论你是何种职业&#xff0c;我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章&#xff0c;也欢…

自主武器系统对伦理和法律的挑战

【第十届北京香山论坛是中国军事科学学会、中国国际战略学会联合主办的论坛&#xff0c;将于2023年10月29日至31日在北京举行。本次论坛的主题是“共同安全、持久和平”&#xff0c;聚焦全球安全倡议重点合作方向&#xff0c;为各方共议安全难题、求解安全之策、促进安全合作提…

Leetcode1971. 寻找图中是否存在路径

Every day a Leetcode 题目来源&#xff1a;1971. 寻找图中是否存在路径 解法1&#xff1a;并查集 并查集介绍&#xff1a;并查集详解 代码&#xff1a; /** lc appleetcode.cn id1971 langcpp** [1971] 寻找图中是否存在路径*/// lc codestart class UnionFind {vector&…

Node-RED系列教程-27node-red操作邮件节点

提前注册好一个163邮箱: 安装以下节点: 演示发送邮件的功能

ESXI6.5安装教程

设置从IPMI Virtual Disk 3000启动&#xff0c;出现如下界面&#xff1a; 默认选择第一项&#xff0c;回车安装 安装程序正在检测服务器硬件信息&#xff0c;如果不满足系统安装条件会跳出错误提示。 检测完成之后会出现下面界面 回车 按F11 这里列出了服务器硬盘信息&#…

【算法|动态规划No.29】leetcode132. 分割回文串 II

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【手撕算法系列专栏】【LeetCode】 &#x1f354;本专栏旨在提高自己算法能力的同时&#xff0c;记录一下自己的学习过程&#xff0c;希望…

022-第三代软件开发-QCustomPlot核心迁移

第三代软件开发-QCustomPlot核心迁移 文章目录 第三代软件开发-QCustomPlot核心迁移项目介绍先说点GitHub CopilotQCustomPlot核心迁移QQuickPaintedItemXXX_QCustomChart 关键字&#xff1a; Qt、 Qml、 QCustomPlot、 GitHub Copilo、 关键字5 项目介绍 欢迎来到我们的 …

Leetcode—2331.计算布尔二叉树的值【简单】

2023每日刷题&#xff08;六&#xff09; Leetcode—2331.计算布尔二叉树的值 递归实现代码 /*** Definition for a binary tree node.* struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*/ bool evaluateTree(struct TreeNod…

计算机网络_网络层概述

4.1 网络层概述 4.1.1 一.分组转发和路由选择 网络层的主要任务就是将分组从源主机经过多个网络和多段链路传输到目的主机&#xff0c;可以将该任务划分为分组转发和路由选择两种重要的功能。 注释:A发送到B,从1端口进入. 如何得知是从2还是从3中转发出去呢?--------->这…

M4内核启动全过程(从零写代码,不用任何库,深入分析启动过程和函数调用规则)

引言 玩过stm32的小伙伴&#xff0c;应该知道&#xff0c;在使用的keil工程里面有一个start.s的启动文件&#xff08;网上关于这个启动文件的分析很多&#xff0c;本文不是讲解启动文件的文字&#xff0c;不打算具体讲解这个文件的内容&#xff09;。start.s文件是芯片复位、启…

微信小程序-微信授权登录

前言 小程序可以通过微信官方提供的登录能力方便地获取微信提供的用户身份标识&#xff0c;快速建立小程序内的用户体系 一.微信授权登录工作流程 1.理论叙述 触发授权登录: 用户在小程序中触发登录操作&#xff0c;通常通过点击登录按钮或执行相关操作。 授权弹窗: 小程序弹…

python树结构包treelib入门及其计算应用

树是计算机科学中重要的数据结构。例如决策树等机器学习算法设计、文件系统索引等。创建treelib包是为了在Python中提供树数据结构的有效实现。 Treelib的主要特点包括&#xff1a; 节点搜索的高效操作。支持常见的树操作&#xff0c;如遍历、插入、删除、节点移动、浅/深复制…

【Ascend C算子开发(入门)】——Ascend C编程模式与范式

Ascend C编程模型与范式 1.并行计算架构抽象 Ascend C编程开发的算子是运行在AI Core上的&#xff0c;所以我们需要了解一下AI Core的结构。AI Core主要包括计算单元、存储单元、搬运单元。 计算单元包括了三种计算资源&#xff1a;Scalar计算单元&#xff08;执行标量计算&…