هدف پروژه: آشنایی با پالس pwm و کاربرد های آن. روند کار به این صورت است که با پالس pwm شدت نور یک led را کنترل می کنیم.

سخت افزار مورد استفاده: در این مقاله از برد آموزشی avr شرکت نامینیک مبتنی بر تراشه ATMEGA32 استفاده می کنیم. از تایمر 1 به عنوان تولید کننده پالس استفاده کرده وled شماره d9 برد که به پین صفر پورت b وصل است را درایو می کنیم.

کتابخانه های استفاده شده: کتاب خانه تعریف خود میکرو و کتابخانه sleep در این پروژه فراخوانی شده است. که در خطوط 9 و 10 مشاهده می کنید.

تشریح کد: pwm مخفف مدولاسیون پهنای باند پالس است. اگر یک موج مربعی داشته باشیم. به ازای هر فرکانس، طول موج برحسب ثانیه مشخص است که در این مدت سیگنال مدتی 1 و مدتی صفر است. حال اگر بتوانیم مدت 1 بودن سیگنال را کم و زیاد کنیم یک موج pwm ساخته ایم. تایمر صفر و یک در این میکرو توانایی تولید پالس pwm را به ما می دهد. توجه کنید که بدون تایمر هم می توان این نوع پالس ها را تولید کرد. ولی علاوه بر زحمت برنامه نویسی، زمان بندی کار نیز در برنامه های بزرگ دردسر ساز است.

ما می خواهیم خروجی pwm تایمر را به led شماره d9 بدهیم اما خروجی pwm تایمر در پین 5 پورت d است. در حالی که led مورد نظر ما در برد به پین صفر پورت b وصل است. با دو خط اضافه در برنامه مشکل حل می شود یعنی هر گاه خروجی pwm در پین 5 پورت d عوض شد، خروجی متصل به led را هم عوض می کنیم. از دید بیرون میکرو انگار هر دو پایه آینه هم هستند. این کار را در خط 17و 23 انجام داده ایم. در این مثال تایمر در مد pwm سریع 10 بیتی استفاده شده است. در این حالت  تایمر از صفر تا مقدار نهایی خود یعنی 1023 می شمارد و هرگاه مقدار رجیستر تایمر به مقدار رجیستر  ocr1a برسد خروجی pwm روی پایه میکرو را معکوس کرده و به شمارش ادامه می دهد تا سر ریز شود در این هنگام دوباره خروجی pwm را معکوس کرده و باز از صفر شروع به شمارش می کند. با تغییر رجیستر ocr1a در برنامه می توانید زمان 1 بودن پالس را کم و زیاد کنید. دقت کنید که هرگاه رجیستر ocr1a را در برنامه تغییر دادید، بلافاصله اعمال نمی شود و بعد از سرریز تایمر مقدار این رجیستر به روز می شود. ما وقفه سرریز و رسیدن مقدار تایمر به رجیستر ocr1a را فعال کرده ایم و در همین دو حالت به تبع تغییرات در پین 5 پورت d، خروجی صفر پورت b را معکوس می کنیم. وقفه سرریز در این جا  کاربرد دیگری نیز دارد. مقدار اولیه رجیستر ocr1a 511 است. ما در هر 40 بار سرریز تایمر، مقدار رجیستر ocr1a را یک واحد زیاد می کنیم تا مقدار 1000(یعنی  مقدار 1 بودن سیگنال را افزایش می دهیم. پس به تدریج نور دیود نورانی بیشتر می شود.)  بعد مقدار رجیستر ocr1a را تا 10 کم می کنیم (نور ال ای دی آرام آرام کم می شود.) و دوباره با زیاد کردن رجیستر ocr1a مراحل را تکرار می کنیم. نور ال ای دی باید به طور مداوم کم و زیاد شود. در این برنامه در مواقعی هم که روال وقفه ها اجرا نمی شود با پردازنده کاری نداریم پس با دستور idle کلاک پردازنده را خاموش می کنیم تا میکرو توان کمتری را مصرف کند. توجه کنید که مقدار 10 و 1000 که ما برای حداقل و حداکثر رجیستر ocr1a در نظر گرفتیم در اینجا اختیاری بوده و چون تایمر1 را در حالت pwm 10 بیتی تعریف کرده ایم، می تواند هر مقداری بین 0 تا 1023 داشته باشد.

