利用stm32来产生1M,1K,1Hz的3个方波(转)

http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=3762261&bbs_page_no=1&bbs_id=3020

 下面把问题具体化: 

    1。利用微控制器来产生1M、1K、1Hz的3个方波 
    2。3个方波都必须非常精准(假定系统使用的晶体是非常准确的) 
    3。效率要高,包括代码短,占用CPU的时间少,因为STM32不能产生了3个方波后,其他的事情就做不了。 
    4。最后考虑如何实现3个方波的同步问题 

二、问题的讨论与分析 
     
    产生方波,当然是使用T/C了。那么为什么说“T/C溢出中断+中断服务,在中断服务中将某个I/O输出取反......”是“愚蠢的”?大多数的书上不都是这样介绍和举例的吗(尤其是那些只会51的朋友,可能也就认为这是唯一的方法了)。 

     先说说“枪毙”上面方法的原因。如果是产生1K的方波,或许还能马马乎乎说的过去。可是1M的方波就有问题了。要产生频率为1M的方 波,那么周期是1us,T/C的定时中断间隔为0.5us(取反输出,2次为一个方波周期)。在看STM32的系统时钟,最高为72M。那么在0.5us 内,STM32能执行几条指令?大约36条(按1MPS/1M算)指令执行的时间。如果考虑中断的响应需要的时间,中断现场保护和中断现场恢复,中断退出 的时间,在中断服务中你能做多少事情? 

      就算你水平高,使用汇编,在中断中能完成1M方波的以及另外2个方波的产生,你的STM32还能做什么事情?已经被这3个方波吊死了! 
  
      因此,正确的方法,应该采用定时器配备的比较匹配输出功能,或PWM波的产生功能(50%的PWM)。由于这2个定时器的增强功能在 51中是没有的,所以很多人不会想到这点。但是新的微控制器中配备定时器都具备这样的功能,10几年前推出的AVR就已经有了,何况是STM32? 

     当然用STM32,就要认真学习STM32的手册(至少看2份:STM32 103器件手册和硬件参考声明书)。我是要用STM32通用的几个T/C来做这件事,所以重点看TIMx的部分。 
      
     天呀,STM32的通用T/C功能如此的强大和复杂,不得不仔细学习。 

     经过分析和研究,决定采用TIM2产生1M方波,采用TIM3产生1K方波,具体的思路、方法和具体计算与主要的配置如下:

     1。系统采用8M外部晶体产生的时钟,(不使用PLL) 
     2。AHB和APB1的分频系数都是1,时钟为8M。APB1可以提供TIM2、TIM3、TIM4作为计数时钟,本例中只将APB1作为TIM2的计数时钟:8M 
     3。TIM2使用8M的APB1作为计数时钟,TIM2的预分频器为1分频,采用通道4比较匹配,触发取反输出TIM2_OC4(在PA3脚)。 
     4。TIM2的重载寄存器为3(4分频),C4通道比较寄存器为3 
     5。TIM2设置为主定时器,比较相等事件产生触发时钟(2M),作为TIM3的计数时钟 
  
     6。TIM3使用TIM2比较相等事件产生的触发时钟2M作为计数时钟,TIM3的预分频器为1分频,采用通道1比较匹配,PWM方式1工作,输出TIM3_OC1(在PA6脚)。 
     7。TIM3的重载寄存器为1999(2000分频),C1通道比较寄存器为1000 
     8。TIM3设置为副定时器,采用TIM2比较相等事件产生触发时钟(2M)作为计数时钟(由于TIM2、TIM3都是硬件计数,保证TIM2的产生1M方波和的TIM3产生的1K方波完全同步) 

     简单说明一下: 
      
     TIM2采用比较匹配后自动触发取反输出的工作方式,TIM2从0计数到3后与比较寄存器的值相等了,当第4个计数脉冲到后,自动将 PA3的引脚电平取反,同时由于TIM2的重载值也为3,因此第4个计数脉冲到后TIM2返回0开始计数,所以8个计数脉冲,PA3输出一个方波,相当与 8M/8,产生1M方波。 
      
     TIM2同时为主定时器,产生1M方波,就有2M的比较相等事件发生,该2M事件作为TIM3的计数时钟,由TIM3分频后产生1K方波(参考:STM32F10xxx硬件参考手册的使用一个定时器作为另一个的预分频器部分)。 

     TIM3采用PWM工作方式产生1K的方波。计数值到1000,与比较寄存器的值相等,会自动把PA6取反,当计数值到达1999后, 与重载寄存器相同,第2000个计数脉冲到达,TIM3自动回0,并再次把PA6取反。这样在PA6脚上产生与PA3上1M方波同步的1K方波。 

     以上产生1M和1K的方波方法,只要做完TIM的初始化后,在PA3和PA6上自动产生了,不需要使用任何中断,以后程序也不需要做任何的控制和管理(相当硬件产生的方波),CPU可以完全让出做其他的事情。效率极高! 

     下面是具体工程代码,更具体的配置请参考代码配置和器件手册学习体会吧。我还是使用STM32_Init.c进行初始化配置的,比使用库简单方便,而且易懂。点击此处下载  ourdev_513426.rar(文件大小:303K)   (原文件名:stm32_demo_4.rar)   

      例程中只是产生1M、1K方波。利用TIM4,采用相同的方法,再产生1个1Hz的方波应该是没有问题的。赶兴趣的自己试试吧。 

