ايران ويج

نسخه‌ی کامل: این برنامه چطور کار می کنه؟
شما در حال مشاهده‌ی نسخه‌ی متنی این صفحه می‌باشید. مشاهده‌ی نسخه‌ی کامل با قالب بندی مناسب.
سلام
خوب هستید

دوستان و اساتید بزرگوار من یک تکه کد مربوط به دستگاه اندازه گیری اولتراسونیک دارم که ظاهرا درست هم کار می کنه.

می خواستم اگر ممکنه نحوه کار و طرز استفاده و معنا و مفهوم دستورات رو یه مختصر برام توضیح بدید بلکه ما هم از کار شما سر در آوردیم!! Wink

کد:
/*****************************************************
This program was produced by the
CodeWizardAVR V2.05.3 Standard
Automatic Program Generator
© Copyright 1998-2011 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com

Project :
Version :
Date    : 8/28/2014
Author  : PerTic@n
Company : If You Like This Software,Buy It
Comments:


Chip type               : ATmega32
Program type            : Application
AVR Core Clock frequency: 8.000000 MHz
Memory model            : Small
External RAM size       : 0
Data Stack size         : 512
*****************************************************/

#include <mega32.h>

// Alphanumeric LCD functions
#include <alcd.h>

#include <delay.h>
#include <stdio.h>
#define trigger PORTC.1
#define echo PINC.0
unsigned int jarak,p;
char buf[33];


void ukur_jarak()
{
unsigned int i;
jarak=0;
delay_us(100);
trigger=1;  //tout, H=5 us
delay_us(15);
trigger=0;
delay_us(100);
while(!echo);
for (i=0;i<=500;i++)
{
if (echo) {jarak++;}
delay_us(58);
}
}


void main(void)
{
// Declare your local variables here

// Input/Output Ports initialization
// Port A initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTA=0x00;
DDRA=0x00;

// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTB=0x00;
DDRB=0x00;

// Port C initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTC=0x00;
DDRC.0=0;
DDRC.1=1;

// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTD=0x00;
DDRD=0x00;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=0xFF
// OC0 output: Disconnected
TCCR0=0x00;
TCNT0=0x00;
OCR0=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer1 Stopped
// Mode: Normal top=0xFFFF
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer2 Stopped
// Mode: Normal top=0xFF
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// INT2: Off
MCUCR=0x00;
MCUCSR=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x00;

// USART initialization
// USART disabled
UCSRB=0x00;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;

// ADC initialization
// ADC disabled
ADCSRA=0x00;

// SPI initialization
// SPI disabled
SPCR=0x00;

// TWI initialization
// TWI disabled
TWCR=0x00;

// Alphanumeric LCD initialization
// Connections are specified in the
// Project|Configure|C Compiler|Libraries|Alphanumeric LCD menu:
// RS - PORTD Bit 0
// RD - PORTD Bit 1
// EN - PORTD Bit 2
// D4 - PORTD Bit 4
// D5 - PORTD Bit 5
// D6 - PORTD Bit 6
// D7 - PORTD Bit 7
// Characters/line: 16
lcd_init(16);

lcd_clear ();
//lcd_putsf ("SRF05 non timer");
lcd_gotoxy(0,0);
lcd_putsf ("Range=");
lcd_gotoxy(0,1);
lcd_putsf ("MASS=");

while (1)
{
ukur_jarak();
sprintf (buf,"%d cm",jarak);
lcd_putsf("    ");
lcd_gotoxy (6,0);
lcd_puts (buf);

p=30-jarak;
sprintf (buf,"%d cm",p);
lcd_putsf("    ");
lcd_gotoxy (5,1);
lcd_puts (buf);


delay_ms(500);
}
}

