You are on page 1of 48

LAB 4-1

LẬP TRÌNH SỬ DỤNG NGẮT

MỤC TIÊU:

 Hiểu và sử dụng được ngắt ngoài, ngắt timer, UART


 Quét LED 7 đoạn và LED ma trận sử dụng ngắt timer

THAM KHẢO:

 Tài liệu hướng dẫn thí nghiệm, chương 3, 4, 5, 7


 Atmel-2505-Setup-and-Use-of-AVR-Timers_ApplicationNote_AVR130.pdf

BÀI 1

a) Lập trình tạo một xung tần số 1 Khz trên chân PC0 sử dụng ngắt timer 1 overflow. Khi
timer 1 tràn, trong chương trình phục vụ ngắt đảo chân PC0 và đặt lại giá trị cho thanh
ghi đếm

.EQU P_OUT=0
.EQU TF= -62
.ORG 0
RJMP MAIN
.ORG 0x001E ;điểm vào ISR TIMER1_OVF

RJMP TIMER1_OVF_ISR ;chuyển đến ISR thực sự


.ORG 0x0040

MAIN:
LDI R16, HIGH(RAMEND) ;dời stack
OUT SPH, R16
LDI R16, LOW(RAMEND)
OUT SPL, R16
LDI R16, (1<<P_OUT) ;đặt PC0 output
OUT DDRC, R16
LDI R17, HIGH(TF) ;ghi byte cao trước
STS TCNT1H, R17 ;nạp TCNT1H
LDI R17,LOW(TF) ;nạp byte thấp TF
STS TCNT1L, R17 ;byte thấp TF cất vào TCNT1L
;chuyển TEMP vào TCNT1H
SEI ;cho phép ngắt toàn cục
LDI R17, (1<<TOIE1) ;cho phép ngắt Timer1 tràn
STS TIMSK1, R17

https://doe.dee.hcmut.edu.vn/
LAB 4-1
LẬP TRÌNH SỬ DỤNG NGẮT

LDI R17, 0x00 ;Timer1 mode NOR


STS TCCR1A, R17

LDI R17, 0x03 ;NOR, chia N=64, chạy Timer1


STS TCCR1B, R17
LDI R17,0X00

START:
RJMP START ;lặp vòng tại chỗ
;------------------------------------------
TIMER1_OVF_ISR:
LDI R17, 0x00 ;dừng Timer0
STS TCCR1B, R17
LDI R17, HIGH(TF) ;ghi byte cao trước
STS TCNT1H, R17 ;nạp TCNT1H
LDI R17,LOW(TF) ;nạp byte thấp TF
STS TCNT1L, R17 ;byte thấp TF cất vào TCNT1L

IN R17, PORTC ;đọc PortC


EOR R17, R16 ;đảo bit PC0
OUT PORTC, R17
LDI R17 , 0x03 ;Timer0 chạy, chia N=64
STS TCCR1B, R17
RETI

b) Kết nối PC0 vào oscilloscope để đo dạng sóng


(Lưu ý: tần số xung clock cho CPU trên kit thí nghiệm là 8Mhz)

https://doe.dee.hcmut.edu.vn/
LAB 4-1
LẬP TRÌNH SỬ DỤNG NGẮT

BÀI 2

a) Lặp lại bài 1 sử dụng timer 1 ở mode CTC, sử dụng ngắt COMPARE_MATCH, tạo ra 1
xung với tần số 100 Hz trên chân PC0.
b) Cấu hình timer để tạo ra ngắt COMPARE_MATCH sau mỗi 1ms, trong ngắt sử dụng 1
số đếm để đếm số lần xảy ra ngắt và điều khiển chân PC0 để tạo ra xung tần số 100 Hz.
HD: Mỗi lần xảy ra ngắt cộng số đếm lên 1, nếu số đếm bằng 5 thì đảo PC0 và reset số
đếm về 0.

.EQU P_OUT=0
.EQU TF= 125
.ORG 0
RJMP MAIN
.ORG 0x001A
;điểm vào ISR TIMER1_OVF
RJMP TIMER1 ;chuyển đến ISR thực sự
.ORG 0x0040

MAIN:
LDI R16, HIGH(RAMEND) ;dời stack
OUT SPH, R16
LDI R16, LOW(RAMEND)

https://doe.dee.hcmut.edu.vn/
LAB 4-1
LẬP TRÌNH SỬ DỤNG NGẮT

OUT SPL, R16


LDI R16, (1<<P_OUT) ;đặt PC0 output
OUT DDRC, R16
LDI R17,HIGH(TF) ;gtrị so sánh kênh A
STS OCR1AH,R17 ;ghi byte cao trước
LDI R17,LOW(TF)
STS OCR1AL,R17 ;ghi byte thấp sau
SEI ;cho phép ngắt toàn cục
LDI R17, (1<<OCIE1A) ;cho phép ngắt Ssánh kênh A
STS TIMSK1, R17
LDI R17,0x00;Timer1 mode CTC4
STS TCCR1A,R17
LDI R17,0x0B ;Timer1 chạy, N=64
STS TCCR1B,R17

LDI R17, 0 ;xóa R17 để thực hiện đảo bit


LDI R18,5

START:
RJMP START ;lặp vòng tại chỗ
;------------------------------------------
TIMER1:
DEC R18
BRNE TT

IN R17, PORTC ;đọc PortC


EOR R17, R16 ;đảo bit PC0
OUT PORTC, R17

LDI R18,5
TT: RETI

c) Biên dịch chương trình và quan sát oscilloscope để kiểm tra chương trình.

https://doe.dee.hcmut.edu.vn/
LAB 4-1
LẬP TRÌNH SỬ DỤNG NGẮT

BÀI 3

a) Kết nối các tín hiệu cần thiết để điều khiển khối LED 7 đoạn.
b) Sử dụng ngắt COMPARE_MATCH của timer 1 như ở Bài 2 để xuất số 1-2-3-4 ra 4 LED
7 đoạn với tần số quét 50 Hz. Để đo tần số quét, đảo chân PC0 mỗi lần chuyển sang LED
kết tiếp và đo xung này trên oscilloscope.

https://doe.dee.hcmut.edu.vn/
LAB 4-1
LẬP TRÌNH SỬ DỤNG NGẮT

(Tham khảo Chương 4, tài liệu hướng dẫn thí nghiệm)

.EQU LED_7SEG_PORT = PORTD


.EQU LED_7SEG_DIR = DDRD
.EQU LED_7_SEG_LATCH_PORT = PORTB
.EQU LED_7_SEG_LATCH_DIR = DDRB
.EQU nLED0PIN = 4
.EQU nLED1PIN = 5
.DEF LED_7SEG_POSITON = R20
.DEF LED_7SEG_DIGIT = R21

.ORG 0
RJMP MAIN
.ORG 0x001A
RJMP TIMER1_COMPA_ISR
MAIN:
; INIT LED_7_SEG
LDI R16, 0xFF
OUT LED_7SEG_DIR, R16
LDI R16, (1 << nLED0PIN) | (1 << nLED1PIN)
OUT LED_7_SEG_LATCH_DIR, R16
;INIT TIMER1 INTERRUPT
SBI DDRC, 0 // PC0 PIN IS OUTPUT
LDI R16, 0
STS TCNT1H, R16
STS TCNT1L, R16
LDI R16, HIGH(124)
STS OCR1AH, R16
LDI R16, LOW(124)
STS OCR1AL, R16
LDI R16, (1 << OCIE1A) // COMPARE A MATCH INTERRUPT ENABLE
STS TIMSK1, R16
SEI // ALL INTERRUPT ENABLE
;INIT TIMER1 MODE
CLR R16
STS TCCR1A, R16
LDI R16, (1 << WGM12) | (1 << CS11) | (1 << CS10)
// CONFIG CTC4 MODE AND PRESCALER IS 64
STS TCCR1B, R16
LDI LED_7SEG_DIGIT, 1
CLR LED_7SEG_POSITON
HERE:
RJMP HERE
TIMER1_COMPA_ISR:
PUSH R16
IN R16, PORTC
LDI R17, 0x01
EOR R16, R17
OUT PORTC, R16

https://doe.dee.hcmut.edu.vn/
LAB 4-1
LẬP TRÌNH SỬ DỤNG NGẮT

