Mündəricat:

AVR mikro nəzarətçisi. Zamanlayıcıdan istifadə edərək LEDlər Flaş. Taymerlər kəsir. Taymer CTC rejimi: 6 addım
AVR mikro nəzarətçisi. Zamanlayıcıdan istifadə edərək LEDlər Flaş. Taymerlər kəsir. Taymer CTC rejimi: 6 addım

Video: AVR mikro nəzarətçisi. Zamanlayıcıdan istifadə edərək LEDlər Flaş. Taymerlər kəsir. Taymer CTC rejimi: 6 addım

Video: AVR mikro nəzarətçisi. Zamanlayıcıdan istifadə edərək LEDlər Flaş. Taymerlər kəsir. Taymer CTC rejimi: 6 addım
Video: İş müsahibələrində soruşulan 5 əsas sual | Təcrübələrim 2024, Noyabr
Anonim
Image
Image

Hamıya salam!

Taymerlər elektronika sahəsində vacib bir anlayışdır. Hər bir elektron komponent zaman əsasında işləyir. Bu vaxt bazası bütün işlərin sinxronizasiya olunmasına kömək edir. Bütün mikro nəzarətçilər əvvəlcədən təyin edilmiş bir saat tezliyində işləyirlər, hamısında taymer qurmaq üçün bir şərt var. AVR çox dəqiq, dəqiq və etibarlı bir taymerə sahibdir. İçərisində bir çox xüsusiyyətlər təqdim edir, beləliklə onu geniş bir mövzu halına gətirir. Ən yaxşı tərəfi, taymerin CPU -dan tamamilə asılı olmamasıdır. Beləliklə, CPU ilə paralel işləyir və heç bir CPU müdaxiləsi yoxdur ki, bu da taymeri olduqca dəqiq edir. Bu bölmədə AVR Taymerlərinin əsas anlayışlarını izah edəcəyəm. Taymerlərdən istifadə edərək LED flaşını idarə etmək üçün C kodunda sadə bir proqram yazıram.

Addım 1: Təsvir

Problem Bildirimi 1: Hər 50 Ms -də İlk LED (yaşıl) yanıb -sönək
Problem Bildirimi 1: Hər 50 Ms -də İlk LED (yaşıl) yanıb -sönək

ATMega328 -də üç növ taymer var:

Timer/Counter0 (TC0) - iki müstəqil Çıxış Müqayisəsi və PWM dəstəyi olan ümumi təyinatlı 8 bitlik Taymer/Sayıcı moduludur;

Timer/Counter1 (TC1) - 16 bitlik Timer/Counter vahidi, proqramın dəqiq yerinə yetirilmə vaxtını (hadisələrin idarə edilməsi), dalğaların yaranmasını və siqnal vaxtının ölçülməsini təmin edir;

Timer/Counter2 (TC2) -PWM və Asenkron İşləmə ilə ümumi məqsəd, kanal, 8 bitlik Taymer/Sayıcı modulu;

Addım 2: Problem Bildirimi 1: Hər 50 Ms -də İlk LED (yaşıl) yanıb -sönək

Problem Bildirimi 1: Hər 50 Ms -də İlk LED (yaşıl) yanıb -sönək
Problem Bildirimi 1: Hər 50 Ms -də İlk LED (yaşıl) yanıb -sönək
Problem Bildirimi 1: Hər 50 Ms -də İlk LED (yaşıl) yanıb -sönək
Problem Bildirimi 1: Hər 50 Ms -də İlk LED (yaşıl) yanıb -sönək

Metodologiya:

- yüksək tezlikli elektrik siqnalını tam ədədlərə bölməklə daha aşağı tezliyə endirmək üçün Timer0 prescalaler istifadə etmək;

- Timer0 hər dəfə daşdıqda bir fasilə istifadə etmək;

Timer0 (8 bit) bundan sonra 0 -dan 255 -ə qədər sayılır, daşır, bu dəyər hər saat nəbzində dəyişir.

F_CPU = 16MHz: Saat müddəti = 1000ms / 16000000Hz = 0.0000625ms

Taymer sayı = (Lazım Gecikmə / Saat Vaxtı) -1 = (50ms / 0.0000625ms) = 799999

