Bài giảng lập trình avr lưu hành nội bộ HVKTQStài liệu để tham gia minirobotcon .Tài liệu sẽ hướng dẫn cô đọng chi tiết từng nội đung liên quan đên AVR.Tài liệu được tổng hợp từ rất nhiều từ các trang avr trong nước cũng như quốc tế .Đọc hết tài liệu này bạn có thể nắm chắc làm tự làm các dự án liên quan đến AVR đặc biệt liên quan đến lv robot
HỌC VIỆN KỸ THUẬT QUÂN SỰ BỘ MÔN ROBOT ĐB & CĐT - KHOA HÀNG KHÔNG VŨ TRỤ THIẾT KẾ VÀ LẬP TRÌNH MINIROBOT (Dùng cho học viên đào tạo thi miniRobocon) HÀ NỘI 2015 MỤC LỤC LẬP TRÌNH NGẮT Nội dung chương tìm hiểu khái niệm về ngắt ngắt chương trình Trong Phần 3.1, điều ngắt AVR thảo luận Trong mục 3.2, ngắt Timer đề cập đến Ngắt thảo luận mục 3.3 Trong phần 3.4, thứ tự ưu tiên ngắt vi điều khiển AVR nghiên cứu 3.1 Ngắt vi điều khiển AVR Trong mục này, xem xét khác biệt hỏi vòng ngắt, sau ngắt khác AVR tìm hiểu 3.1.1 Ngắt hỏi vòng Mỗi vi điều khiển dùng để điều khiển nhiều thiết bị khác Có hai phương pháp mà vi điều khiển điều khiển thiết bị là: ngắt hỏi vòng Với phương pháp dùng ngắt, thiết bị cần điều khiển vi điều khiển, thiết bị thông báo cho cách gửi tín hiệu ngắt Khi nhận tín hiệu ngắt, vi điều khiển dừng lại tất công việc làm, chuyển sang chương trình điều khiển thiết bị gọi ngắt Các chương trình liên kết với ngắt gọi trình phục vụ ngắt(Interrupt Service routine – ISR hay Interrupt handler) Trong phương pháp hỏi vòng, vi điều khiển liên tục giám sát kiểm tra trạng thái thiết bị định; điều kiện trạng thái đáp ứng, thực trình phục vụ ngắt Sau đó, tiếp tục theo dõi trạng thái thiết bị mỗi ngắt thực Mặc dù phương pháp hỏi vòng theo dõi tình trạng nhiều thiết bị thực trình phục vụ ngắt điều kiện ngắt đáp ứng, nhiên phương pháp phương pháp hiệu vi điều khiển Ưu điểm ngắt vi điều khiển phục vụ cho nhiều thiết bị (không phải tất thời điểm); thiết bị vi điều khiển điều khiển dựa thứ tự ưu tiên gán cho Phương pháp hỏi vòng gán thứ tự ưu tiên kiểm tra tất thiết bị (round-robin scheduler) Quan trọng hơn, phương pháp ngắt vi điều khiển bỏ qua (mask) yêu cầu điều khiển thiết bị Đây điều thực với phương pháp hỏi vòng Lý quan trọng mà ngắt thích hợp phương pháp hỏi vòng phương pháp hỏi vòng, vi điều khiển phải lãng phí nhiều thời gian cho việc kiểm tra yêu cầu điều khiển thiết bị chưa cần điều khiển Vì vậy, ngắt sử dụng để tránh tải cho vi điều khiển 3.1.2 Trình phục vụ ngắt Mỗi ngắt liên kết với chương trình con, chương trình gọi trình phục vu ngắt (ISR Interrupt Handler) Khi ngắt gọi, vi điều khiển thực trình phục vụ ngắt Nói chung, hầu hết vi xử lý, ngắt có vị trí cố định nhớ để lưu địa ISR Tập hợp địa ISR gọi bảng vector ngắt, Bảng Ngắt Reset External Interrupt request External Interrupt request External Interrupt request Time/Counter2 Compare Match Time/Counter2 Overflow Time/Counterl Capture Event Time/Counterl Compare Match A Time/Counterl Compare Match B Time/Counterl Overflow Time/CounterO Compare Match Time/CounterO Overflow SPI Transfer complete USART, Receive complete USART, Data Register Empty USART, Transmit Complete ADC Conversion complete EEPROM ready Analog Comparator Two-wire Serial Interface (I2C) Store Program Memory Read Địa vector ngắt ROOM(Hex) 0000 0002 0004 0006 0008 000A 000C 000E 0010 0012 0014 0016 0018 001A 001C 001E 0020 0022 0024 0026 0028 3.1.3 Các bước để thi hành ngắt(Steps in executing an interrupt) Sau kích hoạt ngắt, vi điều khiển thực bước sau: Kết thúc chương trình thực lưu địa lệnh (program counter) stack Nó nhảy đến địa cố định nhớ gọi bảng vector ngắt Bảng vector ngắt cho vi điều khiển đến địa trình phục vụ ngắt (ISR) Vi điều khiển bắt đầu thực chương trình phục vụ ngắt thực lệnh cuối trình phục vụ ngắt Vi điều khiển quay trở lại nơi mà bị ngắt Đầu tiên, lấy địa chương trình (Program Counter) từ ngăn xếp stack cách đặt byte đầu ngăn stack xếp vào PC Sau đó, bắt đầu thực chương trình từ địa 3.1.4 Các ngắt với vi điều khiển AVR(Sources of interrupts in the AVR) Có nhiều ngắt AVR, tùy thuộc vào số thiết bị ngoại vi kết nối với chip Sau số ngắt thường sử dụng AVR: • Có hai ngắt dành cho Timer, ngắt tràn(overflow interrupt) ngắt so sánh(Compare interrupt) • Ba ngắt thiết lập dành cho ngắt phần cứng bên Các chân PD2 (PORTD.2), PD3 (PORTD.3), PB2 (PORTB.2) dành cho ngắt INT0, INT1, INT2, tương ứng • Truyền thông USART có ba ngắt, dành cho nhận tín hiệu hai ngắt cho truyền tín hiệu • Ngắt SPI • Ngắt ADC (analog-to-digital converter) 3.1.5 Kích hoạt không kích hoạt ngắt (Enabling and disabling an interrupt) Sau vi điều khển khởi động khởi động lại, tất ngắt bị vô hiệu hóa (mask), có nghĩa không ngắt đáp ứng vi điều khiển chúng kích hoạt Các ngắt phải cho phép (unmask) phần mềm vi điều khiển đáp ứng cho chúng Bit D7 ghi trạng thái SREG (Status Register) kích hoạt vô hiệu hóa toàn ngắt vi điều khiển Hình … cho thấy bit ghi SREG Bit I dùng để việc vô hiệu hóa tất ngắt cách thiết lập giá trị Hình : Thanh ghi trạng thái(SREG- Status Register) Để cho phép ngắt hoạt động, bước sau phải thực hiện: • Bit D7 (I) ghi SREG phải thiết lập mức cao HIGH phép ngắt xảy Điều thực với lệnh "SEI" (Set Interrupt) • Nếu I = , ngắt cho phép cách thiết lập mức cao HIGH bit cho phép ngắt hoạt động Trong AVR, có số ghi I/O chứa bit cho phép ngắt hoạt động Ví dụ, ghi TIMSK có bit cho phép ngắt Timer0, Timer1, Timer2 hoạt động.Chú ý rằng, bit I = 0, không ngắt đáp ứng, bit cho phép hoạt động thiết lập mức HIGH OCIE0 TOIE0 TICIE1 OCIE1A Bít điều khiển ngắt tràn Timer0 = không cho phép ngắt tràn Timer0 = cho phép ngắt tràn Timer0 Bít điều khiển ngắt so sánhTimer0 = không cho phép ngắt so sánhTimer0 = cho phép ngắt so sánhTimer0 Bít điều khiển ngắt tràn Timer1 = không cho phép ngắt tràn Timer1 = cho phép ngắt tràn Timer1 Bít điều khiển ngắt so sánh kênh Btimer1 = không cho phép ngắt so sánh kênh B Timer1 = cho phép ngắt so sánh kênh B Timer1 Bít điều khiển ngắt so sánh kênh A Timer1 = không cho phép ngắt so sánh kênh A Timer1 = cho phép ngắt so sánh kênh A Timer1 Bít điều khiển ngắt input capture interrupt Timer1 TOIE1 = không cho phép ngắt input capture interrupt Timer1 = cho phép ngắt input capture interrupt Timer1 Bít điều khiển ngắt tràn Timer2 OCIE0 = không cho phép ngắt tràn Timer2 = cho phép ngắt tràn Timer2 Bít điều khiển ngắt so sánhTimer2 TOIE0 = không cho phép ngắt so sánhTimer2 = cho phép ngắt so sánhTimer2 Hình : Thanh ghi điều khiển ngắt timer TIMSK(Timer Interrupt Mask) OCIE1B 3.2 Ngắt Timer Trong chương … thảo luận làm để sử dụng Timers 0, 1, với phương pháp hỏi vòng Trong phần việc sử dụng ngắt để viết chương trình tính với vi điều khiển AVR nghiên cứu Người đọc cần xem trước chương … Thay đổi trạng thái cờ ngắt ngắt Timer Như biết Chương …, cờ tràn Timer thiết lập lên mức cao giá trị ghi đếm Timer chuyển từ giá trị cực đại 0x00 Trong chương này, cho thấy làm để theo dõi cờ timer với hướng dẫn "SBRS R2 0, TOVO" Trong phương pháp hỏi vòng, chương trình phải chờ cờ TOVO thiết lập mức cao Vấn đề với phương pháp vi điều khiển phải kiểm tra liên tục xem cờ TOVO thiết lập lên mức cao chưa, làm điều khác Việc sử dụng ngắt tránh làm cho điều khiển bị tải Nếu bit cho phép ngắt tràn Timer0 ghi TIMSK kích hoạt, cờ TOV0 nâng lên ghi đếm Timer0 chuyển từ 0xFF sang 0x00, vi điều khiển nhảy đến bảng vector ngắt để thực trình phục vụ ngắt ISR Bằng cách này, vi điều khiển làm việc khác thông báo ghi đếm Timer0 tràn Ngắt Bit cờ tràn Thanh ghi Timer0 TOV0 TIFR Bit kích hoạt TOIE0 Thanh ghi TIMSK Timer1 Timer2 TOV1 TOV2 TIFR TIFR TOIE1 TOIE2 TIMSK TIMSK Hình : Cờ kích hoạt ngắt Timer ghi Cờ so sánh ngắt Đôi nhiệm vụ cần thực lặp lặp lại Các chương trình viết cách sử dụng chế độ CTC cờ so sánh (OCF) Để làm vậy, cần phải nạp giá trị thích hợp vào ghi OCR khởi tạo đếm thời gian hoạt động chế độ CTC Khi giá trị ghi đếm TCNT giá trị ghi OCR, cờ OCF thiết lập mức cao, cờ so sánh thiết lập lên mức cao ngắt so sánh xảy Ví dụ 10-3: Sử dụng Timer0 Timer1 viết chương trình : a PORTA đếm lên Timer1 tràn Timer1 tràn giây lần b Mộ nguồn xung nối với Timer0 Timer0 sử dụng để đếm lên số xung Bất giá trị ghi đếm Timer0 200, trạng thái PORTB.0 thay đổi Đáp án : #include #include int main () { DDRA = 0xFF; DDRD = 0xFF; DDRB |= 0x40; PORTB |= 0x01; TCNT0 = -200; TCCR0 = 0x06; TCNT1H TCNT1L TCCR1A TCCR1B = = = = //make PORTA output //make PORTD output //PORTB.6 as an output //activate pull-up //load TimerO with -200 //Normal mode, falling edge, no prescaler (-31250)>>8; (-31250)&0xFF; 0x00; 0x04; //the high byte //overflow after 31250 clocks //Normal mode //internal clock, prescaler 1:256 TIMSK = (1[...]... Điều gì xảy ra nếu vi điều khiển AVR đang thực hiện một trình phục vụ ngắt ISR thì một ngắt khác được kích hoạt? Khi vi điều khiển AVR bắt đầu thực hiện một trình phục vụ ngắt ISR, nó vô hiệu hóa bit I trong thanh ghi SREG, gây ra tất cả các ngắt bị vô hiệu, và không có ngắt nào khác xảy ra trong khi trình phục vụ ngắt đang thực hiện Khi lệnh RETI được thực hiện, AVR thiết lập bit I lên mức cao, điều này... bất kỳ ưu tiên) được thực hiện trong khi một trình phục vụ ngắt khác đang được thực, có thể thiết lập bit I bằng cách sử dụng lệnh SEI Tuy nhiên người lập trình cần phải thực hiện điều đó một cách cẩn thận Ví dụ, khi một ngắt ngoài với mức ưu tiên đang được thực hiện, thiết lập bit I lên mức cao trong khi chân ngắt ngoài vẫn còn hoạt động sẽ gây ra việc trình phục vụ ngắt ISR được kích hoạt trở lại... được thiết lập khi thanh ghi bộ đếm của Timer0 ngược Khi giá trị thanh ghi bộ đếm TCNT0 chuyển từ $ FF đến 00, cờ TOVO được thiết lập lên 1 và nó vẫn được thiết lập cho đến các phần mềm xóa nó 22 Để xóa cờ này, cần phải viết 1(không phải viết 0) tới nó Thật vậy quy tắc này áp dụng cho tất cả các lá cờ của các chip AVR Trong AVR, khi muốn xóa một bit cờ bất kỳ trong một thanh ghi, cần phải thiết lập bit... thể thiết lập giá trị của thanh ghi đếm với giá trị FD16 = 25310 và chờ đợi cho đến khi cờ được thiết lập sau 3 xung nhịp của bộ tạo dao động Sau xung lần đầu tiên, giá trị thanh ghi đếm tăng lên FE16 = 25410 ; sau xung thứ hai, nó sẽ trở thành FF16 = 25510 ; và sau xung thứ ba, nó tràn (giá trị của thanh ghi bộ đếm được thiết lập về 0016 = 0010 0x00) và cờ được thiết lập Các vi điều khiển AVR có từ... đến khi nó đạt đến giá trị tối đa OxFF Khi giá trị của thanh ghi này chuyển từ 0xFF sang 0x00, nó thiết lập mức cao cho cờ TOV0 (Timer tràn) Các bước để lập trình Timer0 ở chế độ bình thường Để tạo ra một khoangt thời gian trễ sử dụng Timer0 ở chế độ bình thường, các bước thực hiện như sau : - Thiết lập giá trị đếm ban đầu cho thanh ghi TCNT0 - Ghi giá trị vào các bit của thanh ghi điều khiển TCCR0,... nếu nó được thiết lập lên 1 - Dừng hoạt động của Timer0 bằng cách ngắt nguồn xung nhịp đồng hồ : TCCR0 = 0x00 ; // timer stopped, mode = Normal - Xóa cờ TOV0 cho các vòng tiếp theo - Quay trở lại bước 1 để tải TCNT0 lại Ví dụ 9-3: Trong chương trình sau đây, xung vuông 50% được tạo ra trên chân PORTB.5 Timer0 được sử dụng để tạo thời gian trễ Phân tích 23 chương trình trên #include void T0Delay();... cờ OCF0 sẽ được thiết lập và quá trình xóa thanh ghi bộ đếm xảy ra Điều đó có nghĩa giá trị của thanh ghi TCNT0 được xóa sau 9 + 1 = 10 chu kỳ đồng hồ Bởi vì XTAL = 8 MHz, bộ đếm đếm lên mỗi 0.125µ s Do đó, khoảng thời gian giữ chậm được tạo ra là 10 × 0.125µ s = 1.25µ s Ví dụ 9.19: Tìm thời gian trễ được tạo ra bởi Timer0 trong đoạn chương trình sau XTAL = 8MHz #include 31 int main()... PORTD = PINC; //wait here } ISR (TIMER0_OVF_vect) { //ISR for TimerO compare match 16 PORTB ^= 0x20; //toggle PORTB.5 ) CHƯƠNG 4 LẬP TRÌNH VỚI TIMER/COUNTER Trong thực tế, nhiều ứng dụng cần phải đếm sự kiện hoặc tạo ra các khoảng trễ thời gian Do đó, trong vi điều khiển AVR có các thanh ghi được thiết kế để dùng cho mục đích này Xem hình 1 Khi muốn đếm một sự kiện, nguồn sự kiện bên ngoài được kết... hiện ngắt 1 Ví dụ 10-13: Giả sử chân INT0 được nối với một công tắc mà ở trạng thái không bấn thì luôn ở mức cao Viết một chương trình thay đổi trạng thái PORTC.3 chỉ một lần khi bấm công tắc(trạng thái của chân INT0 xuống mức thấp) Đáp án : #include #include int main () { DDRC = 1