采用STM32制做分频器输出
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
采用STM32制做分频器输出
在实际的应用过程中,碰到一个案例。
需要对一个输入信号进行分频输出。
如下图所示,每输入一个固定的脉冲信号,输出一个分频后的脉冲。
本方案的要求如下:
1、根据不同的输入信号源,可以输出不同的频率。
一种信号要求每输入10个脉冲,要求输出一个脉冲,第二种信号,则要求输入15个脉冲才输出一个脉冲。
2、由于输入信号的频率比较高【最高超过120K】,不能够使用中断来处理脉冲输出。
可行性分析:
1、STM32芯片可以对输入的PWM信号进行计数。
因此,对输入脉冲的计数应该可以实现。
2、STM32芯片有PWM输出功能。
而且支持自动加载功能【使用影子寄存器的方式】。
可以实现PWM的输出不需要中断参与。
3、STM32芯片的PWM输出功能,有很多模式,其中,有比较输出模式,有触发输出【翻转输出】。
认为这两种方法中,应该有一种方法可以实现计数到一定脉冲以后,输出脉冲。
实现的过程及源代码
采用定时器的输入计数功能。
实现了对脉冲输入的计数。
试了一下,采用比较输出,发现只能输出一个跳变沿以后,输入信号怎么变,输出都不发生变化。
思考,可能是因为计数一直在累加,所以,达到比较输出值以后,计数很长时间不能从头开始。
无法实现重复输出功能。
将定时器的周期修改为分频个数以后,计数可以实现到设定个数以后,从0开始计数。
但PWM输出还是一直不变化。
然后,试了一下,采用触发输出模式【翻转输出】。
当输入的个数达到设定的触发输出个数时。
能有效的输出翻转一次。
效果实现了。
接下来,发现一个问题,每输入15个脉冲,要求输出一个脉冲。
脉冲是有高电平有低电平的。
按占空比50%计算。
那么每输入7.5个脉冲,就需要翻转一次PWM输出。
头大了。
小数点没法控制。
突发奇想,如果不检测脉冲个数,改检测跳变沿的话。
那么,这个问题就解决了。
原来检测7.5个脉冲,刚好是15个跳变沿。
查了一下,ST刚好允许每个定时器的通道1【只有通道1支持】有变化沿可以计数。
采用跳变沿计数以后,最终效果实现。
代码如下:采用定时器8的通道1输出,通道4输出PWM
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 ; /*CH1 */
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; /* CH4 */
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
TIM_DeInit(TIM8);
TIM_TimeBaseStructure.TIM_Period = 15-1; //-计数是从0开始的,所以减1 TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM8, &TIM_TimeBaseStructure);
TIM_TIxExternalClockConfig(TIM8,TIM_TIxExternalCLK1Source_TI1ED,
TIM_ICPolarity_Rising,0);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 15-1; //-计数是从0开始的,所以减1
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
/* Output Compare Toggle Mode configuration: Channel4 */
TIM_OC4Init(TIM8, &TIM_OCInitStructure);
TIM_OC4PreloadConfig(TIM8, TIM_OCPreload_Disable);
TIM_SetCounter(TIM8, 0);
TIM_ARRPreloadConfig(TIM8, ENABLE);
TIM_Cmd(TIM8, ENABLE);
TIM_CtrlPWMOutputs(TIM8, ENABLE);
//============================================================
//============================================================
从网上找到了参考资料如下:
TIMx的输出比较模式是用来控制一个输出波形或者指示何时一段给定的的时间已经到时。
当计数器与捕获/比较寄存器的内容相同时,输出比较功能做如下操作:
将输出比较模式(TIMx_CCMRx寄存器中的OCxM位)和输出极性(TIMx_CCER 寄存器中的CCxP位)定义的值输出到对应的管脚上。
在比较匹配时,输出管脚可以保持它的电平(OCxM=000)、被设置成有效电平(OCxM=001)、被设置成无有效电平(OCxM=010)或进行翻转(OCxM=011)。
这几种模式对应定义在库中
TIM_OCInitTypeDef structure
TIM_OCInitTypeDef定义于文件“stm32f10x_tim.h”:
typedef struct
{
u16 TIM_OCMode;
u16 TIM_Channel;
u16 TIM_Pulse;
u16 TIM_OCPolarity;
} TIM_OCInitTypeDef;
TIM_OCMode选择定时器模式。
该参数取值见下表。
设置中断状态寄存器中的标志位(TIMx_SR寄存器中的CCxIF位)。
若设置了相应的中断屏蔽(TIMx_DIER寄存器中的CCXIE位),则产生一个中断。
若设置了相应的使能位(TIMx_DIER寄存器中的CCxDE位,TIMx_CR2寄存器中的CCDS位选择DMA请求功能),则产生一个DMA请求。
TIMx_CCMRx中的OCxPE位选择TIMx_CCRx寄存器是否需要使用预装载寄存器。
在输出比较模式下,更新事件UEV对OCxREF和OCx输出没有影响。
同步的精度可以达到计数器的一个计数周期。
输出比较模式(在单脉冲模式下)也能用来输出一个单脉冲。
输出比较模式的配置步骤:
1.选择计数器时钟(内部,外部,预分频器)
2.将相应的数据写入TIMx_ARR和TIMx_CCRx寄存器中
3.如果要产生一个中断请求和/或一个DMA请求,设置CCxIE位和/或CCxDE 位。
4.选择输出模式,例如:必须设置OCxM=’011’、OCxPE=’0’、CCxP=’0’和CCx E=’1’,当计数器CNT与CCRx匹配时翻转OCx的输出管脚,CCRx预装载未用,开启OCx输出且高电平有效。
5.设置TIMx_CR1寄存器的CEN位启动计数器
TIMx_CCRx寄存器能够在任何时候通过软件进行更新以控制输出波形,条件是未使用预装载寄存器(OCxPE=’0’,否则TIMx_CCRx影子寄存器只能在发生下一次更新事件时被更新)。
000:冻结。
输出比较寄存器TIMx_CCR1与计数器TIMx_CNT间的比较对OC1REF 不起作用;也就是Timing模式
001:匹配时设置通道1为有效电平。
当计数器TIMx_CNT的值与捕获/比较寄存器1(TIMx_CCR1)相同时,强制OC1REF为高。
这个也就是ACTIVE模式
010:匹配时设置通道1为无效电平。
当计数器TIMx_CNT的值与捕获/比较寄存器1(TIMx_CCR1)相同时,强制OC1REF为低。
这个也就是INACTIVE模式
011:翻转。
当TIMx_CCR1=TIMx_CNT时,翻转OC1REF的电平。
也就是toggle
模式。