Mục lục:

Bộ vi điều khiển AVR. Đèn LED Flasher sử dụng bộ hẹn giờ. Bộ hẹn giờ Ngắt. Chế độ hẹn giờ CTC: 6 bước
Bộ vi điều khiển AVR. Đèn LED Flasher sử dụng bộ hẹn giờ. Bộ hẹn giờ Ngắt. Chế độ hẹn giờ CTC: 6 bước

Video: Bộ vi điều khiển AVR. Đèn LED Flasher sử dụng bộ hẹn giờ. Bộ hẹn giờ Ngắt. Chế độ hẹn giờ CTC: 6 bước

Video: Bộ vi điều khiển AVR. Đèn LED Flasher sử dụng bộ hẹn giờ. Bộ hẹn giờ Ngắt. Chế độ hẹn giờ CTC: 6 bước
Video: AVR | Bài 3.3 Timer 1 [11] 2024, Tháng mười một
Anonim
Image
Image

Chào mọi người!

Bộ hẹn giờ là một khái niệm quan trọng trong lĩnh vực điện tử. Mọi thành phần điện tử hoạt động trên cơ sở thời gian. Cơ sở thời gian này giúp giữ cho tất cả các công việc được đồng bộ hóa. Tất cả các bộ vi điều khiển đều hoạt động ở một số tần số xung nhịp được xác định trước, chúng đều có một điều khoản để thiết lập bộ định thời. AVR tự hào có bộ đếm thời gian rất chính xác, chính xác và đáng tin cậy. Nó cung cấp vô số tính năng trong đó, do đó làm cho nó trở thành một chủ đề rộng lớn. Phần tốt nhất là bộ đếm thời gian hoàn toàn độc lập với CPU. Do đó, nó chạy song song với CPU và không có sự can thiệp của CPU, điều này làm cho bộ đếm thời gian khá chính xác. Trong phần này, tôi giải thích các khái niệm cơ bản của AVR Timers. Tôi đang viết một chương trình đơn giản bằng mã C để điều khiển đèn LED nhấp nháy, sử dụng bộ hẹn giờ.

Bước 1: Mô tả

Tuyên bố sự cố 1: Đèn LED đầu tiên của Let’s Flash (xanh lục) Cứ sau 50 Ms
Tuyên bố sự cố 1: Đèn LED đầu tiên của Let’s Flash (xanh lục) Cứ sau 50 Ms

Trong ATMega328 có ba loại bộ định thời:

Bộ định thời / Bộ đếm0 (TC0) - là một mô-đun Bộ định thời / Bộ đếm 8 bit đa năng, với hai Đơn vị So sánh Đầu ra độc lập và hỗ trợ PWM;

Bộ định thời / Bộ đếm1 (TC1) - Bộ định thời / Bộ đếm 16 bit cho phép đo thời gian thực hiện chương trình chính xác (quản lý sự kiện), tạo sóng và đo thời gian tín hiệu;

Bộ định thời / Bộ đếm2 (TC2) -là một mục đích chung, kênh, mô-đun Bộ định thời / Bộ đếm 8-bit với PWM và Hoạt động không đồng bộ;

Bước 2: Tuyên bố vấn đề 1: Hãy nhấp nháy đèn LED đầu tiên (màu xanh lá cây) Cứ sau 50 Ms

Tuyên bố sự cố 1: Đèn LED đầu tiên của Let’s Flash (xanh lục) Cứ sau 50 Ms
Tuyên bố sự cố 1: Đèn LED đầu tiên của Let’s Flash (xanh lục) Cứ sau 50 Ms
Tuyên bố sự cố 1: Đèn LED đầu tiên của Let’s Flash (xanh lục) Cứ sau 50 Ms
Tuyên bố sự cố 1: Đèn LED đầu tiên của Let’s Flash (xanh lục) Cứ sau 50 Ms

Phương pháp luận:

- sử dụng bộ đếm trước Timer0 để giảm tín hiệu điện tần số cao xuống tần số thấp hơn bằng phép chia số nguyên;

- sử dụng ngắt mỗi khi Timer0 tràn;

Timer0 (8 bit) nó đếm từ 0 đến 255 sau đó chúng bị tràn, giá trị này thay đổi ở mọi xung clock.

F_CPU = 16MHz: Khoảng thời gian đồng hồ = 1000ms / 16000000Hz = 0,0000625ms

