小白学STM32——跑马灯寄存器版本

      

一.寄存器简介

STM32 的 IO 口可以由软件配置成如下 8 种模式:
1)、输入浮空
2)、输入上拉
3)、输入下拉
4)、模拟输入
5)、开漏输出
6)、推挽输出
7)、推挽式复用功能
8)、开漏复用功能

        每个 IO 口可以自由编程,但 IO 口寄存器必须要按 32 位字被访问。STM32 的很多 IO 口都
是 5V 兼容的。
        STM32 的每个 IO 端口都有 7 个寄存器来控制。他们分别是:

         GPIOx_CRL :   端口配置低寄存器 ,0-7

         GPIOx_CRH :端口配置高寄存器, 8-15

         GPIOx_IDR : 端口输入寄存器

         GPIOx_ODR :端口输出寄存器

          GPIOx_BSRR :端口位设置/清除寄存器

          GPIOx_BRR :端口清除寄存器   

          GPIOx_LCKR :端口清配置锁存寄存器

STM32 的 IO 口位配置表如表所示:

STM32 输出模式配置如表 所示:

端口低配置(0-7)寄存器 CRL 的描述,如图所示:

 该寄存器的复位值为 0X4444 4444,从图 6.1.1 可以看到,复位值其实就是配置端口为浮空
输入模式。从上图还可以得出:STM32 的 CRL 控制着每组 IO 端口(A~G)的低 8 位的模式。
每个 IO 端口的位占用 CRL 的 4 个位,高两位为 CNF,低两位为 MODE。这里我们可以记住几
个常用的配置,比如 0X0 表示模拟输入模式(ADC 用)、0X3 表示推挽输出模式(做输出口用,
50M 速率)、0X8 表示上/下拉输入模式(做输入口用)、0XB 表示复用输出(使用 IO 口的第二
功能,50M 速率)。

端口高配置(8-15)寄存器 CRH


CRH 的作用和 CRL 完全一样,只是 CRL 控制的是低 8 位输出口,而 CRH 控制的是高 8
位输出口。这里我们对 CRH 就不做详细介绍了。

:比如我们要设置 PORTC 的 11 位为上拉输入(1000),12 位为推挽输出50MHz(0011)。代码如下:

 先清除该位的数据、后设置状态

GPIOC->CRH&=0XFFF00FFF; //清掉这 2 个位原来的设置,同时也不影响其他位的设置
GPIOC->CRH|=0X00038000; //PC11 输入,PC12 输出
GPIOC->ODR=1<<11; //PC11 上拉

通过这 3 句话的配置,我们就设置了 PC11 为上拉输入,PC12 为推挽输出。


IDR 是一个端口输入数据寄存器,只用了低 16 位。该寄存器为只读寄存器,并且只能以
16 位的形式读出。该寄存器各位的描述如图 6.1.2 所示:

要想知道某个 IO 口的状态,你只要读这个寄存器,再看某个位的状态就可以了。使用起
来是比较简单的。
ODR 是一个端口输出数据寄存器,也只用了低 16 位。该寄存器为可读写,从该寄存器读
出来的数据可以用于判断当前 IO 口的输出状态。而向该寄存器写数据,则可以控制某个 IO 口
的输出电平。该寄存器的各位描述如图 6.1.3 所示:

 通过 BSRR 和 BRR 寄存器设置 GPIO 端口输出

BSRR

该寄存器通过举例子可以很清楚了解它的使用方法。

例:设置 GPIOA 的第 1 个端口值为 1,那么只需要往寄存器 BSRR 的低 16 位对应位写 1 即可:

GPIOA->BSRR=1<<1;
 设置 GPIOA 的第 1 个端口值为 0,只需要往寄存器高 16 位对应为写 1 即可:

GPIOA->BSRR=1<<(16+1)
该寄存器往相应位写 0 是无影响的,所以我们要设置某些位,我们不用管其他位的值。
 

BRR

 BRR 寄存器是端口位清除寄存器。该寄存器的作用跟 BSRR 的高 16 位雷同,这里就不做
详细讲解。

二.跑马灯寄存器实现

1.硬件设计

引脚:         LED0 ---GPIOB_5         LED1 ---GPIOE_5

GPIO输出方式:         推挽输出

2.软件设计

1)使能寄存器(RCC_APB2ENR)

在STM32开发手册中找到APB2 外设时钟使能寄存器(RCC_APB2ENR)

要使能GPIOE_5和GPIOB_5

2)工程搭建

工程搭建与库函数版本相同,这里就不多赘述。

需要新搭建:HARDWARE--->LED--->led.c和led.h文件

led.h代码如下

#ifndef __LED_H
#define __LED_H

void LED_Init(void);  //LED初始化函数

#endif

代码分析:这段代码包括了LED初始化函数 void LED_Init(void); 

led.c代码如下

#include "led.h"
#include "stm32f10x.h"