RCALL DISPLAY_7SEG
INC LED_7SEG_DIGIT
INC LED_7SEG_POSITON
CPI LED_7SEG_POSITON, 4
BRNE EXIT_ISR
CLR LED_7SEG_POSITON
LDI LED_7SEG_DIGIT, 1
EXIT_ISR:
POP R16
RETI

DISPLAY_7SEG:
SER R16
OUT LED_7SEG_PORT, R16
SBI LED_7_SEG_LATCH_PORT, nLED1PIN
NOP
CBI LED_7_SEG_LATCH_PORT, nLED1PIN

LDI ZH, HIGH(TABLE_7SEG_DATA << 1)


LDI ZL, LOW(TABLE_7SEG_DATA << 1)
CLR R16
ADD ZL, LED_7SEG_DIGIT
ADC ZH, R16
LPM R16, Z
OUT LED_7SEG_PORT, R16
SBI LED_7_SEG_LATCH_PORT, nLED0PIN
NOP
CBI LED_7_SEG_LATCH_PORT, nLED0PIN

LDI ZH, HIGH(TABLE_7SEG_CONTROL << 1)


LDI ZL, LOW(TABLE_7SEG_CONTROL << 1)
CLR R16
ADD ZL, LED_7SEG_POSITON
ADC ZH, R16
LPM R16, Z
OUT LED_7SEG_PORT, R16
SBI LED_7_SEG_LATCH_PORT, nLED1PIN
NOP
CBI LED_7_SEG_LATCH_PORT, nLED1PIN

RET

TABLE_7SEG_DATA:
.DB
0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0X88,0X83,0XC6,0XA1,0X86,0X8E
TABLE_7SEG_CONTROL:
.DB 0b00000111, 0b00001011, 0b00001101, 0b00001110

https://doe.dee.hcmut.edu.vn/
LAB 4-1
LẬP TRÌNH SỬ DỤNG NGẮT

BÀI 4

a) Kết nối thêm các tín hiệu cần thiết để điều khiển LCD ký tự
b) Kết nối tín hiệu UART ra khối RS232 và kết nối dây USB-Serial.
c) Viết chương trình nhận ký tự từ UART sử dụng ngắt, xuất ký tự đó ra LCD ở vị trí đầu
tiên bên trái, đồng thời đếm số ký tự nhận được và xuất ra 4 LED 7 đoạn. Khi nhận được
hơn 1000 ký tự thì reset về 0.
Hướng dẫn:
Sử dụng ngắt UART để nhận ký tự. Trong ngắt UART tăng biến đếm (16 bit), chuyển số
này thành số BCD và ghi vào 4 byte LED7segValue. Ví dụ số đếm đang là 500, ta ghi 0-
5-0-0 vào 4 byte này.
Phần quét LED giữ nguyên như ở bài 3.
Tham khảo chương 4, phần 4.4, tài liệu hướng dẫn thí nghiệm.

https://doe.dee.hcmut.edu.vn/
LAB 4-1
LẬP TRÌNH SỬ DỤNG NGẮT

.include "m324padef.inc" ; Include Atmega324pa definitions


.org 0x0000 ; interrupt vector table
rjmp reset_handler ; reset
.org 0x001A
rjmp timer1_COMP_ISR
.org 0x0028
rjmp usart_RX_ISR
reset_handler:
; initialize stack pointer
ldi r16, high(RAMEND)
out SPH, r16
ldi r16, low(RAMEND)
out SPL, r16
ldi r16, (1<<PCIE0)
sts PCICR, r16
call initTimer1CTC
call led7seg_portinit
call Led7seg_buffer_init
call LCD_Init
call USART_Init
; enable global interrupts
sei
.def counter = r24
main:
call USART_ReceiveChar
rjmp main

;Calculate and disp to 7seg


calculate:
push r17
push r20
push r16
push r31
push r30
;ldi r20,3 ;LED index start at 3
;ldi r31,high(LED7segIndex)
;ldi r30,low(LED7segIndex)
;st z,r20
ldi r31,high(LED7segValue)
ldi r30,low(LED7segValue)
mov r16, counter // get data

ldi r20,0
push r20
;st z+,r20 ;Chu so hang nghin
check100:
cpi r16,100
brlo exit100
inc r20
subi r16,100

https://doe.dee.hcmut.edu.vn/
LAB 4-1
LẬP TRÌNH SỬ DỤNG NGẮT

rjmp check100
exit100:
cpi r20,10 // so sanh voi 10 de kiem tra > 1000
brne not_reset_counter
ldi r20,0
ldi r16,0
not_reset_counter:
push r20
;st z+,r20 ;Chu so hang tram
ldi r20,0
check10:
cpi r16,10
brlo exit10
inc r20
subi r16,10
rjmp check10
exit10:
push r20
;st z+,r20 ;Chu so hang chuc
st z+,r16 ;Chu so hang don vi
pop r20
st z+,r20 ;Chu so hang chuc
pop r20
st z+,r20 ;Chu so hang tram
pop r20
st z+,r20 ;Chu so hang nghin
pop r30
pop r31
pop r16
pop r20
pop r17
ret

; Lookup table for 7-segment codes


table_7seg_data:
.DB 0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0X88,0X83
.DB 0XC6,0XA1,0X86,0X8E
; Lookup table for LED control
table_7seg_control:
.DB 0b00001110,0b00001101, 0b00001011, 0b00000111
.equ LED7SEGPORT = PORTB
.equ LED7SEGDIR = DDRB
.equ LED7SEGLatchPORT = PORTD
.equ LED7SEGLatchDIR = DDRD
.equ nLE0Pin = 4
.equ nLE1Pin = 5
.dseg
.org SRAM_START ;starting address is 0x100
LED7segValue: .byte 4 ;store the BCD value to display
LED7segIndex: .byte 1

https://doe.dee.hcmut.edu.vn/
LAB 4-1
LẬP TRÌNH SỬ DỤNG NGẮT

.cseg
.align 2
;init the Led7seg buffer
Led7seg_buffer_init:
push r20
ldi r20,3 ;LED index start at 3
ldi r31,high(LED7segIndex)
ldi r30,low(LED7segIndex)
st z,r20
ldi r20,0
ldi r31,high(LED7segValue)
ldi r30,low(LED7segValue)
st z+,r20 ;display value is 0000
st z+,r20
st z+,r20
st z+,r20
pop r20
ret
;uart
;init UART 0
;CPU clock is 8Mhz
USART_Init:
; Set baud rate to 9600 bps with 8 MHz clock/ (8Mghz*2^1)/(16*9600) -1 = 103.167
ldi r16, 103
sts UBRR0L, r16
;set double speed
ldi r16, (1 << U2X0)
sts UCSR0A, r16
; Set frame format: 8 data bits, no parity, 1 stop bit
ldi r16, (1 << UCSZ01) | (1 << UCSZ00)
sts UCSR0C, r16
; Enable transmitter and receiver
ldi r16, (1 << RXEN0) | (1 << TXEN0) | (1<< RXCIE0)
sts UCSR0B, r16
ret
;send out 1 byte in r16
USART_SendChar:
push r17
; Wait for the transmitter to be ready
USART_SendChar_Wait:
lds r17, UCSR0A
sbrs r17, UDRE0 ;check USART Data Register Empty bit
rjmp USART_SendChar_Wait
sts UDR0, r16 ;send out
pop r17
ret
;receive 1 byte in r16
USART_ReceiveChar:
push r17
; Wait for the transmitter to be ready

https://doe.dee.hcmut.edu.vn/
LAB 4-1
LẬP TRÌNH SỬ DỤNG NGẮT

USART_ReceiveChar_Wait:
lds r17, UCSR0A
sbrs r17, RXC0 ;check USART Receive Complete bit
rjmp USART_ReceiveChar_Wait
lds r16, UDR0 ;get data
pop r17
ret

