16F876A Вольтамперметр. Проблемы Исходника

Поклонники продукции Microchip Technology Inc тусуются тут.
Ответить
Аватара пользователя
4uvak
Встал на лапы
Сообщения: 99
Зарегистрирован: Чт авг 16, 2012 10:41:42

16F876A Вольтамперметр. Проблемы Исходника

Сообщение 4uvak »

Пишу свою первую прошивку на 16F876A. Вольтамперметр. Написал для начала исходник для вольтметра. Результаты показаний на дисплее отображаются корректно. Вот исходник.

Код: Выделить всё

         LIST     p=16F876A
         #include <P16F876A.inc>
         __CONFIG (_LVP_OFF & _CP_OFF & _CPD_OFF & _PWRTE_OFF & _WDT_ON & _XT_OSC & _BODEN_ON & _DEBUG_OFF )

cblock     0x20
LCD_tmp
LCD_tmp1
Reg_tmp1
Reg_tmp2
lcd_load
Reg_tmpL
Reg_tmpH
bin1
bin2
bcd1
bcd2
bcd3
TenK
Thou
Hund
Tens
Ones
ctr
endc    

#define RS_LCD         LCD_tmp1,RA4 ; назначаем вывод команд RS на PORTA для LCD
#define E_LCD         LCD_tmp1,RA5 ; назначаем вывод команд E на PORTA для LCD
#define LCD_PORT_E_RS PORTA         ; назначаем порт для вывода данных PORTB для LCD
#define LCD_PORT     PORTC         ; назначаем порт для вывода данных PORTC для LCD (8 разрядов)
                         ;;;;;;;;;;;;;;;;;;;
                         ; старт программы ;
                         ;;;;;;;;;;;;;;;;;;;
         org         0
         goto     START
                         ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                         ; инициализация контроллера ;
                         ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
START     bcf         STATUS,RP0 ; переход в банк 0
         banksel     OPTION_REG ; переходим в регистр OPTION_REG
         movlw     b'10001110' ; отключаем подтягивающие резисторы PORTB, включаем предделитель перед WDT 1:64
         movwf     OPTION_REG ; -//-
         banksel     INTCON     ; переходим в регистр INTCON
         movlw     b'00000000' ; глобальный запрет прерываний
         movwf     INTCON     ; -//-
         banksel     PIE1         ; переходим в регистр PIE1
         movlw     b'00000000' ; глобальный запрет периферийных прерываний
         movwf     PIE1         ; -//-
         banksel     PIE2         ; переходим в регистр PIE2
         movlw     b'00000000' ; глобальный запрет прерываний EEPROM, CCP2
         movwf     PIE2         ; -//-
         banksel     TRISA         ; переходим в регистр PORTA
         movlw     b'00000011' ; настраиваем все порты на выход, AN0, AN1 на вход
         movwf     TRISA         ; -//-
         banksel     TRISB         ; переходим в регистр PORTB
         movlw     b'00000000' ; настраиваем все порты на выход
         movwf     TRISB         ; -//-
         banksel     TRISC         ; переходим в регистр PORTC
         movlw     b'00000000' ; настраиваем все порты на выход
         movwf     TRISC         ; -//-
         banksel     T1CON         ; переходим в регистр T1CON
         movlw     b'00000000' ; отключаем модуль T1CON
         movwf     T1CON         ; -//-
         banksel     T2CON         ; переходим в регистр T2CON
         movlw     b'00000000' ; отключаем модуль T2CON
         movwf     T2CON         ; -//-
         banksel     CCP1CON     ; переходим в регистр CCP1CON
         movlw     b'00000000' ; отключаем модуль CCP1
         movwf     CCP1CON     ; -//-
         banksel     CCP2CON     ; переходим в регистр CCP2CON
         movlw     b'00000000' ; отключаем модуль CCP2
         movwf     CCP2CON     ; -//-
         banksel     SSPSTAT     ; переходим в регистр SSPSTAT
         movlw     b'00000000' ; отключаем модуль SSPSTAT
         movwf     SSPSTAT     ; -//-
         banksel     SSPCON     ; переходим в регистр SSPCON
         movlw     b'00000000' ; отключаем модуль SSPCON
         movwf     SSPCON     ; -//-
         banksel     SSPCON2     ; переходим в регистр SSPCON2
         movlw     b'00000000' ; отключаем модуль SSPCON2
         movwf     SSPCON2     ; -//-
         banksel     TXSTA         ; переходим в регистр TXSTA
         movlw     b'00000000' ; отключаем модуль TXSTA
         movwf     TXSTA         ; -//-
         banksel     RCSTA         ; переходим в регистр RCSTA
         movlw     b'00000000' ; отключаем модуль RCSTA
         movwf     RCSTA         ; -//-
         banksel     ADCON0     ; переходим в регистр ADCON0
         movlw     b'00000000' ; отключаем модуль АЦП
         movwf     ADCON0     ; -//-
         banksel     ADCON1     ; переходим в регистр ADCON1
         movlw     b'00000000' ; отключаем модуль АЦП
         movwf     ADCON1     ; -//-
         bsf         STATUS,RP0 ; переход в банк 1
         bcf         STATUS,RP0 ; переход в банк 0
         clrwdt
                         ;;;;;;;;;;;;;;;;;;;;;;;;;
                         ; инициализация дисплея ;
                         ;;;;;;;;;;;;;;;;;;;;;;;;;
         call     del_100ms     ; начальная задержка 100 милисекунд
         movlw     b'00000001' ; очищаем дисплей
         call     LCD_com     ; загружаем команду
         call     del_5ms
         movlw     b'00000110' ; сдвиг курсора вправо
         call     LCD_com     ; загружаем команду
         movlw     b'00001100' ; отключаем курсор
         call     LCD_com     ; загружаем команду
         movlw     b'00010100' ; двигаем курсор вправо
         call     LCD_com     ; загружаем команду
         movlw     b'00111000' ; вкл 8 разрядный ввод данных, размер символа 5х8 символов
         call     LCD_com     ; загружаем команду    
