搜索
bottom↓
回复: 19

我做的M16捕捉及12位PWM输出试验

[复制链接]

出0入0汤圆

发表于 2005-5-28 10:22:25 | 显示全部楼层 |阅读模式
经过一段时间的摸索,ICP及PWM终于取得了收获。我要做的实验是要求ICP进行捕捉来测量脉冲的频率,计算出的结果显示在5位LED数码管上,同时利用12位的PWM输出测量结果。测量电路与以前做过的“M16频率测量及PWM”一文的电路相同,脉冲信号输入到T0及ICP引脚。各计数器的作用如下:

Timer0:对外部脉冲进行计数,使用溢出中断,在其中断服务程序中对溢出次数进行计数;

Timer1:ICP捕捉及PWM控制,工作在方式15,OCR1A的值定为0x0FFF,使用ICP捕捉中断和溢出中断。 溢出中断服务程序中对Timer1的溢出次数进行计数,ICP中断服务程序中读出Timer0的TCNT0及其溢出次数、Timer1的溢出次数及ICR1的值,并且允许中断嵌套;

Timer2:工作在CTC方式,产生1mS的定时中断,用于LED数码管的动态扫描和测量闸门的控制。

在开始试验时,由于开放的中断比较多,其实际的响应与我的设想存在偏差,因此测量的结果总是不稳定,表现为显示值随机跳动比较的大。通过JTAG的观察发现,引起这种原因的根源在于,T0、T1及ICP的中断可能同时触发,而根据AVR的中断优先级设定,ICP会抢先进入中断,导致了ICP中断服务程序中读到的T0或T1的溢出值不正确,最终影响依次计算结果。当采用了中断嵌套方式后,这个问题基本上得到了解决,出现异常的情况已经无法用肉眼观察到。

程序用CVAVR编写,源码如下:

/*********************************************

This program was produced by the

CodeWizardAVR V1.23.8d Professional

Automatic Program Generator

?Copyright 1998-2003 HP InfoTech s.r.l.

http://www.hpinfotech.ro

e-mail:office@hpinfotech.ro



Project :

Version :

Date    : 2005-5-23

Author  : Bucker

Company :

Comments:





Chip type           : ATmega16L

Program type        : Application

Clock frequency     : 8.000000 MHz

Memory model        : Small

External SRAM size  : 0

Data Stack size     : 256

*********************************************/



#include <mega16.h>

#include <sbit.h>

#define EnableICP 10



flash char LedDat[]={/*0,1,2,3,4,5,6,7,8,9,A,b,C,d,E,F,-,*/

0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x58,0x5E,0x79,0x71,0x40};

unsigned char LED[6],Status=0,Time0H,Time0L,Timer0H=0;

unsigned int Timer1H=0,Time1H,Time1L,Na=0;



// Timer 0 overflow interrupt service routine

interrupt [TIM0_OVF] void timer0_ovf_isr(void)

{

        // Place your code here

        Timer0H++;

}



// Timer 1 overflow interrupt service routine

interrupt [TIM1_OVF] void OldTimer1_ovf_isr(void)

{

        // Place your code here

        Timer1H++;

}



#pragma savereg-



// Timer 1 input capture interrupt service routine

interrupt [TIM1_CAPT] void OldTimer1_capt_isr(void)

{

        // Place your code here

        unsigned char sREG;

        #asm("sei")

        #asm("st -y,r30")

        sREG=SREG;

        Time0L=TCNT0;

        Time1L=ICR1;

        Time1H=Timer1H;

        Time0H=Timer0H;

        BitSet(Status,0);

        BitClr(TIMSK,5);

        Na=0;

        SREG=sREG;

        #asm("ld r30,y+")

}



#pragma savereg+



// Timer 2 output compare interrupt service routine

interrupt [TIM2_COMP] void timer2_comp_isr(void)

{

        // Place your code here

        static char Nb=0;

        #asm("sei")

        if (Nb<5)

        {

                PORTA=LED[Nb];

                PORTD&=0xF8;

                PORTD|=Nb;

        }

        else PORTA=0x00;

        if (++Nb>10) Nb=0;

        if (Na<60000)

        {

                if (Na++>EnableICP)

                {

                        BitSet(TIFR,5);

                        BitSet(TIMSK,5);

                }

        }

}



// Declare your global variables here



void main(void)

