You are on page 1of 23

This program was produced by the CodeWizardAVR V2.04.

1 Evaluation Automatic Program Generator © Copyright 1998-2009 Pavel Haiduc, HP InfoTech s.r.l. http://www.hpinfotech.com Project : Version : Date : 6/12/2009 Author : Freeware, for evaluation and non-commercial use only Company : Comments: Chip type : ATmega32 Program type : Application AVR Core Clock frequency: 8.000000 MHz Memory model : Small External RAM size : 0 Data Stack size : 512 ************************************************** ***/ #include <mega32.h> // Timer 0 overflow interrupt service routine interrupt [TIM0_OVF] void timer0_ovf_isr(void) { // Place your code here } // Timer 0 output compare interrupt service routine interrupt [TIM0_COMP] void timer0_comp_isr(void) { // Place your code here } // Declare your global variables here void main(void) { // Declare your local variables here // Input/Output Ports initialization // Port A initialization

// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T PORTA=0x00; DDRA=0x00; // Port B initialization // Func7=In Func6=In Func5=In Func4=In Func3=Out Func2=In Func1=In Func0=In // State7=T State6=T State5=T State4=T State3=0 State2=T State1=T State0=T PORTB=0x00; DDRB=0x08; // Port C initialization // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T PORTC=0x00; DDRC=0x00; // Port D initialization // Func7=Out Func6=In Func5=Out Func4=Out Func3=In Func2=In Func1=In Func0=In // State7=0 State6=T State5=0 State4=0 State3=T State2=T State1=T State0=T PORTD=0x00; DDRD=0xB0; // Timer/Counter 0 initialization // Clock source: System Clock // Clock value: 125.000 kHz // Mode: Phase correct PWM top=FFh // OC0 output: Inverted PWM TCCR0=0x73; TCNT0=0x00; OCR0=0x7f; // Timer/Counter 1 initialization // Clock source: System Clock // Clock value: 31.250 kHz // Mode: Fast PWM top=03FFh // OC1A output: Inverted // OC1B output: Non-Inv. // Noise Canceler: Off // Input Capture on Falling Edge // Timer 1 Overflow Interrupt: Off // Input Capture Interrupt: Off // Compare A Match Interrupt: Off // Compare B Match Interrupt: Off TCCR1A=0xE3; TCCR1B=0x0C;

// External Interrupt(s) initialization // INT0: Off // INT1: Off // INT2: Off MCUCR=0x00. // Timer/Counter 2 initialization // Clock source: System Clock // Clock value: 7. TCCR2=0x6F. ICR1H=0x00. TCNT2=0x00. // Timer(s)/Counter(s) Interrupt(s) initialization TIMSK=0x03. OCR2=0x00.TCNT1H=0x00. // Global enable interrupts #asm("sei") while (1) { // Place your code here . SFIOR=0x00. TCNT1L=0x00. // Analog Comparator initialization // Analog Comparator: Off // Analog Comparator Input Capture by Timer/Counter 1: Off ACSR=0x80. OCR1AL=0xe2. ICR1L=0x00. OCR1BH=0x0f. MCUCSR=0x00.813 kHz // Mode: Fast PWM top=FFh // OC2 output: Non-Inverted PWM ASSR=0x00. OCR1AH=0x08. OCR1BL=0x0f.

} .}.

COM01) PWM (pulse width modulation) là biến điệu độ rộng xung. Mẫu cơ bản là dùng PWM để điều khiển động cơ DC có điện áp 3-12V. DDRB. nếu OCR0=0xff -> V tạo ra là 0V. nhắc tới nguồn xung thì người ta nghĩ ngay đến PWM. Trong các thiết bị cơ điện tử. OCR0=0x00. //Nếu lối ra đảo. //qua bộ lọc RC tạo ra điện áp Vcc/2 . mô-men của động cơ DC rất có iệu quả.3=1 // Portb3 là lối ra PWM //Để tạo ra điện áp lối ra PWM theo ý muốn. . bạn đặt giá trị cho OCR0 OCR0=0x7f . thường dùng PWM để điều tốc. dòng tới 500mA. nhưng có thể mở rộng với điện áp cao hơn! 1/.000 kHz // dùng thạch anh 4MHz.COM00. PWM (Pulse Width Modulation) đang đóng vai trò gần như tuyệt đối trong các hệ công suất chuyển mạch SMPS (Switch Mode Power Supply) còn gọi là nguồn xung. PWM tốc độ cao nhất // Mode: Fast PWM top=FFh // chon chế độ fast PWM 8bit // OC0 output: Inverted PWM // lối ra đảo ! TCCR0=0x79. Nói một cách khác. ngược lại OCR0=0x0 V tạo ra là Vcc.Bạn có thể chọn lối ra không đảo( trong Wizard của CV hoặc nếu dùng ASM thì xem lại trong datasheet để set các bit WGM00.Fast pwm // Timer/Counter 0 initialization // Clock source: System Clock // Clock value: 4000. TCNT0=0x00.WGM01.

Trong đó mức năng lượng tỷ lệ thuận với thời gian mở xung (độ rộng xung tính trên đơn vị thới gian. Để tạo ra xung PWM có điều khiển (CPWM / Controled PWM). 3/.h> #define xtal 4000000//thach anh 4Mhz int dem=0.5 ms --> ta có độ điều biến 50% duty.com/forum/forum_post. với t(on) = 0. chu kỳ t bằng tổng thời gian mở xung t(on) với thời gian tắt xung t(off).ant7. Ví dụ.asp? TID=7026&PN=3#ixzz1OZpsKTc7 -Phần VDK phải trình bày PWM . t = t(on) + t(off).Phần lưu đồ giải thuật phải vẽ dưới dạng các khối chuẩn của một lưu đồ giải thuật //chuong trinh dung cac ngat ngoai trong AVR #include<mega8. Với tần số cố định. . //trinh phuc vu ngat cua INT0 interrupt [EXT_INT0] void ext_int0_isr(void) { dem++. Tần số xung trong PWM có thể cố định hay biến đổi (thường là cố định tần số xung chuyển mạch).1=0. trong đó có sử dụng PWM của VDK . Read more: http://www. 4/.Phần mô hình phải có sơ đồ khối. PORTC.2/.Giải thích sơ đồ khối . đặc trưng thành thuật ngữ "% duty". người ta giao hội giữa một xung hình tam giác với điện áp điều khiển trong một hệ khuếch đại tuyến tính (Op-Amp).1=1. tần số xung 1 KHz --> t = 1 ms. Tỷ lệ của thời gian mở trên chu kỳ xung chính là độ sâu điều biến độ rộng xung. if (dem==1){ PORTB. PWM tạo dựng trên nguyên tắc chuyển lải năng lượng từ A đến B dưới dạng các xung vuông toàn áp (biên độ xung gần với điện áp nguồn cung cấp) liên tiếp.

dem=0. //xay ra ngat khi co canh xuong o chan INT0 hoac chan INT1 GIFR=0xC0. PORTB. PORTC.1=0. PORTC.1=0. } if (dem==0){ PORTB. PORTC.0=0. PORTC.0=0. } if (dem==2){ PORTB.0=1.0=0.PORTC. PORTC.0=1. PORTC. PORTC.1=0.1=1. DDRC.1=1.0=0. } void main(void) { DDRB. PORTC. DDRC. PORTC. } if (dem==1){ PORTB. PORTC. dem=3. PORTC. PORTC.1=0.1=0.1=0.0=1.1=1. } } // Trinh phuc vu ngat cua INT1 interrupt [EXT_INT1] void ext_int1_isr(void) { if (dem==2){ PORTB.1=1.1=0. } if (dem==3){ PORTB. #asm("cli") //thiet lap hoat dong cho ngat ngoai 0 (INT0) va ngat ngoai 1 (INT1): GICR=0xC0.1=0. } dem--.1=1.0=0.//cho cac co ngat len 1 de thuc hien cac ngat khoi dau #asm("sei") //cho ngat } Dieu rong xung pwm voi avr .//cho phep ngat ngoai 0 va ngat ngoai 1 MCUCR=0x0A.1=0.

số lần ngắt / giây: T=clock tỉmer /255*n (với n là số chia 8. TCNT0=150. for evaluation and non-commercial use only Company : Comments: Chip type : ATmega32 Program type : Application AVR Core Clock frequency: 8. HP InfoTech s.l.000000 MHz Memory model : Small External RAM size : 0 Data Stack size : 512 ************************************************** ***/ #include <mega32. 64 .com Project : Version : Date : 6/12/2009 Author : Freeware.hpinfotech. //dat CLK preceal to 8.h> // Timer 0 overflow interrupt service routine .1 Evaluation Automatic Program Generator © Copyright 1998-2009 Pavel Haiduc. http://www. tùy từng bộ timer ) từ đây ta tính được trong 1s có bao nhiêu xung =? Tính được tân số :F=1/T This program was produced by the CodeWizardAVR V2.r. OCR0=50. compare mode DDRB=0xFF. 32 ..04.TCCR0=(0<<WGM01)|(1<<WGM00)|(1<<CS01)|(1<<COM01).

DDRA=0x00. . // Port B initialization // Func7=In Func6=In Func5=In Func4=In Func3=Out Func2=In Func1=In Func0=In // State7=T State6=T State5=T State4=T State3=0 State2=T State1=T State0=T PORTB=0x00. DDRB=0x08.interrupt [TIM0_OVF] void timer0_ovf_isr(void) { // Place your code here } // Timer 0 output compare interrupt service routine interrupt [TIM0_COMP] void timer0_comp_isr(void) { // Place your code here } // Declare your global variables here void main(void) { // Declare your local variables here // Input/Output Ports initialization // Port A initialization // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T PORTA=0x00. // Port C initialization // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T PORTC=0x00.

TCNT1H=0x00. ICR1H=0x00. DDRD=0xB0. OCR1AH=0x08. TCNT1L=0x00. // Timer/Counter 0 initialization // Clock source: System Clock // Clock value: 125.000 kHz // Mode: Phase correct PWM top=FFh // OC0 output: Inverted PWM TCCR0=0x73. // Port D initialization // Func7=Out Func6=In Func5=Out Func4=Out Func3=In Func2=In Func1=In Func0=In // State7=0 State6=T State5=0 State4=0 State3=T State2=T State1=T State0=T PORTD=0x00. . // Timer/Counter 1 initialization // Clock source: System Clock // Clock value: 31. // Noise Canceler: Off // Input Capture on Falling Edge // Timer 1 Overflow Interrupt: Off // Input Capture Interrupt: Off // Compare A Match Interrupt: Off // Compare B Match Interrupt: Off TCCR1A=0xE3.250 kHz // Mode: Fast PWM top=03FFh // OC1A output: Inverted // OC1B output: Non-Inv. TCCR1B=0x0C.DDRC=0x00. OCR0=0x7f. ICR1L=0x00. TCNT0=0x00.

OCR2=0x00. // External Interrupt(s) initialization // INT0: Off // INT1: Off // INT2: Off MCUCR=0x00. OCR1BH=0x0f. // Global enable interrupts #asm("sei") while (1) { // Place your code here . // Analog Comparator initialization // Analog Comparator: Off // Analog Comparator Input Capture by Timer/Counter 1: Off ACSR=0x80.OCR1AL=0xe2. TCNT2=0x00. TCCR2=0x6F. OCR1BL=0x0f. SFIOR=0x00.813 kHz // Mode: Fast PWM top=FFh // OC2 output: Non-Inverted PWM ASSR=0x00. MCUCSR=0x00. // Timer(s)/Counter(s) Interrupt(s) initialization TIMSK=0x03. // Timer/Counter 2 initialization // Clock source: System Clock // Clock value: 7.

hiển thị thông tin trạng thái…rõ ràng trong các nhiệm vụ này việc nhận thông tin người dùng. xuất tín hiệu điều khiển. yêu cầu bộ xử lí tạm ngừng tức khắc các hoạt động hiện tại để “nhảy” đến một nơi khác thực hiện một nhiệm vụ khẩn cấp nào đó. Như vậy. nhận tín hiệu từ cảm biến.}. ngắt báo quá trình gởi dữ liệu bằng RS232 kết thúc…) hay do các tác nhân bên ngoài (ngắt báo có 1 button được nhấn. Hãy tưởng tượng bạn cần thiết kế một mạch điều khiển hoàn chỉnh thực hiện rất nhiều nhiệm vụ bao gồm: nhận thông tin từ người dùng qua các nút nhấn. Nhiệm vụ theo dõi các sự kiện “khẩn cấp” có thể thực hiện bằng 1 trong 2 cách:+Viết 1 hàm thăm dò sự kiện (ví dụ như hàm Button read đã giới thiệu ở bài 1) và phải gọi hàm này ra liên tục. Sau khi kết thúc nhiệm vụ trong ISR. Các tín hiệu dẫn đến ngắt có thể xuất phát từ các thiết bị bên trong chip (ngắt báo bộ đếm timer/counter tràn. là một tín hiệu khẩn cấp gởi đến bộ xử lí. bộ đếm chương trình sẽ được trả về giá trị trước đó để bộ xử lí quay về thực hiện tiếp các nhiệm vụ còn dang dở. ngắt thường được dùng để xử lí các sự kiện bất ngờ nhưng không tốn quá nhiều thời gian. Khái niệm. nếu chương trình chính có quá nhiều nhiệm vụ như đã nói ở trên thì cách này không hiệu quả. Tuy nhiên. ngắt có mức độ ưu tiên xử lí cao nhất. lúc này vi điều khiển sẽ không tốn thời gian cho hàm . nếu đang thực thi 1 hàm khác mà xảy ra sự kiện thì hàm thăm dò trở nên vô dụng và vi điều khiển bắt sót sự kiện. hay tín hiệu cảm biến rất hiếm xảy ra so với các nhiệm vụ khác nhưng lại rất “khẩn cấp” cần được ưu tiên hàng đầu. xử lí thông tin. Ứng dụng. BỘ ĐỊNH THỜI I. 2. Interrupts hay ngắt. +Sử dụng ngắt. } BÀI 3: LẬP TRÌNH NGẮT TRÊN AVR ỨNG DỤNG NGẮT NGOÀI. 1. Ngắt trên AVR. ngắt báo có 1 gói dữ liệu đã được nhận…). nhiệm vụ này gọi là trình phục vụ ngắt – ISR (interrupt service routine ). Lý do đưa ra là mỗi hàm cần 1 thời gian thực thi nhất định.

