单片机第三季-第五课:GPIO控制LED

news2024/11/18 14:56:30

目录

1,GPIO数据手册

1.1,端口配置寄存器

​1.2,端口输入数据寄存器和端口输出数据寄存器 

​1.3,端口位设置/清除寄存器 

1.4,端口位清除寄存器 

2,原理图分析和MDK工程

3,写代码通过GPIO点亮LED 

4,STM32时钟设置函数移植 

5,STM32外设编程经验总结 


1,GPIO数据手册

每个GPI/O端口有两个32位配置寄存器(GPIOx_CRL,GPIOx_CRH),两个32位数据寄存器(GPIOx_IDR和GPIOx_ODR),一个32位置位/复位寄存器(GPIOx_BSRR),一个16位复位寄存器(GPIOx_BRR)和一个32位锁定寄存器(GPIOx_LCKR)。

GPIOx_CRL,GPIOx_CRH中的x代表端口编号,CR代表control register,L代表Low,H代表High;

GPIOx_IDR和GPIOx_ODR中的IDR代表input data register,ODR代表output data register;

GPIOx_LCKR是锁定寄存器,可以将输出锁定,提升安全性,也是STM32与51单片机的区别,STM32用于工业控制的一个特点; 

GPIO端口的每个位可以由软件分别配置成多种模式:

─ 输入浮空

─ 输入上拉

─ 输入下拉

─ 模拟输入

─ 开漏输出

─ 推挽式输出

─ 推挽式复用功能

─ 开漏复用功能 

前四种是输入模式,其中前三个是数字输入,第四个是模拟输入。

下图为IO端口的基本结构:

通过设置可将端口设置为输入或输出端口,图中上半部分为输入,下半部分为输出,输入模式是分为模拟输入以及通过TTL肖特基触发器转化为数字输入。输出模式中的P-MOS和N-MOS起到将输出增强的作用,在软件编程中重点是对图中寄存器的设置。

 输出模式位代表着输出端口可设置的信号输出频率。

1.1,端口配置寄存器

端口配置低寄存器(GPIOx_CRL) (x=A..E)对应端口0-7和端口配置高寄存器(GPIOx_CRH) (x=A..E)对应端口8-18。 

每个端口占四位,分别为CNFy[1:0]和MODEy[1:0],一个寄存器可以配置8个IO。

如果一个端口中的IO超过8个就需要用到配置高寄存器(GPIOx_CRH)。

1.2,端口输入数据寄存器和端口输出数据寄存器 

端口输入数据寄存器(GPIOx_IDR) (x=A..E):

端口输出数据寄存器(GPIOx_ODR) (x=A..E):

1.3,端口位设置/清除寄存器 

端口位设置/清除寄存器(GPIOx_BSRR) (x=A..E):

注:如果同时设置了BSy和BRy的对应位,BSy位起作用。也就是此时置位起作用。 

1.4,端口位清除寄存器 

端口位清除寄存器(GPIOx_BRR) (x=A..E):

 

其他寄存器不再一一列举,具体参考数据手册。

2,原理图分析和MDK工程

需要分析STM32核心板和转接插座的对应端口,以及通过转接插座的端口连接LED的插接口。 

选择PB8-PB15控制LED,也就是STM32的Port B。 

起始代码:

不同的CPU的起始代码一般是不同的;
起始代码是用汇编写的,一般不需要看懂,知道点就行了。 

3,写代码通过GPIO点亮LED 

第一步,寄存器信息确认,确认使用端口地址,Port B,0X4001 0C00 - 0x4001 0FFF。

第二步,找到Port B对应要操作的寄存器,即第一节中介绍的几个寄存器。

有可能涉及到的GPIO的寄存器地址:

寄存器名              偏移量          寄存器地址
GPIOB_CRL        0x00             0x40010C00
GPIOB_CRH       0x04             0x40010C04            
GPIOB_IDR        0x08              0x40010C08
GPIOB_ODR      0x0C             0x40010C0C            
GPIOB_BSRR    0x10             0x40010C10            
GPIOB_BRR      0x14              0x40010C14            

第三步,通过C语言编程操作寄存器。

需要注意的几点:

(1)ARM是内存与IO统一编址的,所以ARM中的所有外设都是通过寄存器的方式来操作的
(2)每个寄存器都有地址,C语言通过这些地址来操作这些寄存器位,用到的C语言技巧主要是C语言的位操作和C语言指针。
(3)常见面试题:用C语言向内存地址0x30000004写入16
    *(unsigned int *)0x30000004 = 16;                                                                                              或者:
    unsigned int *p = (unsigned int *)0x30000004;    *p = 16; 

下边的代码中直接通过操作寄存器的地址控制LED: 

#define GPIOB_CRH 0x40010C04
#define GPIOB_ODR 0x40010C0C

