搜索
bottom↓
回复: 20

请教如何用4M的MCU IO模拟产生2K PWM

[复制链接]

出0入0汤圆

发表于 2019-5-23 11:18:05 | 显示全部楼层 |阅读模式
请教如何用4M的MCU IO模拟产生2K  PWM
占空比0-100%可调,分100阶, 主函数中任务还有AD扫描检测 1ms扫描检测一次.
这个产品主要用于PWM调光用,频率太低了 会闪,所以至少要2K的频率
但是芯片的速度又有限制,大家有什么好的办法。

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2019-5-23 11:23:20 | 显示全部楼层
用汇编写没有问题。

出0入0汤圆

发表于 2019-5-23 12:00:10 | 显示全部楼层
本帖最后由 lcw_swust 于 2019-5-23 12:01 编辑

void timer0()
{
POUT=1;
delay(t);
POUT=0;
}
占空比大的话就反个相

出0入0汤圆

发表于 2019-5-23 12:09:32 来自手机 | 显示全部楼层
建议使用pwm外设

出50入10汤圆

发表于 2019-5-23 12:09:41 | 显示全部楼层
本帖最后由 our2008 于 2019-5-23 12:10 编辑

调光要不闪的话,几百Hz就可以了!

但是控制电流的PWM 得用外部器件!

出0入0汤圆

发表于 2019-5-23 14:17:21 | 显示全部楼层
IIC 或者其他的 SPI 一类的 PWM 调光芯片吧!

出0入0汤圆

发表于 2019-5-23 14:27:36 | 显示全部楼层
本帖最后由 innovision 于 2019-5-23 14:30 编辑

有没有定时器中断可以用呢?
如果有的话,设定1个500us的定时中断。
在中断程序中,进行判断。
duty 小于50%的时候,在中断中直接硬延时输出高电平;其它CPU时间留给主程序
duty 大于50%的时候,在中断中硬延时输出低电平,其它CPU时间留给主程序。

10多年前,我们用PIC16F676(外部20M RC,4个时钟周期,相当于5M 指令周期)可以做到62K的PWM输出,用于充电器的。当时带PWM跟ADC的芯片还是挺贵的

出0入4汤圆

发表于 2019-5-23 14:37:21 | 显示全部楼层
软件模拟的话,2K的PWM,200阶,需要200K的Tick,4M的主频,有点够呛。

出0入0汤圆

发表于 2019-5-23 14:56:58 | 显示全部楼层
STM32 STM8S 都有现在的PWM为何不用?

出0入4汤圆

发表于 2019-5-23 20:47:43 来自手机 | 显示全部楼层
感觉用fpga很轻松,内部有rc的

出0入0汤圆

发表于 2019-5-23 21:13:34 | 显示全部楼层
很肯定地说,IO口模拟做不到,即使8M频率都做不到。换带硬件PWM的吧,又贵不了多少。

出0入0汤圆

发表于 2019-5-23 21:30:03 | 显示全部楼层
利用定时器的计数器在主循环里面不停的判断,还是可以模拟 PWM的

定时器是有吧,如果连定时器都没有,那我这个方法是帮不了你的。。



  1. u8 r_pwm;  
  2. u8 g_pwm;
  3. u8 b_pwm;

  4. //假如定时器的计数寄存器值溢出值为 100,那么当你开了定时器之后,这个counter的值会在  0-99之间循环变化的

  5. //假如红灯的的占空比的数值为  r_pwm = 30的时候,你在主循环不停的刷新以下if语句,就能实现最高亮度的 30%(大约范围):

  6. if(r_pwm> counter)     RedLed = LED_ON;
  7. else                           RedLed = LED_OFF;               


  8. //当你把r_pwm的数值改大或改小,就基本模拟出来 PWM了
复制代码

出0入0汤圆

发表于 2019-5-23 21:31:32 | 显示全部楼层
我都在一个很低端的MCU上面模拟出三路的调光PWM,这个算法有个缺点,就是亮度比较低的时候容易抖动。

出0入76汤圆

发表于 2019-5-23 21:34:06 | 显示全部楼层
这个MCU内部有没有Tiimer ?  有: 好办(定时器可以搞定)。 无: 即然有ADC, 那看能不能把ADC的这个采样中断(连续转换时采样分频的时间能否满足要求)当定时器中断用。
若这些都无的话, 看是否允许将4M主频,提高到8M以上, 否则换MCU吧

出50入0汤圆

发表于 2019-5-23 22:00:56 | 显示全部楼层
本帖最后由 abc220 于 2019-5-23 22:04 编辑

7楼的方法可行,也类似这样用过。100us的定时器中断里面硬延时跑小于50%周期的那段电平。用这个方法8MHz主频,指令周期4分频,相当于2MHz指令周期,输出10K的频率无压力。

出0入0汤圆

发表于 2019-5-24 00:30:39 来自手机 | 显示全部楼层
7楼的方法也不错,又学了一招。标记一下软件模拟pwm

出0入0汤圆

发表于 2019-5-24 01:15:24 | 显示全部楼层
innovision 发表于 2019-5-23 14:27
有没有定时器中断可以用呢?
如果有的话,设定1个500us的定时中断。
在中断程序中,进行判断。

如果有两个定时器配合,还能给应用留出更多时间。一个200k的定时器置高,如果高电平时间大于一个阀值,就设定另一个定时器置低。如果小于阀值则用指令延时置低。这个阀值根据进入中断开销实际确定。
如果对频率要求不严格,也可以共用一个定时器。

出0入0汤圆

发表于 2019-5-24 11:32:57 | 显示全部楼层
只要每次修改定时器的时间,一个定时器就可以;

出0入50汤圆

发表于 2019-5-24 17:30:06 | 显示全部楼层
曾经在16.5889MHz的1T51上用过这样的软件PWM,不过为了速度快,我是用了2个定时器(反正空着,不用白不用啊),分别定时高低电平时长的时间,这样中断处理简单快速。不过即使如此,占空比在接近0和100%的时候,定时器仍然会很尴尬,而硬件PWM则没有这个问题。好在我的应用是不需要用到两端极限的,在5~95%的占空比期间,生成的PWM波占空比还是很准确的,因为转换到DAC的模拟量信号的线性非常好。

出0入296汤圆

发表于 2019-5-24 17:42:41 | 显示全部楼层
主循环里跑个计数器……就是不不停的自增的那种,然后搞个简单的变量去比较匹配……
一个简单的PWM模拟就搞定了。

楼主的2K其实只是一个柔性的要求……真正刚性的是100阶的精度而已……那么小气干啥,搞个128的……
也就是


  1. uint_fast8_t chCounter = 0;
  2. uint_fast8_t chThreshold = 64;

  3. while(1) {

  4.     chCounter++;
  5.     chCounter &= 0x7F;

  6.     if (chCounter > chThreshold ) {
  7.          set_io_high();
  8.     } else {
  9.          set_io_low();
  10.     }
  11. }
复制代码

原理就是这样,至于其它任务,做成非阻塞的就行了……

记得开最高的性能优化……
剩下看你的基本功了。

出10入10汤圆

发表于 2019-5-24 18:02:09 | 显示全部楼层
innovision 发表于 2019-5-23 14:27
有没有定时器中断可以用呢?
如果有的话,设定1个500us的定时中断。
在中断程序中,进行判断。

好方法,学习了
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-21 18:52

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表