list p=16f628 ; list directive to define processor #include ; processor specific variable definitions __CONFIG 03F10H ; ;13 - CP1 1 защита памяти программ выключена ;12 - CP0 1 (СР1 = СР0 = 1) ;11 - CP1 1 ;10 - CP0 1 ;09 - 1 не реализован , читается как 1 ;08 - CPD 1 защита памяти данных выключена ;07 - LVP 0 режим низковольтного программирования выключен, RB4 порт вв\выв ;06 - BODEN 0 сброс по снижению напряжения питания выключен ;05 - MCLRE 0 внутренний сброс MCLR, RA5 порт вв\выв ;04 - FOSC2 1 режим работы тактового генератора (внутренний RC генератор) ;03 - PWRTE 0 таймер по включению питания работает ;02 - WDTE 0 таймер WDT отключен ;01 - FOSC1 0 режим работы тактового генератора (RA6 и RA7 порты вв\выв) ;00 - FOSC0 0 режим работы тактового генератора (RA6 и RA7 порты вв\выв) ; Программа управления контактной сваркой - таймер + рег-ка фазы имп/ + кол-во имп. ; Вывод информации на 8-разр/ индикатор с последовательным выводом MAX7219(3 линии) ; Кнопки "Вправо" - "Влево" для выбора разряда индикатора, который нужно измененить ; Кнопки "Больше" - "Меньше" для изменения выбранного разряда ; Кнопка "Пуск" - для запуска процесса сварки ; Детектор перехода через ноль и управление силовым симистором типа BTA41-600 ; Время паузы между импульсами фиксированное Cblock 20h ; Блок данных в банке 0 adr_ind ; адрес выводимого индикатора dat_ind ; данные на индикатор contbyte ; количество байт на вывод contbit ; количество бит на вывод adr_tmp ; временная ячейка при выводе адреса dat_tmp ; временная ячейка при выводе данных tmp0 ; временная ячейка в паузах tmp1 ; временная ячейка в паузах time_block ; память кол-ва циклов блокировки time_save ; счетчик циклов отпущенных кнопок time_pwr ; счетчик для угла задержки открытия tmp_pwr ; временная ячейка time_pwr time_cicl ; база времени цикла программы - кратно циклам таймера задержки time_delay ; база времени таймера задержки - кратно 10-и циклам контроллера pos_ind ; позиция текущего индикатора cont_imp ; счетчик импульсов в режиме сварки t_imp_s ; значение времени импульса в разряде секунд (старший) t_imp_s1 ; значение времени импульса в разряде десятых долей секунд(средний) t_imp_s2 ; значение времени импульса в разряде сотых долей секунд (младший) t_paus_s ; значение времени паузы в разряде секунд (старший) t_paus_s1 ; значение времени паузы в разряде десятых долей секунд (средний) t_paus_s2 ; значение времени паузы в разряде сотых долей секунд (младший) det_cont0 ; счетчик контроля нулевых импульсов сети det_time ; счетчик времени проверки сигнала импульсов сети t_i_s_tmp ; временная ячейка t_imp_s t_i_s1_tmp ; временная ячейка t_imp_s1 t_i_s2_tmp ; временная ячейка t_imp_s2 t_p_s_tmp ; временная ячейка t_paus_s t_p_s1_tmp ; временная ячейка t_paus_s1 t_p_s2_tmp ; временная ячейка t_paus_s2 t_imp_out1 ; время управления открытием симистора tmp_out1 ; временная ячейка t_imp_out1 MemBit1 ; биты MemBit2 ; биты MemBit3 ; биты endc ; блок данных доступный из всех банков памяти Byte0 equ 70h ; младший байт Byte1 equ 71h ; Byte2 equ 72h ; Byte3 equ 73h ; Byte4 equ 74h ; Byte5 equ 75h ; Byte6 equ 76h ; Byte7 equ 77h ; старший байт AdrWr equ 78h ; адрес ячейки для записи данных DataWr equ 79h ; данные для записи в память AdrRd equ 7Ah ; адрес ячейки для чтения данных DataRd equ 7Bh ; данные для чтения из памяти ind_ROM equ 7Ch ; указатель на начальную ячейку чтения\записи из EEPROM ind_PWR equ 7Dh ; указатель на начало таблицы мощности в EEPROM ;**** Входы-Выходы ************ #define clk PORTA,1 ; выход частоты на индикатор (18н.) #define cs PORTA,0 ; разрешение записи на индикатор (17н.) #define din PORTA,7 ; выход данных на индикатор (16н.) #define InStart PORTB,0 ; вход кнопки Старт (6н.) #define InDet PORTB,1 ; вход детектора сети (7н.) #define InLeft PORTB,2 ; вход выбора установки - влево (8н.) #define InUp PORTB,3 ; вход установки - больше (9н.) #define InRight PORTB,4 ; вход установки - вправо (10н.) #define InDown PORTB,5 ; вход выбора установки - меньше (11н.) #define Out1 PORTB,6 ; выход управляющий на симистором (12н.) #define Out2 PORTB,7 ; выход дублирующий на светодиод (13н.) ;****Биты памяти******************** #define m1.0 MemBit1,0 ; #define BlInd MemBit1,1 ; индикация состояния блокировки #define First_Cicl MemBit1,2 ; бит первого цикла опроса, устранение дребезга #define InCycle MemBit1,3 ; бит запуска процесса сварки ; #define InProg MemBit1,4 ; бит нахождения в режиме программирования #define m15 MemBit1,5 ; #define addPoint MemBit1,6 ; бит включения в разряде десятичной точки #define pwr_ok MemBit1,7 ; уровень pwr в норме перед запуском #define end_scan MemBit2,0 ; окончено сканирование детектора сети #define mod_man MemBit2,1 ; бит ручного режима (кол-во импульсов в программе = 0) #define cont1_imp MemBit2,2 ; отсчет одного импульса из времени сварки на 10мс #define cnt_imp_end MemBit2,3 ; импульс выведен #define cnt_p_end MemBit2,4 ; пауза отсчитана #define cnt_del_pwr MemBit2,5 ; задержка угла открытия отработана #define cnt_out1 MemBit2,6 ; длит-ть импульса управления на симистор отработана #define st_del_pwr MemBit2,7 ; старт отработки импульса задержки pwr #define m30 MemBit3,0 ; #define m31 MemBit3,1 ; #define m32 MemBit3,2 ; #define m33 MemBit3,3 ; #define m34 MemBit3,4 ; #define m35 MemBit3,5 ; #define m36 MemBit3,6 ; #define m37 MemBit3,7 ; ;************************ ;;; первичная загрузка данных ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ORG 0x2100 ; инициализации ячеек EEPROM контроллера DE 0FH, 0FH, 0FH, 0FH, 00H, 03H, 00H, 0AH ;00 на индикатор "-" время паузы DE 07H, 0FH, 01H, 0FH, 00H, 02H, 00H, 0DH ;08 на индикатор "L" мин настройки DE 09H, 0FH, 01H, 0FH, 00H, 03H, 00H, 0BH ;10 на индикатор "E" станд настр DE 09H, 0FH, 02H, 0FH, 00H, 05H, 00H, 0CH ;18 на индикатор "H" мах настройки DE 09H, 0FH, 0FH, 0FH, 0FH, 0FH, 0FH, 0EH ;20 на индикатор "P" ручной режим DE 00H, 00H, 00H, 00H, 00H, 00H, 00H, 00H ;28 DE 28H, 24H, 21H, 1EH, 1BH, 17H, 13H, 0FH ;30 таблица углов задержек 9max - 0min DE 0AH, 05H, 00H, 00H, 00H, 00H, 00H, 00H ;38 подбирается примерно(кратно 100мкс) ;для мощности 0 - примерно 30% мощности ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Вектор сброса микропроцессора ORG 0x000 ; вектор сброса контроллера goto init_pic ; инициализация контроллера ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Вектор обработки прерываний ORG 0x004 ; обработка вектора прерывания retfie ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Основная программа start clrwdt ; сброс на всякий случай call del500 ; программируемая задержка цикла(time_cicl&time_delay) btfss mod_man ; если не ручной режим goto next0 ; идем на нормальное сканирование btfss InStart ; проверяем вход Старт, 1 - не активен goto next0 ; проверяем условие - кнопка Старт отпущена btfss Out1 ; ждем окончания очередного циклам goto contr_fin ; заканчиваем цикл если ручной реж. и кнопка Старт отп. next0 btfsc InCycle ; проверяем бит запуска цикла сварки goto control ; если активен (1) на метку контроля цикла сварки btfsc InProg ; проверяем бит режима программирования goto next1 ; если в режиме прогр. (1) - пропускаем кнопку Старт btfss InStart ; проверяем вход Старт, 1- не активен goto m_start ; если 0 - на программу обработки ; Сканирование кнопок Ввер - Вниз Влево - Вправо next1 btfss InUp ; проверяем вход кнопки "вверх", 1- не активен goto m_up ; если 0 - на программу обработки btfss InDown ; проверяем вход кнопки "вниз", 1- не активен goto m_down ; если 0 - на программу обработки btfss InLeft ; проверяем вход кнопки "влево", 1- не активен goto m_left ; если 0 - на программу обработки btfss InRight ; проверяем вход кнопки "вправо", 1- не активен goto m_right ; если 0 - на программу обработки ; окончание цикла сканирования - все кнопки отпущены ; цикл таймера на всякий случай переустановим (после рабочего цикла) movlw .40 ; установим цикл программы на 20мс - норм сканирование movwf time_cicl ; 40 циклов по 500 мкс (в time_delay длит. 1-го цикла) movlw .50 ; настроим таймер задержки на 500мкс - норм. сканир. movwf time_delay ; сохраним в регистре time_delay bcf First_Cicl ; входов нет сбрасываем бит 1-го входа(мб дребезг) bcf pwr_ok ; и разряда PWR bcf end_scan ; окончания цикла сканирования btfsc BlInd ; кнопки отпущены, проверяем бит блокировки goto continue ; если бит установлен - отрабатываем таймер блокировки btfsc InProg ; если был вход в режим программирования goto cont_save ; считаем время отпущенных кнопок goto start ; если бит сброшен - на начало ; Обслуживание кнопки "Влево" - запуск режима Программирования, сдвиг выбранного разр. m_left btfsc BlInd ; проверим есть ли бит блокировки, 0 - нет блокировки goto m_left3 ; 1 - есть блокировка, не выполняем ничего. btfsc First_Cicl ; проверим - 1-й вход или 2-й goto m_left2 ; если уже 2-й (First_Cicl=1) то на обработку bsf First_Cicl ; установим бит 1-го входа (устранение дребезга) goto start ; ничего не делаем m_left2 movlw 0xC8 ; время обновляем для контроля отпущенных кнопок - 4s movwf time_save ; и сохраняем bsf InProg ; устанавливаем бит перехода в режим программирования bsf Out2 ; зажгем светодиод m_left0 incf pos_ind, f ; указатель - на старший индикатор bcf STATUS, C ; бит переноса очистим movlw 0x89 ; проверка на старший индикатор (адрес 76h) addwf pos_ind, w ; сложим с текущим указателем (70..76) btfss STATUS, C ; если есть перенос, то >76 , пропускаем след. команду goto m_left1 ; нет переноса, проверяем след ячейку movlw 0x70 ; был перенос, загружаем указатель на младший разряд movwf pos_ind ; и сохраняем m_left1 movf pos_ind, w ; позицию текущего индикатора movwf FSR ; загружаем в индексный регистр bcf STATUS, C ; бит переноса очистим movlw 0xf6 ; проверим на переполнение >9 (ищем цифры 0 - 9) addwf INDF, w ; содержимое ячейки с адресом в индексном регистре btfsc STATUS, C ; если есть перенос, то >9 , выполняем след. команду goto m_left0 ; продолжим поиск ячеек с цифрами bsf BlInd ; и установим бит блокировки call outdisp ; на п\п вывода данных на индикатор m_left3 movlw .10 ; время блокировки примерно 0,2 сек (10х20мс) movwf time_block ; сохраним в ячейке time_block goto start ; знакоместо с цифрой найдено, на начало программы ; Обслуживание кнопки "Вправо" - запуск режима Программирования, сдвиг выбранного разр. m_right btfsc BlInd ; проверим есть ли бит блокировки, 0 - нет блокировки goto m_right3 ; 1 - есть блокировка, не выполняем ничего. btfsc First_Cicl ; проверим - 1-й вход или 2-й goto m_right2 ; если уже 2-й (First_Cicl=1) то на обработку bsf First_Cicl ; установим бит 1-го входа (устранение дребезга) goto start ; ничего не делаем m_right2 movlw 0xC8 ; время обновляем для контроля отпущенных кнопок - 4s movwf time_save ; и сохраняем bsf InProg ; устанавливаем бит перехода в режим программирования bsf Out2 ; зажгем светодиод m_right0 decf pos_ind, f ; указатель - на младший индикатор bcf STATUS, C ; бит переноса очистим movlw 0x90 ; проверка на младший индикатор (адрес 70h) addwf pos_ind, w ; сложим с текущим указателем (70..77) btfsc STATUS, C ; если нет переноса, то <70 , пропускаем след. команду goto m_right1 ; есть перенос, ==> в диапазоне, проверяем след ячейку movlw 0x76 ; был перенос, загружаем указатель на старший разряд movwf pos_ind ; и сохраняем m_right1 movf pos_ind, w ; позицию текущего индикатора movwf FSR ; загружаем в индексный регистр bcf STATUS, C ; бит переноса очистим movlw 0xf6 ; проверим на переполнение >9 (ищем цифры 0 - 9) addwf INDF, w ; содержимое ячейки с адресом в индексном регистре btfsc STATUS, C ; если есть перенос, то >9 , выполняем след. команду goto m_right0 ; продолжим поиск ячеек с цифрами bsf BlInd ; и установим бит блокировки call outdisp ; на п\п вывода данных на индикатор m_right3 movlw .10 ; время блокировки примерно 0,2 сек (10х20мс) movwf time_block ; сохраним в ячейке time_block goto start ; знакоместо с цифрой найдено, на начало программы ; обслуж. кн. "Вверх" - в режиме просмотра увеличиваем адрес блока для чтения из EEPROM ; в режиме программирования - увеличиваем содержимое выбранного разряда. m_up btfsc BlInd ; проверим есть ли бит блокировки, 0 - нет блокировки goto m_up2 ; 1 - есть блокировка, не выполняем ничего. btfsc First_Cicl ; проверим - 1-й вход или 2-й goto m_up1 ; если уже 2-й (First_Cicl=1) то на обработку bsf First_Cicl ; установим бит 1-го входа (устранение дребезга) goto start ; ничего не делаем m_up1 bsf Out2 ; светодиод зажгем btfsc InProg ; проверяем - режим программирования или ожидания goto inc_byte ; усли режим программирования - на метку "увеличить" btfsc ind_ROM, 5 ; 5-й бит указателя = 0? (конечный адр 20Н - 0010 0000) goto m_up11 ; если дошли до конца - ничего не делаем movlw 0x08 ; если не дошли - увеличиваем указатель на след. строку addwf ind_ROM, f ; сохраняем результат в ячейке указателя call read_blck ; читаем новое содержимое из EEPROM goto m_up11 ; inc_byte movlw 0xC8 ; время обновляем для контроля отпущенных кнопок - 4s movwf time_save ; и сохраняем movf pos_ind, w ; позицию текущего индикатора movwf FSR ; загружаем в индексный регистр bcf STATUS, C ; очистим бит переноса incf INDF, F ; увеличим на 1 содержимое ячейки с адресом в FSR movlw 0f6h ; проверим на переполнение >9 addwf INDF, w ; содержимое ячейки с адресом в индексном регистре btfsc STATUS, C ; если есть перенос, то >9 , выполняем след. команду clrf INDF ; есть переполнение, обнулим ячейку m_up11 bsf BlInd ; и установим бит блокировки call outdisp ; на п\п вывода данных на индикатор m_up2 movlw .10 ; время блокировки примерно 0,2 сек (10х20мс) movwf time_block ; сохраним в ячейке time_block goto start ; продолжим сканирование ; обслуж/ кн/ "Вниз" - в режиме отображения уменьшаем адрес блока для чтения из EEPROM ; в режиме программирования - уменьшаем содержимое выбранного разряда. m_down btfsc BlInd ; проверим есть ли бит блокировки, 0 - нет блокировки goto m_down2 ; 1 - есть блокировка, не выполняем ничего. btfsc First_Cicl ; проверим - 1-й вход или 2-й goto m_down1 ; если уже 2-й (First_Cicl=1) то на обработку bsf First_Cicl ; установим бит 1-го входа (устранение дребезга) goto start ; ничего не делаем m_down1 bsf Out2 ; зажгем светодиод btfsc InProg ; проверяем - режим программирования или ожидания goto dec_byte ; усли режим программирования - на метку "увеличить" movf ind_ROM, f ; режим проверки содержимого ячейки на 0 btfsc STATUS, Z ; проверяем бит нуля регистра статуса goto m_down11 ; если содержимое регистра 0 - ничего не делаем movlw 0x08 ; если не дошли - увеличиваем указатель на след. строку subwf ind_ROM, f ; сохраняем результат в ячейке указателя call read_blck ; читаем новое содержимое из EEPROM goto m_down11 ; dec_byte movlw 0xC8 ; время обновляем для контроля отпущенных кнопок - 4s movwf time_save ; и сохраняем movf pos_ind, w ; позицию текущего индикатора movwf FSR ; загружаем в индексный регистр movf INDF, F ; проверяем содержимое ячейки на 0 btfsc STATUS, Z ; Z=1 если содержимое ячейки = 0 goto m_down10 ; если содержимое регистра = 0 - загрузим исх. данные goto m_down12 ; если содержимое ячейки не 0 - уменьшаем содержимое m_down10 movlw 0x09 ; загружаем нач значение на 9 movwf INDF ; и сохраним в текущем регистре goto m_down11 ; m_down12 decf INDF, F ; одинарное уменьшение m_down11 bsf BlInd ; и установим бит блокировки call outdisp ; на п\п вывода данных на индикатор m_down2 movlw .08 ; время блокировки примерно 0,16 сек (08х20мс) movwf time_block ; сохраним в ячейке time_block goto start ; продолжим сканирование ; обслуживание кнопки "Старт" - если не в режиме программирования запускает цикл сварки m_start btfsc BlInd ; проверим есть ли бит блокировки, 0 - нет блокировки goto m_start3 ; 1 - есть блокировка, не выполняем ничего. btfsc First_Cicl ; проверим - 1-й вход или 2-й goto m_start2 ; если уже 2-й (First_Cicl=1) то на обработку bsf First_Cicl ; установим бит 1-го входа (устранение дребезга) goto start ; на начало программы ; проверяем ячейку PWR на значения 0...9 - его нет в режиме регулировки паузы m_start2 btfsc pwr_ok ; если установлен бит чтения из таблицы "уровень PWR" goto m_start4 ; продолжим на старт4 movlw 0xf6 ; проверим на переполнение >9 (ищем цифры 0 - 9) addwf Byte0, w ; содержимое ячейки Byte0 btfsc STATUS, C ; если есть перенос, то >9 , выполняем след. команду goto m_pwr_err ; ошибка - не задана мощность (в режиме уст-ки паузы) ; чтение из таблицы времени задержки в зависимости от значения PWR movf ind_PWR, w ; начальный адрес памяти для чтения из EEPROM addwf Byte0, w ; прибавим смещение из младшего разряда индикатора call read_byte ; movwf time_pwr ; Отправим в ячейку задержки угла открывания movwf tmp_pwr ; и сохраним во временной ячейке bsf pwr_ok ; установим бит - уровень в норме clrf det_cont0 ; сбросим счетчики проверки импульсов сети clrf det_time ; ; проверим на ручной режим - старшая ячейка индикатора Byte7 movlw 0x0E ;проверим наличие ручного режима (код 0E - буква "Р") XORWF Byte7,w ;сравним со значением в индикаторе 7 (старший) btfsc STATUS, Z ;Z=1 если содержимое идентично bsf mod_man ; установим бит ручного режима если на индикаторе 7 "P" btfsc mod_man ; если бит ручного режима установлен - goto m_start7 ; пропускаем загрузку данных времени импульса и паузы ; проверяем кол-во импульсов в ячейке Byte2 - если 0, то ручной режим movf Byte2, f ; в ячейке Byte2 количество импульсов - проверим на 0 btfsc STATUS, Z ; Z=1 если в ячейке число равно 0 bsf mod_man ; установим бит ручного режима если в ячейке 0 btfsc mod_man ; если бит ручного режима установлен - goto m_start7 ; пропускаем загрузку данных времени импульса и паузы ; ручной режим не обнаружен, готовим данные для запуска movf Byte2, w ; прочитаем количество импульсов movwf cont_imp ; и сохраним movf Byte6, w ; прочитаем количество секунд в импульсе movwf t_imp_s ; и сохраним данные movwf t_i_s_tmp ; и временная ячейка movf Byte5, w ; прочитаем количество десятых долей секунд в импульсе movwf t_imp_s1 ; и сохраним данные movwf t_i_s1_tmp ; и временная ячейка movf Byte4, w ; прочитаем количество сотых долей секунд в импульсе movwf t_imp_s2 ; и сохраним данные movwf t_i_s2_tmp ; и временная ячейка movlw 0x06 ; начальный адрес для чтения секунд паузы из EEPROM=06 call read_byte ; movwf t_paus_s ; сохраним данные movwf t_p_s_tmp ; и временная ячейка movlw 0x05 ; начальный адрес для чтения десятых долей секунд паузы call read_byte ; movwf t_paus_s1 ; сохраним данные movwf t_p_s1_tmp ; и временная ячейка movlw 0x04 ; начальный адрес для чтения сотых долей секунд паузы call read_byte ; movwf t_paus_s2 ; сохраним данные movwf t_p_s2_tmp ; и временная ячейка m_start7 movlw .2 ;установим цикл программы на 100мкс - быстр. скан. movwf time_cicl ;2 цикла по 40 мкс + примерно до 30 циклов кода movlw .4 ;установим цикл задерки на 40 мкс - быстр. скан. movwf time_delay ;4 циклов по 10 мкс (в time_delay длит. 1-го цикла) goto start ; меняем время цикла для сканирования детектора сети ; проверка поступающих импульсов сети PORTB 1 - InDet ; цикл опроса установлен на 100 мкс, период импульсов 10 мс ; импульс перехода через 0 длительность примерно 0,5 мс (активный ноль) m_start4 btfsc end_scan ; пока не закончено сканирование goto m_start5 ; incfsz det_time, f ; увеличиваем счетчик цикла проверки (256 циклов) goto m_st_scan ; продолжаем сканирование bsf end_scan ; время вышло , проверяем данные goto m_start5 ; на метку проверки данных m_st_scan btfss InDet ; если на детекторе не 1 incf det_cont0, f; увеличиваем счетчик нулей goto start ; продолжаем сканирование ; установка бита ошибки , если что то не так с импульсами сети ; имеем 256 циклов проверки примерно по 100мкс (от 2-х до 3-х полупериодов) ; должно быть 2..3 импульса нулевых по 0,5мс (мин 6 имп мах 20) m_start5 movf det_cont0, f; проверка регистра счетчика длительности нулей на 0 btfsc STATUS, Z ; если Z=1 то в регистре 0 и идем на метку error 0 goto m_det_err0 ; movlw 0xFA ; проверка регистра на мин значение (6) addwf det_cont0, w; если в регистре меньше 6 btfss STATUS, C ; то после сложения С=0 и идем на метку error L goto m_det_errL ; movlw 0xEC ; проверка регистра на мax значение (20=14h) addwf det_cont0, w; если в регистре больше или равно 20 btfsc STATUS, C ; то после сложения С=1 и идем на метку error goto m_det_errH ; bsf InCycle ; установим бит начала цикла сварки goto m_start3 ; переходим на режим сварки ; выведем информацию по ошибке детектора сети ошибка "Е0" m_det_err0 movlw 0x00 ; символ "0" - счетчик нулевых импульсов в нуле goto m_det_err ; m_det_errL movlw 0x0D ; символ "L" - нулевых импульсов меньше минимального goto m_det_err ; m_det_errH movlw 0x0C ; символ "H" - нулевых импульсов больше максимального m_det_err movwf Byte4 ; отправим код ошибки в байт 4 movlw 0x0A ; символ "-" movwf Byte5 ; отправим в разряд 5 movlw 0x0F ; потушим разряды 3 - 0 movwf Byte3 ; movwf Byte2 ; movwf Byte1 ; movwf Byte0 ; movlw 0x0B ; в 1-й разряд выведем символ "Е" movwf Byte7 ; clrf Byte6 ; во 2-й разряд символ "0" call outdisp ; и выведем на дисплей goto m_start6 ; и на окончание ; выведем информацию по отсутствию числа в разряде PWR, ошибка "Е1" m_pwr_err bcf pwr_ok ; сбросим бит - установка мощности ок movlw 0x0F ; потушим разряды 7 - 2 movwf Byte7 ; movwf Byte6 ; movwf Byte5 ; movwf Byte4 ; movwf Byte3 ; movwf Byte2 ; movlw 0x0B ; в 1-й разряд выведем символ "Е" movwf Byte1 ; movlw 0x01 ; в нулевой разряд символ "0" movwf Byte0 ; call outdisp ; и выведем на дисплей ; возврат нормального цикла сканирования в случае ошибки m_start6 movlw .40 ;установим цикл программы на 20мс - норм. сканирование movwf time_cicl ;40 цикла по 500 мкс movlw .50 ;цикл задерки на 500 мкс - нормальное сканирование movwf time_delay ;50 циклов по 10 мкс m_start3 bsf BlInd ; установим бит блокировки нажатия кнопки movlw .10 ; время блокировки примерно 0,2 сек (10х20мс) movwf time_block ; сохраним в ячейке time_block goto start ; на начало программы ; контроль времени отпущенной кнопки continue decfsz time_block, F ; уменьшаем счетчик циклов таймера блокировки goto start ; пока не 0 - на начало bcf BlInd ; если 0 - сбросим бит блокировки bcf mod_man ; сбросим бит ручного режима btfss InProg ; проверим бит режима программирования bcf Out2 ; если нет - потушим светодиод btfsc InProg ; проверяем бит режима программирования goto start ; если в режиме программирования (1) - пропускаем вывод call read_blck ; на пп чтения блока из 8 байт из EEPROM и на инд. call outdisp ; выведем начальную информацию на индикатор goto start ; на начало программы cont_save decfsz time_save, F ; уменьшаем счетчик ненажатых кнопок goto start ; bcf InProg ; если вышло время - сбрасываем бит программирования bcf Out2 ; потушим светодиод call wr_blck ; записываем новые данные в текущий блок movlw 0x76 ; текущая позиция индикатора для коррекции - 6 (0-6) movwf pos_ind ; сохраним в регистре call outdisp ; выведем на индикатор goto start ; на начало программы ; режим обслуживания цикла сварки - ожидаем запускающий импульс перехода сети через 0 ; бит начала цикла st_del_pwr устанавливается во время нулевого импульса сети и ; сбрасывается после вывода импульса . Пока бит не активен ничего не делаем. control btfsc InDet ; ожидание нулевого импульса сети для старта цикла goto contr1 ; идем на contr1 (сеть = 1) bsf cont1_imp ; установим бит для отсчета одного импульса 10мс bsf st_del_pwr ; установим бит для старта отсчета угла задержки bcf cnt_del_pwr ; сбросим бит отсчета угла задержки открытия bcf cnt_out1 ; сбросим бит отсчета времени управления на симистор bcf Out1 ; сбросим управляющие выходы на симистор bcf Out2 ; и контрольный светодиод goto cont_end ; пока есть нулевой импульс сети - ничего не делаем ; отсчитываем угол задержки открытия симистора - нулевой импульс детектора закончен contr1 btfss st_del_pwr ; если не установлен стартовый бит - пропускаем goto cont_end ; btfsc cnt_del_pwr ; задержка pwr отработана? goto contr2 ; если уже отработана - идем на проверку режима вывода bsf Out2 ; зажгем контр. светодиод, чтобы отследить задержку call cnt_pwr ; на п\п отсчитывания задержки угла открытия btfss cnt_del_pwr ; задержка pwr отработана? goto cont_end ; если еще на отработана - сразу на конец ; угол отсчитан - проверяем режим, ручной или вывод сварочного импульса contr2 btfsc mod_man ; если ручной режим - пропускаем счет goto contr5 ; вывод импульса в ручном, продолжительность не считаем ; отсчет количества сварочных импульсов по 10мс (общее время 1-го импульса сварки) btfsc cnt_imp_end ; сварочный импульс еще не выведен? goto contr3 ; импульс выведен, проверяем вывод паузы btfsc cont1_imp ; одиночный импульс для отсчета кол-ва импульсов сети call cont_impuls ; проверим вывод сварочного импульса bcf cont1_imp ; сразу сбросим одиночный бит до след. цикла сети btfsc cnt_imp_end ; сварочный импульс еще не выведен? goto cont_end ; импульс выведен, заканчиваем этот цикл goto contr5 ; на вывод импульса на симистор ; отсчет времени паузы между сварочными импульсами contr3 btfsc cnt_p_end ; пауза между сварочными импульсами выведена? goto contr4 ; пауза отработана, проверим - все импульсы отработаны? btfsc cont1_imp ; одиночный импульс для отсчета кол-ва импульсов сети call cont_pausa ; проверим вывод паузы между сварочными импульсами bcf cont1_imp ; сразу сбросим одиночный бит до след. цикла сети btfsc cnt_p_end ; пауза отсчитана полностью? goto cont_end ; пауза отсчитана заканчиваем этот цикл goto cont_end ; пауза не отсчитана, заканчиваем цикл ; проверка на количество сварочных импульсов (импульс сварки + время паузы = 1 цикл) contr4 decfsz cont_imp, f ; уменьшаем счетчик выводимых импульсов (сварка + пауза) goto contr_new ; если не 0 - на загрузку данных для нового цикла goto contr_fin ; заканчиваем цикл - выход в основное меню contr_new bcf cnt_imp_end ; сбросим бит отсчета времени сварочного импульса bcf cnt_p_end ; сбросим бит отсчета паузы межды импульсами сварки goto cont_end ; и на конец цикла contr_fin bcf cnt_imp_end ; сбросим бит отсчета времени сварочного импульса bcf cnt_p_end ; сбросим бит отсчета паузы межды импульсами сварки bcf cnt_del_pwr ; сбросим бит отсчета угла задержки открытия bcf cnt_out1 ; сбросим бит отсчета времени управления на симистор movlw .40 ; установим цикл программы на 20мс - норм сканирование movwf time_cicl ; 40 циклов по 500 мкс movlw .50 ; настроим таймер задержки на 500мкс - норм. скан. movwf time_delay ; сохраним в регистре time_delay bcf InCycle ; сбросим бит цикла сварки bcf mod_man ; сбросим бит ручного режима goto contr6 ; и на сброс цикла ; вывод импульса на симистор contr5 bsf Out1 ; установим выход на симистор bcf Out2 ; сбросим выход с контрольного светодиода ; goto cont_end ; и на конец цикла btfss cnt_out1 ; импульс на симистор выдан? goto contr7 ; если нет - контролируем длительность contr6 bcf Out1 ; сбросим выход с симистора bcf st_del_pwr ; сбросим бит цикла вывода goto cont_end ; и на конец цикла contr7 call imp_out1 ; считаем длительность импульса cont_end goto start ; на начало программы ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Подпрограмма инициализации контроллера init_pic clrf PCLATH ; обнулим старшие разряды счетчика адресов программы clrf INTCON ; запрет всех прерываний, сброс флагов прерываний bcf STATUS, IRP ; Банк0-1 при косвенной адресации bcf STATUS, RP1 ; к банкам 2-3 скорее всего не будем обращаться bcf STATUS, RP0 ; инициализация регистров банка 0 clrf PORTA ; очистим защелки порта А clrf PORTB ; и порта В clrf MemBit1 ; ячейки с битами очистим clrf MemBit2 ; clrf MemBit3 ; movlw 0x07 ; компараторы линий порта А выключены, movwf CMCON ; входы RA0 и RA3 цифровые movlw 0x10 ; указатель адреса чтения блока из EEPROM на 3-й блок movwf ind_ROM ; адреса блоков: 00h(1-й), 08h, 10h, 18h, 20h (5-й) movlw 0x30 ; указатель адреса чтения таблицы углов из EEPROM movwf ind_PWR ; адрес блока: 30h - 3Fh. Сохраним в регистре ind_PWR movlw 0x76 ; текущая позиция индикатора для коррекции - 6 (0-6) movwf pos_ind ; сохраним в регистре pos_ind movlw .50 ; настроим таймер задержки на 500мкс - норм. скан. movwf time_delay ; сохраним в регистре time_delay movlw .20 ; 20 циклов в режиме быстрого цикла по 100 мкс movwf t_imp_out1 ; время управляющего импульса на симистор movwf tmp_out1 ; время управляющего импульса на симистор (временная) bsf STATUS, RP0 ; инициализация регистров в банке 1 movlw 0x7C ; линии 0,1,7 порта А на выход остальные входы movwf TRISA ; movlw 0x3F ; линии 6,7 порта В на выход, остальные входы movwf TRISB ; movlw 0x0F ; Подтяг. рез. включены, прерывания по заднему фронту movwf OPTION_REG ; внутр.такт. сигнал для TMR0, преддел.1:128 перед wdt. clrf PIE1 ; запрет прерываний от периферийных модулей clrf VRCON ; откл/ модуль источника опорн. напряжения компараторов bsf PCON, OSCF ; установим бит режима работы INTRC на 4MHz bcf STATUS, RP0 ; 0 - банк ;Подпрограмма инициализации драйвера(MAX7219) bsf cs ; линия выборки индикатора - установим bcf din ; линию данных индикатора обнулим bcf clk ; линию импульсов индикатора обнулим movlw .4 ; movwf time_cicl ;4 цикла по 500 мкс (в time_delay длит. 1-го цикла) call del500 ;вызов подпрограммы паузы 4x0,5=2 мс movlw 0x0F ;выключить тестовый режим movwf adr_tmp ; movlw 0x00 ; movwf dat_tmp ; call send ; movlw 0x0C ;включить драйвер в рабочий режим movwf adr_tmp ; movlw 0x01 ; movwf dat_tmp ; call send ; movlw 0x0A ;установить интенсивность свечения 09\32 (04) movwf adr_tmp ;другие значения - 07 - 15\32 movlw 0x04 ; 02 - 5\32 movwf dat_tmp ; 0A - 21\32 и т.д. call send ; movlw 0x09 ;включить декодирование для всех индикаторов movwf adr_tmp ; movlw 0xFF ; movwf dat_tmp ; call send ; movlw 0x0B ;использовать 8 индикаторов movwf adr_tmp ; movlw 0x07 ; movwf dat_tmp ; call send ; ; чтение инф на индикатор из EEPROM call read_blck ; на пп чтения блока из 8 байт из EEPROM и на инд. call outdisp ; выведем начальную информацию на индикатор movlw .40 ;установим цикл программы на 20мс - норм сканирование movwf time_cicl ;40 циклов по 500 мкс (в time_delay длит. 1-го цикла) goto start ; на начало программы ; Чтение байта из EEPROM с адресом в W , результат чтения в W на выходе из п\п ; для загрузки адреса берем базу - ячейку ind_PWR и прибавляем смещение - Byte0 ; образец загрузки перед вызовом п\п read_byte bsf STATUS, RP0 ; Банк 1 movwf EEADR ; Скопировать W в регистр EEAdr bsf EECON1, RD ; Инициализировать чтение movf EEDATA, w ; Скопировать число из ячейки EEPROM в регистр W bcf STATUS, RP0 ; Банк 0 return ; Чтение блока из 8-и байт из EEPROM с начальным адресом в W на индикатор (Byte7-Byte0) ; Начальный адрес данных для записи на индикатор предварительно загружаем в FSR ; Используем область памяти, доступную из всех банков. read_blck movlw 0x70 ; адрес Byte0 памяти для копирования записи из EEPROM movwf FSR ; сохраним в индексном регистре movf ind_ROM, w ; готовим инф. для чтения - в W нач адрес чтения bsf STATUS, RP0 ; Банк 1 movwf EEADR ; Скопировать W в регистр EEAdr read_0 bsf EECON1, RD ; Инициализировать чтение movf EEDATA, w ; Скопировать число из ячейки EEPROM в регистр W movwf INDF ; Отправим по адресу в FSR incf EEADR, f ; указатель на след ячейку памяти EEPROM incf FSR, f ; указатель на след ячейку памяти для вывода на инд. btfss FSR, 3 ; читаем 8 ячеек с 0000 по 0111 ( на 1000 заканчиваем) goto read_0 ; продолжаем цикл чтения bcf STATUS, RP0 ; инициализация регистров банка 0 return ; Запись блока из 8-и байт из EEPROM с начальным адресом в W на индикатор (Byte7-Byte0) ; Начальный адрес данных предварительно загружаем в FSR. ; Используем область памяти, доступную из всех банков. wr_blck movlw 0x70 ; адрес Byte0 памяти для копирования записи из EEPROM movwf FSR ; сохраним в индексном регистре movf ind_ROM, w ; готовим инф. для чтения - в W нач адрес чтения bsf STATUS, RP0 ; Банк 1 movwf EEADR ; Скопировать W в регистр EEAdr wr_0 movf INDF, W ; Записать в регистр W данные из ячейки с адресом в FSR movwf EEDATA ; Скопировать число из регистра W в регистр данных. bsf EECON1,WREN ; Разрешить запись. movlw 055h ; Обязательная movwf EECON2 ; процедура movlw 0AAh ; при записи. movwf EECON2 ; ----"---- bsf EECON1,WR ; Запись wr_chk btfsc EECON1,WR ; проверяем окончание записи goto wr_chk ; цикл ожидания окончания записи incf EEADR, f ; указатель на след ячейку памяти EEPROM incf FSR, f ; указатель на след ячейку памяти для вывода на инд. btfss FSR, 3 ; читаем 8 ячеек с 0000 по 0111 ( на 1000 заканчиваем) goto wr_0 ; продолжаем цикл чтения bcf EECON1,WREN ; Сбросить флаг разрешения записи в EEPROM. bcf STATUS, RP0 ; Банк 0 bcf PIR1, EEIF ; и сбрасываем бит прерывания по окончании записи return ;подпрограмма отправки 8-ми байт данных из регистров ОЗУ на драйвер MAX7219 outdisp movlw .8 ;запись счетчика циклов movwf contbyte ;счетчик выгружаемых байт информации (знакомест) movlw 0x70 ;установка начального адреса FSR (адрес Byte0) movwf FSR ; movlw .1 ;адрес первого знакоместа в MAX7219 movwf adr_ind ;сохраним в адресный регистр adr_ind movwf adr_tmp ;адресный регистр adr_ind - во временный для вывода outdisp1 movf FSR, w ;прочитаем текущее содержимое FSR XORWF pos_ind, w ;сравним с положением регулируемого разряда btfsc STATUS, Z ;Z=1 если содержимое идентично bsf addPoint ;установим бит добавления точки btfss STATUS, Z ;если не равны bcf addPoint ;то сбросим movf INDF, w ;читаем в W содержимое ОЗУ по адресу в регистре FSR btfsc addPoint ;проверим бит добавления точки iorlw 0x80 ;если включен - добавим десятичную точку (7-й бит) movwf dat_tmp ;сохраняем данные для отправки call send ;отправки пакета (адрес знакоместа - данные) на драйвер incf FSR, f ;инкремент регистра FSR incf adr_ind, w ;инкремент регистра adr_ind movwf adr_tmp ;новый адрес - во временный для вывода movwf adr_ind ;и сохраним decfsz contbyte, f ;декремент счетчика циклов goto outdisp1 ;счетчик не равен нулю: переход на метку viv_1 return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Подпрограмма отправки 2-х байт (пакета данных) на драйвер (MAX7219) по протоколу SPI send bcf cs ;Сбросить линию выбора драйвера CS - активировать прием movlw .8 ;Отправка содержимого адр. байта adr_tmp на драйвер movwf contbit ;Счетчик выгружаемых бит информации send1 bcf clk ;тактовый бит сбросим btfsc adr_tmp,7 ;анализ старшего бита adr_tmp bsf din ;если не 0 - установим бит данных btfss adr_tmp,7 ;если не 1 bcf din ;сбросим бит данных nop ;пауза bsf clk ;загружаем бит данных положительным фронтом clk rlf adr_tmp,F ;сдвигаем следующий бит для анализа decfsz contbit,F ;повторяем пока не выведем все 8 бит goto send1 ; movlw .8 ;Отправка содержимого байта данных dat_tmp на драйвер movwf contbit ;Счетчик выгружаемых бит информации send2 bcf clk ;тактовый бит сбросим btfsc dat_tmp,7 ;анализ старшего бита dat_tmp bsf din ;если не 0 - установим бит данных btfss dat_tmp,7 ;если не 1 bcf din ;сбросим бит данных nop ;пауза bsf clk ;загружаем бит данных положительным фронтом clk rlf dat_tmp,F ;сдвигаем следующий бит для анализа decfsz contbit,F ;повторяем пока не выведем все 8 бит goto send2 ; bcf clk ;сбросим тактовый сигнал bsf cs ;установить линию выбора драйвера - сохр. принятые дан. return ;выход из подпрограммы ; подпрограмма декремента заданного количества импульсов (время сварки) cont_impuls btfsc cnt_imp_end ; если бит готовности уже установлен goto cont_imp2 ; ничего не делаем - на выход movf t_i_s_tmp, w ; проверяем на 0 все ячейки - секунд addwf t_i_s1_tmp, w ; - десятых addwf t_i_s2_tmp, w ; - и сотых долей секунд btfss STATUS, Z ; если не 0 (Z=0) goto cont_imp1 ; идем на метку счета movf t_imp_s, w ; достигли нуля - перезагружаем значения movwf t_i_s_tmp ; секунд movf t_imp_s1, w ; movwf t_i_s1_tmp ; десятых долей секунд movf t_imp_s2, w ; movwf t_i_s2_tmp ; и сотых долей секунд bsf cnt_imp_end ; установим бит окончания счета длит-ти импульса goto cont_imp2 ; и на выход cont_imp1 movlw .1 ; subwf t_i_s2_tmp, f ; уменьшим на 1 ячейку сотых долей секунд btfsc STATUS, C ; если нет переноса (C=1) goto cont_imp2 ; идем на выход movlw .9 ; есть перенос (С=0) , загружаем 9 movwf t_i_s2_tmp ; в разряд сотых и уменьшаем разряд десятых movlw .1 ; subwf t_i_s1_tmp, f ; уменьшаем разряд десятых долей секунд btfsc STATUS, C ; если нет переноса (C=1) goto cont_imp2 ; идем на выход movlw .9 ; есть перенос (С=0) , загружаем 9 movwf t_i_s1_tmp ; в разряд десятых и уменьшаем разряд секунд movlw .1 ; subwf t_i_s_tmp, f ; уменьшаем разряд секунд cont_imp2 return ; ; подпрограмма декремента заданного количества импульсов (время паузы) cont_pausa btfsc cnt_p_end ; если бит готовности уже установлен goto cont_p2 ; ничего не делаем - на выход movf t_p_s_tmp, w ; проверяем на 0 все ячейки - секунд addwf t_p_s1_tmp, w ; - десятых addwf t_p_s2_tmp, w ; - и сотых долей секунд btfss STATUS, Z ; если не 0 (Z=0) goto cont_p1 ; идем на метку счета movf t_paus_s, w ; достигли нуля - перезагружаем значения movwf t_p_s_tmp ; секунд movf t_paus_s1, w ; movwf t_p_s1_tmp ; десятых долей секунд movf t_paus_s2, w ; movwf t_p_s2_tmp ; и сотых долей секунд bsf cnt_p_end ; установим бит окончания счета длительности паузы goto cont_p2 ; и на выход cont_p1 movlw .1 ; subwf t_p_s2_tmp, f ; уменьшим на 1 ячейку сотых долей секунд btfsc STATUS, C ; если нет переноса (C=1) goto cont_p2 ; идем на выход movlw .9 ; есть перенос (С=0) , загружаем 9 movwf t_p_s2_tmp ; в разряд сотых и уменьшаем разряд десятых movlw .1 ; subwf t_p_s1_tmp, f ; уменьшаем разряд десятых долей секунд btfsc STATUS, C ; если нет переноса (C=1) goto cont_p2 ; идем на выход movlw .9 ; есть перенос (С=0) , загружаем 9 movwf t_p_s1_tmp ; в разряд десятых и уменьшаем разряд секунд movlw .1 ; subwf t_p_s_tmp, f ; уменьшаем разряд секунд cont_p2 return ; ; подпрограмма отсчета задержки угла открывания cnt_pwr btfsc cnt_del_pwr ; если бит готовности уже установлен goto cnt_pwr1 ; ничего не делаем - на выход decfsz tmp_pwr, f ; уменьшаем временную ячейку goto cnt_pwr1 ; если еще не 0 идем на выход movf time_pwr, w ; достигли нуля - перезагружаем на новый цикл movwf tmp_pwr ; временную ячейку bsf cnt_del_pwr ; установим бит готовности cnt_pwr1 return ; ; подпрограмма отсчета управляющего импульса на тиристор imp_out1 btfsc cnt_out1 ; если бит готовности уже установлен goto imp_out1_1 ; ничего не делаем - на выход decfsz tmp_out1, f ; уменьшаем временную ячейку goto imp_out1_1 ; если еще не 0 идем на выход movf t_imp_out1, w ; достигли нуля - перезагружаем на новый цикл movwf tmp_out1 ; временную ячейку bsf cnt_out1 ; установим бит готовности imp_out1_1 return ; подпрограмма задержки, входное значение в W - количество циклов del500 movf time_cicl, w ;количество циклов таймера из ячейки time_cicl movwf tmp1 ;сохраним del501 movf time_delay, w ;длит-сть одного цикла берем из ячейки time_delay movwf tmp0 ;и сохраняем del502 nop ; тело из 10-и циклов задержки nop nop nop nop nop nop decfsz tmp0,F ; счетчик внутреннего цикла на 500 мкс goto del502 ; decfsz tmp1,F ; счетчик внешнего цикла (входное задание на счет) goto del501 ; return ;выход из подпрограммы end