前言
📝说明↔LED灯和蜂鸣器就不再介绍了,具体可以去51单片机系列了解👋
操作STM32当中的GPIO一共有三步骤如下👇
㈠使用RCC开启GPIO的时钟 [RCC-即复位与时钟控制,主要是通过寄存器配置时钟源]
注⇢时钟相当于单片机的心脏,开启后才能实现相应的功能。
㈡使用GPIO_Init函数初始化GPIO口。
㈢使用输出或者输入函数控制GPIO口。
在这里一共涉及了RCC和GPIO两个外设,那么就让我们来看看这两个函数有哪些库函数。
下面介绍下 RCC 的库函数以及 GPIO 的库函数。
这个代码头文件是在stm32f10x_rcc.h头文件当中的。
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);
1.RCC AHC外设时钟控制
2.RCC APB2外设时钟控制
3.RCC APB1外设时钟控制
🌴说明↔在上述代码中是我们最常用的三个函数的头文件,可以跳转到.c文件看看具体是什么意思。
这个代码头文件是在stm32f10x_gpio.h头文件当中的。我们目前了解以下GPIO头文件即可。
//note:调用这个函数,所指定的GPIO外设就会被复位.
void GPIO_DeInit(GPIO_TypeDef* GPIOx);
//note:调用这个函数,可以复位AFIO的外设.
void GPIO_AFIODeInit(void);
//note:调用这个函数,用结构体当中的参数也就是成员变量来初始化GPIO口
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
//note:调用这个函数,可以把结构体变量赋值一个默认值
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);
//Read function
1.读取输入数据寄存器某一个端口输入值.
2.读取输入整个数据寄存器的.
3.读取输出数据寄存器的某一位,所以原则上它并不是用来读取端口的输入数据.
4.读取输出整个数据寄存器的.
说明:读取输入是可以高低电平变化的(Io电平)而读取输出是代表输出一个指定的电平.
注:一般读取输入都是外在控制比较多,像按键和传感器等.
//写入函数
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);
//Write function
1.指定端口设置成为高电平.
2.指定端口设置成为低电平.
3.前两个也是指定端口的,第三个参数:根据值来设置指定的端口电平.
4.第一个参数选择外设,第二个参数可以同时对16个端口进行写入操作.
这里面重要的函数是GPIO初始化以及8个读写函数。
这上面的读写函数就是可以实现读写GPIO口的功能,以上代码的源文件.c相比五一C语言难度是难了许多设计到C语言很多比较难的知识点,如果你不会这些知识点或者是还是不了解,那么我推荐你还是在回去学习一下C语言,因为这些函数尽管是可以在库函数直接拿来就可以用的。但是这样你对于这种理解层面对于32的代码库上你只是一个很浅的水平,所以说C语言很重要。一般我认为学到这种你起码还是要学习下数据结构这样对于你理解层面帮助会很大,前提是你的C语言要过关尤其是关于指针各个方面的,不然你学数据结构你也是对于它来说非常懵的一个状态。
正式开始成为点灯大师(@^0^) 注→这里我们把引脚阴极是在STM32引脚当中的A0引脚当中,阳极放在Vcc上。此时我们给A0引脚低电平LED灯就会被点亮。
#include "stm32f10x.h"
int main(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_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_ResetBits(GPIOA,GPIO_Pin_0);
}
说明-写代码之前介绍下如下代码👇
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);
第一个参数和第二个参数自然不需要介绍了,介绍下第三个参数 BitVal 是什么意思吧,其实很容易就是控制此引脚高低电平。你给第三个参数是Bit_SET那么此引脚为高电平,如果我们参数是Bit_RESET此引脚为低电平。
#include "stm32f10x.h" // Device header
#include "Delay.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);
}
}
int main(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_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
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, Bit_RESET);
Delay_ms(500);
GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET);
Delay_ms(500);
//如果第三个参数给0 or1 在这里需要进行强制转换成BitAction枚举类型,不然会warning.
GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)0);
Delay_ms(500);
GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)1);
Delay_ms(500);
}
}
示例代码如下👇
#include "stm32f10x.h"
#include "Delay.h"
#define BINARY 1 //根据0||1选择
int main(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_All; //注:GPIO_Pin_All:相当于选中了所有位
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
while (1)
{
#if BINARY//1
GPIO_Write(GPIOA, ~0x0001); //0000 0000 0000 0001
Delay_ms(100);
GPIO_Write(GPIOA, ~0x0002); //0000 0000 0000 0010
Delay_ms(100);
GPIO_Write(GPIOA, ~0x0004); //0000 0000 0000 0100
Delay_ms(100);
GPIO_Write(GPIOA, ~0x0008); //0000 0000 0000 1000
Delay_ms(100);
GPIO_Write(GPIOA, ~0x0010); //0000 0000 0001 0000
Delay_ms(100);
GPIO_Write(GPIOA, ~0x0020); //0000 0000 0010 0000
Delay_ms(100);
GPIO_Write(GPIOA, ~0x0040); //0000 0000 0100 0000
Delay_ms(100);
GPIO_Write(GPIOA, ~0x0080); //0000 0000 1000 0000
Delay_ms(100);
#else//0
int i = 0;
for(i=0;i<8;i++)
{
GPIO_Write(GPIOA, ~(0x0001<<i));
Delay_ms(100);
}
#endif
}
}
说明→当然你还可以使用数组的方式来获取,这里就不再演示了。
说明→这个是上述代码的接线图。
接线图如下👇
注意→在这里A15、B3、B4三个IO口别选,因为这三个口默认的是调试端口,如果要用做普通端口还需要进行配置。
代码示例如下👇
#include "stm32f10x.h" // Device header
#include "Delay.h"
int main(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
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;
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(1000);
}
}