STM32入门_江协科技_5~6_OB记录的自学笔记_GPIO输出_LED流水灯_蜂鸣器

news2024/12/23 14:17:42

5. GPIO 输出

5.1. GPIO简介

  • GPIO(General Purpose Input Output)通用输入输出口
  • 可配置为8种输入输出模式
  • 引脚电平:0V~3.3V,部分引脚可容忍5V(端口输入5V的电压,之前引脚定义表格中带FT标识的)
  • 输出模式下可控制端口输出高低电平,用以驱动LED、控制蜂鸣器、模拟通信协议输出时序等
  • 输入模式下可读取端口的高低电平或电压,用于读取按键输入、外接模块电平信号输入、ADC电压采集、模拟通信协议接收数据等

5.2. GPIO基本结构

在这里插入图片描述

  • 所有GPIO挂载在APB2外设总线上面
  • GPIO外设命名GPIOA,GPIOB…,引脚对应PA0,PA1…PA15,PB0,PB1…PB15
  • GPIO模块内包含寄存器和驱动器,寄存器是特殊的存储器,STM32内核可以通过APB2总线对寄存器进行读写以完成输出和输入电平的功能;
  • 寄存器的每一位对应一个引脚,输出寄存器写1为输出高电平,写0为输出低电平,输入寄存器高电平读1,低电平读0;
  • STM32为32位,内部寄存器也为32位,但是GPIO端口只有16位,所以寄存器只有低16位对应有端口,高16位没有用到;
  • 驱动器负责增大驱动能力,如需要GPIO点灯;

5.3. GPIO位结构

在这里插入图片描述

  1. 如上图所示,右侧IO引脚旁边的VDD与VSS所接保护二极管,如果IO引脚电压大于3.3V,VDD保护二极管导通,电流不进入芯片内部,如果IO引脚电压小于0V,VSS保护二极管导通,此处电流从IO引脚导出,不必从芯片内部汲取电流;
  2. 虚线框内的VDD加开关和电阻组成上拉电阻,VSS加开关和电阻组成下拉电阻,开关的通断通过程序配置,如果上开关导通,下开关断开,为上拉输入模式,反之为下拉输入模式,如果两个开关都断开,则为浮空输入模式;
  3. 上拉和下拉的作用:给输入提供一个默认的电平,对于一个数字端口,输入不是低电平0就是高电平1,如果处于浮空模式,实际情况是引脚的输入电平易受到外界的干扰而变化,为避免出现这种情况,有必要在输入端口加入上拉和下拉电阻,例如,如果接入上拉电阻成为上拉输入模式,即使引脚悬空,也有上拉电阻保证引脚的高电平,所以上拉输入又称作为高电平的输入模式,同理,下拉为低电平输入模式;
  4. TTL肖特基触发器用于对输入的电压进行整形,如果输入电压大于某个阈值,则触发器瞬间输出高电平,反之输入电压小于某个阈值,则触发器瞬间输出低电平,防止输入的电平信号因为干扰失真而导致的信号误判;
  5. 经过触发器整形的信号直接写入输入数据寄存器;
  6. 输入部分至片上外设有2路,其中模拟输入一路是需要输送至ADC进行信号转换,所以从触发器前接入,另一路复用功能输入连接到其他需要读取端口的外设上,如串口的输入输入引脚等,因为这路是数字量,所以接触发器后端;
  7. 输出部分:输出数据寄存器直接控制16位端口,如果只是需要对其中某一位端口进行控制而不影响其他端口的话,则需要借助位设置清除寄存器来完成,在位设置寄存器对应位直接写1就可以使某一位输出置1;(另一种方式是先读出输出数据寄存器,然后用按位与和按位或的方式更改某一位,最后将更改后的数据写回去,此方法麻烦,效率低,对于IO口操作不太合适)
  8. 输出控制后接的两个MOS管可以想象为2个开关,我们通过信号来控制开关的导通与关闭;
  9. 此处MOS管输出有3种模式,推挽,开漏和关闭
  10. 推挽输出模式下,P-MOS与N-MOS均有效,数据寄存器为1时,P-MOS导通,N-MOS断开,输出直接接到VDD,输出高电平,反之数据寄存器为0时,N-MOS导通,P-MOS断开,输出直接接到VSS,输出低电平,这种模式下高地电平均有较强的驱动能力,所以推挽输出模式也叫强推输出模式;
  11. 在推挽输出模式下,STM32对IO口拥有绝对控制权,高低电平均由STM32说的算。
  12. 在开漏输出模式下,P-MOS是无效的,只有N-MOS工作,数据寄存器为1时,下管断开,输出相当于断开,输出处于高阻模式,数据寄存器为0时,下管导通,输出直接接到VSS,输出低电平,这种模式下只有低电平有驱动能力,高电平没有驱动能力,开漏模式用于通信协议的驱动方式,如I2C通信引脚就是用开漏模式,在多机通信的情况下,这个模式可以避免各个设备的相互干扰,同时开漏模式还可以用于输出5V的电平信号(需要I/O引脚接5V上拉电阻)。
  13. 当I/O引脚配置为输入模式的时候,两个MOS管均无效,也就是输出关闭,端口的电平由外部信号来控制,MOS管处于关闭工作模式;

