一、前言
由于我在使用LCD通过软件模拟SPI来启动的时候用到背光控制,用到PE12引脚中有一个TIM1_CH3N的定时器复用功能,在此之前还没深入了解到这个互补通道的功能,所以就浅浅尝试了一下。下面是一个定时器的简单的理解和初始化配置知识点。(博主也还不是很懂互补通道的知识,只是简单的概括一下)
定时器的理解
在 STM32F407 系列微控制器中,定时器分为通用定时器和高级控制定时器,其中TIM1、TIM8为STM32F407 中功能最丰富的定时器,即高级控制定时器。高级控制定时器(TIM1和TIM8)和通用定时器在基本定时器的基础上引入了外部引脚,可以输入捕获和输出比较功能。高级控制定时器比通用定时器增加了可编程死区互补输出、 重复计数器、带刹车(断路)功能。高级控制定时器时基单元包含一个16位自动重载计数器ARR,一个16位的计数器CNT,可向上/下计数,一个16位可编程预分频器PSC,预分频器时钟源有多种可选, 有内部的时钟、外部时钟。还有一个8位的重复计数器RCR,这样最高可实现40位的可编程定时。下表为高级定时器和通用定时器的IO分配表(参考STM32ZGT6)

二.高级控制定时器(不开启互补通道)
对于没开启互补通道,我将会采用定时器1通道3(TIM1_CH3)进行展开初始化配置

TIM1的时钟为APB2时钟的两倍即168M。
配置步骤:
1.使能TIM1时钟、硬件GPIO时钟。
//使能TIM1和PE端口时钟(TIM1属于APB2,PE属于AHB1)
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
2.配置PE13为TIM1_CH3复用模式
// 2. 配置PE13为TIM1_CH3复用模式(AF_TIM1)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; // PE13引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; // 复用模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; // 推挽输出(驱动背光)
GPIO_InitStructure.GPIO_Speed = GPIO_High_Speed; // 高速模式
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; // 无上下拉(背光电路通常有下拉)
GPIO_Init(GPIOE, &GPIO_InitStructure);
// 3. 绑定PE13到TIM1_CH3
GPIO_PinAFConfig(GPIOE, GPIO_PinSource13, GPIO_AF_TIM1);
3.配置定时器1相关参数(时基参数)包括预分频值(PSC)、自动重装载值(ARR)和计数模式。
//配置TIM1输出的频率
TIM_TimeBaseStructure.TIM_Period = 10000/200-1;//中断频率演变为PWM输出的频率
TIM_TimeBaseStructure.TIM_Prescaler = 16800-1; //要进行16800的分频
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数模式
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
4.PWM模式配置
//配置TIM1的工作模式:PWM1模式
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//打开脉冲输出
TIM_OCInitStructure.TIM_Pulse = 10; // PWM频率 100 周期 1/100 = 10ms
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//定时器计数值(CNT)<比较值(CCR),通道输出高电平;定时器计数值(CNT)≥比较值(CCR),通道输出低电平
5.配置TIM1通道
TIM_OC3Init(TIM1, &TIM_OCInitStructure);
6.使能TIM1、使能TIM1的PWM输出
/* TIM1使能计数 */
TIM_Cmd(TIM1, ENABLE);
TIM_CtrlPWMOutputs(TIM1, ENABLE);
三、高级控制定时器(开启互补通道)
对于开启互补通道,我将会采用TIM1_CH3N进行展开初始化配置
在进行配置前,我们先了解什么是互补输出?在stm32中,互补输出是指定定时器的两个通道之间存在一种互补关系。互补意思就是,相反。在互补输出中,若一个通道输出信号为高电平,则其互补通道将输出低电平,反之亦然。
《互补通道图》先欠着
那什么又是死区控制呢?STM32中高级定时器都带有死区控制功能,一般来说死区控制主要用于马达、变频器等控制。(图片来源网络)

死区时间计算:
假设STM32F407的高级定时器1的时钟为168MHz,设置tDTS=1/168 us。死区时间计算是分段计算,每段公式不一样。

对于互补输出和死区控制知识就先只能列出一点点(博主也还是不怎么懂)。
下面进行代码的配置:
1.配置硬件时钟:
// 1. 使能TIM1和PE端口时钟(TIM1属于APB2,PE属于AHB1)
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
2.配置PE12为TIM1_CH3N复用模式
// 2. 配置PE12为TIM1_CH3N复用模式(AF_TIM1)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; // PE12引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; // 复用模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; // 推挽输出(驱动背光)
GPIO_InitStructure.GPIO_Speed = GPIO_High_Speed; // 高速模式
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; // 无上下拉(背光电路通常有下拉)
GPIO_Init(GPIOE, &GPIO_InitStructure);
3.绑定PE12到TIM1_CH3N
// 3. 绑定PE12到TIM1_CH3N
GPIO_PinAFConfig(GPIOE, GPIO_PinSource12, GPIO_AF_TIM1);
4.配置定时器1相关参数(时基参数)
TIM_TimeBaseStructure.TIM_Period = 99; // 周期=99(计数0-99,共100个单位)
TIM_TimeBaseStructure.TIM_Prescaler = 16799; // 分频=16799(168MHz/(16799+1)=10kHz)
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // 向上计数
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; // 时钟不分频
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; // 高级定时器特有,无重复计数
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
5.配置TIM1_CH3N互补PWM(仅用互补输出,主输出CH3禁用)
// 5. 配置TIM1_CH3N互补PWM(仅用互补输出,主输出CH3禁用)
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; // PWM1:CNT<CCR时输出高
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable; // 禁用主输出CH3
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; // 使能互补输出CH3N
TIM_OCInitStructure.TIM_Pulse = 50; // 初始占空比50%(CCR=50)
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; // 主输出极性(禁用可忽略)
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High; // 互补输出高电平有效(匹配背光驱动)
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset; // 主输出空闲重置
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset; // 互补输出空闲重置
TIM_OC3Init(TIM1, &TIM_OCInitStructure); // 配置通道3(对应CH3N)
6. 配置死区时间
// 6. 配置死区时间(防止硬件短路,背光单路输出可设小值)
TIM_BDTRInitStructure.TIM_DeadTime = 10; // 死区=10(10*100ns=1μs,无H桥可设0)
TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1; // 锁定配置,防止误修改
TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Disable; // 关闭OSSI模式
TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Disable; // 关闭OSSR模式
TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure);
7.使能TIM1和PWM输出
// 7. 使能TIM1和PWM输出(高级定时器必须调用TIM_CtrlPWMOutputs)
TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable); // 使能CCR3预装载
TIM_ARRPreloadConfig(TIM1, ENABLE); // 使能ARR预装载
TIM_Cmd(TIM1, ENABLE); // 启动TIM1
TIM_CtrlPWMOutputs(TIM1, ENABLE); // 关键:使能PWM输出(含互补输出)
总结
通过软件模拟spi来驱动LCD,了解到定时器的互补输出来控制背光灯的PWM控制,也了解了一个新的知识(浅浅的了解一下,还没完全弄明白)。不仅弄明白了如何软件模拟spi,还会看一点点时序图,希望我会有更大的进步,希望大家也能学到新的知识~(下篇应该会出如何通过软件模拟spi)到这里完美撒花啦~谢谢大家!如果有错误的地方多多支出~
5644

被折叠的 条评论
为什么被折叠?