led7seg_portinit:
push r20
ldi r20, 0b11111111 ; SET led7seg PORT as output
out LED7SEGDIR, r20
in r20, LED7SEGLatchDIR ; read the Latch Port direction register
ori r20, (1<<nLE0Pin) | (1 << nLE1Pin)
out LED7SEGLatchDIR,r20
pop r20
ret;
;Display a value on a 7-segment LED using a lookup table
; Input: R27 contains the value to display
; R26 contain the LED index (3..0)
; J34 connect to PORTD
; nLE0 connect to PB4
; nLE1 connect to PB5
; Output: None
display_7seg:
push r16 ; Save the temporary register
; Look up the 7-segment code for the value in R18
; Note that this assumes a common anode display, where a HIGH output turns OFF the
segment
; If using a common cathode display, invert the values in the table above
ldi zh,high(table_7seg_data<<1) ;
ldi zl,low(table_7seg_data<<1) ;
clr r16
add r30, r27
adc r31,r16
lpm r16, z
out LED7SEGPORT,r16
sbi LED7SEGLatchPORT,nLE0Pin
nop
cbi LED7SEGLatchPORT,nLE0Pin
ldi zh,high(table_7seg_control<<1)
ldi zl,low(table_7seg_control<<1) ;
clr r16
add r30, r26
adc r31,r16
lpm r16, z
out LED7SEGPORT,r16
sbi LED7SEGLatchPORT,nLE1Pin
nop
cbi LED7SEGLatchPORT,nLE1Pin

https://doe.dee.hcmut.edu.vn/
LAB 4-1
LẬP TRÌNH SỬ DỤNG NGẮT

pop r16 ; Restore the temporary register


ret ; Return from the function
initTimer1CTC:
push r16
ldi r16, high(40000) ; Load the high yte into the temporary register 40000
sts OCR1AH, r16 ; Set the high byte of the timer 1 compare value
ldi r16, low(40000) ; Load the low byte into the temporary register
sts OCR1AL, r16 ; Set the low byte of the timer 1 compare value
ldi r16, (1 << CS10)| (1<< WGM12) ; Load the value 0b00000101 into the temporary register
sts TCCR1B, r16 ;
ldi r16, (1 << OCIE1A); Load the value 0b00000010 into the temporary register
sts TIMSK1, r16 ; Enable the timer 1 compare A interrupt
pop r16
ret

timer1_COMP_ISR:
push r16
push r26
push r27
ldi r31,high(LED7segIndex)
ldi r30,low(LED7segIndex)
ld r16,z
mov r26,r16
ldi r31,high(LED7segValue)
ldi r30,low(LED7segValue)
add r30,r16
clr r16
adc r31,r16
ld r27,z
call display_7seg
cpi r26,0
brne timer1_COMP_ISR_CONT
ldi r26,4 ;if r16 = 0, reset to 3
timer1_COMP_ISR_CONT:
dec r26 ;else, decrease
ldi r31,high(LED7segIndex)
ldi r30,low(LED7segIndex)
st z,r26
pop r27
pop r26
pop r16
reti

usart_RX_ISR:
ldi r16,0
ldi r17,0
call LCD_Move_Cursor
lds r16,UDR0
call USART_SendChar
call LCD_Send_Data ; display the character

https://doe.dee.hcmut.edu.vn/
LAB 4-1
LẬP TRÌNH SỬ DỤNG NGẮT

inc counter
call calculate
reti

;init the LCD


;LCD_D7..LCD_D4 connect to PA7..PA4
;LCD_RS connect to PA0
;LCD_RW connect to PA1
;LCD_EN connect to PA2
.equ LCDPORT = PORTA ; Set signal port reg to PORTA
.equ LCDPORTDIR = DDRA ; Set signal port dir reg to PORTA
.equ LCDPORTPIN = PINA ; Set clear signal port pin reg to PORTA
.equ LCD_RS = PINA0
.equ LCD_RW = PINA1
.equ LCD_EN = PINA2
.equ LCD_D7 = PINA7
.equ LCD_D6 = PINA6
.equ LCD_D5 = PINA5
.equ LCD_D4 = PINA4
LCD_Init:
; Set up data direction register for Port A
ldi r16, 0b11110111 ; set PA7-PA4 as outputs, PA2-PA0 as output
out LCDPORTDIR, r16
; Wait for LCD to power up
call DELAY_10MS
call DELAY_10MS
; Send initialization sequence
ldi r16, 0x02 ; Function Set: 4-bit interface
call LCD_Send_Command
ldi r16, 0x28 ; Function Set: enable 5x7 mode for chars
call LCD_Send_Command
ldi r16, 0x0E ; Display Control: Display OFF, Cursor ON
call LCD_Send_Command
ldi r16, 0x01 ; Clear Display
call LCD_Send_Command
ldi r16, 0x80 ; Clear Display
call LCD_Send_Command
ret
; Function to move the cursor to a specific position on the LCD
; Assumes that the LCD is already initialized
; Input: Row number in R16 (0-based), Column number in R17 (0-based)
LCD_Move_Cursor:
cpi r16,0 ;check if first row
brne LCD_Move_Cursor_Second
andi r17, 0x0F
ori r17,0x80
mov r16,r17
; Send command to LCD
call LCD_Send_Command
ret

https://doe.dee.hcmut.edu.vn/
LAB 4-1
LẬP TRÌNH SỬ DỤNG NGẮT

LCD_Move_Cursor_Second:
cpi r16,1 ;check if second row
brne LCD_Move_Cursor_Exit ;else exit
andi r17, 0x0F
ori r17,0xC0
mov r16,r17
; Send command to LCD
call LCD_Send_Command
LCD_Move_Cursor_Exit:
; Return from function
ret
; Subroutine to send string to LCD
;address of the string on ZH-ZL
;string end with Null
.def LCDData = r16
LCD_Send_String:
push ZH ; preserve pointer registers
push ZL
push LCDData
; fix up the pointers for use with the 'lpm' instruction
lsl ZL ; shift the pointer one bit left for the lpm instruction
rol ZH
; write the string of characters
LCD_Send_String_01:
lpm LCDData, Z+ ; get a character
cpi LCDData, 0 ; check for end of string
breq LCD_Send_String_02 ; done
; arrive here if this is a valid character
call LCD_Send_Data ; display the character
rjmp LCD_Send_String_01 ; not done, send another character
; arrive here when all characters in the message have been sent to the LCD module
LCD_Send_String_02:
pop LCDData
pop ZL ; restore pointer registers
pop ZH
ret
; Subroutine to send command to LCD
;Command code in r16
;LCD_D7..LCD_D4 connect to PA7..PA4
;LCD_RS connect to PA0
;LCD_RW connect to PA1
;LCD_EN connect to PA2
LCD_Send_Command:
push r17
call LCD_wait_busy ; check if LCD is busy
mov r17,r16 ;save the command
; Set RS low to select command register
; Set RW low to write to LCD
andi r17,0xF0
; Send command to LCD

https://doe.dee.hcmut.edu.vn/
LAB 4-1
LẬP TRÌNH SỬ DỤNG NGẮT

out LCDPORT, r17


nop
nop
; Pulse enable pin
sbi LCDPORT, LCD_EN
nop
nop
cbi LCDPORT, LCD_EN
swap r16
andi r16,0xF0
; Send command to LCD
out LCDPORT, r16
; Pulse enable pin
sbi LCDPORT, LCD_EN
nop
nop
cbi LCDPORT, LCD_EN
pop r17
ret
LCD_Send_Data:
push r17
call LCD_wait_busy ;check if LCD is busy
mov r17,r16 ;save the command
; Set RS high to select data register
; Set RW low to write to LCD
andi r17,0xF0
ori r17,0x01
; Send data to LCD
out LCDPORT, r17
nop
; Pulse enable pin
sbi LCDPORT, LCD_EN
nop
cbi LCDPORT, LCD_EN
; Delay for command execution
;send the lower nibble
nop
swap r16
andi r16,0xF0
; Set RS high to select data register
; Set RW low to write to LCD
andi r16,0xF0
ori r16,0x01
; Send command to LCD
out LCDPORT, r16
nop
; Pulse enable pin
sbi LCDPORT, LCD_EN
nop
cbi LCDPORT, LCD_EN

https://doe.dee.hcmut.edu.vn/
LAB 4-1
LẬP TRÌNH SỬ DỤNG NGẮT

