STM32使用寄存器点灯实验

寄存器点灯实验

操作过程

使能IO口时钟配置寄存器RCC_APB2ENR

初始化IO口模式,配置寄存器GPIOx_CRH/CRL

操作IO口,输出高低电平,配置寄存器GPIOx_ODR或者BSRR/BRR。

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

在STM32中文参考手册6.3RCC寄存器描述的6.3.7小节可以看到该寄存器的使用说明

STM32使用寄存器点灯实验_第1张图片

因为使用的是GPIOA端口组,所以使能IOPAEN位,该位置1则IO端口A时钟开启

端口配置低寄存器(GPIOx_CRL) (x=A…E)

在中文参考手册的8.2节可以找到GPIO寄存器相关配置寄存器的描述
STM32使用寄存器点灯实验_第2张图片

因为开发板上的PA1连接到了LED灯,所以对CNF1和MODE1进行初始化,MODE1初始化为11,设置为输出模式,速度为50MHz,CNF1初始化为00,设置为通用推挽输出模式

因为没有用到更高的引脚位,所以端口配置高寄存器(GPIOx_CRH) 并不用配置

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

STM32使用寄存器点灯实验_第3张图片

往ODR寄存器的ODR1位写入0,则PA1引脚输出低电平,LED灯被点亮

端口位设置/清除寄存器(GPIOx_BSRR) ,端口位清除寄存器(GPIOx_BRR)

也可以使用这两个寄存器,因为是PA1输出低电平LED灯才被点亮,所以这两个寄存器都有效

如果LED灯是引脚输出高电平才能被点亮,那就只有端口位设置/清除寄存器(GPIOx_BSRR)的设置功能才能输出高电平,BRR寄存器不行

STM32使用寄存器点灯实验_第4张图片

STM32使用寄存器点灯实验_第5张图片

程序

参照手册搭建好寄存器的工程模板后,新建LED.h和LED.c文件,开始编写代码

LED.h

在头文件中要添加函数声明,因为写了多种初始化方法,所以这些函数都要添加声明

#ifndef __LED_H__
#define __LED_H__

//宏定义,LED_Init_3,LED_Init_4
#define IOPAEN                  0x01<<2
#define CNF1_AND_MODE1          ((u32)0x0F<<4)
#define OUT_MODE_PP			   ((u32)0x03<<4)
#define ODR1                    ((u16)0x01<<1)
#define BSRR_BR1                ((u32)0x01<<17)
#define BRR_BR1                 ((u16)0x01<<1)

void LED_Init_1(void);
void LED_Init_2(void);
void LED_Init_3(void);
void LED_Init_4(void);

#endif

LED.c

分别用三种不同的写法实现点亮LED灯,方法一是直接往寄存器写入十六进制,方法二是用移位的方法初始化寄存器,但这两种方法的数值第一眼看去不好理解,不看参考手册的话很难知道0xFFF4是初始化什么,(u16)0x01<<2也是一样

所以推荐使用第三种方法,用宏定义,先在LED.h头文件中定义好数值,然后使用时直接调用宏名即可,可以让人一眼就看出初始化的是哪个位

第四种方法是使用BSRR或BRR寄存器对PA1进行赋值,一样能使LED灯点亮

#include "LED.h"
#include "stm32f10x.h"

/**
  * @name 	LED_Init_1
  * @brief	LED初始化-寄存器(写法1)
  * @param	None
  * @retval	None
  */
void LED_Init_1()
{
	//初始化APB2上GPIOA的时钟
	RCC->APB2ENR |= 0xFFF4;

  //GPIOA端口配置低寄存器
  //4 ~ 7配置的是PA1,所以先将这4位清零
  GPIOA->CRL &= 0xFFFFFF0F;

  //然后MODE1初始化为11,CNF1初始化为00,设置为通用推挽输出模式
  GPIOA->CRL |= 0xFFFFFF3F;

  //配置端口输出数据寄存器,将ODR1置0,输出低电平,点亮LED
  GPIOA->ODR &= 0xFFFD;
}

/**
  * @name 	LED_Init_2
  * @brief	LED初始化-寄存器(写法2)
  * @param	None
  * @retval	None
  */
void LED_Init_2()
{
  //初始化APB2上GPIOA的时钟
  RCC->APB2ENR |= ((u16)0x01<<2);

  //GPIOA端口配置低寄存器
  //4 ~ 7配置的是PA1,所以先将这4位清零
  GPIOA->CRL &= ~((u32)0x0F<<4);

  //然后MODE1初始化为11,CNF1初始化为00,设置为通用推挽输出模式
  GPIOA->CRL |= ((u32)0x03<<4);

  //配置端口输出数据寄存器,将ODR1置0,输出低电平,点亮LED
  GPIOA->ODR &= ~((u16)0x01<<1);
}

/**
  * @name 	LED_Init_3
  * @brief	LED初始化-寄存器(写法3)
  * @param	None
  * @retval	None
  */
void LED_Init_3()
{
	//初始化APB2上GPIOA的时钟
	RCC->APB2ENR |= IOPAEN;

	//GPIOA端口配置低寄存器
	//4 ~ 7配置的是PA1,所以先将这4位清零
	GPIOA->CRL &= ~CNF1_AND_MODE1;

	//然后MODE1初始化为11,CNF1初始化为00,设置为通用推挽输出模式
	GPIOA->CRL |= OUT_MODE_PP;

	//配置端口输出数据寄存器,将ODR1置0,输出低电平,点亮LED
	GPIOA->ODR &= ~ODR1;
}


/**
  * @name 	LED_Init_4
  * @brief	LED初始化-寄存器(测试BSRR寄存器和BRR寄存器)
  * @param	None
  * @retval	None
  */
void LED_Init_4()
{
  //初始化APB2上GPIOA的时钟
	RCC->APB2ENR |= IOPAEN;

	//GPIOA端口配置低寄存器
	//4 ~ 7配置的是PA1,所以先将这4位清零
	GPIOA->CRL &= ~CNF1_AND_MODE1;

	//然后MODE1初始化为11,CNF1初始化为00,设置为通用推挽输出模式
	GPIOA->CRL |= OUT_MODE_PP;

	//配置端口输出数据寄存器,将ODR1置0,输出低电平,点亮LED
	//GPIOA->ODR &= ~ODR1;

  //配置端口位设置/清除寄存器(GPIOx_BSRR) 31-16位置1则对应的ODR位清0,LED点亮
  //GPIOA->BSRR |= BSRR_BR1;

  //配置端口位清除寄存器(GPIOx_BRR) 15-0位置1则对应的ODR位清0,LED点亮
  GPIOA->BRR |= BRR_BR1;
}

main.c

主函数中引入LED.h头文件后,直接调用LED初始化函数即可

#include "LED.h"

int main()
{
	//LED_Init_1();
	//LED_Init_2();
	//LED_Init_3();
	LED_Init_4();
	while(1)
	{
		
	}
}

你可能感兴趣的:(STM32,stm32,单片机,arm,学习,嵌入式硬件)