背景:IDF版本V5.1.2 ,配置ESP32 通用定时器,实现100HZ,占空比50% 的PWM波形。
根据乐鑫官方的IDF指导文档设置内部计数器的分辨率,计数器每滴答一次相当于 1 / resolution_hz 秒。
(ESP-IDF编程指导文档:通用定时器 - ESP32 - — ESP-IDF 编程指南 release-v5.1 文档)
那我们根据官方的指导编写初始化ESP32通用定时器的代码:
设置 分辨率 resolution_hz = 1000,重装载值 reload_count = 5,
那根据计算 PWM周期 =1/((resolution_hz *reload_count )*2) = 1/(1000*5*2) = 0.1 ms = 100HZ
但是实际上,按照上面的代码调用gpTimer_Init(1000,10)配置,ESP32 gptimer通用定时器初始化报错:assert failed: timer_ll_set_clock_prescale /IDF/components/hal/esp32s3/include/hal/timer_ll.h:86 (divider >= 2 && divider <= 65536)
通过上面的报错,我们找到timer_ll_set_clock_prescale 函数的源代码:
通过查看timer_ll_set_clock_prescale 源码,我们发现该函数设置的分频值divider 必须是2~65536 !
分析:乐鑫官方的IDF指导文档设置内部计数器的分辨率,计数器每滴答一次相当于 1 / resolution_hz 秒,其中的resolution_hz 实际上并不是真正设置的分频值!!!
查看源码我们发现:gptimer_new_timer();会调用gptimer_select_periph_clock();然后调用timer_ll_set_clock_prescale();去设置真正的分频值!
通过上面的分析,想必大家都已经明白了问题的所在了:
乐鑫官方文档写的定时器 分辨率 =1 / resolution_hz 秒。其中的resolution_hz 不是定时器的预分频值(divider),只是分辨率!是为了开发者更方便设置定时器,但是resolution_hz 的值并不能随意设置。
由于ESP32的通用定时器的时钟源APB为80MHZ,且分频器是16位的。
所以 2 =< divider <= 65536
那么 80000000/65536 = 1221 <= resolution_hz <= 40000000 = 80000000/2
综上所述:乐鑫官方的定时器分辨率中的 resolution_hz 最大设置为40000000,最小1221 !
所以我gpTimer_Init(1000,10)配置resolution_hz =1000,定时器初始化就会报错:assert failed: timer_ll_set_clock_prescale /IDF/components/hal/esp32s3/include/hal/timer_ll.h:86 (divider >= 2 && divider <= 65536)。
正确应该 调用gpTimer_Init(10000,50)设置 分辨率 resolution_hz = 10000,重装载值 reload_count = 50,1/((1/10000)*50*2))=100HZ。
就可以实现100hz 50% 占空比的PWM。
要是想测试 resolution_hz 最大设置为40000000 可以调用 gpTimer_Init(40*1000*1000,200*1000);也可以实现100hz 50% 占空比的PWM。