Đếm bộ hẹn giờ = (Độ trễ bắt buộc / Khoảng thời gian đồng hồ) -1 = (50ms / 0,0000625ms) = 799999

Đồng hồ đã tích tắc 799999 lần để có độ trễ chỉ 50 mili giây!

Chúng ta có thể sử dụng kỹ thuật phân chia tần số được gọi là đặt trước để giảm số đếm của bộ đếm thời gian. AVR cung cấp cho chúng ta các giá trị bộ định tỷ lệ sau để lựa chọn: 8, 64, 256 và 1024. Xem bảng tóm tắt kết quả của việc sử dụng các bộ định tỷ lệ khác nhau.

Giá trị bộ đếm phải luôn là số nguyên. Hãy chọn một bộ định mức 256!

Trong hầu hết các bộ vi điều khiển, có một thứ gọi là Ngắt. Ngắt này có thể được kích hoạt bất cứ khi nào các điều kiện nhất định được đáp ứng. Bây giờ bất cứ khi nào một ngắt được kích hoạt, AVR sẽ dừng và lưu việc thực hiện quy trình chính của nó, tham gia vào lệnh gọi ngắt (bằng cách thực hiện một quy trình đặc biệt, được gọi là Quy trình Dịch vụ Ngắt, ISR) và sau khi thực hiện xong, quay trở lại quy trình chính và tiếp tục thực hiện nó.

Vì độ trễ yêu cầu (50ms) lớn hơn độ trễ tối đa có thể: 4, 096ms = 1000ms / 62500Hz * 256, hiển nhiên là bộ hẹn giờ sẽ bị tràn. Và bất cứ khi nào bộ hẹn giờ bị tràn, ngắt sẽ được kích hoạt.

Ngắt bao nhiêu lần nên được kích hoạt?

50ms / 4.096ms = 3125/256 = 12.207 Nếu bộ đếm thời gian chạy tràn 12 lần, thì 12 * 4.096ms = 49.152ms sẽ trôi qua. Trong lần lặp thứ 13, chúng ta cần độ trễ 50ms - 49.152ms = 0.848ms.

Ở tần số 62500Hz (prescaler = 256), mỗi lần đánh dấu mất 0,016ms. Do đó, để đạt được độ trễ 0,848ms, nó sẽ cần 0,848ms / 0,016ms = 53 tick. Vì vậy, trong lần lặp thứ 13, chúng tôi chỉ cho phép bộ đếm thời gian đếm đến 53, và sau đó đặt lại nó.

Khởi tạo Timer0 / Counter (xem ảnh):

TCCR0B | = (1 << CS02) // thiết lập bộ định thời với bộ đếm trước = 256 TCNT0 = 0 // khởi tạo bộ đếm TIMSK0 | = (1 << TOIE0) // cho phép ngắt tràn sei () // cho phép ngắt toàn cục tot_overflow = 0 // khởi tạo biến bộ đếm tràn

Bước 3: Tuyên bố sự cố 2: Đèn LED thứ hai của Let’s Flash (màu xanh lam) Cứ sau 1 giây

Tuyên bố sự cố 2: Đèn LED thứ hai của Let’s Flash (xanh lam) Cứ sau 1 giây
Tuyên bố sự cố 2: Đèn LED thứ hai của Let’s Flash (xanh lam) Cứ sau 1 giây
Tuyên bố sự cố 2: Đèn LED thứ hai của Let’s Flash (xanh lam) Cứ sau 1 giây
Tuyên bố sự cố 2: Đèn LED thứ hai của Let’s Flash (xanh lam) Cứ sau 1 giây
Tuyên bố sự cố 2: Đèn LED thứ hai của Let’s Flash (xanh lam) Cứ sau 1 giây
Tuyên bố sự cố 2: Đèn LED thứ hai của Let’s Flash (xanh lam) Cứ sau 1 giây

Phương pháp luận:

- sử dụng bộ đếm trước Timer1 để giảm tín hiệu điện tần số cao xuống tần số thấp hơn bằng phép chia số nguyên;

- sử dụng Clear Timer trên Chế độ So sánh (CTC);

- sử dụng Ngắt với Chế độ CTC;

Timer1 (16 bit) nó đếm từ 0 đến 65534 sau đó, chúng bị tràn. Giá trị này thay đổi ở mọi xung đồng hồ.

