输出模式:可控制输出高低电平,驱动LED,蜂鸣器等
输入模式:读取端口的高低电平,外界的信号输入
在STM32中,所有的GPIO均挂载在APB2外设总线,命名为GPIOA,GPIOB。。。
1硬件介绍:LED,蜂鸣器
LED:发光二极管,正向通电点亮,反向通电不亮。
有源蜂鸣器(本实验):内部自带振荡源,将正负极接上直流电压即可持续发声,频率固定。
无源蜂鸣器:内部不带振荡源,需要控制器提供振荡脉冲才可发声,调整提供振荡脉冲的频率,可发出不同频率的声音。注:LED长脚为正极、灯内部小头为正极。本实验的蜂鸣器低电平驱动。
2点灯
#include "stm32f10x.h" // Device header
#include "Delay.h"
int main(void){
// 开启APB2-GPIOA的外设时钟RCC
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// 初始化PA0端口:定义结构体及参数
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//下面是对GPIO端口赋值的常用的四种方式
// GPIO_ResetBits(GPIOA, GPIO_Pin_0);//复位PA0
// GPIO_SetBits(GPIOA, GPIO_Pin_0);//将PA0置1
// GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET);//将PA0清零
// GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);//此函数可以对16位端口同时操作
while(1){
//正常思路
GPIO_ResetBits(GPIOA, GPIO_Pin_0);//复位PA0
Delay_ms(500);
GPIO_SetBits(GPIOA, GPIO_Pin_0);//将PA0置1
Delay_ms(500);
//使用GPIO_WriteBit函数,且强制类型转换
GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)0);//把0类型转换成BitAction枚举类型
Delay_ms(500);
GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)1);
Delay_ms(500);
};
}
(1开启RCC时钟,2复定义结构体,3选择输出模式)
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);
}
}
3流水灯
#include "stm32f10x.h" // Device header
#include "Delay.h"
int main(void){
// 开启APB2-GPIOA的外设时钟RCC
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// 初始化PA的8个端口:定义结构体及参数
GPIO_InitTypeDef GPIO_InitStructure;
//同时定义某几个端口
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_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
while(1){
//使用GPIO_SetBits、GPIO_ResetBits进行赋值,这里仅用于演示“或操作”同时赋值
GPIO_SetBits(GPIOA, 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_ResetBits(GPIOA, GPIO_Pin_0);
// //对指定的端口同时赋值
// GPIO_Write(GPIOA, ~0x01);
Delay_ms(500);
GPIO_Write(GPIOA, ~0x02);
Delay_ms(500);
GPIO_Write(GPIOA, ~0x04);
Delay_ms(500);
GPIO_Write(GPIOA, ~0x08);
Delay_ms(500);
GPIO_Write(GPIOA, ~0x10);
Delay_ms(500);
GPIO_Write(GPIOA, ~0x20);
Delay_ms(500);
GPIO_Write(GPIOA, ~0x40);
Delay_ms(500);
GPIO_Write(GPIOA, ~0x80);
Delay_ms(500);
};
}
4蜂鸣器
#include "stm32f10x.h" // Device header
#include "Delay.h"
int main(void){
// 开启APB2-GPIOB的外设时钟RCC
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
// 初始化PB12端口:定义结构体及参数
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
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(100);
Delay_ms(600);
};
}
5按键
需要进行软件消抖,基本思路是延迟5-10ms,跳过抖动时间范围,一般选择弱上拉设计电路
按键控制流水灯
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "LED.h"
#include "Key.h"
int main(void){
LED_Init();
Key_Init();
while(1){
if(Key_GetNum()==1){LED1_TURN();}
else if(Key_GetNum()==2){LED2_TURN();}
};
}
LED.h
#ifndef __LED_H
#define __LED_H
void LED_Init(void);
void LED1_TURN(void);
void LED2_TURN(void);
#endif
led.c
#include "stm32f10x.h" // Device header
/**
* @brief 初始化PA2、PA1作为两个LED的输出端口
* @param 无
* @retvl 无
*/
void LED_Init(void){
// 开启APB2-GPIOA的外设时钟RCC
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// 初始化PA的输出端口:定义结构体及参数
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_1;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure);
//默认输出为低电平-LED初始不亮
GPIO_SetBits(GPIOA, GPIO_Pin_2 | GPIO_Pin_1);
};
/**
* @brief LED1状态翻转
* @param 无
* @retvl 无
*/
void LED1_TURN(void){
if(GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_1)==1){
GPIO_ResetBits(GPIOA, GPIO_Pin_1);
}else{
GPIO_SetBits(GPIOA, GPIO_Pin_1);
}
}
/**
* @brief LED2状态翻转
* @param 无
* @retvl 无
*/
void LED2_TURN(void){
if(GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_2)==1){
GPIO_ResetBits(GPIOA, GPIO_Pin_2);
}else{
GPIO_SetBits(GPIOA, GPIO_Pin_2);
}
}
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"
/**
* @brief 初始化B11、B1作为按键2、按键1
* @param 无
* @retvl 无
*/
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_11 | GPIO_Pin_1;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//只有输出才有速度等级,但是这里也可以定义
GPIO_Init(GPIOB, &GPIO_InitStructure);
};
/**
* @brief 检测哪个按键已经按下-松开触发
* @param 无
* @retvl 返回按下的按键编号
* @arg 0,1,2
*/
uint8_t Key_GetNum(void){
uint8_t keynum = 0;
if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11)==0){
Delay_ms(20);
while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11)==0);
Delay_ms(20);
keynum = 2;
}
if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1)==0){
Delay_ms(20);
while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1)==0);
Delay_ms(20);
keynum = 1;
}
return keynum;
};
6光敏电阻控制蜂鸣器
main.c
#include "stm32f10x.h" // Device header
#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.h
#ifndef __BUZZER_H
#define __BUZZER_H
void Buzzer_Init(void);
void Buzzer_ON(void);
void Buzzer_OFF(void);
#endif
buzzer.c
#include "stm32f10x.h" // Device header
/**
* @brief 蜂鸣器初始化-PB12推挽输出
*/
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(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB, GPIO_Pin_12);
}
/**
* @brief 蜂鸣器开启-低电平驱动
*/
void Buzzer_ON(void){
GPIO_ResetBits(GPIOB, GPIO_Pin_12);
}
/**
* @brief 蜂鸣器开启-低电平驱动
*/
void Buzzer_OFF(void){
GPIO_SetBits(GPIOB, GPIO_Pin_12);
}
lightsensor.h
#ifndef __LIGHTSENSOR_H
#define __LIGHTSENSOR_H
void LightSensor_Init(void);
uint8_t LightSensor_Get(void);
#endif
lightdendor.c
#include "stm32f10x.h" // Device header
/**
* @brief 光敏传感器初始化-PB13上拉输入
*/
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;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
/**
* @brief 读取光敏传感器的数字输入信号-光强越强分压越低
* @retvl 读取到的数字输入信号0/1
*/
uint8_t LightSensor_Get(void){
return GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_13);
}
c语言知识
#define宏定义: #define ABC 12345
typedef定义:typedef unsigned int uint8_t;