5.4. GPIO模式

在这里插入图片描述

  • 浮空输入,上拉输入,下拉输入三种模式的电路基本相同,区别是上拉电阻和下拉电阻的连接,都属于数字输入口,都可以读取端口的电平高低,当引脚悬空时,上拉输入默认高电平,下拉输入默认低电平,浮空输入的电平不确定,在使用浮空输入时,端口一定要接连续的驱动源,不能有悬空的状态。
  • 浮空/上拉/下拉输入的电路结构:
    在这里插入图片描述
- 如上图所示:浮空/上拉/下拉输入模式下,输出驱动器是断开的,端口只能输入,通过开关的关闭状况选择浮空/上拉/下拉输入模式,信号通过触发器整形输入到数据寄存器。同时注意注释中VDD_FT对5V容忍I/O脚是特殊的,具体特殊情况手册中未描述,笔者猜测是保护二极管的不同;
- 模拟输入的电路结构:

在这里插入图片描述

- 从上图模拟输入的电路图可以看出,模拟输入下,输出驱动器断开,输入触发器断开,信号直接进入ADC。
- 开漏输出/推挽输出的电路结构:

在这里插入图片描述

- 如上图可见:开漏输出/推挽输出的电路结构基本相同,区别是开漏输出高电平为高阻态,没有驱动能力,推挽输出高电平接VDD,有驱动能力。输出由输出数据寄存器控制,P-MOS如果无效就是开漏输出,P-MOS / N-MOS都有效则是推挽输出,同时注意在输出模式下,输入也是有效的,但在输入模式下,输出无效,因为一个端口只能有一个输出,但可以有多个输入;
- 复用开漏/推挽输出的电路结构图:

在这里插入图片描述

- 如上图可见:和普通的开漏输出与推挽输出差不多,区别在于复用的输出,引脚电平由片上外设控制,同时注意这8个模式中,处模拟输入外,其他7个模式输入都有效;

5.5. LED和蜂鸣器介绍

•LED:发光二极管,正向通电点亮,反向通电不亮;
•有源蜂鸣器:内部自带振荡源,将正负极接上直流电压即可持续发声,频率固定,低电平触发;
•无源蜂鸣器:内部不带振荡源,需要控制器提供振荡脉冲才可发声,调整提供振荡脉冲的频率,可发出不同频率的声音;

在这里插入图片描述

5.6. LED和蜂鸣器的硬件电路

  • 在这里插入图片描述

  • 左边两个图LED驱动电路,左上图为低电平驱动模式,低电平LED点亮,高电平LED灭,左下图为高电平驱动模式,STM32推挽输出模式可以驱动LED,高电平LED亮,低电平LED灭;
  • 右侧蜂鸣器电路,接三极管驱动蜂鸣器,避免STM32直驱蜂鸣器导致芯片负担过重,右上图PNP三极管,IO口低电平三极管导通,3.3V电压开始驱动蜂鸣器,右下图为NPN三极管,IO口高电平导通,此时蜂鸣器电路产生电流,蜂鸣器工作;

5.7. 面包板介绍和面包板结构

  • 在这里插入图片描述

  • 上图中下面的图是面包板背面撕去双面胶后的情况,可见上下横向标识红蓝线的小孔横向导通(用于供电),中间纵向小孔,5个一组导通,右侧是拆出内部夹片后与LED连接的示意图;