F_CPU = 16MHz: Khoảng thời gian đồng hồ = 1000ms / 16000000Hz = 0,0000625ms

Đồng hồ đã điểm 15999999 lần để có độ trễ 1 giây!

Chúng ta có thể sử dụng kỹ thuật phân chia tần số được gọi là đặt trước để giảm số đếm của bộ đếm thời gian. AVR cung cấp cho chúng ta các giá trị bộ định tỷ lệ sau để lựa chọn: 8, 64, 256 và 1024. Xem bảng tóm tắt kết quả của việc sử dụng các bộ định tỷ lệ khác nhau. Giá trị bộ đếm phải luôn là số nguyên. Hãy chọn một bộ đếm trước 256!

Trong chế độ Clear timer on Compare (CTC), thanh ghi OCR1A hoặc ICR1 được sử dụng để thao tác độ phân giải của bộ đếm. Trong chế độ CTC, bộ đếm bị xóa về 0 khi giá trị bộ đếm (TCNT1) khớp với OCR1A hoặc ICR1. OCR1A hoặc ICR1 xác định giá trị hàng đầu cho bộ đếm, do đó cũng là độ phân giải của nó. Chế độ này cho phép kiểm soát tốt hơn tần số đầu ra đối sánh so sánh Nó cũng đơn giản hóa hoạt động đếm các sự kiện bên ngoài. Chúng ta phải yêu cầu AVR đặt lại Timer1 / Counter ngay khi giá trị của nó đạt đến giá trị 62500, do đó để đạt được độ trễ 1s.

Khởi tạo Timer1 / Counter (xem ảnh):

TCCR1B | = (1 << WGM12) | (1 << CS12) // thiết lập bộ định thời với prescaler = 256 và chế độ CTC TCNT1 = 0 // khởi tạo bộ đếm TIMSK1 | = (1 << OCIE1A) // cho phép so sánh ngắt OCR1A = 62500 // khởi tạo giá trị so sánh

Bước 4: Tuyên bố sự cố 3: Đèn LED thứ ba của Let’s Flash (màu đỏ) Cứ sau 16 mili giây

Tuyên bố sự cố 3: Đèn LED thứ ba của Let’s Flash (màu đỏ) cứ sau 16 mili giây
Tuyên bố sự cố 3: Đèn LED thứ ba của Let’s Flash (màu đỏ) cứ sau 16 mili giây
Tuyên bố sự cố 3: Đèn LED thứ ba của Let’s Flash (màu đỏ) cứ sau 16 mili giây
Tuyên bố sự cố 3: Đèn LED thứ ba của Let’s Flash (màu đỏ) cứ sau 16 mili giây
Tuyên bố sự cố 3: Đèn LED thứ ba của Let’s Flash (màu đỏ) cứ sau 16 mili giây
Tuyên bố sự cố 3: Đèn LED thứ ba của Let’s Flash (màu đỏ) cứ sau 16 mili giây
Tuyên bố sự cố 3: Đèn LED thứ ba của Let’s Flash (đỏ) Cứ sau 16 mili giây
Tuyên bố sự cố 3: Đèn LED thứ ba của Let’s Flash (đỏ) Cứ sau 16 mili giây

Phương pháp luận:

- sử dụng bộ đếm trước Timer2 để giảm tín hiệu điện tần số cao xuống tần số thấp hơn bằng cách chia số nguyên;

- sử dụng Clear Timer trên Chế độ So sánh (CTC);

- sử dụng Chế độ CTC phần cứng mà không bị gián đoạn;

Timer2 (8 bit) nó đếm từ 0 đến 255 sau đó, chúng bị tràn. Giá trị này thay đổi ở mọi xung đồng hồ.

F_CPU = 16MHz: Khoảng thời gian đồng hồ = 1000ms / 16000000Hz = 0,0000625ms

Đếm bộ hẹn giờ = (Độ trễ bắt buộc / Khoảng thời gian đồng hồ) -1 = (16ms / 0,0000625ms) = 255999

Đồng hồ đã tích điểm 255999 lần để có độ trễ là 16ms!

Xem bảng tóm tắt kết quả của việc sử dụng các bộ định mức trước khác nhau. Giá trị bộ đếm phải luôn là số nguyên. Hãy chọn một bộ đếm trước 1024!