{

        // Declare your local variables here

        unsigned int a,b=0,OldTimer0,Timer0;

        unsigned long L,OldTimer1,Timer1,Temp1,Temp0;

        // Input/Output Ports initialization

        // Port A initialization

        // Func0=Out Func1=Out Func2=Out Func3=Out Func4=Out Func5=Out Func6=Out Func7=Out

        // State0=0 State1=0 State2=0 State3=0 State4=0 State5=0 State6=0 State7=0

        PORTA=0x00;

        DDRA=0xFF;



        // Port B initialization

        // Func0=In Func1=In Func2=In Func3=In Func4=In Func5=In Func6=In Func7=In

        // State0=T State1=T State2=T State3=T State4=T State5=T State6=T State7=T

        PORTB=0x00;

        DDRB=0x00;



        // Port C initialization

        // Func0=In Func1=In Func2=In Func3=In Func4=In Func5=In Func6=In Func7=In

        // State0=T State1=T State2=T State3=T State4=T State5=T State6=T State7=T

        PORTC=0x00;

        DDRC=0x00;



        // Port D initialization

        // Func0=Out Func1=Out Func2=Out Func3=In Func4=Out Func5=In Func6=In Func7=In

        // State0=0 State1=0 State2=0 State3=T State4=T State5=T State6=T State7=T

        PORTD=0x00;

        DDRD=0x07;



        // Timer/Counter 0 initialization

        // Clock source: T0 pin Rising Edge

        // Mode: Normal top=FFh

        // OC0 output: Disconnected

        TCCR0=0x07;

        TCNT0=0x00;

        OCR0=0x00;



        // Timer/Counter 1 initialization

        // Clock source: System Clock

        // Clock value: 8000.000 kHz

        // Mode: Fast PWM top=OCR1A

        // OC1A output: Discon.

        // OC1B output: Non-Inv.

        // Noise Canceler: Off

        // Input Capture on Falling Edge

        TCCR1A=0x23;

        TCCR1B=0x19;

        TCNT1H=0x00;

        TCNT1L=0x00;

        ICR1H=0x00;

        ICR1L=0x00;

        OCR1AH=0x0F;

        OCR1AL=0xFF;

        OCR1BH=0x00;

        OCR1BL=0x00;

        // Timer/Counter 2 initialization

        // Clock source: System Clock

        // Clock value: 250.000 kHz

        // Mode: CTC top=OCR2

        // OC2 output: Disconnected

        ASSR=0x00;

        TCCR2=0x0B;

        TCNT2=0x00;

        OCR2=0xF9;



        // External Interrupt(s) initialization

        // INT0: Off

        // INT1: Off

        // INT2: Off

        MCUCR=0x00;

        MCUCSR=0x00;



        // Timer(s)/Counter(s) Interrupt(s) initialization

        TIMSK=0xA5;



        // Analog Comparator initialization

        // Analog Comparator: Off

        // Analog Comparator Input Capture by Timer/Counter 1: Off

        // Analog Comparator Output: Off

        ACSR=0x80;

        SFIOR=0x00;



        // Global enable interrupts

        #asm("sei")



        while (1)

        {

                // Place your code here

                if (BitTst(Status,0))

                {

                        Timer0=Time0L|(unsigned int)Time0H<<8;

                        Timer1=Time1L|(unsigned long)Time1H<<16;

                        L=8e6/59986*60000/(Temp1=(Timer1-OldTimer1))*(Temp0=(Timer0-OldTimer0));

                        if (L/10!=9932)

                        {

                                if (b++>2)

                                {

                                        PORTA=0x00;

                                        b=0;

                                }

                        }

                        OldTimer1=Timer1;

                        OldTimer0=Timer0;

                        LED[0]=LedDat[L/10000];

                        a=L % 10000;

                        LED[1]=LedDat[a/1000];

                        a%=1000;

                        LED[2]=LedDat[a/100];

                        a%=100;

                        LED[3]=LedDat[a/10];

                        LED[4]=LedDat[a % 10] | 0x80;

                        BitClr(Status,0);

                }

        }

}



原理图可参考点击此处打开armok0150871.pdf




-----此内容被bucker于2005-05-28,11:07:16编辑过

出0入0汤圆

发表于 2007-4-29 11:34:14 | 显示全部楼层
正是我现在做的实验!!可以参考一下!顶一下!!!!!!!

出0入0汤圆

发表于 2007-12-10 19:11:46 | 显示全部楼层
谢谢楼主~~~

出0入0汤圆

发表于 2007-12-11 11:15:37 | 显示全部楼层
楼主,我觉的只用ICP捕获脉冲就可以了也就是设置timer1就可以了,还用timer0干吗?解释一下可以吗?

出0入0汤圆

发表于 2007-12-11 17:20:28 | 显示全部楼层
楼主,在吗?

出0入0汤圆

 楼主| 发表于 2007-12-17 19:47:26 | 显示全部楼层
Timer0是进行外部脉冲技术的,如果只用ICP端捕获单脉冲,在测量高频信号时会出现测量结果较大的跳动。

出0入0汤圆

发表于 2009-1-5 16:25:34 | 显示全部楼层
嗯,学习一下!

出0入0汤圆

发表于 2009-1-4 17:22:13 | 显示全部楼层
很奇怪,为什么我也用的mega16,而且也用的输入捕捉功能,但是捕捉功能老是少脉冲,是怎么回事啊?

出0入0汤圆

发表于 2008-10-14 20:08:11 | 显示全部楼层
受益很大,谢谢LZ。

不过要是我想捕捉测量的不是脉冲的频率,而是脉冲的脉宽,因为ICP及PWM都要用到TCNT1寄存器,是不是就不能同时使用了?

出0入0汤圆

发表于 2008-10-14 22:31:53 | 显示全部楼层
ark

出0入0汤圆

发表于 2008-10-14 20:50:18 | 显示全部楼层
正好用到,参考下~

出0入0汤圆

发表于 2010-9-1 15:25:53 | 显示全部楼层
学习!!!!!!

出0入0汤圆

发表于 2011-1-1 13:22:11 | 显示全部楼层
icp与pwm T1同时可用

出0入0汤圆

发表于 2011-1-1 23:08:15 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-1-17 16:27:29 | 显示全部楼层
MARK

出0入0汤圆

发表于 2011-1-21 10:37:43 | 显示全部楼层
谢谢楼主

出0入0汤圆

发表于 2011-1-21 12:09:57 | 显示全部楼层
mark!

出0入0汤圆

发表于 2011-1-22 10:24:25 | 显示全部楼层
焊!!!!!!

出0入0汤圆

发表于 2011-4-17 14:07:48 | 显示全部楼层
mark

出0入0汤圆

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

本版积分规则

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

GMT+8, 2024-5-8 09:13

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

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