gooo    
         call     OUT_U         ; отправляемся читать данные АЦП, и вывод данных на дисплей
;         call     OUT_I         ; отправляемся читать данные АЦП, и вывод данных на дисплей
         call     del_100ms
         call     del_100ms
         clrwdt
         goto     gooo

OUT_U ; выводим U на дисплей содержимое регистров Thou, Hund, Tens, Ones (тысячи, сотни, десятки, единицы)
         banksel     ADCON0     ; переходим в регистр ADCON0
         movlw     b'01000001' ; включаем модуль АЦП, RA0 - вход, Fosc/8
         movwf     ADCON0     ; -//-
         banksel     ADCON1     ; переходим в регистр ADCON1
         movlw     b'10000000' ; включаем правое выравнивание
         movwf     ADCON1     ; -//-
         bcf         STATUS,RP0 ; переход в банк 0
         bsf         ADCON0,2     ; включаем преобразование АЦП
         call     del_20mcs
         btfsc     ADCON0,2     ; ожидаем завершения
         goto     $-1         ; преобразования
         movfw     ADRESH     ; перепишем результат преобразования
         movwf     Reg_tmpH     ; в старший временный регистр
         banksel     ADRESL     ; переходим в регистр ADRESL
         movfw     ADRESL     ; перепишем результат преобразования
         bcf         STATUS,RP0 ; переход в банк 0
         movwf     Reg_tmpL     ; в младший временный регистр

         call     TRANSFORMER_dig ; перекодируем двоичное число результата преобразования в десятичное
         movlw     0x80         ; курсор в пределах первой строки ( 0x80 - начало )
         call     LCD_com     ; загружаем команду
         movlw     0x55         ; U
         call     LCD_dig     ; загружаем данные
         movlw     0x3D         ; =
         call     LCD_dig     ; загружаем данные
         movf     Thou,W     ; копируем в W содержимое Thou
         btfsc     Thou,0     ; проверяем значение регистра тысячных показаний, если 1, значит переполнение показаний
         goto     overflow_U ; отправляемся отображать 9,99V
         movf     Hund,W     ; копируем в W содержимое Hund
         call     TABL_dig     ; отправляем на дисплей содержимое Hund
         call     LCD_dig     ; загружаем данные
         movlw     0x2C         ; ,
         call     LCD_dig     ; загружаем данные
         movf     Tens,W     ; копируем в W содержимое Tens
         call     TABL_dig     ; отправляем на дисплей содержимое Tens
         call     LCD_dig     ; загружаем данные
         movf     Ones,W     ; копируем в W содержимое Ones
         call     TABL_dig     ; отправляем на дисплей содержимое Ones
         call     LCD_dig     ; загружаем данные
         movlw     0x56         ; V
         call     LCD_dig     ; загружаем данные
         return
overflow_U movlw     0x39         ; 9 (выводим 9,99V вместо 10,23V)
         call     LCD_dig     ; загружаем данные
         movlw     0x2C         ; ,
         call     LCD_dig     ; -//-
         movlw     0x39         ; 9
         call     LCD_dig     ; загружаем данные
         movlw     0x39         ; 9
         call     LCD_dig     ; загружаем данные
         movlw     0x56         ; V
         call     LCD_dig     ; загружаем данные
         return

                         ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                         ; Подпрограмма трансформации двоичного числа в десятичное ;
                         ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
TRANSFORMER_dig
         movf     Reg_tmpL,W ; копируем младший байт результата преобразования АЦП в
         movwf     bin2         ; в bin2            
         movf     Reg_tmpH,W ; копируем старший байт результата преобразования АЦП в
         movwf     bin1         ; в bin1
;bin2 = младший байт преобразуемого числа
;bin1 = старший байт преобразуемого числа
;bcd3 ( младший полубайт ) = единицы
;bcd3 ( старший полубайт ) = десятки
;bcd2 ( младший полубайт ) = сотни
;bcd2 ( старший полубайт ) = тысячи
;bcd1 ( младший полубайт ) = десятки тысяч                                        
         movlw     .16
         movwf     ctr
         clrf     bcd1
         clrf     bcd2
         clrf     bcd3
         goto     start
adjdec     movlw     0x33
         addwf     bcd1,f
         addwf     bcd2,f
         addwf     bcd3,f
         movlw     0x03
         btfss     bcd1,3
         subwf     bcd1,f
         btfss     bcd2,3
         subwf     bcd2,f
         btfss     bcd3,3
         subwf     bcd3,f
         movlw     0x30
         btfss     bcd1,7
         subwf     bcd1,f
         btfss     bcd2,7
         subwf     bcd2,f
         btfss     bcd3,7
         subwf     bcd3,f