Saat artıq 799999 dəfə işarə edərək yalnız 50 ms gecikmə verdi!

Taymer sayını azaltmaq üçün tezlik bölmə texnikasından istifadə edə bilərik. AVR bizə seçim üçün aşağıdakı prescaler dəyərlərini təklif edir: 8, 64, 256 və 1024. Cədvəldə fərqli presalalerlərin istifadəsinin nəticələrini ümumiləşdirin.

Sayaç dəyəri həmişə tam ədəd olmalıdır. Gəlin 256 -a bir prescaler seçək!

Əksər mikrokontrolörlərdə Interrupt adlı bir şey var. Müəyyən şərtlər yerinə yetirildikdə bu fasilə atıla bilər. İndi bir fasilə atıldıqda, AVR dayanır və əsas işin icrasını saxlayır, fasilə çağırışına qatılır (Xüsusi bir proseduru yerinə yetirərək, Interrupt Service Routine, ISR adlanır) və bununla bitdikdən sonra, əsas qaydadır və onu icra etməyə davam edir.

Lazım olan gecikmə (50ms) maksimum mümkün gecikmədən daha çox olduğundan: 4, 096ms = 1000ms / 62500Hz * 256, açıq şəkildə taymer daşacaq. Və nə vaxt taymer daşırsa, fasilə verilir.

Fasilə neçə dəfə atılmalıdır?

50ms / 4.096ms = 3125/256 = 12.207 Taymeri 12 dəfə aşsa, 12 * 4.096ms = 49.152ms keçərdi. 13 -cü təkrarlamada 50ms - 49.152ms = 0.848ms gecikməyə ehtiyacımız var.

62500Hz tezliyində (prescaler = 256) hər bir gənə 0.016 ms çəkir. Beləliklə, 0.848 ms gecikmə əldə etmək üçün 0.848ms / 0.016ms = 53 gənə lazımdır. Beləliklə, 13 -cü təkrarlamada, yalnız 53 -ə qədər saymağa və sonra sıfırlamağa icazə veririk.

Timer0/Counter -ı işə salın (şəkilə baxın):

TCCR0B | = (1 << CS02) // prescaler ilə timer qurun = 256 TCNT0 = 0 // sayğacı işə salın TIMSK0 | = (1 << TOIE0) // daşqın kəsilməsini aktiv edin sei () // qlobal fasilələri təmin edin tot_overflow = 0 // daşma sayğac dəyişənini işə salın

Addım 3: Problem İfadəsi 2: Hər 1 saniyədə ikinci LED (mavi) yanıb -sönək

Problem İfadəsi 2: Hər 1 saniyədə ikinci LED (mavi) yanıb -sönək
Problem İfadəsi 2: Hər 1 saniyədə ikinci LED (mavi) yanıb -sönək
Problem İfadəsi 2: Hər 1 saniyədə ikinci LED (mavi) yanıb -sönək
Problem İfadəsi 2: Hər 1 saniyədə ikinci LED (mavi) yanıb -sönək
Problem İfadəsi 2: Hər 1 saniyədə ikinci LED (mavi) yanıb -sönək
Problem İfadəsi 2: Hər 1 saniyədə ikinci LED (mavi) yanıb -sönək

Metodologiya:

- yüksək tezlikli elektrik siqnalını tam ədədlərə bölməklə daha aşağı tezliyə endirmək üçün Timer1 prescaler istifadə etmək;

- Müqayisə (CTC) rejimində Clear Timer istifadə etmək;

- CTC rejimi ilə fasilələrdən istifadə etmək;

Timer1 (16 bit), bundan sonra 0 -dan 65534 -ə qədər sayılır, onlar daşır. Bu dəyər hər saat nəbzində dəyişir.

F_CPU = 16MHz: Saat müddəti = 1000ms / 16000000Hz = 0.0000625ms Zamanlayıcı sayı = (Lazım Gecikmə / Saat Zaman Periyodu) -1 = (1000ms / 0.0000625ms) = 15999999

Saat 1 saniyə gecikdirmək üçün artıq 15999999 dəfə işarələndi!