void main()
{
    //将 port B端口的8-15设置为输出模式,最大速度50MHz,通用推挽输出模式
    *((unsigned int *)GPIOB_CRH) = 0x3333 3333;
    
    //输出1将8个LED灯全部点亮
    *((unsigned int *)GPIOB_ODR) = 0x0000 ffff;

    while(1)

}

4,STM32时钟设置函数移植 

需要配置时钟的时钟控制寄存器(RCC_CR),时钟配置寄存器(RCC_CFGR)

第一步,时钟控制寄存器(RCC_CR)打开HSE ON(使用外部晶振),检测是否ready(HSE RDY)。

第二部,时钟配置寄存器(RCC_CFGR)配置HPRE(AHB)、PPRE1(APB1)、PPRE2(APB2)、PLLSRC、PLLXTPRE、PLLMUL。

第三步,配置时钟控制寄存器(RCC_CR) ,PLL ON,并检测PLL RDY。

 第四步,配置时钟配置寄存器(RCC_CFGR)中的SW,选择时钟源,并检测SWS状态。

时钟设置时需注意对flash相关寄存器的操作 。

另外需要注意各端口时钟的使能是独立的:

时钟函数代码:

头文件: 

#ifndef __CLOCK_H__
#define __CLOCK_H__

#include "gpio.h"


// 寄存器宏定义
// RCC寄存器基地址0x40021000
#define RCC_BASE	0x40021000			// RCC部分寄存器的基地址·
#define RCC_CR		(RCC_BASE + 0x00)	// RCC_CR的地址·
#define RCC_CFGR	(RCC_BASE + 0x04)

#define FLASH_ACR	0x40022000

// 用C语言来访问寄存器的宏定义
#define rRCC_CR		(*((volatile unsigned int *)RCC_CR))
#define rRCC_CFGR	(*((volatile unsigned int *)RCC_CFGR))
#define rFLASH_ACR	(*((volatile unsigned int *)FLASH_ACR))



// 时钟源切换到HSE并使能PLL,将主频设置为12MHz
void Set_SysClockTo72M(void);

#endif

源文件: 

#include "clock.h"


void Set_SysClockTo72M(void)
{
	unsigned int rccCrHserdy = 0;
	unsigned int rccCrPllrdy = 0;
	unsigned int rccCfrSwsPll = 0;
	unsigned int faultTime = 0;


	rRCC_CR = 0x00000083;
	rRCC_CR &= ~(1<<16);	  	// 关闭HSEON
	rRCC_CR |= (1<<16);			//打开HSEON,让HSEON工作

	do
	{
		rccCrHserdy = rRCC_CR & (1<<17);	//检测第17位是否为1
		faultTime++;//检测时间
	}
	while ((faultTime<0x0FFFFFFF) && (rccCrHserdy==0));

	if ((rRCC_CR & (1<<17)) != 0)
	{
		rFLASH_ACR |= 0x10;
		rFLASH_ACR &= (~0x03);
		rFLASH_ACR |= (0x02);

		// HSE ready,下面配置PLL并且等待ready
		rRCC_CFGR &= (~((0x0f<<4) | (0x07<<8) | (0x07<<11)));
		//rRCC_CFGR &= (~(0x3ff<<4));
		// AHB和APB2未分频,APB1被2分频,所以,AHB和APB2都是72MHz,APB是36MHz
		rRCC_CFGR |= ((0x0<<4) | (0x04<<8) | (0x0<<11));

		// 选择HSE作为PLL输入并且HSE不分频,所以PLL输入为8MHz
		rRCC_CFGR &= (~((1<<16) | (1<<17)));   	// 清零bit17和bit16
		rRCC_CFGR |= ((1<<16) | (0<<17));		//bit16置1

		// 设置PLL倍频系数为9
		rRCC_CFGR &= (~(0x0f<<18));   			// 清零bit18-21
		rRCC_CFGR |= (0x07<<18);				// 9倍频

		// 打开PLL开关
		rRCC_CR |= (1<<24);

		// do while 循环等待PLL时钟稳定
		faultTime = 0;
		do
		{
			rccCrPllrdy = rRCC_CR & (1<<25);	//检测25为是否为1
			faultTime++;//检测时间
		}
		while ((faultTime<0x0FFFFFFF) && (rccCrPllrdy==0));
		//while (rccCrPllrdy==0);

		if ((rRCC_CR & (1<<25)) == (1<<25))
		{
		  	// 到这里说明PLL已经稳定了,可以用了,下面就可以切了
			
			// 切换PLL输出为SYSCLK
			rRCC_CFGR &= (~(0x03<<0));   
			rRCC_CFGR |= (0x02<<0);	

			faultTime = 0;
			do
			{
				rccCfrSwsPll = rRCC_CFGR & (0x03<<2);	//检测第25位是否为1
				faultTime++;//检测时间
			}
			while ((faultTime<0x0FFFFFFF) && (rccCfrSwsPll!=(0x02<<2)));
			
		   	if ((rRCC_CFGR & (0x03<<2))== (0x02<<2))
			{
				//到这里时钟就设置好了

			}
			else
			{
				// 到这里说明PLL输出作为SYSCLK不成功
				while (1);
			}

		}
		else
		{
			// 到这里说明PLL启动时出错了,PLL不能稳定工作
			while (1);
		}

	}
	else
	{
		// HSE配置超时,说明HSE不可用,一般硬件存在问题
		while (1);
	}
}

