GPIO寄存器配置

本文详细介绍了如何使用STM32F103单片机的GPIO进行寄存器配置,包括PA8、PA11、PA12的配置,以及如何通过寄存器操作实现GPIO的输入输出模式,还讨论了在模拟IIC和SPI任务中的应用实例,最后展示了如何实现简单的流水灯效果。
摘要由CSDN通过智能技术生成

点灯大师之寄存器配置操作

前言

本文主要写给已经入门stm32f103但时间没那么长的朋友,也欢迎各位大佬斧正。

最近的ARM课要求我们使用stm32f103单片机来完成一个GPIO口的配置与翻转任务,如果只是使用标准库函数来配置的话十分简单,于是我想到了通过寄存器配置的方式来完成这个任务,顺便再来复习复习有关于GPIO的输入与输出问题,同时也探讨一下在许多软件模拟IIC或SPI任务里的一些常见用法。

代码差异

本文里使用的GPIO口为PA8、PA11、PA12
使用标准库进行配置代码如下

void LED_Init(void)
{
	GPIO_InitTypeDef  GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_11|GPIO_Pin_12;				 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		
	GPIO_Init(GPIOA, &GPIO_InitStructure);			 
}

如果是配置寄存器那么可以这么写

void LED_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	//PA8
	GPIOA->CRH&=0XFFFFFFF0;GPIOA->CRH|=0x3;
	//PA11
	GPIOA->CRH&=0XFFFF0FFF;GPIOA->CRH|=0x3000;
	//PA12
	GPIOA->CRH&=0XFFF0FFFF;GPIOA->CRH|=0x30000;
}

原理分析

在分析原理之前,我想多提一嘴
你可能在其它地方(比如IIC通讯里)使用类似这样的代码:

#define SDA_IN()  {GPIOB->CRL&=0XFFFFFF0F;GPIOB->CRL|=8<<4;}
#define SDA_OUT() {GPIOB->CRL&=0XFFFFFF0F;GPIOB->CRL|=3<<4;}

上面的代码就是直接通过配置寄存器的方式来实现GPIO口的输入与输出配置的。

下面,咱们来看看这些代码到底是什么含义。

参考STM32参考手册第八章 8.2节GPIO寄存器描述

在这里插入图片描述
在这里插入图片描述

用于配置一个PORT的GPIO寄存器一共由两个,分别是高位寄存器和低位寄存器。
高位寄存器用于管理这个PORT的高八位引脚(8-15);低位寄存器用于管理这个PORT的低八位引脚(0-7).

拿本次的点灯代码来举例分析,我希望把PA8配置为推挽输出和最大50MHz频率。

PA8所在的端口为A口,并且由GPIO高位寄存器(CRH)的前四位管理(CNF8和MODE8),表上所提示的信息是当MODE不为0时,CNF决定输出模式;MODE为0时,CNF决定输入模式。

MODE不为0时有3种状态可选择,配置为01则最大速度为10MHz,10时为最大2MHz,11为最大50MHz;此时,CNF取00时,IO口就会被配置为推挽输出模式,01则为开漏输出模式…

GPIOA->CRH&=0XFFFFFFF0;GPIOA->CRH|=0x3;

上面这句代码的意思就是选择GPIO A的高位寄存器,保留前4*7=28位配置不变,然后给最后的4位(也就是对应PA8的管理位)配置位0x3,也就是二进制的0011,前两位00配置给CNF,后两位11配置给MODE,对应在表上的内容就是把这个引脚配置为推挽输出模式,最大速度50MHz。

那么我们不妨再来看看模拟IIC时的代码:

#define SDA_IN()  {GPIOB->CRL&=0XFFFFFF0F;GPIOB->CRL|=(u32)8<<4;}
#define SDA_OUT() {GPIOB->CRL&=0XFFFFFF0F;GPIOB->CRL|=(u32)3<<4;}

这两句宏定义定义了SDA线的输入输出模式
其中SDA_IN()在执行时会选择GPIO B端口的低位寄存器,清空2号引脚的配置其它引脚的配置保留,然后再把0x8(也就是二进制1000)配置给某一个引脚。

这个引脚在哪呢?当你把0x8左移4位之后,它就变成了0x80(也就是1000 0000),代码里使用|=相当于把低位寄存器的第7位(一般都是从0位开始计数,所以到第八位的时候,其实是寄存器的第7位)配置为1。

由于前面把2号引脚的配置给清空了,所以此时寄存器的第7位到第4位(也就是对应管理2号引脚的位)的值位二进制的1000,对应之前的表可知:MODE位为00表示该引脚配置为输入模式CNF位为10表示该引脚配置为上拉/下拉输入模式

那么下面那句SDA_OUT()我想你应该已经知道了它的含义,就不说了。看到这里,相信你已经可以在别人代码的基础上更改模拟IIC、SPI等通讯协议的引脚配置了,这将会使你能够自由地决定这些引脚的选用。

对于点灯、流水灯这种简单的应用来说,只要翻转IO口即可

GPIO_SetBits(LED_Port, LED_Pin);
GPIO_ResetBits(LED_Port, LED_Pin);
//或者
GPIO_WriteBit(LED_Port, LED_Pin, (BitAction)(state));

对于流水灯来说,只要再给一个延时关闭和点亮新的灯,然后放到循环里循环操作即可。

感谢您的阅读,希望本文能对您有所帮助,欢迎大佬们勘误

最后附上流水灯视频

流水灯

  • 39
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值