; ; Измеритель емкости и ESR электролитических конденсаторов ; C/ESR meter ; Автор Гинц Олег ; Версия 1.01 ; Дата 20/04/2007 ; ; В программе использованы фрагменты кода измерителя FLC ; Александра Буевского, г.Минск, Беларусь ; НАЗНАЧЕНИЕ ВЫВОДОВ КОНТРОЛЛЕРА PIC16F873A ;*************************************************************************************** ;*НОГА * ИМЯ * НАЗНАЧЕНИЕ ;*************************************************************************************** ; 1 * MCLR/Vpp * Сброс ; 2 * RA0/AN0 * выход ДУ (Ку=330) ; 3 * RA1/AN1 * выход ДУ (Ку=33) ; 4 * RA2/AN2/Vref- * Кн. Set coeff./Set "0" ; 5 * RA3/AN3/Vref+ * ; 6 * RA4/T0CKI * Кн.+/Test ; 7 * RA5/AN4/SS * Кн.- ; 8 * Vss * GND ; 9 * OSC1/CLKIN * Кварц 20 МГц ; 10 * OSC2/CLKOUT * Кварц 20 МГц ; 11 * RC0/T1OSO/T1CKI * Заряд Сх, I=10mA ; 12 * RC1/T1OSI/CCP2 * Разряд Сх ; 13 * RC2/CCP1 * Компаратор верхнего уровня зарядки Сх ; 14 * RC3/SCK/SCL * вх."-" на землю ; 15 * RC4/SDI/SDA * вх."+" на Сх ; 16 * RC5/SDO * вх."-" на Сх ; 17 * RC6/TX/CK * Компаратор нижнего уровня зарядки Сх ; 18 * RC7/RX/DT * ; 19 * Vss * +5V ; 20 * Vdd * GND ; 21 * RB0/INT * LCD_D4 ; 22 * RB1 * LCD_D5 ; 23 * RB2 * LCD_D6 ; 24 * RB3/PGM * LCD_D7 ; 25 * RB4 * LCD_R/S ; 26 * RB5 * LCD_E ; 27 * RB6/PGC * ; 28 * RB7/PGD * ;**************************************************************************************** Port_A_Config equ 0xFF ; Port A bit equates Kn_Set equ 2 Kn_Plus equ 4 Kn_Minus equ 5 Port_B_Config equ b'11000000' Port_C_Config equ b'11000100' ; Port C bit equates Cap_Charge equ 0 Cap_Discharge equ 1 Comp_Up equ 2 In_N_Gnd equ 3 In_P_Cx equ 4 In_N_Cx equ 5 Comp_Low equ 6 ESR_ready equ b'00110011' ;вкл. разряд, "+" и "-" ДУ на Сх ESR_start equ b'00110000' ;вкл. заряд, "+" и "-" ДУ на Сх Cap_ready equ b'00011011' ;вкл. раздяд, "-" ДУ на землю, "+" на Сх Cap_start equ b'00011000' ;вкл. заряд, "-" ДУ на землю, "+" на Сх Cap_start2 equ b'00110000' ;вкл. заряд, "-" ДУ на Cx, "+" на Сх Max_Count equ .70 ;максимальное число (1 байт, не более 256) переполнений TMR0 при счете ;шаг счета - 0.2 мкс, 65536*0.2=13107.2 мкс - одно переполнение ;или при I=10mA 15 отсчетов/мкФ 65536/15=4369 мкф - одно переполнение ;Пусть Сх мах=150000мкФ, 150000/4369=34 ;Учитывая время заряда до нижней границы константу надо удвоить ;**************************************************************************************** list p=PIC16F873a #include P16F873a.inc ; ; 20.000 MHz __CONFIG _CP_OFF & _BODEN_OFF & _HS_OSC & _WRT_OFF & _WDT_OFF & _PWRTE_ON & _DEBUG_OFF & _CPD_OFF & _LVP_OFF ; #define _BAT PORTA,1 ; 0- low bat #define _RS PORTB,4 #define _E PORTB,5 CBLOCK 0x35 ;0x20-0x34 for FLOATING POINT LIBRARY ; Блоки данных W_TEMP ;сохранение контекста при прерываниях STATUS_TEMP PCLATH_TEMP Dly0 ;Stores 3 bytes of data for the delay count Dly1 ;Dly0 is the least significant byte Dly2 ;while Dly3 is the most significant byte ; Temp Temp1 Temp2 Temp3 Temp4 Count1 Count2 T0 T1 ; Блоки данных T2 ; Старший байт T3 T4 T5 ; Младший байт AX ; Старший байт A0 A1 A2 ; Младший байт A3 A4 A5 BCD0 ; Младший байт BCD1 BCD2 BCD3 BCD4 ; Старший байт U330_L ;Напряжение с выхода ДУ, Ку=330, младший байт U330_H ;Напряжение с выхода ДУ, Ку=330, старший байт U33_L ;Напряжение с выхода ДУ, Ку=33, младший байт U33_H ;Напряжение с выхода ДУ, Ку=33, старший байт TMR1_Count ;Счетчик переполнений TMR1 TMR0_Count ;Счетчик переполнений TMR0 Flags EE_ADR ;вспомогательная ячейка для работы с EEPROM EE_DATA NZ ;число значащих разрядов при выводе на индикатор NC ;номер константы Const_ADR ;адрес константы в EEPROM ENDC CBLOCK 0xB5 W_TEMP1 ;сохранение контекста при прерываниях ENDC ;========================= ; МАКРОСЫ ;========================= bank0 macro bcf STATUS, RP0 endm bank1 macro bsf STATUS, RP0 endm Dly24 MACRO DLY ;Take the delay value argument from the macro, precalculate ;the required 3 RAM values and load the The RAM values Dly2,Dly1 ;and Dly0. banksel Dly0 movlw DLY & H'FF' movwf Dly0 movlw DLY >>D'08' & H'FF' movwf Dly1 movlw DLY >>D'16' & H'FF' movwf Dly2 ;Bytes are shifted and anded by the assembler to make user ;calculations easier. endm ;========================== ORG 0x2100 ; Область EEPROM ; Данные ; Адрес в EEPROM ; корректирующие коэффициенты для: USR_1 DE 0x00, 0x00, 0x03, 0xE8 ; 1 - предела 1 Ом USR_10 DE 0x00, 0x00, 0x03, 0xE8 ; 1 - предела 10 Ом USR_Cx DE 0x00, 0x00, 0x03, 0xE8 ; 1 - измерения емкости ;K_ESR_1 DE 0x7F, 0x00, 0x00, 0x00 ; 1 - предела 1 Ом ;K_ESR_10 DE 0x7F, 0x00, 0x00, 0x00 ; 1 - предела 10 Ом ;K_Cx DE 0x7F, 0x00, 0x00, 0x00 ; 1 - измерения емкости ;numbers in FLOATING POINT LIBRARY format U0_ESR_1 DE 0x85, 0x16, 0x00, 0x00 ; 75=85160000 - "0" на пределе 1 Ом U0_ESR_10 DE 0x81, 0x60, 0x00, 0x00 ; 7=81600000 - "0" на пределе 10 Ом ; множители для расчетов: M_ESR_1 DE 0x75, 0x40, 0x30, 0x0C ; 1/682=7540300C M_ESR_10 DE 0x78, 0x74, 0x89, 0x8D ; 1/67=7874898D M_Cx DE 0x74, 0x2E, 0xC3, 0x3E ; 1/(15*100)=742EC33E sub_Cx DE 0x80, 0x40, 0x00, 0x00 ; 3=80400000 - вычитается из показаний TMR1 ;========================== org 0x700 ; посделние 256 байт 1-й страницы памяти программ Table addwf PCL,F omega dt b'00000000' ;знак омега dt b'00001110' dt b'00010001' dt b'00010001' dt b'00010001' dt b'00001010' dt b'00011011' dt b'00000000' mu dt b'00000000' dt b'00000000' dt b'00010010' dt b'00010010' dt b'00010010' dt b'00011110' dt b'00010001' dt b'00010000' _Const dt "Coeff. for",0 _ESR dt "ESR",0 _Cx dt " Cx ",0 _Time_out dt "Cx ---",0 _1_ohm dt " 1 ",1,0 _10_ohm dt " 10 ",1,0 _tst_1 dt "1",1,"=",0 _tst_10 dt " 10",1,"=",0 _write_U0 dt "U0 ---> EEPROM ",0 _ready dt "It is ready!",0 org 0x00 ;******************************************************************************* ; НАЧАЛО ПРОГРАММЫ ;******************************************************************************* nop ;for MPLAB-ICD2 goto init ;------------------ Interrupt ------------------ org 0x004 movwf W_TEMP ;save W swapf STATUS,W ;swap STATUS, W clrf STATUS movwf STATUS_TEMP ;save status movf PCLATH,W movwf PCLATH_TEMP ;save PCLFTH decfsz TMR0_Count goto restore_context bsf Flags,0 ;Time Out! goto stop_TMR1 restore_context bcf INTCON,T0IF ;clear interrupt flag movf PCLATH_TEMP,W movwf PCLATH swapf STATUS_TEMP,W ;fetch status, reswap nibbles movwf STATUS ;restore status swapf W_TEMP,F ;swap nibbles in preparation swapf W_TEMP,W ;for the swap restoration of w retfie ;return from interrupt ;----------------------------------------------- init banksel INTCON clrf Flags clrf INTCON clrf PCLATH clrf PORTA clrf PORTB movlw ESR_ready ;вкл. разряд, "+" и "-" ДУ на Сх movwf PORTC banksel TRISA movlw Port_A_Config movwf TRISA ;инициализация АЦП movlw b'10000100';правое выравнивание, Vdd, Vss, AN0, AN1, AN3 movwf ADCON1 movlw Port_B_Config movwf TRISB movlw Port_C_Config movwf TRISC ; Инициализация LCD в 4-х битный режим InitLCD call Delay_5_ms call Delay_5_ms call Delay_5_ms ;пауза 15 мс после вкл питания banksel PORTB movlw 3 movwf Count1 movwf PORTB SetLoop bsf _E ;для инициализации LCD 3 раза посылается команда 0x30 nop nop nop bcf _E call Delay_5_ms decfsz Count1,f goto SetLoop movlw 2 ; 4-x битный movwf PORTB call Send movlw 28 ; 4-х битный, 2 строки, 5х7 call CmdLCD movlw 0C ; Включить дисплей call CmdLCD movlw 6 call CmdLCD call Load_ZG ; Загрузить символы мю и омега call ClrDSP ; Очистить дисплей ;-------------------------------------------------- btfsc PORTA, Kn_Set ; goto Main ;------------ режим установки констант ------------ goto c_1 Const_Loop btfss PORTA, Kn_Plus call IncB btfss PORTA, Kn_Minus call DecB btfsc PORTA, Kn_Set goto Const_Loop btfss Flags,5 ;флаг изменения константы goto c_3 call Save_Const ;константа изменилась, надо сохранить c_3 incf NC,F movf NC,W sublw 3 ;число констант btfss STATUS,Z goto $+2 c_1 clrf NC bcf Flags,5 ;Очищаем флаг изменения константы call ClrDSP ; Очистить дисплей movlw LOW _Const call Read_String movlw HIGH $ movwf PCLATH movf NC,W addwf PCL,F ;табличный переход goto const_1_ohm ;+0 goto const_10_ohm ;+1 goto const_Cx ;+2 c_2 call ShowX goto Const_Loop const_1_ohm movlw LOW USR_1 movwf Const_ADR call EEPROM_To_B movlw LOW _1_ohm call Read_String goto c_2 const_10_ohm movlw LOW USR_10 movwf Const_ADR call EEPROM_To_B movlw LOW _10_ohm call Read_String goto c_2 const_Cx movlw LOW USR_Cx movwf Const_ADR call EEPROM_To_B movlw LOW _Cx call Read_String goto c_2 ;------- Инициализация модуля АЦП ------ Main ; banksel ADCON1 ; movlw b'10000100';правое выравнивание, Vdd, Vss, AN0, AN1, AN3 ; movwf ADCON1 ESR_measure banksel PORTC movlw ESR_start ; вкл. заряд, "+" и "-" ДУ на Сх movwf PORTC movlw 0x4 ;Задержка 3.6мкс (18 циклов) для окончания перех.процессов - ПОДОБРАТЬ!!! call Delay_go bcf PORTC, In_P_Cx ;отключаем Сзап от Сх nop ;??? bsf PORTC, Cap_Charge ;выкл. Iзар. ;Измеряем напряжение с выхода диф.усилителя с Ку=330 banksel ADCON0 movlw b'10000001' ;Fosc/32, канал 0, модуль АЦП вкл. movwf ADCON0 call Delay_20_us bsf ADCON0,2 ;начать аналого-цифровое преобразование btfsc ADCON0,2 goto $-1 ; ждем окончания преобразования movf ADRESH,W movwf U330_H banksel ADRESL movf ADRESL,W banksel U330_L movwf U330_L ;Измеряем напряжение с выхода диф.усилителя с Ку=33 banksel ADCON0 movlw b'10001001' ;Fosc/32, канал 1, модуль АЦП вкл. movwf ADCON0 call Delay_20_us bsf ADCON0,2 ;начать аналого-цифровое преобразование btfsc ADCON0,2 goto $-1 ; ждем окончания преобразования movf ADRESH,W movwf U33_H banksel ADRESL movf ADRESL,W banksel U33_L movwf U33_L ;------------ Если ESR>10 Ом, измерение емкости не выполняем ------------ clrf Flags movlw 0x03 subwf U33_H,W ;если показания АЦП>=0x300 (768) btfss STATUS,Z goto Cx_0 ;переход на измерение емкости bsf Flags,0 ;взводим флаг Time Out goto Cx_3 ;------------ Измерение емкости конденсатора ------------ Cx_0 movlw Cap_ready ;вкл. раздяд, "-" ДУ на землю, "+" на Сх movwf PORTC call TMR0_init ;Запускаем TMR0 для предотвращения зависаний при измерении емкости call Delay_200_us btfss PORTC, Comp_Low ; 1 - Cx разрядился goto $-2 ;ждем снова 200 мкс call Delay_200_us ;для надежности еще задержка call TMR1_init movlw 0x03 subwf U330_H,W ;если показания АЦП>=0x300 (768) btfss STATUS,Z ;т.е. ESR>1 Ом, емкость измеряем с компенсацией ESR goto Cx_1 movlw Cap_start2 ;вкл. заряд, "-" ДУ на Cx, "+" на Сх movwf PORTC movlw 0x4 ;Задержка 3.6мкс (18 циклов) для заряда С на "-" входе ДУ call Delay_go bcf PORTC,In_N_Cx ;отключаем "-" вход ДУ от Сх goto Cx_2 Cx_1 movlw Cap_start ;вкл. заряд, "-" ДУ на землю, "+" на Сх movwf PORTC Cx_2 btfsc PORTC, Comp_Low ; 0 - Cx зарядился до нижней границы goto $-1 bsf T1CON, TMR1ON ; запускаем таймер tst_charge btfss PORTC,Comp_Up; 0 - Cx зарядился до верхней границы goto stop_TMR1 btfsc PIR1, TMR1IF ; TMR1 переполнен? call Inc_count goto tst_charge stop_TMR1 clrf T1CON ;остановить TMR1 clrf INTCON ;запрещаем прерывания btfsc PIR1, TMR1IF ;проверим последний раз на переполнение таймера call Inc_count ;было переполнение Cx_3 movlw Cap_ready ;вкл. раздяд, "-" ДУ на землю, "+" на Сх movwf PORTC ;-------------------------------------------------------- ;Выводим результат на индикатор ; call CursorHome call ClrDSP ;Timeout btfss Flags,0 goto Disp_Cx movlw LOW _Time_out call Read_String goto Disp_ESR ;-------------------------------------------------------- clrf FPFLAGS bsf FPFLAGS, RND ; флаг округления при расчетах Disp_Cx movlw LOW _Cx call Read_String clrf AEXP movf TMR1_Count,W movwf AARGB0 movf TMR1H,W movwf AARGB1 movf TMR1L,W movwf AARGB2 btfsc PORTA, Kn_Plus goto Calc_Cx call BCD ;Если нажата кнопка плюс, то тестовый вывод movlw BCD4 ;таймера без обработки call Disp_Full goto Disp_ESR Calc_Cx call FLO2424 ;Integer to float conversion movlw low sub_Cx call EEPROM_To_B call FPS24 ;A=A-3 movlw low M_Cx call EEPROM_To_B call FPM24 ;A=A*M_Cx movlw low USR_Cx call X_To_B call INT2424 ;Output: 24 bit 2's complement integer right ;justified in AARGB0, AARGB1, AARGB2 clrf AEXP call BCD bsf Flags,1 ;не выводить лидирующие нули movlw 3 movwf NZ ;число значащих разрядов, остальные будут 0 bsf Flags,3 ;включить проверку знач. разрядов при выводе movlw BCD3 call DispBCD movlw BCD3 ;показания увеличены в 10 раз, call DispBCD ;здесь сотни тысяч мкФ movlw BCD2 ;десятки тысяч мкФ call DispBCD movlw BCD2 ;тысячи мкФ call DispBCD ; если впереди были одни нули, разделитель не выводим btfsc Flags,1 goto next_1 movlw "," ;разделитель тысяч call CharLCD next_1 movlw BCD1 ;сотни мкФ call DispBCD btfsc Flags,1 ;до сотен небыло значащих цифр, bsf Flags,2 ;будем выводить десятые доли мкФ movlw BCD1 ;десятки мкФ call DispBCD bcf Flags,1 ;проверка на =0 не нужна, выводим все подряд movlw BCD0 ;единицы мкФ call DispBCD btfss Flags,2 ;нужен ли вывод десятичной точки goto next_2 ;нет bcf Flags,2 ;да call DispDot ;десятичная точка movlw BCD0 ;десятые мкФ call DispBCD next_2 call DispSP movlw 2 ;код мю call CharLCD movlw "F" call CharLCD ;---------------------------- Disp_ESR btfss PORTA, Kn_Plus goto tst_ESR bcf Flags,4 ;сброс флага больше 10 Ом movlw 0x03 subwf U330_H,W ;если показания АЦП>=0x300 (768) btfsc STATUS,Z ;проверяем второй канал (10 Ом) goto chk_10 ; Канал 1 Ом call ClrA movf U330_H,W ;усилитель Ку=330, предел 1 Ом movwf AARGB0 movf U330_L,W movwf AARGB1 call FLO1624 ;to 24 bit floating point movlw low U0_ESR_1 call EEPROM_To_B call FPS24 ;A=A-U0 - вычитаем смещение нуля movlw low M_ESR_1 call EEPROM_To_B call FPM24 ;A=A*M_ESR_1 movlw low USR_1 call X_To_B goto ESR_to_LCD chk_10 movlw 0x03 subwf U33_H,W ;если показания АЦП>=0x300 (768) btfsc STATUS,Z bsf Flags,4 ;больше 10 Ом ;канал 10 Ом call ClrA movf U33_H,W ;усилитель Ку=33, предел 10 Ом movwf AARGB0 movf U33_L,W movwf AARGB1 call FLO1624 ;to 24 bit floating point movlw low U0_ESR_10 call EEPROM_To_B call FPS24 ;A=A-U0 - вычитаем смещение нуля movlw low M_ESR_10 call EEPROM_To_B call FPM24 ;A=A*M_ESR_10 movlw low USR_10 call X_To_B ESR_to_LCD call SecLine movlw LOW _ESR call Read_String btfss Flags,4 ;>10 ohm? goto next_3 movlw ">" call CharLCD goto next_4 next_3 call DispSP next_4 movlw 0x80 andwf AARGB0,W ;выделяем знак "-" btfsc STATUS,Z goto next_5 ;результат > 0 call ClrA ;результат < 0, выводим одни нули goto next_6 next_5 call INT2424 next_6 bcf Flags,3 ;выключить проверку знач. разрядов при выводе bsf Flags,1 ;не выводить лидирующие нули clrf AEXP call BCD movlw BCD2 call DispBCD movlw BCD2 call DispBCD ;десятки Ом bcf Flags,1 ;проверка на =0 не нужна, выводим все подряд movlw BCD1 ;единицы Ом call DispBCD call DispDot movlw BCD1 call DispBCD movlw BCD0 call DispBCD movlw BCD0 call DispBCD call DispSP movlw 1 ;знак ом call CharLCD end_disp banksel PORTC bsf PORTC, Cap_Discharge ;вкл. разряд Сх call Delay_05_sec banksel PORTC bcf PORTC, Cap_Discharge ;выкл. разряд Сх goto ESR_measure ;Для тестирования - вывод АЦП без обработки ;сразу 2-х каналов (1 и 10 Ом) tst_ESR call SecLine ;канал 1 Ом movlw LOW _tst_1 call Read_String call ClrA movf U330_H,W ;усилитель Ку=330, предел 1 Ом movwf AARGB1 movf U330_L,W movwf AARGB2 call BCD movlw BCD1 call Disp_Full ;канал 10 Ом movlw LOW _tst_10 call Read_String call ClrA movf U33_H,W ;усилитель Ку=33, предел 10 Ом movwf AARGB1 movf U33_L,W movwf AARGB2 call BCD movlw BCD1 call Disp_Full btfsc PORTA, Kn_Set ;проверка кнопки установки нуля goto end_disp ;Сохранение U0 в EEPROM ------------------------ call CursorHome movlw LOW _write_U0 call Read_String ;U0 для l Ом call ClrA movf U330_H,W ;усилитель Ку=330, предел 1 Ом movwf AARGB0 movf U330_L,W movwf AARGB1 call FLO1624 ;to 24 bit floating point call BEQUA movlw LOW U0_ESR_1 movwf Const_ADR call Save_Const ;U0 для l0 Ом call ClrA movf U33_H,W ;усилитель Ку=33, предел 10 Ом movwf AARGB0 movf U33_L,W movwf AARGB1 call FLO1624 ;to 24 bit floating point call BEQUA movlw LOW U0_ESR_10 movwf Const_ADR call Save_Const call Delay_3_sec call ClrDSP movlw LOW _ready call Read_String call Delay_1_sec goto end_disp ;------------------------- TMR1 ------------------------- ;Инициализация таймера TMR1, шаг счета = 0.2 мкс TMR1_init clrf TMR1L clrf TMR1H bcf PIR1, TMR1IF movlw b'00000000'; 1:1 Fosc/4 movwf T1CON clrf TMR1_Count return ;------------------------- TMR1 ------------------------- ;Увеличить счетчик переполнений TMR1 Inc_count bcf PIR1, TMR1IF ;очищаем флаг переполнения таймера incfsz TMR1_Count,F return bsf Flags,0 ;Time out goto stop_TMR1;за отведенное время измерения не дождались окончания заряда ;------------------------- TMR0 ------------------------- ;Инициализация таймера TMR0, шаг счета = 0.2 мкс TMR0_init movlw Max_Count movwf TMR0_Count ;начальное значение счетчика переполнений TMR0 clrf TMR0 ;clear timer movlw OPTION_REG ;Work around the OPTION movwf FSR ;address OPTION_REG -> FSR movlw b'00000111' ; set up timer. 1:256 presc movwf INDF bcf INTCON,T0IF ;clear tmr0 int flag bsf INTCON,T0IE ;enable TMR0 int bsf INTCON,GIE ;enable global interrupts clrf TMR0 ;start timer return ;------------------------- Delay ------------------------- ; Подпрограммы пауз Delay_3_sec ;Пауза 3 сек Dly24 D'937499' ; 3/(4/20000000)/16=937500-1=937499 goto DoDly24 Delay_2_sec ;Пауза 2 сек Dly24 D'624999' ; 2/(4/20000000)/16=625000-1=624999 goto DoDly24 Delay_1_sec ;Пауза 1 сек Dly24 D'312499' ; 1/(4/20000000)/16=312500-1=312499 goto DoDly24 Delay_05_sec ;Пауза 0.5 сек Dly24 D'156249' ; 0.5/(4/20000000)/16=156250-1=156249 goto DoDly24 Delay_5_ms ;Пауза 5 мс Dly24 D'1562' ; 0.005/(4/20000000)/16=1562.5=1562 goto DoDly24 Delay_200_us ;Пауза 200 мкс Dly24 D'62' ; 0.0002/(4/20000000)/16=62.5=62 goto DoDly24 DoDly24 ;16 Tcy per loop movlw H'FF' ;Start with -1 in W addwf Dly0,F ;LSB decrement btfsc STATUS,C ;was the carry flag set? clrw ;If so, 0 is put in W addwf Dly1,F ;Else, we continue. btfsc STATUS,C clrw ;0 in W addwf Dly2,F btfsc STATUS,C clrw ;0 in W iorwf Dly0,W ;Inclusive-OR all variables iorwf Dly1,W ;together to see if we have reached iorwf Dly2,W ;0 on all of them. btfss STATUS,Z ;Test if result of Inclusive-OR's is 0 goto DoDly24 return Delay_20_us movlw 0x1F ;Задержка 20 мкс Delay_go movwf Dly0 decfsz Dly0,F goto $-1 nop nop return ;---------------------- LCD --------------------- ; Перевод указателя на второй символ второй строки SecLine movlw 0xC0 ; Загрузка команды CmdLCD movwf Temp4 ; bcf _RS swapf Temp4, W andlw 0x0F movwf PORTB bsf _E nop nop nop bcf _E movf Temp4, W andlw 0x0F movwf PORTB bsf _E nop nop nop bcf _E ; clrf PORTB call Delay_200_us return ; Перекодировка в ASCII и вывод NumLCD andlw 0x0F ; маска iorlw 0x30 ; ASCII ; Вывод ASCII символа CharLCD movwf Temp4 SendLCD swapf Temp4, W andlw 0x0F iorlw b'00010000' ; RS=1 movwf PORTB bsf _E nop nop nop bcf _E movf Temp4, W andlw 0x0F iorlw b'00010000' ; RS=1 movwf PORTB Send bsf _E nop nop nop bcf _E clrf PORTB call Delay_200_us return CursorHome movlw 0x02 ; Дисплей в исходное состояние goto LongSend ClrDSP movlw 1 ; Очистка дисплея LongSend call CmdLCD goto Delay_5_ms DispDot movlw "." goto CharLCD Disp0 movlw "0" goto CharLCD DispSP movlw " " goto CharLCD ;----------------------------------------------------------- ;Чтение строки из таблицы и вывод на LCD Read_String movwf Count1 decf Count1,F ;коррекция начального смещения movlw HIGH Table movwf PCLATH get_next_s movf Count1,W call Table andlw 0xFF ; проверка на конец строки btfsc STATUS, Z return call CharLCD incf Count1,F goto get_next_s ;---------------------- Load CGRAM LCD --------------------- ;загрузить знакогенератор Load_ZG movlw b'01001000' ; AC in CGRAM=8 call CmdLCD movlw HIGH Table movwf PCLATH movlw .16 ;2 знака по 8 байт movwf Count1 movlw LOW omega-1 movwf Count2 ;смещение в таблице get_s call Table ;получить символ из таблицы call CharLCD incf Count2,F movf Count2,W decfsz Count1,F goto get_s return ;---------------------------------------------------------- ;вывод из переданного в W адреса блока BCD0...4 ;на индикатор Disp_Full movwf FSR ;адрес ячейки для вывода на LCD next_byte swapf INDF,W call NumLCD movf INDF,W call NumLCD ;проверим, добрались ли мы до BCD0 movlw BCD0 subwf FSR,W btfsc STATUS,Z return decf FSR,F goto next_byte ;---------------------- BCD to LCD --------------------- ; Вывод разряда и подготовка к выводу следующего DispBCD movwf FSR NextNibble swapf INDF,F movf INDF,W btfss Flags,1 ;1 - не выводить лидирующие нули goto chk_NZ andlw 0x0F btfsc STATUS,Z return ;пропуск вывода bcf Flags,1 ; эту и все посдедующие цифры выводим chk_NZ btfss Flags,3 ; 1- выводить только NZ разрядов, остальные - 0 goto NumLCD movf NZ,F btfsc STATUS,Z ;счетчик=0? goto Disp0 ;да, выводим 0 decf NZ,F ;нет, выводим то что есть call NumLCD return ;---------------------- BCD --------------------- ; Перекодировка значения из двоичного в десятичный формат BCD movlw 0x20 movwf T1 clrf BCD0 clrf BCD1 clrf BCD2 clrf BCD3 clrf BCD4 BcdLoop rlf AARGB2, F rlf AARGB1, F rlf AARGB0, F rlf AEXP, F rlf BCD0, F rlf BCD1, F rlf BCD2, F rlf BCD3, F rlf BCD4, F decfsz T1, F goto Adjust return Adjust movlw .5 movwf Count2 movlw BCD0 movwf FSR goto ADloop+1 ADloop incf FSR, F call Adjbcd decfsz Count2, F goto ADloop goto BcdLoop Adjbcd movlw 0x03 addwf INDF, W movwf T0 btfsc T0, 3 movwf INDF movlw 0x30 addwf INDF, W movwf T0 btfsc T0, 7 movwf INDF return ;------------------------------------------------------- ; Копирование "по назначению" блока (4 байта) данных ; Temp1 = адрес получателя - указывается старший адрес блока ; Temp2 = адрес источника - указывается старший адрес блока ;CEQUA movlw CX ; C=A Copy_From_A movwf Temp1 ; Xw=A movlw AEXP movwf Temp2 goto Copy BEQUA movlw AEXP ; B=A Copy_To_B movwf Temp2 ; B=Xw movlw BEXP goto Copy_B ;AEQUF movlw FX ; A=F Copy_To_A movwf Temp2 ; A=Xw movlw AEXP Copy_B movwf Temp1 Copy movlw 4 ; Объём блока movwf Count1 Copy_Loop movf Temp2, W movwf FSR movf INDF, W movwf Temp3 movf Temp1, W movwf FSR movf Temp3, W movwf INDF decf Temp1, F ; двигаемся в сторону уменьшения decf Temp2, F ; адресов decfsz Count1, F goto Copy_Loop return ;------------------------------------------------------- X_To_B call EEPROM_To_B ; Загрузка коэффициента X call ASwapB call FLO2424 call FPM24 return ASwapB movlw T5 call Copy_From_A movlw BEXP call Copy_To_A movlw T5 call Copy_To_B return ;------------------------------------------------------- ; Очистка блоков А и В ClrB movlw BEXP ; Очистка блока В goto ClrA+1 ClrA movlw AEXP ; Очистка блока А movwf FSR movlw 4 ;Объем блока movwf Count1 ClrLoop clrf INDF ; Цикл очистки decf FSR, F ; уменьшаем адрес decfsz Count1, F goto ClrLoop return ;------------------------------------------------------- ; Чтение данных из EEPROM в блок B EEPROM_To_B movwf EE_ADR ; Сохраняем адрес ячейки EEPROM movlw BEXP movwf FSR movlw 4 ;Объем блока movwf Count1 EE_read_loop call ReadEEPROM banksel BEXP movwf INDF incf EE_ADR, F decf FSR, F decfsz Count1, F goto EE_read_loop return ; Чтение EEPROM ReadEEPROM movf EE_ADR,W ; banksel EEADR ; банк 2 movwf EEADR ; адрес ячейки EEPROM banksel EECON1 ; банк3 bcf EECON1,EEPGD ;выбрать EEPROM bsf EECON1,RD ;инициализровать чтение banksel EEDATA ; банк2 movf EEDATA,W ; W = EEDATA return ;------------------------------------------------------- ; Запись блока BARG в EEPROM ; Адрес в EEPROM задается в Const_ADR Save_Const movf Const_ADR,W movwf EE_ADR movlw BEXP movwf FSR movlw 4 ;Объем блока movwf Count1 EE_write_loop movf INDF,W movwf EE_DATA call WriteEEPROM banksel BEXP incf EE_ADR, F decf FSR, F decfsz Count1, F goto EE_write_loop return ; Запись EEPROM WriteEEPROM banksel EECON1 ;банк3 btfsc EECON1,WR goto $-1 banksel EE_ADR movf EE_ADR,W banksel EEADR ;банк2 movwf EEADR banksel EE_DATA movf EE_DATA,W banksel EEDATA ;банк2 movwf EEDATA banksel EECON1 ;банк3 bcf EECON1,EEPGD bsf EECON1,WREN movlw 0x55 movwf EECON2 movlw 0xAA movwf EECON2 bsf EECON1,WR nop bcf EECON1,WREN return ;------------------------------------------------------- ; Инкрементирование полублока B IncB bsf Flags,5 ;устанавливаем флаг изменения константы incf BARGB2, F btfsc STATUS, Z incf BARGB1, F goto ShowX ; Декрементирование полублока B DecB bsf Flags,5 ;устанавливаем флаг изменения константы movf BARGB2, F btfsc STATUS, Z decf BARGB1, F decf BARGB2, F ShowX movlw BEXP call Copy_To_A call BCD call SecLine movlw BCD1 call DispBCD call DispDot movlw BCD1 call DispBCD movlw BCD0 call DispBCD movlw BCD0 call DispBCD call Delay_05_sec return ;======================================================= ; PIC16 24 BIT FLOATING POINT LIBRARY #define P16_MAP1 0 #define P16_MAP2 1 include "math16.inc" include "fp24.a16" END