STM32 一灯大师——寄存器点亮流水灯

目录

1、配置端口输出数据寄存器(ODR)

2、配置低寄存器(CRL)

3、配置复位和时钟控制寄存器(RCC)

4、拓展:如何让PC2和PC3两个LED灯同时闪烁?

5、总结: GPIO功能框图和常用的寄存器

(1)CRL和CRH寄存器

(2)IDR和ODR寄存器

(3)端口位清楚寄存器(BRR)

(4)端口位设置/清除寄存器(BSRR)

6、总结:什么是推挽输出,什么是开漏输出

 (1)推挽输出:

 (2)开漏输出:

7、配置GPIO初始化结构体步骤

学习51我们从最简单的点灯开始,同样32也是,首先我们从最简单的寄存器控制点亮LED开始。

1、配置端口输出数据寄存器(ODR)

控制LED灯:给PC2/PC3输出低电平,LED灯亮;给PC2/PC3输出高电平,LED灯会灭。

那么如何控制端口:我们要选择GPIO寄存器的端口输出数据寄存器,该寄存器共有32位,高16位始终为0。因为控制端口是PC2/3,所以,外设基地址按照GPIOC的去写。

绝对地址=外设基地址+偏移地址

0X4001 1000+0C=0X4001 100C

注意:找到绝对地址之后,该绝对地址在系统看来只是一个数,所以我们要对他进行类型转换,让系统知道我们是对该地址里的内容进行操作。(unsigned int *)0x4001 100c:把后面的数转换为unsigned int指针类型,编译器就会认为这串数是个地址;*(unsigned int *)0x4001 100c表示该地址里的值。

*(unsigned int *)0X4001100C &= ~(1<<2);
*(unsigned int *)0X4001100C &= ~(1<<3);

PC2亮灭是对ODR2进行修改(左移2位),PC3亮灭是对ODR3进行修改(左移3位)。

还要注意的是,绝对地址的中间不能添加空格符!但是这样是烧写进去之后灯不会亮,是因为我们还没配置CRL寄存器。

2、配置低寄存器(CRL)

 这个寄存器来配置GPIO端口的输入输出模式。

由于是RC2/3所以是CNF2和MODE2来控制,CNF2取决于MODE的配置,MODE选择01,CNF2选择00(通用推挽输出模式)所以是0001(注意一个小方框里面就是2位)。

3、配置复位和时钟控制寄存器(RCC)

配置到这里,但是灯还是不会亮。因为stm32为了节省功耗,让每个外设都对应时钟,在上电复位之后,所有时钟都是关闭的。所以,如果你想使用GPIO这个外设,就需要把GPIO外设的时钟给打开。 由于GPIO是属于APB2的,所以用到APB2 外设时钟使能寄存器(RCC_APB2ENR);如果是属于APB1的外设,就用APB1外设时钟使能寄存器(RCC_APB1ENR)。

寻找RCC寄存器的绝对地址:偏移地址0X18,RCC属于AHB,起始地址为0X4002 1000,绝对地址为0X4002 1018

我们用到端口C,且置1是让时钟打开。让第4位置1即可。

 *(unsigned int *)0x40021018 |= (1<<4);

4、拓展:如何让PC2和PC3两个LED灯同时闪烁?

  CRL寄存器和ODR寄存器两个端口都要配置

#include "stm32f10x.h"

void soft_delay(unsigned int count);

int main(void)
{
	// &= ~用来清0(给某一位单独置0)
	// |= 用来给某一位单独置1
	
	//配置RCC寄存器,使能GPIO口的时钟
	*(unsigned int *)0x40021018 |= (1<<4); 
	
	//配置CRL寄存器,配置为推挽输出
	*(unsigned int *)0x40011000 |= (1<<(4*3)); 
	*(unsigned int *)0x40011000 |= (1<<(4*2)); 
	
	//配置ODR寄存器,决定I/O口输出低或高电平
 	//*(unsigned int *)0x4001100C &= ~(1<<2); 
	while(1)
	{
		*(unsigned int *)0x4001100C &= ~(1<<2); //亮
		*(unsigned int *)0x4001100C &= ~(1<<3); //亮
		soft_delay(0xfffff);
		*(unsigned int *)0x4001100C |= (1<<2); //灭
		*(unsigned int *)0x4001100C |= (1<<3); //灭
		soft_delay(0xfffff);
	}
}

