江协科技的stm32视频课程学习笔记 传送门
点亮PC13小灯
// 开启时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; // gpio工作模式
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13; // gpio编号
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; // 工作频率
// 初始化gpio
GPIO_Init(GPIOC, &GPIO_InitStruct);
// 设置特定io口输出低电平。
GPIO_ResetBits(GPIOC, GPIO_Pin_13);
对射式红外传感器计次
清除AFIO相关的配置。
void GPIO_AFIODeInit(void);
锁定某个引脚的配置,防止被意外修改。
void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
引脚重映射(重映射方式, 新的状态)
void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState);
配置AFIO的数据选择器,选择想要的中断引脚。Selects the GPIO pin used as EXTI Line.
void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);
清除EXTI配置,恢复到上电时的状态。
void EXTI_DeInit(void);
根据传入的 EXTI_InitStruct 结构体,初始化EXTI。
void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);
给机构体 EXTI_InitStruct 设置默认值。
void EXTI_StructInit(EXTI_InitTypeDef* EXTI_InitStruct);
软件触发外部中断
void EXTI_GenerateSWInterrupt(uint32_t EXTI_Line);
主程序里查看和清除标志位用EXTI_GetFlagStatus、EXTI_ClearFlag;
中断函数里查看和清除标志位EXTI_GetITStatus、EXTI_ClearITPendingBit。
获取指定中断线状态。Checks whether the specified EXTI line flag is set or not.
FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line);
指定中断线标志位置0。Clears the EXTI's line pending flags.
void EXTI_ClearFlag(uint32_t EXTI_Line);
获取指定中断标志位状态。Checks whether the specified EXTI line is asserted or not.
ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);
清除中断挂起标志位。Clears the EXTI's line pending bits.
void EXTI_ClearITPendingBit(uint32_t EXTI_Line);
配置中断分组,整个程序只配置一次。
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);
根据 NVIC_InitStruct 内容初始化NVIC
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);
设置中断向量表
void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset);
系统低功耗配置
void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState NewState);
关键代码如下。
#include "stm32f10x.h"
#include "CountSensor.h"
uint16_t CountSensor_Count = 0;
void CountSensor_Init(void)
{
// 开启时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
// EXTI、NVIC开启时钟,这两个默认开启,不用体现在代码里,也没法体现在代码里。
// 初始化配置GPIOB 14号引脚。
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPD;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_14;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStruct);
// 配置AFIO
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);
// 配置EXTI
EXTI_InitTypeDef EXTI_InitStruct;
EXTI_InitStruct.EXTI_Line = EXTI_Line14;
EXTI_InitStruct.EXTI_LineCmd = ENABLE;
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_Init(&EXTI_InitStruct);
// 配置NVIC内核外设
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel = EXTI15_10_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&NVIC_InitStruct);
}
uint16_t CountSensor_Get()
{
return CountSensor_Count;
}
void EXTI15_10_IRQHandler(void)
{
if (EXTI_GetITStatus(EXTI_Line14) == SET)
{
CountSensor_Count++;
EXTI_ClearITPendingBit(EXTI_Line14);
}
}
int main(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_ResetBits(GPIOC, GPIO_Pin_13);
OLED_Init();
CountSensor_Init();
OLED_ShowString(1, 1, "Count");
while(1)
{
// Count = ;
OLED_ShowNum(2, 1, CountSensor_Get(), 5);
}
}
定时中断
配置时基单元
void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
结构体变量赋初值
void TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
使能计数器,运行控制。
void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);
使能中断输出信号,中断输出控制。
void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);
选择内部时钟
void TIM_InternalClockConfig(TIM_TypeDef* TIMx);
选择ITRx(其他定时器的时钟)
void TIM_ITRxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);
选择捕获通道的时钟
void TIM_TIxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_TIxExternalCLKSource, uint16_t TIM_ICPolarity, uint16_t ICFilter);
ETR通过外部模式1作为时钟
void TIM_ETRClockMode1Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter);
ETR通过外部模式2作为时钟
void TIM_ETRClockMode2Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter);
配置ETR引脚的预分频器、滤波器等
void TIM_ETRConfig(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter);
单独配置预分频值
void TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler, uint16_t TIM_PSCReloadMode);
单独配置计数器的计数模式
void TIM_CounterModeConfig(TIM_TypeDef* TIMx, uint16_t TIM_CounterMode);
自动重装器预装功能配置。
void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);
给计数器设定一个值
void TIM_SetCounter(TIM_TypeDef* TIMx, uint16_t Counter);
给自动重装器设定一个值
void TIM_SetAutoreload(TIM_TypeDef* TIMx, uint16_t Autoreload);
获取当前计数器的值
uint16_t TIM_GetCounter(TIM_TypeDef* TIMx);
获取当前预分频器的值
uint16_t TIM_GetPrescaler(TIM_TypeDef* TIMx);
关键代码
void Timer_Init(void)
{
// 开启时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
// 配置定时器二的时钟为内部时钟,默认是内部时钟,所以可以不写。
TIM_InternalClockConfig(TIM2);
// 配置定时器的分频、触发方式、溢出值
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStruct.TIM_Period = 10000 - 1;
TIM_TimeBaseInitStruct.TIM_Prescaler = 7200 - 1;
TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0; // 高级定时器才有
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);
// 清除更新事件标志
TIM_ClearFlag(TIM2, TIM_FLAG_Update);
// 配置定时器溢出时触发更新中断,而非其它。
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
// NVIC优先级分组、优先等级、请求中断的通道配置。
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&NVIC_InitStruct);
// 开启定时器。
TIM_Cmd(TIM2, ENABLE);
}
uint16_t Count = 0;
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
{
Count++;
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
}
定时中断——外部时钟
void Timer_Init(void)
{
// 开启时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStruct);
TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 9);
// 配置定时器的分频、触发方式、溢出值
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStruct.TIM_Period = 10 - 1;
TIM_TimeBaseInitStruct.TIM_Prescaler = 1 - 1;
TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);
// 清除更新事件标志
TIM_ClearFlag(TIM2, TIM_FLAG_Update);
// 配置定时器溢出时触发更新中断,而非其它。
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
// NVIC优先级分组、优先等级、请求中断的通道配置。
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&NVIC_InitStruct);
// 开启定时器。
TIM_Cmd(TIM2, ENABLE);
}
uint16_t Timer_GetCounter(void)
{
return TIM_GetCounter(TIM2);
}
TIM输出比较
英文缩写 | 英文全称 | 中文名称 |
---|---|---|
OC | Output Compare | 输出比较 |
IC | Input Capture | 输入捕获 |
CC | Capture/Compare | 输入捕获和输出比较单元 |
输出比较有8种模式,有两种可用于生成PWM波形。