Skip to content

Instantly share code, notes, and snippets.

@nohponex
Last active August 29, 2015 14:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nohponex/6dc412858b9006e14ed2 to your computer and use it in GitHub Desktop.
Save nohponex/6dc412858b9006e14ed2 to your computer and use it in GitHub Desktop.
ΤΗΜΜΥ - Μικροεπεξεργαστές και περιφερειακά : Εξετάσεις 02/2013, Θέμα 2, 3
/**
* Thema 2 02/2013
* Output Mean_LSB => PORTB 7-0 ; Negative logic
* Cable from OC1A (PD5) to INT0 (PD2)
*/
.include "m128def.inc"
.def adc_mux = r18
.def temp = r16
.def temp2 = r17
.def sumH = r20
.def sumL = r21
.equ ADC_MASK = 0b01000000
.equ upper_bound = 0x348
.equ TIMER1_ORC = 58593; ( 15 sec ) ; clocks = ( 15sec )*( CLK /N ) , CLK = 4Mhz, N = 1024
.equ TIMER3_ORC = 19531; ( 5 sec ) ; clocks = ( 5sec )*( CLK /N ) , CLK = 4Mhz, N = 1024
.org 0x00
jmp RESET
.org 0x02
jmp INT0_ISR
.org 0x2A
jmp ADC_ISR
.org 0x34
jmp COUNTER3_COMPA_ISR ;Counter/timer 3 compare match A
;Reset ISR
RESET:
;SETUP STACK POINTER
ldi temp, HIGH( RAMEND )
out SPH, temp
ldi temp, LOW( RAMEND )
clr sumH
clr sumL
;SET PD5 as output
sbi DDRD,5
;SET PD5 HIGH ( negative logic )
sbi PORTD,5
;SET PORTB as output
ser temp
out DDRB, temp
;SET PORTB HIGH ( negative logic )
out PORTB, temp
;SETUP INT0
;Enable INT0 Mask
ldi temp, 0b00000001; INT0 => 1
out EIMSK, temp
;Set INT0 Sense control
ldi temp, 0b00000010; ISC10, ISC00 -> 10 ( falling edge )
sts EICRA, temp;out EICRA, temp ; Use STS instead of out ( EICRA address is out of range for out )
clr adc_mux
;SETUP ADC
ldi temp, ADC_MASK ; ( 0b01000000 ) REFS => 01 MUX => 0000
out ADMUX, temp
;ENABLE ADC ( AVR clock = 4MHz, 13 Clocks per sample, 2500 Samples/sec ===> ADC prescaler ~= 128 )
ldi temp, 0b11101111; ADEN => 1, ADCS => 1, ADFR => 1, ADIF => 0, ADIE => 1, ADSP => 111 ( ADC prescaler : 128 )
out ADCSRA, temp
;SETUP TIMER1
;SET OCR1A value
ldi temp, HIGH( TIMER1_ORC )
out OCR1AH, temp
ldi temp, LOW( TIMER1_ORC )
out OCR1AL, temp
;SET mode CTC AND prescaler AND Compare output Mode ( COM ) ( WG => 0100 (CTC ) )
ldi temp, 0b10000000; COM1A=> 10 WG1,WG0 =>00
out TCCR1A, temp
ldi temp, 0b00001101; WG3, WG2 => 01, CS => 101 ( prescaler : 1024 )
out TCCR1B, temp
; ENABLE GLOBAL INTERRUPTS
sei
;INFINITE LOOP
loop:
jmp loop
;EXTERNAL ADC ISR
ADC_ISR:
in temp, ADCL
in temp2, ADCH
add sumL, temp
adc sumH, temp2
inc adc_mux
cpi adc_mux, 0b1000
brlo dont_reset_adc_mux
;reset adc_mux
clr adc_mux
dont_reset_adc_mux:
;return from ISR
reti
;EXTERNAL INT0 ISR
INT0_ISR:
;Get averare power per channel, per minute
;Multiply by 0,0002 ===> Result at sumH:sumL with 4 decimal digits, ( Average power per channel = (SUM * 60 )/(15 * 2500 * 8) = SUM * 0,0002
;LOW Byte * 2
lsl sumL ; bit 9 => C
;HIGH Byte * 2 ( get C from sumL )
rol sumH
;Compare with upper_bound value IF average power is larger than upper_bound then set alarm
cpi sumH, HIGH( upper_bound )
brlo no_alarm
cpi sumL, LOW( upper_bound )
brlo no_alarm ; Skip if less than
breq no_alarm ; Skip if equal
;ALARM
;SETUP COUNTER_3 WITH 5 SEC TOOGLE
;SET OCR3A value
ldi temp, HIGH( TIMER3_ORC )
sts OCR3AH, temp;out OCR3AH, temp
ldi temp, LOW( TIMER3_ORC )
sts OCR3AL, temp;out OCR3AL, temp
;SET mode CTC AND prescaler AND Compare output Mode ( COM )
ldi temp, 0b10000000; COM3A=> 10 WG 10 =>00
sts TCCR3A, temp;out TCCR3A, temp
ldi temp, 0b0000101; WG 32 => 10, CS => 101 ( prescaler : 1024 )
sts TCCR3B, temp;out TCCR3B, temp
;Clear PORTB ( open all LEDs )
clr temp;
out PORTB, temp
rjmp done;
no_alarm: ;If no alarm is set
; DISABLE COUNTER 3
clr temp
sts TCCR3B, temp;out TCCR3B, temp
;Negative logic
mov temp, sumH
com temp
;Output MSB to PORTB
out PORTB, temp
done:
reti
COUNTER3_COMPA_ISR: ;(alarm)
;Read current PORTB status
in temp, PORTB
;SET temp2 = 0xFF
ser temp2
;XOR ( TOOGLE : 00 XOR 11 => 11, 11 XOR 11 => 00 )
eor temp,temp2
out PORTB, temp
reti;
/**
* Thema 3 02/2013
* Input A,B,C,D => PA0, PA1, PA2, PA3; Positive logic
* Input External INT0 => PD2 ; Sense : Falling edge
* Output O1, O2, O3 => PB0, PB1, PB2 ; Positive logic
*/
.include "m16def.inc"
.def temp = r16
.def input = r17
.def output = r18
.org 0x00
jmp RESET
.org 0x02
jmp INT0_ISR
;Reset ISR
RESET:
;SETUP STACK POINTER
ldi temp, HIGH( RAMEND )
out SPH, temp
ldi temp, LOW( RAMEND )
out SPL, temp
;SET PA 0-3 AS INPUT
;SET PD 2 AS INPUT ( EXTERNAL INT0 )
;SET PB 0-2 AS OUTPUT
ldi temp, 0b00000111
out DDRB, temp
;SET INT0 INTERRUPT SENSE TO FALLING EDGE
ldi temp, 0b00000010
out MCUCR, temp
;ENABLE INT0
ldi temp, 0b01000000
out GICR, temp
;ENABLE GLOBAL INTERRUPTS
sei
;INFINITE LOOP
loop:
jmp loop
;EXTERNAL INT0 ISR
INT0_ISR:
;set temporary output
clr output
;read input
in input, PINA
;Keep lower nibble
andi input, 0x0F
;Check if O1 is set ( ABCD )
cpi input, 0x0F
; If ABCD != 1111 skip O1
brne O1_not_set
;SET O1
ori output, 0b00000001
O1_not_set:
;Get AB and CD
;Copy input to temp
mov temp, input
;Shift left temp register
lsl temp
/*Contents in registers :
;input : 0000DCBA
;temp : 000DCBA0
*/
and temp, input
;apply mask to keep bits 1 and 3 ( bit 1 = AB, bit 3 = CD )
andi temp, 0b00001010
;Check if AB*2 + CD*8 == 0
tst temp
breq done; IF AB*2 + CD*8 == 0 ( Both O2, O3 are 0 )
;AB*2 + CD*8 > 0 then AB is set OR CD is set ===> (O2) AB OR BC is set
;SET O2
ori output, 0b00000010
;Check if AB*2 + CD*8 >= 10
cpi temp, 10
brsh done;IF AB*2 + CD*8 >= 10 then both AB, CD are set ==> (O3) AB XOR BC is clear
;AB*2 + CD*8 < 10 then AB is set XOR CD is set ==> (O3) AB XOR BC is set
;SET O3
ori output, 0b00000100
done:
out PORTB, output
;return from ISR
reti
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment