STM32F407ZG GPIO输出相关实验

STM32F407ZG开发板学习(2)

  • 输入输出模式
    • 输入模式
      • 浮空输入
      • 上拉输入
      • 下拉输入
      • 模拟输入
    • 输出模式
      • 开漏输出
      • 推挽输出
      • 复用开漏输出
      • 复用推挽输出
  • RCC
    • RCC_AHB1PeriphClockCmd
    • RCC_AHB1PeriphResetCmd
    • RCC_AHB1PeriphClockLPModeCmd
  • GPIO
    • GPIO_DeInit
    • GPIO_Init
    • GPIO_StructInit
    • GPIO_ToggleBits
    • GPIO写入函数
      • GPIO_SetBits
      • GPIO_ResetBits
      • GPIO_WriteBit
      • GPIO_Write
  • GPIO输出实验
    • 点亮LED
      • 硬件原理图
        • MCU引脚图
        • LED电路图
      • 根据上述原理图编写main.c
    • 编写延时函数实现跑马灯
      • Delay.h
      • 初始化延时函数的时钟
      • 延时函数
      • main.c的主循环改一下即可
    • 蜂鸣器发声
      • 蜂鸣器原理

输入输出模式

GPIO(general purpose input output):通用输入输出端口的简称。可以通过软件控制其输出和输入。stm32芯片的GPIO引脚与外部设备连接起来,从而实现与外部通信,控制以及数据采集的功能。

输入模式

浮空输入

上拉、下拉都断开,电平忽高忽低不确定,取决于外部电路。用作开关按键的读取。

上拉输入

高电平输入。稳定。

下拉输入

低电平输入。稳定。

模拟输入

用AD采集到IO口上面的真实电压。可以在低功耗模式下运行,实现省电的作用。

输出模式

开漏输出

只输出低电平,仅低电平有驱动能力,要输出高电平需要外接上拉。可以线与,多用于I2C和SMBUS总线。

推挽输出

可以输出高低电平,都有驱动能力,用于连接数字器件。带载能力强。
输出高电平,电流输出到负载,叫灌电流,推;输出低电平,负载电流流向芯片,叫拉电流,挽。

复用开漏输出

复用推挽和复用开漏其实很简单,在你理解了开漏和推挽的原理之后,如果你不想用单片机内部来输出,那么你可以进行复用,将输出转移到其他外设上面。

复用推挽输出

RCC

40_41xxx的stm32f4xx_rcc.h中有如下函数声明,AHB和APB各有两个,具体第一个参数的取值范围可以查看*.c文件。
STM32F407ZG GPIO输出相关实验_第1张图片
这里只举例AHB1的三个常用函数。

RCC_AHB1PeriphClockCmd

使能/禁用AHB1外设时钟。
(uint32_t RCC_AHB1Periph, FunctionalState NewState)
参数:

  1. RCC_AHB1Periph:指定AHB1外设门控时钟,只能是以下的值:
    RCC_AHB1Periph_GPIOA: GPIOA clock
    RCC_AHB1Periph_GPIOB: GPIOB clock
    RCC_AHB1Periph_GPIOC: GPIOC clock
    RCC_AHB1Periph_GPIOD: GPIOD clock
    RCC_AHB1Periph_GPIOE: GPIOE clock
    RCC_AHB1Periph_GPIOF: GPIOF clock
    RCC_AHB1Periph_GPIOG: GPIOG clock
    RCC_AHB1Periph_GPIOG: GPIOG clock //此行官方就是写的G,大概可能应该是H?
    RCC_AHB1Periph_GPIOI: GPIOI clock
    RCC_AHB1Periph_GPIOJ: GPIOJ clock (STM32F42xxx/43xxx devices)
    RCC_AHB1Periph_GPIOK: GPIOK clock (STM32F42xxx/43xxx devices)
    RCC_AHB1Periph_CRC: CRC clock
    RCC_AHB1Periph_BKPSRAM: BKPSRAM interface clock
    RCC_AHB1Periph_CCMDATARAMEN: CCM data RAM interface clock
    RCC_AHB1Periph_DMA1: DMA1 clock
    RCC_AHB1Periph_DMA2: DMA2 clock
    RCC_AHB1Periph_DMA2D: DMA2D clock (STM32F429xx/439xx devices)
    RCC_AHB1Periph_ETH_MAC: Ethernet MAC clock
    RCC_AHB1Periph_ETH_MAC_Tx: Ethernet Transmission clock
    RCC_AHB1Periph_ETH_MAC_Rx: Ethernet Reception clock
    RCC_AHB1Periph_ETH_MAC_PTP: Ethernet PTP clock
    RCC_AHB1Periph_OTG_HS: USB OTG HS clock
    RCC_AHB1Periph_OTG_HS_ULPI: USB OTG HS ULPI clock
  2. NewState:使能/失能,即ENABLE/DISABLE

RCC_AHB1PeriphResetCmd

强制或释放AHB1外围设备复位。
(uint32_t RCC_AHB1Periph, FunctionalState NewState)
参数与上一个函数一致,第一个取值范围些许不同。

RCC_AHB1PeriphClockLPModeCmd

在Low Power (Sleep)模式下使能/关闭AHB1外设时钟。
(uint32_t RCC_AHB1Periph, FunctionalState NewState)
参数与上一个函数一致,第一个取值范围些许不同。

GPIO

GPIO_DeInit

参数:(GPIO_TypeDef* GPIOx)
复位GPIOx(GPIOA到GPIOK)

GPIO_Init

参数:(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)
用一个结构体初始化GPIOx。
结构体的参数如下:

typedef struct
{
  uint32_t GPIO_Pin;  //需要配置的GPIO引脚,可以用按位或操作符选择多个引脚
  GPIOMode_TypeDef GPIO_Mode;  //指定所选引脚的工作模式。
  GPIOSpeed_TypeDef GPIO_Speed;  //指定所选引脚的速度。
  GPIOOType_TypeDef GPIO_OType;  //指定所选引脚的操作输出类型。
  GPIOPuPd_TypeDef GPIO_PuPd;   //指定所选引脚的上拉/下拉操作。 
}GPIO_InitTypeDef;

typedef enum
{ 
  GPIO_Mode_IN   = 0x00, /*输入*/
  GPIO_Mode_OUT  = 0x01, /*输出*/
  GPIO_Mode_AF   = 0x02, /*GPIO备用功能模式,复用*/
  GPIO_Mode_AN   = 0x03  /*GPIO模拟模式*/
}GPIOMode_TypeDef;

typedef enum
{ //这里也是可以使用GPIO_Speed_xxMHz的,xx可取25、50、100
  GPIO_Low_Speed     = 0x00, /*!< Low speed    */
  GPIO_Medium_Speed  = 0x01, /*!< Medium speed */
  GPIO_Fast_Speed    = 0x02, /*!< Fast speed   */
  GPIO_High_Speed    = 0x03  /*!< High speed   */
}GPIOSpeed_TypeDef;

typedef enum
{ 
  GPIO_OType_PP = 0x00,  //推挽 Push Pull
  GPIO_OType_OD = 0x01  //开漏 Open Drain
}GPIOOType_TypeDef;

typedef enum
{ 
  GPIO_PuPd_NOPULL = 0x00, //浮空
  GPIO_PuPd_UP     = 0x01, //上拉
  GPIO_PuPd_DOWN   = 0x02 //下拉
}GPIOPuPd_TypeDef;

GPIO_StructInit

参数:(GPIO_InitTypeDef* GPIO_InitStruct)
将结构体附默认值

GPIO_ToggleBits

参数:(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
切换指定的GPIO引脚。

GPIO写入函数

GPIO_SetBits

参数:(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
把一些bits置1

GPIO_ResetBits

参数:(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
把一些bits置0

GPIO_WriteBit

参数:(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);
将某一位赋指定值

GPIO_Write

参数:(GPIO_TypeDef* GPIOx, uint16_t PortVal);
直接赋值该GPIO的16位

GPIO输出实验

点亮LED

硬件原理图

MCU引脚图

MCU引脚图
可知GPIOF的Pin_9和Pin_10分别接LED0和LED1

LED电路图

STM32F407ZG GPIO输出相关实验_第2张图片
可知LED0和LED1置高电平时不导通,即灯灭,置低电平时导通,灯亮。

根据上述原理图编写main.c

#include "stm32f4xx.h"

int main()
{
    GPIO_InitTypeDef GPIO_InitStructure;
    
    /* 根据原理图使能GPIOF,选择AHB1外设时钟 */
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);
    
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; //选择输出模式
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //选择推挽输出
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; //根据原理图led的两个引脚为PF9和PF10
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //100MHz
    
    GPIO_Init(GPIOF, &GPIO_InitStructure); //初始化GPIOF
    
    GPIO_SetBits(GPIOF, GPIO_Pin_9 | GPIO_Pin_10); //初始化引脚值为高电平,根据原理图即灯熄灭
    
    while(1)
    {
        GPIO_ResetBits(GPIOF, GPIO_Pin_9 | GPIO_Pin_10); //Reset两个引脚(即置0),灯亮
    }
    
}

编写延时函数实现跑马灯

CM4 内核的处理和CM3 一样 ,内部都包含了一个 SysTick 定时器,SysTick是一个24位的倒计数定时器,当计到0时,将从RELOAD寄存器中自动重装载定时初值。只要不把它在SysTick控制及状态寄存器中的使能位清除,就永不停息。我们就是利用STM32的内部SysTick 来实现延时的,这样既不占用中断,也不占用系统定时器。

Delay.h

#ifndef DELAY_H__
#define DELAY_H__
#include "stm32f4xx.h"

void delay_init(u8 SYSCLK); //初始化系统时钟
void delay_ms(u16 xms); //延时xms
void delay_us(u32 xus); //延时xus

#endif

初始化延时函数的时钟

void delay_init(u8 SYSCLK);
参数:(u8 SYSCLK);
SYSCLK就是Systick时钟的频率。
用到misc.h中的一个函数void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource);配置系统时钟的来源,有两个参数可供选择:
SysTick_CLKSource_HCLK_Div8: AHB时钟频率除以8作为系统时钟源。
SysTick_CLKSource_HCLK: 直接使用AHB作为系统时钟源。

延时函数

延时的两个函数操作类似,主要使用了以下几个寄存器:
SysTick是MDK定义了的一个结构体(在core_m4.h里面),里面包含CTRL 、LOAD 、VAL 、
CALIB等4 个寄存器:
CTRL(SysTick control and status register)
STM32F407ZG GPIO输出相关实验_第3张图片
LOAD(SysTick reload value register)
重装值寄存器,即当VAL为0时,VAL将被重装的值。
LOAD
VAL(SysTick current value register)
记录次数的寄存器
STM32F407ZG GPIO输出相关实验_第4张图片

CALIB(SysTick calibration value register)
校准用,这里没有用到。

SysTick时钟使能/关闭:

使能滴答定时器:SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;

关闭滴答定时器:SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk;

SysTick_CTRL_ENABLE_Msk宏定义位1<<0,那么CTRL或等于它即把最低位置1,即打开时钟。

主要逻辑:
给LOAD赋值,清空VAL的值。
等待直到当CTRL的0位(使能位)且16位(COUNTFLAG)都为1时才停止时钟。
清空VAL的值。

延时取值范围:
STM32F407ZG GPIO输出相关实验_第5张图片

STM32F4的时钟系统,如图HCLK最高168MHz,若使用HCLK除以8作为SysTick时钟源,则最高21MHz,那么每微妙所需要的时钟数为21M/s x 1us = 21,则根据24位寄存器,取值范围可以给到 (2^24 - 1) / 21 = 798915 us。ms的取值就大概在798ms。

main.c的主循环改一下即可

	delay_init(168); //初始化延时函数
    
    while(1)
    {
        GPIO_ResetBits(GPIOF, GPIO_Pin_9); //F9置0,F10置1
        GPIO_SetBits(GPIOF, GPIO_Pin_10);
        delay_ms(500);
        GPIO_ResetBits(GPIOF, GPIO_Pin_10); //F9置1,F10置0
        GPIO_SetBits(GPIOF, GPIO_Pin_9);
        delay_ms(500);
    }

蜂鸣器发声

蜂鸣器原理

由于蜂鸣器的启动电流较大,因此一般使用三极管驱动,STM32F4的引脚只作为标记使能。开发板使用的引脚为PF8。
STM32F407ZG GPIO输出相关实验_第6张图片
如图使用NPN型三极管,BEEP输入高电平时导通,蜂鸣器发声。
则具体代码和控制LED类似,不再赘述。

你可能感兴趣的:(STM32学习,stm32,单片机,arm)