Код: Выделить всё
;+--------------------------------------------------------------------+
;|Program: Сосулька + индикатор уровня, 12 светодиодов, ШИМ 3 бит|
;|Autor: EngineerKeen |
;|DATE: 14.01.14 |
;|Hardware: ATTiny13, 9.6MHz |
;+--------------------------------------------------------------------+
.include "tn13def.inc"
.include "MacroAvr.asm"
.def ZERO=R0 ;просто ноль
.def STR=R13 ;для сохранения SREG в прерываниях без стека
;def R1-R12 = Значения ШИМ каналов
.def FRAME_COUNT=R20 ;счетчик кадров
.def PWM=R21 ;счетчик ШИМ
.def STATUS=R23 ;регистр флагов
.def MODE=R25 ;режим работы
.cseg
.org 0
RJMP START ;RESET
RETI ;INT0
RETI ;PCINT0
RETI ;T0 OVERFLOW
RETI ;EE RDY
RETI ;COMP
RJMP NEXT_FRAME ;T0=A
RETI ;T0=B
RETI ;WDG
RJMP ADC_RD ;ADC
.org 0x000A
START:
CLR ZERO ;ZERO=0
OUTI CLKPR,(1<<CLKPCE) ;сброс делителя тактовой
OUT CLKPR,ZERO
OUTI MCUCR,(1<<SE) ;вкл. Sleep
OUTI SPL,low(ramend) ;уст. стека
OUTI DDRB,0x00 ;все порты - входы
OUTI PORTB,0x00 ;
OUTI TCCR0A,(1<<WGM01) ;настройка таймера
OUTI TCCR0B,(1<<CS02)|(1<<CS00);
OUTI OCR0A,0xD0 ;
OUTI TIMSK0,(1<<OCIE0A) ;
OUTI ADCSRA,(1<<ADEN)|(1<<ADIE)|(1<<ADSC)|(1<<ADPS2)|(1<<ADPS0) ;вкл. ADC
OUTI ADMUX,(1<<ADLAR)|(1<<MUX1) ;вход ADC1
OUTI ACSR,(1<<ACD) ;откл. компаратор
CLR STATUS ;сброс STATUS регистра
CLR FRAME_COUNT ;сброс счетуика кадров
CLR PWM ;сброс счетчика ШИМ
CLR XH ;установка указателя на 1й канал
LDI XL,1 ;
RCALL LOAD_FRAME ;загружаем первый кадр
SEI ;вкл. прерывания
SLEEP ;спать
CLR MODE ;режим по умолчанию
LOOP0: CJEQ MODE,0,LOOP0 ;ждем проверки режима
LOOP:
SLEEP ;спать
SBRC STATUS,0 ;проверяем необходимость
RCALL LOAD_FRAME ;грузить новый кадр
SBRC STATUS,1 ;проверяем необходимость
RCALL P_OUT ;обновить порты
RJMP LOOP ;зацикливание
P_OUT:
CBR STATUS,0x02 ;сброс бита обновления портов
LDI R17,13 ;константа для отключения канала (канал №13)
LD R18,X ;загружаем яркость
ANDI R18,0x07 ;только 3 бита
CP PWM,R18 ;сравниваем с ШИМ
BRGE SETBIT ;если меньше, не включаем канал
MOV R17,XL ;если больше загружаем константу для включения
SETBIT:
LDI ZH,High(PX*2-1) ;вычисляем конфигурацию PORT\DDR
LDI ZL,Low(PX*2-1) ;для текущего канала
ADD ZL,R17
ADC ZH,ZERO
LPM R16,Z+ ;загружаем DDR и PORT
MOV R17,R16 ;
SWAP R17 ;DDR - low, PORT - High
ANDI R16,0x0F ;
ANDI R17,0x0F
OUT DDRB,R17 ;выставляем DDR и PORT
OUT PORTB,R16
INC XL ;канал+1
CJNE XL,13,P_RET ;проверяем что N канала не превышен
LDI XL,1
INC PWM ;увеличиваем счетчик ШИМ
ANDI PWM,0x07 ;ШИМ 3 бита!
P_RET:
RET ;возврат в главный цикл
ADC_RD: ;чтение АЦП
SBI ADCSRA,ADSC ;проверяем режим при старте
SBR STATUS,0x02 ;
IN YL,ADCH ;читаем ADC
CJNE MODE,0,ADC_1 ;проверяем режим, если<>0 - сохраняем в OCR и выходим
CJNE YL,0xFF,ADC_2 ;если<>0, и ADC=MAX -> режим 2
LDI YL,0x80
LDI MODE,3 ;режим 3 (бегущий огонь)
RJMP ADC_1 ;
ADC_2: CPI YL,0x00 ;ADC=0 -> режим 2
LDI YL,0x80 ;иначе режим=1
BRNE ADC_0
LDI MODE,2 ;ADC=0: режим 2 (индикатор уровня)
RJMP ADC_1
ADC_0: LDI MODE,1 ;0<ADC<255: режим 1 (сосулька)
ADC_1: OUT OCR0A,YL ;устанавливаем скорость вывода кадров
RETI ;выход
NEXT_FRAME: ;вывод кадра
IN STR,SREG ;сохраняем SREG
INC FRAME_COUNT ;увеличиваем
CJNE FRAME_COUNT,79,NEW_FRAME;счетчик кажров
LDI FRAME_COUNT,0 ;по циклу 0-79
NEW_FRAME:
SBR STATUS,0x01 ;устанавливаем флаг необходимости обновить кадр
NF_OUT: OUT SREG,STR ;
RETI ;возврат
LOAD_FRAME:
CBR STATUS,0x01 ;сбрасываем флаг
CJEQ MODE,1,SOS ;проверяем режим работы MODE, =1 -> грузим следующий кадр
CJNE MODE,2,MODE3 ;=2 -> преобразование АЦП в индикатор уровня, =3 -> бегущий огонь
LDI ZH,0 ;загружаем адрес первого канала
LDI ZL,1
MOV R16,YL ;копируем значение АЦП в R16
LSR R16 ;делим на 4
LSR R16
CYC1: CLR R17 ;вычисляем значение ШИМ для каждого из каналов
CJEQ R16,0,STR_RX ;в зависимости
SUBI R16,5 ;от значения АЦП
BRCS XX1 ;методом последовательного
LDI R17,7 ;вычитания
RJMP STR_RX ;"яркости" из значения АЦП
XX1: SUBI R16,-5 ;и разспределения ее
MOV R17,R16 ;по каналам
CLR R16 ;начиная с 1
SUBI R17,-2 ;
STR_RX: ST Z+,R17 ;
CJNE ZL,13,CYC1 ;
RET ;возврат
MODE3:
INC R1 ;режим 3
MOV R2,R1 ;бегущий огонь
DEC R2 ;увеличиваем яркость канала 1
MOV R3,R2 ;копируем значение в следующий канал
DEC R3 ;уменьшаем значение
MOV R4,R3 ;повторяем до 12 канала
DEC R4
MOV R5,R4
DEC R5
MOV R6,R5
DEC R6
MOV R7,R6
DEC R7
MOV R8,R7
DEC R8
MOV R9,R8
DEC R9
MOV R10,R9
DEC R10
MOV R11,R10
DEC R11
MOV R12,R11
DEC R12
RET ;выход
SOS: MOV R17,FRAME_COUNT ;копируем счетчик кадров в R17
CLR R16 ;вычисляем адрес кадра во флеш памяти
LSL R17 ;смещение=номер кадра*6
ROL R16 ;
LSL R17
ROL R16
ADD R17,FRAME_COUNT
ADC R16,ZERO
ADD R17,FRAME_COUNT
ADC R16,ZERO
LDI ZH,High(FRAME*2) ;Z=(Frame*2)+FC*6
LDI ZL,Low(FRAME*2)
ADD ZL,R17 ;прибавляем смещение
ADC ZH,R16
LPM R1,Z+ ;читаем первый байт кадра
MOV R2,R1 ;сохраняем в каналы 1 и 2
SWAP R1 ;для 1-го - старшие 4 бита
LPM R3,Z+ ;повторяем для каналов
MOV R4,R3 ;3-4
SWAP R3 ;
LPM R5,Z+ ;5-6
MOV R6,R5 ;
SWAP R5 ;
LPM R7,Z+ ;7-8
MOV R8,R7 ;
SWAP R7 ;
LPM R9,Z+ ;9-10
MOV R10,R9 ;
SWAP R9 ;
LPM R11,Z+ ;11-12
MOV R12,R11 ;
SWAP R11 ;
LF_RET: RET ;возврат
PX: .db 0x31,0x32,0x62,0x64,0xC4,0xC8,0x98,0x91,0x51,0x54,0xA2,0xA8,0x00,0x00 ;данные PORT\DDR для каналов +"выкл все №13"
;1 2 3 4 5 6 7 8 9 10 11 12 -- --
Frame:
.db 0x00,0x00,0x00,0x00,0x00,0x00 ;0.5s ;кадры для последовательного вывода "тающей сосульки"
.db 0x10,0x00,0x00,0x00,0x00,0x00 ;1
.db 0x20,0x00,0x00,0x00,0x00,0x00 ;2
.db 0x30,0x00,0x00,0x00,0x00,0x00 ;3
.db 0x40,0x00,0x00,0x00,0x00,0x00 ;4
.db 0x50,0x00,0x00,0x00,0x00,0x00 ;5
.db 0x60,0x00,0x00,0x00,0x00,0x00 ;6
.db 0x70,0x00,0x00,0x00,0x00,0x00 ;7
.db 0x71,0x00,0x00,0x00,0x00,0x00 ;8
.db 0x72,0x00,0x00,0x00,0x00,0x00 ;9
.db 0x73,0x00,0x00,0x00,0x00,0x00 ;10
.db 0x64,0x00,0x00,0x00,0x00,0x00 ;11
.db 0x65,0x00,0x00,0x00,0x00,0x00 ;12
.db 0x56,0x00,0x00,0x00,0x00,0x00 ;13
.db 0x57,0x00,0x00,0x00,0x00,0x00 ;14
.db 0x47,0x00,0x00,0x00,0x00,0x00 ;15
.db 0x47,0x00,0x00,0x00,0x00,0x00 ;16
.db 0x37,0x10,0x00,0x00,0x00,0x00 ;17
.db 0x37,0x20,0x00,0x00,0x00,0x00 ;18
.db 0x27,0x30,0x00,0x00,0x00,0x00 ;19
.db 0x26,0x40,0x00,0x00,0x00,0x00 ;20
.db 0x16,0x50,0x00,0x00,0x00,0x00 ;21
.db 0x15,0x60,0x00,0x00,0x00,0x00 ;22
.db 0x05,0x70,0x00,0x00,0x00,0x00 ;23
.db 0x04,0x71,0x00,0x00,0x00,0x00 ;24
.db 0x03,0x72,0x00,0x00,0x00,0x00 ;25
.db 0x02,0x63,0x00,0x00,0x00,0x00 ;26
.db 0x01,0x54,0x00,0x00,0x00,0x00 ;27
.db 0x00,0x45,0x10,0x00,0x00,0x00 ;28
.db 0x00,0x36,0x20,0x00,0x00,0x00 ;29
.db 0x00,0x27,0x30,0x00,0x00,0x00 ;30
.db 0x00,0x17,0x41,0x00,0x00,0x00 ;31
.db 0x00,0x06,0x52,0x00,0x00,0x00 ;32
.db 0x00,0x05,0x63,0x10,0x00,0x00 ;33
.db 0x00,0x04,0x74,0x20,0x00,0x00 ;34
.db 0x00,0x03,0x65,0x31,0x00,0x00 ;35
.db 0x00,0x02,0x56,0x42,0x00,0x00 ;36
.db 0x00,0x01,0x47,0x53,0x10,0x00 ;37
.db 0x00,0x00,0x36,0x64,0x21,0x00 ;38
.db 0x00,0x00,0x25,0x75,0x42,0x10 ;39
.db 0x00,0x00,0x14,0x66,0x54,0x31 ;40
.db 0x00,0x00,0x03,0x57,0x65,0x43 ;41
.db 0x00,0x00,0x02,0x46,0x76,0x55 ;42
.db 0x00,0x00,0x01,0x35,0x67,0x66 ;43
.db 0x00,0x00,0x00,0x24,0x56,0x77 ;44
.db 0x00,0x00,0x00,0x12,0x35,0x67 ;45
.db 0x00,0x00,0x00,0x01,0x23,0x47 ;46
.db 0x00,0x00,0x00,0x00,0x12,0x37 ;47
.db 0x00,0x00,0x00,0x00,0x01,0x26 ;48
.db 0x00,0x00,0x00,0x00,0x00,0x16 ;49
.db 0x00,0x00,0x00,0x00,0x00,0x06 ;50
.db 0x00,0x00,0x00,0x00,0x00,0x05 ;51
.db 0x00,0x00,0x00,0x00,0x00,0x05 ;52
.db 0x00,0x00,0x00,0x00,0x00,0x05 ;53
.db 0x00,0x00,0x00,0x00,0x00,0x04 ;54
.db 0x00,0x00,0x00,0x00,0x00,0x04 ;55
.db 0x00,0x00,0x00,0x00,0x00,0x04 ;56
.db 0x00,0x00,0x00,0x00,0x00,0x03 ;57
.db 0x00,0x00,0x00,0x00,0x00,0x03 ;58
.db 0x00,0x00,0x00,0x00,0x00,0x03 ;59
.db 0x00,0x00,0x00,0x00,0x00,0x02 ;60
.db 0x00,0x00,0x00,0x00,0x00,0x02 ;61
.db 0x00,0x00,0x00,0x00,0x00,0x02 ;62
.db 0x00,0x00,0x00,0x00,0x00,0x01 ;63
.db 0x00,0x00,0x00,0x00,0x00,0x01 ;64
.db 0x00,0x00,0x00,0x00,0x00,0x01 ;65
.db 0x00,0x00,0x00,0x00,0x00,0x00 ;66
.db 0x00,0x00,0x00,0x00,0x00,0x00 ;67
.db 0x00,0x00,0x00,0x00,0x00,0x00 ;68
.db 0x00,0x00,0x00,0x00,0x00,0x00 ;69
.db 0x00,0x00,0x00,0x00,0x00,0x00 ;70
.db 0x00,0x00,0x00,0x00,0x00,0x00 ;71
.db 0x00,0x00,0x00,0x00,0x00,0x00 ;72
.db 0x00,0x00,0x00,0x00,0x00,0x00 ;73
.db 0x00,0x00,0x00,0x00,0x00,0x00 ;74
.db 0x00,0x00,0x00,0x00,0x00,0x00 ;75
.db 0x00,0x00,0x00,0x00,0x00,0x00 ;76
.db 0x00,0x00,0x00,0x00,0x00,0x00 ;77
.db 0x00,0x00,0x00,0x00,0x00,0x00 ;78
.db 0x00,0x00,0x00,0x00,0x00,0x00 ;79