6.LED闪烁&LED流水灯&蜂鸣器

6.1. LED灯闪烁的面包板电路:

在这里插入图片描述

  • 此为低电平点亮的操作方式,为方便,没有加限流电阻;
    在这里插入图片描述

  • 上图为笔者实际搭建的电路视频教程截图,至此硬件电路搭建完成;

6.2. Keil中新建项目 < 3-1 LED闪烁 >

  1. 在项目文件夹下面新建< User > < Library > < Start >三个文件夹,文件夹内需要复制文件参考3~4节中的操作,后续新建项目可能直接复制现有项目,加快项目新建过程;

  2. 相应文件拷贝到项目文件夹后,点击Keil中如下图标,删除原默认的< Group >组,
    在这里插入图片描述

  3. 新建Start, Library, 和User三个组,
    在这里插入图片描述

  4. Start中添加文件如下图:
    在这里插入图片描述

  5. 同理Library中添加所有的Library文件夹中的文件:
    在这里插入图片描述

  6. 同理将User文件夹中的文件添加进去:
    在这里插入图片描述

  7. 如下图将C语言搜索路径添加进项目选项中:
    在这里插入图片描述

  8. 如下图在Define中添加如下字符串:USE_STDPERIPH_DRIVER (使用标准外设驱动)
    在这里插入图片描述

  9. 如下图在debug中选择ST-Link Debugger,在设置中的Flash Download中勾选Reset and Run;至此工程选项配置完成
    在这里插入图片描述

  10. 如下图,打开User中的main函数文件,全部清空后如图添加头文件和main函数并编译测试没有错误和警告:
    在这里插入图片描述

  11. 如下图将笔者源码文件包中的< 1-2 KeilKill批处理 >文件夹复制到项目目录中,将文件夹下面的KeilKill.exe文件复制到项目文件夹中,该程序的主要作用是清楚工程编译过程中的中间文件,双击运行后会删除不必要的文件用以缩减项目文件的容量;
    在这里插入图片描述

6.3. 开始编程前

  1. 操作STM32的GPIO需要3个步骤:第一步,使用RCC开启GPIO的时钟;第二步,使用GPIO_Init函数初始化GPIO;第三步,使用输入或者输出的函数控制GPIO口,以上总共涉及RCC和GPIO两个外设;

  2. 在Library文件夹中找到stm32f10x_rcc.h文件并打开,在文件末尾位置可以看到很多库函数声明,常用的是如下的三个函数,AHB,APB1,APB2的外设时钟控制,右键函数可以打开相应的函数体做进一步的查看:

    void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState);
    void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);
    void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);

  3. 在Library文件夹中找到stm32f10x_gpio.h的文件并转到文件末尾,可以找到所有GPIO的库函数;

  4. 其中比较重要的是如下的函数,Init初始化函数和4个读取,4个写入函数
    void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
    uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
    uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);
    uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
    uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);
    void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
    void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
    void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);
    void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);

6.4. 开始编程

  1. 因为LED接在A0引脚,对应APB2外设时钟需要初始化;
  2. 将 RCC_APB2PeriphClockCmd 复制到main函数中,右键打开函数定义如下:
  3. 对应函数的参数需要选择如下:

在这里插入图片描述

  1. 接着需要调用< GPIO_Init >函数,跳转该函数的定义,第一个参数为GPIOA,第二个参数为结构体指针< GPIO_InitTypeDef >,在main函数最前端声明结构体如下< GPIO_InitTypeDef GPIO_InitStructure; >, 同时接着下面插入结构体的名字并将结构体的成员引出:
    GPIO_InitStructure.GPIO_Mode =
    GPIO_InitStructure.GPIO_Pin =
    GPIO_InitStructure.GPIO_Speed =
  2. 如下图,右键GPIO_Mode打开GPIO_Mode定义,然后找到注释中的 “ GPIOMode_TypeDef ” 选中并Ctrl+F搜索 “ GPIOMode_TypeDef ”(右键跳转->查看说明->复制粘贴参数)

在这里插入图片描述


	 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(复用推挽)
  1. 介绍GPIO的输出函数如下:
    void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);(指定端口设置高电平)
    void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);(指定端口设置低电平)
    void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);(根据BitVal的值来设置端口)
    void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);(同时对16个端口进行写入操作)
  2. 首先用GPIO_ResetBits程序来点亮LED,程序如下:
#include "stm32f10x.h"                  // Device header


int main(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	GPIO_ResetBits(GPIOA, GPIO_Pin_0);
	
	while(1)
	{
		
	}
}

Proteus中模拟测试没问题:

在这里插入图片描述

  1. 测试GPIO_SetBits函数,参数同GPIO_ResetBits,此时LED灯应熄灭,程序如下:
#include "stm32f10x.h"                  // Device header


int main(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	//GPIO_ResetBits(GPIOA, GPIO_Pin_0);
	GPIO_SetBits(GPIOA,GPIO_Pin_0);
	while(1)
	{
		
	}
}

Proteus测试LED灯熄灭:
在这里插入图片描述

  1. 接着测试GPIO_WriteBit函数点亮LED,此函数的前2个参数与之前相同,第3个参数GPIO_WriteBit可以将对应位置低电平,Bit_SET对应位置高电平,如下图函数说明:

  • 在这里插入图片描述
  1. 此时程序写为如下LED灯应该点亮,Proteus中测试通过: GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_RESET);
  • 在这里插入图片描述
  1. 如果改为GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_SET); led熄灭;
    在这里插入图片描述

6.5. LED灯闪烁效果

  1. 思路是需要延时函数的加入,用函数GPIO_WriteBit 让A0位在SET与RESET中切换;
  2. 延时函数采用作者已经放在示例程序1-3 Delay函数模块中,将此文件夹中的两个文件拷贝到项目文件夹中,项目文件夹中新建System目录,将这2个文件拷贝进去,同时需要在项目选项中添加System目录与搜索路径如下图:
    在这里插入图片描述

在这里插入图片描述


  1. 此时的LED闪烁程序需要修改为如下程序:
#include "stm32f10x.h"                  // Device header
#include "Delay.h"

int main(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	//GPIO_ResetBits(GPIOA, GPIO_Pin_0);
	//GPIO_SetBits(GPIOA,GPIO_Pin_0);
	//GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_RESET);
	//GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_SET);

	while(1)
	{
		GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_RESET);
		Delay_ms(500);
		GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_SET);
		Delay_ms(500);
	}
}

  1. 同时需要注意的是Proteus中模拟的时候,需要双击STM32芯片,并将其中的时钟设置为如下形式:
    在这里插入图片描述

  1. proteus模拟测试通过:
    在这里插入图片描述

  1. 同时需要注意,如果非要用1代表高电平,0代表低电平,则程序需要修改为如下,在0和1前面加入(BitAction)进行强制类型转换,程序编译通过:
#include "stm32f10x.h"                  // Device header
#include "Delay.h"

int main(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	//GPIO_ResetBits(GPIOA, GPIO_Pin_0);
	//GPIO_SetBits(GPIOA,GPIO_Pin_0);
	//GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_RESET);
	//GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_SET);

	while(1)
	{
		GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_RESET);
		Delay_ms(500);
		GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_SET);
		Delay_ms(500);
		GPIO_WriteBit(GPIOA,GPIO_Pin_0,(BitAction)0);	//(BitAction)强制转换0为枚举类型
		Delay_ms(500);
		GPIO_WriteBit(GPIOA,GPIO_Pin_0,(BitAction)1);	//(BitAction)强制转换1为枚举类型
		Delay_ms(500);		
	}
}

  1. 同时,如果将 “ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ” 改为开漏输出模式 “ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD ”,笔者的视频实际测试, A0接LED正极,LED无法点亮,LED负极接A0,LED可以点亮,说明改为开漏模式的时候,低电平还是有驱动能力的,印证了开漏和推挽输出的特性区别;

