【STM32学习笔记】(6)—— 跑马灯实验详解

这篇具有很好参考价值的文章主要介绍了【STM32学习笔记】(6)—— 跑马灯实验详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

跑马灯实验

        在前面五篇STM32学习笔记中,我们已经初步认识了STM32芯片,并且了解STM32的常用寄存器,介绍了STM32的GPIO模式,STM32工程文件,以及最终讲解了如何为STM32添加源文件和头文件的步骤。但是前面的知识只能说是理论和基础,但是非常重要,如果STM32的理论知识不扎实,会导致后续开发项目时,总感觉自己并没有学过STM32,就好像自己是一片浮萍一直飘在水上。所以我们在开发STM32的项目过程中,遇到需要学习一些理论知识时,一定要好好补充自己的理论知识,在实践中检验自己学习的效果是最好的。

GPIO简介

        GPIO 是通用输入输出端口的简称,简单来说就是 STM32 可控制的引脚,STM32 芯片的 GPIO 引 脚与外部设备连接起来,从而实现与外部通讯、控制以及数据采集的功能。STM32 芯片的 GPIO 被分成很多组,每组有 16 个引脚,如型号为 STM32F103ZET6 型号的芯片有 GPIOA、GPIOB、 GPIOC、GPIOD、GPIOE、GPIOF 至 GPIOG 共 7组 GPIO,芯片一共 144 个引脚,其中 GPIO 就占了一大部分,所有的 GPIO 引脚都有基本的输入输出功能。

        最基本的输出功能是由 STM32 控制引脚输出高、低电平,实现开关控制,如把 GPIO 引脚接入 到 LED 灯,那就可以控制 LED 灯的亮灭,引脚接入到继电器或三极管,那就可以通过继电器或 三极管控制外部大功率电路的通断。

        最基本的输入功能是检测外部输入电平,如把 GPIO 引脚连接到按键,通过电平高低区分按键是 否被按下。

        在固件库中,GPIO 端口操作对应的库函数函数以及相关定义在文件 stm32f10x_gpio.h 和 stm32f10x_gpio.c 中。

跑马灯硬件连接

 

【STM32学习笔记】(6)—— 跑马灯实验详解

 

        本章用到的硬件只有 LED(DS0 和 DS1)。其电路在 ALIENTEK 精英 STM32F103 开发板 上默认是已经连接好了的。DS0 接 PB5,DS1 接 PE5。所以在硬件上不需要动任何东西。因为LED发光二极管的阳极串联一个510欧姆的电阻与VCC3.3V电源相连。LED发光二极管的阴极与芯片的GPIO口相连。如果要控制发光二极管发光,则需要将GPIO输出的电平拉低,发光二极管就会由电流流过,电流流过时发光二极管就发光了。当两个GPIO输出的电平不断的拉高或者拉低就能实现了LED的闪烁或者跑马灯的效果了。 

       注意:510欧姆的电阻一共有两个作用:

  1. 起到上拉电阻的作用。
  2. 起到限流电阻的作用,防止流过发光二极管的电路过大而烧坏。

 

跑马灯程序设计

 

        跑马灯实验我们主要用到的固件库文件是:

        stm32f10x_gpio.c                             stm32f10x_gpio.h

        stm32f10x_rcc.c                                stm32f10x_rcc.h

        misc.c                                               misc.h

        stm32f10x_usart                               stm32f10x_usart.h

        其中 stm32f10x_rcc.h 头文件在每个实验中都要引入,因为系统时钟配置函数以及相关的外设时 钟使能函数都在这个其源文件 stm32f10x_rcc.c 中。stm32f10x_usart.h 和 misc.h 头文件在我们 SYSTEM 文件夹中都需要使用到,所以每个实验都会引用。

 

跑马灯所要用到的库函数

1、一个GPIO初始化函数

void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
   /*作用:初始化一个或者多个IO口(同一组)的工作模式,输出类型,速度以及上下拉方式。也就是一组IO            
     口的4个配置寄存器。
   */