Taymer sayını azaltmaq üçün tezlik bölmə üsulundan istifadə edə bilərik. AVR bizə seçim üçün aşağıdakı prescaler dəyərlərini təklif edir: 8, 64, 256 və 1024. Cədvəldə fərqli presalalerlərin istifadəsinin nəticələrini ümumiləşdirin. Sayaç dəyəri həmişə tam ədəd olmalıdır. Gəlin 256 -a qədər bir qablaşdırıcı seçək!

Müqayisədə Clear timer (CTC) rejimində, OCR1A və ya ICR1 reyestri əks qətnaməni idarə etmək üçün istifadə olunur. CTC rejimində, sayğac dəyəri (TCNT1) ya OCR1A və ya ICR1 ilə uyğun gəldikdə sayğac sıfıra təmizlənir. OCR1A və ya ICR1, sayğac üçün ən yüksək dəyəri və buna görə də həllini təyin edir. Bu rejim, müqayisə olunan matçın çıxış tezliyinə daha çox nəzarət etməyə imkan verir, eyni zamanda xarici hadisələrin sayılmasını asanlaşdırır. AVR -ə, Timer1/Counter -in dəyəri 62500 dəyərinə çatan kimi sıfırlamasını və bununla da 1s gecikməsinə nail olmasını bildirməliyik.

Timer1/Counter -ı işə salın (şəkilə baxın):

TCCR1B | = (1 << WGM12) | (1 << CS12) // prescaler = 256 və CTC rejimi ilə timer qurun TCNT1 = 0 // sayğacı işə salın TIMSK1 | = (1 << OCIE1A) // müqayisə fasiləsi OCR1A = 62500 // müqayisə dəyərini başlat

Addım 4: Problem Bildirimi 3: Hər 16 ms -də Üçüncü LED (qırmızı) yanıb -sönək

Problem Bildirimi 3: Hər 16 ms -də Üçüncü LED (qırmızı) yanıb -sönək
Problem Bildirimi 3: Hər 16 ms -də Üçüncü LED (qırmızı) yanıb -sönək
Problem Bildirimi 3: Hər 16 ms -də Üçüncü LED (qırmızı) yanıb -sönək
Problem Bildirimi 3: Hər 16 ms -də Üçüncü LED (qırmızı) yanıb -sönək
Problem Bildirimi 3: Hər 16 ms -də Üçüncü LED (qırmızı) yanıb -sönək
Problem Bildirimi 3: Hər 16 ms -də Üçüncü LED (qırmızı) yanıb -sönək
Problem Bildirimi 3: Hər 16 ms -də Üçüncü LED (qırmızı) yanıb -sönək
Problem Bildirimi 3: Hər 16 ms -də Üçüncü LED (qırmızı) yanıb -sönək

Metodologiya:

- yüksək tezlikli elektrik siqnalını tam ədədlərə bölməklə daha aşağı tezliyə endirmək üçün Timer2 prescalaler istifadə etmək;

- Müqayisə (CTC) rejimində Clear Timer istifadə etmək;

- Hardware CTC Mode -nu fasiləsiz istifadə etmək;

Timer2 (8 bit), bundan sonra 0 -dan 255 -ə qədər sayılır, daşır. Bu dəyər hər saat nəbzində dəyişir.

F_CPU = 16MHz: Saat müddəti = 1000ms / 16000000Hz = 0.0000625ms

Taymer sayı = (Lazım Gecikmə / Saat Zaman Periyodu) -1 = (16ms / 0.0000625ms) = 255999

Saat artıq 255999 dəfə işarə edərək 16 ms gecikmə verdi!

Fərqli prescalers istifadə nəticələrini ümumiləşdirən cədvələ baxın. Sayaç dəyəri həmişə tam ədəd olmalıdır. Bir prescaler 1024 seçək!

CTC rejimində sayğac dəyəri (TCNT2) ya OCR2A və ya ICR2 ilə uyğun gəldikdə sayğac sıfıra təmizlənir. Pin PB3 eyni zamanda TIMER2 - OC2A -nın Çıxış Müqayisə pinidir (diaqrama baxın).

