ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2021-10-24 10:07:24  阅读:315  来源: 互联网

标签:求学 点亮 GPIOx stm32 地址 寄存器 GPIO CRH 外设


文章目录


前言

由于之前作者仅仅只学习了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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有