pop r17
ret
LCD_wait_busy:
push r16
ldi r16, 0b00000111 ; set PA7-PA4 as input, PA2-PA0 as output
out LCDPORTDIR, r16
ldi r16,0b11110010 ; set RS=0, RW=1 for read the busy flag
out LCDPORT, r16
nop
LCD_wait_busy_loop:
sbi LCDPORT, LCD_EN
nop
nop
in r16, LCDPORTPIN
cbi LCDPORT, LCD_EN
nop
sbi LCDPORT, LCD_EN
nop
nop
cbi LCDPORT, LCD_EN
nop
andi r16,0x80
cpi r16,0x80
breq LCD_wait_busy_loop
ldi r16, 0b11110111 ; set PA7-PA4 as output, PA2-PA0 as output
out LCDPORTDIR, r16
ldi r16,0b00000000 ; set RS=0, RW=1 for read the busy flag
out LCDPORT, r16
pop r16
ret
DELAY_10MS: ;
push r16
push r17
ldi r16,106 ;1MC
l1: ldi r17,250 ;1MC
l2: dec r17 ;1MC
brne l2 ;2/1MC
dec r16 ;1MC
brne l1 ;2/1MC
pop r17
pop r16
ret ;4MC

https://doe.dee.hcmut.edu.vn/
LAB 4-1
LẬP TRÌNH SỬ DỤNG NGẮT

BÀI 5

a) Kết nối thêm các tín hiệu I2C vào module RTC. Đưa tín hiệu MFP của RTC vào 1 chân
ngắt ngoài. Thêm vào bài 4 các chức năng sau:
b) Khởi động RTC với thời gian hiện hành, xuất tín hiệu MFP tần số 1 Hz.
c) Sử dụng ngắt ngoài của AVR, cứ mỗi khi có ngắt thì đọc thời gian giờ:phút:giây từ RTC
và xuất ra dòng 2 của LCD
Lưu ý: Các chức năng ở bài 4 vẫn được giữ nguyên.

.include "m324padef.inc" ; Include Atmega324pa definitions


.org 0x0000 ; interrupt vector table
rjmp reset_handler ; reset

https://doe.dee.hcmut.edu.vn/
LAB 4-1
LẬP TRÌNH SỬ DỤNG NGẮT

.org 0x0002
rjmp int0_isr
.org 0x001A
rjmp timer1_COMP_ISR
.org 0x0028
rjmp usart_RX_ISR
reset_handler:
; initialize stack pointer
ldi r16, high(RAMEND)
out SPH, r16
ldi r16, low(RAMEND)
out SPL, r16
ldi r16, (1<<PCIE0)
sts PCICR, r16
call initTimer1CTC
call led7seg_portinit
call Led7seg_buffer_init
call LCD_Init
call USART_Init
call int0_init
call i2c_init
; enable global interrupts
sei
.def counter = r24
.def data = r23
.def ASCII = r19
.equ two_dot = 58
.equ splash = 47
.equ idbyte = 0b11011110
ldi ASCII,48 ;ACSCII
dong2:
.db "Time:",0

; display the first line of information


ldi r16,1
ldi r17,0
call LCD_Move_Cursor
ldi ZH, high(dong2) ; point to the information that is to be displayed
ldi ZL, low(dong2)
call LCD_Send_String
// setup
call i2c_start
ldi data, idbyte // lenh ghi
call i2c_send
ldi data,0x07 // dia chi o nho control rtc
call i2c_send
ldi data,0b01000000 //MFP xuat xung 1Hz
call i2c_send
call i2c_stop
call DELAY_10MS

https://doe.dee.hcmut.edu.vn/
LAB 4-1
LẬP TRÌNH SỬ DỤNG NGẮT

main:
call USART_ReceiveChar
rjmp main

// int0 init
int0_init:
ldi r16,(1<<INT0)
out eimsk, r16
ldi r16,(1<<ISC01)|(1<<ISC00)
sts eicra,r16
cbi ddrd,2
sbi portd,2
ret

// TWI init
int0_isr:
ldi r16,1
ldi r17,5
call LCD_Move_Cursor
// gio
call get_hour
add r16,ASCII
call LCD_Send_Data
mov r16,data
add r16,ASCII
call LCD_Send_Data
//
ldi r16,two_dot
call LCD_Send_Data
//phut
call get_minute
add r16,ASCII
call LCD_Send_Data
mov r16,data
add r16,ASCII
call LCD_Send_Data
//
ldi r16,two_dot
call LCD_Send_Data
//giay
call get_second
add r16,ASCII
call LCD_Send_Data
mov r16,data
add r16,ASCII
call LCD_Send_Data

reti

https://doe.dee.hcmut.edu.vn/
LAB 4-1
LẬP TRÌNH SỬ DỤNG NGẮT

get_second:
call i2c_start
ldi data, idbyte
call i2c_send
ldi data, 0x00
call i2c_send
call i2c_start
ldi data, (idbyte|0x01)
call i2c_send
ldi data,0x00
call i2c_send
lds data,twdr
call i2c_stop
mov r16,data
andi data,0x0f
swap r16
andi r16,0x07
ret
get_minute:
call i2c_start
ldi data, idbyte
call i2c_send
ldi data, 0x01
call i2c_send
call i2c_start
ldi data,(idbyte|0x01)
call i2c_send
ldi data,0x00
call i2c_send
lds data,twdr
call i2c_stop
mov r16,data
andi data,0x0f
swap r16
andi r16,0x07
ret
get_hour:
call i2c_start
ldi data, idbyte
call i2c_send
ldi data, 0x02
call i2c_send
call i2c_start
ldi data,(idbyte|0x01)
call i2c_send
ldi data,0x00
call i2c_send
lds data,twdr
call i2c_stop
mov r16,data

https://doe.dee.hcmut.edu.vn/
LAB 4-1
LẬP TRÌNH SỬ DỤNG NGẮT

andi data,0x0f
swap r16
andi r16,0x03
ret
get_day:
call i2c_start
ldi data, idbyte
call i2c_send
ldi data, 0x04
call i2c_send
call i2c_start
ldi data,(idbyte|0x01)
call i2c_send
ldi data,0x00
call i2c_send
lds data,twdr
call i2c_stop
mov r16,data
andi data,0x0f
swap r16
andi r16,0x03
ret
get_month:
call i2c_start
ldi data, idbyte
call i2c_send
ldi data, 0x05
call i2c_send
call i2c_start
ldi data,(idbyte|0x01)
call i2c_send
ldi data,0x00
call i2c_send
lds data,twdr
call i2c_stop
mov r16,data
andi data,0x0f
swap r16
andi r16,0x01
ret
get_year:
call i2c_start
ldi data, idbyte
call i2c_send
ldi data, 0x06
call i2c_send
call i2c_start
ldi data,(idbyte|0x01)
call i2c_send
ldi data,0x00

https://doe.dee.hcmut.edu.vn/
LAB 4-1
LẬP TRÌNH SỬ DỤNG NGẮT

call i2c_send
lds data,twdr
call i2c_stop
mov r16,data
andi data,0x0f
swap r16
andi r16,0x0f
ret
i2c_init:
ldi r16,0
sts twsr,r16
ldi r16,2 ; 400kHz = 8MHz/(16+2*X*4^twps), X=2
sts twbr,r16
ldi r16,(1<<twen)
sts twcr,r16
ret
i2c_send:
push r16
sts twdr,data
ldi r16,(1<<twint)|(1<<twen)
sts twcr,r16
wait_send:
lds r16,twcr
sbrs r16,twint
rjmp wait_send
pop r16
ret
i2c_start:
push r16
ldi r16,(1<<twint)|(1<<twen)|(1<<twsta)
sts twcr,r16
wait_start:
lds r16,twcr
sbrs r16,twint
rjmp wait_start
pop r16
ret
i2c_stop:
push r16
ldi r16,(1<<twint)|(1<<twen)|(1<<twsto)
sts twcr,r16
pop r16
ret

;Calculate and disp to 7seg


calculate:
push r17
push r20
push r16
push r31

https://doe.dee.hcmut.edu.vn/
LAB 4-1
LẬP TRÌNH SỬ DỤNG NGẮT

push r30
;ldi r20,3 ;LED index start at 3
;ldi r31,high(LED7segIndex)
;ldi r30,low(LED7segIndex)
;st z,r20
ldi r31,high(LED7segValue)
ldi r30,low(LED7segValue)
mov r16, counter // get data