khi đó hàm quét led sẽ là trình phục vụ ngắt và nó sẽ được gọi ra theo 1 chu kỳ xác định với mức ưu tiên cao nhất. ứng với mỗi ngắt sẽ có vector ngắt. cứ sau 1 khoảng thời gian cố định thì xảy ra 1 ngắt. khi đó mọi công việc khác được gác lại cho đến khi xử lý xong công việc mà ngắt giao cho(trình phục vụ ngắt). Số lượng ngắt trên mỗi dòng chip là khác nhau. nếu thực hiện các đoạn lệnh thì vi điều khiển thực hiện công việc 1 cách tuần tự ( từng dòng lệnh được thực thi). Vi điều khiển sẽ thực thi nhiệm vụ xử lý sự kiện khi mà có ngắt xảy ra. Tóm lại.thăm dò nữa. nếu sử dụng ngắt thì vi xử điều khiển thực hiện công việc 1 cách ngẫu nhiên (thực hiện công việc khi có sự kiện ngẫu nhiên). ta ứng dụng vào nhiệm vụ quét led chẳng hạn. vector ngắt là các thanh ghi có địa chỉ cố định được định nghĩa trc nam trog phan dau cua bo nho chuong triih . Một ví dụ khác cho ứng dụng của ngắt là bộ định thời (ngắt tràn timer/counter). Như vậy sẽ không có hiện tượng led bị chớp do vi điều khiển thực hiện quá nhiều công việc(thời gian giữa 2 lần quét bị giãn ra). Hình 1 minh họa cách tổ chức ngắt thông thường trong các chip AVR.