start     rlf         bin2,f
         rlf         bin1,f
         rlf         bcd3,f
         rlf         bcd2,f
         rlf         bcd1,f
         decfsz     ctr,f
         goto     adjdec     ; окончание конвертирования                
         movf     bcd1,w     ; распределение результата по регистрам    
         movwf     TenK         ; десятки тысяч
         swapf     bcd2,w
         movwf     Thou         ; тысячи
         movf     bcd2,w
         movwf     Hund         ; сотни
         swapf     bcd3,w
         movwf     Tens         ; десятки
         movf     bcd3,w
         movwf     Ones         ; единицы
         return    
TABL_dig andlw     b'00001111' ; маскируем старший полубайт W (обнуляем 4 старших байта)
         addwf     PCL,f         ; Содержимое счетчика команд PC увеличивается на величину содержимого аккумулятора W.
         retlw     0x30         ; 0
         retlw     0x31         ; 1
         retlw     0x32         ; 2
         retlw     0x33         ; 3
         retlw     0x34         ; 4
         retlw     0x35         ; 5
         retlw     0x36         ; 6
         retlw     0x37         ; 7
         retlw     0x38         ; 8
         retlw     0x39         ; 9
         retlw     0x41         ; A
         retlw     0x42         ; B
         retlw     0x43         ; C
         retlw     0x44         ; D
         retlw     0x45         ; E
         retlw     0x46         ; F
                         ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                         ; Подпрограмма вывода данных на HD44780 ;
                         ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; загрузка комманды
LCD_com     movwf     LCD_tmp        
         call     E_0
         call     RS_0
         call     LCD_load
         return    
; загрузка цифры
LCD_dig     movwf     LCD_tmp        
         call     E_0
         call     RS_1
         call     LCD_load
         return

; загрузка данных непосредственно в дисплей со стробированием
LCD_load movf     LCD_tmp,W        
         movwf     LCD_PORT
         call     del_1ms
         call     E_1
         call     del_1ms
         call     E_0
         call     del_1ms
         return
E_0         bcf         E_LCD
         movf     LCD_tmp1,W
         movwf     LCD_PORT_E_RS        
         return
E_1         bsf         E_LCD
         movf     LCD_tmp1,W
         movwf     LCD_PORT_E_RS        
         return
RS_0     bcf         RS_LCD
         movf     LCD_tmp1,W
         movwf     LCD_PORT_E_RS        
         return
RS_1     bsf         RS_LCD
         movf     LCD_tmp1,W
         movwf     LCD_PORT_E_RS        
         return
; ЗАДЕРЖКА 5 ms
del_5ms     call     del_1ms
         call     del_1ms
         call     del_1ms
         call     del_1ms
         call     del_1ms
         return
; ЗАДЕРЖКА 100 ms
del_100ms call del_50ms
         call del_50ms
         return

; ЗАДЕРЖКА 50 ms
del_50ms movlw     .238
         movwf     Reg_tmp1
         movlw     .65
         movwf     Reg_tmp2
wr1         decfsz     Reg_tmp1, F
         goto     wr1
         decfsz     Reg_tmp2, F
         goto     wr1
         return                                
; ЗАДЕРЖКА 1 ms
del_1ms     movlw     .75
         movwf     Reg_tmp1
         movlw     .2
         movwf     Reg_tmp2
wr2         decfsz     Reg_tmp1, F
         goto     wr2
         decfsz     Reg_tmp2, F
         goto     wr2
         return
;delay = 20 machine cycles
del_20mcs movlw     .6
         movwf     Reg_tmp1
wr3         decfsz     Reg_tmp1, F
         goto     wr3
         return
         end
Но при попытке добавить в исходник OUT_I подпрограмму для вывода показаний амперметра - программа неимоверно глючит. На дисплее моргает U= и ничего не происходит. Все виснет даже если я не вызываю подпрограмму OUT_I... Но если я убираю из исходника подпрограмму OUT_U то все работает но уже в режиме показаний амперметра. Подпрограммы OUT_U и OUT_I никак не хотят вместе дружить. А по отдельности все прекрасно работает. Помогите - не знаю куда копать!!! Метки менял. Среда разработки MPLAB IDE v8.66. Прошиваю PICkit 2
Вот подпрограмма.

Код: Выделить всё

OUT_I ; выводим I на дисплей содержимое регистров Thou, Hund, Tens, Ones (тысячи, сотни, десятки, единицы)
         banksel     ADCON0     ; переходим в регистр ADCON0
         movlw     b'01001001' ; включаем модуль АЦП, RA1 - вход, Fosc/8
         movwf     ADCON0     ; -//-
         banksel     ADCON1     ; переходим в регистр ADCON1
         movlw     b'10000000' ; включаем правое выравнивание
         movwf     ADCON1     ; -//-
         bcf         STATUS,RP0 ; переход в банк 0
         bsf         ADCON0,2     ; включаем преобразование АЦП
         call     del_20mcs
         btfsc     ADCON0,2     ; ожидаем завершения
         goto     $-1         ; преобразования
         movfw     ADRESH     ; перепишем результат преобразования
         movwf     Reg_tmpH     ; в старший временный регистр
         banksel     ADRESL     ; переходим в регистр ADRESL
         movfw     ADRESL     ; перепишем результат преобразования
         bcf         STATUS,RP0 ; переход в банк 0
         movwf     Reg_tmpL     ; в младший временный регистр

         call     TRANSFORMER_dig ; перекодируем двоичное число результата преобразования в десятичное
         movlw     0xC0         ; курсор в пределах второй строки ( 0xС0 - начало )
         call     LCD_com     ; загружаем команду
         movlw     0x49         ; I
         call     LCD_dig     ; загружаем данные
         movlw     0x3D         ; =
         call     LCD_dig     ; загружаем данные
         movf     Thou,W     ; копируем в W содержимое Thou
         btfsc     Thou,0     ; проверяем значение регистра тысячных показаний, если 1, значит переполнение показаний
