小言_互联网的博客

STM32直接用寄存器点亮GPIO口

453人阅读  评论(0)

直接调用定义好的文件来编程是很方便,但对于初学者很难理解,正所谓,学从难处学,用从易处用,今天看一下只需要启动文件和主函数点亮LED灯的方法。

一、创建一个文件

创建一个文件用来保存我们的工程。打开我的电脑在内存较多的盘里创建一个文件夹,记住这个文件夹的路径。

二、在keil中创建工程

1.打开keil5,找到Project。

2.点击Projict选择New μVision Project…

3.找到我们第一步里创建的文件,把工程放在创建的文件里,然后选择自己使用的芯片,我这里选的是STM32F103ZE。

4.创建一个文件命名为main.c并保存。


5.将启动文件放入到第一步新建的文件夹内。

6.向工程里添加启动文件和main.c文件。



7.可以看到右侧出现了两个文件,一个main.c文件和启动文件

8.在工程面板里也有了这两个文件,到这我们的准备工作就做完了,开始讲解如何点亮LED灯。

三、点亮LED灯的流程和寄存器讲解

1.点亮流程

想让小灯亮起来,我们得有以下三个步骤:
(1)使能GPIO口(为节能,STM32时钟默认都是关闭的,需手动开启)
(2)初始化GPIO口(选择模式)
(3)点亮LED灯。

2、RCC_APB2ENR(外设时钟使能寄存器)

想打开时钟,我们得知道GPIO口是挂在哪

通过数据手册可以看到,GPIO口都是挂在APB2上,所以我们得打开APB2的时钟。


可以看到,在这个寄存器里,2~8位分别控制GPIOA~GPIOG,哪个位 置1,就开启了对应GPIO口的时钟,相反置 0 就是关闭了时钟。

//对于不同的开发板,灯的连接IO口不一样
//我使用的开发板LED连接在GPIOB和GPIOE上
RCC_APB2ENR|=1<<3;	//使能GPIOB口

3、GPIOx_CRL(端口配置低寄存器)/GPIOx_CRH(端口配置高寄存器)

GPIO口有八种模式:
─ 输入浮空
─ 输入上拉
─ 输入下拉
─ 模拟输入
─ 开漏输出
─ 推挽式输出
─ 推挽式复用功能
─ 开漏复用功能
如何配置这些功能?我们来看这个寄存器:

图里标注出了,0~3位控制 0 号引脚,4~7位控制1 号引脚,依次类推,端口低位配置寄存器控制0~7号引脚,端口高位配置寄存器控制8~15号引脚,两个寄存器配置方式一样,我们先配置MODE,再配置CNF,我们在点灯时需要设置推挽输出,先配置MODE就是10,再配置CNF就是00,所以,给哪个引脚设置0010,哪个引脚就是推挽输出。
在这,说明一下,引脚是复位值是0x44444444,也就是复位后为浮空输入,我们要设置PB5推挽输出,所以我们得用GPIOB_CRL&=0xFF0FFFFF; 将需要设置的位清零,如若不清零,在设置后GPIOB_CRL的值实际上为0x44644444;可以看到,它是开漏输出。

GPIOB_CRL&=0xFF0FFFFF;				//复位值是0x44444444,我们得把需要设置的引脚先置 0 再设置
GPIOB_CRL|=0x00200000;				//PB5推挽输出模式

3、BSRR、BRR、ODR

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


BSRR寄存器低15位置 1 是设置输出高电平,高15位置 1 是设置输出低电平。

GPIOB_BSRR|=1<<5;		//PB5输出高电平
GPIOB_BSRR|=1<<21;		//PB5输出低电平

(2)GPIOx_BRR(位清除寄存器)



BRR寄存器只能用来清除,也就是如果低15位置 1 是输出低电平,高15位是保留的。

	GPIOB_BRR|=1<<5;		//PB5输出低电平

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

和BSRR类似,低15位置 1 输出高电平,置 0 输出低电平,高15位保留。

	GPIOB_ODR|=1<<5;		//PB5输出高电平
	GPIOB_ODR|=~1<<5;	//PB5输出低电平

点亮LED灯需要根据线路来确定

我的开发板上是低电平亮,高电平灭。

四、寄存器地址查询

寄存器地址可以在STM32参考手册里找到,在存储器映像中


每个寄存器都有偏移地址,初始地址+偏移地址就是这个寄存器的地址。

#define RCC_APB2ENR		*((unsigned volatile int*)0x40021018)//RCC_APB2ENR寄存器地址
#define GPIOB_CRL		*((unsigned volatile int*)0x40010C00)//GPIOB_CRL寄存器地址
#define GPIOB_BSRR		*((unsigned volatile int*)0x40010C10)//GPIOB_BSRR寄存器地址
#define GPIOB_BRR		*((unsigned volatile int*)0x40010C14)//GPIOB_BRR寄存器地址	
#define	GPIOB_ODR		*((unsigned volatile int*)0x40010C0C)//GPIOB_ODR寄存器地址

需要哪个寄存器我们就按上边定义寄存器地址

五、总程序

//程序实现点亮PB5 LED灯
#define RCC_APB2ENR		*((unsigned volatile int*)0x40021018)//RCC_APB2ENR寄存器地址
#define GPIOB_CRL		*((unsigned volatile int*)0x40010C00)//GPIOB_CRL寄存器地址
#define	GPIOB_ODR		*((unsigned volatile int*)0x40010C0C)//GPIOB_ODR寄存器地址
int main()
{
   
	RCC_APB2ENR|=1<<3;					//GPIOB时钟使能
	
	GPIOB_CRL&=0xFF0FFFFF;				//引脚初始化
	GPIOB_CRL|=0x00200000;				//PB5推挽
	GPIOB_ODR|=1<<5;					//若LED低电平亮,设置推挽输出后LED灯就会亮,所以这先设置输出高电平,让灯灭
	
	while(1)							//不设置死循环,程序运行结束,灯只亮一下
	{
   
		GPIOB_ODR|=~(1<<5);				//输出低电平,灯亮
	}
}

六、总结

其实调用库文件写程序和定义好的寄存器文件写程序,都是对寄存器的操作,就是人家给你提前定义好了,你只需要调用文件就行了,我这样写出来,对寄存器操作更直观,能够让初学者不再困惑对于寄存器的操作,到这既然点亮了一个LED,那做流水灯也已经很容易了,只需要再点亮一个LED,并让两个灯一亮一灭,就能达到流水灯的效果,操作蜂鸣器也呼之欲出,因为都是GPIO口输出。

初学STM32,也是第一次发博客,不正确的地方敬请指教~~~


转载:https://blog.csdn.net/gelad_w/article/details/115429648
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场