使用两个TIM定时器:
一个输出可调频率、占空比的PWM,
一个对输出PWM脉冲计数(计时)。
1.门控方式能实现,但需要复杂的配置和计算,不推荐。
2.脉冲计数是比较实际,也是比较简单的方式;
对输出PWM脉冲计数(计时)方法有多种:
1.IO中断计数,或同步定时中断计数:用另外一个定时器,按照相同频率中断计数(类似IO中断);
2.由PWM频率和脉冲个数,计算输出全部所需的时间,使用定时中断,关闭输出PWM;
3.利用定时器外部脉冲触发(外部时钟模式2功能),计数个数为所需脉冲个数(10个脉冲),则关闭输出PWM;
STM32定时器
利用阻塞延时,控制IO高低变化输出PWM这种方式就行啦,也很简单。其实,这种方法的弊端很大。
1.输出的PWM可能存在误差;
2.对整个系统的实时性可能有影响;
所以不建议使用该方法。
几种实现方法
使用两个定时器配合输出可调频率、占空比的PWM波形,且可指定输出脉冲个数的方法和原理其实不难。
输出PWM的方法就是使用TIM定时器自带有的PWM模式即可完成。主要难点在于还要控制指定输出脉冲的个数。
对于如何控制输出指定脉冲个数,下面大概说下三种方法:
1.脉冲中断计数法
IO中断,或者定时器同步(脉冲)中断。
定时器同步(脉冲)中断简单的说,就是利用定时器同时产生一个相同频率(或者说波形)的中断信号,在中断里面对其累计,累加个数为指定输出波形个数则关闭PWM波形的输出,同时关闭中断计数。
比如:我输出10个波形,10次中断(每次+1)之后,关闭输出。
它的原理,大致如下图:
此方法建议在输出高频PWM时不要使用,频繁中断对系统实时性也是有一定影响。 建议低于1KHz的PWM才使用此方法。
2.定时中断法
基于上面第一种,不适合高频PWM脉冲中断。经过思考,我们是否可以将多次中断的时间累加,只响应一次中断。
原理就是把定时的时间设定为单个脉冲的n倍(n个脉冲),只使用一次中断。
它的原理,大致如下图:
看图片中的提示,建议这个地方使用一个32位的定时器,这个值可能很大。
3.脉冲触发法
此方法可以避免上面两种方法中不足的地方, 相对上面两对实用性更强。电路上面,需要将PWM输出的波形,连接到另一个定时器的ETR引脚。
它的原理没什么特殊的,就是和我们常用的定时更新中断类似,只是输入信号改成PWM脉冲波形(默认为内部时钟CK_INT 如:36M)。
外部时钟源模式2实现方法
上面说过,使用PWM作为另一个定时器的输入时钟,即可达到对PWM计数的功能。
请参看手册中TIM定时器时钟选择章节。
1.输出PWM配置
void PWM_TIM_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(PWM_TIM_CLK, ENABLE); RCC_AHB1PeriphClockCmd(PWM_TIM_GPIO_CLK, ENABLE); GPIO_InitStructure.GPIO_Pin = PWM_TIM_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(PWM_TIM_GPIO_PORT, &GPIO_InitStructure);
GPIO_PinAFConfig(PWM_TIM_GPIO_PORT, PWM_TIM_SOURCE, PWM_TIM_AF);
TIM_TimeBaseStructure.TIM_Prescaler = PWM_PRESCALER; //预分频值 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数 TIM_TimeBaseStructure.TIM_Period = 0xFFFF; //定时周期 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //分频因子 TIM_TimeBaseInit(PWM_TIMx, &TIM_TimeBaseStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //PWM1模式 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //使能输出 TIM_OCInitStructure.TIM_Pulse = 0xFFFF; //脉宽值 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性 PWM_TIM_OCxInit(PWM_TIMx, &TIM_OCInitStructure); TIM_Cmd(PWM_TIMx, DISABLE); }
初始化频率和占空比填充的值是最大值,即TIM_Period = 0xFFFF;TIM_Pulse = 0xFFFF; 实际没有使能定时器(输出的配置见下面函数接口)
2.选择外部时钟,定时中断配置
void CNT_TIM_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(CNT_TIM_CLK, ENABLE); RCC_AHB1PeriphClockCmd(CNT_TIM_GPIO_CLK, ENABLE); GPIO_InitStructure.GPIO_Pin = CNT_TIM_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(CNT_TIM_GPIO_PORT, &GPIO_InitStructure);
GPIO_PinAFConfig(CNT_TIM_GPIO_PORT, CNT_TIM_SOURCE, CNT_TIM_AF);
NVIC_InitStructure.NVIC_IRQChannel = CNT_TIM_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = CNT_TIM_Priority; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);
TIM_ETRClockMode2Config(CNT_TIMx, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_Inverted, 0);
TIM_TimeBaseStructure.TIM_Prescaler = 0; //预分频值 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数 TIM_TimeBaseStructure.TIM_Period = 0xFFFF; //定时周期 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //分频因子 TIM_TimeBaseInit(CNT_TIMx, &TIM_TimeBaseStructure); TIM_ClearFlag(CNT_TIMx, TIM_FLAG_Update); TIM_ITConfig(CNT_TIMx, TIM_IT_Update, ENABLE); //使能"更新"中断 TIM_Cmd(CNT_TIMx, DISABLE); }
和常规的不同点在于: 使用外部时钟源
TIM_ETRClockMode2Config(CNT_TIMx, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_Inverted, 0);
注意检测(捕获)极性TIM_ExtTRGPolarity_Inverted,一般PWM都是高电平为脉冲波形,下降沿才算一个波形的计数。
3.输出PWM函数接口
void PWM_Output(uint32_t Frequency, uint32_t Dutycycle, uint32_t NumPulse) { uint32_t pwm_period; uint32_t pwm_pulse;
pwm_period = PWM_CK_CNT/Frequency - 1; //计算出计数周期(决定输出的频率) pwm_pulse = (pwm_period + 1)*Dutycycle / 100; //计算出脉宽值(决定PWM占空比) TIM_Cmd(PWM_TIMx, DISABLE); //失能TIM TIM_SetCounter(PWM_TIMx, 0); //计数清零 TIM_SetAutoreload(PWM_TIMx, pwm_period); //更改频率 PWM_TIM_SetComparex(PWM_TIMx, pwm_pulse); //更改占空比 TIM_Cmd(PWM_TIMx, ENABLE); //使能TIM TIM_Cmd(CNT_TIMx, DISABLE); TIM_SetCounter(CNT_TIMx, 0); TIM_SetAutoreload(CNT_TIMx, NumPulse-1); //设置中断更新数 TIM_ClearFlag(CNT_TIMx, TIM_FLAG_Update); TIM_Cmd(CNT_TIMx, ENABLE); }
void PWM_Output(uint32_t Frequency, uint32_t Dutycycle, uint32_t NumPulse);
我们只需要调用该函数接口就可以实现指定个数PWM输出了。中途不用软件参数,输出结束时自动响应定时中断,关闭定时器。
中断接口函数
void CNT_TIM_IRQHandler(void) {
if(TIM_GetITStatus(CNT_TIMx, TIM_IT_Update) != RESET) { TIM_ClearITPendingBit(CNT_TIMx, TIM_IT_Update); TIM_Cmd(PWM_TIMx, DISABLE); //关闭PWM输出 TIM_Cmd(CNT_TIMx, DISABLE); //关闭计数 } }
上一篇:STM32F407ADC多通道+定时器触发+DMA模式设置
下一篇:关于STM32进入低功耗模式后无法烧写程序的解决办法
推荐阅读
史海拾趣
Advantech公司是一家全球领先的工业计算机、自动化和嵌入式解决方案提供商,其发展历程充满了创新、合作和技术进步。以下是关于Advantech公司发展的五个相关故事:
创立与早期发展: Advantech公司成立于1983年,最初名为台湾多媒体公司,其初衷是提供音频和视频卡。随着技术的发展和市场需求的变化,公司逐渐转型为提供工业计算机和自动化解决方案的领先供应商。
全球化战略: 随着全球市场的不断扩大,Advantech制定了全球化战略,积极拓展海外业务。1994年,公司在美国成立了第一家子公司,标志着其国际化发展的开始。此后,Advantech陆续在欧洲、亚洲和其他地区建立了办事处和分支机构,构建起了覆盖全球的销售和服务网络。
技术创新与合作伙伴关系: 作为工业自动化领域的领导者之一,Advantech不断进行技术创新,并与全球各类合作伙伴密切合作。公司积极投入研发资金,不断推出新产品和解决方案,以满足客户不断变化的需求。同时,Advantech与众多软件和硬件供应商建立了紧密的合作关系,共同推动行业的发展。
智能化转型: 随着工业4.0和物联网的迅速发展,Advantech积极响应智能化转型的趋势,推出了一系列智能化解决方案,涵盖工业自动化、智慧城市、智能交通等多个领域。公司致力于为客户提供智能化、数字化的整体解决方案,助力其实现生产效率提升和智能化升级。
生态系统建设: 为了进一步提升解决方案的综合性和竞争力,Advantech积极构建生态系统,与行业合作伙伴共同打造全方位的服务体系。公司通过开放式的合作模式,与合作伙伴共享资源和技术,实现优势互补,共同拓展市场,推动行业的发展和进步。
以上述五个方面为基础,Advantech在电子行业中不断发展壮大,成为了全球工业自动化和智能化领域的领导者之一。
在电子技术的不断推动下,Global Specialties始终保持对新技术的高度敏感。公司不断投入研发资源,对现有产品进行升级换代,并推出了一系列具有创新性的新产品。例如,公司开发的智能测试仪器能够自动完成复杂的测试任务,大大提高了测试效率和准确性。这些技术创新不仅巩固了Global Specialties在业内的领先地位,还为公司带来了更多的商业机会。
近年来,AAC公司一直致力于技术创新和产品研发。在声学、光学、触感、传感器及半导体等领域,AAC积累了近三十年的技术经验。这些技术积累使得AAC能够不断推出具有创新性和竞争力的新产品。例如,AAC在某次创新峰会上发布了超宽频音质的Opera高低音分频方案、旗舰级体验大众化的声学触觉一体化Combo方案以及安卓触感“天花板级”的仿生振感马达等三大技术新品。这些新品的发布不仅彰显了AAC在电声元器件领域的技术实力,也为智能手机等消费电子行业注入了新的活力。
这五个故事只是AAC公司发展历程中的一部分,但它们足以展现AAC在电子行业中的不断进取和创新精神。从一个合资企业起步,到如今成为全球著名的电声元器件制造商之一,AAC凭借敏锐的市场洞察、坚定的发展决心以及持续的技术创新,在电子行业书写了自己的传奇篇章。
请注意,以上内容仅是基于参考文章的事实性描述,并未涉及对AAC公司的任何评价或判断。同时,由于我无法获取AAC公司的实时信息,因此以上内容可能与AAC公司的最新发展情况有所出入。如需了解更多关于AAC公司的最新信息,建议查阅相关新闻或访问AAC公司官方网站。
CSB公司深知人才是企业发展的核心竞争力。因此,公司一直注重人才培养和团队建设。通过建立完善的培训体系、提供丰富的职业发展机会、营造积极向上的企业文化等方式,CSB公司吸引了一批批优秀的人才加入。这些人才为公司的发展注入了新的活力,推动了公司在技术、市场、管理等方面的不断进步。
随着公司实力的增强,aconno开始积极拓展国内外市场。通过与各大电商平台和分销商建立合作关系,aconno的产品迅速覆盖了更广泛的地域和用户群体。此外,公司还积极参与国际电子展和技术交流会,与全球合作伙伴建立紧密的合作关系,共同推动电子行业的发展。
背景:在光伏胶膜领域取得成功后,福斯特开始寻求多元化发展。
发展:公司依托在光伏材料领域的技术积累和市场优势,逐步向电子电路、锂电等新材料领域拓展。同时,公司还成立了新材料研究院,专注于新材料的研发和创新。
成果:目前,福斯特在电子电路、锂电等领域也取得了显著成绩,为公司带来了新的增长点。
嵌入式的开发如今是变的越来越复杂,对嵌入式工程师的要求越来越高。如何从一个应届毕业生, 或者普通的工程师向嵌入式迈进呢。网络上的资料很多,书店的书籍也很多,但大家都很难下手或者靠自学提高。 在最近的公司招聘面试的过程中,发现很多面试者( ...… 查看全部问答∨ |
|
小弟我刚接触驱动开发,现在在学习PassThru,把书上的例子用VS2008+DDKWinWiard+XP SP3+DDK(server 03)编译PassThru 但是却出现了莫名奇妙的错误: c:\\MyProject\\PassThru\\PassThru\\miniport.c(74) : error C4013: \'NdisIMGetDeviceContext\ ...… 查看全部问答∨ |
|
撇开软件部分不说,单看硬件方面的设置: 1)基于ARM7裸机的串口简单的编程:如串口初始化,设置波特率,寄存器设置,中断向量设置等 2)自己基于CE下编一个串口驱动,也是要向上面一样设置ARM芯片的初始化吗?和裸机的那些设置是一样 ...… 查看全部问答∨ |
|
eboot.bin文件烧进系统以后,会自行压缩成eboot.nb0文件。我现在需要知道这个压缩的过程的代码是在哪个文件的哪个函数里的!有知道的吗??? 我找了F:\\WINCE500\\PUBLIC\\COMMON\\OAK\\DRIVERS\\ETHDBG\\BLCOMMON的BLCOMMON.c文件的DownloadImage函 ...… 查看全部问答∨ |
|
在这夏天,炎热酷暑。在这夏天,躲在架设有几十台电脑的实验室,狭窄的空间,空气是凝固的,室内气温自然上去了。就这样,度过了一个刻骨铭心的暑假!然而,一个暑假下来,付出是多,收获也是多的。你们是否记得, ...… 查看全部问答∨ |
我写了一个LM3S9B92的UART简单收发程序,想下载到开发板中,用的是IAR软件,和J-LINK仿真器,请高手指教一下具体的步骤,比如说软件的相关配置等等问题,谢了 我在下载的 过程中出现了这个问题 Fatal Error[Lc002]: could not open file ...… 查看全部问答∨ |
设计资源 培训 开发板 精华推荐
- 全球首款Cortex-M23内核物联网芯片SAML10和SAM L11系列 闯关获取SAML10/SAML11法宝,拆除电子界安全危机,赢好礼!
- 【EEWORLD第三十一届】2011年10月社区明星人物揭晓!
- 艾睿电子线上研讨会:英特尔FPGA深度学习加速技术 7月30日上午10:00-11:30 期待您的莅临!
- 【有奖问答】MOSFET,选型我在行!
- Microchip 喊你快来打造你的理想型单片机,智能门铃、百元京东卡等【80份】好礼等你赢!
- 有奖直播|物联网时代的典型应用
- 【在线研讨会讲义下载】TOF 技术介绍及产品应用
- 有奖直播:ams投影照明(MLA)增强汽车与道路的沟通
- 『ADI实验室电路DIY大赛』正式启动!