تریب جان من نمیخوام ازون روش استفاده کنم توضیح دادم چجوری میخوام
اصلا سروو رو فراموش کن میخوام با بیسکام یک برنامه بنویسم که فرکانس 50 هرتز مربعی تولید کنه و بشه توش نیم سیکل مثبت رو از 1 تا 2 میلی ثانیه تغییر داد با مگا 8 و کریستال 8 مگ و بیسکام ببینم چکار میکنی؟
بشه سیکل مثبت رو بدست گرفت بقیش حله
خوب هر 10 میلی ثانیه یه خروجی رو toggle کنی فرکانس 50 درست می شه .
اون توابع هم همین کارو می کنن .
برای تغییر سیکل کاری هم کافیه مثلا 8 میلی ثانیه صفر و 12 میلی ثانیه پایه یک بشه . همین .
البته با تایمرها بهتره انجام بدی .
خوب من این برنامه رو با کمک کتاب نوشتم:
از اون دستور TOGGLE که گفتی هم استفاده کردم:
$regfile = "M8DEF.DAT"
$crystal = 16000000
Config Portc = Output
Ddrc.0 = 1 : Portc.0 = 0
Config Timer1 = Timer , Prescale = 1024
Enable Interrupts
Enable Timer1
Enable Ovf1
On Timer1 Lable
Timer1 = 57722
Start Timer1
Do
Loop
End
Lable:
Toggle Portc.0
Timer1 = 57722
Start Timer1
Return
این برنامه وقتی میره تو LABLE هر نیمثانیه پورت C رو معکوس میکنه که یک فرکانس با طول موجهای ثابت و یکنواخت بدست میاد (1 هرتز)
حالا من میخوام طول موج مثبت که سپری شد یک پورت یک بشه و بعد از طول موج دیگه ای که با اولی فرق داره همون پورت صفر بشه اصلا بزار راحتتر بگم میخوام مثلا 1 ثانیه پورت یک باشه و دو ثانیه صفر یعنی دوبار شمارش داشته باشم ؟؟؟؟
آقای bozonghare چیزی که شما خواسته بودین با روش PWM بصورت دقیق بدست میاد ولی به عنوان ساده ترین روش میتونین از برنامه پایینی استفاده کنین:
تو این برنامه مقدار طول موجو به میلی ثانیه میتونین با تقسیم ولتاژ مقاومتی و بوسیله ADC بدست بیارین. تازه این تقسیم ولتاژم به عنوان فیدبک از یه قسمت مدار هم میتونین بکار بگیرین روشهای مختلف دیگه ای هم هست که میتونین مقدار طول موجو به میکرو تعریف کنید(بد ترین و کم انعطاف ترین حالت استفاده از کیپد)
کد php:
Do
()A = Getadc
Set Portd.0
Waitms A
Reset Portd.0
Waitms A
LOOP
بله ILGAR جان من از روش شما استفاده کردم ولی میدونین مشکلش چیه اون متغیر A از 1 تا 2 تفییر میکنه با اعشار مثلا 1.25 وقتی A اعشاری میشد Waitms فقط اعداد صحیح رو میگرفت یعنی از 1 تا 1.6 رو همون 1 حساب میکرد و 1.6 به بالا رو 2 میگرفت (تو اسیلوسکوپ پروتئوس قشنگ معلومه)
اگه این مشکل نبود کار من حل بود ولی مجبور شدم از WAITUS استفاده کنم و 1.25 جمو ضرب در 1000 کنم و بزارم تو A و بعد بگم : WAITUS A باز مشکل اینجا بود که WAITUS درست عمل نمیکرد و مجبور شدم 1 تا 2 رو به 40 قسمت تقسیم کنم و از دستور JMP استفاده کنم:
If V2 =< 1.00 Then
Jmp B
End If
If V2 > 1.00 And V2 < 1.025 Then
JMP C
End If
If V2 > 1.025 And V2 < 1.05 Then
JMP D
End If
If V2 > 1.05 And V2 < 1.075 Then
JMP E
.
.
.
.
B:
Set Portd.0
Waitus 1000
Reset Portd.0
Waitms 18
Return
C:
Set Portd.0
Waitus 1025
Reset Portd.0
Waitms 18
Return
D:
Set Portd.0
Waitus 1050
Reset Portd.0
Waitms 18
.
.
.
ممکنه درباره PWM یکم توضیح بدی برا این کار من؟؟؟؟
خوب اینکه مشکلی نیست به جای msاز us استفاده کنین و بازه تغییر ولتاژ ADC رو جوری انتخاب کنین که حداقل یک میلی ثانیه در 0 ولت و حداکثر 2 میلی ثانیه در 5 ولت براتون بده.
حواستون به میزان کلاکی که میکرو برای عمل ()getkbd مصرف میکنه باشه این مقدارو تاحدی با روش آزمون خطا میتونین بدست بیاریدش.
این روشیکه من استفاده کردم راحته ولی کلا 40 نقطه برا 1 تا2 درست کردم که خیلیم وقت گرفت نمیدونم برنامم تو مگا 8 جا میگیره یا نه 483 خط شده این پست آخر منظورتونو نفهمیدم ممکنه با برنامه توضیح بدین؟
من اینو طبق گفته شما نوشتم ولی WAITUS متغیر B رو که از 1000 تا 2000 تغییر میکنه قبول نمیکنه:
$regfile = "m8def.dat"
$crystal = 8000000
Config Lcdpin = Pin , Db4 = Pinb.3 , Db5 = Pinb.2 , Db6 = Pinb.1 , Db7 = Pinb.0 , E = Pinb.4 , Rs = Pinb.5
Config Lcd = 16 * 2 : Cursor Off : Cls
Config Portd = Output
Dim A As Word
Dim V2 As Single
Dim V3 As Single
Dim V As Single
Dim B As Single
Config Adc = Single , Prescaler = Auto , Reference = Avcc
Start Adc
Do
A = Getadc(1)
V2 = A
V2 = V2 / 1024
B = 1 + V2
B = B * 1000
Set Portd.0
Waitus B
Reset Portd.0
Waitms 18
V3 = A
V3 = V3 / 1024
V3 = V3 * 5
Cls
Lcd "V=" ; Fusing(v3 , "#.##") ; " VOLT"
Home Lower
Lcd "T=" ; Fusing(b , "#.##") ; " U.SEC"
Loop
End
اینم تصویر مدار:
![[تصویر: 887ondbj7f5w3chvg6lf.jpg]](http://www.dehcadeh.com/upload/images/887ondbj7f5w3chvg6lf.jpg)
الان برنامه من درسته مال شما هم تقریبا شبیه برنامه من فقط تقسیم و ضرب کم داره... مشکل اینجای که در Waitus A ، این دستور درست عمل نمیکنه ، اگه درست عمل کنه که برنامه درسته ، یعنی مثلا 1500 میلی ثانیه یا همون 1.5 میلی ثانیه رو نمیشمره این تو شبیه ساز پروتئوس کاملا مشخصه میخواین شما هم تست کنین همین برنامه بالای من و مداریکه کشیدم ، اونم که یک سروو هست و از 1 تا 2 میلی ثانیه لازم داره تا از -90 درجه بشه 90 درجه.
؟؟؟
اینم برنامه طبق فرموده شما:
$regfile = "m8def.dat"
$crystal = 8000000
Config Lcdpin = Pin , Db4 = Pinb.3 , Db5 = Pinb.2 , Db6 = Pinb.1 , Db7 = Pinb.0 , E = Pinb.4 , Rs = Pinb.5
Config Lcd = 16 * 2 : Cursor Off : Cls
Config Portd = Output
Dim A As Word
Dim V2 As Single
Dim V3 As Single
Dim V As Single
Dim B As Single
Config Adc = Single , Prescaler = Auto , Reference = Avcc
Start Adc
Do
A = Getadc(1)
A = A + 1000
Set Portd.0
Waitus A
Reset Portd.0
Waitus 18000
B = A
V3 = A / 2
V3 = V3 / 1024
V3 = V3 * 5
Cls
Lcd "V=" ; Fusing(v3 , "#.##") ; " VOLT"
Home Lower
Lcd "T=" ; Fusing(b , "#.##") ; " U.SEC"
Loop
End
LCD دقیقا از 1000 تا 2000 میکرو ثانیه رو نشون میده یعنی عددی که تو A ریخته شده ولی دستور Waitus درست عمل نمیکنه نمیدونم چرا شما میدونین چرا؟؟ امتحان کنید
خوب گفتم که !
اینهمه دستورو گذاشتین داخل do - loop انتظار دارین waitus درست عمل کنه؟!
میدونین چقدر وقت میکرو صرف این دستورا میشه. شاید هم وقت رسیدگی میکرو به دستورهای داخل حلقه بیشتر از یک میلی ثانیه (که براتون مهمه )باشه.
من دیگه نمیخوام مطالب قبلی رو تکرار کنم لطفاً پستهای قبلی منو یک بار دیگه مرور کنید