当前位置:文档之家› 嵌入式系统原理实验三跑马灯

嵌入式系统原理实验三跑马灯

实验三跑马灯实验实验目的:通过一个经典的跑马灯程序,了解STM32F1 的IO 口作为输出使用的方法。

通过代码控制ALIENTEK 战舰STM32 开发板上的两个LED:DS0 和DS1 交替闪烁,实现类似跑马灯的效果内容要点:1.硬件设计本章用到的硬件只有LED(DS0 和DS1)。

其电路在ALIENTEK 战舰STM32F103开发板上默认是已经连接好了的。

DS0 接PB5,DS1 接PE5。

所以在硬件上不需要动任何东西。

其连接原理图如图:2.软件设计跑马灯实验我们主要用到的固件库文件是:stm32f10x_gpio.c /stm32f10x_gpio.hstm32f10x_rcc.c/stm32f10x_rcc.hmisc.c/ misc.hstm32f10x_usart /stm32f10x_usart.h其中stm32f10x_rcc.h 头文件在每个实验中都要引入,因为系统时钟配置函数以及相关的外设时钟使能函数都在这个其源文件stm32f10x_rcc.c 中。

stm32f10x_usart.h 和misc.h 头文件在我们SYSTEM 文件夹中都需要使用到,所以每个实验都会引用。

首先,找到之前新建的Template 工程,在该文件夹下面新建一个HARDWARE的文件夹,用来存储以后与硬件相关的代码,然后在HARDWARE 文件夹下新建一个LED 文件夹,用来存放与LED 相关的代码。

新建led.h和led.c文件,一个外设对应一个.h和.c文件。

在Manage Components 管理里面新建一个HARDWARE 的组,并把led.c 加入到这个组里面,将led.h 头文件的路径加入到工程里面一般的头文件有固定的格式,多个地方调用头文件会重复引用,为了避免头文件内容重复引用,一般通过预编译的方式来写头文件。

一般的格式如下:#ifndef __LED_H#define __LED_H……#endif第一次调用时会将#define下面这一节全部定义,重复调用时,下面的东西就不会被引用。

头文件里一般用来写函数声明或者宏定义,在源文件中再去定义具体的函数。

#ifndef __LED_H#define __LED_Hvoid LED_Init(void);#endif然后我们打开USER 文件夹下的LED.uvprojx 工程(如果是使用的上面新建的工程模板,那么就是Template. uvprojx,大家可以将其重命名为LED. uvprojx),按新建按钮新建一个文件,然后保存在HARDWARE->LED 文件夹下面,保存为led.c。

在该文件中输入如下代码:#include "led.h"#include "stm32f10x.h"//引用顶层头文件,否则RCC_APB2PeriphClockCmd()函数不可见//初始化PB5 和PE5 为输出口.并使能这两个口的时钟//LED IO 初始化void LED_Init(void){GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE); //使能PB,PE 端口时钟GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED0-->PB.5 推挽输出GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_SetBits(GPIOB,GPIO_Pin_5);//输出PB5为高电平GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED0-->PB.5 推挽输出GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOE, &GPIO_InitStructure);GPIO_SetBits(GPIOE,GPIO_Pin_5); //PE5 输出高}该代码里面就包含了一个函数void LED_Init(void),该函数的功能就是用来实现配置PB5和PE5 为推挽输出。

这里需要注意的是:在配置STM32 外设的时候,任何时候都要先使能该外设的时钟。

GPIO 是挂载在APB2 总线上的外设,在固件库中对挂载在APB2 总线上的外设时钟使能是通过函数RCC_APB2PeriphClockCmd()来实现的。

代码如下:RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);这两行代码的作用是使能APB2 总线上的GPIOB 和GPIOE 的时钟。

或者可以写成RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE,ENABLE);在配置完时钟之后,LED_Init 配置了GPIOB.5 和GPIOE.5 的模式为推挽输出,并且默认输出1。

这样就完成了对这两个IO 口的初始化。

函数代码是:GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED0-->GPIOB.5 端口配置GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO 口速度为50MHzGPIO_Init(GPIOB, &GPIO_InitStructure); //初始化GPIOB.5GPIO_SetBits(GPIOB,GPIO_Pin_5); //GPIOB.5 输出高GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED1-->GPIOE.5 推挽输出GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO 口速度为50MHzGPIO_Init(GPIOE, &GPIO_InitStructure); //初始化GPIOE.5GPIO_SetBits(GPIOE,GPIO_Pin_5); //GPIOE.5 输出高在GPIOE.5 的初始化的时候就不需要再重复最后一行代码:GPIO_SetBits(GPIOE,GPIO_Pin_5);的作用是在初始化中将GPIOE.5 输出设置为高。

保存led.c 代码,这样LED_Init()函数就编写完成了。

接下来,开始写main.c文件首先,我们要用到GPIO相关的函数来操作I/O口,所以要先包含顶层的头文件#include "stm32f10x.h"其次要将led.h文件包含进来#include "led.h"之后就可以在main函数中调用LED_Init( )函数了。

#include "stm32f10x.h"#include "led.h"int main(void){LED_Init( ); //初始化与LED 连接的硬件接口while(1){ }}接下来就可以设置I/O口的电平了。

首先while(1){GPIO_SetBits(GPIOB,GPIO_Pin_5);GPIO_SetBits(GPIOE,GPIO_Pin_5);GPIO_ResetBits(GPIOB,GPIO_Pin_5);GPIO_ResetBits(GPIOE,GPIO_Pin_5);}如果不延时的话,我们是看不到效果的,所以我们调用一个延时delay_init();在调用之前要引用头文件#include "delay.h"#include "stm32f10x.h"#include "led.h"#include "delay.h"int main(void){delay_init();LED_Init( );while(1){GPIO_SetBits(GPIOB,GPIO_Pin_5);GPIO_SetBits(GPIOE,GPIO_Pin_5);delay_ms(500);GPIO_ResetBits(GPIOB,GPIO_Pin_5);GPIO_ResetBits(GPIOE,GPIO_Pin_5);delay_ms(500);}}实验现象:LED灯同时亮灭,中间间隔500毫秒。

能否让LED灯出现跑马灯现象,即一个亮的同时另一个灭?。

相关主题