ldi r20,0
push r20
;st z+,r20 ;Chu so hang nghin
check100:
cpi r16,100
brlo exit100
inc r20
subi r16,100
rjmp check100
exit100:
cpi r20,10 // so sanh voi 10 de kiem tra > 1000
brne not_reset_counter
ldi r20,0
ldi r16,0
not_reset_counter:
push r20
;st z+,r20 ;Chu so hang tram
ldi r20,0
check10:
cpi r16,10
brlo exit10
inc r20
subi r16,10
rjmp check10
exit10:
push r20
;st z+,r20 ;Chu so hang chuc
st z+,r16 ;Chu so hang don vi
pop r20
st z+,r20 ;Chu so hang chuc
pop r20
st z+,r20 ;Chu so hang tram
pop r20
st z+,r20 ;Chu so hang nghin
pop r30
pop r31
pop r16
pop r20
pop r17
ret

https://doe.dee.hcmut.edu.vn/
LAB 4-1
LẬP TRÌNH SỬ DỤNG NGẮT

; Lookup table for 7-segment codes


table_7seg_data:
.DB 0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0X88,0X83
.DB 0XC6,0XA1,0X86,0X8E
; Lookup table for LED control
table_7seg_control:
.DB 0b00001110,0b00001101, 0b00001011, 0b00000111
;.DB 0b00000001,0b00000010, 0b00000100, 0b00001000
; J34 connect to PORTD
; nLE0 connect to PB4
; nLE1 connect to PB5
; Output: None
.equ LED7SEGPORT = PORTB
.equ LED7SEGDIR = DDRB
.equ LED7SEGLatchPORT = PORTD
.equ LED7SEGLatchDIR = DDRD
.equ nLE0Pin = 4
.equ nLE1Pin = 5
.dseg
.org SRAM_START ;starting address is 0x100
LED7segValue: .byte 4 ;store the BCD value to display
LED7segIndex: .byte 1
.cseg
.align 2
;init the Led7seg buffer
Led7seg_buffer_init:
push r20
ldi r20,3 ;LED index start at 3
ldi r31,high(LED7segIndex)
ldi r30,low(LED7segIndex)
st z,r20
ldi r20,0
ldi r31,high(LED7segValue)
ldi r30,low(LED7segValue)
st z+,r20 ;display value is 0000
st z+,r20
st z+,r20
st z+,r20
pop r20
ret
;uart
;init UART 0
;CPU clock is 8Mhz
USART_Init:
; Set baud rate to 9600 bps with 8 MHz clock/ (8Mghz*2^1)/(16*9600) -1 = 103.167
ldi r16, 103
sts UBRR0L, r16
;set double speed
ldi r16, (1 << U2X0)
sts UCSR0A, r16

https://doe.dee.hcmut.edu.vn/
LAB 4-1
LẬP TRÌNH SỬ DỤNG NGẮT

; Set frame format: 8 data bits, no parity, 1 stop bit


ldi r16, (1 << UCSZ01) | (1 << UCSZ00)
sts UCSR0C, r16
; Enable transmitter and receiver
ldi r16, (1 << RXEN0) | (1 << TXEN0) | (1<< RXCIE0)
sts UCSR0B, r16
ret
;send out 1 byte in r16
USART_SendChar:
push r17
; Wait for the transmitter to be ready
USART_SendChar_Wait:
lds r17, UCSR0A
sbrs r17, UDRE0 ;check USART Data Register Empty bit
rjmp USART_SendChar_Wait
sts UDR0, r16 ;send out
pop r17
ret
;receive 1 byte in r16
USART_ReceiveChar:
push r17
; Wait for the transmitter to be ready
USART_ReceiveChar_Wait:
lds r17, UCSR0A
sbrs r17, RXC0 ;check USART Receive Complete bit
rjmp USART_ReceiveChar_Wait
lds r16, UDR0 ;get data
pop r17
ret

led7seg_portinit:
push r20
ldi r20, 0b11111111 ; SET led7seg PORT as output
out LED7SEGDIR, r20
in r20, LED7SEGLatchDIR ; read the Latch Port direction register
ori r20, (1<<nLE0Pin) | (1 << nLE1Pin)
out LED7SEGLatchDIR,r20
pop r20
ret;
;Display a value on a 7-segment LED using a lookup table
; Input: R27 contains the value to display
; R26 contain the LED index (3..0)
; J34 connect to PORTD
; nLE0 connect to PB4
; nLE1 connect to PB5
; Output: None
display_7seg:
push r16 ; Save the temporary register
; Look up the 7-segment code for the value in R18

https://doe.dee.hcmut.edu.vn/
LAB 4-1
LẬP TRÌNH SỬ DỤNG NGẮT

; Note that this assumes a common anode display, where a HIGH output turns OFF the
segment
; If using a common cathode display, invert the values in the table above
ldi zh,high(table_7seg_data<<1) ;
ldi zl,low(table_7seg_data<<1) ;
clr r16
add r30, r27
adc r31,r16
lpm r16, z
out LED7SEGPORT,r16
sbi LED7SEGLatchPORT,nLE0Pin
nop
cbi LED7SEGLatchPORT,nLE0Pin
ldi zh,high(table_7seg_control<<1)
ldi zl,low(table_7seg_control<<1) ;
clr r16
add r30, r26
adc r31,r16
lpm r16, z
out LED7SEGPORT,r16
sbi LED7SEGLatchPORT,nLE1Pin
nop
cbi LED7SEGLatchPORT,nLE1Pin
pop r16 ; Restore the temporary register
ret ; Return from the function
initTimer1CTC:
push r16
ldi r16, high(40000) ; Load the high yte into the temporary register 40000
sts OCR1AH, r16 ; Set the high byte of the timer 1 compare value
ldi r16, low(40000) ; Load the low byte into the temporary register
sts OCR1AL, r16 ; Set the low byte of the timer 1 compare value
ldi r16, (1 << CS10)| (1<< WGM12) ; Load the value 0b00000101 into the temporary register
sts TCCR1B, r16 ;
ldi r16, (1 << OCIE1A); Load the value 0b00000010 into the temporary register
sts TIMSK1, r16 ; Enable the timer 1 compare A interrupt
pop r16
ret

timer1_COMP_ISR:
push r16
push r26
push r27
ldi r31,high(LED7segIndex)
ldi r30,low(LED7segIndex)
ld r16,z
mov r26,r16
ldi r31,high(LED7segValue)
ldi r30,low(LED7segValue)
add r30,r16
clr r16

https://doe.dee.hcmut.edu.vn/
LAB 4-1
LẬP TRÌNH SỬ DỤNG NGẮT

adc r31,r16
ld r27,z
call display_7seg
cpi r26,0
brne timer1_COMP_ISR_CONT
ldi r26,4 ;if r16 = 0, reset to 3
timer1_COMP_ISR_CONT:
dec r26 ;else, decrease
ldi r31,high(LED7segIndex)
ldi r30,low(LED7segIndex)
st z,r26
pop r27
pop r26
pop r16
reti

usart_RX_ISR:
ldi r16,0
ldi r17,0
call LCD_Move_Cursor
lds r16,UDR0
call USART_SendChar
call LCD_Send_Data ; display the character
inc counter
call calculate
reti

;init the LCD


;LCD_D7..LCD_D4 connect to PA7..PA4
;LCD_RS connect to PA0
;LCD_RW connect to PA1
;LCD_EN connect to PA2
.equ LCDPORT = PORTA ; Set signal port reg to PORTA
.equ LCDPORTDIR = DDRA ; Set signal port dir reg to PORTA
.equ LCDPORTPIN = PINA ; Set clear signal port pin reg to PORTA
.equ LCD_RS = PINA0
.equ LCD_RW = PINA1
.equ LCD_EN = PINA2
.equ LCD_D7 = PINA7
.equ LCD_D6 = PINA6
.equ LCD_D5 = PINA5
.equ LCD_D4 = PINA4
LCD_Init:
; Set up data direction register for Port A
ldi r16, 0b11110111 ; set PA7-PA4 as outputs, PA2-PA0 as output
out LCDPORTDIR, r16
; Wait for LCD to power up
call DELAY_10MS
call DELAY_10MS
; Send initialization sequence

https://doe.dee.hcmut.edu.vn/
LAB 4-1
LẬP TRÌNH SỬ DỤNG NGẮT

ldi r16, 0x02 ; Function Set: 4-bit interface


call LCD_Send_Command
ldi r16, 0x28 ; Function Set: enable 5x7 mode for chars
call LCD_Send_Command
ldi r16, 0x0E ; Display Control: Display OFF, Cursor ON
call LCD_Send_Command
ldi r16, 0x01 ; Clear Display
call LCD_Send_Command
ldi r16, 0x80 ; Clear Display
call LCD_Send_Command
ret
; Function to move the cursor to a specific position on the LCD
; Assumes that the LCD is already initialized
; Input: Row number in R16 (0-based), Column number in R17 (0-based)
LCD_Move_Cursor:
cpi r16,0 ;check if first row
brne LCD_Move_Cursor_Second
andi r17, 0x0F
ori r17,0x80
mov r16,r17
; Send command to LCD
call LCD_Send_Command
ret
LCD_Move_Cursor_Second:
cpi r16,1 ;check if second row
brne LCD_Move_Cursor_Exit ;else exit
andi r17, 0x0F
ori r17,0xC0
mov r16,r17
; Send command to LCD
call LCD_Send_Command
LCD_Move_Cursor_Exit:
; Return from function
ret
; Subroutine to send string to LCD
;address of the string on ZH-ZL
;string end with Null
.def LCDData = r16
LCD_Send_String:
push ZH ; preserve pointer registers
push ZL
push LCDData
; fix up the pointers for use with the 'lpm' instruction
lsl ZL ; shift the pointer one bit left for the lpm instruction
rol ZH
; write the string of characters
LCD_Send_String_01:
lpm LCDData, Z+ ; get a character
cpi LCDData, 0 ; check for end of string
breq LCD_Send_String_02 ; done

https://doe.dee.hcmut.edu.vn/
LAB 4-1
LẬP TRÌNH SỬ DỤNG NGẮT

; arrive here if this is a valid character


call LCD_Send_Data ; display the character
rjmp LCD_Send_String_01 ; not done, send another character
; arrive here when all characters in the message have been sent to the LCD module
LCD_Send_String_02:
pop LCDData
pop ZL ; restore pointer registers
pop ZH
ret
; Subroutine to send command to LCD
;Command code in r16
;LCD_D7..LCD_D4 connect to PA7..PA4
;LCD_RS connect to PA0
;LCD_RW connect to PA1
;LCD_EN connect to PA2
LCD_Send_Command:
push r17
call LCD_wait_busy ; check if LCD is busy
mov r17,r16 ;save the command
; Set RS low to select command register
; Set RW low to write to LCD
andi r17,0xF0
; Send command to LCD
out LCDPORT, r17
nop
nop
; Pulse enable pin
sbi LCDPORT, LCD_EN
nop
nop
cbi LCDPORT, LCD_EN
swap r16
andi r16,0xF0
; Send command to LCD
out LCDPORT, r16
; Pulse enable pin
sbi LCDPORT, LCD_EN
nop
nop
cbi LCDPORT, LCD_EN
pop r17
ret
LCD_Send_Data:
push r17
call LCD_wait_busy ;check if LCD is busy
mov r17,r16 ;save the command
; Set RS high to select data register
; Set RW low to write to LCD
andi r17,0xF0
ori r17,0x01

https://doe.dee.hcmut.edu.vn/
LAB 4-1
LẬP TRÌNH SỬ DỤNG NGẮT

; Send data to LCD


out LCDPORT, r17
nop
; Pulse enable pin
sbi LCDPORT, LCD_EN
nop
cbi LCDPORT, LCD_EN
; Delay for command execution
;send the lower nibble
nop
swap r16
andi r16,0xF0
; Set RS high to select data register
; Set RW low to write to LCD
andi r16,0xF0
ori r16,0x01
; Send command to LCD
out LCDPORT, r16
nop
; Pulse enable pin
sbi LCDPORT, LCD_EN
nop
cbi LCDPORT, LCD_EN
pop r17
ret
LCD_wait_busy:
push r16
ldi r16, 0b00000111 ; set PA7-PA4 as input, PA2-PA0 as output
out LCDPORTDIR, r16
ldi r16,0b11110010 ; set RS=0, RW=1 for read the busy flag
out LCDPORT, r16
nop
LCD_wait_busy_loop:
sbi LCDPORT, LCD_EN
nop
nop
in r16, LCDPORTPIN
cbi LCDPORT, LCD_EN
nop
sbi LCDPORT, LCD_EN
nop
nop
cbi LCDPORT, LCD_EN
nop
andi r16,0x80
cpi r16,0x80
breq LCD_wait_busy_loop
ldi r16, 0b11110111 ; set PA7-PA4 as output, PA2-PA0 as output
out LCDPORTDIR, r16
ldi r16,0b00000000 ; set RS=0, RW=1 for read the busy flag

https://doe.dee.hcmut.edu.vn/
LAB 4-1
LẬP TRÌNH SỬ DỤNG NGẮT

out LCDPORT, r16


pop r16
ret
DELAY_10MS: ;
push r16
push r17
ldi r16,106 ;1MC
l1: ldi r17,250 ;1MC
l2: dec r17 ;1MC
brne l2 ;2/1MC
dec r16 ;1MC
brne l1 ;2/1MC
pop r17
pop r16
ret ;4MC

BÀI 6

a) Kết nối các tín hiệu cần thiết để điều khiển LED ma trận. (gỡ bỏ các dây nối đến LCD,
Led 7 đoạn, RTC, UART).
b) Sử dụng chương trình mẫu, chỉnh sửa nếu cần thiết để hiển thị chữ ‘A’ lên LED ma trận.
Quét LED ma trận sử dụng ngắt timer với tần số quét 25 Hz.
c) Chỉnh sửa chương trình để đạt tần số quét là 125Hz.
d) Viết chương trình để hiển thị Logo Trường ĐH Bách Khoa lên LED ma trận.

.include "m324padef.inc" ; Include Atmega324pa definitions


.org 0x0000 ; interrupt vector table
rjmp reset_handler ; reset
.org 0x001A
rjmp timer1_COMP_ISR
reset_handler:
; initialize stack pointer
ldi r16, high(RAMEND)
out SPH, r16
ldi r16, low(RAMEND)
out SPL, r16
call shiftregister_initport
call shiftregister_cleardata
call initTimer1CTC
; enable global interrupts
sei
call ledmatrix_portinit
main:
jmp main

https://doe.dee.hcmut.edu.vn/
LAB 4-1
LẬP TRÌNH SỬ DỤNG NGẮT

.equ clearSignalPort = PORTB ; Set clear signal port to PORTB


.equ clearSignalPin = 0 ; Set clear signal pin to pin 3 of PORTB
.equ shiftClockPort = PORTB ; Set shift clock port to PORTB
.equ shiftClockPin = 1 ; Set shift clock pin to pin 2 of PORTB
.equ latchPort = PORTB ; Set latch port to PORTB
.equ latchPin = 2 ; Set latch pin to pin 1 of PORTB
.equ shiftDataPort = PORTB ; Set shift data port to PORTB
.equ shiftDataPin = 3 ; Set shift data pin to pin 0 of PORTB
; Initialize ports as outputs
shiftregister_initport:
push r24
ldi
r24,(1<<clearSignalPin)|(1<<shiftClockPin)|(1<<latchPin)|(1<<shiftData
Pin);
out DDRB, r24 ; Set DDRB to output
pop r24
ret
shiftregister_cleardata:
cbi clearSignalPort, clearSignalPin ; Set clear signal pin to low
; Wait for a short time
sbi clearSignalPort, clearSignalPin ; Set clear signal pin to high
ret
; Shift out data
;shift out R27 to bar led
shiftregister_shiftoutdata:
push r18
cbi shiftClockPort, shiftClockPin ;
ldi r18, 8 ; Shift 8 bits
shiftloop:
sbrc r27, 7 ; Check if the MSB of shiftData is 1
sbi shiftDataPort, shiftDataPin ; Set shift data pin to high
sbi shiftClockPort, shiftClockPin ; Set shift clock pin to high
lsl r27 ; Shift left
cbi shiftClockPort, shiftClockPin ; Set shift clock pin to low
cbi shiftDataPort, shiftDataPin ; Set shift data pin to low
dec r18
brne shiftloop
; Latch data
sbi latchPort, latchPin ; Set latch pin to high
cbi latchPort, latchPin ; Set latch pin to low
pop r18
ret
;Lookup table for collumn control
ledmatrix_col_control: .DB 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02,
0x01
; Lookup table for font
;ledmatrix_Font_A: .DB 0b00000000, 0b00000000, 0b01000110, 0b10001001,0b10001001,
0b10001001, 0b01111110, 0b00000000 // Chữ A
ledmatrix_Font_A: .DB 0b01100000, 0b11110000, 0b11101110, 0b01000111,0b01000111,
0b11101110, 0b11110000, 0b01100000 // Logo bach khoa

