专家
公告
财富商城
电子网
旗下网站
首页
问题库
专栏
标签库
话题
专家
NEW
门户
发布
提问题
发文章
STM32
请教:如何使用一个定时器实现多路频率可调PWM(占空比不要求可调)?
2019-07-21 08:07
发布
×
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
站内问答
/
STM32/STM8
11390
18
1401
本帖最后由 bootblack 于 2018-10-31 13:46 编辑
如题,由于硬件上仅剩余一个硬件定时器(通用定时器),需要实现如下功能:
1、实现5路PWM
2、每路PWM频率都可调整(各路PWM频率都是独立的)
3、占空比没有要求,一般保持50%左右即可
4、每路频率都低于10KHz
5、要求频率误差小于等于1Hz
额,想请教下各路大神,有没有很好的思路,敬请指教!感谢!
友情提示:
此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
18条回答
Electronic
2019-07-21 10:18
本帖最后由 Electronic 于 2018-11-8 17:37 编辑
说干就干,用原子的MINI的TIM1的4个通道配置输出4路不同频率的方波,频率可调,提供源码附件
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "timer.h"
//下次增量值
uint16_t TIM1_OC1_PulseAdd = 3600; //72M/10K/2=3600
uint16_t TIM1_OC2_PulseAdd = 3600; //72M/10K/2=3600
uint16_t TIM1_OC3_PulseAdd = 3600; //72M/10K/2=3600
uint16_t TIM1_OC4_PulseAdd = 3600; //72M/10K/2=3600
//比较捕获值
uint16_t TIM1_OC1_PulseVal = 0;
uint16_t TIM1_OC2_PulseVal = 0;
uint16_t TIM1_OC3_PulseVal = 0;
uint16_t TIM1_OC4_PulseVal = 0;
void TIM1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStruct;
NVIC_InitTypeDef NVIC_InitStructure;
//使能时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
//PA8 PA9 PA10 PA11复用推挽输出
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11;
GPIO_Init(GPIOA, &GPIO_InitStruct);
//配置定时器1
TIM_TimeBaseStructure.TIM_Period = 0xFFFF;
TIM_TimeBaseStructure.TIM_Prescaler = 0; //分频越小、精度越高、范围越小; 分频越大、精度越低、范围越大
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
//清除比较捕获中断标志
TIM_ClearFlag(TIM1, TIM_FLAG_CC1);
TIM_ClearFlag(TIM1, TIM_FLAG_CC2);
TIM_ClearFlag(TIM1, TIM_FLAG_CC3);
TIM_ClearFlag(TIM1, TIM_FLAG_CC4);
//配置比较捕获中断
TIM_ITConfig(TIM1, TIM_IT_CC1, ENABLE);
TIM_ITConfig(TIM1, TIM_IT_CC2, ENABLE);
TIM_ITConfig(TIM1, TIM_IT_CC3, ENABLE);
TIM_ITConfig(TIM1, TIM_IT_CC4, ENABLE);
//比较捕获初值(必须设置,不然波形不对齐)
TIM1_OC1_PulseVal = TIM1_OC1_PulseAdd;
TIM1_OC2_PulseVal = TIM1_OC2_PulseAdd;
TIM1_OC3_PulseVal = TIM1_OC3_PulseAdd;
TIM1_OC4_PulseVal = TIM1_OC4_PulseAdd;
//清除比较模式
TIM1->CCMR1 &= ~((7<<4) | (7<<12));
TIM1->CCMR2 &= ~((7<<4) | (7<<12));
//强制为无效电平(不设置,边沿不能对其)
TIM1->CCMR1 |= ((4<<4) | (4<<12));
TIM1->CCMR2 |= ((4<<4) | (4<<12));
//翻转模式
TIM_OCStructInit(&TIM_OCInitStruct);
TIM_OCInitStruct.TIM_OCIdleState = TIM_OCIdleState_Reset;
TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_Toggle; //翻转
TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High; //有效电平
TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;
//比较捕获通道1
TIM_OCInitStruct.TIM_Pulse = TIM1_OC1_PulseVal;
TIM_OC1Init(TIM1, &TIM_OCInitStruct);
//比较捕获通道2
TIM_OCInitStruct.TIM_Pulse = TIM1_OC2_PulseVal;
TIM_OC2Init(TIM1, &TIM_OCInitStruct);
//比较捕获通道3
TIM_OCInitStruct.TIM_Pulse = TIM1_OC3_PulseVal;
TIM_OC3Init(TIM1, &TIM_OCInitStruct);
//比较捕获通道4
TIM_OCInitStruct.TIM_Pulse = TIM1_OC4_PulseVal;
TIM_OC4Init(TIM1, &TIM_OCInitStruct);
//使能中断线
NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
//主输出使能(高级定时器)
TIM_CtrlPWMOutputs(TIM1, ENABLE);
//使能定时器
TIM_Cmd(TIM1, ENABLE);
}
int main(void)
{
delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置中断优先级分组2
LED_Init(); //初始化与LED连接的硬件接口
TIM1_Init(); //PA8被配置为复用功能
//重新配置频率
TIM1_OC1_PulseAdd = 2400; //72M/15K/2=2400
TIM1_OC2_PulseAdd = 3600; //72M/10K/2=3600
TIM1_OC3_PulseAdd = 7200; //72M/ 5K/2=7200
TIM1_OC4_PulseAdd = 36000; //72M/ 1K/2=36000
while(1)
{
LED1 = !LED1;
delay_ms(300);
}
}
//定时器1比较捕获中断
void TIM1_CC_IRQHandler(void)
{
if(TIM_GetITStatus(TIM1, TIM_IT_CC1) != RESET) //比较捕获通道1
{
TIM_ClearITPendingBit(TIM1, TIM_IT_CC1);
TIM1_OC1_PulseVal += TIM1_OC1_PulseAdd; //计算下次的比较捕获值
TIM_SetCompare1(TIM1, TIM1_OC1_PulseVal);
}
if(TIM_GetITStatus(TIM1, TIM_IT_CC2) != RESET) //比较捕获通道2
{
TIM_ClearITPendingBit(TIM1, TIM_IT_CC2);
TIM1_OC2_PulseVal += TIM1_OC2_PulseAdd; //计算下次的比较捕获值
TIM_SetCompare2(TIM1, TIM1_OC2_PulseVal);
}
if(TIM_GetITStatus(TIM1, TIM_IT_CC3) != RESET) //比较捕获通道3
{
TIM_ClearITPendingBit(TIM1, TIM_IT_CC3);
TIM1_OC3_PulseVal += TIM1_OC3_PulseAdd; //计算下次的比较捕获值
TIM_SetCompare3(TIM1, TIM1_OC3_PulseVal);
}
if(TIM_GetITStatus(TIM1, TIM_IT_CC4) != RESET) //比较捕获通道4
{
TIM_ClearITPendingBit(TIM1, TIM_IT_CC4);
TIM1_OC4_PulseVal += TIM1_OC4_PulseAdd; //计算下次的比较捕获值
TIM_SetCompare4(TIM1, TIM1_OC4_PulseVal);
}
}
不知道怎么上传代码,只能复制到上面
STM32 单定时器4路不同频率的方波-2018-11-08.rar
(296.27 KB, 下载次数: 22)
2018-11-8 09:38 上传 点击文件名下载附件
加载中...
查看其它18个回答
一周热门
更多
>
相关问题
STM32F4上I2C(在PROTEUS中模拟)调试不通的问题
6 个回答
芯片供应紧张,准备换个MCU,MM32L系列替换STM32L系列的怎么样?
7 个回答
STM32同时使用两个串口进行数据收发时数据丢包的问题
5 个回答
STM32F103串口通信死机问题
4 个回答
STM32WLE5CC连接SX1268在LoRa模式下能与 SX1278互通吗?
2 个回答
相关文章
ST公司第一款无线低功耗单片机模块有效提高物联网设计生产效率
0个评论
如何实现对单片机寄存器的访问
0个评论
通过USB用STM32片内自带Bootloader下载程序及注意事项
0个评论
欲练此功必先自宫之STM32汇编启动,放慢是为了更好的前行
0个评论
×
关闭
采纳回答
向帮助了您的知道网友说句感谢的话吧!
非常感谢!
确 认
×
关闭
编辑标签
最多设置5个标签!
STM32
保存
关闭
×
关闭
举报内容
检举类型
检举内容
检举用户
检举原因
广告推广
恶意灌水
回答内容与提问无关
抄袭答案
其他
检举说明(必填)
提交
关闭
×
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
×
付费偷看金额在0.1-10元之间
确定
×
关闭
您已邀请
0
人回答
查看邀请
擅长该话题的人
回答过该话题的人
我关注的人
说干就干,用原子的MINI的TIM1的4个通道配置输出4路不同频率的方波,频率可调,提供源码附件
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "timer.h"
//下次增量值
uint16_t TIM1_OC1_PulseAdd = 3600; //72M/10K/2=3600
uint16_t TIM1_OC2_PulseAdd = 3600; //72M/10K/2=3600
uint16_t TIM1_OC3_PulseAdd = 3600; //72M/10K/2=3600
uint16_t TIM1_OC4_PulseAdd = 3600; //72M/10K/2=3600
//比较捕获值
uint16_t TIM1_OC1_PulseVal = 0;
uint16_t TIM1_OC2_PulseVal = 0;
uint16_t TIM1_OC3_PulseVal = 0;
uint16_t TIM1_OC4_PulseVal = 0;
void TIM1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStruct;
NVIC_InitTypeDef NVIC_InitStructure;
//使能时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
//PA8 PA9 PA10 PA11复用推挽输出
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11;
GPIO_Init(GPIOA, &GPIO_InitStruct);
//配置定时器1
TIM_TimeBaseStructure.TIM_Period = 0xFFFF;
TIM_TimeBaseStructure.TIM_Prescaler = 0; //分频越小、精度越高、范围越小; 分频越大、精度越低、范围越大
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
//清除比较捕获中断标志
TIM_ClearFlag(TIM1, TIM_FLAG_CC1);
TIM_ClearFlag(TIM1, TIM_FLAG_CC2);
TIM_ClearFlag(TIM1, TIM_FLAG_CC3);
TIM_ClearFlag(TIM1, TIM_FLAG_CC4);
//配置比较捕获中断
TIM_ITConfig(TIM1, TIM_IT_CC1, ENABLE);
TIM_ITConfig(TIM1, TIM_IT_CC2, ENABLE);
TIM_ITConfig(TIM1, TIM_IT_CC3, ENABLE);
TIM_ITConfig(TIM1, TIM_IT_CC4, ENABLE);
//比较捕获初值(必须设置,不然波形不对齐)
TIM1_OC1_PulseVal = TIM1_OC1_PulseAdd;
TIM1_OC2_PulseVal = TIM1_OC2_PulseAdd;
TIM1_OC3_PulseVal = TIM1_OC3_PulseAdd;
TIM1_OC4_PulseVal = TIM1_OC4_PulseAdd;
//清除比较模式
TIM1->CCMR1 &= ~((7<<4) | (7<<12));
TIM1->CCMR2 &= ~((7<<4) | (7<<12));
//强制为无效电平(不设置,边沿不能对其)
TIM1->CCMR1 |= ((4<<4) | (4<<12));
TIM1->CCMR2 |= ((4<<4) | (4<<12));
//翻转模式
TIM_OCStructInit(&TIM_OCInitStruct);
TIM_OCInitStruct.TIM_OCIdleState = TIM_OCIdleState_Reset;
TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_Toggle; //翻转
TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High; //有效电平
TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;
//比较捕获通道1
TIM_OCInitStruct.TIM_Pulse = TIM1_OC1_PulseVal;
TIM_OC1Init(TIM1, &TIM_OCInitStruct);
//比较捕获通道2
TIM_OCInitStruct.TIM_Pulse = TIM1_OC2_PulseVal;
TIM_OC2Init(TIM1, &TIM_OCInitStruct);
//比较捕获通道3
TIM_OCInitStruct.TIM_Pulse = TIM1_OC3_PulseVal;
TIM_OC3Init(TIM1, &TIM_OCInitStruct);
//比较捕获通道4
TIM_OCInitStruct.TIM_Pulse = TIM1_OC4_PulseVal;
TIM_OC4Init(TIM1, &TIM_OCInitStruct);
//使能中断线
NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
//主输出使能(高级定时器)
TIM_CtrlPWMOutputs(TIM1, ENABLE);
//使能定时器
TIM_Cmd(TIM1, ENABLE);
}
int main(void)
{
delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置中断优先级分组2
LED_Init(); //初始化与LED连接的硬件接口
TIM1_Init(); //PA8被配置为复用功能
//重新配置频率
TIM1_OC1_PulseAdd = 2400; //72M/15K/2=2400
TIM1_OC2_PulseAdd = 3600; //72M/10K/2=3600
TIM1_OC3_PulseAdd = 7200; //72M/ 5K/2=7200
TIM1_OC4_PulseAdd = 36000; //72M/ 1K/2=36000
while(1)
{
LED1 = !LED1;
delay_ms(300);
}
}
//定时器1比较捕获中断
void TIM1_CC_IRQHandler(void)
{
if(TIM_GetITStatus(TIM1, TIM_IT_CC1) != RESET) //比较捕获通道1
{
TIM_ClearITPendingBit(TIM1, TIM_IT_CC1);
TIM1_OC1_PulseVal += TIM1_OC1_PulseAdd; //计算下次的比较捕获值
TIM_SetCompare1(TIM1, TIM1_OC1_PulseVal);
}
if(TIM_GetITStatus(TIM1, TIM_IT_CC2) != RESET) //比较捕获通道2
{
TIM_ClearITPendingBit(TIM1, TIM_IT_CC2);
TIM1_OC2_PulseVal += TIM1_OC2_PulseAdd; //计算下次的比较捕获值
TIM_SetCompare2(TIM1, TIM1_OC2_PulseVal);
}
if(TIM_GetITStatus(TIM1, TIM_IT_CC3) != RESET) //比较捕获通道3
{
TIM_ClearITPendingBit(TIM1, TIM_IT_CC3);
TIM1_OC3_PulseVal += TIM1_OC3_PulseAdd; //计算下次的比较捕获值
TIM_SetCompare3(TIM1, TIM1_OC3_PulseVal);
}
if(TIM_GetITStatus(TIM1, TIM_IT_CC4) != RESET) //比较捕获通道4
{
TIM_ClearITPendingBit(TIM1, TIM_IT_CC4);
TIM1_OC4_PulseVal += TIM1_OC4_PulseAdd; //计算下次的比较捕获值
TIM_SetCompare4(TIM1, TIM1_OC4_PulseVal);
}
}
不知道怎么上传代码,只能复制到上面
一周热门 更多>