Skip to content

Instantly share code, notes, and snippets.

@BobBurns
Created November 27, 2014 00: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 BobBurns/297a090eb7a5e2db984b to your computer and use it in GitHub Desktop.
Save BobBurns/297a090eb7a5e2db984b to your computer and use it in GitHub Desktop.
example program using pin change interrupts from AVR Programming by Elliot Williams
;Capacitive sensor demo in avr assembly
;compile with gavrasm capSense.asm
;flash with avrdude -c avrisp -p m168 -P /dev/tty.usbmodem1411 -b 19200 -U flash:w:capSense.hex
;
;
;what I learned from this program:
; always save the status reg when using interrupts
; and use the right jump vector for interrupt calls
; and keep track of registers used in subroutines
;
;1mhz clock speed X2, 9600 baud UBBR = 12
.equ UBBRvalue = 12
.equ UCSR0C = 0xc2 ;SRAM address of UCSR0C
.def temp = r16
.def temp2 = r17
.def trans_t = r18
.def I_temp = r19
.def xL = r26 ;x reg used as global counter
.def xH = r27
.def zL = r30
.def zH = r31
.device atmega168
;---- global variables ----
.dseg
cc_count: .byte 2 ;remember this is big endian
.cseg
.org 0
jmp reset
.org 0x0008 ;PCINT1 vector
jmp c_change ;pcint1
c_change:
in temp,SREG ;save status register
adiw xH:xL,1
sbi DDRC,PC1
ldi I_temp,4
i_lp: dec I_temp
brne i_lp ;8mhz clock for 1us delay
cbi DDRC,PC1
in I_temp,PCIFR
sbr I_temp,(1 << PCIF1)
out PCIFR,I_temp
out SREG,temp
reti
.undef I_temp
;----- Main -----
.org 0x0034
reset:
cli
lds temp,CLKPR ;clock_prescale_set
sbr temp,(1 << CLKPCE)
sts CLKPR,temp
ldi temp,0x00
sts CLKPR,temp ;set full speed = 8Mhz
;inittialize Stack
ldi temp,low(RAMEND)
out SPL,temp
ldi temp,high(RAMEND)
ldi temp,high(RAMEND)
out SPH,temp
;initialize USART
ldi temp,high(UBBRvalue) ;baud rate param
sts UBRR0H,temp
ldi temp,low(UBBRvalue)
sts UBRR0L,temp
lds temp,UCSR0A
ori temp,(1 << U2X0) ;set use 2x because %error actual baud > .5
sts UCSR0A,temp
;--- USART register values
ldi temp,(1 << TXEN0) | (1 << RXEN0) ;enable transmit and receive
sts UCSR0B,temp
ldi temp,(1 << UCSZ01) | (1 << UCSZ00) ;8 data bits, 1 stop bit
sts UCSR0C,temp
;--- send a message
ldi zH, high(cap_str * 2)
ldi zL, low(cap_str * 2)
rcall print_s
;--- set ddr ---
ldi temp,0xff
out DDRB,temp ;set output on leds
;--- disable all pullups
in temp,MCUCR
sbr temp,(1 << PUD)
out MCUCR,temp
sbi PORTC,PC1 ;leave output high on pc1
;--- init pin change interrupt ---
lds temp,PCICR
sbr temp,(1 << PCIE1)
sts PCICR,temp
lds temp,PCMSK1
sbr temp,(1 << PC1) ;enable pin-change interrupts for 1 (bank C)
sts PCMSK1,temp ;enable specific interupt for pin PC1
;--- event loop ---
loop:
ldi temp,0x00
ldi xH,0x00
ldi xL,0x00 ;xReg is counter
sbi DDRC,PC1 ;start with cap charged
sei ;set global interupt
.equ d_cnt = 50000 ;inline delay
ldi temp2,1
outer: ldi r24,low(d_cnt)
ldi r25,high(d_cnt)
delay: sbiw r25:r24,1
nop ;this makes four clock cycles = 200,000 us
brne delay
dec temp2
brne outer
cli ;clear global interrupt
.equ thresh = 12000
;compare threshhold with count / should work with just high bytes
cpi xH,high(thresh)
brlt led_on
ldi temp,0x00
out PORTB,temp
out PORTB,temp
rjmp msg
led_on: ldi temp,0xff
out PORTB,temp
msg:
mov r24,xH
rcall transmit
mov r24,xL
rcall transmit
ldi r24,0x0d
rcall transmit
ldi r24,0x0a
rcall transmit
rjmp loop
;
;--- Subroutines ---
;print string function
;takes Z loaded with pointer to string with first byte being length
;uses r16,r18,r24
.def byte_tx = r24
.def count = r18
print_s:
lpm count,Z+
for1: lpm byte_tx,Z+
wait: lds temp,UCSR0A
sbis temp,UDRE0 ;wait for Tx buffer to be empty
rjmp wait ;not ready
sts UDR0,byte_tx;
dec count
brne for1
ret
;send one byte
;uses r24 as byte to send
transmit:
lds trans_t,UCSR0A
sbis trans_t,UDRE0
rjmp transmit
sts UDR0,r24
ret
cap_str: .db 22,"==[ Cap sensor ]==",0x0d,0x0a,0x0d,0x0a,0x00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment