Код: Выделить всё
--- D:\Docs\Dropbox\Embed\PIC\Projects\Smart_Home\STP_1b\PIC16F84_master_control\Matrix_keyboard_Libs.asm
1: include p16f84.inc
2: include Matrix_keyboard.h
3:
4: Matrix_ketboard_udata udata_shr
5: key_scan res 1
6: key_addr res 1
7: key_char res 1
8: debounce_counter res 1
9:
10: #define Yes_Press flags,0
11:
12: global key_scan,key_char
13: global Matrix_Keyboard_ISR,Init_Matrix_Keyboard,Key_Read,Key_Convert,Release_Key,Anti_Debounce
14: extern flags
15: extern End_Interrupt_Heandler,flags
16:
17: Matrix_keyboard code
18:
19: ;========== Обработчик прерывания по изминению состояния RB7-RB4
20: Matrix_Keyboard_ISR
04D 205D CALL 0x5d 21: call Key_Read ; Было нажатие, считывам кнопку
04E 206E CALL 0x6e 22: call Key_Convert
04F 1410 BSF 0x10, 0 23: bsf Yes_Press ; Установим флаг нажатой кнокпи
050 100B BCF 0xb, 0 24: bcf INTCON,RBIF ; Сбросим флаг вызваного прерывания
051 280F GOTO 0xf 25: goto End_Interrupt_Heandler
26:
27: ;========== Инициализация матричной клавитуры
28: Init_Matrix_Keyboard ; Begin of program
052 0186 CLRF 0x6 29: clrf PORTB ; Предварительно установим разряды столбцов в 0
053 1683 BSF 0x3, 0x5 30: banksel TRISB ; Select Bank 1
054 307F MOVLW 0x7f 31: movlw b'01111111' ; (0<<RBPU) - Enable pull-ups resistors on PortB
055 0581 ANDWF 0x1, F 32: andwf OPTION_REG
33: if (USE_3x4_KEYBOARD)
056 30F1 MOVLW 0xf1 34: movlw b'11110001'
35: else
36: movlw b'11110000'
37: endif
057 0086 MOVWF 0x6 38: movwf TRISB ; Разряды столбцов становятся выходами и опускаються в 0
39:
058 1283 BCF 0x3, 0x5 40: banksel PORTB ; Return Bank 0
059 100B BCF 0xb, 0 41: bcf INTCON,RBIF
05A 3008 MOVLW 0x8 42: movlw (1<<RBIE) ; Разрешам прерывания по изминению состояния порта RB
05B 048B IORWF 0xb, F 43: iorwf INTCON
05C 0008 RETURN 44: return
45:
46: ;========== Опрос клавиатуры. Помещение кода нажалой клавиши в key_scan
47: Key_Read
05D 0806 MOVF 0x6, W 48: movfw PORTB ; Считываем значение PORTB - это код строки
05E 39F0 ANDLW 0xf0 49: andlw b'11110000' ; Зануляем столбцы
05F 0095 MOVWF 0x15 50: movwf key_scan
060 1683 BSF 0x3, 0x5 51: banksel TRISB
52: if (USE_3x4_KEYBOARD)
061 300E MOVLW 0xe 53: movlw b'00001110'
54: else
55: movlw b'00001111'
56: endif
062 0086 MOVWF 0x6 57: movwf TRISB ; Устанавливаем строки выходами, а столбцы - входами
58:
063 1283 BCF 0x3, 0x5 59: banksel PORTB
064 0186 CLRF 0x6 60: clrf PORTB ; Опускаем все строки в 0
065 0806 MOVF 0x6, W 61: movfw PORTB ; Считываем значение PORTB - это код столбца
62: if (USE_3x4_KEYBOARD)
066 390E ANDLW 0xe 63: andlw b'00001110' ; Зануляем строки
64: else
65: andlw b'00001111' ; Зануляем строки
66: endif
067 0495 IORWF 0x15, F 67: iorwf key_scan ; Логическое сложение результата
68: ;---------- Reset keypad interface
068 1683 BSF 0x3, 0x5 69: banksel TRISB
70: if (USE_3x4_KEYBOARD)
069 30F1 MOVLW 0xf1 71: movlw b'11110001'
72: else
73: movlw b'11110000'
74: endif
06A 0086 MOVWF 0x6 75: movwf TRISB ; Возвращаем строки - как входы, а столбцы - как выходы
76:
06B 1283 BCF 0x3, 0x5 77: banksel PORTB
06C 0186 CLRF 0x6 78: clrf PORTB ; Гарантируем 0 выходные значения
06D 0008 RETURN 79: return
80:
81: ;========== Преобразование кода клавиши, содержащегося в key_scan, в ASCII код, и запись этого кода в key_char
82: Key_Convert
06E 1003 BCF 0x3, 0 83: clrc
06F 0196 CLRF 0x16 84: clrf key_addr
85: ;---------- Сперва определяем строку
070 1B95 BTFSC 0x15, 0x7 86: btfsc key_scan,7
071 2873 GOTO 0x73 87: goto kp1
072 2884 GOTO 0x84 88: goto col_find ; Если строка 1, key_scan без изминений
073 1B15 BTFSC 0x15, 0x6 89: kp1 btfsc key_scan,6
074 2878 GOTO 0x78 90: goto kp2
075 3004 MOVLW 0x4 91: movlw .4
076 0496 IORWF 0x16, F 92: iorwf key_addr ; Если строка 2, порядковый номер нажатой кнопки как минимум 3(4)
077 2884 GOTO 0x84 93: goto col_find
078 1A95 BTFSC 0x15, 0x5 94: kp2 btfsc key_scan,5
079 287D GOTO 0x7d 95: goto kp3
07A 3008 MOVLW 0x8 96: movlw .8
07B 0496 IORWF 0x16, F 97: iorwf key_addr ; Если строка 3, порядковый номер нажатой кнопки как минимум 6(8)
07C 2884 GOTO 0x84 98: goto col_find
07D 1A15 BTFSC 0x15, 0x4 99: kp3 btfsc key_scan,4
07E 2882 GOTO 0x82 100: goto kp4
07F 300C MOVLW 0xc 101: movlw .12
080 0496 IORWF 0x16, F 102: iorwf key_addr ; Если строка 4, порядковый номер нажатой кнопки как минимум 9(12)
081 2884 GOTO 0x84 103: goto col_find
104: kp4
082 3010 MOVLW 0x10 105: movlw .16
083 288E GOTO 0x8e 106: goto keypad_op ; Строка не распознана, возврат с кодом ошибки (E) через таблицу
107: col_find ; Теперь определяем столбец
084 1995 BTFSC 0x15, 0x3 108: btfsc key_scan,3
085 2887 GOTO 0x87 109: goto cf1
086 288E GOTO 0x8e 110: goto keypad_op ; Если столбец 1, key_scan без изминений
087 1915 BTFSC 0x15, 0x2 111: cf1 btfsc key_scan,2
088 288C GOTO 0x8c 112: goto cf2
089 3001 MOVLW 0x1 113: movlw .1
08A 0496 IORWF 0x16, F 114: iorwf key_addr ; Если столбец 2, порядковый номер нажатой кнопки надо увеличить на 1
08B 288E GOTO 0x8e 115: goto keypad_op
116: cf2
117: if (!USE_3x4_KEYBOARD)
118: btfsc key_scan,1
119: goto cf3
120: endif
08C 3002 MOVLW 0x2 121: movlw .2
08D 0496 IORWF 0x16, F 122: iorwf key_addr ; Если столбец 3, порядковый номер нажатой кнопки надо увеличить на 2
123: if (!USE_3x4_KEYBOARD)
124: goto keypad_op
125: cf3 movlw .3
126: iorwf key_addr ; Если столбец 3, порядковый номер нажатой кнопки надо увеличить на 3
127: endif
128: keypad_op
08E 0816 MOVF 0x16, W 129: movfw key_addr
08F 2092 CALL 0x92 130: call Key_Table
090 0097 MOVWF 0x17 131: movwf key_char ; сохраняем ASCII код нажатой кнопки
091 0008 RETURN 132: return
133:
134: ;========== Таблица преобразования кода клавиши в ASCII код символа
135: Key_Table
092 0782 ADDWF 0x2, F 136: addwf PCL
093 3431 RETLW 0x31 137: dt "123A456B789C*0#DE"
094 3432 RETLW 0x32
095 3433 RETLW 0x33
096 3441 RETLW 0x41
097 3434 RETLW 0x34
098 3435 RETLW 0x35
099 3436 RETLW 0x36
09A 3442 RETLW 0x42
09B 3437 RETLW 0x37
09C 3438 RETLW 0x38
09D 3439 RETLW 0x39
09E 3443 RETLW 0x43
09F 342A RETLW 0x2a
0A0 3430 RETLW 0x30
0A1 3423 RETLW 0x23
0A2 3444 RETLW 0x44
0A3 3445 RETLW 0x45
138:
139: ;========== Подпрограмма ожидания отпускания кнопки
140: Release_Key ; Крутимся в цикле и опрашиваем состояние кнопок, пока все не будут отпущены
0A4 205D CALL 0x5d 141: call Key_Read
0A5 0815 MOVF 0x15, W 142: movfw key_scan
143: if (USE_3x4_KEYBOARD)
0A6 39FE ANDLW 0xfe 144: andlw b'11111110' ; Подавляем RB0
0A7 3CFE SUBLW 0xfe 145: sublw b'11111110' ; Проверка на неактивность
146: else
147: sublw b'11111111' ; Проверка на неактивность
148: endif
0A8 1D03 BTFSS 0x3, 0x2 149: btfss STATUS,Z
0A9 28A4 GOTO 0xa4 150: goto Release_Key
0AA 0008 RETURN 151: return
152:
153: ;========== Подпрограмма антидребезговой задержки
154: Anti_Debounce
0AB 0198 CLRF 0x18 155: clrf debounce_counter
156: Loop_Anti_Debounce
0AC 0B98 DECFSZ 0x18, F 157: decfsz debounce_counter
0AD 28AC GOTO 0xac 158: goto Loop_Anti_Debounce
0AE 0008 RETURN 159: return
--- D:\Docs\Dropbox\Embed\PIC\Projects\Smart_Home\STP_1b\PIC16F84_master_control\PIC16F84_master_control.asm
1: list p=16f84
2: __config _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
3: include p16f84.inc
4: include Soft_UART_Lib_use_Timer0.h
5: include Matrix_keyboard.h
6: include Macro.h
7:
8: PIC16F84_Master_Control udata_shr
9: w_temp res 1
10: status_temp res 1
11: command res 1
12: num_of_module res 1
13: flags res 1
14:
15: #define Yes_Press flags,0
16:
17: extern TX_byte,RX_byte,UART_counter,delay_counter,key_scan,key_char
18: extern Ini_UART,Send_TX_byte,Delay_1bit,Start_bit,Receive_bit,Get_RX_byte,Init_Matrix_Keyboard,Key_Read,Key_Convert,Release_Key,Anti_Debounce,Matrix_Keyboard_ISR
19: global flags
20: global End_Interrupt_Heandler
21: ;======================
22: RESET_VECTOR code 0h
000 2815 GOTO 0x15 23: goto Ini
24: ;======================
25: ISR code 4h ; Вектор прерывания
26: Interrupt_Heandler
004 008C MOVWF 0xc 27: push ; Сохраним контекст
005 0E03 SWAPF 0x3, W
006 008D MOVWF 0xd
007 180B BTFSC 0xb, 0 28: btfsc INTCON,RBIF
008 284D GOTO 0x4d 29: goto Matrix_Keyboard_ISR
009 280B GOTO 0xb 30: goto UART_Receive ; Проверяем в последнюю очередь, потому что UART программный, и спец флага прерыванию у него нет
00A 280F GOTO 0xf 31: goto End_Interrupt_Heandler
32:
33: UART_Receive
34: if (USE_T0CKI)
00B 1683 BSF 0x3, 0x5 35: banksel OPTION_REG ; Bank 1
00C 1E81 BTFSS 0x1, 0x5 36: btfss OPTION_REG,T0CS ; Проверим источник тактирования таймера
00D 28C1 GOTO 0xc1 37: goto Receive_bit ; Если внутренний - это очередной бит
00E 28B9 GOTO 0xb9 38: goto Start_bit ; Если внешний - мы ждали старт-бит
39: else
40: btfss INTCON,INTE
41: goto Receive_bit ; Если запрещено внешнее прерывание - это очередной бит
42: goto Start_bit ; Если разрешено внешнее прерывание - мы ждали старт-бит
43: endif
44:
45: End_Interrupt_Heandler
46: if (!USE_T0CKI)
47: bcf INTCON,INTF ; Сбросим флаг внешнего прерывания
48: endif
00F 110B BCF 0xb, 0x2 49: bcf INTCON,T0IF ; Сбросим флаг переполнения Таймера 0
010 0E0D SWAPF 0xd, W 50: pop ; Восстановим контекст
011 0083 MOVWF 0x3
012 0E8C SWAPF 0xc, F
013 0E0C SWAPF 0xc, W
014 0009 RETFIE 51: retfie
52:
53: Ini
015 0190 CLRF 0x10 54: clrf flags
016 2052 CALL 0x52 55: call Init_Matrix_Keyboard
017 20CF CALL 0xcf 56: call Ini_UART ; Инициализация программного UART после инициализации матричной клавиатуры, потому что можем использовать RB0
57:
58: Main
59: ; call Get_RX_byte
60: ; incf RX_byte
61: ; movfw RX_byte
018 3055 MOVLW 0x55 62: movlw b'01010101'
019 20DC CALL 0xdc 63: call Send_TX_byte
01A 20AB CALL 0xab 64: call Anti_Debounce
01B 2818 GOTO 0x18 65: goto Main
66:
01C 1C10 BTFSS 0x10, 0 67: btfss Yes_Press ; Если не было нажатия, крутимся в цикле
01D 2818 GOTO 0x18 68: goto Main
01E 138B BCF 0xb, 0x7 69: bcf INTCON,GIE ; Будем передавать символ, запрещаем прерывания
01F 0817 MOVF 0x17, W 70: movfw key_char
020 20DC CALL 0xdc 71: call Send_TX_byte ; Отправим символ
72: ;---------- Антидребезговый комплекс из задержек и опросов состояния кнопок
021 20A4 CALL 0xa4 73: call Release_Key ; Ждем отпускания всех кнопок
022 20AB CALL 0xab 74: call Anti_Debounce ; Антидребезговая задержка
023 20A4 CALL 0xa4 75: call Release_Key ; Ждем отпускания всех кнопок
024 20AB CALL 0xab 76: call Anti_Debounce ; Антидребезговая задержка
025 20A4 CALL 0xa4 77: call Release_Key ; Ждем отпускания всех кнопок
78: ;---------- Конец антидребезгового комплекса
026 1010 BCF 0x10, 0 79: bcf Yes_Press ; Обработали нажатие, сбросим флаг
027 100B BCF 0xb, 0 80: bcf INTCON,RBIF ; Сбросим флаг возможно прошедшего прерывания
028 178B BSF 0xb, 0x7 81: bsf INTCON,GIE ; Закончили передачу символа, разрешаем прерывания
029 2818 GOTO 0x18 82: goto Main
83:
84: Wait_Num_of_Module ; Первая нажатая кнопка - это номер модуля
02A 1C10 BTFSS 0x10, 0 85: btfss flags,0 ; Если не было нажатия, крутимся в цикле
02B 282A GOTO 0x2a 86: goto Wait_Num_of_Module
02C 138B BCF 0xb, 0x7 87: bcf INTCON,GIE ; Запрещаем повторные прерывания по дребезгу
02D 0817 MOVF 0x17, W 88: movfw key_char
02E 390F ANDLW 0xf 89: andlw b'00001111'
02F 008F MOVWF 0xf 90: movwf num_of_module
91: ;---------- Антидребезговый комплекс из задержек и опросов состояния кнопок
030 20A4 CALL 0xa4 92: call Release_Key ; Ждем отпускания всех кнопок
031 20AB CALL 0xab 93: call Anti_Debounce ; Антидребезговая задержка
032 20A4 CALL 0xa4 94: call Release_Key ; Ждем отпускания всех кнопок
033 20AB CALL 0xab 95: call Anti_Debounce ; Антидребезговая задержка
034 20A4 CALL 0xa4 96: call Release_Key ; Ждем отпускания всех кнопок
97: ;---------- Конец антидребезгового комплекса
035 1010 BCF 0x10, 0 98: bcf flags,0 ; Обработали нажатие, сбросим флаг
036 100B BCF 0xb, 0 99: bcf INTCON,RBIF ; Сбросим флаг возможно прошедшего прерывания
037 178B BSF 0xb, 0x7 100: bsf INTCON,GIE ; Закончили передачу символа, разрешаем прерывания
101: Wait_Command ; Вторая нажатая кнопка - это команда
038 1C10 BTFSS 0x10, 0 102: btfss flags,0 ; Если не было нажатия, крутимся в цикле
039 2838 GOTO 0x38 103: goto Wait_Command
03A 138B BCF 0xb, 0x7 104: bcf INTCON,GIE ; Будем передавать символ, запрещаем прерывания
03B 0817 MOVF 0x17, W 105: movfw key_char
03C 390F ANDLW 0xf 106: andlw b'00001111'
03D 008E MOVWF 0xe 107: movwf command ; Сформируем команду
03E 0E0E SWAPF 0xe, W 108: swapf command,w ; Пепреместим команду в старшую тетраду
03F 048F IORWF 0xf, F 109: iorwf num_of_module ; И наложим маской на номер модуля
110: ; Получаем на выходе номер модуля (младшая тетрада) и переключаемый выход (старшая тетрада)
040 080F MOVF 0xf, W 111: movfw num_of_module ; Берем полученую составную команду
041 20DC CALL 0xdc 112: call Send_TX_byte ; И отправляем в сеть
113: ;---------- Антидребезговый комплекс из задержек и опросов состояния кнопок
042 20A4 CALL 0xa4 114: call Release_Key ; Ждем отпускания всех кнопок
043 20AB CALL 0xab 115: call Anti_Debounce ; Антидребезговая задержка
044 20A4 CALL 0xa4 116: call Release_Key ; Ждем отпускания всех кнопок
045 20AB CALL 0xab 117: call Anti_Debounce ; Антидребезговая задержка
046 20A4 CALL 0xa4 118: call Release_Key ; Ждем отпускания всех кнопок
119: ;---------- Конец антидребезгового комплекса
047 1010 BCF 0x10, 0 120: bcf flags,0
048 100B BCF 0xb, 0 121: bcf INTCON,RBIF ; Сбросим флаг возможно прошедшего прерывания
049 178B BSF 0xb, 0x7 122: bsf INTCON,GIE ; Закончили передачу символа, разрешаем прерывания
123: ; goto Wait_Num_of_Module
124:
04A 20AF CALL 0xaf 125: call Get_RX_byte ; Принимаем ответ (зациклимся в ожидании)
126: ; movfw RX_byte ; Засунем принятый байт в рабочий регистр
127: ; И анализируем ответ
04B 080F MOVF 0xf, W 128: movfw num_of_module
04C 0212 SUBWF 0x12, W 129: subwf RX_byte,w
130:
2007 2BFF GOTO 0x3ff 131: end
--- D:\Docs\Dropbox\Embed\PIC\Projects\Smart_Home\STP_1b\PIC16F84_master_control\Soft_UART_Lib_use_Timer0.asm
1: include Soft_UART_Lib_use_Timer0.h
2:
3: ; В прерывании только прием байта (побитно), и выставление флага окончания приема, который уже анализируется в основном цикле
4: ;======================
5: Soft_UART udata_shr
6: TX_byte res 1
7: RX_byte res 1
8: UART_counter res 1
9: delay_counter res 1
10:
11: global TX_byte,RX_byte,UART_counter,delay_counter
12: global Ini_UART,Send_TX_byte,Delay_1bit,Start_bit,Receive_bit,Get_RX_byte
13:
14: extern End_Interrupt_Heandler
15: ;======================
16: SOFT_UART code
17: ;======================
18: Get_RX_byte
19: if (!USE_T0CKI) ; Если используем INT, есть возможность поспать
20: sleep
21: nop
22: endif
0AF 3000 MOVLW 0 23: movlw 0
0B0 0213 SUBWF 0x13, W 24: subwf UART_counter,w
0B1 1903 BTFSC 0x3, 0x2 25: btfsc STATUS,Z ; Дожидаемся начала приема
0B2 28AF GOTO 0xaf 26: goto Get_RX_byte
27: Loop_Get_RX_byte
0B3 3000 MOVLW 0 28: movlw 0
0B4 0213 SUBWF 0x13, W 29: subwf UART_counter,w
0B5 1D03 BTFSS 0x3, 0x2 30: btfss STATUS,Z ; Дожидаемся окончания приема
0B6 28B3 GOTO 0xb3 31: goto Loop_Get_RX_byte
32: if (USE_ONE_PIN)
0B7 2101 CALL 0x101 33: call Delay_1bit ; Ожидаем завершения приема
34: endif
35: Wait_Receive_complete
36: ; btfss RX ; Ожидаем стоп бит
37: ; goto Wait_Receive_complete
0B8 0008 RETURN 38: return ; Байт принят
39: ;======================
40: Start_bit
41: if (USE_T0CKI)
0B9 1281 BCF 0x1, 0x5 42: bcf OPTION_REG,T0CS ; Устанавливаем тактирование Таймера 0 от внутреннего генератора
0BA 1283 BCF 0x3, 0x5 43: banksel TMR0 ; Bank 0
0BB 3080 MOVLW 0x80 44: movlw .128 ; Перезапишем таймер для периода переполнения в 156 мкс (середина 1 бита данных)
45: else
46: movlw .123 ; Перезапишем таймер для периода переполнения в 156 мкс (середина 1 бита данных)
47: endif
0BC 0081 MOVWF 0x1 48: movwf TMR0
0BD 3008 MOVLW 0x8 49: movlw .8 ; Загрузим количество принимаемых битов
0BE 0093 MOVWF 0x13 50: movwf UART_counter
0BF 0192 CLRF 0x12 51: clrf RX_byte ; Очистим приемник
52: if (!USE_T0CKI)
53: bcf INTCON,INTE ; Запрещаем внешнее прерывание (4 бит)
54: bsf INTCON,T0IE ; Разрешаем прерывание по переполнению Таймера 0 (5 бит)
55: endif
0C0 280F GOTO 0xf 56: goto End_Interrupt_Heandler
57: ;======================
58: Receive_bit
59: if (USE_T0CKI)
0C1 1283 BCF 0x3, 0x5 60: banksel TMR0 ; Bank 0
0C2 30A6 MOVLW 0xa6 61: movlw .166 ; Перезапишем таймер для периода переполнения в 104 мкс
62: else
63: movlw .164 ; Перезапишем таймер для периода переполнения в 104 мкс
64: endif
0C3 0081 MOVWF 0x1 65: movwf TMR0
0C4 1003 BCF 0x3, 0 66: bcf STATUS,C ; Сбросим бит переноса
0C5 0C92 RRF 0x12, F 67: rrf RX_byte ; Задвигаем сброшеный бит переноса в приемный регистр
0C6 1A05 BTFSC 0x5, 0x4 68: btfsc RX ; А теперь проверяем, что на самом деле надо было туда задвинуть
0C7 1792 BSF 0x12, 0x7 69: bsf RX_byte,7 ; Если 1, надо срочно подкорректировать, ведь мы задвинули 0
0C8 0B93 DECFSZ 0x13, F 70: decfsz UART_counter ; Весь байт принят ?
0C9 280F GOTO 0xf 71: goto End_Interrupt_Heandler ; Нет, идем принимать следующий бит
72: if (USE_T0CKI)
0CA 30FF MOVLW 0xff 73: movlw .255 ; Перезапишем таймер для переполнения при приходе старт-бита
0CB 0081 MOVWF 0x1 74: movwf TMR0
0CC 1683 BSF 0x3, 0x5 75: banksel OPTION_REG ; Bank 1
0CD 1681 BSF 0x1, 0x5 76: bsf OPTION_REG,T0CS ; Устанавливаем тактирование Таймера 0 от внешнего источника, чтобы словить следующий старт-бит
77: else
78: bcf INTCON,T0IE ; Запрещаем прерывание по переполнению Таймера 0 (5 бит)
79: bsf INTCON,INTE ; Разрешаем внешнее прерывание (4 бит) для приема следующего старт-бита
80: endif
0CE 280F GOTO 0xf 81: goto End_Interrupt_Heandler ; На выход
82: ;======================
83: Ini_UART
0CF 3010 MOVLW 0x10 84: bsf_TX ; Заранее установим TX
0D0 0485 IORWF 0x5, F
0D1 1683 BSF 0x3, 0x5 85: banksel OPTION_REG ; Bank 1
86: if (USE_PIC12)
87: call 3FFh
88: movwf OSCCAL
89: endif
90:
91: if (!USE_ONE_PIN)
92: bcf_TX ; Настроим TX на выход
93: endif
94:
95: if (USE_T0CKI)
0D2 3038 MOVLW 0x38 96: movlw b'00111000' ; Подтягивающие резисторы включены (для матричной клавиатуры), тактирование Таймера 0 от внешнего источника, инкремент по заднему фронту, пределитель для WD
97: else
98: movlw b'00001000' ; Подтягивающие резисторы включены (для матричной клавиатуры), внешнее прерывание по заднему фронту, тактирование Таймера 0 от внутреннего генератора, пределитель для WD
99: endif
0D3 0081 MOVWF 0x1 100: movwf OPTION_REG
0D4 1283 BCF 0x3, 0x5 101: banksel INTCON ; Bank 0
102:
103: if (USE_PIC12)
104: movlw b'00000111'
105: movwf CMCON ; Выключим аналоговый компаратор
106: endif
107:
0D5 3000 MOVLW 0 108: movlw .0 ; Инициализируем счетчик принятых битов для определения момена начала и конца приема байта в подпрограмме Get_RX_byte
0D6 0093 MOVWF 0x13 109: movwf UART_counter
110:
111: if (USE_T0CKI)
0D7 30FF MOVLW 0xff 112: movlw .255 ; Перезапишем таймер для переполнения при приходе старт-бита
0D8 0081 MOVWF 0x1 113: movwf TMR0
0D9 30A0 MOVLW 0xa0 114: movlw (1<<GIE)|(1<<T0IE) ; Разрешаем прерывания вообще (7 бит) и прерывание по переполнению таймера (5 бит)
115: else
116: movlw (1<<GIE)|(1<<INTE) ; Разрешаем прерывания вообще (7 бит) и внешнее прерывание (4 бит)
117: endif
0DA 048B IORWF 0xb, F 118: iorwf INTCON
0DB 0008 RETURN 119: return
120: ;======================
121: Send_TX_byte ; Подпрограмма передачи 1 байта
0DC 138B BCF 0xb, 0x7 122: bcf INTCON,GIE ; Запрещаем прерывания
123: ; bsf_TX ; Предварительно установим TX
0DD 1605 BSF 0x5, 0x4 124: bsf TX ; Предварительно установим TX
125:
126: if (USE_ONE_PIN)
0DE 1683 BSF 0x3, 0x5 127: banksel OPTION_REG ; Bank 1
128: ; bcf_TX ; Настроим TX на выход
0DF 1205 BCF 0x5, 0x4 129: bcf TX
0E0 1283 BCF 0x3, 0x5 130: banksel INTCON ; Bank 0
131: endif
132:
133: ;-----------------------------------------------------------------------------------------------
134: ; bcf_TX ; Шлем старт бит
0E1 1205 BCF 0x5, 0x4 135: bcf TX ; Шлем старт бит
0E2 0091 MOVWF 0x11 136: movwf TX_byte ; Загрузим передавемый байт
0E3 3008 MOVLW 0x8 137: movlw .8 ; Загрузим количество передаваемых битов
0E4 0093 MOVWF 0x13 138: movwf UART_counter
0E5 0000 NOP 139: nop
140: Transmit_Next_Bit
0E6 0000 NOP 141: nop
0E7 2101 CALL 0x101 142: call Delay_1bit ; Длинной 1 бит
0E8 0C91 RRF 0x11, F 143: rrf TX_byte ; Продвигаем в бит переноса все биты, начиная с младшего
0E9 1803 BTFSC 0x3, 0 144: btfsc STATUS,C ; Проверяем, что выдавилось в бит переноса
145: ; bsf_TX ; Если 1, выставляем 1 на ТХ
0EA 1605 BSF 0x5, 0x4 146: bsf TX ; Если 1, выставляем 1 на ТХ
0EB 1C03 BTFSS 0x3, 0 147: btfss STATUS,C
148: ; bcf_TX ; Если 0, выставляем 0 на ТХ
0EC 1205 BCF 0x5, 0x4 149: bcf TX ; Если 0, выставляем 0 на ТХ
0ED 0B93 DECFSZ 0x13, F 150: decfsz UART_counter ; Весь байт отослан ?
0EE 28E6 GOTO 0xe6 151: goto Transmit_Next_Bit ; Нет, идем слать следующий бит
0EF 2101 CALL 0x101 152: call Delay_1bit ; Задержка длинной 1 бит
0F0 0000 NOP 153: nop
0F1 0000 NOP 154: nop
0F2 0000 NOP 155: nop
0F3 0000 NOP 156: nop
0F4 0000 NOP 157: nop
0F5 3010 MOVLW 0x10 158: bsf_TX ; Шлем стоп-бит
0F6 0485 IORWF 0x5, F
0F7 2101 CALL 0x101 159: call Delay_1bit ; Задержка длинной 1 бит
160: ;-----------------------------------------------------------------------------------------------
161: if (USE_ONE_PIN)
0F8 1683 BSF 0x3, 0x5 162: banksel OPTION_REG ; Bank 1
0F9 3010 MOVLW 0x10 163: bsf_TX ; Настроим ножку на вход
0FA 0485 IORWF 0x5, F
0FB 1283 BCF 0x3, 0x5 164: banksel INTCON ; Вернем Bank 0
165: endif
166:
167: if (USE_T0CKI)
0FC 30FF MOVLW 0xff 168: movlw .255 ; Перезапишем таймер для переполнения при приходе старт-бита
0FD 0081 MOVWF 0x1 169: movwf TMR0
170: else
171: bcf INTCON,INTF ; Сбросим флаг внешнего прерывания
172: endif
0FE 110B BCF 0xb, 0x2 173: bcf INTCON,T0IF ; Сбросим флаг переполнения Таймера 0
0FF 178B BSF 0xb, 0x7 174: bsf INTCON,GIE ; Разрешаем прерывания
100 0008 RETURN 175: return
176: ;======================
177: Delay_1bit
101 301E MOVLW 0x1e 178: movlw BITS_DELAY ; 104 мкс для 9600 бод
102 0094 MOVWF 0x14 179: movwf delay_counter
180: Loop_Delay
103 0B94 DECFSZ 0x14, F 181: decfsz delay_counter
104 2903 GOTO 0x103 182: goto Loop_Delay
105 0008 RETURN 183: return