void soft_delay(unsigned int count)//延时函数,但是不知道延时多长时间
{
	for(;count!=0;count--);
}

void SystemInit(void)
{
	
}

至此,点灯工作完毕,灯开始流水闪烁。

---------------------------------------------------------------------------------------------------------------------------------

5、总结: GPIO功能框图和常用的寄存器

GPIO是通用输入输出端口的简称,软件可控制的引脚。

(1)CRL和CRH寄存器

这两个都是32位的寄存器,因为STM32的GPIO口不像51单片机一样只有高低电平两个参数,STM32的每个GPIO口都有八种输出方式,通过寄存器配置确定是哪一种方式,除此之外,还有输出的速度,也是GPIO口的一个重要的参数。所以,要想描述STM32的一个GPIO的状态,就需要四个位(八种输出方式和三种输出速度),STM32的一个GPIO组有16个GPIO口,CRL和CRH都拥有32个位,CRL负责描述一个GPIO组的低八位GPIO(32/8 = 4,刚好够用),CRH负责描述一个GPIO组的高八位GPIO(同样,32/8 = 4,刚好够用)。

(2)IDR和ODR寄存器

1.IDR是一个端口输入数据寄存器,只使用了低16位,该寄存器为只读寄存器,并且只能以16位数据的形式读出,作用是可以通过其读出寄存器的状态是低还是高,要想知道具体是哪个寄存器的话,就需要看具体那个位的值了,在固件库中,通过

GPIO_ReadInputDataBit函数实现:

比如要读取GPIOA.5的状态,那么方法是:

返回值是 1(Bit_SET)或者 0(Bit_RESET);

2.ODR 是一个端口输出数据寄存器,也只用了低 16 位。该寄存器为可读写,从该寄存器读出来的数据可以用于判断当前 IO 口的输出状态。在固件库中设置 ODR 寄存器的值来控制 IO 口的输出状态是通过函数 GPIO_Write 来实现的:

该函数一般用来往一次性一个 GPIO 的多个端口设值。

(3)端口位清楚寄存器(BRR)


某一位置1:清除对应的位为0(复位)

(4)端口位设置/清除寄存器(BSRR)

高16位:清除,置1:清除对应的位为0(复位)

低16位:设置,置1:设置对应的位为1

BRR和BSRR这两个寄存器配置好之后会把数据传送给ODR这一位的数据就是0或者1.

6、总结:什么是推挽输出,什么是开漏输出

 (1)推挽输出:

     1、可以输出高低电平,用于连接数字器件,高电平由VDD决定,低电平由VSS决定。

     2、推挽结构指两个三极管受两路互补的信号控制,总是在一个导通的时候另外一个截止,优点开关效率效率高,电流大,驱动能力强。

     3、输出高电平时,电流输出到负载,叫拉电流,可以理解成推,输出低电平时,负载电流流向芯片,叫灌电流,即挽。

 (2)开漏输出:

     1、只能输出低电平,不能输出高电平。

     2、如果要输出高电平,则需要外接上拉。

     3、开漏输出具有“线与”功能,一个为低,全部为低,多用于I2C和SMBUS总线。

7、配置GPIO初始化结构体步骤

  (1)选定具体的GPIO(选择哪个I/O口)

  (2)配置GPIO工作模式(CRL和CRH寄存器)(CRL控制低8位I/O口,CRH控制高8位I/O口)

  (3)控制GPIO输出高低电平(ODR、BRR和BSRR)

  • 3
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值