typedef struct
{
      uint16_t GPIO_Pin;  
    //指定要配置的 GPIO 引脚。此参数可以是 @ref GPIO_pins_define的任何值          
      GPIOSpeed_TypeDef GPIO_Speed;	
    //指定所选引脚的速度。此参数可以是ref GPIOSpeed_TypeDef成员变量中的值
      GPIOMode_TypeDef GPIO_Mode;  
    //指定选定引脚的工作模式。此参数可以是 GPIOMode_TypeDef成员变量中的值  
}GPIO_InitTypeDef;

#define GPIO_Pin_0                ((uint16_t)0x0001)  /*!< Pin 0 selected */
#define GPIO_Pin_1                ((uint16_t)0x0002)  /*!< Pin 1 selected */
#define GPIO_Pin_2                ((uint16_t)0x0004)  /*!< Pin 2 selected */
#define GPIO_Pin_3                ((uint16_t)0x0008)  /*!< Pin 3 selected */
#define GPIO_Pin_4                ((uint16_t)0x0010)  /*!< Pin 4 selected */
#define GPIO_Pin_5                ((uint16_t)0x0020)  /*!< Pin 5 selected */
#define GPIO_Pin_6                ((uint16_t)0x0040)  /*!< Pin 6 selected */
#define GPIO_Pin_7                ((uint16_t)0x0080)  /*!< Pin 7 selected */
#define GPIO_Pin_8                ((uint16_t)0x0100)  /*!< Pin 8 selected */
#define GPIO_Pin_9                ((uint16_t)0x0200)  /*!< Pin 9 selected */
#define GPIO_Pin_10               ((uint16_t)0x0400)  /*!< Pin 10 selected */
#define GPIO_Pin_11               ((uint16_t)0x0800)  /*!< Pin 11 selected */
#define GPIO_Pin_12               ((uint16_t)0x1000)  /*!< Pin 12 selected */
#define GPIO_Pin_13               ((uint16_t)0x2000)  /*!< Pin 13 selected */
#define GPIO_Pin_14               ((uint16_t)0x4000)  /*!< Pin 14 selected */
#define GPIO_Pin_15               ((uint16_t)0x8000)  /*!< Pin 15 selected */
#define GPIO_Pin_All              ((uint16_t)0xFFFF)  /*!< All pins selected */

#define IS_GPIO_PIN(PIN)         ((((PIN) & (uint16_t)0x00) == 0x00) && ((PIN) != (uint16_t)0x00))

#define IS_GET_GPIO_PIN(PIN) (((PIN) == GPIO_Pin_0) || \
                              ((PIN) == GPIO_Pin_1) || \
                              ((PIN) == GPIO_Pin_2) || \
                              ((PIN) == GPIO_Pin_3) || \
                              ((PIN) == GPIO_Pin_4) || \
                              ((PIN) == GPIO_Pin_5) || \
                              ((PIN) == GPIO_Pin_6) || \
                              ((PIN) == GPIO_Pin_7) || \
                              ((PIN) == GPIO_Pin_8) || \
                              ((PIN) == GPIO_Pin_9) || \
                              ((PIN) == GPIO_Pin_10) || \
                              ((PIN) == GPIO_Pin_11) || \
                              ((PIN) == GPIO_Pin_12) || \
                              ((PIN) == GPIO_Pin_13) || \
                              ((PIN) == GPIO_Pin_14) || \
                              ((PIN) == GPIO_Pin_15))

 

        在GPIO_InitTypeDef结构体中已经初始化了成员变量,所以在调用这个初始化函数的时候,我们首先需要对GPIO_InitTypeDef成员变量进行赋值。

       但是在给GPIO_InitTypeDef的成员变量赋值时,赋值的内容需要满足对应结构体类型中的成员变量。

       例如:GPIO_Mode的结构类型为GPIOMode_TypeDef,那么给它赋值的内容需要在下面这个结构体当中的成员变量中选择

 

