;Программа регулятора температуры для печи с четырьмя конфорками
;Считаем, что для управления режимами плиты используется биты порта p1 (активный 0)
;11111110b - 0/1 - включить/выключить индикатор нагрева конфорки 1
;11111101b - 0/1 - включить/выключить индикатор нагрева конфорки 2
;11111011b - 0/1 - включить/выключить индикатор нагрева конфорки 3
;11110111b - 0/1 - включить/выключить индикатор нагрева конфорки 4
;11101111b - 0/1 - включить/выключить нагрев нагрев конфорки 1
;11011111b - 0/1 - включить/выключить нагрев нагрев конфорки 2
;10111111b - 0/1 - включить/выключить нагрев нагрев конфорки 3
;01111111b - 0/1 - включить/выключить нагрев нагрев конфорки 4
;режимы порта будем хранить в регистре r7
;посылая r7 в порт P1, отрабатываем режимы для всех конфорок сразу
stack equ 60h ;стек
value equ 30h ;начальный адрес для переменных 30H-33h с ожидаемой
; температурой для каждой из конфорок.
;Предполагаем, что температура в пределах 0-255
work equ 40h ;переменная, необходимая для сравнения температур
key equ 0 ;начальный адрес в памяти (0-3) для считывания состояния
;каждой из четырех ручек,
;(это могут быть физически, например, четыре регистра)
;возможны четыре положения каждой из ручек, которые
;определяются битами D0-D3:
;11111110b - положение 0 - выключить
;11111101b - положение 1 - нагреть условно до 80 градусов
;11111011b - положение 2 - нагреть условно до 100 градусов
;11110111b - положение 3 - нагреть условно до 120 градусов
temp equ 20h ;начальный адрес в памяти (20h-23h) для считывания
; температуры с температурных датчиков.
temp_0 equ 0 ;условные температуры для 4-х положений
temp_1 equ 80
temp_2 equ 100
temp_3 equ 120
;начало программы с адреса 0
mov sp,#stack ;инициируем вершину стека, изначально sp=#7
call init ;все выключаем
main:
mov p1,r7 ;отработать режимы
;читаем положение ручек управления
mov dptr,#key ;начальный адрес для считывания положения ручек
mov r0,#value ;начальный адрес массива переменных, куда запишем ожидаемые
; значения температуры
mov r3,#0feh ;маска для бита в байте режимов (r7)
mov r2,#4 ;счетчик цикла (четыре конфорки)
KeyLoop:
call GetKey ;отработаем для одной конфорки
djnz r4,KeyLoop ;r4=r4-1; циклим, пока r4!=0
;проверяем температуры конфорок
mov dptr,#temp ;начальный адрес для считывания значения термодатчиков
mov r0,#value ;начальный адрес массива переменных, где ожидаемые
; значения температуры
mov r3,#0feh ;маска для бита в байте режимов (r7)
mov r2,#4 ;счетчик цикла (четыре конфорки)
TempLoop:
call GetTemp ;отработаем для одной конфорки
djnz r4,TempLoop ;r4=r4-1; циклим, пока r4!=0
jmp main ;на повтор
;- подпрограммы ------------------------------------------
init: ;начальная инициализация
mov r7,#0ffh ;режимы - все выключить
mov r0,#value ;обнулим, на всякий случай, массив температур
mov r4,#4
init_loop:
mov @r0,#temp_0 ;пишем по адресу в r0 значение temp_0
inc r0 ;на следующий адрес
djnz r4,init_loop ;по всем
ret
;считываем значение положения одной ручки
GetKey:
movx a,@dptr ;читаем память с состоянием ручки
jb acc.0,GK_1 ;если бит D0=1, то проверяем дальше
;положение 0 - выключить
mov @r0,#temp_0 ;запишем значение температуры 0 (на всякий случай)
;по большому счету, это значение не используется,
;положение выключить отрабатывается по-особому,
;но и не помешает...
;для положения 0 гасим индикатор и выключаем обогреватель...
mov a,r3 ;a = маске для включения индикатора (например, 0feh)
swap a ;маска бита в старшей тетраде для обогревателя (0efh)
anl a,r3 ;маска включения для индикатора и обогревателя (0eeh)
cpl a ;маска для выключения (11h)!
orl a,r7 ;выключаем режимы
mov r7,a ;сохраняем
jmp GK_ret ;на выход
GK_1:
jb acc.1,GK_2 ;проверяем бит D1 положения 1, если D1=1, то проверяем дальше
mov @r0,#temp_1 ;значение ожидаемой температуры положения 1
jmp GK_IndOn ;и на общую часть отработки
GK_2:
jb acc.2,GK_3 ;проверяем бит D2 положения 2, если D2=1, то проверяем дальше
mov @r0,#temp_2 ;значение ожидаемой температуры положения 2
jmp GK_IndOn
GK_3:
jb acc.3,GK_ret ;проверяем бит D3 положения 3, если D3=1, то на выход
; (если ничего не встретилось, значит ручка в
; промежуточном состоянии, например, крутится)
mov @r0,#temp_3 ;значение ожидаемой температуры положения 3
;общая часть отработки
GK_IndOn: ;включаем индикацию нагрева
mov a,r7 ;старое состояние
anl a,r3 ;накладываем маску по "и"
mov r7,a ;сохраняем
GK_ret: ;коррекция маски и адресов для следующей конфорки
mov a,r3 ;сдвинем маску
setb c ;чтобы "вдвинуть" единицу
rlc a ;сдвигаем влево на 1 бит, С=1 попадает в младший
mov r3,a ;сохраняем
inc dptr ;адрес состояния ручек
inc r0 ;адрес для хранения значения ожидаемой температуры
ret
;проверяем показания термодатчиков и управляем обогревателями
GetTemp: ;проверим, надо ли управлять обогревателем
mov a,r3 ;маска интересуемой конфорки
orl a,r7 ;"или" с состоянием вкл/выкл индикатора
xrl a,r3 ;xor даст 0, только если оба бита нуля (остальные = 1)
;т.е. нужная конфорка и она должна греть!
jz GT_Temp ; на управление
GT_off: ;выключаем обогреватель
mov a,r3 ;маска конфорки
swap a ;на место управления обогревателем (меняем местами тетрады)
cpl a ;0 -> 1
orl a,r7 ;выключаем
mov r7,a ;сохраняем
jmp GK_ret
GT_Temp: ;управляем
movx a,@dptr ;читаем показание термодатчика в aккумулятор
mov work,@r0 ;читаем ожидаемое значение температуры
cjne a,work,GT_cmp ;сравниваем, != идем на метку
jmp GK_ret ;равно - ничего не делаем
GT_cmp: ;проверим, меньше или больше
jnc GT_off ;если показания термодатчика больше, то выключаем
GT_on: ;если меньше, то включаем
mov a,r3 ;маска конфорки
swap a ;на место управления обогревателем (меняем местами тетрады)
anl a,r7 ;включаем
mov r7,a ;сохраняем
jmp GK_ret ;на коррекцию маски и адресов для следующей конфорки
end
Если Вы уже зарегистрированы на Портале - войдите в систему, если Вы еще не регистрировались - пройдите простую процедуру регистрации.