goto overflow_I ; отправляемся отображать 9,99А
         movf     Hund,W     ; копируем в W содержимое Hund
         call     TABL_dig     ; отправляем на дисплей содержимое Hund
         call     LCD_dig     ; загружаем данные
         movlw     0x2C         ; ,
         call     LCD_dig     ; загружаем данные
         movf     Tens,W     ; копируем в W содержимое Tens
         call     TABL_dig     ; отправляем на дисплей содержимое Tens
         call     LCD_dig     ; загружаем данные
         movf     Ones,W     ; копируем в W содержимое Ones
         call     TABL_dig     ; отправляем на дисплей содержимое Ones
         call     LCD_dig     ; загружаем данные
         movlw     0x41         ; A
         call     LCD_dig     ; загружаем данные
         return
overflow_I movlw 0x39 ; 9 (выводим 9,99А вместо 10,23А)
         call     LCD_dig     ; загружаем данные
         movlw     0x2C         ; ,
         call     LCD_dig     ; -//-
         movlw     0x39         ; 9
         call     LCD_dig     ; загружаем данные
         movlw     0x39         ; 9
         call     LCD_dig     ; загружаем данные
         movlw     0x41         ; A
         call     LCD_dig     ; загружаем данные
         return
Реклама
otest
Друг Кота
Сообщения: 7853
Зарегистрирован: Ср фев 11, 2009 20:35:58

Re: 16F876A Вольтамперметр. Проблемы Исходника

Сообщение otest »

Пишу свою первую прошивку
Может переписываеш у ЗАЕЦа ?
Не вижу переход на OUT_I. :shock:
Оформи CBLOCK через EQU, замени $ на метки и выкладывай весь проект.
Реклама
Smen
Грызет канифоль
Сообщения: 256
Зарегистрирован: Вт окт 08, 2013 07:38:59
Откуда: СПб

Re: 16F876A Вольтамперметр. Проблемы Исходника

Сообщение Smen »

Пока вижу у Вас неправильный вызов ПП "TABL_dig".
Почитайте внимательно про организацию памяти ОЗУ в 16-х ПИКах.
Аватара пользователя
4uvak
Встал на лапы
Сообщения: 99
Зарегистрирован: Чт авг 16, 2012 10:41:42

Re: 16F876A Вольтамперметр. Проблемы Исходника

Сообщение 4uvak »

Не знаю я никакого ЗАЕЦа :o . Единственное что я использовал из чужих трудов в разработке своей программы лежит в прикрепленном Файле. Автор Blaze. Если Вам не трудно - дайте ссылку на труды ЗАЕЦа в разработке аналогичного устройства.
Не видите перехода на OUT_I потому что даже без перехода в эту ПП все глючит. Глюки исчезают при полном удалении ПП OUT_I или OUT_U. Работают они по отдельности, а вместе не хотят.
Smen поищу. А как правильно вызвать ПП?
Вот полный проект.

Код: Выделить всё

            LIST      p=16F876A
            #include  <P16F876A.inc> 
            __CONFIG  (_LVP_OFF & _CP_OFF & _CPD_OFF & _PWRTE_OFF & _WDT_ON & _XT_OSC & _BODEN_ON & _DEBUG_OFF )
 

LCD_tmp   EQU       0x20
LCD_tmp1  EQU       0x21
Reg_tmp1  EQU       0x22
Reg_tmp2  EQU       0x23
lcd_load  EQU       0x24
Reg_tmpL  EQU       0x25
Reg_tmpH  EQU       0x26
bin1      EQU       0x27
bin2      EQU       0x28
bcd1      EQU       0x29
bcd2      EQU       0x2A
bcd3      EQU       0x2B
TenK      EQU       0x2C
Thou      EQU       0x2D
Hund      EQU       0x2E
Tens      EQU       0x2F
Ones      EQU       0x30
ctr       EQU       0x31
    


#define RS_LCD          LCD_tmp1,RB4  ; назначаем вывод команд RS на PORTA для LCD
#define E_LCD           LCD_tmp1,RB5  ; назначаем вывод команд E на PORTA для LCD
#define LCD_PORT_E_RS   PORTB         ; назначаем порт для вывода данных PORTB для LCD
#define LCD_PORT        PORTC         ; назначаем порт для вывода данных PORTC для LCD (8 разрядов)

                            ;;;;;;;;;;;;;;;;;;;
                            ; старт программы ;
                            ;;;;;;;;;;;;;;;;;;;
            org         0
            goto        START 
                            ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                            ; инициализация контроллера ;
                            ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