typedef enum
{ 
  GPIO_Mode_AIN = 0x0,
  GPIO_Mode_IN_FLOATING = 0x04,
  GPIO_Mode_IPD = 0x28,
  GPIO_Mode_IPU = 0x48,
  GPIO_Mode_Out_OD = 0x14,
  GPIO_Mode_Out_PP = 0x10,
  GPIO_Mode_AF_OD = 0x1C,
  GPIO_Mode_AF_PP = 0x18
}GPIOMode_TypeDef;

#define IS_GPIO_MODE(MODE) 		(((MODE) == GPIO_Mode_AIN) || ((MODE) == GPIO_Mode_IN_FLOATING) || \
                           		((MODE) == GPIO_Mode_IPD) || ((MODE) == GPIO_Mode_IPU) || \
                            	((MODE) == GPIO_Mode_Out_OD) || ((MODE) == GPIO_Mode_Out_PP) || \
                            	((MODE) == GPIO_Mode_AF_OD) || ((MODE) == GPIO_Mode_AF_PP))

 

        GPIO_Speed的结构类型为GPIOSpeed_TypeDef,那么给它赋值的内容需要在下面这个结构体当中的成员变量中选择。

 

typedef enum
{ 
  GPIO_Speed_10MHz = 1,
  GPIO_Speed_2MHz, 
  GPIO_Speed_50MHz
}GPIOSpeed_TypeDef;

#define IS_GPIO_SPEED(SPEED) (((SPEED) == GPIO_Speed_10MHz) || ((SPEED) == GPIO_Speed_2MHz) || \
                              ((SPEED) == GPIO_Speed_50MHz))

 

2、两个读取输入电平函数 

uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

作用:读取某个GPIO的输入电平。实际操作的是GPIOx_IDR寄存器。

参数:1、GPIOx:其中x可以是(A..G)以选择GPIO外围设备。

           2、GPIO_Pin:指定要读取的端口位。

返回值:输入端口引脚值。

例如:

      GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_5);//读取GPIOA.5的输入电平

uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);

作用:读取某组GPIO的输入电平。实际操作的是GPIOx_IDR寄存器。

参数:GPIOx:其中x可以是(A..G)以选择GPIO外围设备。

返回值:GPIO输入数据端口值。

例如:

     GPIO_ReadOutputData(GPIOA);//读取GPIOA组中所有io口输出电平

3、两个读取输出电平函数

uint8_t GPIO_ReadOutputDataBit (GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

作用:读取某个GPIO的输出电平。实际操作的是GPIO_ODR寄存器。

参数:1、GPIOx:其中x可以是(A..G)以选择GPIO外围设备。

           2、GPIO_Pin:指定要读取的端口位。

返回值:输出端口引脚值。

例如:

      GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_5);//读取GPIOA.5的输出电平

uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);

作用:读取某组GPIO的输出电平。实际操作的是GPIO_ODR寄存器。

参数:GPIOx:其中x可以是(A..G)以选择GPIO外围设备。

返回值:GPIO输入数据端口值。

例如:

             GPIO_ReadOutputData(GPIOA);//读取GPIOA组中所有io口输出电平

4、四个设置输出电平函数

void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

作用:设置某个IO口输出为高电平(1)。实际操作BSRRL寄存器

参数:1、GPIOx:其中x可以是(A..G)以选择GPIO外围设备。

           2、GPIO_Pin:指定要写入的端口位。

返回值:无

例如:

        GPIO_SetBits(GPIOA, GPIO_Pin_5);//将GPIOA.5的输出电平置为高电平

void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

作用:设置某个IO口输出为低电平(0)。实际操作的BSRRH寄存器。

参数:1、GPIOx:其中x可以是(A..G)以选择GPIO外围设备。

           2、GPIO_Pin:指定要写入的端口位

返回值:无

例如:

        GPIO_ResetBits (GPIOA, GPIO_Pin_5);//将GPIOA.5的输出电平置为低电平

void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);

作用:设置或清除选定的数据端口位。

参数:1、GPIOx:其中x可以是(A..G)以选择GPIO外围设备。

           2、GPIO_Pin:指定要写入的端口位。

           3、BitVal:指定要写入选定位的值。