با تشکر فراوان Heart
به به، به نظر میاد شما هم میکرویی شدید!!
نکته اول که این برنامه ATMEGA هست برای همین به بخش AVR منتقل شد (Xmega ها اسمشون با atxmega شروع میشه)
اما توضیح برنامه نمی دونم چقدر در جریان میکرو هستید ولی خوب کامل توضیح میدم
اولین خط "include <mega32.h<" (از این به بعد دیگه خط ها رو به ترتیب میرم)
میکرو ها یه حافظه دارن مثل بقیه دستگاه ها و پورت ها و ریجیستر های مختلف ادرس های خودشون رو دارن ما به جای اینکه ادرسشون رو حفظ کنیم اسمشون رو حفظ می کنیم (توی دیتاشیت نوشته) بعد این هدر رو لود می کنیم که اون اسم ها رو به ادرس ها وصل کرده
هدر بعدی که لود شده مربوط به نمایشگر کاراکتری هست و توابع مربوط به اونو در خودش جا داده
هدر بعدی توابعی برای ایجاد وقفه در برنامه داره
هدر بعدی رو که اشنایی دارید
اما خط بعدی که اومده "triger" رو تعریف کرده برای شماره پورت 1 از C البته اینو بگم که توی میکرو چیزی به عنوان PORTC.1 وجود نداره و این قابلیت کامپایلر کودویژن هست وگرنه در کاپایلر هایی مثل GCC اینا رو اررور می گیره
خط بعدی هم "echo" رو تعریف کرده
اما تفاوت این دو خط چیه؟ هر دو مربوط به پایه PORTC1 در میکرو هستن ولی رجیستر PORTx خروجی رو کنترل می کنه (صفر و یک می کنه) ریجیستر PINx مقدار پایه رو لود می کنه (ایا پایه در حالت صفر هست یا یک)
وارد تابع main میشیم
اونجا که به PORT مقدار داده درواقع خروجی رو صفر کرده
اما ریجیستری هست به اسم DDRx این ریجیستر مشخص می کنه یک پایه خروجی هست یا ورودی اگر بیت متناظر با پایه 1 باشه
اون پایه خروجی خواهد بود
به همچنین بقیه ی پایه ها
می رسیم به ریجیستر TCCR0 و این مربوط به تایمر میکرو هست که تنظیماتش رو باهاش انجام میدن (برای اطلاعات بیشتر دیتاشیت) اینجا استفاده نشده و بی خودی این رو نوشتن (اینا کار کدویژن هست)
ریجیستر بعدی TCNTx مقدار تایمر رو نگه می داره
این ریجیستر ها کلا مربوط به تایمر ها هستن که برای توضیحات دقیقش برید به دیتاشیت
تا اخر OCR2 مربوط به 3 تایمر داخلی میکرو هست که همشون رو غیر فعال می کنه و ... اینا لازم نبوده باشن
دو خط بعدی پایه های وقفه رو غیر فعال می کنه
خط بعدی وقفه های تایمر ها رو
کلا تا اخر کار اضافی هست این خط ها و کامپایلر خود کار اینا رو اضافه کرده و نیازی بهشون نبوده و بالاش نوشته که دیگه چه چیزی رو غیر فعال می کنه
میرسیم به خط lcd_init
این تابع نمایشگر کاراکتری که به میکرو وصل کردیم رو اماده به کار می کنه همون طوری که می بینید بالاش نوشته کدوم پایه های LCD به کدوم پایه های میکرو وصل شدن این هارو خود کامپایلر انجام میده (توی IDE تنظیم کردن)
بقیه توابع از اسمش پیداست چه کاری می کنن اما تابع "ukur_jarak"
ببینید اینجا باید بریم سراغ طرز کار این ماژول فاصله سنجی که شما دارید
این ماژول ها انواع مختلفی دارن ولی مال شما اینطوری کار میکنه
SRF05
شاید مدل شما این نباشه ولی طرز کارش یکی هست که من مختصری توضیح میدم
وقتی trigger رو یک میکنه درواقع پایه PORTC1 میکرو 1 میشه و ماژول فعال میشه مادامی که این پایه یک هست ماژول پالس صوتی رو ارسال می کنه وقتی صفر شد منتظر دریافت پالس های ارسالی میشه به محض اینکه پالسی دریافت کرد همون پایه ای که ما 1 کردیمش PORTC1 رو 1 می کنه به نشانه دریافت صوت و میزانی که این پایه 1 می مونه مشخص کننده ی فاصله ی بین ارسال و دریافت هست و وقتی از مقداری بیشتر بشه نشون میده اصلا پالسی رو دریافت نکرده
حالا ما توی برنامه توی قسمت while(!echo); درواقع منتظر 1 شدن پایمون میشیم (یعنی صدا برگشته و ماژول گرفته + داریم از ریجیستر PINC1 می خونیم چون ورودی هست)
حالا در حلقه بعدی زمان (طول موج) 1 بودن این پایه رو اندازه می گیره چون ماژول به ازای هر 1 سانتی متر 58میکرو ثانیه طول موج رو اضافه می کنه ایشون خودشون به صورت مرحله به مرحله (سانتی متر سانتی متر) طول 1 بودن رو اندازه گرفتن و در برنامه نشون می دن
انشاالله که خوب توضیح دادمBiggrin
Clap Clap
دست شما درد نکنه واقعا توضیحات کامل و واضح و مفیدی ارائه دادید، من که هیچی از میکرو سر در نمی آوردم الان احساس می کنم می تونم این برنامه رو ویرایشش هم بکنم تا در حد میلیمتر هم جواب بده!!! ( Tongue می دونم الان اینطوری شدید Amaze و می دونم که شدنی نیست Whistle اما اگه دستگاهش رو داشتم حتما تستش می کردم ببینم چی می شه!! Wink )

در هر صورت باز هم بابت توضیحات خوبتون ممنونم Heart
آقا مهدی این یه نمونه ویدئو از نحوه عملکرد این نوع ماژول ها هستش (اینجا طبق گفته شما به میلیمتر نشون میده Biggrin اما فکر نمی کنم زیاد دقیق باشه!!) :

http://www.aparat.com/v/iXecV
من گفتم به میلیمتر ولی این داره به هزارم میلیمتر نشون می ده که البته به قیافش نمی خوره!!
البته با یه سری ضرب و تقسیم کوچولو داخل برنامه میشه واحدها رو براحتی به همدیگه تبدیل کرد و بزرگ و کوچیکشون کرد ..

به نظر من آلتراسونیک برای سنجش فاصله خطای زیادی داره و بهترین روش استفاده از لیزر برای اینکار هستش