START       bcf         STATUS,RP0    ; переход в банк 0
            banksel     OPTION_REG    ; переходим в регистр OPTION_REG
            movlw       b'10001110'   ; отключаем подтягивающие резисторы PORTB, включаем предделитель перед WDT 1:64
            movwf       OPTION_REG    ; -//-
            banksel     INTCON        ; переходим в регистр INTCON
            movlw       b'00000000'   ; глобальный запрет прерываний
            movwf       INTCON        ; -//-
            banksel     PIE1          ; переходим в регистр PIE1
            movlw       b'00000000'   ; глобальный запрет периферийных прерываний
            movwf       PIE1          ; -//-
            banksel     PIE2          ; переходим в регистр PIE2
            movlw       b'00000000'   ; глобальный запрет прерываний EEPROM, CCP2
            movwf       PIE2          ; -//-
            banksel     TRISA         ; переходим в регистр PORTA
            movlw       b'00000011'   ; настраиваем все порты на выход, AN0, AN1 на вход
            movwf       TRISA         ; -//-
            banksel     TRISB         ; переходим в регистр PORTB
            movlw       b'00000000'   ; настраиваем все порты на выход
            movwf       TRISB         ; -//-
            banksel     TRISC         ; переходим в регистр PORTC
            movlw       b'00000000'   ; настраиваем все порты на выход
            movwf       TRISC         ; -//-
            banksel     T1CON         ; переходим в регистр T1CON
            movlw       b'00000000'   ; отключаем модуль T1CON
            movwf       T1CON         ; -//-
            banksel     T2CON         ; переходим в регистр T2CON
            movlw       b'00000000'   ; отключаем модуль T2CON
            movwf       T2CON         ; -//-
            banksel     CCP1CON       ; переходим в регистр CCP1CON
            movlw       b'00000000'   ; отключаем модуль CCP1
            movwf       CCP1CON       ; -//-
            banksel     CCP2CON       ; переходим в регистр CCP2CON
            movlw       b'00000000'   ; отключаем модуль CCP2
            movwf       CCP2CON       ; -//-
            banksel     SSPSTAT       ; переходим в регистр SSPSTAT
            movlw       b'00000000'   ; отключаем модуль SSPSTAT
            movwf       SSPSTAT       ; -//-
            banksel     SSPCON        ; переходим в регистр SSPCON
            movlw       b'00000000'   ; отключаем модуль SSPCON
            movwf       SSPCON        ; -//-
            banksel     SSPCON2       ; переходим в регистр SSPCON2
            movlw       b'00000000'   ; отключаем модуль SSPCON2
            movwf       SSPCON2       ; -//-  
            banksel     TXSTA         ; переходим в регистр TXSTA
            movlw       b'00000000'   ; отключаем модуль TXSTA
            movwf       TXSTA         ; -//-  
            banksel     RCSTA         ; переходим в регистр RCSTA
            movlw       b'00000000'   ; отключаем модуль RCSTA
            movwf       RCSTA         ; -//- 
            banksel     ADCON0        ; переходим в регистр ADCON0
            movlw       b'00000000'   ; отключаем модуль АЦП
            movwf       ADCON0        ; -//- 
            banksel     ADCON1        ; переходим в регистр ADCON1
            movlw       b'00000000'   ; отключаем модуль АЦП
            movwf       ADCON1        ; -//- 
            bsf         STATUS,RP0    ; переход в банк 1
            bcf         STATUS,RP0    ; переход в банк 0
            clrwdt

                            ;;;;;;;;;;;;;;;;;;;;;;;;;
                            ; инициализация дисплея ;
                            ;;;;;;;;;;;;;;;;;;;;;;;;;
            call        del_100ms     ; начальная задержка 100 милисекунд 
            movlw       b'00000001'   ; очищаем дисплей
            call        LCD_com       ; загружаем команду
            call        del_5ms
            movlw       b'00000110'   ; сдвиг курсора вправо
            call        LCD_com       ; загружаем команду 
            movlw       b'00001100'   ; отключаем курсор
            call        LCD_com       ; загружаем команду 
            movlw       b'00010100'   ; двигаем курсор вправо
            call        LCD_com       ; загружаем команду
            movlw       b'00111000'   ; вкл 8 разрядный ввод данных, размер символа 5х8 символов
            call        LCD_com       ; загружаем команду      

gooo        
            call        OUT_U         ; отправляемся читать данные АЦП, и вывод данных на дисплей
            call        OUT_I         ; отправляемся читать данные АЦП, и вывод данных на дисплей
            call        del_100ms
            call        del_100ms
            clrwdt
            goto        gooo


OUT_U ; выводим U на дисплей содержимое регистров Thou, Hund, Tens, Ones (тысячи, сотни, десятки, единицы)
            banksel     ADCON0        ; переходим в регистр ADCON0
            movlw       b'01000001'   ; включаем модуль АЦП, RA0 - вход, Fosc/8
            movwf       ADCON0        ; -//-  
            banksel     ADCON1        ; переходим в регистр ADCON1
            movlw       b'10000000'   ; включаем правое выравнивание
            movwf       ADCON1        ; -//- 
            bcf         STATUS,RP0    ; переход в банк 0
            bsf         ADCON0,2      ; включаем преобразование АЦП
            call        del_20mcs
