Stap 3: Voorbeeld #1: Code
De code is geschreven in de vergadering van de AVR. Als u met controllers zoals ATTiny werkt - is het een must! Het ziet er eng, maar in werkelijkheid is het veel eenvoudiger en gemakkelijker dan C.
Een andere reden voor het gebruik van assembler is dat deze code alleen 148 bytes ruimte na compilatie, moet terwijl de Arduino IDE produceert 644 bytes van binaire uitvoer voor dezelfde code (nog niet getest in AVR GCC), dus als u wilt om uit te breiden de functionaliteit van uw kleine project, hebt u minder dan 400 bytes om te werken met...
/* * Shift register demo #1 * * ATTiny13A Running * ADC running * * PIN ASSIGNMENT: * PB0 - Shift Register Clock * PB1 - Shift Register Serial Data * PB2 - Shift Register Latch(Store) * PB3 - ADC3 (Potentiometer input) * PB4 - [NOT USED] * PB5 - RESET */ .include "tn13Adef.inc" .def A = R16 ; g.p. variable and/or function argument .def B = R17 ; Used in SEND_BYTE and ADC_START as temporary storage .def LED = R18 ; stores current LED output .def BCT = R19 ; Bit counter for SEND_BYTE .equ SRCK = 0 ; PB0 = Clock .equ SRDA = 1 ; PB1 = Serial Data .equ SRLC = 2 ; PB2 = Latch /* INTERRUPT VECTORS */ .org 0x0000 rjmp RESET ; Reset interrupt .org 0x0003 rjmp TC0_OV ; Timer1 interrupt /* * START!!! */ RESET: /* SETUP STACK */ ldi A, low(RAMEND) ; Set stack pointer out SPL, A /* SETUP PINS */ ldi A,0b0000_0111 ; Set output pins PB0..PB2 out DDRB,A /* SETUP TIMER1 */ ldi A,0b0000_0101 ; Set Timer Prescaler (1024) out TCCR0B,A ; This will cause Timer Interrupt every ~27ms ldi A,0b00000010 ; Enable Timer0 Overflow Interrupt out TIMSK0,A /* SETUP ADC3 */ ldi A,0 out ADCSRB,A ; Disable autotrigger(Free running) ldi A,0b00001000 ; Disable Digital Input on PB3(ADC3) out DIDR0,A ldi A,0b00000011 out ADMUX,A ; Source:ADC3, Align:RIGHT, Reference:VCC. ldi A,0b10000110 out ADCSRA,A ; Enable ADC with prescale 1/64 /* RESET REGISTERS */ ldi A,0x00 ; clear A ldi LED,0xFF ; Set all LED's to OFF(1-off, 0-on) rcall SEND_BYTE ; Clear display sei ; Enable interrupts /* Main loop */ MAIN: rjmp MAIN /* * Sends 8-bit data from LED register to Shift Register */ SEND_BYTE: ldi BCT,0b1000_0000 ; Set Bit counter next_bit: mov B,LED ; Move data byte to temp and B,BCT ; Check bit breq zero ; Set Data to 0 sbi PortB,SRDA ; Set Data to 1 rjmp shift ; shift zero: cbi PortB,SRDA shift: sbi PortB,SRCK ; CLK up nop cbi PortB,SRCK ; CLK down clc ; Clear Carry flag ror BCT ; Shift bit counter brne next_bit ; Next iteration sbi PortB,SRLC ; When done, Latch nop cbi PortB,SRLC ret ; Done /* Start ADC conversion. Saves result to A */ ADC_START: sbi ADCSRA,ADSC ; Start ADC conversion adc_wait: sbic ADCSRA,ADSC ; Check conversion status rjmp adc_wait ; Skip jump if completed in A,ADCL ; Get low bits in B,ADCH ; Get high bits lsr B ; Shift 2 bits to the right ror A ; through Carry lsr B ror A ret /* Timer 0 overflow interrupt */ TC0_OV: rcall ADC_START ; start ADC0 Conversion /* Compare Input, Set output */ cpi A,0xC8 ; A>=200? brlo gt_160 ldi LED,0b11100000 rjmp sr_write gt_160: ; A>=160? cpi A,0xA0 brlo gt_120 ldi LED,0b11110000 rjmp sr_write gt_120: ; A>=120? cpi A,0x78 brlo gt_80 ldi LED,0b11111000 rjmp sr_write gt_80: ; A>=80? cpi A,0x50 brlo gt_40 ldi LED,0b11111100 rjmp sr_write gt_40: ; A>=40? cpi A,0x28 brlo lt_40 ldi LED,0b11111110 rjmp sr_write lt_40: ; A<40 ldi LED,0b11111111 sr_write: rcall SEND_BYTE ; Send byte to shift reg. reti ; return