你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32单片机 LED、蜂鸣器和数码管的操作

[复制链接]
STMCU小助手 发布时间:2022-4-8 22:56
在进行一款单片机学习时,最基本也是最简单的外设就是控制I/O口的高低电平。LED、蜂鸣器以及数码管这些都是可以作为外围电路连接在单片机的I/O口上,进而可以实现通过单片机对其进行控制。在本章节中,会以这三种外围电路的控制来学习stm32单片机中的外设资源—GPIO(General-purpose input/output)。

1、点亮LED灯
所使用的基于stm32f103zet6芯片的开发板中,关于LED外围电路的设计如下图中所示。从图中可以看出,只有当二极管(LED)的阴极电压为0V(低电平)时其会导通。因此通过单片机将相应接口的GPIO设置为低电平后,便能够控制LED灯亮,设置为高电平时,LED灯灭。

20210414223007730.png

1.1 寄存器方式
通过前一章节对寄存器开发方式的简单介绍后,在本小节中使用寄存器开发方式实现对LED灯的亮灭控制。下图是一个关于GPIO的结构图,通过对其了解可以知道GPIO可以被配置成输入、输出、复用功能以及模拟输入输出四种模式。其中输入模式又被细分为模拟(ADC采集)、上拉、下拉以及浮空(输入电平不确定,完全由外部的输入决定,按键电路)模式;输出模式被分为推挽(输出高低电平)和开漏模式(输出高阻态或低电平);复用功能也被分为推挽和开漏两种模式,但是输出信号源于其它外设,输入正常可用,但一般直接用外设的寄存器来获取该数据信号;模拟输入输出模式,上下拉无影响。
5V9N5)2_BTQHGWY9FOXKH(C.png

清楚了GPIO的模式配置后,下面通过寄存器来操作端口PC0输出一个低电平,进而使连接在其上的一颗LED灯亮起。最开始的模板准备工作在前一章节中已经详细描述,在此就不做过多赘述。
打开之前已经建立好了的寄存器开发模板,在main.c文件中编写的代码如下。

  1. #include "stm32f10x.h"                        //头文件中定义各种寄存器
  2. void SystemInit()                                //初始化
  3. {
  4.         
  5. }

  6. int main()                                                                //主函数
  7. {
  8.         RCC_APB2ENR |= 1<<4;                        //开启GPIOC挂载的总线APB2的时钟
  9.         GPIOC_CRL &= ~(0x0F<<(4*0));        //
  10.         GPIOC_CRL |= (3<<4*0);                        //配置GPIOC为通用推挽输出模式
  11.         GPIOC_BSRR = (1<<(16+0));                //配置PC0端口为低电平,LED亮
  12.         while(1);        
  13. }
复制代码

1.2 库函数方式
本小节应用库函数开发的方式来点亮一颗LED。重复上一章节中库函数工程模板的建立,对stm32的GPIO进行操作就需要将标准库中的stm32f10x_gpio.c和stm32f10x_cc.c文件添加到项目中,前者是关于GPIO操作的函数声明及模式选项配置的宏定义,后者是关于时钟的一些函数和宏定义。在这里采用模块化编程,也就是将led看做一个功能模块,在项目中新建led.c及led.h文件,最后在main.c文件中包含使用。具体的代码如下所示:

led.c

  1. #include "led.h"

  2. void LED_Init(void)
  3. {
  4.         GPIO_InitTypeDef GPIO_InitStructure;                                        //定义GPIO操作结构体变量
  5.         
  6.         RCC_APB2PeriphClockCmd(LED_PORT_RCC,ENABLE);        //开启时钟
  7.         
  8.         GPIO_InitStructure.GPIO_Pin = LED_PIN;                                        //设置led所在IO口
  9.         
  10.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                //设置为推挽输出模式
  11.         
  12.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                //设置传输速率
  13.         
  14.         GPIO_Init(LED_PORT, &GPIO_InitStructure);                                //初始化GPIO口
  15.         
  16.         GPIO_SetBits(LED_PORT, LED_PIN);                                                //将IO口设置为高电平,LED灭
  17.         
  18. }
复制代码

led.h

  1. #ifndef _led_H
  2. #define _led_H

  3. #include "stm32f10x.h"

  4. #define LED_PORT_RCC RCC_APB2Periph_GPIOC
  5. #define LED_PIN (GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7)
  6. #define LED_PORT  GPIOC

  7. void LED_Init(void);

  8. #endif
复制代码

main.c

  1. #include "stm32f10x.h"
  2. #include "led.h"
  3. int main()
  4. {
  5.         LED_Init();
  6.         while(1)
  7.         {
  8.                 GPIO_ResetBits(LED_PORT,GPIO_Pin_0);                        //翻转IO口电平
  9.         }
  10. }
复制代码

1.3 HAL库方式
打开在上一章节中已经建立好的STM32CubeMX项目,在芯片的图形化界面中找到PC0端口单击后将其设置为GPIO_Output模式;

HO23EU}]AUM${OY@7KP[9{T.png

在左侧的System Core菜单中选择RCC(时钟配置),将HSE和LSE设置为Crystal/ceramic Resonator模式,即外部晶振;

BQVY~[PB`46`P[CAP2BE~DP.png

将GPIO选项中的GPIO Mode and Configuration中的GPIO mode设置为Output Push Pull(推挽输出),User Label设置为LED(端口标签),其它的选项默认即可;

%)4_FJZ]`OI$)1G[DHV7%0Z.png

随后切换主菜单到Clock Configuration时钟配置,在HCLK下方的框中输入72,然后按下回车则系统的时钟就被配置到了72MHz,最后点击GENRATE CODE,即可生成代码;

6BUNEYLLTNS8{VY3AFP)96C.png

紧接着在keil5中打开自动生成的项目,如下图中所示。可以看出整个项目的构成与标准库开发的方式类似,只不过这里的代码都是自动生成的。其中gpio.c文件中的代码为GPIO初始化与上一节中的led.c中的函数功能是相同的,只不过这里是使用了HAL库函数。在需要注意的是如果需要在这些CubeMX软件自动生成的文件中编写自定义的代码,是需要将其写在下述这段注释之间的,XXX表示的是某一个模块,比如Init(初始化)、SystInit(系统时钟初始化)等等;
  1.   /* USER CODE BEGIN XXX*/
  2.         code
  3.   /* USER CODE END XXX */
复制代码

RU6B$]]98D}GZ9ZUTF_11XA.png

最后点亮一颗LED,只需要在main()函数中写下如下代码即可。
  1. {
  2.   /* USER CODE BEGIN 1 */

  3.   /* USER CODE END 1 */

  4.   /* MCU Configuration--------------------------------------------------------*/

  5.   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  6.   HAL_Init();

  7.   /* USER CODE BEGIN Init */

  8.   /* USER CODE END Init */

  9.   /* Configure the system clock */
  10.   SystemClock_Config();

  11.   /* USER CODE BEGIN SysInit */

  12.   /* USER CODE END SysInit */

  13.   /* Initialize all configured peripherals */
  14.   MX_GPIO_Init();
  15.   /* USER CODE BEGIN 2 */

  16.   /* USER CODE END 2 */

  17.   /* Infinite loop */
  18.   /* USER CODE BEGIN WHILE */
  19.   while (1)
  20.   {
  21.     /* USER CODE END WHILE */

  22.     /* USER CODE BEGIN 3 */
  23.         HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
  24.   }
  25.   /* USER CODE END 3 */
  26. }
复制代码

1.4 三种方式的总结与比较
经过了对LED的简单操作,可以发现在这三种方式中,寄存器开发方式最为复杂。其在编写程序前需要查找好所使用寄存器的地址等相关信息,出现了bug时很难精准的定位、开发周期长的缺点,因此寄存器开发常常不会被采用。标准库方式在其基础上简化了很多步骤,只需要通过调用相关外设的接口函数便可实现对应的功能,因此这一种方式也被广泛地应用到stm32单片机的开发中。HAL库开发方式由于CubeMX软件的存在,可以以图形化的方式对各种外设进行配置,大大方便了配置的步骤流程相比较于标准库来说还要更加便捷。

2、无源蜂鸣器的使用
蜂鸣器是一种可以发声的器件,无源蜂鸣器需要对其提供1.5~5KHz频率的脉冲信号,其才可以发出声音。蜂鸣器电路的设计如下图中所示,通过一个三极管将单片机IO口的电流放大后再驱动蜂鸣器,这一点是为了避免出现一个IO输出电流过大导致其它IO口的电流过小的情况。从电路图中可以看出,只需要控制PB5口输出一定频率的脉冲波蜂鸣器即可发声,详细的代码如下所示。

~R%_2K8(F(N)@7P%Z$C(FF7.png

beep.c

  1. #include "beep.h"

  2. void Beep_Init()
  3. {
  4.         GPIO_InitTypeDef GPIO_InitStructure;
  5.         
  6.         RCC_APB2PeriphClockCmd(BEEP_PORT_RCC,ENABLE);
  7.         
  8.         GPIO_InitStructure.GPIO_Pin=BEEP_PIN;
  9.         
  10.         GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
  11.         
  12.         GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
  13.         
  14.         GPIO_Init(BEEP_PORT,&GPIO_InitStructure);
  15. }
复制代码

beep.h

  1. #ifndef _beep_H
  2. #define _beep_H

  3. #include "system.h"

  4. #define BEEP_PORT_RCC RCC_APB2Periph_GPIOB

  5. #define BEEP_PIN GPIO_Pin_5

  6. #define BEEP_PORT GPIOB
  7. void Beep_Init(void);

  8. #define BEEP PBout(5)

  9. #endif
复制代码

main.c

  1. #include "system.h"
  2. #include "led.h"
  3. #include "SysTick.h"
  4. #include "beep.h"

  5. int main()
  6. {
  7.         u16 i=0;
  8.         SysTick_Init(72);
  9.         LED_Init();
  10.         Beep_Init();
  11.         
  12.         while(1)
  13.         {
  14.                 i++;
  15.                 if(i%10==0)
  16.                 {
  17.                         BEEP=!BEEP;
  18.                 }
  19.                 delay_us(10);
  20.         }
  21. }
复制代码

3、无源蜂鸣器的使用

数码管是一种发光器件,基本单元是发光二极管,本小节中用于数码管显示的单片机外围电路如下图中所示。数码管是一个8个LED组成的器件,因此要点亮数码管和LED方式相同,给相应的IO口一个低电平即可。此外,如果需要让数码管显示指定的数字,那么就需要同时点亮对应段的LED。比如需要显示数字“0”,则需要控制a,b,c,d,e,f段对应的PC0~5端口输出低电平即可。

(ALN``FG1OFEU5%E`(9AI.png

smg.c

  1. #include "smg.h"

  2. void SMG_Init()
  3. {
  4.         GPIO_InitTypeDef GPIO_InitStructure;
  5.         
  6.         RCC_APB2PeriphClockCmd(SMG_PORT_RCC,ENABLE);
  7.         
  8.         GPIO_InitStructure.GPIO_Pin=SMG_PIN;
  9.         
  10.         GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
  11.         
  12.         GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
  13.         
  14.         GPIO_Init(SMG_PORT,&GPIO_InitStructure);
  15.         
  16. }
复制代码

smg.h

  1. #ifndef _smg_H
  2. #define _smg_H

  3. #include "system.h"

  4. #define SMG_PORT_RCC                 RCC_APB2Periph_GPIOC

  5. #define SMG_PIN                                 (GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7)
  6.         
  7. #define SMG_PORT  GPIOC
  8. void SMG_Init(void);

  9. #endif
复制代码

main.c


  1. #include "system.h"
  2. #include "led.h"
  3. #include "SysTick.h"
  4. #include "smg.h"

  5. u8 smgduan[16]={0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07,
  6.              0x7F, 0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71};        //数码管显示0~F的编码

  7. int main()
  8. {
  9.         u8 i;
  10.         SysTick_Init(72);
  11.         LED_Init();
  12.         SMG_Init();
  13.         
  14.         while(1)
  15.         {
  16.                 for(i=0;i<16;i++)
  17.                 {
  18.                         GPIO_Write(SMG_PORT,~smgduan<i>);
  19.                         delay_ms(1000);
  20.                 }
  21.         }
  22. }


  23. </i>
复制代码


收藏 评论0 发布时间:2022-4-8 22:56

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版