void LED_Init(){
	
	//使能 GPIOB,GPIOE 端口时钟
	RCC->APB2ENR|=1<<3;  //|=1<<3 第3位变成1,其他位不变 使能GPIOB
  RCC->APB2ENR|=1<<6;  //|=1<<6 第6位变成1,其他位不变 使能GPIOE
	
	//GPIOB.5
	GPIOB->CRL&=0xFF0FFFFF;   //&=0xFF0FFFFF 第5位清零,其余位保持不变
	GPIOB->CRL|=0x00300000;   //|=0x00300000 第5位赋值成3,即0011,第5位为推挽输出模式,最大速度50MHz; 其余位置不变
  GPIOB->ODR|=1<<5;         //|=1<<5       控制第5位输出高电平,即灯灭 ,其余不变
	
	//GPIOE.5
	GPIOE->CRL&=0xFF0FFFFF;   //&=0xFF0FFFFF 第5位清零,其余位保持不变
	GPIOE->CRL|=0x00300000;   //|=0x00300000 第5位赋值成3,即0011,第5位为推挽输出模式,最大速度50MHz; 其余位置不变
	GPIOE->ODR|=1<<5;         //|=1<<5       控制第5位输出高电平,即灯灭 ,其余不变
	
}

代码分析:

①万能头文件和led头文件

#include "led.h"
#include "stm32f10x.h"

②使能GPIOB和GPIOE

//使能 GPIOB,GPIOE 端口时钟
RCC->APB2ENR|=1<<3;  //|=1<<3 第3位变成1,其他位不变 使能GPIOB
RCC->APB2ENR|=1<<6;  //|=1<<6 第6位变成1,其他位不变 使能GPIOE

分析:a.需要使能寄存器(RCC_APB2ENR);

           b.其中GPIOB是位3,GPIOE是位6;

           c. |= 或逻辑 ,|=1<<3 第3位变成1,其他位不变 使能GPIOB,GPIOE同理。

③设置GPIOB_5(推挽输出50MHz)

//GPIOB.5
GPIOB->CRL&=0xFF0FFFFF;   //&=0xFF0FFFFF 第5位清零,其余位保持不变
GPIOB->CRL|=0x00300000;   //|=0x00300000 第5位赋值成3,即0011,第5位为推挽输出模式,最大速度50MHz; 其余位置不变
GPIOB->ODR|=1<<5;         //|=1<<5       控制第5位输出高电平,即灯灭 ,其余不变

 分析:a.需要GPIOB的位5 ,为低端口(0-7),则需要用端口低配置(0-7)寄存器 CRL

            b.配置时需要先将该位清零,其余保持不变 ; GPIOB->CRL&=0xFF0FFFFF;

            c.然后赋值 GPIOB->CRL|=0x00300000;   第5位为推挽输出模式(00),速度50MHz(              11),则第5位为0011,赋值成3。其余位保持不变。

            d.最后将该位设置为高电,平即灯灭 ,其余不变。则需要用 ODR 端口输出数据寄存          器;操作为:GPIOB->ODR|=1<<5;

④设置GPIOE_5(推挽输出50MHz)

//GPIOE.5
GPIOE->CRL&=0xFF0FFFFF;   //&=0xFF0FFFFF 第5位清零,其余位保持不变
GPIOE->CRL|=0x00300000;   //|=0x00300000 第5位赋值成3,即0011,第5位为推挽输出模式,最大速度50MHz; 其余位置不变
GPIOE->ODR|=1<<5;         //|=1<<5       控制第5位输出高电平,即灯灭 ,其余不变

与设置GPIOB_5(推挽输出50MHz)原理相同。

main.c代码如下

#include "stm32f10x.h"
#include "led.h"
#include "delay.h"
 
 int main(void)
 {	
	 
	 //初始化延迟函数
	 delay_init();
	 //初始化GPIO口
	 LED_Init();
	 
	 while(1){
		 
		 GPIOB->ODR|=1<<5;  //控制第5位输出高电平,即灯灭 ,其余不变
		 GPIOE->ODR|=1<<5; 
		 delay_ms(500);
		 
		 GPIOB->ODR&=~(1<<5); //控制第5位输出低电平,即灯亮 ,其余不变
		 GPIOE->ODR&=~(1<<5);
		 delay_ms(500);
		  
	 }
 }
 

代码分析:

①头文件

#include "stm32f10x.h"
#include "led.h"
#include "delay.h"

分析:需要万能头文件,led.h 和 延迟函数头文件

②主函数中初始化

//初始化延迟函数
delay_init();
//初始化GPIO口
LED_Init();

③执行操作

while(1){
		 
  GPIOB->ODR|=1<<5;  //控制第5位输出高电平,即灯灭 ,其余不变
  GPIOE->ODR|=1<<5; 
  delay_ms(500);
		 
  GPIOB->ODR&=~(1<<5); //控制第5位输出低电平,即灯亮 ,其余不变
  GPIOE->ODR&=~(1<<5);
  delay_ms(500);
		  
}

分析:a.执行操作时需要一个while(1)死循环

           b.控制GPIOB和GPIOE第5位输出高电平,即灯灭。需要用到ODR 端口输出数据寄存器,

      具体操作为 GPIOB->ODR|=1<<5 和 GPIOE->ODR|=1<<5 。

           c.控制GPIOB和GPIOE第5位输出低电平,即灯亮 。

      具体操作为 GPIOB->ODR|=1<<5 和 GPIOE->ODR|=1<<5 。

           d.延迟函数 delay_ms(500);

             

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值