5,STM32外设编程经验总结 

STM32和51或其他简单单片机的相同:
(1)开发环境都是Keil;
(2)都是看原理图和数据手册;
(3)都是用C语言;
STM32和51或其他简单单片机的不同:
(1)工程会更复杂,会用到Keil的一些高级设置;
(2)原理图和数据手册比简单单片机更复杂(复杂不是难);
(3)STM32会用到C语言的更多高级特性 ;

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

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

相关文章

快速入门:教你如何使用vue-element-admin 集成框架开发项目(保姆式教学)

设置完中文界面&#xff0c;打开是这样的 端口号更改 嘿嘿&#xff0c;要把项目改成自己的&#xff0c;是不是要更改标题啊 题目更改 src/utils/get-page-title.js src/settings.js 如何添加菜单页面 添加菜单页面&#xff08;父菜单/子菜单&#xff09; 效果图 添加自己的页…

Unity--视觉组件(Raw Image,Mask)||Unity--视觉组件(Text,Image)

1.Raw Image 2.mask “”Raw Image&#xff1a;“” Texture&#xff1a;&#xff08;纹理&#xff09; 表示要显示的图像的纹理&#xff1b; Color&#xff1a;&#xff08;颜色&#xff09; 应用于图像的颜色&#xff1b; Material&#xff1a;&#xff08;材质&#xff09…

FreeRTOS源码阅读笔记3--queue.c

消息队列可以应用于发送不定长消息的场合&#xff0c;包括任务与任务间的消息交换&#xff0c;队列是 FreeRTOS 主要的任务间通讯方式&#xff0c;可以在任务与任务间、中断和任务间传送信息&#xff0c;发送到 队列的消息是通过拷贝方式实现的&#xff0c;这意味着队列存储…

前端开发项目中使用字体库

开发中有些项目要求使用固定的字体&#xff0c;这就需要项目中使用字体库。 首先需要下载字体库 将下载的字体文件放进项目中 在项目代码样式文件中定义字体 font-face {font-family: "Tobias-SemiBold";src: url("./assets/font/Tobias-SemiBold.ttf"…

arcgis基础篇--实验

一、绘制带空洞的面要素 方法一&#xff1a;先绘制出一个面区域&#xff0c;然后在面上再绘制一个面区域代表面洞&#xff0c;两者位于同一个图层内&#xff0c;选中代表面洞的区域&#xff0c;选择【编辑器】-【裁剪】工具&#xff0c;将面裁剪出一个洞&#xff0c;随后删除代…

jupyter notebook添加markdown目录

jupyternotebook添加markdown目录 1. 安装python包2. 安装JavaScript和CSS文件3. 启用扩展4. 设置markdown选项 1. 安装python包 官方安装 使用pip pip install jupyter_contrib_nbextensions # 或者 pip install https://github.com/ipython-contrib/jupyter_contrib_nbext…

苹果M3处理器跑分曝光,单核无敌!

10月底&#xff0c;苹果发布了全新的M3、M3 Pro、M3 Max芯片以及搭载M3系列芯片的3款新硬件&#xff0c;包括&#xff1a;新款24英寸iMac、新款14/16英寸MacBook Pro。 根据苹果官方介绍&#xff0c;M3系列芯片基于台积电3纳米工艺打造&#xff0c;采用全新图形处理器架构&…

【操作系统内核】线程

【操作系统内核】线程 为什么需要线程 比如我要做一个视频播放器&#xff0c;就需要实现三个功能&#xff1a; ① 从磁盘读取视频数据 ② 对读取到的视频数据进行解码 ③ 对解码的数据进行播放 如果串行执行&#xff08;通过一个进程来执行&#xff09;&#xff1a; 那么…

视通科技新品发布:4K30分布式编解码一体机,高性价比之选!

随着信息技术的日新月异&#xff0c;各领域对于音视频传输、控制和显示等方面的需求呈现出爆发式的增长。这种需求的增长源于多种因素&#xff0c;包括但不限于高清视频的普及&#xff0c;实时音视频通信的广泛应用&#xff0c;以及各种显示设备的升级换代。 在这样的背景下&a…

