stm32一个stm32定时器外部计数在计数模式下有几路计数通道????

查看: 20143|回复: 11
STM32学习笔记——单定时器四通道输入捕获
以下笔记始发于观海听涛,原创人Apache,转载请说明
输入捕获作为定时器的一个功能,在工业测速上有很大的应用。STM32的一些定时器具有四个外部通道,可利用一个定时器采集外部四路脉冲频率,节约硬件资源和软件代码
如需要测量一个或多个外部方波脉冲频率,频率低于单片机运行频率,可如下操作:(以TIM4为例)
初始化:(省略GPIO配置,将TIM4的四个通道引脚配置为上拉或浮空输入,省略定时器RCC配置,省略中断NVIC配置)
void TIM_Configuration(void)
{
& &
TIM_ICInitTypeDef&&
TIM_ICInitS
TIM_TimeBaseInitTypeDef&&
TIM_TimeBaseS // TIM4 时基
TIM_DeInit(TIM4);
& & TIM_TimeBaseStructure.TIM_Period =
0& && && && && && && && && && && &
//自动重装值
& & TIM_TimeBaseStructure.TIM_Prescaler =
719;& && && && && && && && && && && &&&
//预分频值, 使TIMx_CLK=1MHz
TIM_TimeBaseStructure.TIM_ClockDivision =
TIM_CKD_DIV1;& && && && && && && &
//输入时钟不分频
& & TIM_TimeBaseStructure.TIM_CounterMode =
TIM_CounterMode_Up;& && && && && &&&
//向上计数
& & TIM_TimeBaseInit(TIM4,
&TIM_TimeBaseStructure);
& && && && && && && && && &&&
//TIM4_TimeBase
//&&TIM_ICInitStructure.TIM_ICMode =
TIM_ICMode_ICAP;& && && && && && && && && &&&
//输入捕捉方式
&&TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;//|
TIM_Channel_2;& && &&&//输入通道
&&
TIM_ICInitStructure.TIM_ICPolarity =
TIM_ICPolarity_R& &&&//捕捉上升沿
&&
TIM_ICInitStructure.TIM_ICSelection =
TIM_ICSelection_DirectTI;& & //捕捉中断
&&
TIM_ICInitStructure.TIM_ICPrescaler =
TIM_ICPSC_DIV1;& && & //捕捉不分频
&&
TIM_ICInitStructure.TIM_ICFilter =
0x0;& && && & //捕捉输入不滤波
&&TIM_ICInit(TIM4, &TIM_ICInitStructure);
&&TIM_ICInitStructure.TIM_Channel = TIM_Channel_2 ;//|
TIM_Channel_2;& && &&&//输入通道
&&
TIM_ICInitStructure.TIM_ICPolarity =
TIM_ICPolarity_R& &&&//捕捉上升沿
&&
TIM_ICInitStructure.TIM_ICSelection =
TIM_ICSelection_DirectTI;& & //捕捉中断
&&
TIM_ICInitStructure.TIM_ICPrescaler =
TIM_ICPSC_DIV1;& && & //捕捉不分频
&&
TIM_ICInitStructure.TIM_ICFilter =
0x0;& && && & //捕捉输入不滤波
&&TIM_ICInit(TIM4, &TIM_ICInitStructure);
&&TIM_ICInitStructure.TIM_Channel = TIM_Channel_3 ;//|
TIM_Channel_2;& && &&&//输入通道
&&
TIM_ICInitStructure.TIM_ICPolarity =
TIM_ICPolarity_R& &&&//捕捉上升沿
&&
TIM_ICInitStructure.TIM_ICSelection =
TIM_ICSelection_DirectTI;& & //捕捉中断
&&
TIM_ICInitStructure.TIM_ICPrescaler =
TIM_ICPSC_DIV1;& && & //捕捉不分频
&&
TIM_ICInitStructure.TIM_ICFilter =
0x0;& && && & //捕捉输入不滤波
&&TIM_ICInit(TIM4, &TIM_ICInitStructure);
&&TIM_ICInitStructure.TIM_Channel = TIM_Channel_4 ;//|
TIM_Channel_2;& && &&&//输入通道
&&
TIM_ICInitStructure.TIM_ICPolarity =
TIM_ICPolarity_R& &&&//捕捉上升沿
&&
TIM_ICInitStructure.TIM_ICSelection =
TIM_ICSelection_DirectTI;& & //捕捉中断
&&
TIM_ICInitStructure.TIM_ICPrescaler =
TIM_ICPSC_DIV1;& && & //捕捉不分频
&&
TIM_ICInitStructure.TIM_ICFilter =
0x0;& && && & //捕捉输入不滤波
&&TIM_ICInit(TIM4, &TIM_ICInitStructure);
&&/* TIM enable counter */
&&TIM_Cmd(TIM4, ENABLE);
&&/* Enable the CC2 Interrupt Request */
&&TIM_ITConfig(TIM4,
TIM_IT_CC1, ENABLE);
&&TIM_ITConfig(TIM4, TIM_IT_CC2, ENABLE);
&&
TIM_ITConfig(TIM4, TIM_IT_CC3, ENABLE);
&&TIM_ITConfig(TIM4, TIM_IT_CC4,
ENABLE);
}复制代码
TIM_TimeBaseStructure.TIM_Period = 0为自动重装值,与普通单片机一样
TIM_TimeBaseStructure.TIM_Prescaler = 719; 预分频值, 使TIMx_CLK=100KHz ,系统时钟运行于72M时720分频,定时器运行于100KHZ,即10us每分度
TIM_ICInitStructure.TIM_ICMode = TIM_ICMode_ICAP; 此句选择定时器为输入捕获模式,但在我的库函数下未定义,所以注释掉,未影响程序执行
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;配置通道1
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_R上升沿捕获
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;捕获中断
TIM_ICInitStructure.TIM_ICFilter = 0x0;不滤波
TIM_ICInit(TIM4, &TIM_ICInitStructure);将配置应用
以上每个通道都需要将整个配置再写一遍,使用与'|'是无效的。
TIM_Cmd(TIM4, ENABLE);使能定时器4
&&TIM_ITConfig(TIM4, TIM_IT_CC1, ENABLE);
&&TIM_ITConfig(TIM4, TIM_IT_CC2, ENABLE);
&&TIM_ITConfig(TIM4, TIM_IT_CC3, ENABLE);
&&TIM_ITConfig(TIM4, TIM_IT_CC4, ENABLE);打开四个通道的捕获中断
以上将TIM配置完成,下面是中断内代码:
TIM4_IRQHandler(void)
{
& && && && && && && && && && && && && && && &
//频率缓冲区计数
static u16 this_time_CH1 = 0;
static u16
last_time_CH1 = 0;
static u8 capture_number_CH1 = 0;
tmp16_CH1;
static u16 this_time_CH2 = 0;
static u16 last_time_CH2 = 0;
static u8 capture_number_CH2 = 0;
vu16 tmp16_CH2;
static u16 this_time_CH3 = 0;
static u16 last_time_CH3 = 0;
static u8 capture_number_CH3 = 0;
vu16 tmp16_CH3;
static u16 this_time_CH4 = 0;
static u16 last_time_CH4 = 0;
static u8 capture_number_CH4 = 0;
vu16 tmp16_CH4;
&&if(TIM_GetITStatus(TIM4, TIM_IT_CC1) == SET)
& && &&&
TIM_ClearITPendingBit(TIM4, TIM_IT_CC1);
& && &&&if(capture_number_CH1 == 0)
& && && && &
capture_number_CH1 = 1;
& && && && &
last_time_CH1 = TIM_GetCapture1(TIM4);
& && &&&else if(capture_number_CH1 == 1)
& && && && &
capture_number_CH1 = 0;
& && && && &
this_time_CH1 = TIM_GetCapture1(TIM4);
& && && && &
if(this_time_CH1 & last_time_CH1)
& && && && &{
& && && && && &
tmp16_CH1 = (this_time_CH1 - last_time_CH1);
& && && && &}
& && && && &else
& && && && &{
& && && && && &
tmp16_CH1 = ((0xFFFF - last_time_CH1) + this_time_CH1);
& && && && &}
& && && && &//TIM2
counter clock = 1MHz
//& && && && &
FreqBuf[cnt] = (1000000L * 100) /
tmp16;& && && && && && &
//*100为扩大显示量程
& &Freq_Value[0]=tmp16_CH1;
&&}
& & if(TIM_GetITStatus(TIM4, TIM_IT_CC2) == SET)
& && &&&
TIM_ClearITPendingBit(TIM4, TIM_IT_CC2);
& && &&&if(capture_number_CH2 == 0)
& && && && &
capture_number_CH2 = 1;
& && && && &
last_time_CH2 = TIM_GetCapture2(TIM4);
& && &&&else if(capture_number_CH2 == 1)
& && && && &
capture_number_CH2 = 0;
& && && && &
this_time_CH2 = TIM_GetCapture2(TIM4);
& && && && &
if(this_time_CH2 & last_time_CH2)
& && && && &{
& && && && && &
tmp16_CH2 = (this_time_CH2 - last_time_CH2);
& && && && &}
& && && && &else
& && && && &{
& && && && && &
tmp16_CH2 = ((0xFFFF - last_time_CH2) + this_time_CH2);
& && && && &}
& && && && &//TIM2
counter clock = 1MHz
//& && && && &
FreqBuf[cnt] = (1000000L * 100) /
tmp16;& && && && && && &
//*100为扩大显示量程
& &Freq_Value[1]=tmp16_CH2;
& && &&&
}
if(TIM_GetITStatus(TIM4, TIM_IT_CC3) == SET)
& && &&&
TIM_ClearITPendingBit(TIM4, TIM_IT_CC3);
& && &&&if(capture_number_CH3 == 0)
& && && && &
capture_number_CH3 = 1;
& && && && &
last_time_CH3 = TIM_GetCapture3(TIM4);
& && &&&else if(capture_number_CH3 == 1)
& && && && &
capture_number_CH3 = 0;
& && && && &
this_time_CH3 = TIM_GetCapture3(TIM4);
& && && && &
if(this_time_CH3 & last_time_CH3)
& && && && &{
& && && && && &
tmp16_CH3 = (this_time_CH3 - last_time_CH3);
& && && && &}
& && && && &else
& && && && &{
& && && && && &
tmp16_CH3 = ((0xFFFF - last_time_CH3) + this_time_CH3);
& && && && &}
& && && && &//TIM2
counter clock = 1MHz
//& && && && &
FreqBuf[cnt] = (1000000L * 100) /
tmp16;& && && && && && &
//*100为扩大显示量程
& &Freq_Value[2]=tmp16_CH3;
if(TIM_GetITStatus(TIM4, TIM_IT_CC4) == SET)
& && &&&
TIM_ClearITPendingBit(TIM4, TIM_IT_CC4);
& && &&&if(capture_number_CH4 == 0)
& && && && &
capture_number_CH4 = 1;
& && && && &
last_time_CH4 = TIM_GetCapture4(TIM4);
& && &&&else if(capture_number_CH4 == 1)
& && && && &
capture_number_CH4 = 0;
& && && && &
this_time_CH4 = TIM_GetCapture4(TIM4);
& && && && &
if(this_time_CH4 & last_time_CH4)
& && && && &{
& && && && && &
tmp16_CH4 = (this_time_CH4 - last_time_CH4);
& && && && &}
& && && && &else
& && && && &{
& && && && && &
tmp16_CH4 = ((0xFFFF - last_time_CH4) + this_time_CH4);
& && && && &}
& && && && &//TIM2
counter clock = 1MHz
//& && && && &
FreqBuf[cnt] = (1000000L * 100) /
tmp16;& && && && && && &
//*100为扩大显示量程
& &Freq_Value[3]=tmp16_CH4;
GPIO_WriteBit(GPIOC, GPIO_Pin_13,
(BitAction)((1-GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_13))));
}复制代码
中断内四部分代码完全一样,只分析其中一段
输入捕获的原理是,定时器正常计数运行,当外部脉冲到来时,将定时器计数值存起来,当下次脉冲到来时,求出这两次计数值差值,即为这两段脉冲的周期。
例如,定时器计数到10,外部脉冲到来,使用last_time_CH1存储10,下次脉冲到来,此时定时器计数值运行到110,使用this_time_CH1存储110,之后做差,tmp16_CH1存储差值100,由于定时器运行于100KHZ,10us计数值增加一次,所以脉冲周期为100*10=1000us=1ms,即为1KHZ。
当然,定时器会溢出重装,此时需要将差值补偿运算,tmp16_CH1 = ((0xFFFF - last_time_CH1) + this_time_CH1);
可测量的范围取决于定时器运行的频率,如果外部频率慢到当定时器整个计数一周后也没有触发两次,会发生溢出,此时计数值已不准确。所以定时器时钟配置取决于外部脉冲频率,应配置得当使得脉冲频率范围不致溢出。
由于每次外部脉冲都会触发中断,尤其是四通道时,所以使用中断方式会略微占用CPU资源,使用DMA可以解决这一问题。
得到脉冲周期后,即可通过运算获得外部频率,进而测速。
哈工大电子设计联盟 观海听涛 HRT车队
& && && && && &
& && && && &QQ
车队好拉风~~~
好厉害。。。看不懂。。。晚安啦~~~
卷来卷去~ 发表于
好厉害。。。看不懂。。。晚安啦~~~
Apache 发表于
版聊,砍死你们
是陶学长么么么么么?
巫师i 发表于
是陶学长么么么么么?
怎么感觉定时器不像是100KHz的,预分频也不是1MHz
怎么感觉定时器不像是100KHz的,预分频也不是1MHz
额……定时器是从总线上720分频出来的,就是定时器运行于100kHz,没有预分频。
额……定时器是从总线上720分频出来的,就是定时器运行于100kHz,没有预分频。 ...
说的不是一码事,我没描述好,我说的是定时器定时时间长度
说的不是一码事,我没描述好,我说的是定时器定时时间长度
定时时间长度由于重装值就是从头到尾,就是把整个定时器跑了一圈的时间,不过在输入捕获中,不需要定时时间啊,只需要定时器本身计数,从而计算差值,定时时间爱多少多少……最好跑完整个定时器这样量程还大。
请教楼主个问题,我试了你的代码,但有点不明白的是:我ch1或者ch2输入脉冲,每次进入一次if(TIM_GetITStatus(TIM4, TIM_IT_CC1) == SET) {...}同时会进入一次if(TIM_GetITStatus(TIM4, TIM_IT_CC2) == SET) {...},也就是说给ch1输入方波, TIM_IT_CC1和 TIM_IT_CC2都会被置位。同理,ch3输入 TIM_IT_CC3和 TIM_IT_CC4也都会被置位。这该如何理解?另外,我只是想用同一个TIMER的4个通道进行4路PWM波的脉冲计数不算周期和占空比,楼主和各位大神有什么好的建议没?谢谢各位,欢迎指教
为什么,同样的程序用到TIMER3就不行了呐??都是同一类定时器的,难道有什么别的讲究?myfuturey后使用快捷导航没有帐号?
STM32自学系列——2.定时器TIM和PWM的输出【暑期持续更新】
本帖最后由 明少丶 于
00:42 编辑
学习完前面的STM32系统框架,时钟,GPIO和按键,我们开始由浅入深的逐个攻破STM32的所有功能。
我自己用的是stm32f103rc可以看看它的功能描述:
1.jpg (41.32 KB, 下载次数: 41)
20:54 上传
内容是:ARM 32位 cortex-M3内核 最高工作频率72MHZ 256KB Flash 48KB SRAM
内嵌RC振荡时钟 8MHZ和32MHZ ,RTC(实时时钟) , NIV(中断) , JTAG SWD仿真下载口 ,
PWM , 2个16位高级、2个16位基本、2个16位通用定时器 , 滴答定时器 , 3个 SPI/I2S ,
5个USART串口 , USB2.0 , CAN通信 , 3个12位 16通道AD转换器 , 2个12位 DA转换器 ,
SDIO(sd卡模块) , 高速i/o端口。
大体意思就是这样。&&所以说其实我们要学的内容不多,几天突破一个。很快我们就可以利用它来DIY一些高端、大气的电子类作品,是不是很开心。我们开始下面的内容:
& && && & STM32的定时器外设功能强大得超出了想像力,STM32一共有8个都为16位的定时器。其中TIM6、TIM7是基本定时器;TIM2、TIM3、TIM4、TIM5是通用定时器;TIM1和TIM8是高级定时器。这些定时器使STM32具有定时、信号的频率测量、信号的PWM测量、PWM输出、三相6步电机控制及编码器接口等功能,都是专门为工控领域量身订做的。
& && && &基本定时器:具备最基本的定时功能,下面是它的结构:
2.jpg (44.56 KB, 下载次数: 34)
21:50 上传
我们来看看它的启动代码:
void TIM2_Configuration(void)
{&& 基本定时器TIM2的定时配置的结构体(包含定时器配置的所有元素例如:TIM_Period = 计数值)
& & TIM_TimeBaseInitTypeDef&&TIM_TimeBaseS
& & 设置TIM2_CLK为72MHZ (即TIM2外设挂在APB1上,把它的时钟打开。)& && &&&
& & RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 , ENABLE);
& & 设置计数值位1000
& & TIM_TimeBaseStructure.TIM_Period=1000;
& & 将TIM2_CLK为72MHZ 除以72 = 1MHZ为定时器的计数频率
& & TIM_TimeBaseStructure.TIM_Prescaler= 71;
& & 这个TIM_ClockDivision是设置时钟分割,这里不分割还是1MHZ的计数频率
& & TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
& & 设置为向上计数模式;(计数模式有向上,向下,中央对齐1,中央对齐2,中央对齐3)
& & TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
& & 将配置好的设置放进stm32f10x-tim.c的库文件中
& & TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
& & 清除标志位
& & TIM_ClearFlag(TIM2, TIM_FLAG_Update);
& & 使能TIM2中断
& & TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
& & 使能TIM2外设& && &&&
& & TIM_Cmd(TIM2, ENABLE);& && && && && && && && && && && && && && && && && && && && && && && && && && && && && && && && && && && && && && && && && && && && && && && && &
& && & 通用定时器:就比基本定时器复杂得多了。除了基本的定时,它主要用在测量输入脉冲的频率、脉冲宽与输出PWM脉冲的场合,还具有编码器的接口。
3.jpg (81.47 KB, 下载次数: 43)
22:46 上传
我们来详细讲解:如何生成PWM脉冲
通用定时器可以利用GPIO引脚进行脉冲输出,在配置为比较输出、PWM输出功能时,捕获/比较寄存器TIMx_CCR被用作比较功能,下面把它简称为比较寄存器。
这里直接举例说明定时器的PWM输出工作过程:若配置脉冲计数器TIMx_CNT为向上计数,而重载寄存器TIMx_ARR被配置为N,即TIMx_CNT的当前计数值数值X在TIMxCLK时钟源的驱动下不断累加,当TIMx_CNT的数值X大于N时,会重置TIMx_CNT数值为0重新计数。
而在TIMxCNT计数的同时,TIMxCNT的计数值X会与比较寄存器TIMx_CCR预先存储了的数值A进行比较,当脉冲计数器TIMx_CNT的数值X小于比较寄存器TIMx_CCR的值A时,输出高电平(或低电平),相反地,当脉冲计数器的数值X大于或等于比较寄存器的值A时,输出低电平(或高电平)。
如此循环,得到的输出脉冲周期就为重载寄存器TIMx_ARR存储的数值(N+1)乘以触发脉冲的时钟周期,其脉冲宽度则为比较寄存器TIMx_CCR的值A乘以触发脉冲的时钟周期,即输出PWM的占空比为 A/(N+1) 。
如果不想看的可以直接看我标注的红色字体,就大体可以理解。
下面我们来编写具体代码和讲解:
void TIM3_GPIO_Config(void)
{配置TIM3复用输出PWM的IO
&&GPIO_InitTypeDef GPIO_InitS
&&打开TIM3的时钟
&&RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
&&打开GPIOA和GPIOB的时钟
&&RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);
&&配置PA6.PA7的工作模式
&&GPIO_InitStructure.GPIO_Pin =&&GPIO_Pin_6 | GPIO_Pin_7;
&&GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;& && &&&
&&GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
&&GPIO_Init(GPIOA, &GPIO_InitStructure);
&&配置PB0.PB1的工作模式
&&GPIO_InitStructure.GPIO_Pin =&&GPIO_Pin_0 | GPIO_Pin_1;
&&GPIO_Init(GPIOB, &GPIO_InitStructure);
void TIM3_Mode_Config(void)
& && &&&TIM_TimeBaseInitTypeDef&&TIM_TimeBaseS//初始化TIM3的时间基数单位
& && &&&TIM_OCInitTypeDef&&TIM_OCInitS//初始化TIM3的外设
& && && &u16 CCR1_Val = 500;& && &&&
& && && &u16 CCR2_Val = 375;
& && && &u16 CCR3_Val = 250;
& && && &u16 CCR4_Val = 125;//PWM信号电平跳变值(即计数到这个数值以后都是低电平之前都是高电平)
/* -----------------------------------------------------------------------
& & TIM3 Channel1 duty cycle = (TIM3_CCR1/ TIM3_ARR+1)* 100% = 50%
& & TIM3 Channel2 duty cycle = (TIM3_CCR2/ TIM3_ARR+1)* 100% = 37.5%
& & TIM3 Channel3 duty cycle = (TIM3_CCR3/ TIM3_ARR+1)* 100% = 25%
& & TIM3 Channel4 duty cycle = (TIM3_CCR4/ TIM3_ARR+1)* 100% = 12.5%
&&----------------------------------------------------------------------- */
&&TIM3的时间基数单位设置(如计数终止值:999,从0开始 ;计数方式:向上计数)& && && &
&&TIM_TimeBaseStructure.TIM_Period = 999;& && &
&&TIM_TimeBaseStructure.TIM_Prescaler = 0;& && && && &
&&TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1 ;& && &&&
&&TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
&&TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
&&TIM3的外设的设置
&&TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;& && &&&//TIM脉冲宽度调制模式1& &
&&TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_E//这个暂时不知道,stm32固件库里没有搜到。应该是定时器输出声明使能的意思& && &&&
&&TIM_OCInitStructure.TIM_Pulse = CCR1_V//设置了待装入捕获比较寄存器的脉冲值& && && &
&&TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_H //TIM输出比较极性高
&&TIM_OC1Init(TIM3, &TIM_OCInitStructure);
&&TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);//使能或者失能TIMx在CCR1上的预装载寄存器
&&下面3路PWM输出和上面的一样不再解说
&&TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_E
&&TIM_OCInitStructure.TIM_Pulse = CCR2_V& && && &
&&TIM_OC2Init(TIM3, &TIM_OCInitStructure);& && && &
&&TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);
&&TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_E
&&TIM_OCInitStructure.TIM_Pulse = CCR3_V& && &&&
&&TIM_OC3Init(TIM3, &TIM_OCInitStructure);& && && &
&&TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);
&&TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_E
&&TIM_OCInitStructure.TIM_Pulse = CCR4_V& && &&&
&&TIM_OC4Init(TIM3, &TIM_OCInitStructure);& && &&&
&&TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable);
&&TIM_ARRPreloadConfig(TIM3, ENABLE);& && &&&//使能TIM3重载寄存器ARR& && && && && &
&&TIM_Cmd(TIM3, ENABLE);//使能TIM3& && && && &&&
太累了边看边写都这个点了日0:24:13在自己床上写的。下面是看看我们程序达到的4路PWM的效果:
4.jpg (84.64 KB, 下载次数: 40)
00:20 上传
可以看到明显占空比不同的4路pwm波。
这一节终于讲完,个人觉得敲一遍代码学起来还是蛮容易懂的。希望看到的人也能搞懂。
最后补充一点pwm具体能干什么?&&特别是对广大电子DIY爱好者的应用:
智能小车的电机控制:我们可以利用pwm来控制我们的智能小车的车速;
机器人:给“机器人关节”舵机周期一定(我以前玩过具体多少毫秒忘记了)pwm波就可以控制舵机的转动角度了;
呼吸灯:输入不同的pwm波就可以达到明暗渐明渐暗的效果。
还有别的应用大家一起发挥想象力给予补充。我们可以一起交流,希望大家支持。
刚刚学习STM32,共勉
凑个热闹,看不懂,不过感兴趣
大神是怎么学会51单片机,学习方法牛逼,佩服
王栋春 发表于
凑个热闹,看不懂,不过感兴趣
花点时间,应该看得懂。很人性化的东西。
酷爱diy 发表于
大神是怎么学会51单片机,学习方法牛逼,佩服
刚上大学空余时间看到机器人感兴趣,就认识了微型计算机。从51这种基础的8位微机开始学的,不懂就去百度。买书看看。我一般学一款微机都不会去买单片机学习板,其实买个微机的最小系统就够了。一般都不会超过50,只能建议怎么多了。
那么你的方法除了百度与看书最重要的是怎么学习的,我学的头大了
酷爱diy 发表于
那么你的方法除了百度与看书最重要的是怎么学习的,我学的头大了
理解很重要。就和解数学题一样,思路要理清。最好看别人的教学视频,然后自己理解消化,拿去应用举一反三。就可以了。
你是怎样组织代码的???根据参考手册将一个个函数调用起来么???我是学正点原子的开发板,但是我只是大概了解一下外设的结构,简介。还有就是照着书把代码抄进去而已,感觉达不到更好效果。
电子DIY嘿皮 发表于
你是怎样组织代码的???根据参考手册将一个个函数调用起来么???我是学正点原子的开发板,但是我只是大 ...
是效果没出来,还是什么?&&我也学了好几天才用的很自然。重点在于理解,才能去用,
Copyright &
Powered bySTM32&定时器的4通道计数器应用
通用定时器确实比较强悍,功能极多我也比较晕
&此为在不牵扯PWM 与 DMA
下像C51那样计数点灯。
&当然你要配置一些IO口作为点灯用这里就不详细说了。
LED2_ON&&GPIO_ResetBits(GPIOD,
GPIO_Pin_7)
#define LED2_OFF&GPIO_SetBits(GPIOD,
GPIO_Pin_7)
然后启用通用定时器2设置它的中断等3.0的库;
&&//Timer2中断*//
void NVIC_Configuration(void)
&NVIC_InitTypeDef NVIC_InitS
&NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
&NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
//TIM2全局中断3.0的
&NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority
&NVIC_InitStructure.NVIC_IRQChannelSubPriority =
&NVIC_InitStructure.NVIC_IRQChannelCmd =
&NVIC_Init(&NVIC_InitStructure);
&//TIM2 clock enable
&TIM_TimeBaseInitTypeDef&
TIM_TimeBaseS
&TIM_OCInitTypeDef&
TIM_OCInitS
&TIM_TimeBaseStructure.TIM_Period =
8000;&&&//计数值&&&TIM_TimeBaseStructure.TIM_Prescaler =
7200-1;&&&
&//预分频,此值+1为分频的除数
&TIM_TimeBaseStructure.TIM_ClockDivision =
0x0;& &//设置时钟分割
&TIM_TimeBaseStructure.TIM_CounterMode =
TIM_CounterMode_Up; &//向上计数
**********************************************************************************************&
&TIM_TimeBaseInit(TIM2,
&TIM_TimeBaseStructure);
TIM_ClockDivision,设置时钟分割
它就是RCC控制寄存器1(TIMx_CR1)的位9:8(CKD),具体含义如下:
CKD[1:0]: 时钟分频因子定义在定时器时钟(CK_INT)频率与数字滤波器(ETR,TIx)使用的采样频率之间的分频比例。0x00:tDTS = 1 x&tCK_INT
0x01:tDTS = 2 x
0x10:tDTS = 4 x
TIM_TimeBaseStructure中应该还有一个更新报告& uint8_t TIM_RepetitionC不管他也行。
& 72M/7200=10K分频后的结果就是,定时器速度为10K.计数器为向上计数,8000 溢出,所以溢出时间就是
.8秒.而捕获的比较值则为:
u16 CCR1_Val = 4000;
u16 CCR2_Val = 2000;
u16 CCR3_Val = 1000;
u16 CCR4_Val = 500;也就是说,在定时器开始计数后,第一通道的中断发生在.4秒,第二通道是0.2,第三通道是0.1,第四是0.05*/
************************************************************************************************&
&&&//比较设置*/&&&&&&&&&&&&&&
& TIM_OCInitStructure.TIM_OCMode =
TIM_OCMode_I&&&&&&&//输出比较非主动模式
& TIM_OCInitStructure.TIM_OCPolarity =
TIM_OCPolarity_H&&//极性为正&
&&&&//比较通道1*/&&&&&&&&&&&
& TIM_OCInitStructure.TIM_Pulse =
CCR1_V& //就是4000装入捕获比较寄存器的脉冲值
& TIM_OC1Init(TIM2,
&TIM_OCInitStructure);&&&&&&&&&&&&&//写入配置
& TIM_OC1PreloadConfig(TIM2,
TIM_OCPreload_Disable);&&//禁止OC1重装载,其实可以省掉这句,因为默是
&//4路都不重装的.
********************************************************************************************
typedef struct
& uint16_t TIM_OCM //选择定时器模式
比较多有的功能也比较相似
& uint16_t TIM_OutputS //使能通道 为了和2.0兼容吧我不管他& uint16_t
TIM_OutputNS //失能??
& uint16_t
TIM_P&&&&&&
//待装入捕获比较寄存器的脉冲值&
uint16_t TIM_OCP& //输出极性
& uint16_t TIM_OCNP&
//???& uint16_t
TIM_OCIdleS& //???
& uint16_t TIM_OCNIdleS&
//???不懂得不管用默认就好
} TIM_OCInitTypeD
********************************************************************************************&
&&&&//比较通道2 /&&&&&&
&TIM_OCInitStructure.TIM_Pulse =
&TIM_OC2Init(TIM2,
&TIM_OCInitStructure);
&TIM_OC2PreloadConfig(TIM2,
TIM_OCPreload_Disable);
&&&//比较通道3 /&&&&&&&&&
&TIM_OCInitStructure.TIM_Pulse =
&TIM_OC3Init(TIM2,
&TIM_OCInitStructure);
&TIM_OC3PreloadConfig(TIM2,
TIM_OCPreload_Disable);
&//比较通道4 /&&&&
&TIM_OCInitStructure.TIM_Pulse =
&TIM_OC4Init(TIM2,
&TIM_OCInitStructure);
&TIM_OC4PreloadConfig(TIM2,
TIM_OCPreload_Disable);
&//使能预装载/
&TIM_ARRPreloadConfig(TIM2,
ENABLE);& //这个历程中没有软件修改寄存器所以没他也行
&&//预先清除所有中断位防止一启用就有中断从九九那抄的/
&TIM_ClearITPendingBit(TIM2, TIM_IT_CC1 |
TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4|TIM_IT_Update);
&&//4个通道和溢出都配置中断/
&TIM_ITConfig(TIM2, TIM_IT_CC1 | TIM_IT_CC2 |
TIM_IT_CC3 | TIM_IT_CC4|TIM_IT_Update, ENABLE);
&&//允许TIM2开始计数 /
&TIM_Cmd(TIM2, ENABLE);
服务中断函数比较简单直接抄来
void TIM2_IRQHandler(void)
&if (TIM_GetITStatus(TIM2, TIM_IT_CC1) !=
&&//必须清空标志位/*/
&&TIM_ClearITPendingBit(TIM2,
TIM_IT_CC1);
&&&//点亮LED5 一定要是中文的 不然中间的 内容就不见了 本想大家移植到自己的作品中方便 看来SINA
不可这样用
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。}

我要回帖

更多关于 stm32定时器计数模式 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信