سلام علیکم
مشکلی که من با ان مواجه شده مربوط به تمرین کتاب آموزش AVR آقای الوندی فصل 6 تمرین 9 می باشد. من این کتاب را برای یادگیری می خوانم و لذا در صورت پاسخ به من، جنبه تمرین برای استاد و نمره و .... ندارد.
صورت مسئله: می خواهیم در ATmega16 برای یک موج با فرکانس ثابت و دوره وظیفه متغییر که به ورودی capture(PIND.6) اعمال می شود دوره وظیفه را با استفاده از کانتر 1 و capture اندازه گیری کرده و روی lcd نمایش دهیم. من برای شروع و تست فرکانس را 10khz و duty cycle(d.c.)=50% گرفتم(شکل موج در اسیلوسکوپ در شماتیک پروتئوس)
روش حل من: در حالت بالا رونده زمان را خوانده ودر متغییر K1 ذخیره شود و در لبه پایین رونده، زمان در متغییر K2 ذخیره شود و با توجه به رابطه d.c. ، مقدار آن را محاسبه کنم. من برای این حداقل 5 روز وقت گذاشتم (یک روز دیگرهم بدلیل یک مشکل در دیباگ در پروتئوس و جستجو برای راه حل ان در اینترنت تلف شد) لذا در صورت مساعدت ، بسیار ممنون می شوم.
من کد کدویژن را با پروتئوس دیباگ کردم چیزی که من مشاهده کردم این بود که در جاهایی که من انتظار دارم مقدار سیگنال صفر باشد یهو یک می شود و یا بالعکس. مثلا با شروع از یک حالت صفر پس از 3 یا 4 پالس ساعت یهو به وقفه کپچر(capcher) می رود در حالیکه نباید چنین باشد . می خواستم در سایت eca.ir پیام و پست بگذارم ولی نمی دانستم آنجا چگونه کدها و شماتیک پروتئوس را قرار دهم( چند وقت قبل یک میل به مدیر سایت زدم و از ایشان برای روش پلود عکس و کدو.. راهنمایی خواستم ولی جوابی نیامد.یک قسمت برای راهنمایی و یا یک میل برای پشتیبانی به غیر از میل مدیر سایت پیدا نکرم)
مسئله ای که من دربرنامه هم خواستم به ان توجه کنم این است که فرض کنیم PIND.6 مقدارش تغییرکند ولی باید مدنظر قرار داد که این می تواند بدلیل نویز باشدحال برای این مشکل مثلا در ابتدای برنامه 5 بارپشت سرهم PIND.6 را می خوانم اگر 5 بار ثابت بود دلیل تغییرنویز نیست. ایا شما روش بهتری سراغ دارید؟
خیلی طولانی شد . خلاصه دمار من در امده و اعصاب خط خطی شده. اگر کمک کنید ممنون وتشکر.
کد :
#include <mega16.h>
#asm
.equ __lcd_port=0x1B; // port a connected to lcd
#endasm
#include <lcd.h>
#include <stdio.h>
#include <delay.h>
typedef unsigned long int unli;
typedef unsigned char unch;
unli oldtemp=0,freq=10000; // freq=10khz , wave frequency
unli clk =8000000; // clock frequency
volatile unli k1=0,k2=0;
volatile unch flag=1; // when flag=1, in rising edge capturing occured and
// when flag=0, in falling edge capturing occured.
void lcd_display(unli k1,unli k2){
float number=0.0;
char buff[20];
lcd_clear();
lcd_gotoxy(2,0);
lcd_putsf("duty cycle %= "

lcd_gotoxy(2,1);
number=100*(float)(k2-k1+1)/(0XFFFF-0XFCE0+1);
sprintf(buff,"%3.1f",number);
lcd_puts(buff);
//delay_ms(1000);
}
interrupt [TIM1_OVF] void timer1_ovf_isr(void){
unsigned char temp=0;
temp=TCCR1B;
TCCR1B=0X00;
TCNT1H=0XFC;
TCNT1L=0XE0; // OR TCNT1=0XFCE0;
TCCR1B=temp;
}
interrupt [TIM1_CAPT] void timer1_capt_isr(void){
unli newtemp=0;
TCCR1B=0X00;
#asm("cli"

if (flag==1) {
k1=ICR1L+ ((long)(ICR1H)*256) ;
TCCR1B=0X81;
}
else {
k2=ICR1L+(long)ICR1H*256;
TCCR1B=0XC1;
newtemp=k2-k1;
if (newtemp != oldtemp) lcd_display(k1,k2);
oldtemp=newtemp;
};
flag= ! flag;
//TIFR |= 0b00100000;
#asm("sei"

}
void main(void)
{
unch i1=0,i2=0,i3=0,i4=0,i5=0;
lcd_init(16);
lcd_clear();
lcd_gotoxy(2,0);
lcd_putsf("lcd ready ok "

delay_ms(250);
DDRA=(0<<DDA7) | (0<<DDA6) | (0<<DDA5) | (0<<DDA4) | (0<<DDA3) | (0<<DDA2) | (0<<DDA1) | (0<<DDA0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
PORTA=(0<<PORTA7) | (0<<PORTA6) | (0<<PORTA5) | (0<<PORTA4) | (0<<PORTA3) | (0<<PORTA2) | (0<<PORTA1) | (0<<PORTA0);
DDRD=(0<<DDD7) | (0<<DDD6) | (0<<DDD5) | (0<<DDD4) | (0<<DDD3) | (0<<DDD2) | (0<<DDD1) | (0<<DDD0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
PORTD=(0<<PORTD7) | (0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (0<<PORTD1) | (0<<PORTD0);
ICR1H=0X00;
ICR1L=0X00;
TCCR1A=0X00;
TCNT1H=0XFC;
TCNT1L=0XE0;
TIMSK= 0X24;
TIFR=0X24;
while(1){
while (PIND.6==1);
i1=PIND.6; // i1 to i5 is used for PIND.6 --
// --changing to zero is not beacause of noise,
// namely for 5 clock cycle PIND.6 must be zero.
i2=PIND.6;
i3=PIND.6;
i4=PIND.6;
i5=PIND.6;
if( (i1==0)&(i2==0)&(i3==0)&(i4==0)&(i 5==0)) break;
};
TCCR1B=0XC1;
#asm("sei"

while (1) {} ;
}
دیدگاه