基于B站江科大的STM32教程学习STM32,这篇文章作为学习过程中记录知识点的复盘总结,因此只记录一些对于我个人来说比较关键的点。
一、GPIO输入
GPIO(General Purpose Input Output)通用输入输出口
可配置为8种输入输出模式
引脚电平:0V~3.3V,部分引脚可容忍5V
输出模式下可控制端口输出高低电平,用以驱动LED、控制蜂鸣器、模拟通信协议输出时序等
输入模式下可读取端口的高低电平或电压,用于读取按键输入、外接模块电平信号输入、ADC电压采集、模拟通信协议接收数据等。
最常用的是推挽输出模式。
1.1蜂鸣器
有源蜂鸣器:内部自带振荡源,将正负极接上直流电压即可持续发声,频率固定
无源蜂鸣器:内部不带振荡源,需要控制器提供振荡脉冲才可发声,调整提供振荡脉冲的频率,可发出不同频率的声音
流水灯
#include "stm32f10x.h"//STM32核心头文件
#include "Delay.h"//延时函数头文件
/*主函数 */
int main(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//开启时钟 启用APB2总线上的外设时钟 GPIOA挂载在APB2上
/*GPIO初始化配置 */
GPIO_InitTypeDef GPIO_IntitStructure;//定义GPIO初始化结构体
GPIO_IntitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//配置为推挽输出模式
GPIO_IntitStructure.GPIO_Pin = GPIO_Pin_All;//配置所有引脚从PA0~PA15
GPIO_IntitStructure.GPIO_Speed = GPIO_Speed_50MHz;//配置GPIO输出速度为50MHz
GPIO_Init(GPIOA, &GPIO_IntitStructure); //初始化GPIOA
while(1)
{
GPIO_Write(GPIOA, ~0x0001); //0000 0000 0000 0001
Delay_ms(500);
GPIO_Write(GPIOA, ~0x0002); //0000 0000 0000 0010
Delay_ms(500);
GPIO_Write(GPIOA, ~0x0004); //0000 0000 0000 0100
Delay_ms(500);
GPIO_Write(GPIOA, ~0x0008); //0000 0000 0000 1000
Delay_ms(500);
GPIO_Write(GPIOA, ~0x0010); //0000 0000 0001 0000
Delay_ms(500);
GPIO_Write(GPIOA, ~0x0020); //0000 0000 0010 0000
Delay_ms(500);
GPIO_Write(GPIOA, ~0x0040); //0000 0000 0100 0000
Delay_ms(500);
GPIO_Write(GPIOA, ~0x0080); //0000 0000 1000 0000
Delay_ms(500);
// for (uint8_t i = 0; i < 8; i++) {
// GPIO_Write(GPIOA, ~(1 << i)); // 依次左移1,实现PA0~PA7轮流低电平
// Delay_ms(500);
//}
}
}
关键点总结:开启时钟,初始化GPIO配置输出模式为推挽输出,控制引脚输出高低电平
蜂鸣器
#include "stm32f10x.h"//STM32核心头文件
#include "Delay.h"//延时函数头文件
int main(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//开启时钟 启用APB2总线上的外设时钟 GPIOB挂载在APB2上
GPIO_InitTypeDef GPIO_IntitStructure;//定义GPIO初始化结构体
GPIO_IntitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//配置为推挽输出模式
GPIO_IntitStructure.GPIO_Pin = GPIO_Pin_12;//配置引脚PA12
GPIO_IntitStructure.GPIO_Speed = GPIO_Speed_50MHz;//配置GPIO输出速度为50MHz
GPIO_Init(GPIOB, &GPIO_IntitStructure);//初始化GPIOB
while(1)
{
GPIO_ResetBits(GPIOB,GPIO_Pin_12);//拉低PB12输出低电平
Delay_ms(100);
GPIO_SetBits(GPIOB,GPIO_Pin_12);//拉高PB12输出高店
Delay_ms(100);
GPIO_ResetBits(GPIOB,GPIO_Pin_12);
Delay_ms(100);
GPIO_SetBits(GPIOB,GPIO_Pin_12);
Delay_ms(700);
}
}
关键点总结:同流水灯一样,首先是开启时钟,然后初始化GPIOB并设置输出模式为推挽输出,然后控制引脚输出高低电平
OLED屏
初始化OLED函数,调用OLED函数库显示文本或者数字。
中断系统
EXTI外部中断
我们通过对射式红外传感器计次和旋转编码器计次来学习EXTI外部中断。
《参考上方EXTI基本结构图》
通过外设连接GPIO输入信号(中断源)至AFIO配置选择中断引脚,连接EXTI并配置EXTI中断的触发条件,配置NVIC优先级使能中断通道。封装EXTI中断服务函数来执行红外传感器被遮挡次数的计次。
/*CountSensor.c*/
#include "stm32f10x.h" // Device header
uint16_t CountSensor_Count;// 定义计数器变量,用于记录传感器触发次数
void CountSensor_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//开启GPIOB时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//开启AFIO时钟
/*GPIOB初始化*/
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);//AFIO外部中断引脚配置
/*配置EXTI 设置中断的触发条件*/
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_InitStructure.EXTI_Line = EXTI_Line14;//选择第14号中断线
EXTI_InitStructure.EXTI_LineCmd = ENABLE;//中断使能
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;;//设为中断模式
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发
EXTI_Init(&EXTI_InitStructure);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //配置NVIC优先级分组为组2
/*配置EXTI15_10中的中断通道*/
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;//选择EXTI15-10中断
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//抢占优先级1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//子优先级1
NVIC_Init(&NVIC_InitStructure);
}
/*获取计数器当前值的函数*/
uint16_t CountSensor_Get(void)
{
return CountSensor_Count;
}
/*EXTI15_10中断服务函数*/
void EXTI15_10_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line14) == SET)//检测是否是EXTI14触发的中断
{
CountSensor_Count ++;//计数器加1
EXTI_ClearITPendingBit(EXTI_Line14);//清除EXTI14中断标志位
}
}
/*Main.c*/
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "CountSensor.h"
int main(void)
{
OLED_Init();
CountSensor_Init();
OLED_ShowString(1, 1,"Count:");
while(1)
{
OLED_ShowNum(1, 7, CountSensor_Get(),5);
}
}