6.6. LED流水灯

  1. LED流水灯的接线图如下,对应面包板上面需要接线:
    在这里插入图片描述

  1. 复制3-1 LED闪烁 项目目录,重命名为 3-2 LED流水灯,双击打开“ project.uvprojx ”文件,在Keil中直接打开了一个新的项目,修改main文件程序实现LED流水灯;
  2. 需要注意的是,GPIO_Pin_0 需要增加定义到 GPIO_Pin_7,同时打开GPIO_Pin的定义可以看到如下规律,同时需要注意的是每个端口对应一个位,后面的注释中对应的二进制的数字只写了最后4位的,实际(uint16_t)0x0001) 改为2进制表示应该是 0000 0000 0000 0001 , 这个需要注意)
    define GPIO_Pin_0 ((uint16_t)0x0001) /*!< Pin 0 selected / (对应二进制1为0001
    define GPIO_Pin_1 ((uint16_t)0x0002) /
    !< Pin 1 selected / (对应二进制2为0010
    define GPIO_Pin_2 ((uint16_t)0x0004) /
    !< Pin 2 selected / (对应二进制4为0100
    define GPIO_Pin_3 ((uint16_t)0x0008) /
    !< Pin 3 selected / (对应二进制8为1000
    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 */…
  3. 基于上述规律,程序可以用如下图所示按位或的方式全部选中所需要的位,最终用GPIO_Pin_All,直接初始化所有端口为推挽输出模式;
    在这里插入图片描述

  1. 此时LED流水灯的简单程序如下:
#include "stm32f10x.h"                  // Device header
#include "Delay.h"

int main(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	//GPIO_ResetBits(GPIOA, GPIO_Pin_0);
	//GPIO_SetBits(GPIOA,GPIO_Pin_0);
	//GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_RESET);
	//GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_SET);

	while(1)
	{
		GPIO_Write(GPIOA,~0x0001);	//对应二进制0000 0000 0000 0001,0点亮,所以取反
		Delay_ms(500);
		GPIO_Write(GPIOA,~0x0002);	//对应二进制0000 0000 0000 0010,0点亮,所以取反
		Delay_ms(500);
		GPIO_Write(GPIOA,~0x0004);	//对应二进制0000 0000 0000 0100,0点亮,所以取反
		Delay_ms(500);
		GPIO_Write(GPIOA,~0x0008);	//对应二进制0000 0000 0000 1000,0点亮,所以取反
		Delay_ms(500);
		GPIO_Write(GPIOA,~0x0010);	//对应二进制0000 0000 0001 0000,0点亮,所以取反
		Delay_ms(500);
		GPIO_Write(GPIOA,~0x0020);	//对应二进制0000 0000 0010 0000,0点亮,所以取反
		Delay_ms(500);
		GPIO_Write(GPIOA,~0x0040);	//对应二进制0000 0000 0100 0000,0点亮,所以取反
		Delay_ms(500);
		GPIO_Write(GPIOA,~0x0080);	//对应二进制0000 0000 1000 0000,0点亮,所以取反
		Delay_ms(500);
	}
}

  1. Proteus中仿真测试通过:
    在这里插入图片描述

6.7. 蜂鸣器

  1. 蜂鸣器STM32面包板接线图如下,蜂鸣器IO接B12;

  2. 在这里插入图片描述

  3. 如上图接好杜邦线和蜂鸣器模块完成硬件电路,同时需要注意此处笔者接的蜂鸣器是B12输出低电平,蜂鸣器响,输出高电平,蜂鸣器不响;

  4. Keil中复制粘贴3-2项目文件夹并改名为< 3-3 蜂鸣器 >,并在Keil中打开

  5. Keil中建立简单测试程序对蜂鸣器进行测试,程序如下

#include "stm32f10x.h"                  // Device header
#include "Delay.h"

int main(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	GPIO_Init(GPIOB,&GPIO_InitStructure);
	
	while(1)
	{
		GPIO_ResetBits(GPIOB,GPIO_Pin_12);
		Delay_ms(500);
		GPIO_SetBits(GPIOB,GPIO_Pin_12);
		Delay_ms(500);
	}
}

  1. 需要注意的是Proteus中进行仿真测试的时候的电路如下,buzz蜂鸣器选用的是DC驱动有源蜂鸣器,标识有Active的可以仿真,NPN的选用如下图,BUZZ的操作电压需要修改为5V电压,编译程序后Proteus仿真没有问题;
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  1. 修改程序响100ms,关100ms,响100ms,关700ms,程序如下:
#include "stm32f10x.h"                  // Device header
#include "Delay.h"