https://doe.dee.hcmut.edu.vn/
LAB 4-1
LẬP TRÌNH SỬ DỤNG NGẮT

; J38 connect to PORTD


; clear signal pin to pin 0 of PORTB
; shift clock pin to pin 1 of PORTB
; latch pin to pin 0 of PORTB
; shift data pin to pin 3 of PORTB
; Output: None
.equ LEDMATRIXPORT = PORTD
.equ LEDMATRIXDIR = DDRD
.dseg
.org SRAM_START ;starting address is 0x100
LedMatrixBuffer : .byte 8
LedMatrixColIndex : .byte 1
.cseg
.align 2
ledmatrix_portinit:
push r20
push r21
ldi r20, 0b11111111 ; SET port as output
out LEDMATRIXDIR, r20
ldi r20,0 ;col index start at 0
ldi r31,high(LedMatrixColIndex)
ldi r30,low(LedMatrixColIndex)
st z,r20
ldi r20,0
ldi r31,high(ledmatrix_Font_A << 1) ;Z register point to fontA value
ldi r30,low(ledmatrix_Font_A << 1)
ldi r29,high(LedMatrixBuffer) ; Y register point to fontA value
ldi r28,low(LedMatrixBuffer)
ldi r20,8
ledmatrix_portinit_loop: ;copy font to display buffer
lpm r21,z+
st y+,r21
dec r20
cpi r20,0
brne ledmatrix_portinit_loop
pop r21
pop r20
ret
; Display a Collumn of Led Matrix
; Input: R27 contains the value to display
; R26 contain the Col index (3..0)
; Output: None
ledmatrix_display_col:
push r16 ; Save the temporary register
push r27
clr r16
out LEDMATRIXPORT,r16
call shiftregister_shiftoutdata
ldi r31,high(ledmatrix_col_control << 1)
ldi r30,low(ledmatrix_col_control << 1)

https://doe.dee.hcmut.edu.vn/
LAB 4-1
LẬP TRÌNH SỬ DỤNG NGẮT

clr r16
add r30,r26
adc r31,r16
lpm r27,z
out LEDMATRIXPORT,r27
pop r27
pop r16 ; Restore the temporary register
ret ; Return from the function
initTimer1CTC:
push r16
ldi r16, high(8000) ; Load the high yte into the temporary register
sts OCR1AH, r16 ; Set the high byte of the timer 1 compare value
ldi r16, low(8000) ; Load the low byte into the temporary register
sts OCR1AL, r16 ; Set the low byte of the timer 1 compare value
ldi r16, (1 << CS10)| (1<< WGM12) ; Load the value 0b00000101 into the temporary register
sts TCCR1B, r16 ;
ldi r16, (1 << OCIE1A); Load the value 0b00000010 into the temporary
register
sts TIMSK1, r16 ; Enable the timer 1 compare A interrupt
pop r16
ret
timer1_COMP_ISR:
push r16
push r26
push r27
ldi r31,high(LedMatrixColIndex)
ldi r30,low(LedMatrixColIndex)
ld r16,z
mov r26,r16
ldi r31,high(LedMatrixBuffer)
ldi r30,low(LedMatrixBuffer)
add r30,r16
clr r16
adc r31,r16
ld r27,z
call ledmatrix_display_col
inc r26
cpi r26,8
brne timer1_COMP_ISR_CONT
ldi r26,0 ;if r26 = 8, reset to 0
timer1_COMP_ISR_CONT:
ldi r31,high(LedMatrixColIndex)
ldi r30,low(LedMatrixColIndex)
st z,r26
pop r27
pop r26
pop r16
reti

https://doe.dee.hcmut.edu.vn/
LAB 4-1
LẬP TRÌNH SỬ DỤNG NGẮT

https://doe.dee.hcmut.edu.vn/
LAB 4-1
LẬP TRÌNH SỬ DỤNG NGẮT

https://doe.dee.hcmut.edu.vn/
BÁO CÁO
Nhóm:
Nhóm môn học: Môn thí nghiệm:

BÀI 1
1. Trả lời các câu hỏi
a. Với chế độ Normal mode, mỗi khi vào ngắt OverFlow ta có phải khởi động lại
thanh ghi đếm hay không?
b. Giải thích các giá trị ghi vào các thanh ghi cấu hình timer và prescaler.
2. Mã nguồn chương trình với chú thích

BÀI 2
1. Trả lời các câu hỏi
a. Với chế độ CTC mode, mỗi khi vào ngắt COMPARE_MATCH ta có phải
khởi động lại thanh ghi đếm hay không?
b. Điểm tiện lợi của chế độ này so với cách cấu hình ở bài 1 là như thế nào?
c. Giải thích các giá trị ghi vào các thanh ghi cấu hình timer và prescaler.
2. Mã nguồn và chú thích

BÀI 3
1. Trả lời các câu hỏi

a. Để đạt được tần số quét 50Hz thì 1 LED sẽ sáng trong bao lâu?

b. Khi đó, chân PC0 (đảo mỗi khi chuyển LED) sẽ có tần số là bao nhiêu?

c. Số lần xảy ra ngắt cần thiết để chuyển LED là bao nhiêu?


2. Mã nguồn và chú thích

https://doe.dee.hcmut.edu.vn/
BÁO CÁO
Nhóm:
Nhóm môn học: Môn thí nghiệm:

BÀI 4
1. Trả lời các câu hỏi

a. Mô tả các kết nối trên kit.

b. Mô tả cách cấu hình UART

c. Chuyển đổi số đếm thành số BCD để ghi vào bộ đệm hiển thị LED như
thế nào?
2. Mã nguồn và chú thích

BÀI 5
1. Trả lời các câu hỏi
a. Mô tả kết nối trên kit
b. Để xảy ra ngắt 1 s 1 lần thì ngắt ngoài cấu hình như thế nào?
c. Hiện tượng gì sẽ xảy ra nếu ta cấu hình ngắt ngoài tích cực theo mức thấp?
2. Mã nguồn chương trình với chú thích

BÀI 6
1. Trả lời các câu hỏi
a. Mô tả kết nối trên kit
b. Để có tần số quét 25Hz thì một cột LED sáng trong bao lâu?
c. Sự khác nhau khi quét ở tần số 25Hz và 125Hz

https://doe.dee.hcmut.edu.vn/
BÁO CÁO
Nhóm:
Nhóm môn học: Môn thí nghiệm:

2. Mã nguồn chương trình với chú thích

https://doe.dee.hcmut.edu.vn/
LAB 4-2
GIAO TIẾP I/O VÀ CÁC LỆNH TÍNH TOÁN

MỤC TIÊU:

 Hiểu và sử dụng được ngắt timer

 Hiểu cách điều khiển và đo tốc độ động cơ

THAM KHẢO:

 Tài liệu hướng dẫn thí nghiệm, chương 12

 Atmel-2505-Setup-and-Use-of-AVR-Timers_ApplicationNote_AVR130.pdf

BÀI 1

Yêu cầu:
a. Viết chương trình điều khiển tốc độ động cơ DC dùng PWM với tần số 1 Khz, sử dụng
timer 0. Điều khiển tốc độ tăng/giảm sử dụng 2 nút nhấn, mỗi lần nhấn nút tăng/giảm
duty cycle 5%. Cho phép động cơ chạy/dừng và điều khiển động cơ quay thuận/ngược
bằng 2 switch trên dip switch.

.DEF FLAG_REG=R18
.EQU CONT_IN=PINA
.EQU CONT_DR=DDRA
.EQU CONT_OUT=PORTA
.EQU SW_FLG=0
.EQU SW_DIR=0 ;=0 THUAN, =1 NGHICH
.EQU P_OUT=4 ;NGO RA XUNG PWM
.EQU SW1=0 ;TANG %
.EQU SW2=1 ;GIAM %
.EQU SW3=2
.EQU SW4=3
.EQU CONT_DIR1=4
.EQU CONT_DIR2=5
.EQU PMIN=1 ;TOC DO MIN
.EQU PMAX=124 ;TOC DO MAX
.EQU DELTA=6 ;THAY DOI 5%TOC DO MAX
.ORG 0
RJMP MAIN