Taymer/Counter2 Nəzarət Qeydiyyatı A - TCCR2A Bit 7: 6 - COM2A1: 0 - A Bölməsini müqayisə etmək üçün Çıxış Rejimini müqayisə edin. LED -i dəyişdirməliyik, seçimini seçirik: Müqayisə Maçında OC2A -nı dəyişdir OC2A pin avtomatik olaraq dəyişdirilir. Bayraq bitini yoxlamağa ehtiyac yoxdur, heç bir kəsilməyə qatılmağa ehtiyac yoxdur.

Timer2/Counter -ı işə salın

TCCR2A | = (1 << COM2A0) | (1 << WGM21) // keçid rejimində və CTC rejimində TCCR2B timer OC2A pinini qurun | = (1 << CS22) | (1 << CS21) | (1 << CS20) // timceri prescaler ilə qurun = 1024 TCNT2 = 0 // sayğacı işə salın OCR2A = 250 // müqayisə dəyərini başlayın

Addım 5: C proqramında kod yazmaq. HEX faylını mikro nəzarətçinin flaş yaddaşına yükləmək

C proqramında kod yazılması, mikro nəzarətçinin flaş yaddaşına HEX faylının yüklənməsi
C proqramında kod yazılması, mikro nəzarətçinin flaş yaddaşına HEX faylının yüklənməsi
C proqramında kod yazılması, mikro nəzarətçinin flaş yaddaşına HEX faylının yüklənməsi
C proqramında kod yazılması, mikro nəzarətçinin flaş yaddaşına HEX faylının yüklənməsi

İnteqrasiya edilmiş İnkişaf Platforması - Atmel Studio -dan istifadə edərək AVR mikrokontrolör tətbiqini C Kodunda yazmaq və qurmaq.

F_CPU, Hertz-də saat tezliyini təyin edir və avr-libc kitabxanasından istifadə edən proqramlarda çox yayılmışdır. Bu vəziyyətdə, gecikmələrin necə hesablanacağını təyin etmək üçün gecikmə qaydaları istifadə olunur.

#ifndef F_CPU

#define F_CPU 16000000UL // nəzarətçi kristal tezliyini izah edir (16 MHz AVR ATMega328P) #endif

Sancaqlar üzərində məlumat axını nəzarətini təmin etmək üçün #include // header. Sancaqlar, portlar və s.

Birincisi, avr-libc-in bir hissəsidir və üzərində işlədiyiniz hər hansı bir AVR layihəsində istifadə ediləcəkdir. io.h istifadə etdiyiniz CPU -nu təyin edəcək (bu səbəbdən tərtib edərkən hissəni qeyd edirsiniz) və öz növbəsində istifadə etdiyimiz çip üçün uyğun IO tərif başlığını da daxil edəcək. Bütün pinləriniz, portlarınız, xüsusi qeydləriniz və s. Üçün sabitləri təyin edir.

#include // başlığı kəsmək üçün

uçucu uint8_t tot_overflow; // daşqın sayını saymaq üçün qlobal dəyişən

Problemin Bildirilməsi Metodologiyası: Hər 50 ms -də İlk olaraq Flaş (Yaşıl) LED

- yüksək tezlikli elektrik siqnalını tam ədədlərə bölməklə daha aşağı tezliyə endirmək üçün Timer0 prescalaler istifadə etmək;

- Timer0 hər dəfə daşdıqda bir fasilə istifadə etmək;

void timer0_init () // timer0 başlatmaq, kəsmək və dəyişmək

