Задача
Измерять напряжение 0…5 В и показывать его с точностью до десятых.
Микроконтроллер: PIC16F877A, кварц 4 МГц. Среда: MPLAB X + MPASM (или любой совместимый ассемблер). Как настроить среду и прошить контроллер — в статье программирование PIC.
Что понадобится
- PIC16F877A
- кварц 4 МГц + 2×22 пФ
- два индикатора с общим катодом
- 7 резисторов 330 Ом
- 2 транзисторных ключа
- делитель на входе (при измерении выше 5 В)
Схема подключения
| Вывод | Подключение |
|---|---|
| RA0 / AN0 | измеряемое напряжение (не выше 5 В) |
| RB0…RB6 | сегменты, RB7 — десятичная точка |
| RD0 / RD1 | ключи разрядов: вольты и десятые |
Алгоритм
- Измерить напряжение и получить код 0…255.
- Вычитать по 51 единице — столько приходится на один вольт.
- Остаток разложить на десятые доли шагами по 5 единиц.
- Вывести оба разряда динамической индикацией, зажигая точку у целых.
Листинг на ассемблере
Код проверен ассемблером и собирается без ошибок. Скачать: p28.asm · p28.hex (готовая прошивка).
;=======================================================
; Проект 28. Цифровой вольтметр 0..5 В
; PIC16F877A, 4 МГц. Вход AN0, индикация на двух
; семисегментных разрядах: целые вольты и десятые
; Сегменты RB0..RB6, разряды RD0 (вольты) и RD1 (десятые)
;=======================================================
LIST p=16F877A
#include <p16f877a.inc>
__CONFIG _XT_OSC & _WDT_OFF & _PWRTE_ON & _BODEN_OFF & _LVP_OFF & _CPD_OFF & _CP_OFF
cblock 0x20
d1, volts, tenths, tmp, acc, loops
endc
ORG 0x000
goto Start
Table
addwf PCL,f
retlw b'00111111'
retlw b'00000110'
retlw b'01011011'
retlw b'01001111'
retlw b'01100110'
retlw b'01101101'
retlw b'01111101'
retlw b'00000111'
retlw b'01111111'
retlw b'01101111'
Start
bsf STATUS,RP0
clrf TRISB
clrf TRISD
movlw b'00000001'
movwf TRISA
movlw b'00001110'
movwf ADCON1
bcf STATUS,RP0
movlw b'01000001'
movwf ADCON0
Main
call Measure
call Convert
movlw .50 ; показываем результат ~0,5 с
movwf loops
Show
bcf PORTD,1
movf volts,w
call Table
iorlw b'10000000' ; точка после целых вольт
movwf PORTB
bsf PORTD,0
call Delay5ms
bcf PORTD,0
movf tenths,w
call Table
movwf PORTB
bsf PORTD,1
call Delay5ms
decfsz loops,f
goto Show
goto Main
Measure
bsf ADCON0,GO
MW btfsc ADCON0,GO
goto MW
movf ADRESH,w ; 0..255 соответствует 0..5 В
movwf acc
return
;--- перевод кода в вольты и десятые ---
;--- 1 вольт ~ 51 единица кода (255/5) ---
Convert
clrf volts
movf acc,w
movwf tmp
V1 movlw .51
subwf tmp,w
btfss STATUS,C ; осталось меньше вольта?
goto Tenth
movwf tmp
incf volts,f
goto V1
Tenth
clrf tenths ; остаток -> десятые доли
T1 movlw .5
subwf tmp,w
btfss STATUS,C
return
movwf tmp
incf tenths,f
movf tenths,w
xorlw .10
btfsc STATUS,Z
clrf tenths
goto T1
Delay5ms
movlw .250
movwf d1
D5 nop
nop
nop
nop
nop
decfsz d1,f
goto D5
return
END
Пояснения
- Деления у PIC нет, поэтому перевод сделан циклом вычитания — приём универсален для любого масштабирования.
- Точность ограничена восемью битами: шаг составляет около 20 мВ. Для большей точности берут все 10 бит и опорное напряжение стабилизируют.
- Для измерения напряжений выше 5 В ставят резистивный делитель, а коэффициент учитывают в пересчёте.
Что дальше
Разобравшись с этим проектом, переходите к следующему в разделе проекты на PIC. Справочник по архитектуре и периферии контроллеров — на странице микроконтроллеры PIC.