搜索
bottom↓
回复: 13

用AD转换改变PWM频率及占空比

[复制链接]

出0入0汤圆

发表于 2010-12-11 23:56:04 | 显示全部楼层 |阅读模式
有一个项目要输出一个频率及占空比都可调的PWM信号。现在我已经实现频率可调,但是占空比调节出现在问题。
当占空比调节输入转换后大于频率的值时就不会比较匹配,我的问题是用什么办法可以现在占空比连续可调呢?

我试过的方法是,当占空比输入的值大于频率输入的值时就把它减去(最大值-频率输入)。这样虽然可以调节占空比,但是如果频率不是输入最大值时占空电位器没有转满程就已经达到最大值了。

请问各位还有没有其他的办法呢?谢谢

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

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

发表于 2010-12-12 00:59:47 | 显示全部楼层
占空比是个比值 不可能大于1的,你怎么跟频率值比较还大于频率值呢.
你要是想在频率改变时不变占空比,有了频率值,一个乘法不就得出占空值了。 或许没明白对你的意思

出0入0汤圆

 楼主| 发表于 2010-12-12 08:34:18 | 显示全部楼层
回复【1楼】My5A1
-----------------------------------------------------------------------
谢谢关注,我是用两个电位器通过ADC来调频率和占空比。两个转换的值为0-255,假如某个频率OCRA的值只要100,而占空比最大值也就是OCRB的值是255,这时候OCRB不就大于OCRA了吗?这时的PWM就保持低或者是高了。

请问怎么再0-255转变成1%-90%呢?谢谢

出0入0汤圆

发表于 2010-12-12 09:17:50 | 显示全部楼层
占空比是一个比例,而不是一个确定的数据,因此占空比AD读取的数据可以先和256相比得到你希望的占空比,然后将这个比值*周期就得到了你想要的比较寄存器的数值,然后取整,送入寄存器中。这样说够明白的吧?

出0入0汤圆

 楼主| 发表于 2010-12-13 20:10:55 | 显示全部楼层
回复【3楼】tiancaigao7 天才杨威利
-----------------------------------------------------------------------

谢谢各位的关注,程序我已经写好了。明天我再发上来,下班时拷到卡里了却没带回家来。
我是被小数点给卡了,因为用“/”运算之后是没有小数的。我用了把原来的数乘以100最后结果再除以100。已经可以实现我所要的功能了。另外有一种方法是浮点运算,这个小弟不懂。希望知道的同学可以告知一声。谢谢

出0入0汤圆

发表于 2010-12-13 23:46:33 | 显示全部楼层
等待着lz的程序,小弟也学学

出0入0汤圆

发表于 2010-12-14 08:40:27 | 显示全部楼层
曾经大学时候做过,偷懒的,mega8 10bitad  只用了8bit,然后把采样进来的0-255的值,直接赋给OCRn,调节占空比

出0入0汤圆

 楼主| 发表于 2010-12-14 19:21:23 | 显示全部楼层
/******************************************
芯片型号:tiny13A
******************************************/

#include <avr/io.h>
#include <util/delay.h>
#include "adc_init.c"
#define unchar unsigned char
#define unint unsigned int

unchar counter,d,f;
unchar duty,freq,x;
int flag,a,c,b;

/****************************************************
                                        PWM初始化程序
*****************************************************/
void pwm_init()
{
        TCCR0B = 0X0c;
        TCCR0A = 0X23;  
        TCNT0 = 0;
}

/***************************************************
                                        PWM控制程序
***************************************************/

void pwm_con(void)
{
        if ((PINB & _BV(PB3)) != 0)//PB3输入低电平时启动PWM,搞电平停止
        {
                _delay_ms(1);
                if ((PINB & _BV(PB3)) != 0)
                {
                        TCCR0B = 0;
                        TCCR0A = 0;
                }
        }
        else
        {
                TCCR0B = 0x0c;
                TCCR0A = 0X23;
        }/**/
}

/*************************************************
                                PWM更新程序
*************************************************/

void pwm_set()
{
        if ((TIFR0 & (1 << OCF0B)) != 0)//
        {
                b = adc(2);//acd2
                f = adc(1);//acd1
                a = f;
                               
                if (b < 230)//控制占空比在90%以内
                {
                        b = (b * 100);//求占空比
                        x = (b / 256);
                        a = (a * x);
                        d = (a / 100);                               
                }

                OCR0A = f;
                OCR0B = d;       
                TIFR0 |= (1 << OCF0B);
        }
}

/************************************************
                                        主程序
************************************************/

int main()
{
        pwm_init();
        adc_init();
        DDRB = 0x23;
        while(1)
        {
                pwm_con();
                pwm_set();
        }
}

出0入0汤圆

 楼主| 发表于 2010-12-14 19:22:50 | 显示全部楼层
/*****************************************
名称:adc_init.c
ADC设置及转换程序
********************************************/

#include <avr/io.h>
#define unchar unsigned char
#define unint unsigned int

#define ADC_ON()   ADCSRA |= _BV(ADSC);
#define ADIF_CLR() ADCSRA |= _BV(ADIF);

unchar ad_data;

/***********************************************
                                ADC初始程序
***********************************************/
void adc_init(void)
{
        ADCSRA |= 0x86;
        ADMUX = 0x21;
        ADC_ON();
        ADMUX = 0x22;
        ADC_ON();
}

/************************************************
                                AD转换程序
************************************************/
unchar adc(unchar port)
{
        ADMUX = port|0x20;//选择通道
        ADC_ON();//启动转换

        while ((ADCSRA&(1<<ADIF)) == 0);//定待结果

        ad_data = ADCH;//保存结果
        ADIF_CLR();//清除标记

        return ad_data;//返回结果
}

出0入0汤圆

发表于 2010-12-14 20:06:00 | 显示全部楼层
学习

出0入0汤圆

发表于 2012-5-22 11:00:43 | 显示全部楼层
谢谢分享

出0入0汤圆

发表于 2012-5-25 09:44:08 | 显示全部楼层
好像很有趣的样子,拷回去玩玩~~

出0入0汤圆

发表于 2012-5-25 21:36:27 | 显示全部楼层
学习啦,谢谢~~~~

出0入0汤圆

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

本版积分规则

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

GMT+8, 2024-7-24 00:30

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

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