STM32F1常用外设介绍(超详细35000字介绍)
Posted 计算机小混子
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了STM32F1常用外设介绍(超详细35000字介绍)相关的知识,希望对你有一定的参考价值。
STM32学习笔记
GPIO配置步骤
步骤:
-
第一步,使用RCC开启GPIO的时钟
-
第二步,使用GPIO_Init()函数初始化GPIO
-
第三步,使用输出或者输入的函数控制GPIO口
常用的RCC开启始终函数
void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph,FunctionalState NewState);
void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph,FunctionalState NewState);
void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph,FunctionalState NewState);
参数1:选择外设,参数2:使能或者失能
常用的GPIO函数
复位GPIO外设函数
void GPIO_DeInit(GPIO_TypeDef* GPIOx);
复位AFIO外设函数
void GPIO_AFIODeInit(void);
初始化GPIO口函数
用结构体的参数来初始化GPIO口,先定义一个结构体变量,然后把再给结构体赋值,最后调用此函数,函数内部会自动读取结构体的值,然后自动把外设的各个参数配置好
void GPIO_Init(GPIO_TypeDef* GPIOx,GPIO_InitTypedef* GPIO_InitStruct);
给GPIO结构体变量赋一个默认值函数
void GPIO_StructInit(GPIO_InitTypedef* GPIO_InitTypedef);
GPIO的输出函数
把制定的端口设置为高电平:函数
void GPIO_SetBits(GPIO_InitTypedef* GPIOx,uint16_t GPIO_Pin);
把指定的端口设置为低电平
void GPIO_ResetBits(GPIO_InitTypedef* GPIOx,uint16_t GPIO_Pin);
对根据第三个参数的值来设置电平
void GPIO_WriteBit(GPIO_InitTypedef* GPIOx,uint16_t GPIO_Pin,BitAction BitVal);
对GPIOx 16个端口同时进行写入操作:
void GPIO_Write(GPIO_InitTypedef* GPIOx,uint16_t PortVal);
在推挽输出模式下,高低电平都具有驱动能力,开漏输出模式的高电平是没有驱动能力的,开漏输出模式的低电平具有驱动能力
#define的新名字在左边,并且可以给任何变量换名字,而typedef只能给变量换名字,新名字在右边
GPIO的输入函数
读取输入数据寄存器某个端口的输入值,返回值是高低电平函数
uint8_t GPIO_ReadInputDataBit(GPIO_InitTypedef* GPIOx,uint16_t GPIO_Pin);
读取GPIO的每一位的值,返回值是16位的数据,每一位代表一个端口值
uint16_t GPIO_ReadInputData(GPIO_InitTypedef* GPIOx);
读取输出数据寄存器的某一位
uint8_t GPIO_ReadOutputDataBit(GPIO_InitTypedef* GPIOx,uint16_t GPIO_Pin);
读取整个输出寄存器
uint16_t GPIO_ReadOutputData(GPIO_InitTypedef* GPIOx);
程序示例
void LED_Init(void)
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//开启GPIO时钟
GPIO_InitTypeDef GPIO_InitStructure;//定义GPIO结构体
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);//置高电平
void LED1_ON(void)
GPIO_ResetBits(GPIOA, GPIO_Pin_1);
void LED1_OFF(void)
GPIO_SetBits(GPIOA, GPIO_Pin_1);
void LED1_Turn(void)
if (GPIO_ReadOutputDataBit(GPIOA, 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(GPIOA, GPIO_Pin_2) == 0)
GPIO_SetBits(GPIOA, GPIO_Pin_2);
else
GPIO_ResetBits(GPIOA, GPIO_Pin_2);
中断
-
中断:在主程序运行过程中,出现了特定的中断触发条件(中断源),使得CPU暂停当前正在运行的程序,转而去处理中断程序,处理完成后又返回原来被暂停的位置继续运行
-
中断优先级:当有多个中断源同时申请中断时,CPU会根据中断源的轻重缓急进行裁决,优先响应更加紧急的中断源
-
中断嵌套:当一个中断程序正在运行时,又有新的更高优先级的中断源申请中断,CPU再次暂停当前的中断程序,转而去处理新的中断程序,处理完后依次进行返回
-
NVIC:NVIC的中断优先级由优先级寄存器的4位(0~15)决定,这4位可以进行切分,分为高n位的抢占优先级和低4-n位的响应优先级
-
抢占优先级高的可以进行中断嵌套,响应优先级高的可以进行优先排队,抢占优先级和响应优先级均相同的按中断号排队
-
EXTI:(Extern Interrupt)外部中断
-
EXTI可以检测指定GPIO口的电平信号,当其指定的GPIO口产生电平变化时,EXTI将立即向NVIC发出中断申请,经过NVIC裁决后即可中断CPU主程序,使CPU执行EXTI对应的中断程序
-
支持的触发方式:上升沿/下降沿/双边沿/软件触发
-
支持的GPIO口:所有GPIO口,但相同的Pin不能同时触发中断
-
通道数:16个GPIO_Pin,外加PVD输出、RTC闹钟、USB唤醒、以太网唤醒
-
触发响应方式:中断响应/事件响应
AFIO选择中断引脚,外部中断的9-5,15-10会触发同一个中断函数,再根据标志位来区分到底是哪个中断进来的
配置数据选择器,只有一个Pin接到EXTI
在STM32中AFIO主要完成两个任务:复用功能引脚重映射、中断引脚选择
或、与、非门
EXTI配置步骤
- 第一步,配置RCC,把设计到的外设时钟都打开
- 第二步,配置GPIO,选择端口为输入模式
- 第三步,配置AFIO,选择使用的一路GPIO,连接到后面的EXTI
- 第四步,配置EXTI,选择边沿触发方式,选择触发响应方式
- 第五步,配置NVIC,给中断选择一个合适的优先级
EXTI和NVIC时钟默认是打开的,NVIC是内核的外设,内核的外设都不需要开启时钟,RCC管的都是内核外的外设
复位AFIO外设
void GPIO_AFIODeInit(void);
锁定GPIO配置函数
锁定引脚的配置,防止意外更改
void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin);
配置AFIO的事件输出功能函数
void GPIO_EventOutputConfig(uint8_t GPIO_PortSource,uint8_t GPIO_PinSource);
void GPIO_EventOutputCmd(FunctionalState NewState);
配置引脚重映射函数
void GPIO_PinRemapConfig(uint32_t GPIO_Remap,FunctionalState NewState);
配置AFIO的数据选择器
选择想使用的中断引脚函数
void GPIO_EXTILineConfig(uint8_t GPIO_PortSource,uint8_t GPIO_PinSource);
恢复上电默认的状态函数
void EXTI_DeInit(void);
根据结构体配置EXTI外设函数
void EXTI_Init(EXTI_InitTypedef* EXTI_InitStruct);
给传入的结构体参数赋一个默认值函数
void EXTI_StructInit(EXTI_InitTypedef* EXTI_InitStruct);
软件触发外部中断函数
参数给一个中断线,就能软件触发一次这个外部中断函数
void EXTI_GenerateSWInterrupt(uint32_t EXTI_Line);
在外设运行的时候会产生一些状态标志位,例如:外部中断来了,挂起寄存器会置一个标志位,标志位放在状态寄存器,
当程序想看这些标志位
获取指定的标志位函数
FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line);
对置1的标志位进行清除函数
void EXTI_ClearFlag(uint32_t EXTI_Line);
在中断函数中获取标志位函数
ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);
清除中断挂起标志位函数
void EXTI_ClearITPendingBit(uint32_t EXTI_Line);
中断分组函数
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);
根据结构体里面的参数初始化NVIC函数
void NVIC_Init(NVIC_InitTypedef* NVIC_InitStruct);
设置中断向量表函数
NVIC_SetVectorTable函数的功能是设置向量表的位置和偏移。其中输入参数中,对于32位的OFFSET向量表基地址的偏移量对于FLASH,参数值必须高于0x08000100,对于RAM必须高于0X100.
void NVIC_SetVectorTable(uint8_t NVIC_VectTab,uint32_t Offset);
系统低功耗配置函数
void NVIC_SystemLPConfig(uint8_t LowPowerMode,FunctionalState NewState)
中断函数要简短快速,不要在中断中执行Delay
程序示例
int16_t Encoder_Count;
void Encoder_Init(void)
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//开启GPIO时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);//开启AFIO时钟
GPIO_InitTypeDef GPIO_InitStructure;//定义初始化结构体
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;//开启引脚
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//设置响应速度
GPIO_Init(GPIOB, &GPIO_InitStructure);//配置参数
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0);//选择中断线路
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource1);
EXTI_InitTypeDef EXTI_InitStructure;//定义外部中断结构体
EXTI_InitStructure.EXTI_Line = EXTI_Line0 | EXTI_Line1;//设置中断线
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_InitTypeDef NVIC_InitStructure;//定义NVIC结构体
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;//设置中断通道
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//通道使能
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//响应优先级
NVIC_Init(&NVIC_InitStructure);//写入参数
NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;//设置中断通道
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//通道使能
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;//响应优先级
NVIC_Init(&NVIC_InitStructure);//写入参数
int16_t Encoder_Get(void)
int16_t Temp;
Temp = Encoder_Count;
Encoder_Count = 0;
return Temp;
void EXTI0_IRQHandler(void)//线路0中断函数
if (EXTI_GetITStatus(EXTI_Line0) == SET)//判断中断挂起位
/*如果出现数据乱跳的现象,可再次判断引脚电平,以避免抖动*/
if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 0)//读取输入高低电平
if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)
Encoder_Count --;
EXTI_ClearITPendingBit(EXTI_Line0);//清除中断挂起标志位
void EXTI1_IRQHandler(void)//线路1中断函数
if (EXTI_GetITStatus(EXTI_Line1) == SET)//判断标志位
/*如果出现数据乱跳的现象,可再次判断引脚电平,以避免抖动*/
if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)//读取输入高低电平
if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 0)
Encoder_Count ++;
EXTI_ClearITPendingBit(EXTI_Line1);//清除中断挂起标志位
定时器
-
TIM(Timer)定时器
-
定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断
-
16位计数器、预分频、自动重装寄存器的时基单元,在72M计数时钟下可以实现最大59.65s的定时
-
不仅具备基本的定时器中断功能,而且还包含内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等多种功能
-
根据复杂度和应用场景分为了高级定时器、通用定时器、基本定时器三种类型
-
对72MHz计72个数就是1MHz,也就是1us的时间,计72000个数,那就是1KHz也就是1ms的时间
-
59.65s =65536 X 65536X 1/72M/(中断频率倒数),
-
STM32的定时器支持级联的模式:一个定时器的输出当做另一个定时器的输入最大定时时间就是59.65s X 65536 X 65536
- 预分频器(PSC):对输入的基准频率提前进行一个分频的操作
- 实际分频系数 = 预分频器的值 + 1,最大可以写65535即65536分频
- 计数器(CNT):也是16位,值可以从0~65535,当计数器的值自增(自减)到目标值时,产生中断,完成定时
- 自动重装寄存器():也是16位当计数值等于自动重装值时,就是计时的时间到了,就会产生一个中断信号,并且清零计数器,计数器自动开始下一次的计数计时,计数值等于自动重装值的中断一般叫做“更新中断”,此更新中断就会通往NVIC,再配置好NVIC的定时器通道,定时器上的更新中断就会得到CPU的响应了,对应的事件叫做“更新事件”,更新事件不会触发中断,但可以触发内部其他电路的工作
- 从基准时钟,到预分频器,再到计数器,计数器自增,同时不断地与自动重装寄存器进行比较,计数器和自动重装寄存器的值相等时,即计时时间到,这时会产生一个更新中断和更新事件,CPU响应更新中断,就完成了定时中断的任务了。
主从触发模式
使用定时器的主模式,可以把定时器的更新事件映射到触发输出TRGO(Trigger Out)的位置,TRGO直接接到DAC的触发转换引脚上,这样定时器的更新就不需要再通过中断来触发DAC转换了
缓冲寄存器:某个时刻把预分频器由0改成了1,当计数计到一半的时候改变了分频值,这个变化不会立即生效,而是会等到本次计数周期结束时,产生了了更新事件,预分频器的值才会被传递到缓冲寄存器里面去,才会生效。
举个例子来说,如果我们想改变ARR寄存器中的值,但是当前的定时还没有结束,在这时如果未设置影子寄存器,那么设定的值会立即生效。而如果设置了影子寄存器,那么新的值会在当前计数周期结束之后生效。
计数器计数频率:CK_CNT = CK_PSC / (PSC + 1)
计数器溢出频率:CK_CNT_OV = CK_CNT / (ARR + 1) = CK_PSC / (PSC + 1) / (ARR + 1)
开启定时器步骤
- 第一步,RCC开启时钟
- 第二步,选择时基单元的时钟源
- 第三步,配置时基单元
- 第四步,配置输出中断控制,允许更新中断输出到NVIC
- 第五步,配置NVIC,在NVIC中打开定时器中断的通道,并分配一个优先级
- 第六步,运行控制
- 第七步,使能计数器
定时器常用的库函数
恢复缺省配置函数
void TIM_DeInit(TIM_TypeDef* TIMx);
时基单元初始化函数
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);
选择TIx捕获通道的时钟函数
void TIM_TIxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_TIxExternalCLKSource,uint16_t TIM_ICPolarity, uint16_t ICFilter);
参数3:输入的极性 参数4:滤波器
选择ETR通过外部时钟模式1输入的时钟函数
void TIM_ETRClockMode1Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter);
参数2:预分频器 参数3:输入的极性 参数4:滤波器
选择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);
参数3:写入的模式,在更新事件生效,或者在写入后,手动产生一个更新事件,让这个值立刻生效
改变计数器的计数模式函数
void TIM_CounterModeConfig(TIM_TypeDef* TIMx, uint16_t TIM_CounterMode);
自动重装器预装功能配置函数
TIM_ARRPreloadConfig设置为DISABLE 和ENABLE的问题,他的作用只是允许或禁止在定时器工作时向ARR的缓冲器中写入新值,以便在更新事件发生时载入覆盖以前的值。
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);
使用跨文件的变量: extern声明变量,告诉编译器,有Num这个变量在别的文件中定义了,在此文件中也可以使用
程序示例:
void Timer_Init(void)
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//开启TIM2时钟
TIM_InternalClockConfig(TIM2);//使用内部时钟
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//定义时基单元结构体
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;//设置不分频
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//设置向上计数
TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1;//ARR自动重装值
TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;//PSC不分频
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//重复计数器的值,高级定时器特有
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);//写入参数
TIM_ClearFlag(TIM2, TIM_FLAG_Update);//清除更新标志位
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);//中断输出
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断优先级分组
NVIC_InitTypeDef NVIC_InitStructure;//NVIC结构体
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;//定时器通道
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;//抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//响应优先级
NVIC_Init(&NVIC_InitStructure);//写入参数
TIM_Cmd(TIM2, ENABLE);//开启定时器
/*
void TIM2_IRQHandler(void)
if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)//判断是否中断溢出
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);//清除中断标志位
*/
输出比较
- OC(Output Compare)输出比较
- 输出比较可以通过比较CNT和CCR寄存器值的关系,来对输出电平进行置1、置0或翻转的操作,用于输出一定频率和占空比的PWM波形
- 每个高级定时器和通用定时器都拥有4个输出比较通道
- 高级定时器的前3个通道额外拥有死去生成和互补输出的功能
输出比较常用的函数
配置输出比较函数
void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_OC3Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_OC4Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
给输出比较结构体赋一个默认值函数
void TIM_OCStructInit(TIM_OCInitTypeDef* TIM_OCInitStruct);
配置强制输出模式函数
在运行中想要暂停输出波形并且强制输出高或者低电平,强制输出高电平和设置百分百占空比一样,强制输出低电平和设置百分百低电平是一样的。
void TIM_ForcedOC1Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
void TIM_ForcedOC2Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
void TIM_ForcedOC3Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
void TIM_ForcedOC4Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
配置CCR寄存器的预装功能函数
预装功能就是影子寄存器:写入的值不会立即生效,而是在更新事件才会生效
void TIM_OC1PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
void TIM_OC2PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
void TIM_OC3PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
void TIM_OC4PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
配置快速使能函数
void TIM_OC1FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);
void TIM_OC2FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);
void TIM_OC3FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);
void TIM_OC4FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);
外部事件时清除REF信号函数
void TIM_ClearOC1Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);
void TIM_ClearOC2Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);
void TIM_ClearOC3Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);
void TIM_ClearOC4Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);
单独设置输出比较的极性函数
带N的是高级定时器里互补通道的配置函数
void TIM_OC1PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);
void TIM_OC1NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);
void TIM_OC2PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);
void TIM_OC2NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);
void TIM_OC3PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);
void TIM_OC3NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);
void TIM_OC4PolarityConfigstm32系列单片机都有哪些外设接口模块