werf        btfsc       ADCON0,2      ; ожидаем завершения
            goto        werf          ; преобразования
            movfw       ADRESH        ; перепишем результат преобразования
            movwf       Reg_tmpH      ; в старший временный регистр
            banksel     ADRESL        ; переходим в регистр ADRESL
            movfw       ADRESL        ; перепишем результат преобразования
            bcf         STATUS,RP0    ; переход в банк 0
            movwf       Reg_tmpL      ; в младший временный регистр


            call        TRANSFORMER_dig ; перекодируем двоичное число результата преобразования в десятичное
            movlw       0x80          ; курсор в пределах первой строки ( 0x80 - начало )
            call        LCD_com       ; загружаем команду 
            movlw       0x55          ; U
            call        LCD_dig       ; загружаем данные
            movlw       0x3D          ; =
            call        LCD_dig       ; загружаем данные
            movf        Thou,W        ; копируем в W содержимое Thou
            btfsc       Thou,0        ; проверяем значение регистра тысячных показаний, если 1, значит переполнение показаний
            goto        overflowU    ; отправляемся отображать 9,99V
            movf        Hund,W        ; копируем в W содержимое Hund
            call        TABL_dig      ; отправляем на дисплей содержимое Hund
            call        LCD_dig       ; загружаем данные
            movlw       0x2C          ; ,
            call        LCD_dig       ; загружаем данные
            movf        Tens,W        ; копируем в W содержимое Tens
            call        TABL_dig      ; отправляем на дисплей содержимое Tens
            call        LCD_dig       ; загружаем данные
            movf        Ones,W        ; копируем в W содержимое Ones
            call        TABL_dig      ; отправляем на дисплей содержимое Ones
            call        LCD_dig       ; загружаем данные
            movlw       0x56          ; V
            call        LCD_dig       ; загружаем данные
            return
overflowU  movlw       0x39          ; 9 (выводим 9,99V вместо 10,23V)
            call        LCD_dig       ; загружаем данные
            movlw       0x2C          ; ,
            call        LCD_dig       ; -//- 
            movlw       0x39          ; 9
            call        LCD_dig       ; загружаем данные
            movlw       0x39          ; 9
            call        LCD_dig       ; загружаем данные
            movlw       0x56          ; V
            call        LCD_dig       ; загружаем данные
            return


OUT_I ; выводим I на дисплей содержимое регистров Thou, Hund, Tens, Ones (тысячи, сотни, десятки, единицы)
            banksel     ADCON0        ; переходим в регистр ADCON0
            movlw       b'01001001'   ; включаем модуль АЦП, RA1 - вход, Fosc/8
            movwf       ADCON0        ; -//-  
            banksel     ADCON1        ; переходим в регистр ADCON1
            movlw       b'10000000'   ; включаем правое выравнивание
            movwf       ADCON1        ; -//- 
            bcf         STATUS,RP0    ; переход в банк 0
            bsf         ADCON0,2      ; включаем преобразование АЦП
            call        del_20mcs
desa        btfsc       ADCON0,2      ; ожидаем завершения
            goto        desa          ; преобразования
            movfw       ADRESH        ; перепишем результат преобразования
            movwf       Reg_tmpH      ; в старший временный регистр
            banksel     ADRESL        ; переходим в регистр ADRESL
            movfw       ADRESL        ; перепишем результат преобразования
            bcf         STATUS,RP0    ; переход в банк 0
            movwf       Reg_tmpL      ; в младший временный регистр


            call        TRANSFORMER_dig ; перекодируем двоичное число результата преобразования в десятичное
            movlw       0xC0          ; курсор в пределах второй строки ( 0xС0 - начало )
            call        LCD_com       ; загружаем команду 
            movlw       0x49          ; I
            call        LCD_dig       ; загружаем данные
            movlw       0x3D          ; =
            call        LCD_dig       ; загружаем данные
            movf        Thou,W        ; копируем в W содержимое Thou
            btfsc       Thou,0        ; проверяем значение регистра тысячных показаний, если 1, значит переполнение показаний
            goto        overflowI    ; отправляемся отображать 9,99A
            movf        Hund,W        ; копируем в W содержимое Hund
            call        TABL_dig      ; отправляем на дисплей содержимое Hund
            call        LCD_dig       ; загружаем данные
            movlw       0x2C          ; ,
            call        LCD_dig       ; загружаем данные
            movf        Tens,W        ; копируем в W содержимое Tens
            call        TABL_dig      ; отправляем на дисплей содержимое Tens
            call        LCD_dig       ; загружаем данные
            movf        Ones,W        ; копируем в W содержимое Ones
            call        TABL_dig      ; отправляем на дисплей содержимое Ones
            call        LCD_dig       ; загружаем данные
            movlw       0x41          ; A
            call        LCD_dig       ; загружаем данные
            return
overflowI  movlw       0x39          ; 9 (выводим 9,99A вместо 10,23A)
            call        LCD_dig       ; загружаем данные
            movlw       0x2C          ; ,
            call        LCD_dig       ; -//- 
            movlw       0x39          ; 9
            call        LCD_dig       ; загружаем данные
            movlw       0x39          ; 9
            call        LCD_dig       ; загружаем данные
            movlw       0x41          ; A
            call        LCD_dig       ; загружаем данные
            return


                            ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                            ; Подпрограмма трансформации двоичного числа в десятичное ;
                            ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
TRANSFORMER_dig
            movf        Reg_tmpL,W    ; копируем младший байт результата преобразования АЦП в   
            movwf       bin2          ; в bin2               
            movf        Reg_tmpH,W    ; копируем старший байт результата преобразования АЦП в    
            movwf       bin1          ; в bin1
