Làm thế nào để tôi tạo một bộ đếm thời gian ngắt với Arduino?


9

Tôi đang cố gắng tạo ra một sự chậm trễ thời gian với Arduino. Tôi muốn sử dụng hàm interts (), vì nó là một ngắt nội bộ.

Ví dụ: Giả sử, tôi muốn bật và tắt đèn, chỉ với thời gian của ngắt.

Có mã mẫu, nhưng nó sử dụng các ngắt ngoài (Đính kèm ()). Tôi muốn vẫn sử dụng các ngắt nội bộ.


2
Tôi nghĩ rằng điểm mà Kortuk cũng thể hiện là phần đính kèm là một thứ trừu tượng, bạn không gắn bất kỳ thành phần bên ngoài nào :)
clabacchio

Bài viết này có thể giúp bạn. engblaze.com/ từ
Seth Archer Brown

Câu trả lời:


10

Blog của Noah Stahl có một ví dụ về việc nhấp nháy đèn LED với Timer2 . Với bảng dữ liệu đó, bạn sẽ có thể điều chỉnh nó theo bất kỳ ngắt nào bạn muốn sử dụng - nghĩa là ngắt có chức năng bình thường mà bạn có thể đủ khả năng nhất để từ bỏ hoặc sẵn sàng sửa đổi. Timer2 thường được sử dụng cho một số chức năng PWM.

Ví dụ của ông trích dẫn ATmega2560; Tôi có thể xác nhận rằng nó cũng hoạt động với ATmega328p. Nhìn xung quanh trang web của anh ấy để biết thêm các ví dụ ngắt Arduino hữu ích.

Biên tập:

Đây là một chút chỉnh sửa của tôi - chủ yếu là trong các nhận xét - phiên bản mã của Nô-ê. Gọi Timer2init () từ chức năng Arduino setup () sau khi bạn khởi tạo mọi cấu trúc dữ liệu hoặc phần cứng có liên quan, vì thời gian - và gián đoạn - sẽ bắt đầu khi bạn thực hiện.

Trước đó, tôi đã sử dụng nó để ghép một màn hình 7 chữ số 3 chữ số để trước khi khởi tạo bộ hẹn giờ, tôi đã khởi tạo các thanh ghi I / O hiển thị và làm trống dữ liệu hiển thị ở nơi ISR ​​sẽ tìm nó.

Có một bảng trong các nhận xét về một số dữ liệu thời gian hữu ích từ bảng dữ liệu và các tính toán của riêng tôi để tham khảo để thiết lập sơ đồ thời gian khác.

Macro ISR () đảm nhiệm việc tạo mã nhập và thoát mã ngắt cho ISR thay vì nhập và thoát của hàm thông thường và liên kết nó với vectơ ngắt thích hợp. Phần còn lại của hàm đó là 1) mã được chạy ở mỗi ngắt và 2) mã mã để đặt lại bộ hẹn giờ cho lần ngắt tiếp theo.

Như đã viết, điều này sẽ rơi vào một bản phác thảo .pde hoặc .ino (hoặc tệp .cpp, nếu bạn sử dụng nhật thực, f / ex). Bản phác thảo cần #define LEDPIN và setup () cần gọi Timer2init (). Hàm lặp có thể trống hoặc không; đèn LED sẽ bắt đầu nhấp nháy khi tải xuống (tốt, theo nghĩa đen, sau khi Timer2init () được gọi).

/*
 * From sample interrupt code published by Noah Stahl on his blog, at:
 * http://arduinomega.blogspot.com/p/arduino-code.html
 * 
 */


/*** FUNC

Name:           Timer2init

Function:       Init timer 2 to interrupt periodically. Call this from 
                the Arduino setup() function.

Description:    The pre-scaler and the timer count divide the timer-counter
                clock frequency to give a timer overflow interrupt rate:

                Interrupt rate =  16MHz / (prescaler * (255 - TCNT2))

        TCCR2B[b2:0]   Prescaler    Freq [KHz], Period [usec] after prescale
          0x0            (TC stopped)     0         0
          0x1                1        16000.        0.0625
          0x2                8         2000.        0.500
          0x3               32          500.        2.000
          0x4               64          250.        4.000
          0x5              128          125.        8.000
          0x6              256           62.5      16.000
          0x7             1024           15.625    64.000


Parameters: void

Returns:    void

FUNC ***/

void Timer2init() {

    // Setup Timer2 overflow to fire every 8ms (125Hz)
    //   period [sec] = (1 / f_clock [sec]) * prescale * (255-count)
    //                  (1/16000000)  * 1024 * (255-130) = .008 sec


    TCCR2B = 0x00;        // Disable Timer2 while we set it up

    TCNT2  = 130;         // Reset Timer Count  (255-130) = execute ev 125-th T/C clock
    TIFR2  = 0x00;        // Timer2 INT Flag Reg: Clear Timer Overflow Flag
    TIMSK2 = 0x01;        // Timer2 INT Reg: Timer2 Overflow Interrupt Enable
    TCCR2A = 0x00;        // Timer2 Control Reg A: Wave Gen Mode normal
    TCCR2B = 0x07;        // Timer2 Control Reg B: Timer Prescaler set to 1024
}



/*** FUNC

Name:       Timer2 ISR

Function:   Handles the Timer2-overflow interrupt

Description:    Maintains the 7-segment display

Parameters: void

Returns:    void

FUNC ***/

ISR(TIMER2_OVF_vect) {
    static unsigned int led_state = 0; // LED state

    led_state = !led_state;         // toggles the LED state
    digitalWrite(TOGGLE_PIN, led_state);

    TCNT2 = 130;     // reset timer ct to 130 out of 255
    TIFR2 = 0x00;    // timer2 int flag reg: clear timer overflow flag
};

(@Kortuk: Nhận xét mà bạn đề cập là quan sát của tôi về một số người bình luận ở đây và không nhắm vào cá nhân bạn và nó không cần thiết. Tôi xin lỗi và tôi đã xóa nó.) bây giờ không chỉ trình diễn, mà còn là hướng dẫn. Nó bao gồm các nhận xét tôi đã viết vào mã để sử dụng cho riêng mình (nghĩa là: Nếu tôi có thể hiểu chúng 6 tháng kể từ bây giờ, người khác cũng sẽ có thể), cũng như một vài hướng dẫn "cách sử dụng" trong câu trả lời. Cảm ơn lời đề nghị của bạn.
JRobert

Lưu ý rằng các giá trị trước của 32 và 128 không có sẵn cho timer0 và timer1 (ít nhất là với atmega328).
tuupola

Đó là điều tốt để biết - cảm ơn. Tôi sử dụng cái này cho Timer2 (cho đến nay) và về cơ bản nó là một phần bổ sung.
JRobert

5

Hàm AttachInterrupt () thực sự đang gắn một ngắt với thay đổi trạng thái bên ngoài trên một pin, nó không có bất kỳ tùy chọn nào khác.

Trên cùng một trang, các tùy chọn chế độ được liệt kê là:

chế độ xác định khi ngắt nên được kích hoạt. Bốn yếu tố được xác định trước là giá trị hợp lệ:

  • THẤP để kích hoạt ngắt bất cứ khi nào pin thấp,
  • THAY ĐỔI để kích hoạt ngắt bất cứ khi nào pin thay đổi giá trị
  • RỦI RO để kích hoạt khi pin đi từ thấp đến cao,
  • FALLING cho khi pin đi từ cao xuống thấp.

Xin lỗi để trở thành người mang tin xấu, đó là một trong những điều đầu tiên tôi cũng tìm kiếm.


Tôi nghĩ rằng anh ta có nghĩa là anh ta muốn sử dụng bộ hẹn giờ bên trong, thay vì một thiết bị bên ngoài ... nhưng tôi không biết rõ về Arduino, vì vậy tôi không thể nói nếu có thể
clabacchio

@clabacchio, tôi đang nói rằng lựa chọn duy nhất là sử dụng kích hoạt bên ngoài, không có chức năng hẹn giờ bên trong.
Kortuk

À, tốt :) nhưng ít nhất các bo mạch Arduino có bộ hẹn giờ nào không?
clabacchio

Vâng, đó là cách họ hoàn thành những thứ như sự chậm trễ.
Kortuk