动态规划(5)---Leetcode338.比特位计数

题目 给你一个整数 n &#xff0c;对于 0 < i < n 中的每个 i &#xff0c;计算其二进制表示中 1 的个数 &#xff0c;返回一个长度为 n 1 的数组 ans 作为答案。 分析 通常动态规划的做题顺序&#xff0c;先确定dp数组dp[i],然后确定确定递推公式&#xff0c;再dp数…

Gogs安装和部署教程-centos上

0、什么是 Gogs? Gogs 是一款极易搭建的自助 Git 服务。 Gogs 的目标是打造一个最简单、最快速和最轻松的方式搭建自助 Git 服务。使用 Go 语言开发使得 Gogs 能够通过独立的二进制分发&#xff0c;并且支持 Go 语言支持的 所有平台&#xff0c;包括 Linux、Mac OS X、Windo…

华为防火墙2种局域网内远程监控其它端口的方法

防火墙必须要工作在三层&#xff0c;接口上有地址 第一种用ip-link 这种方法是如果监测的接口故障后&#xff0c;自身优先级降低2 FW3 ip-link check enable ip-link 1 destination 1.1.1.1 interface g0/0/0 mode icmp hrp track ip-link 1 active FW4 ip-link check …

Hls学习(一)

1&#xff1a;CPU、DSP、GPU都算软件可编程的硬件 2&#xff1a;dsp在递归方面有所减弱&#xff0c;在递归方面有所增强&#xff0c;比如递归啊等&#xff0c;GPU可以同时处理多个进程&#xff0c;对于大块数据&#xff0c;流处理比较适用 3&#xff1a;为了提高运算量处理更多…

7-Zip的介绍和【阿里云盘】的使用

7zip从入门到入坑 前言一、7-zip的介绍和安装1、基本介绍1&#xff09;7-Zip 主要特征2&#xff09;支持格式3&#xff09;基础功能4&#xff09;安装环境需求 2、基本操作&#xff08;1&#xff09;简便的界面&#xff08;2&#xff09;发生的问题 二、阿里云盘的使用1、“exe…

OSG练习:模仿Ventsim制作三维矿井智能通风系统

1、效果 2、计划内容 1) 三维场景的加载显示;已实现 2)矿井巷道建模及纹理;已实现 3)矿井基础数据采集及修正;已实现 4)通风网络解算算法;已实现 5)通风设备及设施模型制作;未实现 6)风流模拟效果 ;进行中 7)火灾模拟效果;未实现 8)巷道属性查看栏;未实现 9)…

k8s 裸金属集群部署metalLB软负载均衡 —— 筑梦之路

metalLB 官方网站 Repo&#xff1a;https://github.com/metallb/metallb 官网&#xff1a;https://metallb.universe.tf/installation metalLB解决什么问题&#xff1f; MetalLB 是一个用于裸机 Kubernetes 集群的负载均衡器实现&#xff0c;使用标准路由协议。 k8s 并没有为裸…

深度学习 python opencv 火焰检测识别 火灾检测 计算机竞赛

文章目录 0 前言1 基于YOLO的火焰检测与识别2 课题背景3 卷积神经网络3.1 卷积层3.2 池化层3.3 激活函数&#xff1a;3.4 全连接层3.5 使用tensorflow中keras模块实现卷积神经网络 4 YOLOV54.1 网络架构图4.2 输入端4.3 基准网络4.4 Neck网络4.5 Head输出层 5 数据集准备5.1 数…

解锁 PaddleOCR 的超能力

光学字符识别&#xff08;OCR&#xff09;是一项强大的技术&#xff0c;使机器能够从图像或扫描文档中识别和提取文本。OCR 在各个领域都有应用&#xff0c;包括文件数字化、从图像中提取文本以及基于文本的数据分析。在本文中&#xff0c;我们将探讨如何使用 PaddleOCR&#x…

LeetCode【923】三数之和的多种可能性

题目&#xff1a; 思路&#xff1a; https://www.jianshu.com/p/544cbb422300 代码&#xff1a; int threeSumMulti(vector<int>& A, int target) {//Leetcode923:三数之和的多钟可能//initialize some constint kMod 1e9 7;int kMax 100;//calculate frequenc…

25 _ 红黑树(上):为什么工程中都用红黑树这种二叉树?

上两节,我们依次讲了树、二叉树、二叉查找树。二叉查找树是最常用的一种二叉树,它支持快速插入、删除、查找操作,各个操作的时间复杂度跟树的高度成正比,理想情况下,时间复杂度是O(logn)。 不过,二叉查找树在频繁的动态更新过程中,可能会出现树的高度远大于log2n的情况…