;bin2 = младший байт преобразуемого числа
;bin1 = старший байт преобразуемого числа
;bcd3 ( младший полубайт ) = единицы
;bcd3 ( старший полубайт ) = десятки
;bcd2 ( младший полубайт ) = сотни
;bcd2 ( старший полубайт ) = тысячи
;bcd1 ( младший полубайт ) = десятки тысяч                                          
            movlw       .16 
            movwf       ctr 
            clrf        bcd1 
            clrf        bcd2 
            clrf        bcd3 
            goto        start 
adjdec      movlw       0x33 
            addwf       bcd1,f 
            addwf       bcd2,f 
            addwf       bcd3,f 
            movlw       0x03 
            btfss       bcd1,3 
            subwf       bcd1,f 
            btfss       bcd2,3 
            subwf       bcd2,f 
            btfss       bcd3,3 
            subwf       bcd3,f 
            movlw       0x30 
            btfss       bcd1,7 
            subwf       bcd1,f 
            btfss       bcd2,7 
            subwf       bcd2,f 
            btfss       bcd3,7 
            subwf       bcd3,f 
start       rlf         bin2,f 
            rlf         bin1,f 
            rlf         bcd3,f 
            rlf         bcd2,f 
            rlf         bcd1,f 
            decfsz      ctr,f 
            goto        adjdec        ; окончание конвертирования                  
            movf        bcd1,w        ; распределение результата по регистрам        
            movwf       TenK          ; десятки тысяч 
            swapf       bcd2,w
            movwf       Thou          ; тысячи 
            movf        bcd2,w
            movwf       Hund          ; сотни 
            swapf       bcd3,w
            movwf       Tens          ; десятки 
            movf        bcd3,w
            movwf       Ones          ; единицы
            return      

TABL_dig    andlw       b'00001111'   ; маскируем старший полубайт W (обнуляем 4 старших байта)
            addwf       PCL,f         ; Содержимое счетчика команд PC увеличивается на величину содержимого аккумулятора W.
            retlw       0x30          ; 0
            retlw       0x31          ; 1 
            retlw       0x32          ; 2 
            retlw       0x33          ; 3 
            retlw       0x34          ; 4 
            retlw       0x35          ; 5  
            retlw       0x36          ; 6 
            retlw       0x37          ; 7 
            retlw       0x38          ; 8 
            retlw       0x39          ; 9
            retlw       0x41          ; A
            retlw       0x42          ; B
            retlw       0x43          ; C
            retlw       0x44          ; D
            retlw       0x45          ; E
            retlw       0x46          ; F

                            ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                            ; Подпрограмма вывода данных на HD44780 ;
                            ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; загрузка комманды
LCD_com     movwf       LCD_tmp           
            call        E_0
            call        RS_0
            call        LCD_load
            return     

; загрузка цифры 
LCD_dig     movwf       LCD_tmp           
            call        E_0
            call        RS_1
            call        LCD_load
            return 
 
; загрузка данных непосредственно в дисплей со стробированием
LCD_load    movf        LCD_tmp,W         
            movwf       LCD_PORT
            call        del_1ms
            call        E_1
            call        del_1ms 
            call        E_0
            call        del_1ms 
            return 

E_0         bcf         E_LCD
            movf        LCD_tmp1,W    
            movwf       LCD_PORT_E_RS         
            return

E_1         bsf         E_LCD
            movf        LCD_tmp1,W    
            movwf       LCD_PORT_E_RS         
            return

RS_0        bcf         RS_LCD
            movf        LCD_tmp1,W    
            movwf       LCD_PORT_E_RS         
            return

RS_1        bsf         RS_LCD
            movf        LCD_tmp1,W    
            movwf       LCD_PORT_E_RS         
            return

; ЗАДЕРЖКА 5 ms 
del_5ms     call        del_1ms
            call        del_1ms
            call        del_1ms
            call        del_1ms
            call        del_1ms
            return

; ЗАДЕРЖКА 100 ms 
del_100ms   call   del_50ms
            call   del_50ms
            return
  
; ЗАДЕРЖКА 50 ms
del_50ms    movlw       .238
            movwf       Reg_tmp1
            movlw       .65
            movwf       Reg_tmp2
wr1         decfsz      Reg_tmp1, F
            goto        wr1
            decfsz      Reg_tmp2, F
            goto        wr1
            return                                    

; ЗАДЕРЖКА 1 ms
del_1ms     movlw       .75
            movwf       Reg_tmp1
            movlw       .2
            movwf       Reg_tmp2
wr2         decfsz      Reg_tmp1, F
            goto        wr2
            decfsz      Reg_tmp2, F
            goto        wr2
            return

;delay = 20 machine cycles
del_20mcs   movlw       .6
            movwf       Reg_tmp1
wr3         decfsz      Reg_tmp1, F
            goto        wr3
            return

            end
Вложения
HD44780.asm
(26.26 КБ) 413 скачиваний
Реклама
Эиком - электронные компоненты и радиодетали
otest
Друг Кота
Сообщения: 7853
Зарегистрирован: Ср фев 11, 2009 20:35:58

Re: 16F876A Вольтамперметр. Проблемы Исходника

Сообщение otest »

Ищи в сети книги и диск.
Подсчитывать адрес регистров через CBLOCK и переходы через $ ни каждому захочется.
Если хочеш помощи, выкладывай проект МПЛАБ , а не куски кода.
Реклама
Аватара пользователя
4uvak
Встал на лапы
Сообщения: 99
Зарегистрирован: Чт авг 16, 2012 10:41:42