此参数可以是BitAction枚举值之一:

typedef enum

{

          Bit_RESET = 0,    // Bit_RESET:清除端口引脚

          Bit_SET     // Bit_SET:设置端口引脚

}BitAction;

#define IS_GPIO_BIT_ACTION(ACTION)                                                                                                                                                 (((ACTION) == Bit_RESET) || ((ACTION) == Bit_SET))

返回值:无

例如:

        GPIO_WriteBit(GPIOA, GPIO_Pin_5, Bit_RESET);// 清除GPIOA.5数据端口位。

void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);

作用:将数据写入指定的GPIO数据端口。

参数:1、GPIOx:其中x可以是(A..G)以选择GPIO外围设备。

            2、PortVal:指定要写入端口输出数据寄存器的值。。

返回值:无

例如:

        GPIO_Write(GPIOA,1);将数据“1”写入指定的GPIOA数据端口。

        后面两个函数不常用,也是用来设置IO口输出电平。

跑马灯实验编写步骤:

      1. 使能IO口时钟。调用函数RCC_AHB1PeriphClockCmd();

           不同的外设调用的时钟使能函数可能不一样

      2. 初始化 GPIO 口模式。调用GPIO_Init();把目标引脚为推挽输出模式;

      3. 编写简单测试程序,控制 GPIO 引脚输出高、低电平。

跑马灯源文件和头文件中的代码

头文件中的代码:

#ifndef __LED_H
#define __LED_H

void LED_Init(void);//初始化
		    
#endif

 

源文件中的代码:

#include "led.h"

//初始化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;	 //IO口速度为50MHz
 GPIO_Init(GPIOB, &GPIO_InitStructure);	 //根据设定参数初始化GPIOB.5
 GPIO_SetBits(GPIOB,GPIO_Pin_5);	 //PB.5 输出高
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;	 //LED1-->PE.5 端口配置, 推挽输出
 GPIO_Init(GPIOE, &GPIO_InitStructure);	 //推挽输出 ,IO口速度为50MHz
 GPIO_SetBits(GPIOE,GPIO_Pin_5); 	 //PE.5 输出高 
}

 

跑马灯实验中主函数里的代码

        main.c里的代码:

#include "delay.h"
#include "led.h"	
/**
 *****************下面注视的代码是通过调用库函数来实现IO控制的方法*****************************************
int main(void)
{ 
 
delay_init();      //初始化延时函数
LED_Init();       //初始化LED端口
while(1)
{
GPIO_ResetBits(GPIOB,GPIO_Pin_5);  //LED0对应引脚GPIOB.5拉低,亮  
GPIO_SetBits(GPIOE,GPIO_Pin_5);   //LED1对应引脚GPIOE.5拉高,灭 
delay_ms(300);       //延时300ms
GPIO_SetBits(GPIOB,GPIO_Pin_5);	   //LED0对应引脚GPIOB.5拉高,灭 GPIO_ResetBits(GPIOE,GPIO_Pin_5); //LED1对应引脚GPIOE.5拉低,亮 
delay_ms(300);                     //延时300ms
	}
} 

 

函数执行流程如下:

        (1) 使用 GPIO_InitTypeDef 定义 GPIO 初始化结构体变量,以便下面用于存储 GPIO 配置。

        (2) 调用库函数 RCC_APB2PeriphClockCmd 来使能 LED 灯的 GPIO 端口时钟,这个函数的调用和详细资料会在后面的一篇文章讲解。

        (3) 向 GPIO 初始化结构体赋值,把引脚初始化成推挽输出模式。

        (4) 使用以上初始化结构体的配置,调用 GPIO_Init 函数向寄存器写入参数,完成 GPIO 的初始化。

      (5)紧接着使用两个GPIO的库函数,分别为GPIO_SetBits()与GPIO_ResetBits(),在置低和置高之间延时一段时间,就实现了两个LED灯轮流转的实验目的。文章来源地址https://www.toymoban.com/news/detail-403253.html

到了这里,关于【STM32学习笔记】(6)—— 跑马灯实验详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32F407ZGT6正点原子F4探索者开发板 -- 跑马灯例程

    LED0 - PF9 LED1 - PF10 PF9 = 0, LED0 亮,PF9 = 1,LED0 灭 PF10 = 0, LED1 亮,PF10 = 1,LED1 灭

    2024年02月15日
    浏览(56)
  • 跑马灯实验

             1.熟悉龙芯实验开发板、熟悉 VIVADO 的编译环境及操作流程。         2.掌握 FPGA 编程入门知识、利用门级方法实现简单逻辑电路。         3.继续学习 Verilog HDL 语法、掌握跑马灯的设计、熟悉调试过程。          本次实验用 Verilog HDL 语言来描述 6 个不

    2024年02月04日
    浏览(44)
  • 20230705点亮STC32G实验箱9.6(STC32G12K128)开发板的跑马灯LED(深入了解)

    08第六集:LED闪烁第六集:LED闪烁和花式点灯上和花式点灯上.mp4 09第六集:LED闪烁和花式点灯下.mp4 【大文哥学习32位8051】20230704【冲哥视频】第六集的晶振时钟的学习困惑 2023/7/5 17:36 delay_ms(3000); 刷机的时候如果使用11.0592M的Fosc,3秒钟的延迟大概7秒钟。 刷机的时候如果使用

    2024年02月12日
    浏览(48)
  • 单片机(3)跑马灯,按钮控制的跑马灯(2种编程)

     先上电路图(图示的是高电平点亮的跑马灯)  这个是程序截图(keil5):我的建议是是先自己打一遍,边打边试着理解程序的意思。 下面的是没有注释的代码 下一个是另外一种编程思路  

    2024年02月11日
    浏览(38)
  • 3.跑马灯

    推挽模式输出:因为LED0和LED1阳极都是3.3V,需要将阴极设置为低电平才可以点亮LED; 操作io口时,必须引入源文件和头文件; 关于时钟的文件存放在rcc中; void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct); 作用:初始化一个或多个io口(同一组)的工作方式和速度, 该函数

    2024年02月10日
    浏览(43)
  • Android --- 跑马灯效果

    跑马灯效果主要使用的控件为TextView,其中涉及的几个标签如下所示: android:ellipsize If set, causes words that are longer than the view is wide to be ellipsized instead of broken in the middle. You will often also want to set scrollHorizontally or singleLine as well so that the text as a whole is also constrained to a single line in

    2023年04月08日
    浏览(77)
  • Android 实现跑马灯效果

    Android中实现跑马灯效果有多种方式,本篇简单介绍下: 1: TextView属性实现 这里需要注意下: 需要限制textview的宽度,不能设置为wrap_content 启动跑马灯效果需要获取焦点requestFocus(). 2: 代码实现 3: 自定义 view实现 这里可以使用动画的效果实现. 4: 实现竖直效果的跑马灯

    2024年01月18日
    浏览(58)
  • CSS按钮-跑马灯边框

    思路很简单,实现方法有很多很多。但是大体思路与实现方法都类似:渐变色 + 动画,主要区别在动画的具体实现

    2024年02月11日
    浏览(47)
  • CSS 之 跑马灯边框

    一、简介 ​ 之前有做过渐变色边框的样式,然后某天刷抖🎵,看到某个老师在讲跑马灯的样式效果,于是就自己尝试实现一下跑马灯样式的边框,虽然这种样式并不常见(基本没卵用),其使用场景我至今没想到,但是它足够花里胡哨,玩的就是花活。CSS才是前端最难精通

    2024年01月17日
    浏览(41)
  • 从零开始学习vivado——day4 跑马灯(让8个LED灯以每个0.5s的速率循环闪烁)

    研一从零开始学习verilog!!!此时不学何时学! 第一次写博客,以此激励自己努力学习! 我跟的视频教程是b站的一个up主,小梅哥爱漂流。 ①编写端口代码: ②计数器 其中,一定是=,如果直接用=,则波形图会出现错误,从00000010到00000100的时间会非常短,导致整个图像看

    2024年02月02日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包