Код: Выделить всё
; ******************************************************
; * Автор: СКАЗОЧНИК *
; * Дата: 30.03.2016 *
; * Версия: 160330 *
; * Имя файла: АЦП *
; * Для AVR: ATTiny13 *
; * Тактовая частота: 4,8 MHz *
; * Среда разработки: AVR Studio 4.19 *
; * *
; * Выполняемые функции: включение фар от скорости *
; * *
; * *
; ******************************************************
; ================
; ПОДКЛЮЧАЕМЫЕ БИБЛИОТЕКИ (.include)
; ================
.include "tn13Adef.inc"
; ============
; ТИП МИКРОКОНТРОЛЛЕРА (.device)
; ============
.device ATtiny13A
; =================
; ОБЪЯВЛЕНИЯ И КОНСТАНТЫ (.def, .equ)
; =================
.def temp = R16
.def cnt = R20
.def OFFL = R17
.def OFFH = R24
.def ONTumL = R18
.def ONTumH = R25
.def ONBlL = R19
.def ONBlH = R26
.def PERIODL = R21
.def OVF = R22
.def PERIODH = R23
.def Addres = R27
; ====
; ПЕРЕМЕННЫЕ В ОЗУ (.dseg) RAM (.byte 1)
; ====
.dseg
;Counter1: .BYTE 1 ;Счетчик 0 для нулевого канала ШИМ
; ====
; МАССИВЫ И Т.Д. (.eseg) EEPROM (.db, .dw)
; ====
.eseg
.org 0x05
EE_PARAM:
.db 0xD8, 0x0E, 0x1F, 0x07, 0xA1, 0x04
; =================
; МАКРОСЫ (.MACRO)
; =================
.MACRO PUSHF ; Положить СРЕГ в стек
push r16
in r16, SREG
push r16
.ENDM
.MACRO POPF ; Достать СРЕГ из стека
pop r16
out SREG, r16
pop r16
.ENDM
; ******************************
; НАЧАЛО ПРОГРАММЫ (.cseg) FLASH
; ******************************
.cseg
; ------------------
; ВЕКТОРЫ ПРЕРЫВАНИЙ
; ------------------
rjmp RESET ; Reset Handler
rjmp INT0add ; External Interrupt0 Handler
rjmp PCI0add
rjmp OVF0add
rjmp ERDYadd
rjmp ACIadd
rjmp OC0Aadd
rjmp OC0Badd
rjmp WDTadd
rjmp ADCCadd
;RESET: ; Reset Handler
;INT0add: ; External Interrupt0 Handler
PCI0add:
;OVF0add:
ERDYadd:
ACIadd:
OC0Aadd:
OC0Badd:
WDTadd:
ADCCadd:
reti ; Выход из прерываний, которые не используются
; ----------------------
; ОБРАБОТЧИКИ ПРЕРЫВАНИЙ
; ----------------------
INT0add:
push temp ; Закидываем в стек темп
in temp, SREG ; Закидываем в стек СРЕГ
push temp
in temp, TIFR0 ; Проверка флага переполнения таймера
andi temp, (1<<1) ; Накладываем маску, если 1 бит был единицей, то он и останется, все остальные будут 0. Если он 0, то будет флаг Z
breq NOFLAG ; Нет флага (стоит Z), значит уходим, иначе обрабатываем флаг
out TIFR0, temp ; В темп уже есть этот флаг, как 1, снова его запихиваем и тем самым скинем флаг
inc OVF ; Добавляем еще одно переполнение к таймеру
NOFLAG: in PERIODL, TCNT0 ; Считываем значение младшего
mov PERIODH, OVF ; Считываем занчение старшего
clr OVF ; Чистим все для очередного замера
out TCNT0, OVF
pop temp ; Вытаскиваем из стека СРЕГ
out SREG, temp
pop temp ; Вытаскиваем из стека темп
reti
;----------------------------------------------------------------------------------------
OVF0add:
inc OVF
cpi OVF, 251
brsh OVER
reti
OVER: ldi OVF, 250
reti
; **************************************************************************************************
; ИНИЦИАЛИЗАЦИЯ МК (логическое начало основной программы) ******************************************
; **************************************************************************************************
; --------- конфигурация портов -----------------------------------------------
Reset: ldi temp, (0<<PB4)|(0<<PB3)|(1<<PB2)|(0<<PB1)|(1<<PB0) ; Конфигурация порта
out DDRB, temp
ldi temp, (1<<PB4)|(1<<PB3)|(0<<PB2)|(1<<PB1)|(0<<PB0)
out PORTB, temp
ldi temp, low(RAMEND) ; Загрузка указателя стека
out SPL, temp
clr temp
out TCCR0A, temp ; Нормальный режим счета (выводы отключены)
out TCNT0, temp ; Очищаем счетный регистр
ldi temp, (0<<FOC0A)|(0<<FOC0B)|(0<<WGM02)|(1<<CS02)|(0<<CS01)|(0<<CS00) ; Делитель 256
out TCCR0B, temp
ldi temp, (0<<OCIE0B)|(0<<OCIE0A)|(1<<TOIE0) ; Разрешаем прерывание по переполнению
out TIMSK0, temp
ldi temp, (1<<ISC01)|(1<<ISC00) ; Запуск прерываний по переднему спаду (внешние)
out MCUCR, temp
ldi temp, (1<<INT0) ; Запуск прерывания внешнего
out GIMSK, temp
sbis PINB, 4 ; Если джампер снят, то пропускаем режим программирования
rcall PROGRAMM ; иначе уходим в режим программирования РАЗРЕШИТЬ ПРЕРЫВАНИЯ!!!!!!!!!!!!
G: sbis PINB, 4 ; Снова проверяем перемычку, если стоит, то идем покругу.
rjmp G ; чтобы не выполлялась программа дальше, пока не уберут перемычку
;--------------------
ldi temp, 5 ; Здесь хранится первое значение скорости, при котором все выключается
out EEARL, temp ; загружаем адрес нужной ячейки
sbi EECR, EERE ; Выставляем бит чтения
in OFFL, EEDR ; Забираем из регистра данных результат
ldi temp, 6 ; Здесь хранится первое значение скорости, при котором все выключается
out EEARL, temp ; загружаем адрес нужной ячейки
sbi EECR, EERE ; Выставляем бит чтения
in OFFH, EEDR ; Забираем из регистра данных результат
;--------------------
ldi temp, 7 ; Здесь хранится второе значение скорости, при котором включаются туманки
out EEARL, temp ; загружаем адрес нужной ячейки
sbi EECR, EERE ; Выставляем бит чтения
in ONTumL, EEDR ; Забираем из регистра данных результат
ldi temp, 8 ; Здесь хранится второе значение скорости, при котором включаются туманки
out EEARL, temp ; загружаем адрес нужной ячейки
sbi EECR, EERE ; Выставляем бит чтения
in ONTumH, EEDR ; Забираем из регистра данных результат
;---------------------
ldi temp, 9 ; Здесь хранится третье значение скорости, при котором включается ближний свет
out EEARL, temp ; загружаем адрес нужной ячейки
sbi EECR, EERE ; Выставляем бит чтения
in ONBlL, EEDR ; Забираем из регистра данных результат
ldi temp, 10 ; Здесь хранится третье значение скорости, при котором включается ближний свет
out EEARL, temp ; загружаем адрес нужной ячейки
sbi EECR, EERE ; Выставляем бит чтения
in ONBlH, EEDR ; Забираем из регистра данных результат
ldi temp, 0 ; Закидываем нулевой адрес в ЕЕПРОМ
out EEARL, temp ;
ldi PERIODL, 250
ldi PERIODH, 250
; ---------- разрешение прерываний --------------------------------------------
sei ; Разрешаем прерывания
; *******************************************************************************************************************
; ОСНОВНАЯ ПРОГРАММА (основной цикл) ********************************************************************************
; *******************************************************************************************************************
Start:
cp ONBlL, PERIODL
cpc ONBlH, PERIODH
brsh ONB
rjmp T
ONB: sbi PORTB, 2
T: cp ONTumL, PERIODL ; Если
cpc ONTumH, PERIODH
brsh ONT
rjmp O
ONT: sbi PORTB, 0
O: cp OFFL, PERIODL ; Сравниваем с настоящим значением накопленного
cpc OFFH, PERIODH ; Если начисленное больше, то выключаем (скорость сильно маленькая)
brlo OFF
rjmp Start
OFF: cbi PORTB, 0
cbi PORTB, 2
rjmp Start ; Конец программы, переход на начало
; *******************************************************************************************************************
; ПОДПРОГРАММЫ ******************************************************************************************************
; *******************************************************************************************************************
PROGRAMM:
sei ; Разрешаем прерывания! Этим запускаем прерывания по спаду фронта
ldi cnt, 3
ldi Addres, 5
DO: sbis PINB, 3 ; Если кнопка не нажата, то выходим
rjmp STORE ; И идем сохранять значение
rjmp DO ; Иначе, крутимся бесконечно, пока не нажмут кнопку
STORE:
EEWrite: sbic EECR, EEPE ; Ждем готовности памяти к записи. Крутимся в цикле
rjmp EEWrite ; до тех пор пока не очистится флаг EEWE
cli
;ldi temp, 5
out EEARL, Addres ; Загружаем адрес нужной ячейки
out EEDR,PERIODL ; и сами данные, которые нам нужно загрузить
sbi EECR,EEMPE ; взводим предохранитель
sbi EECR,EEPE ; записываем байт (не более 4х таков ожидание)
EEWrite1: sbic EECR, EEPE ; Ждем готовности памяти к записи. Крутимся в цикле
rjmp EEWrite1 ; до тех пор пока не очистится флаг EEWE
inc Addres
out EEARL, Addres ; Загружаем адрес нужной ячейки
out EEDR,PERIODH ; и сами данные, которые нам нужно загрузить
sbi EECR,EEMPE ; взводим предохранитель
sbi EECR,EEPE ; записываем байт (не более 4х таков ожидание)
ldi temp, 0 ; Закидываем нулевой адрес в ЕЕПРОМ
out EEARL, temp ;
sei
inc Addres ; Сдвинули для следующего круга
cpi Addres, 9
brne TT
sbi PORTB, 0 ; Включаем туманки (светодиод)
;
TT: cpi Addres, 11
brne N
sbi PORTB, 2 ; Включаем ближний (светодиод)
N: rcall DELAY ; Подавляем дребезг
sbis PINB, 3 ; Проверка (отпустили ли кнопку)
rjmp N
clz
dec cnt ; Считаем очередной круг
breq END ; Уходим, если уже три круга прошло
rjmp DO ; И если не прошло три круга, то идем на очередной
; sbis PORTB, 0
; rjmp ON
; rjmp OFF
;
; ON: sbi PORTB, 0
; rjmp N
;;
; OFF: cbi PORTB, 0
;
END:
ret
;=============
;================
DELAY: ; Веся задержка будет равна примерно 50 мкс
push temp ; Положим перменную в стек, может она еще где-то используется
in temp, SREG ; Закидываем в стек СРЕГ
push temp
ldi R16, 200 ; Задержка ~8.107 mсек
ldi R28, 200
ldi R29, 0
Loop3: subi R16, 1
sbci R28, 0
sbci R29, 0
brcc Loop3
pop temp ; Вытаскиваем из стека СРЕГ
out SREG, temp ; Возвращаем занчение обратно из стека
pop temp ; Вытаскиваем переменную из стека
ret
;====================