前言:
本文详细的介绍了IO口的输出模式,并简单进行了跑马灯实验。本文使用的是STM32F103C8T6芯片,其他芯片的原理是相同的,可以在本实验的基础上进行修改。
本文需要有创建好的STM32F103C8T6的工程文件
如有需要可以从下方连接下载:
链接: https://pan.baidu.com/s/1Lmjp-e6ifl-AfZmAfuRxrQ 提取码: vk7y
一、理论知识介绍
GPIO的输出模式共计四种:推挽输出、开漏输出、复用推挽输出、复用开漏输出。
1.1推挽输出
英文是Push-Pull Output(Output PP)
推挽输出模式是最常用的GPIO输出模式。在该模式下,引脚可以输出高电平或低电平,同时具有一定的驱动能力,可以驱动外部电路。
特点:可以输出高电平和低电平,具有一定的驱动能力。
应用场景:用于驱动外部电路,如控制LED灯、驱动其他逻辑电路等。
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // 推挽输出模式
1.2开漏输出
英文是Open-Drain Output(Output OD)
在该模式下,引脚只能输出低电平,要输出高电平需要通过外部上拉电阻或其他方式。常用于与外部器件连接,例如与开漏输出的I2C总线器件进行通信。
特点:只能输出低电平,需要外部上拉电阻将引脚拉高;具有一定的驱动能力。
应用场景:与外部器件连接时,如I2C总线,用于与其他设备进行通信。
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; //开漏输出模式
1.3复用推挽输出
英文是AF Push-Pull Output(AF PP)
复用推挽输出模式允许将GPIO引脚用作特定外设功能。在该模式下,引脚可以输出高电平或低电平,并具有一定的驱动能力。
特点:具有推挽输出的特性,可用于将GPIO引脚用作特定外设的功能。
应用场景:连接到外设的特殊功能引脚,如UART串口通信引脚、PWM输出等。
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // 复用推挽输出模式
1.4复用开漏输出
英文是AF Open-Drain Output(AF OD)
复用开漏输出模式允许将GPIO引脚用作特定外设功能。在该模式下,引脚只能输出低电平,要输出高电平需要通过外部上拉电阻或其他方式。
特点:具有开漏输出的特性,可用于将GPIO引脚用作特定外设的功能。
应用场景:连接到外设的特殊功能引脚,如I2C总线通信引脚、故障信号输出等。
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; // 复用开漏输出模式
以上就是四种GPIO输出模式的介绍,本文控制LED灯亮灭使用推挽输出模式
二、硬件连接
STM32F103C8T36--->PA0----PA7依次连接八个LED灯,LED灯的引脚一端连接IO口,LED灯的引脚另一端接地。
三、软件编写
打开工程文件(如有需要在文章开头下载)
3.1创建函数文件夹
本文使用定义库函数来进行编程,将会新建一个Hardwear文件夹用来存放LED显示函数,在主函数中直接调用定义的函数即可实现LED的亮灭。(也可以直接将函数定义到主函数中,但要进行部分修改)
首先打开工程文件所在的文件夹,创建"Hardwear"文件夹。
然后打开KILE5软件,点击“三个方块”,打开文件管理界面,在工程中新建“Hardwear”文件夹。
点击OK后再左侧工程文件管理处就显示了Hardwear文件夹。
然后要添加文件夹路径,让工程文件可以找到文件夹的地址。(这步前往别忘了)
依次点击"魔法棒"-->"C/C++"-->"..."即可添加文件路径了
添加之后如下图所示
然后添加LED.c和LEC.h文件
首先右键Hardwear文件夹”再点击“Add New item to Group “Hardwear” ”
弹出以下界面,先选择创建“.C”文件,创建“LED.c”,再选择创建"LED.h“文件,创建"led.h”
要在工程文件夹中看一下LED.c与LED.h是否创建到了Hardwear文件夹,要确保LED.c和LED.h必须在Hardwera文件夹中。
创建函数文件夹就完成了(千万不要漏掉哪一步,不然就无法运行了)
3.2编写"LED.c"文件
首先在最上方引入标准库
#include "stm32f10x.h" // Device header
在LED.c中,先创建LED初始化函数(LED_Init),对PA0到PA7的引脚进行初始化
这是整体的代码,再下面进行解读
void LED_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_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;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
解读:
首先对RCC_APB2时钟进行启用
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
然后对GPIO口的参数进行定义
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_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;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
最后对GPIO进行初始化
GPIO_Init(GPIOA, &GPIO_InitStructure);
完成LED_Init函数的编写
在LED.c中,创建LED发光函数(LED_On),用来点亮LED。
void LED_On(int LED)
{
GPIO_WriteBit(GPIOA,LED,Bit_SET);
}
在LED.c中,创建LED发光函数(LED_Off),用来熄灭LED。
void LED_Off(int LED)
{
GPIO_WriteBit(GPIOA,LED,Bit_RESET);
}
完成对LED.c文件的配置
LED.c完整的代码如下
#include "stm32f10x.h" // Device header
void LED_Init(void)//LED初始化
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_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;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void LED_On(int LED)//LED亮
{
GPIO_WriteBit(GPIOA,LED,Bit_SET);
}
void LED_Off(int LED)//LED灭
{
GPIO_WriteBit(GPIOA,LED,Bit_RESET);
}
3.3编写"LED.h"文件
LED.h主要进行函数的声明,代码如下
#ifndef LED_H
#define LED_H
//函数声明
void LED_Init(void);
void LED_On(int LED);
void LED_Off(int LED);
#endif
3.4"main.c"文件的编写
想实现跑马灯效果,直接让LED灯依次亮灭即可。
首先在main.c文件中引入"LED.h”的头文件
#include "LED.h"
再进行LED初始化,调用LED_Init();函数
LED_Init();
再进行效果编写,完整代码如下
#include "stm32f10x.h" // Device header
#include "LED.h"
int main(void)
{
LED_Init();
int i =0;
while (1)
{
LED_On(0);
i =1000;
while(i--);
LED_Off(0);
LED_On(1);
i =1000;
while(i--);
LED_Off(1);
LED_On(2);
i =1000;
while(i--);
LED_Off(2);
LED_On(3);
i =1000;
while(i--);
LED_Off(3);
LED_On(4);
i =1000;
while(i--);
LED_Off(4);
LED_On(2);
i =1000;
while(i--);
LED_Off(5);
LED_On(6);
i =1000;
while(i--);
LED_Off(6);
LED_On(7);
i =1000;
while(i--);
LED_Off(7);
}
}
因为本文没有定义延时函数,就使用while(i--)进行了简单的延时,如果需要进行精确的延时的话要定义正确的延时函数来进行延时
本文完--
以下是本文的例程文件,有需要可以下载:
链接: https://pan.baidu.com/s/1v-xm7Paj1WEc_GfgF7npag 提取码: ef5w