1
@ icarus74 ATMega328 thực sự có 3 bộ định thời (một là 16b và hai là 8b) nhưng tất cả chúng đều được Arduino sử dụng. Một cái được sử dụng cho các hàm như delay () và millis () và cả ba đều được sử dụng cho PWM (bạn có thể tìm thêm thông tin trong hàm 'init ()', tệp 'Wired.c' trong Arduino IDE).
vasco

2

Bài viết này về PWM sẽ xóa tan rất nhiều nghi ngờ của bạn về việc sử dụng bộ định thời Arduino. Có hai bộ định thời 8 bit và một bộ hẹn giờ 16 bit trên Arduino. Không có API cấp cao để nối trực tiếp chức năng ISR vào bộ định thời, được cung cấp cùng với Arduino SDK (nghĩa là thư viện chuẩn), nhưng phương pháp cài đặt Thanh ghi chức năng đặc biệt và số học bit / hoạt động trên chúng. Tuy nhiên, có một thư viện đóng góp của người dùng được gọi là Timer one .


Thực tế, có một số kết hợp hẹn giờ khác nhau có thể tùy thuộc vào Arduino nào đang được đề cập. Trả lời là sai lệch.
Dường như

@SeeminglySo, quan tâm đến công phu? Nếu bạn đang nói về phần cứng Arduino, lưu ý rằng câu trả lời nằm trong ngữ cảnh của câu hỏi và cũng là lúc câu hỏi được hỏi.
icarus74

Arduino Mega (dựa trên ATmega1280) được phát hành vào ngày 26 tháng 3 năm 2009 và Mega 2560 (ATmega2560) được phát hành vào ngày 24 tháng 9 năm 2010, cả hai trước khi câu hỏi này được hỏi. Cả hai bộ vi điều khiển đều có nhiều hơn bộ đếm thời gian / bộ đếm 2x 8 bit và 1x 16 bit được chỉ định trong câu trả lời.
Dường như

Hầu hết các tương tác tôi đã thấy cho đến nay, có một tài liệu tham khảo rõ ràng về Arduino có nghĩa là giống như Duemilanove hoặc Uno tức là các bảng dựa trên sê-ri 328. Các bảng khác luôn luôn có đủ điều kiện rõ ràng bởi dòng uP không. hoặc Mega, Nano, Micro, v.v ... Dù sao đi nữa, tôi sẽ khiêm tốn chấp nhận sự điều chỉnh. Trong bối cảnh này, một sự làm rõ là tốt hơn.
icarus74

1

Arduino đang sử dụng cả ba bộ định thời trong ATMega328. Timer1(16 bit) được sử dụng cho các chức năng như delay()millis()và cho đầu ra PWM trên các chân 5 và 6. Hai bộ định thời khác - Timer0Timer2được sử dụng cho đầu ra PWM trên các chân 3, 9, 10, 11.

Vì vậy, không có chức năng Arduino cho ngắt hẹn giờ. Nhưng, có một cách. Bạn có thể sử dụng mã này để bật ngắt hẹn giờ Timer2:

ISR(TIMER2_OVF_vect) {
  // Interrupt routine.
}

void setup() {
  // Enable Timer2 interrupt.
  TIMSK2 = (0<<OCIE2A) | (1<<TOIE2);
}

void loop() {
  // Your main loop.
}

Tôi đã viết mã này mà không cần kiểm tra, vì vậy có thể tôi đã mắc lỗi. Trong trường hợp đó, hãy kiểm tra biểu dữ liệu, tr.156 .

Nếu bạn muốn thay đổi tần số hẹn giờ (bộ đếm gộp), chỉ cần thay đổi thanh ghi TCCR2A. Để biết thêm thông tin, hãy xem bảng dữ liệu trang 153. Nhưng nếu bạn thay đổi tần số của bộ định thời gian, bạn cũng thay đổi tần số tín hiệu PWM trên hai chân đầu ra!


AFAIK trên ATmega328 Timer0Timer28 bit và chỉ Timer116 bit.
tuupola

Không, điều này không chính xác. Đó là Timer0, không phải Timer1, được sử dụng cho delay () và millis () và cho đầu ra PWM trên chân 5 và 6. Timer0 là bộ định thời 8 bit. Xem ví dụ: Bộ đếm thời gian và ngắt Arduino .
Peter Mortensen
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.