【02】STM32:跑马灯配置

一、库函数版本

1.新建一个 led.h 文件

#ifndef _LED_H
#define _LED_H
#include "sys.h"

#define LED0 PBout(5) // DS0
#define LED1 PEout(5) // DS1

void LED_Init(void); // LED接口初始化

#endif

  这段代码里面最关键就是 2 个宏定义,通过位带操作 PB5 输出高低电平从而控制 LED0 。

LED0=1; //通过位带操作控制 LED0 的引脚 PB5 输出高电平
LED0=0; //通过位带操作控制 LED0 的引脚 PB5 输出低电平

  同样也可以使用固件库操作和寄存器操作,来实现 IO 口操作。

GPIO_SetBits(GPIOB, GPIO_Pin_5); //设置 GPIOB.5 输出 1,等同 LED0=1;
GPIO_ResetBits (GPIOB, GPIO_Pin_5); //设置 GPIOB.5 输出 0,等同 LED0=0;

  还可以通过直接操作寄存器,BRR 和 BSRR 的方式来操作 IO 口输出高低电平。

GPIOB->BRR=GPIO_Pin_5; //设置 GPIOB.5 输出 1,等同 LED0=1;
GPIOB->BSRR=GPIO_Pin_5; //设置 GPIOB.5 输出 0,等同 LED0=0;

2.新建一个 led.c文件

#include "led.h"

void LED_Init(void)
{
	
	GPIO_InitTypeDef GPIO_InitStructure;
	
	// 使能GPIOB、GPIOE端口时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE); 
	
	// 配置GPIOB.5 推挽输出
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	GPIO_SetBits(GPIOB, GPIO_Pin_5);
	
	// 配置GPIOE.5 推挽输出
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
	GPIO_Init(GPIOE, &GPIO_InitStructure);
	GPIO_SetBits(GPIOE, GPIO_Pin_5);
}

  该函数的功能就是用来实现配置 PB5和 PE5 为推挽输出。这里需要注意的是:在配置 STM32 外设的时候,任何时候都要先使能该外设的时钟。GPIO 是挂载在 APB2 总线上的外设,在固件库中对挂载在 APB2 总线上的外设时钟使能是通过函数 RCC_APB2PeriphClockCmd()来实现的。

  需要说明的是,因为 GPIOB 和 GPIOE 的 IO 口的初始化参数都是设置在结构体变量GPIO_InitStructure 中,因为两个 IO 口的模式和速度都一样,所以我们只用初始化一次,在GPIOE.5 的初始化的时候就不需再重复初始化速度和模式了。

3.编写main.c文件

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

int main(void)
{
	delay_init(); // 延时函数初始化
	LED_Init(); // LED接口初始化
	while(1)
	{
		LED0 = 1;
		LED1 = 0;
		delay_ms(1000);
		LED0 = 0;
		LED1 = 1;
		delay_ms(1000);
	}
}

  在固件库 V3.5 中,系统在启动的时候会调用 system_stm32f10x.c 中的函数 SystemInit()对系统时钟进行初始化,完毕之后会调用 main()函数,所以我们不需要再在 main()函数中调用 SystemInit()函数。

 二、寄存器版本

1.启动文件修订

  将startup_stm32f10x_hd.s的 Reset_Handler 函数部分代码进行注释,因为寄存器版本没有用到SystemInit函数,引用的话可能会报错。

Reset_Handler   PROC
                EXPORT  Reset_Handler             [WEAK]
                IMPORT  __main
				;寄存器版本代码,因为没有用到SystemInit函数,所以注释掉以下代码为防止报错!
				;库函数版本代码,建议加上这里(外部必须实现SystemInit函数),以初始化stm32时钟等。
                ;IMPORT  SystemInit			
                ;LDR     R0, =SystemInit	
                ;BLX     R0                  
                LDR     R0, =__main
                BX      R0
                ENDP

2.新建一个led.h文件

#ifndef _LED_H
#define _LED_H
#include "sys.h"

#define LED0 PBout(5)  //DS0
#define LED1 PEout(5)  //DS1

void LED_Init(void);

#endif

3.新建一个led.c文件

#include "led.h"

void LED_Init(void)
{
	// RCC->APB2ENR寄存器的第3位置1,使能端口B、E时钟
	RCC->APB2ENR|=1<<3;
	RCC->APB2ENR|=1<<6;
	
	// GPIO->CRL寄存器的第20~23位清零,设置端口模式
	GPIOB->CRL&=0XFF0FFFFF;
	GPIOB->CRL|=0X00300000;
	GPIOB->ODR|=1<<5;
	
	GPIOE->CRL&=0XFF0FFFFF;
	GPIOE->CRL|=0X00300000;
	GPIOE->ODR|=1<<5;
}

  首先要将PORTB 和 PORTE 的时钟使能,再设置端口管脚模式。APB2ENR 是 APB2 总线上的外设时钟使能寄存器,通过将位3和位6设为1,即可使能PORTB和PORTE时钟。

 

  下步准备设置端口模式,由下图可以看出GPIO_Pin_5为CRL寄存器的20~23位,将该位清零设置为3。(推挽输出、50MHZ)

 

4.新建一个main.c文件

#include "sys.h"
#include "usart.h"
#include "delay.h"
#include "led.h"

int main(void)
{
	Stm32_Clock_Init(9); //系统时钟设置
	delay_init(72); //延时初始化
	LED_Init();
	while(1)
	{
	    LED0=1;
	    LED1=1;
		delay_ms(300);
		LED0=0;
		LED1=0;
		delay_ms(300);
		
	}
}

  这段main 函数先调用 Stm32_Clock_Init 函数,配置系统时钟为 9 倍频,也就是 8*9=72M(外部晶振是 8Mhz),然后调用 delay_init 函数,初始化延时函数。接着就是调用 LED_Init 来初始化 PE5 和 PB5 为输出。最后在死循环里面实现 LED0 和 LED1 交替闪烁,间隔为 300ms。

posted @ 2020-10-08 19:26  代码打碟手  阅读(683)  评论(0编辑  收藏  举报