三、注意点: 
    1。如果TIMx采用内部系统时钟作为计数时钟的话,还需要经过几关:系统时钟----》AHB时钟(带分频器)----》APB1(带分频器)。APB1的最高频率为36M。 
    2。TIMx本身的分频器,0为1分频,1为2分频,2为3分频...... 
    3。TIMx的重载寄存器中的值,就是计数器的上限值,当计数器工作在单程UP方式时,到达重载寄存器中的值,再下一个脉冲就是溢出, 
    4。自动比较匹配输出或PWM的输出引脚通常为2个,可以通过软件配置选择其中的一个。本例中采用确省的输出脚,没有重新配置。 

    STM32的TIMx功能非常强大,能提供了多种不同的方式来实现本题3个方波的产生。当然,功能越强,使用也越复杂。希望本应用笔记能起到抛砖引玉的作用。 
以下是使用STM32 HAL库检测1MHz方波频率的示例代码: ```c #include "main.h" #include "stm32f1xx_hal.h" /* 配置TIM2 */ void MX_TIM2_Init(void) { TIM_ClockConfigTypeDef sClockSourceConfig = {0}; TIM_MasterConfigTypeDef sMasterConfig = {0}; htim2.Instance = TIM2; htim2.Init.Prescaler = (SystemCoreClock / 1000000) - 1; htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.Period = 0xFFFFFFFF; htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; if (HAL_TIM_Base_Init(&htim2) != HAL_OK) { Error_Handler(); } sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK) { Error_Handler(); } sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK) { Error_Handler(); } } int main(void) { HAL_Init(); MX_TIM2_Init(); HAL_TIM_Base_Start(&htim2); /* 计算捕获寄存器的最大值 */ uint32_t maxCapture = 0xFFFFFFFF / HAL_RCC_GetHCLKFreq(); while (1) { /* 捕获捕获计数器的值 */ uint32_t capture = __HAL_TIM_GET_COUNTER(&htim2); /* 如果计数器溢出,则重置计数器 */ if (capture > maxCapture) __HAL_TIM_SET_COUNTER(&htim2, 0); /* 延迟1秒 */ HAL_Delay(1000); /* 计算方波频率 */ uint32_t frequency = capture * HAL_RCC_GetHCLKFreq(); printf("Frequency: %lu Hz\n", frequency); } } ``` 请注意,这只是演示如何使用STM32 HAL库检测1MHz方波频率的示例代码。您需要根据自己的具体硬件和使用情况进行适当的修改。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值