Код: Выделить всё
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 ; выводим 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