Trong MikroC. trình phục vụ ngắt được định nghĩa như 1 hàm thông thường nhưng kèm theo khai báo địa chỉ của vector ngắt.3. . Trình phục vụ ngắt – ISR. Cú pháp khai báo như sau: Kiểu_dữ_liệu_trả_vềTên_hàm() org địa_chỉ vector_ngắt { Khối lệnh.

quan sát hình 2 trước khi tìm hiểu 2 thanh ghi này. mỗi thiết bị bao gồm một tập hợp các thanh ghi điều khiển. có 3 thanh ghi liên quan đến ngắt ngoài đó là MCUCR. Các thanh ghi điều khiển ngắt ngoài. ta có 3 ngắt ngoài là INT0. MCUCR (MCU Control Register) và MCUCSR (MCU Control and Status Register) Là2 thanh ghi xác lập chế độ ngắt cho ngắt ngoài. Với ngắt ngoài. 1. GICR và GIFR. Cụ thể các thanh ghi được 2. USART. các ngắt khác thường gắn với hoạt động của 1 thiết bị nào đó như Timer/counter. } Ngắt ngoài (External Interrupt).} Địa chỉ vector ngắt được liệt kê trong bảng 1(bỏ đi $ vì đây là ký hiệu địa chỉ tuyệt đối. PD3. trạng thái.SFR (Special Function Registers) trên vùng nhớ IO. Ví dụ: // Trình phục vụ ngắt khai báo trong phần mềm MikroC voidInterrupt() org 0x16 { // chọn ngắt có địa chỉ là $016 RS485Master_Receive(data). ngắt…khác nhau. PB2. Khi làm việc với các thiết bị ngoại vi của AVR. ADC… Ngắt ngoài là cách rất hiệu quả để thực hiện giao tiếp giữa người dùng và vi điều khiển. . a. hầu như chúng ta chỉ thao tác trên các thanh ghi chức năng đặc biệt . định dạng theo hệ thập lục phân trong C). INT1 và INT2 tương ứng với các chân PD2. Giới thiệu Ngắt ngoài là loại ngắt duy nhất độc lập với các thiết bị của vi điều khiển. Đối với Atmega16.

khi vừa nhấn 1 nút. trạng thái chuyển từ thấp sang cao. gọi là cạnh lên – Rising Edge. trạng thái (logic) các chân INT là cao do điện trở kéo lên.Falling Edge. chúng ta gọi là cạnh xuống . Dưới đây là cấu trúc thanh ghi MCUCR được trích ra từ datasheet của chip Atmega16 .các nút nhấn dùng tạo ra các ngắt.Trong những trường hợp cụ thể. 1 trong 4 khả năng trên đều hữu ích. Thanh ghi MCUCR chứa các bits cho phép chúng ta chọn 1 trong 4 khả trên để kích hoạt ngắt ngoài INT0 và INT1. Nếu không nhấn. sẽ có sự chuyển trạng thái từ cao sang thấp. khi nút được nhấn và giữ. Có 4 khả năng có thể xảy ra khi chúng ta nhấn và thả các nút nhấn. trạng thái các chân INT được xác định là thấp và cuối cùng khi thả các nút. ví dụ trong các ứng dụng đếm xung (đếm encoder của servo motor chẳng hạn) thì 2 khả năng “cạnh” phải được dùng.

cờ ngắt INTF2 phải được xóa trong thanh ghi GIFR trước khi kích hoạt lại ngắt INT2 . cuối cùng.Xung cấp cho INT2 phải có độ rộng lớn hơn50ns thì mới xuất hiện ngắt. để tránh sai sót. Khi thay đổi bit ISC2. một ngắt có thể xảy ra. nếu nhỏ hơn thì không đảm bảo có ngắt xảy ra. vì vậy trước khi thay đổi bit này. ta cần vô hiệu hóa chức năng ngắt ngoài INT2 trong thanh ghi GICR sau đó mới thay đổi bit ISC2.

Chú ý: Các chân ngắt PD2. Tóm tắt quá trình thiết lập ngắt ngoài. PD3. +Bước 3: Cho phép ngắt toàn cục thông qua bit 7 của thanh ghi SREG. +Bước 1: Chọn chế độ ngắt thông qua thanh ghi MCUCR và MCUCSR Bước 2: Khởi động ngắt ngoài thông qua thanh ghi GICR. Thực hành ngắt ngoài Ví dụ : Viết chương trình sử dụng ngắt điều khiển 1 led 7 đoạn bằng . PB2 khi sử dụng là các chân ngắt ngoài thì phải thiết lập các chân này là ngõ vào thông qua thanh ghi DDRx.

Tác động vào các chân INT bằng nút nhấn. Khi tác động vào chân INT0 thì giá trị hiển thị tăng 1. tác động vào chân INT2 thì giá trị hiển thị bằng 0. tác động bằng cạnh xuống. Sơ đồ thí nghiệm như sau .phương pháp chốt. tác động vào chân INT1 thì giá trị hiển thị giảm 1.