Re: 16F876A Вольтамперметр. Проблемы Исходника

Сообщение 4uvak »

Проект
Вложения
16F876A.rar
(17.53 КБ) 196 скачиваний
Реклама
otest
Друг Кота
Сообщения: 7853
Зарегистрирован: Ср фев 11, 2009 20:35:58

Re: 16F876A Вольтамперметр. Проблемы Исходника

Сообщение otest »

Попробуй отключить WDT.
Аватара пользователя
4uvak
Встал на лапы
Сообщения: 99
Зарегистрирован: Чт авг 16, 2012 10:41:42

Re: 16F876A Вольтамперметр. Проблемы Исходника

Сообщение 4uvak »

Пробовал - бестолку! Прямо мистика какая то. Подпрограммы по отдельности работают прекрасно(с удалением из кода одной или другой подпрограммы). Но строит подпрограммы оставить вместе в коде и даже не вызывать мешающую подпрограмму - все равно глюк! Как? Если подпрограмма не вызывается, а просто стоит невостребованная???
otest
Друг Кота
Сообщения: 7853
Зарегистрирован: Ср фев 11, 2009 20:35:58

Re: 16F876A Вольтамперметр. Проблемы Исходника

Сообщение otest »

Не нужно паники, нужен анализ.
Когда задаёш вопросы , то читай внимательно ответы.
Пока вижу у Вас неправильный вызов ПП "TABL_dig".
Это 1-й глюк. Перенеси таблицу в начало программы.
Smen
Грызет канифоль
Сообщения: 256
Зарегистрирован: Вт окт 08, 2013 07:38:59
Откуда: СПб

Re: 16F876A Вольтамперметр. Проблемы Исходника

Сообщение Smen »

4uvak писал(а):Пробовал - бестолку! Прямо мистика какая то. Подпрограммы по отдельности работают прекрасно(с удалением из кода одной или другой подпрограммы). Но строит подпрограммы оставить вместе в коде и даже не вызывать мешающую подпрограмму - все равно глюк! Как? Если подпрограмма не вызывается, а просто стоит невостребованная???
Никакой мистики.
Для начала, Вас не смущают сообщения компилятора, типа:

Код: Выделить всё

Message[302] D:\PROV\16F876A\16F876A.ASM 196 : Register in operand not in bank 0.  Ensure that bank bits are correct.
Warning[203] D:\PROV\16F876A\16F876A.ASM 297 : Found opcode in column 1. (andlw)
Ладно, это - мелочи.
Что, например, за код?

Код: Выделить всё

E_0         bcf         E_LCD
            movf        LCD_tmp1,W    
            movwf       LCD_PORT_E_RS         
            return
Почему просто нельзя ногой дрыгать?
Если вы хотите байтом выводить, так тогда его сперва считать нужно, затем выставить нужные биты, а уж затем только выводить.
Ну, и вся программа такая, в общем.
Глюк сидел, как и говорил выше.
Подправил программу (см. аттач)
Кстати, а в чём Вы вообще программу отлаживали? Это же сразу должно быть заметно.
Заодно приложил проект для Протеуса, и для МПЛАБа с Протеусом.
Учитесь с отладкой работать.
P.S.: Ещё Протеус ругается, что время АЦП не выдержано. Он, конечно, может и ошибаться, но я не проверял. Это уж сами как-нибудь.

otest писал(а):Перенеси таблицу в начало программы.
Можно, конечно, и так, но это - половинчатая мера.
Лучше сразу правильно делать.
Вложения
16F876A.zip
(43.13 КБ) 225 скачиваний
Аватара пользователя
4uvak
Встал на лапы
Сообщения: 99
Зарегистрирован: Чт авг 16, 2012 10:41:42

Re: 16F876A Вольтамперметр. Проблемы Исходника

Сообщение 4uvak »

Всем большое спасибо за помощь и правильные наводки! Разобраться помогла статья http://chipmk.ru/index.php?option=com_c ... 5-10-13-47 где все толково описано насчет организации памяти.
Smen дрыгал ногами я раньше пока не наткнулся на отрицательные нюансы эффекта чтения-модификации-записи. После этого я и стал использовать переменную, вместо правки порта. Правлю переменную, потом запись в порт!
Если честно я отладочными средствами пользоваться не умею. Отладку производил в готовом устройстве.
Если не трудно - дайте ссылку где грамотно описан процесс отладки...
Изображение
Smen
Грызет канифоль
Сообщения: 256
Зарегистрирован: Вт окт 08, 2013 07:38:59
Откуда: СПб

Re: 16F876A Вольтамперметр. Проблемы Исходника

Сообщение Smen »

4uvak писал(а):пока не наткнулся на отрицательные нюансы эффекта чтения-модификации-записи.
Так не надо на него "натыкаться" и всего делов.
4uvak писал(а):я отладочными средствами пользоваться не умею. Отладку производил в готовом устройстве.
Так Вы никогда ничего не отладите.
В МПЛАБе выбираете подходящий дебагер.
Включаете симуляцию (зелёная кнопочка).
F7 - пошаговая отладка
F9 - "воспроизведение"
Точки останова - двойной клик ЛКМ на нужной строке.
Откройте проект, который в аттаче, всё поймёте. Там, в качестве дебагера Протеус, поэтому его сперва установить надо.
Ответить

Вернуться в «PIC»