پالس pwm کاربرد های زیادی دارد. سیستم های مکانیکی مثل الکترو موتور ها، نسبت به سیستم های الکترونیکی خیلی کند هستند. آن ها 1 و صفر شدن پالس pwm را به خاطر فرکانس بالایش اصلا درک نمی کنند و اصطلاحا به سطح dc پالس جواب می دهند. آن ها پالس را یک مقدار ثابت dc می بینند. نه یک موجی که مقدارش بین صفر و 1 در نوسان است. مقدار dc سیگنال pwm برابر است با مدت زمان یک بودن سیگنال تقسیم بر مدت زمان یک سیکل موج (یعنی مدت زمان صفر بودن به علاوه مدت زمان یک بودن). توجه کنید که این حرف ها فقط زمانی صادق است که فرکانس پالس pwm به مراتب بزرگتر از فرکانس نسبی شی باشد و به عبارت غیر علمی تر، شی مورد بحث به نوعی حافظه دار باشد و تا اثر سیکل قبلی موج در آن از بین نرفته سیکل بعدی تحریکش می کند. پس به تغییرات پالس هم کمی دیر جواب می دهد. این یکی از کاربرد های پالس  pwm است. یک کاربرد دیگر از اسم خود پالس پیدا است. یعنی همان مدولاسیون. می توان اطلاعات را به عرض پالس نسبت داد و مثلا با میکرو های دیگر ارتباط برقرار کرد و کاربردهای دیگر.پالس pwm کاربرد های زیادی دارد. سیستم های مکانیکی مثل الکترو موتور ها، نسبت به سیستم های الکترونیکی خیلی کند هستند. آن ها 1 و صفر شدن پالس pwm را به خاطر فرکانس بالایش اصلا درک نمی کنند و اصطلاحا به سطح dc پالس جواب می دهند. آن ها پالس را یک مقدار ثابت dc می بینند. نه یک موجی که مقدارش بین صفر و 1 در نوسان است. مقدار dc سیگنال pwm برابر است با مدت زمان یک بودن سیگنال تقسیم بر مدت زمان یک سیکل موج (یعنی مدت زمان صفر بودن به علاوه مدت زمان یک بودن). توجه کنید که این حرف ها فقط زمانی صادق است که فرکانس پالس pwm به مراتب بزرگتر از فرکانس نسبی شی باشد و به عبارت غیر علمی تر، شی مورد بحث به نوعی حافظه دار باشد و تا اثر سیکل قبلی موج در آن از بین نرفته سیکل بعدی تحریکش می کند. پس به تغییرات پالس هم کمی دیر جواب می دهد. این یکی از کاربرد های پالس  pwm است. یک کاربرد دیگر از اسم خود پالس پیدا است. یعنی همان مدولاسیون. می توان اطلاعات را به عرض پالس نسبت داد و مثلا با میکرو های دیگر ارتباط برقرار کرد و کاربردهای دیگر.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
/*****************************************************
Chip type               : ATmega32
AVR Core Clock frequency: 8.000000 MHz
Memory model            : Small
External RAM size       : 0
Data Stack size         : 512
*****************************************************/
 
#include <mega32.h>
#include <sleep.h>
 
int i=0;
bit g=0;
 
// Timer1 overflow interrupt service routine
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
   PORTB.0=~PORTB.0;  
}
 
// Timer1 output compare A interrupt service routine
interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
    PORTB.0=~PORTB.0;
    i++;
    if(i==5)
    {
        if(!g)
        {
             OCR1A++;
        }
        else
        {
             OCR1A--;
        }
        if(OCR1A==1000)
        {
             g=1;
        }
        if(OCR1A==1)
        {
             g=0;
        }
        i=0;
    }
}
 
void main(void)
{
PORTB=0x00;
DDRB=0x01;
 
PORTD=0x00;
DDRD=0x20;
 
// Timer/Counter 1 initialization
// Clock value: 7.813 kHz
// Mode: Fast PWM top=0x03FF
// Timer1 Overflow Interrupt: On
// Compare A Match Interrupt: On
TCCR1A=0xC3;
TCCR1B=0x09;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x3F;
OCR1BH=0x00;
OCR1BL=0x00;
 
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x14;
 
// Global enable interrupts
#asm("sei")
 
sleep_enable();
 
while (1)
      {
         idle();
      }
}

دانلود سورس کد

در  اینجا شما میتوانید سورس برنامه را دریافت