https://doe.dee.hcmut.edu.vn/
LAB 4-2
GIAO TIẾP I/O VÀ CÁC LỆNH TÍNH TOÁN

.ORG 0x40
MAIN: LDI R16, HIGH(RAMEND)
OUT SPH, R16
LDI R16, LOW(RAMEND)
OUT SPL, R16
LDI R16, (1<<P_OUT)
OUT DDRB, R16
LDI R16, 0b00110000
OUT CONT_DR, R16
LDI R16, 0x0F
OUT CONT_OUT, R16 ;DIEN TRO KEO LEN CHO 4SW
LDI R16, PMAX
OUT OCR0A, R16
LDI R16, PMIN
OUT OCR0B, R16
LDI R16, 0b00100011 ;TIMER0 MODE FPWM7, KHONG DAO OC0B
OUT TCCR0A, R16
LDI R16, 0b00001100 ;TIMER0 MODE FPWM7, HE DO CHIA N=256
OUT TCCR0B, R16
LDI R19, DELTA
START:
RCALL GET_SW_DIR
RCALL GET_SW ;DOC SW
SBRS FLAG_REG, SW_FLG ;CO SW_FLG=1 CÓ SW NHAN
RJMP START
IN R18, CONT_IN
ANDI R18, 0b00000011
CPI R17, 1 ;SW1=UP NHAN?
BRNE SW2_CHK ;KIEM TRA SW2
IN R17, OCR0B
ADD R17, R19
CPI R17, PMAX
BRCS UP_SP
LDI R17, PMAX
UP_SP: OUT OCR0B, R17
RJMP START
SW2_CHK: CPI R17, 2
BRNE START ;KIEM TRA SW3
IN R17, OCR0B ;DOC OCR2B
SUB R17, R19
CPI R17, PMIN
BRCC DWN_SP ;CHUA, CAP NHAT GIA TRI MOI
LDI R17, PMIN
DWN_SP: OUT OCR0B, R17
RJMP START
GET_SW: CBR FLAG_REG, (1<<SW_FLG); XOA CO BAO NHAN SW
BACK0: LDI R16, 50
WAIT0: IN R17, CONT_IN
ANDI R17, (1<<SW1)|(1<<SW2)

https://doe.dee.hcmut.edu.vn/
LAB 4-2
GIAO TIẾP I/O VÀ CÁC LỆNH TÍNH TOÁN

CPI R17, (1<<SW1)|(1<<SW2)


BREQ EXIT_SW
DEC R16
BRNE WAIT0
PUSH R17
BACK1: LDI R16, 50
WAIT1: IN R17, CONT_IN
ANDI R17, (1<<SW1)|(1<<SW2)
CPI R17, (1<<SW1)|(1<<SW2)
BRNE BACK1
DEC R16
BRNE WAIT1
POP R17
CPI R17, (1<<SW2); KIEM TRA SW1=0
BRNE SW2_CODE
LDI R17, (1<<SW1)
RJMP SET_FLG
SW2_CODE: CPI R17, (1<<SW1); KIEM TRA SW2=0
BRNE EXIT_SW
LDI R17, (1<<SW2)
SET_FLG: SBR FLAG_REG, (1<<SW_FLG)
EXIT_SW: RET
GET_SW_DIR:
BRAKE: IN R18, CONT_IN
ANDI R18, 0b00001000
CPI R18, 0 ;=0 PHANH DONG CO
BRNE NEXT
SBI CONT_OUT, CONT_DIR1
SBI CONT_OUT, CONT_DIR2
RJMP GET_SW_DIR
NEXT: IN R18, CONT_IN
ANDI R18, 0b00000100 ;??C SWITCH THUAN NGHICH
CPI R18, 0b00000100
BRNE DIR_FORWARD ;=0 NGHICH,=1 THU?N
SBI CONT_OUT, CONT_DIR1
CBI CONT_OUT, CONT_DIR2
RJMP EXIT
DIR_FORWARD:CPI R18, 0
BRNE EXIT
CBI CONT_OUT, CONT_DIR1
SBI CONT_OUT, CONT_DIR2
EXIT: RET

 Kết nối động cơ vào kit thí nghiệm


 Kết nối tín hiệu từ 2 switch trên dipswitch vào 2 chân port của AVR

https://doe.dee.hcmut.edu.vn/
LAB 4-2
GIAO TIẾP I/O VÀ CÁC LỆNH TÍNH TOÁN

 Kết nối tín hiệu từ 2 nút nhấn vào 2 chân port của AVR
 Kết nối tín hiệu từ chân OC0B ra 1 kênh đo của khối test point
 Kết nối tín hiệu từ 2 chân port điều khiển chiều quay thuận/ngược ra led đơn để
kiểm tra trạng thái.

b. Biên dịch, thực thi và kiểm tra hoạt động của chương trình bằng cách đo dạng sóng trên
oscilloscope và quan sát trạng thái các LED khi thay đổi dip switch và khi nhấn các nút
nhấn tăng/giảm tốc độ.

https://doe.dee.hcmut.edu.vn/
LAB 4-2
GIAO TIẾP I/O VÀ CÁC LỆNH TÍNH TOÁN

Xung PWM gốc

https://doe.dee.hcmut.edu.vn/
LAB 4-2
GIAO TIẾP I/O VÀ CÁC LỆNH TÍNH TOÁN

Xung PWM sau 3 lần nhấn nút tăng duty cycle

https://doe.dee.hcmut.edu.vn/
LAB 4-2
GIAO TIẾP I/O VÀ CÁC LỆNH TÍNH TOÁN

Trường hợp động cơ chạy thuận: tín hiệu MOTOR_ENABLE và MOTOR_CTRL1 bằng
1, MOTOR_CTRL2 = 0, Led D6 sáng

c. Kết nối tín hiệu PWM vào MOTOR_ENABLE, tín hiệu điều khiển chiều quay vào
MOTOR_CTRL1, MOTOR_CTRL2 trên J76 của khối DC_MOTOR.

d. Kiểm tra hoạt động của hệ thống.


e. Đo dạng sóng từ hai tín hiệu A-B của encoder và so sánh trong hai trường hợp động cơ
quay thuận hay ngược.

BÀI 2

Yêu cầu:
Thêm vào bài 1 ở trên chức năng đo tốc độ động cơ và hiển thị tốc độ, chiều quay lên LCD.
Tín hiệu từ 1 kênh của encoder đưa vào ngõ vào clock cho timer 2, sử dụng timer 2 ở chế độ
dùng clock ngoài. Khi timer 2 tràn sẽ sinh ra một ngắt, khi đó ta tăng 1 số đếm lên để đếm số lần
tràn của timer.
Hai kênh từ encoder cũng được đưa vào 2 chân port để xác định chiều quay thuận/ngược.
Thời gian 1 s tạo ra sử dụng ngắt timer 1. Khi ngắt xảy ra, đếm số lượng xung từ encoder trong
vòng 1 s và tính ra tốc độ động cơ, đưa lên LCD. Reset các số đếm để bắt đầu lại quá trình đo

BÀI 1
3. Trả lời các câu hỏi
c. Mô tả cách kết nối trên kit

https://doe.dee.hcmut.edu.vn/
LAB 4-2
GIAO TIẾP I/O VÀ CÁC LỆNH TÍNH TOÁN

d. Chụp ảnh dạng xung của 2 kênh encoder trong trường hợp quay thuận và quay
nghịch.
4. Mã nguồn chương trình với chú thích

BÀI 2
3. Trả lời các câu hỏi
a. Mô tả kết nối trên
b. Với động cơ trong thí nghiệm, công thức tính tốc độ như thế nào?
c. Timer 1 có thể được sử dụng để tạo ngắt sau mỗi 1 s hay không?
d. Cấu hình timer 1 như thế nào?
e. Thanh ghi đếm của timer 2 là thanh ghi bao nhiêu bit?
f. Để sử dụng timer 2 đếm số xung trong vòng 1s, có xảy ra trường hợp tràn
timer 2 không?
HD: từ tốc độ tối đa của động cơ, tỉ số truyền, số xung/vòng ta tính ra số
xung tối đa trong 1s.
g. Nếu có khả năng tràn timer 2, ta phải làm gì để đảm bảo tính đúng số xung
encoder?
4. Mã nguồn và chú thích

https://doe.dee.hcmut.edu.vn/

You might also like