Немного 0xFF. Как бы я писал программы если бы у меня было много времени или зарплата побольше:-)
(«Телесистемы»: Конференция «Микроконтроллеры и их применение»)

миниатюрный аудио-видеорекордер mAVR

Отправлено misyachniy 20 мая 2005 г. 13:50


; Программа управления дверцей/шторкой диспенсера(устройство выдачи наличных)
; В данной пьесе участвуют следующие лица и исполнители

; Входящие сигналы:

; DoorIsClose датчик - дверца закрыта, активный '1' световой поток перекрыт
; DoorIsOpen датчик - дверца открыта, активный '1' световой поток перекрыт

; CloseDoor команда закрыть дверь, активный '0'
; OpenDoor команда открыть дверь, активный '0'

; Исходящие сигналы:

; StateIsClose сигнализация диспенсеру - дверца закрыта, активный '1'
; StateIsOpen сигнализация диспенсеру - дверца открыта, активный '1'

; MP и MM управление сдвоенным оптроном транзисторные выходы которого
; включени в "H" мост и управляют микромоторчиком дверцы
; если MP != MM то мотор будет крутится в ту или иную сторону.
; DDR соответствующих ножек тоже должны быть установлены в '1'

; Есть еще "действующие лица" которых сложно
; задетектировать/идентифицировать/предположить.
; Это подклинивание механизма, злоумышленник вставляющий посторонние предметы,
; Дед Мороз примораживающий механику и т.д.

; А также массовка в составе таймеров, ватч-догов и т.д.

; Общий вид пьесы.
; После инициализации портов и сбросов всех сигналов(ножек) в неактивное сотояние
; процессор переходит в неактивное состояние.
; Опрос датчиков, фильтрация помех, выполнение действий происходит
; по прерыванию таймера 0.
; Тактирование процессора от внутреннего RC генератора 1МГц.
; Прерывание 1000000/(256*256), что составит около 0,066 секунд
; Фильтрация от помех состояния датчиков упрощенная.
; Каждый раз по прерыванию "заталкиваем" в регистр по 1 при активном
; сигнале и 0 при неактивном.
; решение принимаем при значении в регистре 0x00 или 0xFF
; Таким образом время действия сигнала не менее 0,066*8=0,5 секунд.

; Собственно пьеса о проделках таймера.

; 1-й АКТ
; Опросить датчики DoorIsClose, DoorIsOpen и при равенстве 0x00 или 0xFF
; выставить соответствующие потенциалы для диспенсера StateIsClose, StateIsOpen
; 2-й АКТ
; Опросить сигналы(команды) CloseDoor, OpenDoor
; Проанализировать сначала пару CloseDoor/DoorIsClose и включить мотор
; в нужном направлении.
; Если первая пара не требует отработки проанализировать аналогично OpenDoor/DoorIsOpen.
; Для того чтобы предотвратить бесконечную отработку команды CloseDoor/OpenDoor,
; вводится переменная MotorToOff, наверное 1 байт будет достаточно -
; 255*0.066=16 секунд. Которая инициализируются при включении/отключении мотора.
; 3-й АКТ
; Если мотор включен то декрементировать MotorToOff
; до срабатывания требуемого датчика или при достижении 0, отключать мотор.
; таким образом бесконечная отработка команды будет предотвращена.
; 4-й АКТ
; Диспенсер держит активную команду до 2-х минут, злоумышленник или
; сбой механики может привести к тому что, после 16 секунд, дверца не займет
; требуемого положения и в действие вступит опять АКТ 2, мотор снова включится.
; Заклиненый мотор имеет очень низкое сопротивление и много мощности выделяется на
; транзисторах "H" моста. Перегревается самый близкий к стабилизатору питания мотора.
; Совместный нагрев и ведет к отказу транзистора. Таким образом нужно вводить
; еще одну переменную для отсчета паузы, после не успешной попытки закрыть/открыть
; дверцу, для предотвращения перегрева. Пауза должна быть около 2-х минут, чтобы
; дать возможность остыть транзисторам и не слишком большой чтобы программа
; управления диспенсером не посчитала сбой полным отказом. Назовем эту переменную
; TimeForCool. Ее рассчетное значение:
; 2 минуты= 120 секунд=120/0,066=1800 срабатываний таймера 0.
; Эпилог
; Теперь выстроим порядок проверки условий для изменения состояния мотора
; по мере убывания приоритета:

; 1) TimeForCool==0
; 2) Опрос команд CloseDoor, OpenDoor и датчиков DoorIsClose, DoorIsOpen
; 3) Проверка MotorToOff
; 4) Проверка датчика DoorIsClose
; (при подаче питания/провисания дверцы от выработки механики)

; Получилось не драматическое произведение а детектив,
; самое интересное в последней главе :-)

.include "tn26def.inc"

; ножки входных сигналов уже разведены на плате изменить нельзя.
; да и часть исходных текстов тоже досталась по наследству :-).

.equ CloseDoor = PB4
.equ OpenDoor = PB6

.equ DoorIsClose = PA0
.equ DoorIsOpen = PB0

; выходные сигналы
.equ StateIsClose = PB1
.equ StateIsOpen = PB3

; Входы встречно-включенных оптронов, направление вращения двигателя
; и защита от сквозных токов в мосте
.equ MM = PA5
.equ MP = PA3

; переменные
.def temp =R16
.def temp2 =R17


; байт для подсчета времени, на отключения мотора, тайм аут на команду
.def MotorToOff = R18

; байты для фильтрации от помех при опросе датчиков
;.def StateClose = R19
;.def StateOpen = R20

.def CurentState = R21 ; текущее сотояние логического состояния контроллера
.equ None = 0
.equ Closing = 1
.equ Opening = 2

; слово для подсчета времени на охлаждение транзисторов/мотора

.def lTimeForCool = R24
.def hTimeForCool = R25

.include "isrtable.inc" ; здесь ничего интересного, таймер 0 отрабатывается.

; Константы :-) будем менять здесь, что-бы не рыскать по тексту

.equ _MotorToOff = 100 ; 255 = 16 c половиной секунд
.equ _TimeForCool = 900 ; 1800 = две минуты

;.equ SignaledState = 0x03 ; датчик сработал и маска сколько бит анализировать
;.equ UnSignaledState = 0x00 ; датчик не сработал

SYSRES:
cli
wdr

ldi temp,0x0C
out WDTCR,temp ;Watch DOG on 0.25sec

sbi ACSR,7 ;Comparator Disable

ldi temp,1< out MCUCR,temp

clr temp
out GIMSK,temp ; эти прерывания нас не интересуют

ldi temp, 1< out TIMSK, temp

ldi temp,(1< out DDRA,temp

ser temp ; Все ножки подтянем
out PORTA,temp

ldi temp,(1< out DDRB, temp

ldi temp,~((1<
out PORTB,temp

ldi temp,4 ;SETUP T/C0 (CK/256)~0,066sec 256*256 циклов
out TCCR0,temp

ldi temp,127
out SP,temp

ser temp ;FLAGSs INT OFF
out TIFR,temp

; Обнулим счетчики и фильтры
clr hTimeForCool
clr lTimeForCool
clr MotorToOff

ldi CurentState, Closing ; по включению проверим закрыта ли дверь
sei

; все проинициализировали теперь пусть таймер работает
TheTimeToSleep:
nop
sleep
nop
rjmp TheTimeToSleep
;------------------------------------------------------------
; Таймер о переполнился, прошло 0,065 секунды
OVF_0:
wdr

; трансляция состояния датчиков положения двери
sbic PINA, DoorIsClose
sbi PORTB, StateIsClose
sbis PINA, DoorIsClose
cbi PORTB, StateIsClose

sbic PINB, DoorIsOpen
sbi PORTB, StateIsOpen
sbis PINB, DoorIsOpen
cbi PORTB, StateIsOpen


; проверим, может hardware еще не остыло :-)

tst lTimeForCool
brne WaitCool
tst hTimeForCool
brne WaitCool

rjmp CheckCommands ; считаем что остыло, будем пробовать закрывать, открывать

; декрементируем время паузы на охлаждение
WaitCool:
sbiw lTimeForCool,1
rjmp EndISR


; Теперь анализируем команды, в начале на закрытие потом на открытие
CheckCommands:
sbis PINB, CloseDoor
rjmp MakeCloseDoor

sbis PINB, OpenDoor
rjmp MakeOpenDoor

; или может прошлую команду не доработали ?
cpi CurentState, Closing
breq MakeCloseDoor

cpi CurentState, Opening
breq MakeOpenDoor

; команд нет, а дверца НЕ закрыта ?
; cpi StateClose, SignaledState ; датчик сработал и отфильтрован?
; breq EndISR ; дверца закрыта, уходим по английски не прощаясь :-)

rjmp EndISR ; нет ни команд, ни не оконченных действий

; пытаемся закрыть дверцу


MakeCloseDoor:
; cpi StateClose, SignaledState ; датчик сработал и отфильтрован?
sbic PINA, DoorIsClose
rjmp SuccessMove ; датчик и команда совпадают ничего не надо делать

ldi CurentState, Closing
sbi PORTA,MM ; выберем направление движения
cbi PORTA,MP
rjmp MakeMove ; собственно на обработку включения

MakeOpenDoor:

; cpi StateOpen, SignaledState ; датчик сработал и отфильтрован?
sbic PINB, DoorIsOpen
rjmp SuccessMove ; датчик и команда совпадают ничего не надо делать

ldi CurentState, Opening
cbi PORTA,MM ; выберем направление движения
sbi PORTA,MP
rjmp MakeMove ; собственно на обработку включения

MakeMove:
sbi DDRA,MM ; пустили мотор
sbi DDRA,MP

cpi MotorToOff, 0
breq StartMotorTimer ; Команда только пришла запускаем таймер на выполнения

; команда уже выполняется, проверяем может время вышло и пора отключатся?
dec MotorToOff
brne EndISR ; пока нет, выходим из прерывания

; Ваше время истекло :-(
cbi DDRA,MM
cbi DDRA,MP ; остановили мотор
ldi hTimeForCool, High(_TimeForCool) ; установили задержку для остывания
ldi lTimeForCool, Low(_TimeForCool)
rjmp EndISR

StartMotorTimer:
ldi MotorToOff, _MotorToOff ; максимальное время отработки команды
rjmp EndISR

SuccessMove:
cbi DDRA,MM
cbi DDRA,MP ; остановили мотор
clr MotorToOff ;
ldi CurentState, None
EndISR:
reti


Составить ответ  |||  Конференция  |||  Архив

Ответы



Перейти к списку ответов  |||  Конференция  |||  Архив  |||  Главная страница  |||  Содержание  |||  Без кадра

E-mail: info@telesys.ru