Сб мар 25, 2023 18:01:57
Сб мар 25, 2023 18:04:40
All interrupts have a separate Interrupt Vector in the Interrupt Vector table. The interrupts have priority in accordance with their Interrupt Vector position. The lower the Interrupt Vector address, the higher the priority.
---
ru: Все прерывания имеют отдельный вектор прерывания в таблице векторов прерываний. Прерывания имеют приоритет в соответствии с их положением в векторе прерывания. Чем меньше адрес вектора прерывания, тем выше приоритет.
Сб мар 25, 2023 18:06:44
Сб мар 25, 2023 18:24:02
Сб мар 25, 2023 19:13:03
Сб мар 25, 2023 19:53:05
Сб мар 25, 2023 20:05:02
Сб мар 25, 2023 20:06:48
REGISTER 2-5: PIR1: PERIPHERAL INTERRUPT REQUEST REGISTER 1
...
bit 6 ADIF: A/D Interrupt Flag bit
1 = A/D conversion complete
0 = A/D conversion has not completed or has not been started
...
REGISTER 9-1: ADCON0: A/D CONTROL REGISTER 0
../
bit 1 GO/DONE: A/D Conversion Status bit
1 = A/D conversion cycle in progress. Setting this bit starts an A/D conversion cycle. This bit is automatically cleared by hardware when the A/D conversion has completed.
0 = A/D conversion completed/not in progress
...
Сб мар 25, 2023 20:21:46
Сб мар 25, 2023 20:54:11
Сб дек 09, 2023 08:00:48
Вс янв 07, 2024 18:58:24
;Запись в видео-память возможна в режиме:
;1) фиксированного адреса (команда 0x44): каждый раз сначала передается адрес ячейки памяти, потом байт данных
;2) автоувеличения адреса (команда 0x40): каждый раз сначала передается адрес ячейки памяти, потом несколько байт данных (до 16-ти). Каждый следующий байт пишется в следующую ячейку
;Управление включением-выключеним и яркостью задается командой: 0x80 с параметрами — битами:
;1) Влючение выключание задается установкой/сбросом 3-го бита.
;2) Яркость задается от 0 до 7 — 3-мя младшими битами.
;Запись в видео-память состоит из минимум 2-х байт:
;1) Задает адрес записи (или начала записи, если задан режим автоувеличения адреса): 0xC0 + адрес 0-15.
;2) Собственно байт данных
;Чтение клавиатуры состоит из 3-х этапов:
;1) Отправки команды чтения клавиатуры: 0x42
;2) Не забыть отпустить DIO (setb DIO)
;3) Чтения 32 бит данных
STB equ P2.0
CLK equ P2.1
DIO equ P2.2
Byte equ R7 ; отсылаемый в ТМ1638 байт
Bit_counter equ R6 ; счетчик отправленых или принятых бит
Bit_counter_ equ 6h ; он же, в форме для сохранения в стек
Symbol equ R5 ; порядковый номер выводимого на индикатор числа
Symbol_counter equ R4 ; счетчик выводимых на индикатор чисел, до 8
KeyByte_counter equ R3 ; счетчик примаемых байт состояния клавиатуры, до 4
KeyByte_pointer equ R1 ; указатель на 1 из 4 примаемых байт состояния клавиатуры (подходит только R0 или R1)
KeyByte equ 9h ; байт состояния клавиаутры, установленый байт отвечает нажатой кнопке, после него должны быть свободны еще 3 байта, в которые временно записывается состояние клавиатуры при считывании
Counter equ 8h ; счетчик, показывающий порядковый номер нажатой кнопки (установленого бита в байте KeyByte)
Temp_Counter equ R2 ; временная версия предыдущего счетчика, из которой делается вычетание при сравнении, и содержимое которой соответсвенно портиться при каждом сравнении
Led_State equ 0h ; здесь хранится состояние светодиодов ТМ1638
dseg at 10h
Stack:
cseg at 0
jmp Ini
org 0Bh ; Прерывание по переполнению Timer0
jmp TM1638
TM1638:
push ACC
push Bit_counter_
mov Byte, #01000010b ; Установка режима работы - Чтение клавиатуры
; |||
; ||+-------- Запись в индикатор (0) / Чтение клавиатуры (1)
; |+--------- Автоинкремент адреса (0) / фиксированный адрес (1)
; +---------- Normal Mode (0) / Test Mode (1)
call Send_Byte
setb DIO ; Установим ногу на вход !!!
mov KeyByte_counter,#4 ; Будем читать 4 байта клавиатуры
mov KeyByte_pointer,#KeyByte; Установим указатель на место записи 1 считаного байта
Loop_Receive_All_Keys:
mov Bit_counter,#8 ; Принимаем 8 бит
Loop_Receive_Byte:
clr CLK ; Дергаем клок
rr A ; Прием идет младшим битом вперед, поэтому двигаем вправо
setb CLK ; По фронту клока на DIO получаем бит
jb DIO, Set_Log_1 ; Формируем запихиваемый бит
clr ACC.7
jmp Skip_Set_Log_1
Set_Log_1:
setb ACC.7
Skip_Set_Log_1:
djnz Bit_counter,Loop_Receive_Byte ; Пока не примем 8 бит
mov @KeyByte_pointer,A ; И сохраняем
inc KeyByte_pointer ; Делаем адрес для следующего байта
djnz KeyByte_counter,Loop_Receive_All_Keys ; Принимаем 4 байта
setb STB ; И поднимаем строб - прием закончен
mov A, KeyByte+1 ; А теперь склеим все 4 байта в 1 и получим байт с состоянием всех 8 кнопок
rl A
orl KeyByte,A
mov A, KeyByte+2
rl A
rl A
orl KeyByte,A
mov A, KeyByte+3
rl A
rl A
rl A
orl KeyByte,A ; Склейка байтов в 1 закончена, теперь у нас в KeyByte состояние всех 8 кнопок (но оно инверсное, то есть установленый бит отвечает нажатой кнопке!)
mov Byte, #01000100b ; Вернем прежний режим работы - Запись в индикатор, но уже с фиксированным адресом, чтобы можно было что-то оперативно локально менять, не задевая другое
; |||
; ||+-------- Запись в индикатор (0) / Чтение клавиатуры (1)
; |+--------- Автоинкремент адреса (0) / фиксированный адрес (1)
; +---------- Normal Mode (0) / Test Mode (1)
call Send_Byte
setb STB
pop Bit_counter_
pop ACC
reti
Ini:
mov SP, #Stack
;============== Настройка таймеров и маски прерываний ==========================
mov TMOD, #00000001b ; Режим работы таймеров Т0 и Т1
; ||||||||
; ||||||++-------Режим работы Т0 (01 - 16-бит, 10 - 8-бит с автоперезагрузкой, 11 - 2 независимых 8-бит)
; |||||+---------С/Т0: 0-таймер, 1-счетчик
; ||||+----------: 0-управление по TR0, 1-Управление по TR0 и INT0
; ||++---------- работы Т1 (01 - 16-бит, 10 - 8-бит с автоперезагрузкой, 11 - невозможно)
; |+----------/Т1: 0-таймер, 1-счетчик
; +----------: 0-управление по TR1, 1-управление по TR1 и INT1
mov TCON, #00010000b ; Управление таймерами Т0 и Т1
; ||||||||
; |||||||+-------IT0 - Тип INT0: 0-по уровню, 1-динамический по спаду
; ||||||+--------IE0 - Запрос прерывания INT0 (при IT0=1 автоматически сбрасывается в обработчике)
; |||||+---------IT1 - Тип INT1: 0-по уровню, 1-динамический по спаду
; ||||+---------- - Запрос прерывания INT1 (при IT1=1 автоматически сбрасывается в обработчике)
; |||+---------- - Запуск Т0
; ||+---------- - Флаг переполнения Timer0
; |+---------- - Запуск Т1
; +---------- - Флаг переполнения Timer1
mov IE, #10000010b ; Прерывания
; ||||||||
; |||||||+-------EX0 - разрешение обработки прерываний от внешнего входа INT0
; ||||||+--------ЕТ0 - разрешение обработки прерываний от Timer0
; |||||+---------EX1 - разрешение обработки прерываний от внешнего входа INT1
; ||||+---------- - разрешение обработки прерываний от Timer1
; |||+---------- - разрешение обработки прерываний от посл.порта
; ||+---------- - разрешение обработки прерываний от Timer2
; |+----------, не используеться
; +---------- - разрешение обработки всех прерываний
;============== Настройка TM1638 ============
mov Byte, #01000000b ; Установка режима работы
; |||
; ||+-------- Запись в индикатор (0) / Чтение клавиатуры (1)
; |+--------- Автоинкремент адреса (0) / фиксированный адрес (1)
; +---------- Normal Mode (0) / Test Mode (1)
call Send_Byte
setb STB
mov Byte, #10001000b ; Управление яркостью индикатора
; ||||
; |||+------- Младший бит яркости
; ||+-------- Средний бит яркости
; |+--------- Старший бит яркости
; +---------- Бит включения индикатора
call Send_Byte
setb STB
;============================
; Заполнение индикаторов и светодиодов TM1638 начальными значениями, необходимо, чтобы не выводился мусор, если все должно быть погашено, заполняем нулями
;============================
mov Byte, #11000000b ; Установка начального адреса - (0b - 1 знакоместо дисплея, 1b - LED1, 10b - 1 знакоместо дисплея, 11b - LED2 и т.д.)
; ||||
; |||+------- 1 бит адреса
; ||+-------- 2 бит адреса
; |+--------- 3 бит адреса
; +---------- 4 бит адреса
call Send_Byte ; Адрес шлем без строба
mov Symbol, #1
mov Symbol_counter,#8
Loop_Symbol:
mov DPTR, #Symbol_Table ; Адрес таблицы в DPTR
mov A, Symbol ; Номер символа в АСС
movc A, @A+DPTR ; Достаем символ из таблицы
mov Byte, A ; Запихиваем
call Send_Byte ; и отправляем
inc Symbol ; Следующий символ из таблицы символов
mov Byte, #0 ; Каждый второй байт (последний бит байта) это отдельный светодиод, поэтому просто гасим их
call Send_Byte
djnz Symbol_counter,Loop_Symbol; Шлем 8 бит
setb STB ; А после данных - строб
;============== Главный цикл ==================
mov KeyByte,#0
mov Led_State,#0 ; Установим начальное состояние светодиодов - все выключены
Main:
;============== Процедура преобразования порядкового номера бита в байте в число, соответствующее его порядковому номеру ================
mov A, KeyByte
jz Main ; Если нет нажатыж клавиш, нечего сюда и лезть
mov Counter,#0 ; Обнулим счетчик порядкового номера бита
Loop:
mov Temp_Counter,Counter ; Перенесем счетчик порядкового номера бита во временную переменную
cjne Temp_Counter,#8,Skip ; И проверяем, все ли 8 бит были проверены
jmp Main ; Да, валим в начало (в реальности попадание сюда теоретически невозможно, потому что пустой байт jz Main не пропустит, а выставлений бит кнопки выкинет из цикла до попадания сюда)
Skip:
inc Counter ; Нет, проверяем следующий бит
rr A ; Заталкиваем его в ACC.7
jnb ACC.7, Loop
;============== Здесь мы получаем в Counter число, соответствующее порядковому номеру выставленного в KeyByte бита ====
mov DPTR, #Led_Addr_Table ; Загружаем таблицу адресов светодиодов
mov A, Counter ; Порядковый номер установленого бита - это номер светодиода, состояние котрого мы будем менять
movc A, @A+DPTR ; Берем адрес светодиода
clr EA ; Запрещаем прерывания, чтобы сканирование клавиатуры не мешало отправлять данные
mov Byte, A ; Загружаем адрес свтодиода
call Send_Byte ; И отсылаем (адрес шлем без строба)
;============== Этот кусок определяет, включать, или выключать светодиод в зависимости от его предыдущего состояния ====================
mov A, Led_State ; Загрузим состояние светодиодов
Loop_2:
rr A ; Провернем вправо
djnz Counter,Loop_2 ; Столько раз, сколько насчитали в счетчик порядкого номера установленого бита
jb ACC.7,Led_Off ; Проверим, включен ли текущий светодиод (по логике, нам надо было бы проверять 0 бит, но 1 раз сдвиг мы делаем в любом случае, так что 0 бит переместится в 7, поэтому его и проверяем)
mov Byte,#1 ; Выключен, будем зажигать
jmp Skip_Led_Off
Led_Off:
mov Byte,#0 ; Включен, будем гасить
Skip_Led_Off:
;===========================
call Send_Byte
setb STB ; А после данных - строб
mov A, KeyByte
xrl Led_State,A ; Переключим состояние светодиодов
setb EA
jmp Main
;============== Отправка 1 байта =============
Send_Byte:
mov A, Byte
mov Bit_counter,#8
clr STB
Loop_Send_Byte:
jb ACC.0, Log_1 ; Передача идет младшим битом вперед, поэтому проверяем нулевой бит
clr DIO
jmp Skip_Log_1
Log_1:
setb DIO
Skip_Log_1:
clr CLK
rr A ; Передача идет младшим битом вперед, поэтому двигаем вправо
setb CLK
djnz Bit_counter,Loop_Send_Byte
ret
;============== Таблица символов ==============
Symbol_Table:
db 00111111b ; 0
db 00000110b ; 1
db 01011011b ; 2
db 01001111b ; 3
db 01100110b ; 4
db 01101101b ; 5
db 01111101b ; 6
db 00000111b ; 7
db 01111111b ; 8
db 01101111b ; 9
Led_Addr_Table:
db 0
db 0C1h ; Адрес 1 светодиода
db 0C3h ; Адрес 2 светодиода
db 0C5h ; Адрес 3 светодиода
db 0C7h ; Адрес 4 светодиода
db 0C9h ; Адрес 5 светодиода
db 0CBh ; Адрес 6 светодиода
db 0CDh ; Адрес 7 светодиода
db 0CFh ; Адрес 8 светодиода
end
Сб янв 13, 2024 11:34:29
Чт янв 18, 2024 04:11:23