使用库函数点亮第一个LED灯
目录
二、GPIO库函数介绍
2.1、GPIO外设的库文件
2.2、GPIO常用库函数
2.2.1、初始化函数
2.2.2、设置管脚输出电平函数
2.2.3、读取管脚输入电平函数
2.2.4、使能GPIO时钟函数
三、GPIO初始化步骤
3.1、使能对应的GPIO端口时钟
3.2、初始化GPIO
四、使用库函数编写点亮LED程序
4.1、LED初始化
4.2、点亮D1指示灯
一、LED模块硬件电路
- 相同网络标号表示它们是连接在一起的,因此 DS0、DS1 发光二极管阴极是连接在 STM32 的 PB5、PE5 管脚上。如果要使 DS0 指示灯亮,只需要控制 PB5 管脚输出低电平,如果要使 DS0 指示灯灭,只需控制 PB5 输出高电平。
- 两个相同的网络标号就表示这两处在电气上是相连的,即标有相同网络标号的两点,相当于是用一根导线连起来的。
- 网络标号一般用在较复杂的电路图中,连线较多,或两个需要相连的元件距离较远时,用导线相连感觉很乱,就常用相同的网络标号来标注两个连接点,使电路图显得简洁。
二、GPIO库函数介绍
2.1、GPIO外设的库文件
stm32f10x_gpio.c
stm32f10x_gpio.h
2.2、GPIO常用库函数
2.2.1、初始化函数
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
功能:初始化一个或多个IO口(同一组端口)的工作模式、输出速度即GPIO的2个配置寄存器。
初始化范例
GPIO_InitTypeDef GPIO_InitStructure; //定义结构体变量
GPIO_InitStructure.GPIO_Pin_0; // 选择你要设置的IO口
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //设置推挽输出模式
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHZ;//设置传输速率
GPIO_Init(GPIOC,&GPIO_InitStructure);/*初始化GPIO*/
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1; /*一次对多个管脚进行初始化,前提必须是它们的配置模式需一样*/
2.2.2、设置管脚输出电平函数
void GPIO_SetBits(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin);
功能:设置某个IO口为高电平(可同时设置同一端口的多个IO)。底层是通过配置BSRR寄存器。
void GPIO_ResetBits(GPIO_TypeDef* GPIOx,uint16_t GPIO_pin);
功能:设置某个IO口为低电平(可同时设置同一端口的多个IO)。底层 是通过配置BSRR寄存器。
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);
功能:设置端口管脚输出电平,很少使用。
2.2.3、读取管脚输入电平函数
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
功能:读取端口中的某个管脚输入电平。底层是通过读取IDR寄存器。
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);
功能:读取某组端口的输入电平。底层是通过读取IDR寄存器。
2.2.4、使能GPIO时钟函数
void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);
不同的外设调用的时钟使能函数可能不一样
使能GPIOC端口时钟:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
三、GPIO初始化步骤
3.1、使能对应的GPIO端口时钟
#define LED1_PORT_RCC RCC_APB2Periph_GPIOB
#define LED2_PORT_RCC RCC_APB2Periph_GPIOE
3.2、初始化GPIO
四、使用库函数编写点亮LED程序
4.1、LED初始化
4.2、点亮D1指示灯
五、软件
5.1、led.h文件
该文件主要是对 led.c 源文件的函数声明以及端口管脚的宏定义,方便其他文件调用该函数。在该头文件中可以看到使用了一个定义头文件的结构
#ifndef _led_H
#define _led_H
#endif
功能:防止头文件被重复包含,避免引起编译错误。
在头文件的开头,使用“ #ifndef”关键字,判断标号“ _led_H”是否被定义,若没有被定义,则从“ #ifndef”至“ #endif”关键字之间的内容都有效,即这个头文件若被其它文件“ #include”,它就会被包含到其该文件中,且头文件中紧接着使用“ #define”关键字定义上面判断的标号“ _led_H”。当这个头文件被同一个文件第二次“ #include”包含的时候,由于有了第一次包含中的“ #define _led_H”定义,这时再判断“ #ifndef _led_H”,判断的结果就是假了,从“ #ifndef”至“ #endif”之间的内容都无效,从而防止了同一个头文件被包含多次,编译时就不会出现“ redefine(重复定义)”的错误了。
#ifndef _led_H /*防止头文件被重复包含 意为:如果没有定义*/
#define _led_H /*那么就在此处定义*/
#include "stm32f10x.h"
/*使用宏定义 LED1_PORT_RCC、LED1_PIN 和 LED1_PORT存放在led.h头文件中
可以增强代码的移植性;即使后续需要换其他端口,只需简单修改这几个宏就可以完成对
LED 的控制。*/
#define LED1_PORT GPIOB // DS0端口
#define LED1_PIN GPIO_Pin_5 // DS0的引脚
#define LED1_PORT_RCC RCC_APB2Periph_GPIOB // DS0的端口时钟
#define LED2_PORT GPIOE // DS1的端口
#define LED2_PIN GPIO_Pin_5 // DS1的引脚
#define LED2_PORT_RCC RCC_APB2Periph_GPIOE //DS1的端口时钟
void LED_Init(void); //
#endif // 结束
5.2、led.c
#include "led.h"
void LED_Init()
{
GPIO_InitTypeDef GPIO_InitStructure; // 给结构体GPIO_InitTypeDef 取个别名GPIO_InitStructure
RCC_APB2PeriphClockCmd(LED1_PORT_RCC|LED2_PORT_RCC,ENABLE);// 开启DS0或DS1的时钟
GPIO_InitStructure.GPIO_Pin=LED1_PIN; // 端口配置
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; // 推挽输出模式配置
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //输出速度配置
GPIO_Init(LED1_PORT,&GPIO_InitStructure); // 初始化GPIO_Init()
GPIO_SetBits(LED1_PORT,LED1_PIN);// 将LED端口拉高,熄灭所有LED
GPIO_InitStructure.GPIO_Pin=LED2_PIN; //选择你要设置的 IO 口
GPIO_Init(LED2_PORT,&GPIO_InitStructure); /* 初始化 GPIO */
GPIO_SetBits(LED2_PORT,LED2_PIN); //将 LED 端口拉高,熄灭所有 LED
}
函数中的 LED1_PORT_RCC、LED1_PIN 和 LED1_PORT 等是我们定义的宏,其存放在 led.h 头文件内。LED1_PORT_RCC 定义的是 DS0 端口时钟(如RCC_APB2Periph_GPIOB),LED1_PIN 定义的是 DS0 的引脚(如 GPIO_Pin_5),LED1_PORT 定义的是 DS0 的端口(如 GPIOB)。这样定义宏的好处是有效提高了程序的移植性,即使后续需要换其他端口,只需简单修改这几个宏就可以完成对LED 的控制。
5.3、main.c
#include "stm32f10x.h"
#include "led.h"
int main()
{
LED_Init();
GPIO_ResetBits(LED1_PORT,LED1_PIN);
while(1)
{
}
}
翼codm: 我也不行
洒去犹能化碧涛: 我的是发送有一小部分乱码
旭日初扬: typedef unsigned char u8;
旭日初扬: 你试试不就知道了么
你在看什么啊: 有没有老哥告诉一下,“int fputc(int ch,FILE *p) //函数默认的,在使用printf函数时自动调用”这里我把函数名称改成foutc1成么?会影响函数的正常使用么?