Em đang thử mày mò lập trình nhận dạng Remote hồng ngoại để điều khiển một số thiết bị.
Và thử làm remote học mã!
Em có tham khảo một số ý tưởng trên mạng mạng và trên trang của mình thì thấy rất khả thi.
Tuy nhiên, em vẫn chưa hiểu rõ về chức năng Input capture để đo độ rộng xung của Timer 1
Ý tưởng của em la thế này:
Tại chân ICP - chân 20 của Atmega16 - mắc với đầu ra mắt thu hồng ngoại.
Khai báo tần số timer 1 là 1000khz sau khi qua bộ chia. Khai báo chức năng ngắt tràn timer1, ngắt Input capture. Cho phép ngắt Input capture khi có xung tại chân ICP xuống thấp (falling edge)
1. Đợi chân ICP xuống mức thấp (khi có tín hiệu của remote). Tiến hành reset Timer1, đổi trạng thái ngắt ICP thành tác động sườn lên (rising edge).
Khi có ngắt lần 2 (sườn lên vừa thay đổi trước đó của ICP), thì lưu lại giá trị của timer1 trong thanh ghi ICR. Ta có được độ rộng xung thấp.
2. Tuơng tự ta reset timer 1 và tiếp tục đảo sườn tác động ngắt của ICP thành sườn xuống (falling edge), đợi cho xảy ra ngắt ta lại lưu lại giá trị đếm đựoc của timer1 trong thanh ghi ICR. Ta có được độ rộng của xung cao.
Vấn đề ở đây là hình như cách em lấy giá trị của timer 1 trong thanh ghi ICR bị sai thì phải, cả cách reset cho timer 1 đếm lại từ đầu cũng sai.
Dưới đây là code em viết. Anh chị nào xem và giải thích giúp sai chổ nào. Nếu anh chị nào có sẵn code về chức năng Input capture đo xung này thì cho em xin càng tốt.
Đây là phần em khai báo timer1
Và thử làm remote học mã!
Em có tham khảo một số ý tưởng trên mạng mạng và trên trang của mình thì thấy rất khả thi.
Tuy nhiên, em vẫn chưa hiểu rõ về chức năng Input capture để đo độ rộng xung của Timer 1
Ý tưởng của em la thế này:
Tại chân ICP - chân 20 của Atmega16 - mắc với đầu ra mắt thu hồng ngoại.
Khai báo tần số timer 1 là 1000khz sau khi qua bộ chia. Khai báo chức năng ngắt tràn timer1, ngắt Input capture. Cho phép ngắt Input capture khi có xung tại chân ICP xuống thấp (falling edge)
1. Đợi chân ICP xuống mức thấp (khi có tín hiệu của remote). Tiến hành reset Timer1, đổi trạng thái ngắt ICP thành tác động sườn lên (rising edge).
Khi có ngắt lần 2 (sườn lên vừa thay đổi trước đó của ICP), thì lưu lại giá trị của timer1 trong thanh ghi ICR. Ta có được độ rộng xung thấp.
2. Tuơng tự ta reset timer 1 và tiếp tục đảo sườn tác động ngắt của ICP thành sườn xuống (falling edge), đợi cho xảy ra ngắt ta lại lưu lại giá trị đếm đựoc của timer1 trong thanh ghi ICR. Ta có được độ rộng của xung cao.
Vấn đề ở đây là hình như cách em lấy giá trị của timer 1 trong thanh ghi ICR bị sai thì phải, cả cách reset cho timer 1 đếm lại từ đầu cũng sai.
Dưới đây là code em viết. Anh chị nào xem và giải thích giúp sai chổ nào. Nếu anh chị nào có sẵn code về chức năng Input capture đo xung này thì cho em xin càng tốt.
Code:
// Timer1 input capture interrupt service routine interrupt [TIM1_CAPT] void timer1_capt_isr(void) { // Place your code here if(khoidong == 0) //bien kiem tra ngắt lần đầu tiên { TCNT1=0x00; // reset timer 1 về 0 (cách gán lại giá trị đếm cho timer1 thế này đúng không ạ) TCCR1B=0x42; //cho chan ICP ngat o xung cao khoidong = 1; } if(ngatkdlan1 == 1) { timekdlow = (unsigned int)ICR1H*256 + ICR1L; //do xung khoi dong thap //đọc lại giá trị của timer 1 (anh chị xem thế này đúng chưa ạ) TCNT1 = 0x00; //reset timer1 TCCR1B=0x02; //doi chan ICP xuong xung thap khoidong = 2; ngatkdlan1 = 0; } ........
Code:
// Timer/Counter 1 initialization // Clock source: System Clock // Clock value: 1000.000 kHz // Mode: Normal top=0xFFFF // OC1A output: Discon. // OC1B output: Discon. // Noise Canceler: Off // Input Capture on Falling Edge // Timer1 Overflow Interrupt: On // Input Capture Interrupt: On // Compare A Match Interrupt: Off // Compare B Match Interrupt: Off TCCR1A=0x00; TCCR1B=0x02; TCNT1H=0x00; TCNT1L=0x00; ICR1H=0x00; ICR1L=0x00; OCR1AH=0x00; OCR1AL=0x00; OCR1BH=0x00; OCR1BL=0x00;
Comment