Trong chế độ CTC, bộ đếm bị xóa về 0 khi giá trị bộ đếm (TCNT2) khớp với OCR2A hoặc ICR2. Chân PB3 cũng là chân So sánh đầu ra của TIMER2 - OC2A (xem sơ đồ).

Thanh ghi điều khiển bộ đếm thời gian / bộ đếm 2 A - TCCR2A Bit 7: 6 - COM2A1: 0 - Chế độ đầu ra so sánh cho Thiết bị so sánh A. Vì chúng ta cần chuyển đổi đèn LED, chúng tôi chọn tùy chọn: Chuyển đổi OC2A trên So sánh so sánh Bất cứ khi nào kết hợp so sánh xảy ra, Chân OC2A được tự động bật tắt. Không cần kiểm tra bất kỳ bit cờ nào, không cần quan tâm đến bất kỳ ngắt nào.

Khởi tạo Timer2 / Counter

TCCR2A | = (1 << COM2A0) | (1 << WGM21) // thiết lập chân OC2A của bộ định thời ở chế độ bật tắt và chế độ CTC TCCR2B | = (1 << CS22) | (1 << CS21) | (1 << CS20) // thiết lập bộ đếm thời gian với prescaler = 1024 TCNT2 = 0 // khởi tạo bộ đếm OCR2A = 250 // khởi tạo giá trị so sánh

Bước 5: Viết mã cho chương trình trong C. Tải lên tệp HEX vào bộ nhớ flash của vi điều khiển

Viết mã cho một chương trình trong C. Tải lên tệp HEX vào bộ nhớ flash của vi điều khiển
Viết mã cho một chương trình trong C. Tải lên tệp HEX vào bộ nhớ flash của vi điều khiển
Viết mã cho một chương trình trong C. Tải lên tệp HEX vào bộ nhớ flash của vi điều khiển
Viết mã cho một chương trình trong C. Tải lên tệp HEX vào bộ nhớ flash của vi điều khiển

Viết và xây dựng ứng dụng vi điều khiển AVR trong C Code bằng Nền tảng phát triển tích hợp - Atmel Studio.

F_CPU xác định tần số xung nhịp trong Hertz và phổ biến trong các chương trình sử dụng thư viện avr-libc. Trong trường hợp này, nó được sử dụng bởi các thói quen trì hoãn để xác định cách tính toán độ trễ thời gian.

#ifndef F_CPU

#define F_CPU 16000000UL // cho biết tần số tinh thể của bộ điều khiển (16 MHz AVR ATMega328P) #endif

#include // header để bật kiểm soát luồng dữ liệu qua các chân. Xác định chân, cổng, v.v.

Tệp bao gồm đầu tiên là một phần của avr-libc và sẽ được sử dụng trong khá nhiều dự án AVR mà bạn làm việc. io.h sẽ xác định CPU bạn đang sử dụng (đó là lý do tại sao bạn chỉ định phần khi biên dịch) và lần lượt bao gồm tiêu đề định nghĩa IO thích hợp cho chip mà chúng tôi đang sử dụng. Nó chỉ đơn giản xác định các hằng số cho tất cả các chân, cổng, thanh ghi đặc biệt của bạn, v.v.

#include // header để bật ngắt

dễ bay hơi uint8_t tot_overflow; // biến toàn cục để đếm số lần tràn

Phương pháp luận của Tuyên bố vấn đề: Đèn LED đầu tiên (Xanh lục) nhấp nháy sau mỗi 50 ms

- sử dụng bộ đếm trước Timer0 để giảm tín hiệu điện tần số cao xuống tần số thấp hơn bằng phép chia số nguyên;

- sử dụng ngắt mỗi khi Timer0 tràn;

void timer0_init () // khởi tạo timer0, ngắt và biến

