1.按键控制LED
模块化编程:对于驱动代码来说,会把它封装起来,单独放在另外的.c和.h文件。
Hardware文件夹:用来存放硬件驱动
Hardware文件里的LED.C用来存放驱动程序的主体代码
LED.h用来存放这个驱动程序可以对外提供的函数或变量的声明
LED.h里面要添加一个防止头文件重复包含的代码
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);//读取整个输出寄存器的
现象:原本灯不亮,按下按键灯亮,在按一下熄灭
main.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "LED.h"
#include "Key.h"
uint8_t KeyNum; //全局变量
int main(void)
{
LED_Init(); //在主函数直接调用LED_Init,完成了LED的初始化
Key_Init();
while (1)
{
KeyNum = Key_GetNum(); //不断读取键码值,放在KeyNum变量里
if (KeyNum ==1) //按键1按下
{
LED1_Turn(); //点亮LED1
}
if (KeyNum ==2) //按键2按下
{
LED2_Turn(); //熄灭LED
}
Delay_ms(500);
LED1_OFF();
LED2_ON();
Delay_ms(500);
}
}
LED.h
#ifndef __LED_H
#define __LED_H
void LED_Init(void);//这就是对模块外部声明,这个函数可以被外部调用的函数
void LED1_ON(void);
void LED1_OFF(void);
void LED1_Turn(void); //调用这个函数,LED1的状态取反 按键按下,LED状态取反
void LED2_ON(void);
void LED2_OFF(void);
void LED2_Turn(void); //调用这个函数,LED1的状态取反 按键按下,LED2状态取反
#endif
LED.C
#include "stm32f10x.h" // Device header
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_1 |GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA ,&GPIO_InitStructure);
//我们只需要调用LED_Init函数,LED的两个GPIO口就可以直接初始化完成了,这个函数需要被外部引用的,需要复制函数的第一行
GPIO_SetBits(GPIOA ,GPIO_Pin_1 |GPIO_Pin_2); //这样初始化后,不操作LED,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) //调用这个函数,LED1的状态取反 按键按下,LED状态取反
{
if (GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_1) == 0) //读取当前端口输出状态,如PA1输出寄存器为0
{
GPIO_SetBits(GPIOA ,GPIO_Pin_1);//把PA1置1
}
else
{
GPIO_ResetBits(GPIOA ,GPIO_Pin_1);//否则置0
}
}
void LED2_ON(void)
{
GPIO_ResetBits (GPIOA ,GPIO_Pin_2 );
}
void LED2_OFF(void)
{
GPIO_SetBits (GPIOA ,GPIO_Pin_2 );
}
void LED2_Turn(void) //调用这个函数,LED1的状态取反 按键按下,LED2状态取反
{
if (GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_2) == 0) //读取当前端口输出状态,如PA2输出寄存器为0
{
GPIO_SetBits(GPIOA ,GPIO_Pin_2);//把PA2置1
}
else
{
GPIO_ResetBits(GPIOA ,GPIO_Pin_2);//否则置0
}
}
Key.h
#ifndef __KEY_H
#define __KEY_H
void Key_Init(void);
uint8_t Key_GetNum(void);
#endif
Key.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
void Key_Init(void) //将按键的两个端口设置为上拉输入模式
{
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 ; //按键接在PB1和PB11端口上
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz ;
GPIO_Init(GPIOB,&GPIO_InitStructure);
}
uint8_t Key_GetNum(void) //读取按键值
{
uint8_t KeyNum = 0; //局部变量
if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)//读取PB1端口的值
{
Delay_ms (20); //消抖
while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0); //检测按键松手的情况
Delay_ms (20); //消抖
KeyNum =1;
}
if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == 0)//读取PB11端口的值
{
Delay_ms (20); //消抖
while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == 0); //检测按键松手的情况
Delay_ms (20); //消抖
KeyNum =2; //PB11的建码设置为2
}
return KeyNum ;
}
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);
}
}
2.光敏传感器控制蜂鸣器
蜂鸣器的I/O口接PB12
光敏传感器DO数字输出端口接PB13
光敏传感器:当遮住光线时,输出指示灯灭,代表输出高电平
松手时,输出指示灯亮,代表输出低电平
Hardware文件里面添加蜂鸣器的驱动文件:Buzzer.c和Buzzer.h
Hardware文件里面添加光敏传感器模块的驱动文件:LightSensor.c和LightSensor.h
main.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "Buzzer.h"
#include "LightSensor.h"
int main(void)
{
Buzzer_Init(); //初始化蜂鸣器
LightSensor_Init (); //初始化光敏传感器
while (1)
{
if (LightSensor_Get() == 1) //光线暗
{
Buzzer_ON (); //蜂鸣器鸣叫
}
else
{
Buzzer_OFF();
}
}
}
Buzzer.c
#include "stm32f10x.h" // Device header
void Buzzer_Init(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(GPIOA ,&GPIO_InitStructure);
//我们只需要调用Buzzer_Init函数,Buzzer的两个GPIO口就可以直接初始化完成了,这个函数需要被外部引用的,需要复制函数的第一行
GPIO_SetBits(GPIOA ,GPIO_Pin_12 ); //这样初始化后,不操作Buzzer就是不叫
}
void Buzzer_ON(void)
{
GPIO_ResetBits (GPIOB ,GPIO_Pin_12 );
}
void Buzzer_OFF(void)
{
GPIO_SetBits (GPIOB ,GPIO_Pin_12 );
}
void Buzzer_Turn(void) //调用这个函数,蜂鸣器的状态取反
{
if (GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_12) == 0) //读取当前端口输出状态,输出寄存器为0
{
GPIO_SetBits(GPIOB ,GPIO_Pin_12);//把置1
}
else
{
GPIO_ResetBits(GPIOB ,GPIO_Pin_12);//否则置0
}
}
Buzzer.h
#ifndef __BUZZER_H
#define __BUZZER_H
void Buzzer_Init(void);
void Buzzer_ON(void);
void Buzzer_OFF(void);
void Buzzer_Turn(void);
#endif
LightSensor.c
#include "stm32f10x.h" // Device header
void LightSensor_Init(void)
{
RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOB,ENABLE ); //开启时钟
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 ; //光敏传感器是PB13
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz ;
GPIO_Init(GPIOB,&GPIO_InitStructure);
}
//返回端口值的函数
uint8_t LightSensor_Get(void)
{
return GPIO_ReadOutputDataBit (GPIOB, GPIO_Pin_13);
}
LightSensor.h
#ifndef __LIGHT_SENSOR_H
#define __LIGHT_SENSOR_H
void LightSensor_Init(void);
uint8_t LightSensor_Get(void);
#endif