int main(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	GPIO_Init(GPIOB,&GPIO_InitStructure);
	
	while(1)
	{
		GPIO_ResetBits(GPIOB,GPIO_Pin_12);
		Delay_ms(100);
		GPIO_SetBits(GPIOB,GPIO_Pin_12);
		Delay_ms(100);
		GPIO_ResetBits(GPIOB,GPIO_Pin_12);
		Delay_ms(100);
		GPIO_SetBits(GPIOB,GPIO_Pin_12);
		Delay_ms(700);
	}
}

  1. 几种使用库函数的方法:
  • 第一种方法,先打开.h文件,找到文件末尾,看有哪些函数,接着右键打开函数定义,查看函数和参数的用法,
  • 第二种方法打开STM32F103XX固件函数库用户手册,有所有函数介绍和使用方法,可能有用户手册与库函数版本不对应的问题;
  • 第三种方法是上网搜索,参考他人的代码;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1666152.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

暗区突围哪里获得测试资格 暗区突围测试资格获取方法

在游戏业界的浩瀚星空中&#xff0c;《暗区突围》如同一颗璀璨新星&#xff0c;以其独树一帜的游戏模式和前所未有的沉浸式体验&#xff0c;迅速吸引了全球玩家的目光。它不仅仅是一款游戏&#xff0c;更像是一次对勇气、智慧与团队合作的深度探索。玩家在危机四伏的暗区中&…

【软考高项】四十四、高级项目管理

一、项目集管理 相关角色 项目集发起人、项目集指导委员会、项目集经理、其他影响项目集的干系人项目集管理绩效域 项目集战略一致性、项目集效益管理、项目集干系人参与、项目集治理和项目集生命周期管理 二、项目组合管理 项目组合经理角色 项目组合管理原…

软件测试报告(交付文档支撑word原件)

软件测试报告在软件开发过程中起着至关重要的作用&#xff0c;主要有以下几个主要原因&#xff1a; 1、确保软件质量 2、提供决策支持 3、记录测试过程和结果 4、促进沟通和协作 5、符合标准和法规要求 6、改进测试流程和策略 7、降低风险 软件开发全套资料获取进主页或者本文…

【字符函数与字符串函数】

文章目录 一、strlen函数1.strlen函数的使用2.strlen函数的模拟实现(1)计算器办法(2)不创建临时变量计数器(3)指针 二、strcpy函数1、strcpy函数的使用2、strcpy函数的模拟实现 三、strcat函数1、strcat函数的使用2、strcat模拟实现3、字符串自己给自己追加&#xff1f; 四、st…

2024年数维杯数学建模

高质量原创论文已完成 需要的私我

构建内网yum仓库

1、环境介绍 系统&#xff1a;龙蜥os 7.9 2、安装epel源 yum install epel-release -y3、安装nginx服务器并启动 yum install nginx httpd -y配置 server {listen 80;server_name repo.wtown.com;root /usr/share/nginx/html/repo;index index.html index.htm;location / {…

信息安全-古典密码学简介

目录 C. D. Shannon: 一、置换密码 二、单表代替密码 ① 加法密码 ② 乘法密码 ③密钥词组代替密码 三、多表代替密码 代数密码 四、古典密码的穷举分析 1、单表代替密码分析 五、古典密码的统计分析 1、密钥词组单表代替密码的统计分析 2、英语的统计规…

报表-集成

1、部署报表服务器 以centos为例 1.1 将服务拷贝到服务器 其中JDK-17是对应平台的jdk 1.2 修改lite-report下的source.config 1.3 把设计好的报表文件拷贝到lite-report/report 1.4 启动服务&#xff1a;sh run.sh restart 2、使用Nginx location /litereport/ { …

前端笔记-day1

文章目录 01-标签的写法02-HTML的基本骨架03-标签的关系04-注释05-标题标签06-段落标签07-换行与水平线标签08-文本格式化标签09-图像的基本使用10-图像的属性12-绝对路径13-超链接14-音频15-视频标签16-招聘案例18-个人简历19-vue简介 01-标签的写法 <strong>文字内容&…

LabVIEW开发MOOG控制系统数据处理软件

LabVIEW开发MOOG控制系统数据处理软件 在现代航空领域&#xff0c;飞机结构的静强度试验是保证飞机安全运行的关键环节。MOOG加载控制系统作为试验中的关键设备&#xff0c;其数据输出的直观性和易处理性对于提高试验效率具有重要意义。设计了一种基于LabVIEW的MOOG控制系统数…