{TCCR0B | = (1 << CS02); // prescaler ilə taymer qurun = 256 TCNT0 = 0; // sayğacı başlatmaq TIMSK0 | = (1 << TOIE0); // nterrupt sei daşımasını aktivləşdir (); // qlobal fasilələri aktiv et tot_overflow = 0; // daşma sayğac dəyişənini işə salın}

Problem Bildirmə Metodologiyası: Hər 1 saniyədə bir Flaş İkinci LED (mavi)

- yüksək tezlikli elektrik siqnalını tam ədədlərə bölməklə daha aşağı tezliyə endirmək üçün Timer1 prescaler istifadə etmək;

- Müqayisə (CTC) rejimində Clear Timer istifadə etmək;

- CTC rejimi ilə kəsilmələrdən istifadə etmək;

void timer1_init () // timer1 başlatmaq, kəsmək və dəyişmək {TCCR1B | = (1 << WGM12) | (1 << CS12); // prescaler = 256 və CTC rejimi ilə timer qurun TCNT1 = 0; // sayğacı işə salın OCR1A = 62500; // TIMSK1 müqayisə dəyərini başlatmaq | = (1 << OCIE1A); // müqayisə kəsilməsini aktiv et}

Problem Bildirmə Metodologiyası: Hər 16 ms -də üçüncü LED (qırmızı) yanıb sönür

- yüksək tezlikli elektrik siqnalını tam ədədlərə bölməklə daha aşağı tezliyə endirmək üçün Timer2 prescaler istifadə etmək;

- Müqayisə (CTC) rejimində Clear Timer istifadə etmək;

- Hardware CTC Mode -nu fasiləsiz istifadə etmək;

void timer2_init () // timer2 başlatmaq {TCCR2A | = (1 << COM2A0) | (1 << WGM21); // keçid rejimində və CTC rejimində timer OC2A pin qurmaq TCCR2B | = (1 << CS22) | (1 << CS21) | (1 << CS20); // prescaler ilə timer qurun = 1024 TCNT2 = 0; // sayğacı işə salın OCR2A = 250; // müqayisə dəyərini başladın}

TCNT0 daşdıqda çağırılan TIMER0 daşması kəsmə xidməti rutini:

ISR (TIMER0_OVF_vect)

{tot_overflow ++; // daşqınların sayını izləyin}

Bu ISR, hər hansı bir matç baş verdikdə işə salınır, burada özü ilə keçin:

ISR (TIMER1_COMPA_vect) {PORTC ^= (1 << 1); // bura apararaq keçin}

int main (boş)

{DDRB | = (1 << 0); // birləşdirin 1 (yaşıl) pin PB0 DDRC | = (1 << 1); // birləşdirmək 2 (mavi) pin PC1 DDRB | = (1 << 3); // birləşdirmək 3 (qırmızı) pin PB3 (OC2A) timer0_init (); // timer0 timer1_init () başlatmaq; // timer1 timer2_init () başlatmaq; // timer2 -ni işə salın (1) // sonsuza qədər döngə {

Timer0 12 dəfə aşsa, 12 * 4.096ms = 49.152ms keçərdi. 13 -cü təkrarlamada 50ms - 49.152ms = 0.848ms gecikməyə ehtiyacımız var. Beləliklə, 13 -cü təkrarlamada, yalnız 53 -ə qədər saymağa və sonra sıfırlamağa icazə veririk.

if (tot_overflow> = 12) // yoxsa yoxlayın. overflows = 12 QEYD: '> =' istifadə olunur

{if (TCNT0> = 53) // taymer sayının 53 -ə çatıb çatmadığını yoxlayın {PORTB ^= (1 << 0); // led TCNT0 = 0 -ı dəyişir; // saytı sıfırla tot_overflow = 0; // daşma sayğacını sıfırlayın}}}}

HEX faylını mikro nəzarətçi flash yaddaşına yükləmək:

DOS sorğu pəncərəsinə əmr yazın:

avrdude –c [proqramçının adı] –p m328p –u –U flash: w: [hex faylınızın adı] Mənim vəziyyətimdə belədir: avrdude –c ISPProgv1 –p m328p –u –U flaş: w: Timers.hex

Bu əmr mikro nəzarətçinin yaddaşına hex fayl yazır. Mikrodenetleyici flash yaddaşının yanmasının ətraflı təsviri ilə videoya baxın:

Mikro nəzarətçi flash yaddaşı yanır …

Tamam! İndi mikrokontrolör proqramımızın təlimatlarına uyğun işləyir. Gəlin yoxlayaq!

Addım 6: Elektrik dövrəsinin qurulması

Elektrik dövrəsinin qurulması
Elektrik dövrəsinin qurulması
Elektrik dövrəsinin qurulması
Elektrik dövrəsinin qurulması
Elektrik dövrəsinin qurulması
Elektrik dövrəsinin qurulması

Şematik sxemə uyğun olaraq komponentləri birləşdirin.

Tövsiyə: