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

目录

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.mfbz.cn/a/131946.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

华为防火墙二层透明模式下双机热备负载分担配置(两端为路由器)

这种模式只做负载分担&#xff0c;不能是主备备份&#xff0c;因为主备备份模式下&#xff0c;备设备会把vlan down掉&#xff0c;如果是主备备份模式&#xff0c;那在主挂后&#xff0c;备的状态在切换过程中先起vlan&#xff0c;再建立ospf邻接&#xff0c;那业务会断线较久&…

Labview利用声卡捕获波形

一般的计算机上自带的声卡&#xff0c;均既有A/D功能&#xff0c;又有D/A功能&#xff0c;就是一款具备基本配置的数据采集卡&#xff0c;并且技术成熟&#xff0c;性能稳定。 后台如下&#xff1a;

前端开发学习指南

前端是一个看似入门门槛不高&#xff0c;但要学好很难的领域。前端的知识体系庞杂又松散&#xff0c;技术演进快&#xff0c;如果摸不清脉络的话很容易陷入盲人摸象的困境甚至跑偏。 其实只要掌握了正确的方法&#xff0c;学习前端和学好前端就只是个时间问题&#xff0c;希望下…

Vatee万腾的科技决策力奇迹:Vatee科技决策力的独特之选

在金融投资的复杂领域中&#xff0c;Vatee万腾以其独特的科技决策力创造了一场真正的奇迹。这不仅是一种引领投资者走向成功的选择&#xff0c;更是一种开启新时代的科技决策奇迹。 Vatee的科技决策力背后蕴藏着强大的智慧和创新。通过大数据分析、智能算法的运用&#xff0c;V…

熊海CMS 靶场

熊海CMS 靶场 0x01 前言 初步了解cms&#xff0c;Content Management System 内容管理系统。它是一种用于创建、编辑、管理和发布内容的软件程序或工具。内容管理系统通常用于网站、博客、企业内部系统等各种应用中&#xff0c;可以帮助用户管理和发布各种类型的内容&#xf…

100V耐压内置MOS ESOP8 40V输入转5V 2.1A恒压输出

100V耐压内置MOS ESOP8 40V输入转5V 2.1A恒压输出 SC9102 是一款宽电压范围降压型 DC-DC 电源管理芯片&#xff0c;内部集成使能开关控制、基准电源、误差放大器、 过热保护、限流保护、短路保护等功能&#xff0c;非常适合宽电压输入降压使用。 SC9102 零功耗使能控制&…

asp.net学院网上报销系统VS开发sqlserver数据库web结构c#编程Microsoft Visual Studio

一、源码特点 asp.net学院网上报销系统是一套完善的web设计管理系统&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为vs2010&#xff0c;数据库为sqlserver2008&#xff0c;使用c#语言 开发 asp.net学院网上报销系统 应用技术…

jacoco插桩源码,看这一篇就够了

知识储备 众所周知&#xff0c;jacoco的功能主要分成两块&#xff1a; jacoco agentjacoco cli 其中jacoco agent主要用来对业务方服务进行插装&#xff0c;而cli则提供一些工具对插桩数据进行处理&#xff0c;比如dump&#xff0c;merge,report等&#xff0c;今天我们着重通…

计算机毕设 大数据工作岗位数据分析与可视化 - python flask

文章目录 0 前言1 课题背景2 实现效果3 项目实现3.1 概括 3.2 Flask实现3.3 HTML页面交互及Jinja2 4 **完整代码**5 最后 0 前言 &#x1f525; 这两年开始毕业设计和毕业答辩的要求和难度不断提升&#xff0c;传统的毕设题目缺少创新和亮点&#xff0c;往往达不到毕业答辩的要…

作用域插槽slot-scope

一般用于组件封装&#xff0c;将使用props传入组件的数据再次调出来或者单纯调用组件中的数据。也可用于为组件某个部分自定义样式以及为某次使用组件自定义样式。 直接拿elementui的el-table举例&#xff1a; <template><el-table v-loading"loading&q…

