Att få mer I/O pins på ATTiny med Skift register (3 / 6 steg)
Steg 3: Exempel #1: kod
Koden är skriven i AVR församling. Om du arbetar med kontrollanter som ATTiny - är det ett måste! Det ser skrämmande, men i verkligheten är det mycket enklare och lättare än C.
En annan anledning till att använda assembler är att denna kod endast behöver 148 byte utrymme efter sammanställning, medan Arduino IDE ger 644 byte av binära utdata för samma kod (har inte testat i AVR GCC), så om du vill utöka funktionaliteten i ditt lilla projekt, du har mindre än 400 byte kvar för att arbeta med...
/*
* Skift registrera demo #1
*
* ATTiny13A löpning
* ADC kör
*
* PIN-BELÄGGNING:
* PB0 - SKIFT Register klocka
* PB1 - SKIFT Register seriella Data
* PB2 - SKIFT Register Latch(Store)
* PB3 - ADC3 (Potentiometer ingång)
* PB4 - [INTE ANVÄNDS]
* PB5 - ÅTERSTÄLL
*/
.include "tn13Adef.inc"
def A = R16; g.p. variabel och/eller funktion argument
.def B = R17; Används i SEND_BYTE och ADC_START som tillfällig lagring
.def LED = R18; lagrar nuvarande LED utdata
.def BCT = R19; Bitars räknare för SEND_BYTE
.EQU SRCK = 0; PB0 = klocka
.EQU SRDA = 1; PB1 = seriella Data
.EQU SRLC = 2; Pb2 = Latch
/ * AVBRYTA VEKTORER * /
.org 0x0000
rjmp RESET; Återställa avbrott
.org 0x0003
rjmp TC0_OV; Timer1 avbrott
/*
* BÖRJA!
*/
RESET:
/ * SETUP STACK * /
LDI A, low(RAMEND); Ställ in buntpekaren
reda på SPL, A
/ * SETUP STIFT * /
LDI A, 0b0000_0111; Ställa in utgångsstift PB0... PB2
ut DDRB, A
/ * SETUP TIMER1 * /
LDI A, 0b0000_0101; Ställa in Timer Prescaler (1024)
ut TCCR0B, A; Detta kommer att orsaka Timer avbryta varje ~ 27ms
LDI A, 0b00000010; Aktivera Timer0 Overflow avbrott
ut TIMSK0, A
/ * SETUP ADC3 * /
LDI A, 0
ut ADCSRB, A; Inaktivera autotrigger(Free running)
LDI A, 0b00001000; Inaktivera Digital ingång på PB3(ADC3)
ut DIDR0, A
LDI A, 0b00000011
ut ADMUX, A; Källa: ADC3, justera: rätt, referens: VCC.
LDI A, 0b10000110
ut ADCSRA, A; Aktivera ADC med prescale 1/64
/ * ÅTERSTÄLL REGISTER * /
LDI A, 0x00; Rensa A
LDI LED, 0xFF; Ange alla lysdioder på OFF (1-off, 0-på)
rcall SEND_BYTE; Tydlig display
SEI; Aktivera avbrott
/ * Main loop * /
MAIN:
rjmp MAIN
/*
* Skickar 8-bitars data från LED register till SKIFT Register
*/
SEND_BYTE:
LDI BCT, 0b1000_0000; Ställa in bitars räknare
next_bit:
MOV B, ledde; Flytta databyte till temp-
och B, BCT; Kolla lite
breq noll. Ställ in Data till 0
SBI PortB, SRDA; Ställ in Data till 1
rjmp SKIFT. Skift
Zero:
CBI PortB, SRDA
SKIFT:
SBI PortB, SRCK; CLK upp
NOP
CBI PortB, SRCK; CLK ner
CLC; Rensa bär flaggan
ror BCT; Shift bitars räknare
brne next_bit; Nästa iteration
SBI PortB, SRLC; När gjort, spärr
NOP
CBI PortB, SRLC
ret; Gjort
/ * Starta ADC konvertering. Sparar resultatet till A * /
ADC_START:
SBI ADCSRA, ADSC; Start ADC konvertering
adc_wait:
sbic ADCSRA, ADSC; Kontrollera konverteringsstatus för
rjmp adc_wait; SKIP hoppa om avslutad
i A, ADCL; Få låga bitar
i B, ADCH; Få höga bitar
LSR B; Shift 2 bitar till höger
ror A; genom bär
LSR B
ror A
ret
/ * Timer 0 spill avbrott * /
TC0_OV:
rcall ADC_START; Starta ADC0 omvandling
/ * Jämföra 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; Skicka byte att skifta reg.
Reti; returnera