STM32基础GPIO输出操作:点亮和闪烁LED灯,实现跑马流水灯效果(使用标准库GPIO输出模式)

STM32GPIO输出流程:

操作STM32的GPIO需要三个步骤
第一步:RCC开启时钟
第二步:使用GPIO_Init函数初始化GPIO
第三步:使用输出或输入的函数控制GPIO口

1、RCC最常用的函数:

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);

这三个函数分别是使能或失能AHB、APB1、APB2外设时钟控制。

2、GPIO库函数

void GPIO_DeInit(GPIO_TypeDef* GPIOx);
void GPIO_AFIODeInit(void);
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
void GPIO_StructInit(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);

GPIO复位函数

DeInit复位指定的GPIO外设
AFIODeInit函数,可以复位AFIO外设
GPIO_Init函数是通过结构体参数初始化GPIO口(最常用)
GPIO_StructureInit可以把结构体变量赋默认值

GPIO读函数

uint8_t GPIO_ReadInputDataBit
uint16_t GPIO_ReadInputData
uint8_t GPIO_ReadOutputDataBit
uint16_t GPIO_ReadOutputData

GPIO写函数

void GPIO_SetBits
void GPIO_ResetBits
void GPIO_WriteBit
void GPIO_Write

GPIO八种工作模式

代码后面有注释,可以看后面的定义

typedef enum
{ GPIO_Mode_AIN = 0x0,            //模拟输入(Analog IN)
  GPIO_Mode_IN_FLOATING = 0x04,   //浮空输入(In Floating)
  GPIO_Mode_IPD = 0x28,           //下拉输入(In Pull Down)
  GPIO_Mode_IPU = 0x48,           //上拉输入(In Pull Up)
  GPIO_Mode_Out_OD = 0x14,        //开漏输出(Out Open Drain)
  GPIO_Mode_Out_PP = 0x10,        //推挽输出(Out Push Pull)
  GPIO_Mode_AF_OD = 0x1C,         //复用开漏(Atl Open Drain)
  GPIO_Mode_AF_PP = 0x18          //复用推挽(Atl Push Pull)
}GPIOMode_TypeDef;

开始编程

将小灯正极连接到PA0引脚,串联一个10k或可调电阻,负极接到GND上。(采用高电平驱动模式),可采用面包板接线。

添加两个Delay库函数

Delay.h

#ifndef __DELAY_H
#define __DELAY_H

void Delay_us(uint32_t us);
void Delay_ms(uint32_t ms);
void Delay_s(uint32_t s);

#endif

Delay.c

#include "stm32f10x.h"

/**
  * @brief  微秒级延时
  * @param  xus 延时时长,范围:0~233015
  * @retval 无
  */
void Delay_us(uint32_t xus)
{
	SysTick->LOAD = 72 * xus;				//设置定时器重装值
	SysTick->VAL = 0x00;					//清空当前计数值
	SysTick->CTRL = 0x00000005;				//设置时钟源为HCLK,启动定时器
	while(!(SysTick->CTRL & 0x00010000));	//等待计数到0
	SysTick->CTRL = 0x00000004;				//关闭定时器
}

/**
  * @brief  毫秒级延时
  * @param  xms 延时时长,范围:0~4294967295
  * @retval 无
  */
void Delay_ms(uint32_t xms)
{
	while(xms--)
	{
		Delay_us(1000);
	}
}
 
/**
  * @brief  秒级延时
  * @param  xs 延时时长,范围:0~4294967295
  * @retval 无
  */
void Delay_s(uint32_t xs)
{
	while(xs--)
	{
		Delay_ms(1000);
	}
} 

 源代码:

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

int main() {
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    GPIO_InitTypeDef GPIO_InitTStrusture;//如果不支持函数中间定义变量就需要把这一行写到函数内部最前面
    GPIO_InitTStrusture.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
    GPIO_InitTStrusture.GPIO_Pin = GPIO_Pin_0;// 0引脚//时钟设置也可以按位或
    GPIO_InitTStrusture.GPIO_Speed = GPIO_Speed_50MHz;//输出频率 
    GPIO_Init(GPIOA,&GPIO_InitTStrusture);
    GPIO_ResetBits(GPIOA, GPIO_Pin_0);//ResetBits函数实现默认低电平
    GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_RESET);//WriteBit函数实现默认低电平
    while(1) {
        GPIO_ResetBits(GPIOA, GPIO_Pin_0);
        Delay_ms(500);
        GPIO_SetBits(GPIOA, GPIO_Pin_0);
        Delay_ms(500);
        GPIO_WriteBit(GPIOA,GPIO_Pin_0,(BitAction)0);//使用BitAction强制类型转换为Bit_RESET
        Delay_ms(500);
        GPIO_WriteBit(GPIOA,GPIO_Pin_0,(BitAction)1);
        Delay_ms(500);
    }
}

流水灯

初始化多个GPIO引脚

流水灯在GPIO初始化与上面同理,需要修改这一行部分代码

GPIO_InitTStrusture.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2;

这样就可以把0、1、2三个GPIO引脚初始化

也可以采用这个代码直接将全部的GPIO端口初始化:

GPIO_InitTStrusture.GPIO_Pin = GPIO_Pin_All;

为什么这样可以呢?如下图所示

因为每个GPIO_Pin_的值代表了一个16进制数,如果将这个16进制数换为2进制的话对应的:

GPIO_Pin_0为0000 0000 0000 0001

GPIO_Pin_1为0000 0000 0000 0010

GPIO_Pin_1为0000 0000 0000 0100

…           …        …        …        …        …

每个端口对应一个位,选取一些进行按位或的操作后,对应位置都为1。这样就同时选择了多个端口。

除了GPIO,时钟控制和GPIO_SetBits函数内部的参数也可以。

 使用GPIO_Write函数

GPIO_Write(GPIOA,0x0001);//0000 0000 0000 0001

第二个参数对应16个GPIO口,某一位为1对应就是这个端口为高电平。这个代码就表示第一位为高电平,其余为低电平,也就是PA0为高电平,其余为低电平。因此我们可以写出流水灯的代码如下。

流水灯源代码:

#include "stm32f10x.h"                  // Device header
#include "DELAY.h"
int main() {
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	GPIO_InitTypeDef GPIO_InitTStrusture;//如果不支持函数中间定义变量就需要把这一行写到函数内部最前面
	GPIO_InitTStrusture.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
	GPIO_InitTStrusture.GPIO_Pin = GPIO_Pin_All;// 0引脚//时钟设置也可以按位或
	GPIO_InitTStrusture.GPIO_Speed = GPIO_Speed_50MHz;//输出频率 
	GPIO_Init(GPIOA,&GPIO_InitTStrusture);
    while(1) {
        //GPIO_Write(GPIOA,0x0001);
		//使用GPIO_Write函数同时控制多个GPIO,第二个参数直接写到GPIO的ODR寄存器里//16进制数每一位
        对应一个GPIO端口,PA0-PA15。
		//若是低电平点亮,可以在前面加上~进行按位取反。例:~0x0001;
		GPIO_Write(GPIOA,0x0001);//0000 0000 0000 0001
		Delay_ms(500);
		GPIO_Write(GPIOA,0x0002);//0000 0000 0000 0010
		Delay_ms(500);
		GPIO_Write(GPIOA,0x0004);//0000 0000 0000 0100
		Delay_ms(500);

	}
	
}

物联沃分享整理
物联沃-IOTWORD物联网 » STM32基础GPIO输出操作:点亮和闪烁LED灯,实现跑马流水灯效果(使用标准库GPIO输出模式)

发表评论