目录
2.简要介绍GPIO_ReadOutputDataBit函数
前言
前边介绍了些GPIO的相关函数,整合一下,写一个小实验——按键控制LED
一、接线
二、模块化编程
因为该实验涉及到多个外设,全部代码写到一个文件里太乱太杂,也不适于以后直接使用某模块
(因为某些代码比较简单,比如延时函数代码,以后直接用就行)。
1.写LED部分
LED.c
建议在工程文件夹中新建hardware文件夹,以后外设部分都放在hardware里,如图所示:
先上代码:LED.c
#include "stm32f10x.h" // Device header
void LED_Init()
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz ;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_SetBits(GPIOA, GPIO_Pin_1 | GPIO_Pin_2); //上电时保持LED是灭的
}
void LED1_ON(void)
{
GPIO_ResetBits(GPIOA,GPIO_Pin_1); //灯亮
}
void LED1_OFF(void)
{
GPIO_SetBits(GPIOA,GPIO_Pin_1); //灯灭
}
void LED1_turn(void) //按键按下 如果输出0,置1,否则置0,这样就实现了电平翻转,即GPIO_ReadOutputDataBit函数的意义
{
if(GPIO_ReadOutputDataBit(GPIOB,GPIO_Pin_1)==0)
{
GPIO_SetBits(GPIOA,GPIO_Pin_1);
}
else
{
GPIO_ResetBits(GPIOA,GPIO_Pin_1);
}
}
void LED2_ON(void)
{
GPIO_ResetBits(GPIOA,GPIO_Pin_2);
}
void LED2_OFF(void)
{
GPIO_SetBits(GPIOA,GPIO_Pin_2);
}
void LED2_turn(void)
{
if(GPIO_ReadOutputDataBit(GPIOB,GPIO_Pin_2)==0)
{
GPIO_SetBits(GPIOA,GPIO_Pin_2);
}
else
{
GPIO_ResetBits(GPIOA,GPIO_Pin_2);
}
}
在LED模块的GPIO初始化中,要先给LED高电平,保证上电时LED是熄灭状态。
2.简要介绍GPIO_ReadOutputDataBit函数
在LED反转电平函数中涉及到了GPIO_ReadOutputDataBit函数,所以下边简单介绍一下该函数:
该函数作用为,读取指定端口管脚的输出
先看函数定义:
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
uint8_t bitstatus = 0x00;
/* Check the parameters */
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
assert_param(IS_GET_GPIO_PIN(GPIO_Pin));
if ((GPIOx->ODR & GPIO_Pin) != (uint32_t)Bit_RESET)
{
bitstatus = (uint8_t)Bit_SET;
}
else
{
bitstatus = (uint8_t)Bit_RESET;
}
return bitstatus;
}
可以看到,该函数和之前SetBits等函数用法并无不同,在此时LED.c中表示:按键按下时,如果输出0,置1,否则置0,这样就实现了电平翻转,这也就是此刻用GPIO_ReadOutputDataBit函数的意义。
LED.h
头文件的定义和51并无不同:
上代码:
#ifndef __LED_H__
#define __LED_H__
void LED_Init(void);
void LED1_ON(void);
void LED1_OFF(void);
void LED2_ON(void);
void LED2_OFF(void);
void LED1_turn(void);
void LED2_turn(void);
#endif
3.写按键部分
key.c
上代码:
#include "stm32f10x.h" // Device header
#include "Delay.h"
//按键的初始化
void key_Init()
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitTypeDef GPIO_InitStrucTure;
GPIO_InitStrucTure.GPIO_Mode = GPIO_Mode_IPU; //按键,用上拉
GPIO_InitStrucTure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_11;
GPIO_InitStrucTure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStrucTure);
}
//按键检测
uint8_t key_GetNum(void)
{
uint8_t key_Num = 0;
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)==0) //按键按下
{
Delay_ms(20); //按键消抖
while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)==0);//检测松手,因为按键按下且松手后才有动作
Delay_ms(20); //按键消抖
key_Num = 1;
}
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11)==0)
{
Delay_ms(20); //按键消抖
while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11)==0);
Delay_ms(20); //按键消抖
key_Num = 2;
}
return key_Num;
}
因为涉及到两个按键,所以在写按键初始化时,结构体子项GPIO_PIN的值为GPIO_Pin_1 | GPIO_Pin_11,采用上拉输入的模式,按键部分也和51一样注意按键消抖的问题,这样按键部分就写完了。
最后,在主函数中调用即可。
main.c
#include "stm32f10x.h" // Device header
#include "LED.h"
#include "key.h"
#include "Delay.h"
uint8_t key_Num;
int main(void)
{
LED_Init();
key_Init();
while(1)
{
key_Num=key_GetNum();
if(key_Num==1)
{
LED1_turn();
}
if(key_Num==2)
{
LED2_turn();
}
}
}