55. 右旋字符串(第八期模拟笔试)

55. 右旋字符串&#xff08;第八期模拟笔试&#xff09; 原题链接&#xff1a;完成情况&#xff1a;解题思路&#xff1a;参考代码&#xff1a;错误经验吸取 原题链接&#xff1a; 55. 右旋字符串&#xff08;第八期模拟笔试&#xff09; https://kamacoder.com/problempage…

spring6-国际化:i18n | 数据校验:Validation

文章目录 1、国际化&#xff1a;i18n1.1、i18n概述1.2、Java国际化1.3、Spring6国际化1.3.1、MessageSource接口1.3.2、使用Spring6国际化 2、数据校验&#xff1a;Validation2.1、Spring Validation概述2.2、实验一&#xff1a;通过Validator接口实现2.3、实验二&#xff1a;B…

伦敦金冬令时开市时间怎样调整

在刚刚过去的一周&#xff0c;欧美的金融市场已经正式进入了冬令时&#xff0c;这对伦敦金市场的交易时间也产生了影响。由于美国于今年11月5日(星期日&#xff09;开始正式实施冬令时间&#xff0c;所以香港的伦敦金平台的交易时间也随之而有所调整。 从今年11月6日开始&#…

体力属性在重生奇迹MU中的演变史

我相信&#xff0c;在任何一个网络游戏中都有体力这种属性&#xff0c;它本身就是血量的另一种表达&#xff0c;先天体力有优势的职业&#xff0c;往往就是后期成长较高&#xff0c;这已经是网游中一种常态&#xff0c;因为高血在PK中占据优势&#xff01;重生奇迹MU同样如此&a…

FiRa标准——MAC实现(二)

在IEEE 802.15.4z标准中&#xff0c;最关键的就是引入了STS&#xff08;加扰时间戳序列&#xff09;&#xff0c;实现了安全测距&#xff0c;大大提高了测距应用的安全性能。在FiRa的实现中&#xff0c;其密钥派生功能是非常重要的一个部分&#xff0c;本文首先对FiRa MAC中加密…

Haproxy实现七层负载均衡

目录 Haproxy概述 haproxy算法&#xff1a; Haproxy实现七层负载 ①部署nginx-server测试页面 ②(主/备)部署负载均衡器 ③部署keepalived高可用 ④增加对haproxy健康检查 ⑤测试 Haproxy概述 haproxy---主要是做负载均衡的7层&#xff0c;也可以做4层负载均衡 apache也可…

光刻掩膜版怎么制作的?

光掩膜版基本上是 IC 设计的“主模板”。掩模版有不同的尺寸。常见尺寸为 6 x 6 英寸一般的掩膜版由石英或玻璃基板组成。光掩膜版涂有不透明薄膜。更复杂的掩模版使用其他材料。 一般来说&#xff0c;术语“photo mask”用于描述与 1X 步进机或光刻系统一起使用的“主模板”。…

Xmind常用快捷键

Xmind 是什么&#xff1f; Xmind 是一款全功能的思维导图和头脑风暴软件。像大脑的瑞士军刀一般&#xff0c;助你理清思路&#xff0c;捕捉创意。 全功能&#xff1a;提供9种专业的的思维导图结构&#xff0c;丰富的模板和配色&#xff0c;精美的贴纸和插画&#xff0c;还有演…

ansible-第二天

ansible 第二天 以上学习了ping、command、shell、script模块&#xff0c;但一般不建议使用以上三个&#xff0c;因为这三个模块没有幂等性。举例如下&#xff1a; [rootcontrol ansible]# ansible test -a "mkdir /tmp/1234"[WARNING]: Consider using the file …

RabbitMQ 之 Work Queues 工作队列

目录 一、轮训分发消息 1、抽取工具类 2、启动两个工作线程 3、生产者代码 4、结果展示 二、消息应答 1、概念 2、自动应答 3、消息应答的方法 4、Multiple 的解释 5、消息自动重新入队 6、消息手动应答代码 &#xff08;1&#xff09;生产者 &#xff08;2&#…
最新文章