'*************************************************************************** '* 12V UPS (Pic16F876,OSC-4MHz) * '*************************************************************************** '------------------------------------------------------------------------------- START: Knopka_MINUS var PORTC.5 ' задаем и прописываем соответствие переменных Knopka_PLUS var PORTC.6 ' к портам ввода-вывода Knopka_OK var PORTC.4 AVAR var PORTA.4 BIP var PORTB.0 LED_YELLOW var PORTB.1 U_REG var PORTC.0 LCD var PORTC.1 FAN_MAX var PORTC.2 FAN_MIN var PORTC.3 ' значения bite(0/1),byte(0-255),word(0-65535) U_ACP var word ' переменная для анализа и расчетов U AKK на АЦП UAC_ACP var word ' переменная для анализа и расчетов U AC230 на АЦП I_ACP var word ' переменная для анализа и расчетов I на АЦП T_ACP var word ' переменная для анализа и расчетов T на АЦП I var word I1 var word U var word U1 var word UAC var word UAC1 var word T var word T1 var word ISUMM var word ' переменная для расчета усредненного тока ISUMM=0 I1SUMM var word ' переменная для расчета усредненного тока I1SUMM=0 ICONTROL var word ' переменная для контроля 3% остаточного зарядного тока ICONTROL=0 USUMM var word ' переменная для расчета усредненного напряжения USUMM=0 U1SUMM var word ' переменная для расчета усредненного напряжения U1SUMM=0 UACSUMM var word ' переменная для расчета усредненного напряжения AC230 UACSUMM=0 UAC1SUMM var word ' переменная для расчета усредненного напряжения AC230 UAC1SUMM=0 TSUMM var word ' переменная для расчета усредненной температуры TSUMM=0 T1SUMM var word ' переменная для расчета усредненной температуры T1SUMM=0 UAKK var word ' переменная напряжения на аккумуляторе без тока зарядки UAKK = 0 DU var word ' переменная dU падения напряжения на изм.резисторе R=0.05Om DU = 0 U_PWM var byte ' переменная ШИМ регулировки напряжения (0-255) U_PWM = 0 ' начальная установка скважности =0 AK var byte ' порядковый номер в списке аккумуляторов AK=0 EMK var byte ' емкость аккумулятора STEEP var byte ' переменная шага цикла зарядки X var byte ' переменная для циклов P var byte ' переменная для циклов паузы Y var byte ' переменная для цикла подпрограмм YY var byte ' переменная для цикла подпрограмм TONE var byte ' переменная для музыки DUR var byte ' переменная для музыки F var byte ' флажок частоты прерываний таймера TMR1(2Hz) F=0 SECUND var byte ' переменная времени часов SECUND=0 MINUT var byte ' переменная времени часов MINUT=0 HOUR var byte ' переменная времени часов HOUR=0 DAY var byte ' переменная времени часов DAY=0 SECUND_ZAR var byte ' переменная времени зарядки для индикации на LCD SECUND_ZAR=0 MINUT_ZAR var byte ' переменная времени зарядки для индикации на LCD MINUT_ZAR=0 HOUR_ZAR var byte ' переменная времени зарядки для индикации на LCD HOUR_ZAR=0 DAY_ZAR var byte ' переменная времени зарядки для индикации на LCD DAY_ZAR=0 LCD_MIN var byte ' переменная получения паузы отключения дисплея LCD_SEC var byte ' переменная получения паузы отключения дисплея T_EMK_MIN var byte ' переменная для интервала времени выбора ёмкости T_EMK_SEC var byte ' переменная для интервала времени выбора ёмкости T_ZAR_MIN var byte ' переменная для интервала времени зарядки T_ZAR_SEC var byte ' переменная для интервала времени зарядки T_IMP_SEC var byte ' переменная для интервала импульса зарядки PORTA = %00000000 ' перед началом сбрасываем в 0 все выходы порта A PORTB = %00000000 ' сбрасываем в 0 все выходы порта B PORTC = %00000000 ' сбрасываем в 0 все выходы порта C TRISA = %11111111 ' конфигурируем все выводы порта A как входы TRISB = %00000000 ' конфигурируем выводы порта B как выходы TRISC = %11110000 ' конфигурируем выводы порта С (0-выход,1-вход) ' RC7 RC6 RC5 RC4 RC3 RC2 RC1 RC0 ' | | | | | | | | ' Вх Вх Вх Вх Вых Вых Вых Вых ADCON0 = 1 ' выбираем тактовый источник 1-8Tosc ADCON1 = 2 ' 2=0010 конфигурируем AN входы порта А как все Аналог. ' AN4 AN3 AN2 AN1 AN0 D-цифровой вход ' | | | | | А-аналоговый АЦП ' A A A A A define OSC 4 ' задаем частоту кварца (по умолчанию всегда 4MHz) DEFINE ADC_BITS 8 ' задаем 8-разрядную (256 ступенек) точность входов АЦП ' 5000mV/255=19.61mV одна ступенька define ADC_CLOCK 1 ' выбираем тактовый источник для АЦП 1-Fosc/8(для 5-20MHz) define ADC_SAMPLEUS 50 ' задаем время преобразования в микросекундах define LCD_DREG PORTB ' задаем порт B для передачи данных на LCD индикатор define LCD_DBIT 4 ' задаем RB4 вывод, который будет подключен ' к выводу DB4 LCD define LCD_RSREG PORTB ' задаем порт B, который будет выдавать сигнал RS define LCD_RSBIT 3 ' задаем RB3 вывод, который будет выдавать RS DEFINE LCD_EREG PORTB ' задаем порт B, который будет выдавать сигнал E DEFINE LCD_EBIT 2 ' задаем RB2 вывод, который будет выдавать E DEFINE LCD_BITS 4 ' задаем 4-битный режим передачи данных на LCD ' (подключаем только 4 шины данных LCD) DEFINE LCD_LINES 4 ' задаем вывод информации в 4 строки LCD DEFINE LCD_COMMANDUS 2000 ' пауза между передачей команд на LCD DEFINE LCD_DATAUS 50 ' пауза между передачей данных на LCD pause 1000 ' пауза для инициализации LCD (1000/4Mhz=0.25sec) high LCD ' зажигания подсветки LCD дисплея LCDOUT $FE,1 ' очищаем экран LCD lcdout $FE,$80," 12V ",$A0,$A7,$4F,$4B," " lcdout $FE,$C0," ",$A0,$45,$A4,$A8,$45,$50,$45,$A0,$4F,$A6,$48,$4F,$A1,$4F," " lcdout $FE,$94," ",$A8,$A5,$54,$41,$48,$A5,$B1," " lcdout $FE,$D4," ",$A1,$4F,$54,$4F,$42," K ",$50,$41,$A0,$4F,$54,$45," " ' вывод информации на русском из таблицы символов дисплея ' " 12V БЛОК " ' " БЕЗПЕРЕБОЙНОГО " ' " ПИТАНИЯ " ' " ГОТОВ К РАБОТЕ " on interrupt goto myINT ' Зададим адрес обработки прерываний - ' он находится по адресу метки myINT TMR1=3036 ' Установка предварительного значения таймера(<65635) ' после запуска прерываний получим F(прер.)=2Гц PIE1.0 = 1 ' Прерывание 1-разрешено /0-запрещено INTCON.6 = 1 ' от периферийных устройств микроконтроллера, ' т.к. TMR1 - периферия INTCON.7 = 1 ' Установим бит глобального разрешения прерываний ' (этот бит разрешает работу всех запросов вообще) T1CON=%00110000 ' Предустановлен делитель 1:8, Fosc/4, но не включен таймер ' После всех настроек перейдем на выполнение главной программы, а таймер будет ' включен позже и начнет увеличивать свое значение с каждым циклом. В начале мы ' предустановили делитель 1:8, загрузили таймер значением 3036 и как только ' он дотикает до 65535 и придет следующий тик - это вызовет его ' переполнение и, соответственно, прерывание по переполнению TMR1 for X=0 to 8 ' музыка, запускаем цикл из 9 нот и длительностей lookup X,[80,0,75,0,68,0,75,0,80],TONE ' из двух массивов lookup X,[15,0,15,0,15,0,15,0,20],DUR sound BIP,[TONE,DUR] next X if Knopka_OK = 0 then sound BIP,[120,50] goto TEST endif pause 4000 ' пауза 4000/4Mhz=1sec SECUND=0 MINUT=0 HOUR=0 DAY=0 T1CON.0=1 ' запуск таймера прерывания TMR1 по переполнению T_EMK_MIN=MINUT ' записываем в переменную показания минут T_EMK_SEC=SECUND ' записываем в переменную показания секунд '------------------------------------------------------------------------------- EMKOSTJ: gosub ACP_T ' переход на п/программу считывания данных T gosub DC_FAN ' переход на п/программу работы вентилятора if AVAR = 1 then ' если сигнал AVAR активен (пропало 230V), то goto AVAR_MODE ' переход на п/программу аварийного режима endif repeat ' повторять действия пока не выполнится условие until ' (пока не пройдет 1min) if Knopka_MINUS = 0 then ' если нажата кнопка "-" sound BIP,[120,5] T_EMK_MIN=MINUT ' сброс счетчика - записываем в переменную новые показания минут T_EMK_SEC=SECUND ' сброс счетчика - записываем в переменную новые показания секунд if AK>0 then AK=AK-1 endif pause 500 endif if Knopka_PLUS = 0 then ' если нажата кнопка "+" sound BIP,[120,5] T_EMK_MIN=MINUT ' сброс счетчика - записываем в переменную новые показания минут T_EMK_SEC=SECUND ' сброс счетчика - записываем в переменную новые показания секунд if AK<5 then AK=AK+1 endif pause 500 endif if Knopka_OK = 0 then ' если нажата "OK", то переход дальше sound BIP,[100,10] T_EMK_MIN=MINUT ' сброс счетчика - записываем в переменную новые показания минут T_EMK_SEC=SECUND ' сброс счетчика - записываем в переменную новые показания секунд pause 500 LCDOUT $FE,1 ' очищаем экран LCD goto PRE_ZAR ' переход на п/пр.PRE_ZAR endif lookup AK,[45,55,65,75,85,95],EMK ' массив емкостей lcdout $FE,$80," ",$42,$AE,$A0,$4F,$50," ",$45,$4D,$4B,$4F,$43,$54,$A5," " lcdout $FE,$C0," <<- ",dec2 EMK," A/h ->> " lcdout $FE,$94," 12V ",$41,$4B,$4B,$A9,$4D,$A9,$A7,$B1,$54,$4F,$50,$48,$4F,$A6," " lcdout $FE,$D4," ",$A0,$41,$54,$41,$50,$45,$A5," " ' вывод информации на русском из таблицы символов дисплея ' " ВЫБОР EМКОСТИ " ' " <<- 55 A/h ->> " ' " 12V АККУМУЛЯТОРНОЙ " ' " БАТАРЕИ " until (T_EMK_MIN<>MINUT) AND (T_EMK_SEC=SECUND) ' повторяли действия пока не выполнилось условие until ' (пока не прошла 1min) EMK=55 ' если ёмкость не выбрана, в течении 1 min, то sound BIP,[120,5] ' она принимается равной 55A/h и переход далее goto PRE_ZAR ' на п/пр.PRE_ZAR '------------------------------------------------------------------------------- PRE_ZAR: low U_REG ' сброс на выходе ШИМ U_REG (PORTC.0) на ноль U_PWM=0 ' сбрасываем ШИМ скважность на минимум UAKK=0 low LED_YELLOW ' гасим желтый светодиод - нет зарядки LCDOUT $FE,1 ' очищаем экран LCD SECUND=0 ' обнуляем все показания часов MINUT=0 ' обнуляем все показания часов HOUR=0 ' обнуляем все показания часов DAY=0 ' обнуляем все показания часов '------------------------------------------------------------------------------- ZARADKA: lcdout $FE,$80," ",$42,$4B,$A7,$B0,$AB,$45,$48," 0-",$50,$45,$A3,$A5,$4D," " lcdout $FE,$C0," ",$A4,$41,$50,$B1,$E0,$4B,$A5," " lcdout $FE,$94," 12V ",$41,$4B,$4B,$A9,$4D,$A9,$A7,$B1,$54,$4F,$50,$48,$4F,$A6," " lcdout $FE,$D4," ",$A0,$41,$54,$41,$50,$45,$A5," " ' вывод информации на русском из таблицы символов дисплея ' " ВКЛЮЧЕН 0-РЕЖИМ " ' " ЗАРЯДКИ " ' " 12V АККУМУЛЯТОРНОЙ " ' " БАТАРЕИ " for P=1 to 400 pause 10 ' пауза 4000/4Mhz=1sec next P STEEP=0 '------------------------------------------------------------------------------- ZAR_0: 'нулевой этап- зарядка импульсным (f=1Гц) 20% током до напряжения 10V ' (процесс десульфатации) if AVAR = 1 then ' если сигнал AVAR активен (пропало 230V), то goto AVAR_MODE ' переход на п/программу аварийного режима endif gosub ACP_T ' переход на п/программу считывания данных T gosub DC_FAN ' переход на п/программу работы вентилятора gosub ACP_U ' переход на п/программу считывания данных АЦП напр. UAKK = U gosub ACP_UAC ' переход на п/программу считывания данных АЦП 230V gosub ACP_TO_LCD: ' переход на п/программу отображения данных на LCD if Knopka_PLUS = 0 then ' если нажата кнопка "+" sound BIP,[100,20] goto ZAR_1 ' переход на первый этап зарядки endif if UAKK<10000 then ' если Uакк в mV меньше 10V, то goto IMPULS else ' если Uакк в mV больше 10V, то sound BIP,[100,20] pause 500 goto ZAR_1 ' переход на первый этап зарядки endif IMPULS: '----------------------------------------------------------------------- T_IMP_SEC=SECUND ' записываем в переменную новые показания секунд ' (ограничения времени импулься зарядки 1sec) repeat ' повторять действия пока не выполнится условие until high U_REG ' на выходе U_REG (PORTC.0) выдаем сигнал "1"-(5V) high LED_YELLOW ' зажигаем желтый светодиод - происходит зарядка gosub ACP_I ' переход на п/программу считывания данных АЦП тока until (I>EMK*20) or (T_IMP_SEC<>SECUND) ' повторяли действия пока не выполнилось условие until ' импульс тока зарядки больше 20% от 0.1*Ah или ' прошла 1сек. low U_REG ' сброс на выходе U_REG (PORTC.0) на ноль low LED_YELLOW ' гасим желтый светодиод - нет зарядки for P=1 to 400 pause 10 ' пауза 4000/4Mhz=1sec между импульсами зарядки next P goto ZAR_0 '------------------------------------------------------------------------------- ZAR_1: 'первый этап- зарядка постоянным макс.током 0.05*Ah до напр.13.2V ' c контролем тока зарядки и c контролем Uзар.<14.8V low U_REG ' сброс на выходе U_REG (PORTC.0) на ноль low LED_YELLOW ' гасим желтый светодиод - нет зарядки UAKK=0 lcdout $FE,$80," ",$42,$4B,$A7,$B0,$AB,$45,$48," 1-",$50,$45,$A3,$A5,$4D," " lcdout $FE,$C0," ",$A4,$41,$50,$B1,$E0,$4B,$A5," " lcdout $FE,$94," 12V ",$41,$4B,$4B,$A9,$4D,$A9,$A7,$B1,$54,$4F,$50,$48,$4F,$A6," " lcdout $FE,$D4," ",$A0,$41,$54,$41,$50,$45,$A5," " ' вывод информации на русском из таблицы символов дисплея ' " ВКЛЮЧЕН 1-РЕЖИМ " ' " ЗАРЯДКИ " ' " 12V АККУМУЛЯТОРНОЙ " ' " БАТАРЕИ " for P=1 to 400 pause 10 ' пауза 4000/4Mhz=1sec next P STEEP=1 '------------------------------------------------------------------------------- ZAR_1_START: gosub ACP_U ' переход на п/программу считывания данных АЦП напр. UAKK=U ' напряжение без тока зарядки gosub ACP_UAC ' переход на п/программу считывания данных АЦП 230V T_ZAR_MIN=MINUT ' записываем в переменную показания минут T_ZAR_SEC=SECUND ' записываем в переменную показания секунд repeat ' повторять действия пока не выполнится условие until ' (пока не пройдет 1min зарядки), ' потом - пауза 2sec и замер напряжения акк. if AVAR = 1 then ' если сигнал AVAR активен (пропало 230V), то goto AVAR_MODE ' переход на п/программу аварийного режима endif pwm U_REG,U_PWM,1 ' на выходе U_REG (PORTC.0) выдаем сигнал ШИМ 1 пачку(5ms при 4MHz) high LED_YELLOW ' зажигаем желтый светодиод - происходит зарядка gosub ACP_I ' переход на п/программу считывания данных АЦП тока gosub ACP_T ' переход на п/программу считывания данных T gosub DC_FAN ' переход на п/программу работы вентилятора gosub ACP_U ' переход на п/программу считывания данных АЦП напр. U=U-DU ' компенсируем падение dU на изм.резисторе gosub ACP_UAC ' переход на п/программу считывания данных АЦП 230V gosub ACP_TO_LCD: ' переход на п/программу отображения данных на LCD if Knopka_PLUS = 0 then ' если нажата кнопка "+" sound BIP,[100,20] goto ZAR_2 ' переход на второй этап зарядки endif if Knopka_MINUS = 0 then ' если нажата кнопка "-" sound BIP,[100,20] goto ZAR_0 ' переход на нулевой этап зарядки endif if U>14800 then ' если напряжение зарядки выше 14.8V -> U_PWM=U_PWM-1 ' уменьшаемаем скважность ШИМ -> уменьшаемаем U if U_PWM<=1 then U_PWM=1 endif else ' U<14.8V if I U_PWM=U_PWM+1 ' увеличиваем скважность ШИМ -> увеличиваем ток if U_PWM>=254 then U_PWM=254 endif endif if I>=EMK*50 then ' если ток на АЦП в mА больше 0.05*Ah -> U_PWM=U_PWM-1 ' уменьшаемаем скважность ШИМ -> уменьшаемаем ток if U_PWM<=1 then U_PWM=1 endif endif endif if U>13200 and UAKK>12000 then ' если U на АЦП в mV при зарядке больше 13.2V sound BIP,[100,20] ' и Uакк больше 12V(частично заряжен),то goto ZAR_2 ' переход на второй этап зарядки endif until (T_ZAR_MIN<>MINUT) AND (T_ZAR_SEC=SECUND) ' повторяли действия пока не выполнилось условие until ' (пока не прошла 1min) low U_REG ' сброс на выходе U_REG (PORTC.0) на ноль low LED_YELLOW ' гасим желтый светодиод - нет зарядки for P=1 to 800 pause 10 ' пауза 8000/4Mhz=2sec next P goto ZAR_1_START '------------------------------------------------------------------------------- ZAR_2: 'второй этап- зарядка постоянным 20% током от 0.1*Ah до напряжения 14.8V ' c контролем тока зарядки и c контролем Uзар.<14.8V low U_REG ' сброс на выходе ШИМ U_REG (PORTC.0) на ноль U_PWM=0 ' сбрасываем ШИМ скважность на минимум low LED_YELLOW ' гасим желтый светодиод - нет зарядки UAKK=0 lcdout $FE,$80," ",$42,$4B,$A7,$B0,$AB,$45,$48," 2-",$50,$45,$A3,$A5,$4D," " lcdout $FE,$C0," ",$A4,$41,$50,$B1,$E0,$4B,$A5," " lcdout $FE,$94," 12V ",$41,$4B,$4B,$A9,$4D,$A9,$A7,$B1,$54,$4F,$50,$48,$4F,$A6," " lcdout $FE,$D4," ",$A0,$41,$54,$41,$50,$45,$A5," " ' вывод информации на русском из таблицы символов дисплея ' " ВКЛЮЧЕН 2-РЕЖИМ " ' " ЗАРЯДКИ " ' " 12V АККУМУЛЯТОРНОЙ " ' " БАТАРЕИ " for P=1 to 400 pause 10 ' пауза 4000/4Mhz=1sec next P STEEP=2 '------------------------------------------------------------------------------- ZAR_2_START: gosub ACP_U ' переход на п/программу считывания данных АЦП напр. UAKK=U ' напряжение без тока зарядки gosub ACP_UAC ' переход на п/программу считывания данных АЦП 230V T_ZAR_MIN=MINUT ' записываем в переменную показания минут T_ZAR_SEC=SECUND ' записываем в переменную показания секунд repeat ' повторять действия пока не выполнится условие until ' (пока не пройдет 1min зарядки), ' потом - пауза 2sec и замер напряжения акк. if AVAR = 1 then ' если сигнал AVAR активен (пропало 230V), то goto AVAR_MODE ' переход на п/программу аварийного режима endif pwm U_REG,U_PWM,1 ' на выходе U_REG (PORTC.0) выдаем сигнал ШИМ 1 пачку(5ms при 4MHz) high LED_YELLOW ' зажигаем желтый светодиод - происходит зарядка gosub ACP_I ' переход на п/программу считывания данных АЦП тока gosub ACP_T ' переход на п/программу считывания данных T gosub DC_FAN ' переход на п/программу работы вентилятора gosub ACP_U ' переход на п/программу считывания данных АЦП напр. U=U-DU ' компенсируем падение dU на изм.резисторе gosub ACP_UAC ' переход на п/программу считывания данных АЦП 230V gosub ACP_TO_LCD: ' переход на п/программу отображения данных на LCD if Knopka_PLUS = 0 then ' если нажата кнопка "+" sound BIP,[100,20] goto ZAR_3 ' переход на третий этап зарядки endif if Knopka_MINUS = 0 then ' если нажата кнопка "-" sound BIP,[100,20] goto ZAR_1 ' переход на первый этап зарядки endif if U>14800 then ' если напряжение зарядки выше 14.8V -> U_PWM=U_PWM-1 ' уменьшаемаем скважность ШИМ -> уменьшаемаем U if U_PWM<=1 then U_PWM=1 endif else if I увеличиваем ток if U_PWM>=254 then U_PWM=254 endif endif if I>=EMK*20 then ' если ток на АЦП в mА больше 20% от 0.1*Ah, U_PWM=U_PWM-1 ' то уменьшаемаем скважность ШИМ -> уменьшаемаем ток if U_PWM<=1 then U_PWM=1 endif endif endif if U>=14800 and UAKK>12000 then ' если U на АЦП в mV при зарядке больше 14.8V sound BIP,[100,20] ' и Uакк больше 12V(частично заряжен),то goto ZAR_3 ' переход на третий этап зарядки endif until (T_ZAR_MIN<>MINUT) AND (T_ZAR_SEC=SECUND) ' повторяли действия пока не выполнилось условие until ' (пока не прошла 1min) low U_REG ' сброс на выходе U_REG (PORTC.0) на ноль low LED_YELLOW ' гасим желтый светодиод - нет зарядки for P=1 to 800 pause 10 ' пауза 8000/4Mhz=2sec next P goto ZAR_2_START '------------------------------------------------------------------------------- ZAR_3: 'третий этап- зарядка постоянным напряжением 14.8V до min тока зарядки, ' но чтобы ток был меньше 20% от 0.1*Ah lcdout $FE,$80," ",$42,$4B,$A7,$B0,$AB,$45,$48," 3-",$50,$45,$A3,$A5,$4D," " lcdout $FE,$C0," ",$A4,$41,$50,$B1,$E0,$4B,$A5," " lcdout $FE,$94," 12V ",$41,$4B,$4B,$A9,$4D,$A9,$A7,$B1,$54,$4F,$50,$48,$4F,$A6," " lcdout $FE,$D4," ",$A0,$41,$54,$41,$50,$45,$A5," " ' вывод информации на русском из таблицы символов дисплея ' " ВКЛЮЧЕН 3-РЕЖИМ " ' " ЗАРЯДКИ " ' " 12V АККУМУЛЯТОРНОЙ " ' " БАТАРЕИ " for P=1 to 400 pause 10 ' пауза 4000/4Mhz=1sec next P STEEP=3 '------------------------------------------------------------------------------- ZAR_3_START: gosub ACP_U ' переход на п/программу считывания данных АЦП напр. UAKK=U ' напряжение без тока зарядки gosub ACP_UAC ' переход на п/программу считывания данных АЦП 230V ICONTROL=0 T_ZAR_MIN=MINUT ' записываем в переменную показания минут T_ZAR_SEC=SECUND ' записываем в переменную показания секунд repeat ' повторять действия пока не выполнится условие until ' (пока не пройдет 1min зарядки), ' потом - пауза 2sec и замер напряжения акк. if AVAR = 1 then ' если сигнал AVAR активен (пропало 230V), то goto AVAR_MODE ' переход на п/программу аварийного режима endif pwm U_REG,U_PWM,1 ' на выходе U_REG (PORTC.0) выдаем сигнал ШИМ 1 пачку(5ms при 4MHz) high LED_YELLOW ' зажигаем желтый светодиод - происходит зарядка gosub ACP_T ' переход на п/программу считывания данных T gosub DC_FAN ' переход на п/программу работы вентилятора gosub ACP_U ' переход на п/программу считывания данных АЦП напр. gosub ACP_UAC ' переход на п/программу считывания данных АЦП 230V gosub ACP_I ' переход на п/программу считывания данных АЦП тока ICONTROL=(ICONTROL+I)/2 ' усредняем значения тока U=U-DU ' компенсируем падение dU на изм.резисторе gosub ACP_TO_LCD: ' переход на п/программу отображения данных на LCD if Knopka_PLUS = 0 then ' если нажата кнопка "+" sound BIP,[100,20] goto SAVE_MODE ' переход на этап хранения заряда и контроля endif if Knopka_MINUS = 0 then ' если нажата кнопка "-" sound BIP,[100,20] goto ZAR_2 ' переход на второй этап зарядки endif if U>14800 then ' если напряжение зарядки выше 14.8V -> U_PWM=U_PWM-1 ' уменьшаемаем скважность ШИМ -> уменьшаемаем U if U_PWM<=1 then U_PWM=1 endif else ' напряжение меньше 14.8V if I увеличиваем ток if U_PWM>=254 then U_PWM=254 endif else ' ток больше 20% от 0.1*Ah U_PWM=U_PWM-1 ' уменьшаемаем скважность ШИМ -> уменьшаемаем ток if U_PWM<=1 then U_PWM=1 endif endif endif until (T_ZAR_MIN<>MINUT) AND (T_ZAR_SEC=SECUND) ' повторяли действия пока не выполнилось условие until ' (пока не прошла 1min) if (ICONTROL<=EMK*3) and (UAKK>13200) then ' если усредненный ток зарядки в mА sound BIP,[100,20] ' меньше 3% от 0.1*Ah, то аккум.заряжен на 100% --> goto SAVE_MODE ' переход на этап хранения заряда и контроля endif low U_REG ' сброс на выходе U_REG (PORTC.0) на ноль low LED_YELLOW ' гасим желтый светодиод - нет зарядки for P=1 to 800 pause 10 ' пауза 8000/4Mhz=2sec next P goto ZAR_3_START '------------------------------------------------------------------------------- SAVE_MODE: ' этап контроля и хранение заряда батареи импульсным 20% током ' с паузами, поддержка напряжения не ниже 13.2V U_PWM=0 ' убираем ШИМ на выходе, отключаем зарядку low U_REG ' сброс на выходе U_REG (PORTC.0) на ноль low LED_YELLOW ' гасим желтый светодиод - нет зарядки UAKK=0 lcdout $FE,$80," ",$A4,$41,$4B,$4F,$48,$AB,$45,$48," ",$A8,$50,$4F,$E1,$45,$43,$43," " lcdout $FE,$C0," ",$A4,$41,$50,$B1,$E0,$4B,$A5,". " lcdout $FE,$94," ",$48,$41,$AB,$41,$54," ",$A8,$50,$4F,$E1,$45,$43,$43," " lcdout $FE,$D4," ",$43,$4F,$58,$50,$41,$48,$45,$48,$A5,$B1," ",$A4,$41,$50,$B1,$E0,$41," " ' вывод информации на русском из таблицы символов дисплея ' " ЗАКОНЧЕН ПРОЦЕСС " ' " ЗАРЯДКИ. " ' " НАЧАТ ПРОЦЕСС " ' " СОХРАНЕНИЯ ЗАРЯДА " for P=1 to 400 pause 10 ' пауза 4000/4Mhz=1sec next P SECUND_ZAR=SECUND MINUT_ZAR=MINUT HOUR_ZAR=HOUR DAY_ZAR=DAY SECUND=0 MINUT=0 HOUR=0 DAY=0 LCD_MIN=MINUT ' записываем в переменную показания минут LCD_SEC=SECUND ' записываем в переменную показания секунд '------------------------------------------------------------------------------- SAVE_MODE_START: if (LCD_MIN<>MINUT) AND (LCD_SEC=SECUND) then ' прошла 1min - гасим дисплей low LCD endif if AVAR = 1 then ' если сигнал AVAR активен (пропало 230V), то goto AVAR_MODE ' переход на п/программу аварийного режима endif gosub ACP_T ' переход на п/программу считывания данных T gosub DC_FAN ' переход на п/программу работы вентилятора gosub ACP_I ' переход на п/программу считывания данных I gosub ACP_U ' переход на п/программу считывания данных АЦП напр. UAKK = U gosub ACP_UAC ' переход на п/программу считывания данных АЦП 230V if Knopka_MINUS = 0 then ' если нажата кнопка "-" sound BIP,[100,20] LCD_MIN=MINUT ' сброс счетчика - записываем в переменную новые показания минут LCD_SEC=SECUND ' сброс счетчика - записываем в переменную новые показания секунд high LCD goto ZAR_3 ' переход на третий этап зарядки endif if Knopka_PLUS = 0 then ' если нажата кнопка "+" sound BIP,[100,20] LCD_MIN=MINUT ' сброс счетчика - записываем в переменную новые показания минут LCD_SEC=SECUND ' сброс счетчика - записываем в переменную новые показания секунд high LCD endif if Knopka_OK = 0 then ' если нажата кнопка "OK" sound BIP,[100,20] LCD_MIN=MINUT ' сброс счетчика - записываем в переменную новые показания минут LCD_SEC=SECUND ' сброс счетчика - записываем в переменную новые показания секунд high LCD endif ' вывод информации, dec 1,2,3 -колличество выдимых знаков if DAY=0 then if HOUR=0 then lcdout $FE,$80, $E0,$45,$A3,$A9,$50,$48,$AE,$A6," ",$50,$45,$A3,$A5,$4D," ",dec2 MINUT,":",dec2 SECUND else ' HOUR>0 lcdout $FE,$80, $E0,$45,$A3,$A9,$50,$48,$AE,$A6," ",$50,$45,$A3,$A5,$4D," ",dec2 HOUR,"h",dec2 MINUT endif else ' DAY>0 lcdout $FE,$80, $E0,$45,$A3,$A9,$50,$48,$AE,$A6," ",$50,$45,$A3,$A5,$4D," ",dec2 DAY,"d",dec2 HOUR endif lcdout $FE,$C0,"U(230)=",DEC3 UAC,"V t=",DEC2 T,"'C" lcdout $FE,$94,"U(akk)=",DEC2 UAKK/1000,".",DEC1 UAKK/100,"V ",dec2 EMK,"A/h" if DAY_ZAR=0 then if HOUR_ZAR=0 then lcdout $FE,$D4, $42,$50,$45,$4D,$B1," ",$A4,$41,$50,$B1,$E0,$4B,$A5," ",dec2 MINUT_ZAR,":",dec2 SECUND_ZAR else ' HOUR_ZAR>0 lcdout $FE,$D4, $42,$50,$45,$4D,$B1," ",$A4,$41,$50,$B1,$E0,$4B,$A5," ",dec2 HOUR_ZAR,"h",dec2 MINUT_ZAR endif else ' DAY_ZAR>0 lcdout $FE,$D4, $42,$50,$45,$4D,$B1," ",$A4,$41,$50,$B1,$E0,$4B,$A5," ",dec2 DAY_ZAR,"h",dec2 HOUR_ZAR endif ' вывод информации на дисплей ' "ДЕЖУРНЫЙ РЕЖИМ --:--" ' "U(230)=225V t=25'C" ' "U(akk)=13.2V 62A/h" ' "ВРЕМЯ ЗАРЯДКИ --:--" if UAKK<12600 then ' если Uакк в mV меньше 12.6V (все равно разрядился, sound BIP,[100,20] ' несмотря на импульсы Save), high LCD ' зажигаем дисплей и goto PRE_ZAR ' переход на зарядку endif if UAKK<13200 then ' если Uакк в mV меньше 13.2V, то goto PUSK_IMPULSA endif goto SAVE_MODE_START '------------------------------------------------------------------------------- PUSK_IMPULSA: T_IMP_SEC=SECUND ' записываем в переменную новые показания секунд ' (ограничения времени импулься зарядки 1sec) repeat ' повторять действия пока не выполнится условие until high U_REG ' на выходе U_REG (PORTC.0) выдаем сигнал "1"-(5V) high LED_YELLOW ' зажигаем желтый светодиод - происходит зарядка gosub ACP_I ' переход на п/программу считывания данных АЦП тока until (I>EMK*20) or (T_IMP_SEC<>SECUND) ' повторяли действия пока не выполнилось условие until ' (импульс тока зарядки больше 20% от 0.1*Ah или ' прошла 1сек). low U_REG ' сброс на выходе U_REG (PORTC.0) на ноль low LED_YELLOW ' гасим желтый светодиод - нет зарядки for P=1 to 800 pause 10 ' пауза 8000/4Mhz=2sec между импульсами зарядки next P goto SAVE_MODE_START '------------------------------------------------------------------------------- AVAR_MODE: ' этап при пропадании сетевого напряжения 230V sound BIP,[100,10] high LCD ' включаем индикатор SECUND=0 MINUT=0 HOUR=0 DAY=0 low FAN_MIN ' для экономии выкл.вентилятор зарядки блока питания low FAN_MAX '------------------------------------------------------------------------------- AVAR_MODE_START: gosub ACP_U ' переход на п/программу считывания данных АЦП напр. UAKK = U gosub ACP_UAC ' переход на п/программу считывания данных АЦП 230V if HOUR=0 then lcdout $FE,$80," ",$50,$45,$A3,$A5,$4D," ",$41,$42,$41,$50,$A5,$A5,"! ",dec2 MINUT,":",dec2 SECUND else ' HOUR>0 lcdout $FE,$80," ",$50,$45,$A3,$A5,$4D," ",$41,$42,$41,$50,$A5,$A5,"! ",dec2 HOUR,"h",dec2 MINUT endif lcdout $FE,$C0," U(avar)=",DEC3 UAC,"V " lcdout $FE,$94," U(akk)=",DEC2 UAKK/1000,".",DEC1 UAKK/100,"V " lcdout $FE,$D4, $45,$4D,$4B,$4F,$43,$54,$C4," ",$41,$4B,$4B,$A9,$4D,". ",dec2 EMK,"A/h" ' вывод информации, dec 1,2,3 -колличество выдимых знаков ' вывод информации на дисплей ' " РЕЖИМ АВАРИИ! --:--" ' " U(avar)=225V " ' " U(akk)=13.2V " ' "EМКОСТЬ АККУМ. 62A/h" if AVAR = 0 then ' если сигнал AVAR не активен (появилось 230V), goto PRE_ZAR ' переход на контроль и зарядку аккумулятора endif goto AVAR_MODE_START '------------------------------------------------------------------------------- '*************************************************************************** '=========================================================================== ' ПОДПРОГРАММЫ * '=========================================================================== '*************************************************************************** '------------------------------------------------------------------------------- ACP_I: ' подпрограмма считывания I с входа АЦП for Y= 1 to 10 ' запускаем цикл 100 замеров тока, чтобы не было ' пульсаций на дисплее. Делаем цикл в цикле для ' расчета 100(10 в 10) замеров, иначе (при 1 цикле 100) ' происходит ошибка в расчетах тока(I>65836 word). for YY=1 to 10 ' запускаем цикл 10 замеров и усредняем их ADCIN 0,I_ACP ' замеряем колличество ступенек напряжения ' в канале АЦП AN0 и записываем в переменную I_ACP I1=(I_ACP*19)+(I_ACP*61/100) ' 5000mV/255=19.61mV одна ступенька (АЦП 8бит) ' расчет U в mV (соответствующий току) I1SUMM=I1SUMM+I1 next YY I1=I1SUMM/10 ' усредняем 10 показаний I1SUMM=0 ISUMM=ISUMM+I1 next Y I=ISUMM/10 ' усредняем 10 показаний ISUMM=0 ' расчет падения напряжения в mV на изм.резисторе R=0.05Om DU=I/10 ' ОУ в схеме x10, мы /10 I=I*2 ' перевод mV в mA. По схеме (коэффициент ОУ =10), ' при 1000mA на R=0.05Om имеем 50mV x2 x10(ОУ)=1000mA return '------------------------------------------------------------------------------- ACP_U: ' подпрограмма считывания U с входа АЦП for Y=1 to 5 ' запускаем циклы 50 замеров и усредняем их for YY=1 to 10 ADCIN 1,U_ACP ' замеряем колличество ступенек напряжения ' в канале АЦП AN1 и записываем в переменную U_ACP U1=(U_ACP*19)+(U_ACP*61/100) ' 5000mV/255=19.61mV одна ступенька (АЦП 8бит) ' расчет U в mV и перевод в mV U1SUMM=U1SUMM+U1 next YY U1=U1SUMM/10 ' усредняем 10 показаний U1SUMM=0 USUMM=USUMM+U1 next Y U=USUMM/5 ' усредняем 5 показаний USUMM=0 U=U*10 ' расчет U с коэффициентом 10 (делитель 1/10 по схеме) return '------------------------------------------------------------------------------- ACP_UAC: ' подпрограмма считывания U AC230 с входа АЦП for Y=1 to 5 ' запускаем циклы 50 замеров и усредняем их for YY=1 to 10 ADCIN 3,UAC_ACP ' замеряем колличество ступенек напряжения ' в канале АЦП AN3 и записываем в переменную UAC_ACP UAC1=(UAC_ACP*19)+(UAC_ACP*61/100) ' 5000mV/255=19.61mV одна ступенька (АЦП 8бит) ' расчет UAC в mV UAC1SUMM=UAC1SUMM+UAC1 next YY UAC1=UAC1SUMM/10 ' усредняем 10 показаний UAC1SUMM=0 UACSUMM=UACSUMM+UAC1 next Y UAC=UACSUMM/5 ' усредняем 5 показаний UACSUMM=0 UAC=UAC*10 ' расчет U с коэффициентом 10 (делитель 1/10 по схеме) ' перевод V(mV) в 230(V). При 19200mV(вых)=237V(вх) UAC=UAC/81 ' 19200/237=81 return '------------------------------------------------------------------------------- ACP_T: ' подпрограмма считывания T с входа АЦП for Y=1 to 20 ' запускаем цикл 20 замеров и усредняем их ADCIN 4,T_ACP ' замеряем колличество ступенек напряжения ' в канале АЦП AN4 и записываем в переменную T_ACP T=(T_ACP*19)+(T_ACP*61/100) ' 5000mV/255=19.61mV одна ступенька (АЦП 8бит) ' расчет U в mV TSUMM=TSUMM+T next Y T=TSUMM/20 ' усредняем 20 показаний TSUMM=0 ' перевод mV в t'C по уравнению прямой ' Rt(15k)-11.26k/22'C и 6.15k/36.6'C ' (22'C)11.26k->2.648V,(36'C)6.15k->1.904V ' уравнениe прямой через две точки T=(6680/93)-(T*7/372) ' A(2648mV;22'C) и B(1904mV;36'C) return '------------------------------------------------------------------------------- DC_FAN: ' подпрограмма контроля работы вентилятора if T<34 then ' если температура T<34 градусов, то low FAN_MIN ' на выходе FAN_MIN (PORTC.3)--> 0 low FAN_MAX ' на выходе FAN_MAX (PORTC.2)--> 0 endif if T>35 AND T<39 then ' если температура 35 1 low FAN_MAX ' на выходе FAN_MAX (PORTC.2)--> 0 endif if T>40 then ' если температура T>40 градусов, то low FAN_MIN ' на выходе FAN_MIN (PORTC.3)--> 0 high FAN_MAX ' на выходе FAN_MAX (PORTC.2)--> 1 endif if T>55 then ' если температура T>55 градусов, то перегрев! low FAN_MIN ' на выходе FAN_MIN (PORTC.3)--> 0 high FAN_MAX ' на выходе FAN_MAX (PORTC.2)--> 1 U_PWM=U_PWM-10 ' уменьшаем ступенчато скважность ШИМ на 10 if U_PWM<10 then U_PWM=10 endif sound BIP,[100,5] ' -> уменьшаемаем U и I lcdout $FE,$80," ",$A8,$45,$50,$45,$A1,$50,$45,$42," !!! " ' вывод информации на дисплей ' " ПЕРЕГРЕВ !!! " ' "U(230)=225V t=25'C" ' "U(akk)=14.8V/(13.2V)" ' "I(akk)=2.5A 62A/h" for P=1 to 150 pause 10 ' пауза 1500 next P endif return '------------------------------------------------------------------------------- ACP_TO_LCD: ' подпрограмма отображения данных на LCD в процессе зарядки if DAY=0 then if HOUR=0 then lcdout $FE,$80,dec1 STEEP,"-",$AC,$41,$A1," ",$A4,$41,$50,$B1,$E0,$4B,$A5," ",dec2 MINUT,":",dec2 SECUND else ' HOUR>0 lcdout $FE,$80,dec1 STEEP,"-",$AC,$41,$A1," ",$A4,$41,$50,$B1,$E0,$4B,$A5," ",dec2 HOUR,"h",dec2 MINUT endif else ' DAY>0 lcdout $FE,$80,dec1 STEEP,"-",$AC,$41,$A1," ",$A4,$41,$50,$B1,$E0,$4B,$A5," ",dec2 DAY,"d",dec2 HOUR endif lcdout $FE,$C0,"U(230)=",DEC3 UAC,"V t=",DEC2 T,"'C" lcdout $FE,$94,"U(akk)=",DEC2 U/1000,".",DEC1 U/100,"V/(",DEC2 UAKK/1000,".",DEC1 UAKK/100,"V)" lcdout $FE,$D4,"I(akk)=",DEC1 I/1000,".",DEC1 I/100,"A ",dec2 EMK,"A/h" ' вывод информации, dec 1,2,3 -колличество выдимых знаков ' вывод информации на дисплей ' "X-ШАГ ЗАРЯДКИ --:--" ' "U(230)=225V t=25'C" ' "U(akk)=14.8V/(13.2V)" ' "I(akk)=2.5A 62A/h" return '------------------------------------------------------------------------------- disable ' disable-enable границы где прерывания не работают ' исключаем действие прерывания само на себя. MyINT: 'подпрограмма прерываний таймера TMR1 (отсчет времени 0.5сек/2Гц) If PIR1.0=1 Then ' Проверим, было ли вызвано прерывание ' именно переполнением таймера TMR1. Если это так, PIR1.0=0 ' то сразу сбросим флаг этого прерывания, ' чтобы при выходе снова не попасть в обработчик. TMR1=3040 ' Установка предварительного значения таймера ' на 4 больше, чем вначале (3036)-4 цикла уходят на запись числа. F=F+1 if F=2 then ' :2,получаем 1Гц из 2импульсов прерывания по 0.5сек/2Гц F=0 ' для индикации часов SECUND=SECUND+1 if SECUND=60 then SECUND=0 MINUT=MINUT+1 if MINUT=60 then MINUT=0 HOUR=HOUR+1 if HOUR=24 then HOUR=0 DAY=DAY+1 endif endif endif endif endif resume enable end '------------------------------------------------------------------------------- TEST: 'подпрограмма теста и настройки устройства pwm U_REG,U_PWM,1 ' на выходе U_REG (PORTC.0) выдаем сигнал ШИМ 1 пачку(5ms при 4MHz) gosub ACP_U ' переход на п/программу считывания данных АЦП напр. gosub ACP_UAC ' переход на п/программу считывания данных АЦП 230 напр. gosub ACP_I ' переход на п/программу считывания данных АЦП тока gosub ACP_T ' переход на п/программу считывания данных АЦП T gosub DC_FAN ' переход на п/программу контроля температуры lcdout $FE,$80," -",$50,$45,$A3,$A5,$4D," ",$48,$41,$43,$54,$50,$4F,$A6,$4B,$A5,"- " lcdout $FE,$C0,"U(230)=",DEC3 UAC,"V t=",DEC2 T,"'C" lcdout $FE,$94,"U=",DEC2 U/1000,".",DEC1 U/100,"V-",DEC4 DU,"mV/",DEC2(U-DU)/1000,".",DEC1 (U-DU)/100,"V" lcdout $FE,$D4,"I=",DEC1 I/1000,".",DEC1 I/100,"A/",DEC4 I,"mA (",DEC3 U_PWM,")" ' вывод информации на дисплей, ' dec 1,2,3 -колличество выдимых знаков ' " -РЕЖИМ НАСТРОЙКИ- " ' "U(230)=225V t=25'C" ' "U=14.8V-0250mV/14.7V" ' "I=2.5A/2500mA (127)" if Knopka_MINUS = 0 then ' если нажата кнопка "-" sound BIP,[110,2] U_PWM=U_PWM-1 ' уменьшаемаем скважность ШИМ -> уменьшаемаем U if U_PWM<=1 then U_PWM=1 endif endif if Knopka_PLUS = 0 then ' если нажата кнопка "+" sound BIP,[110,2] U_PWM=U_PWM+1 ' увеличиваем скважность ШИМ -> увеличиваем U if U_PWM>=254 then U_PWM=254 endif endif goto TEST '-------------------------------------------------------------------------------