##15 探索高级数据增强技术以提高模型泛化能力

文章目录 前言数据增强的重要性常见的数据增强技术高级数据增强技术在PyTorch中实现数据增强结论 前言 在深度学习领域&#xff0c;数据增强是一种有效的技术&#xff0c;它可以通过在原始数据上应用一系列变换来生成新的训练样本&#xff0c;从而增加数据的多样性&#xff0c…

Redis过期删除策略和内存淘汰策略有什么区别?

Redis过期删除策略和内存淘汰策略有什么区别&#xff1f; 前言过期删除策略如何设置过期时间&#xff1f;如何判定 key 已过期了&#xff1f;过期删除策略有哪些&#xff1f;Redis 过期删除策略是什么&#xff1f; 内存淘汰策略如何设置 Redis 最大运行内存&#xff1f;Redis 内…

ADS基础介绍篇1

一. ADS简介 常用的射频仿真软件有ADS和AWR&#xff0c;ADS(Advanced Design system)最传统&#xff0c;是Agilent公司于2008年推出的电磁场仿真器&#xff0c;可提供原理图设计和layout版图设计。仿真功能十分强大&#xff0c;可提供从无源到有源&#xff0c;从直流到交流&am…

算法提高之矩阵距离

算法提高之矩阵距离 核心思想&#xff1a;多源bfs 从多个源头做bfs&#xff0c;求距离 先把所有1的坐标存入队列 再把所有1连接的位置存入 一层一层求 #include <iostream>#include <cstring>#include <algorithm>using namespace std;const int N 1…

关于画图-一次性搞定各类高级论文作图及配色

关于画图-一次性搞定各类高级论文作图及配色 图&#xff08;Figure&#xff09;可以让各类论文的结果更加直观&#xff0c;有时候一张图片比一大段文字更有说服力。 但许多新手作者可能会有一连串的疑惑&#xff1a;数据这么多&#xff0c;什么时候该做什么类型的图&#xff…

NASA数据集——2002-2011年全球18.7 至 89.0 千兆赫的亮度温度、海冰浓度和海冰积雪深度三级网格产品(AE_SI12)数据

AMSR-E/Aqua Daily L3 12.5 km Brightness Temperature, Sea Ice Concentration, & Snow Depth Polar Grids V003 三级网格产品&#xff08;AE_SI12&#xff09;包括 18.7 至 89.0 千兆赫的亮度温度、海冰浓度和海冰积雪深度。 简介 美国国家航空航天局地球观测系统 Aqu…

##16 利用迁移学习和微调提升深度学习模型性能

文章目录 前言什么是迁移学习&#xff1f;迁移学习的主要优势迁移学习的策略1. 特征提取器2. 微调 在PyTorch中实现迁移学习环境设置加载预训练模型修改模型以适应新任务训练和微调模型迁移学习的示例应用 结论 前言 在深度学习的多个领域中&#xff0c;迁移学习技术已经成为了…

现代信号处理9_正则化(CSDN_20240512)

正则化的引入 解线性方程组&#xff1a; 这项工作有很多种做法&#xff0c;下面介绍两种&#xff0c;如下图所示&#xff0c;有一些数据点需要拟合&#xff0c;拟合的方法有很多。 1&#xff09; 构造线性函数①&#xff0c;这种函数比较简单&#xff0c;此时 2&#xff09; 构…

信息系统项目管理师0102:可行性研究的内容(7项目立项管理—7.2项目可行性研究—7.2.1可行性研究的内容)

点击查看专栏目录 文章目录 7.2项目可行性研究7.2.1可行性研究的内容1.技术可行性分析2.经济可行性分析3.社会效益可行性分析4.运行环境可行性分析5.其他方面的可行性分析记忆要点总结7.2项目可行性研究 可行性研究是在项目建议书被批准后,从技术、经济、社会和人员等方面的条…

46 udp网络程序

查询网络服务的命令 netstat -nlup n: 显示数字 a&#xff1a;显示所有 u&#xff1a;udp服务 p&#xff1a;显示pid Recv-Q收到的数量&#xff0c;本地ip和远端ip&#xff0c;00表示可以收到任何地址 网络聊天 服务端 定义一个server类&#xff0c;成员保存ip地址&#xff…