其他分享
首页 > 其他分享> > stm32点亮流水灯(小白的求学之路)

stm32点亮流水灯(小白的求学之路)

作者:互联网

文章目录


前言

由于之前作者仅仅只学习了51单片机的一些操作,对stm32单片机操作完全不会,过程中很曲折,如果有什么错的地方,希望可以告诉作者加以改正。

一、怎么点亮一个LED?

这个问题困扰了很久,因为stm32与51不同,51单片机直接可以操作引脚,而stm32要复杂得多。下面我们先来了解一下输入输出管脚——GPIO。

1、GPIO简介

GPIO 是通用输入输出端口的简称,简单来说就是 STM32 可控制的引脚,STM32 芯片的 GPIO 引脚与外部设备连接起来,从而实现与外部通讯、控制以及数据采集的功能。
STM32 芯片的 GPIO 被分成很多组,每组有 16 个引脚,如 GPIOA、GPIOB、GPIOC,所有的 GPIO 引脚都有基本的输入输出功能。
(这里我们可以类比51单片机的引脚,点灯的时候只需要将GPIO管脚置为高电平或者低电平)
问题又来了,怎么设置GPIO管脚呢?
这个时候就会用到寄存器啦。

2、寄存器

1、片上外设区分为三条总线,根据外设速度的不同,不同总线挂载着不同的外设,APB1挂载低速外设,APB2 和 AHB 挂载高速外设。相应总线的最低地址我们称为该总线的基地址,总线基地址也是挂载在该总线上的首个外设的地址。其中 APB1 总线的地址最低,片上外设从这里开始,也叫外设基地址。

总线名称总线基地址相对外设基地址的偏移
APB10x4000 00000x0
APB20x4001 00000x0001 0000
AHB0x4001 80000x0001 8000

(到这里可以发现一个公式:地址=基地址+相对地址偏移)
2、外设基地址
GPIO 属于高速的外设 ,挂载到APB2 总线上。
在这里插入图片描述

外设名称外设基地址相对 APB2 总线的地址偏移
GPIOA0x4001 08000x0000 0800
GPIOB0x4001 0C000x0000 0C00
GPIOC0x4001 10000x0000 1000

现在我们知道了GPIO的地址,是不是意味着可以直接通过地址来设置GPIO呢?
答案还是否定的,还需要操作里面特定功能的寄存器来设置GPIO管脚,比如:输入数据寄存器 GPIOx_IDR,GPIO 模式GPIOx_CRL或者GPIOx_CRH,时钟使能RCC_APB2ENR。

3、 APB2 外设时钟使能寄存器(RCC_APB2ENR)
为减小stm32的功耗而设置,如果不把对应管角的时钟使能,对应管脚不会工作。
在这里插入图片描述

这里我们以打开GPIOA的时钟为例子:
首先找到APB2的地址0x4001 0000,通过地址=基地址+相对地址偏移,得到RCC_APB2ENR的地址0x4001 0018。我们可以直接赋值为0x00000004

4、GPIO 模式GPIOx_CRL或者GPIOx_CRH
每个 GPI/O 端口有两个 32 位配置寄存器(GPIOx_CRL,GPIOx_CRH)。低8位GPIOx0—7在GPIOx_CRL,高8位GPIOx8—15在GPIOx_CRH。
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
什么是推挽输出?什么又是开漏输出呢?
推挽输出:可以输出高,低电平,连接数字器件。(我们点亮LED的模式)
开漏输出:输出端相当于三极管的集电极,要得到高电平状态需要上拉电阻才行,适合于做电流型的驱动,其吸收电流的能力相对强(一般20ma以内)。

例如把GPIOB8设置为推挽输出,就找到GPIOB_CRH的地址,赋值为0x00000002。

5.输入数据寄存器 GPIOx_IDR
在这里插入图片描述
假如我们想点亮PA0,只需要将IDR0位置为0;

二、硬件

现在我们知道了软件的编写,硬件又该怎么连接呢?
在这里插入图片描述
我用的是stm32f103c8t6芯片,本次运用了GPIO_A8和GPIO_B8,和GPIO_C13,找到与之对应的管脚A8,B8,C13,用线把管脚引出来,再将LED的低电平引脚相连(LED长的引脚为高电平)。
在这里插入图片描述
采用串口通信,需要usb与STM32如图链接。其中要求usb的RXD连接核心板的TXD(A9),usb的TXD连接核心板的RXD(A10)。

烧录软件:
需要用到MCUISP
在这里插入图片描述
使用教程: STM32最小系统下载程序方法.

三、用寄存器点亮流水灯

代码如下:

#include<stdio.h>
#define pRCC_APB2ENR	*((unsigned volatile int*)0x40021018)//APB2的地址
#define pGPIOB_CRH	*((unsigned volatile int*)0x40010c04)//GPIO_B8的模式
#define pGPIOB_ODR	*((unsigned volatile int*)0x40010c0c)//GPIO_B8的数据
	//GPIO_B8配置寄存器
#define pGPIOC_CRH	*((unsigned volatile int*)0x40011004)//GPIO_C13的模式
#define pGPIOC_ODR	*((unsigned volatile int*)0x4001100c)//GPIO_C13的数据
	//GPIO_C0配置寄存器
#define pGPIOA_CRH	*((unsigned volatile int*)0x40010804)//GPIO_A8的模式
#define pGPIOA_ODR	*((unsigned volatile int*)0x4001080c)//GPIO_A8的数据
	//GPIO_A8配置寄存器
	void  Delay_ms( volatile  unsigned  int  t) 
{
     unsigned  int  i;
     while(t--)
         for (i=0;i<800;i++);
}
int main(void)
    {
      pRCC_APB2ENR =0x0000001c;//打开APB2中B,C,D外设时钟
			
			pGPIOB_CRH =0x00000002;
			pGPIOC_CRH =0x00200000;
			pGPIOA_CRH =0x00000002;
			//设置寄存器为推挽模式
			while(1)
			{
			  pGPIOB_ODR =0x00000000;
			Delay_ms(10000000);
			  pGPIOB_ODR =0x00000100;		
				Delay_ms(10000000);
				//闪烁GPIO_B8
				pGPIOA_ODR =0x00000000;
			Delay_ms(10000000);
			  pGPIOA_ODR =0x00000100;		
				Delay_ms(10000000);
				//闪烁GPIC_A8
				pGPIOC_ODR =0x00000000;
			Delay_ms(10000000);
			  pGPIOC_ODR =0x00002000;		
				Delay_ms(10000000);
				//闪烁GPID_C13
			}
    }

实验效果

在这里插入图片描述

总结

通过本次的学习,初步了解并实现了从软件到硬件的过渡,同时也学习到了很多关于stm32寄存器的知识,在学习的过程中有很多次都想放弃了,特别是在写软件的时候。最后,功夫不负有心人,做出来的效果还是不错的。

标签:求学,点亮,GPIOx,stm32,地址,寄存器,GPIO,CRH,外设
来源: https://blog.csdn.net/weixin_57517458/article/details/120883428