{TCCR0B | = (1 << CS02); // thiết lập bộ định thời với prescaler = 256 TCNT0 = 0; // khởi tạo bộ đếm TIMSK0 | = (1 << TOIE0); // cho phép tràn nterrupt sei (); // cho phép ngắt toàn cục tot_overflow = 0; // khởi tạo biến bộ đếm tràn}

Phương pháp luận của Tuyên bố vấn đề: Đèn LED thứ hai nhấp nháy (màu xanh lam) cứ sau 1 giây

- sử dụng bộ đếm trước Timer1 để giảm tín hiệu điện tần số cao xuống tần số thấp hơn bằng phép chia số nguyên;

- sử dụng Clear Timer trên Chế độ So sánh (CTC);

- sử dụng Ngắt với Chế độ CTC;

void timer1_init () // khởi tạo timer1, ngắt và biến {TCCR1B | = (1 << WGM12) | (1 << CS12); // thiết lập bộ định thời với chế độ prescaler = 256 và CTC TCNT1 = 0; // khởi tạo bộ đếm OCR1A = 62500; // khởi tạo giá trị so sánh TIMSK1 | = (1 << OCIE1A); // bật ngắt so sánh}

Phương pháp luận của Tuyên bố vấn đề: Đèn LED thứ ba nhấp nháy (màu đỏ) sau mỗi 16ms

- sử dụng bộ đếm trước Timer2 để giảm tín hiệu điện tần số cao xuống tần số thấp hơn bằng cách chia số nguyên;

- sử dụng Clear Timer trên Chế độ So sánh (CTC);

- sử dụng Chế độ CTC phần cứng mà không bị gián đoạn;

void timer2_init () // khởi tạo timer2 {TCCR2A | = (1 << COM2A0) | (1 << WGM21); // thiết lập chân OC2A của bộ định thời ở chế độ bật tắt và chế độ CTC TCCR2B | = (1 << CS22) | (1 << CS21) | (1 << CS20); // thiết lập bộ đếm thời gian với prescaler = 1024 TCNT2 = 0; // khởi tạo bộ đếm OCR2A = 250; // khởi tạo giá trị so sánh}

Quy trình dịch vụ ngắt tràn TIMER0 được gọi bất cứ khi nào TCNT0 tràn:

ISR (TIMER0_OVF_vect)

{tot_overflow ++; // theo dõi số lần tràn}

ISR này được kích hoạt bất cứ khi nào một trận đấu xảy ra, do đó, chuyển đổi được dẫn ở đây chính nó:

ISR (TIMER1_COMPA_vect) {PORTC ^ = (1 << 1); // chuyển đổi đã dẫn ở đây}

int main (void)

{DDRB | = (1 << 0); // nối led 1 (xanh) vào chân PB0 DDRC | = (1 << 1); // nối led 2 (màu xanh) vào chân PC1 DDRB | = (1 << 3); // nối led 3 (đỏ) vào chân PB3 (OC2A) timer0_init (); // khởi tạo timer0 timer1_init (); // khởi tạo timer1 timer2_init (); // khởi tạo timer2 while (1) // vòng lặp mãi mãi {

Nếu Timer0 bị tràn 12 lần, thì 12 * 4.096ms = 49.152ms sẽ trôi qua. Trong lần lặp thứ 13, chúng ta cần độ trễ 50ms - 49.152ms = 0.848ms. Vì vậy, trong lần lặp thứ 13, chúng tôi chỉ cho phép bộ đếm thời gian đếm đến 53, và sau đó đặt lại nó.

if (tot_overflow> = 12) // kiểm tra xem có không. trong tổng số lần tràn = 12 LƯU Ý: '> =' được sử dụng

{if (TCNT0> = 53) // kiểm tra xem bộ đếm thời gian có đạt đến 53 hay không {PORTB ^ = (1 << 0); // bật tắt led TCNT0 = 0; // đặt lại bộ đếm tot_overflow = 0; // đặt lại bộ đếm tràn}}}}

Tải lên tệp HEX vào bộ nhớ flash của vi điều khiển:

gõ vào cửa sổ nhắc DOS lệnh:

avrdude –c [tên của lập trình viên] –p m328p –u –U flash: w: [tên tệp hex của bạn] Trong trường hợp của tôi, đó là: avrdude –c ISPProgv1 –p m328p –u –U flash: w: Timers.hex

Lệnh này ghi tệp hex vào bộ nhớ của vi điều khiển. Xem video mô tả chi tiết quá trình ghi bộ nhớ flash của vi điều khiển:

Ghi bộ nhớ flash vi điều khiển…

Vâng! Bây giờ, bộ vi điều khiển hoạt động theo hướng dẫn của chương trình của chúng tôi. Hãy cùng kiểm tra nào!

Bước 6: Làm mạch điện

Làm mạch điện
Làm mạch điện
Làm mạch điện
Làm mạch điện
Làm mạch điện
Làm mạch điện

Kết nối các thành phần phù hợp với sơ đồ.

Đề xuất: