Как сравнить значение в одном из нескольких диапазонов, используя PIC16F877A - PullRequest
0 голосов
/ 14 октября 2019

Домашнее задание: оставьте все то же самое, что и в домашнем задании № 1, спроектируйте систему, которая может считывать настройки потенциометра и отображать в реальном времени диапазоны напряжения высокого, среднего и низкого уровня на ЖК-модуле. Ваша программа должна отображать в реальном времени напряжение High = 4,5 В и выше, Medium = от 2,0 В до 3,0 В и Low = 1,5 В и ниже и обновлять показания и отображать каждые 5 секунд, чтобы отражать изменения потенциометра. Если напряжение находится за пределами диапазонов, на ЖК-дисплее отобразится «Неизвестно».

Я получил от ASM все, кроме возможности «больше чем», «меньше чем» длядиапазоны. Я могу видеть, как сделать это в C-коде для PIC, но не в ASM. Буду признателен за любую помощь.

Плата: Руководство по системе обучения uC Ред. 3 от ODU Microchip: PIC16F877A Язык кодирования: ASM в MPLAB (MPASM Assembler v5.50)

Упрощенный тестовый код, ориентированный напросто сравнение диапазонов:

; 
; File: main.asm
; Target: PIC16F877A
; 
; Description:
;   Simplified range compare test code
; 
    #include <P16F877A.INC>


    __CONFIG  0x3F32                ;This is the control bits for CONFIG register

    ORG     0x0000                  ;RESET or WDT reset vector
    GOTO    START

    ORG     0x0004                  ;Regular INT vector

;This is the area where your interrupt service routine goes

    RETFIE
;
;Table of messages
;
Message_High:
    DT "High"
Message_Mid:
    DT "Mid"
Message_Low:
    DT "Low"
Message_Unknown:
    DT "Unknown"

ValueToCheck EQU    0x20

START:                              ;The starting place of the user codes

    banksel ValueToCheck
    clrf    ValueToCheck

TestLoop:
    movf    ValueToCheck,W
    sublw   d'45'                   ; Do calculation: WREG - ValueToCheck
    btfsc   STATUS,C                ; CARRY not set so ValueToCheck < 45
    goto    ShowHigh

    movf    ValueToCheck,W
    sublw   d'30'                   ; Do calculation: WREG - ValueToCheck
    btfsc   STATUS,C                ; CARRY not set so ValueToCheck < 30
    goto    ShowUnknown

    movf    ValueToCheck,W
    sublw   d'20'                   ; Do calculation: WREG - ValueToCheck
    btfsc   STATUS,C                ; CARRY not set so ValueToCheck < 20
    goto    ShowMid

    movf    ValueToCheck,W
    sublw   d'15'                   ; Do calculation: WREG - ValueToCheck
    btfsc   STATUS,C                ; CARRY not set so ValueToCheck < 15
    goto    ShowUnknown

ShowLow:
    movlw   Message_Low             ; Load WREG with message pointer
    goto    ShowMessage

ShowMid:
    movlw   Message_Mid             ; Load WREG with message pointer
    goto    ShowMessage

ShowHigh:
    movlw   Message_High            ; Load WREG with message pointer
    goto    ShowMessage

ShowUnknown:
    movlw   Message_Unknown         ; Load WREG with message pointer
ShowMessage:
;
; This is test code so no output
;
    nop     ; With breakpoint here. WREG not loaded with expected message pointer.
;
;
;
    incf    ValueToCheck,F
    goto    TestLoop

    END                             ;End program

Мне просто нужна помощь, чтобы выяснить, как заставить программу отображать напряжение в RANGES в ASM на ЖК-дисплее. Любая помощь с благодарностью! Спасибо!

1 Ответ

0 голосов
/ 06 ноября 2019

Сначала я хотел бы поблагодарить Питера Кордеса за открытие этой темы. Посмотрим, стоил ли мой ответ.

Реляционное сравнение с PIC16F877A на языке ассемблера представляет проблемы для новых детей. Вот некоторые вещи, которые я нашел сбивающими с толку.

PIC16F не выполняет арифметику со знаком.

Инструкция вычитания указывает на ЗАИМ, утверждая НЕ НОСИТЬ.

Код операции 'SUBLW'меня смутило порядок вычитания.

Из таблицы данных я обнаружил, что флаги CARRY и ZERO являются результатом: (k - WREG) для литеральной константы 'k'.

Соотношение между литеральной константой 'k' и WREG после оператора "SUBLW k" указывается в флагах состояния следующим образом:

  • ZERO установлен, CARRY устанавливается, когда'k' = WREG
  • Ноль очищен, CARRY установлен, когда 'k'> WREG
  • Ноль очищен, CARRY очищен, когда 'k'

При более понятном описании поведения флагов состояния рабочий код выглядит следующим образом:

; 
; File: main.asm
; Target: PIC16F877A
; 
; Description:
;   Simplified range compare test code
;
;   Bugs corrected 2019-NOV-05
; 
    #include <P16F877A.INC>


    __CONFIG  0x3F32                ;This is the control bits for CONFIG register

    ORG     0x0000                  ;RESET or WDT reset vector
    GOTO    START

    ORG     0x0004                  ;Regular INT vector

;This is the area where your interrupt service routine goes

    RETFIE
;
;Table of messages
;
Message_High:
    DT "High"
Message_Mid:
    DT "Mid"
Message_Low:
    DT "Low"
Message_Unknown:
    DT "Unknown"

ValueToCheck EQU    0x20

START:                              ;The starting place of the user codes

    banksel ValueToCheck
    clrf    ValueToCheck

TestLoop:
    movf    ValueToCheck,W
    sublw   d'45'                   ; Do calculation: 45 - ValueToCheck
    btfss   STATUS,Z                ; ZERO  set so ValueToCheck = 45
    btfss   STATUS,C                ; CARRY set so ValueToCheck < 45
    goto    ShowHigh                ; When ValueToCheck >= 45

    movf    ValueToCheck,W
    sublw   d'30'                   ; Do calculation: 30 - ValueToCheck
    btfss   STATUS,C                ; CARRY set so ValueToCheck < 30
    goto    ShowUnknown             ; When 30 > ValueToCheck < 45

    movf    ValueToCheck,W
    sublw   d'20'                   ; Do calculation: 20 - ValueToCheck
    btfss   STATUS,Z                ; ZERO  set so ValueToCheck = 20
    btfss   STATUS,C                ; CARRY set so ValueToCheck < 20
    goto    ShowMid                 ; When 20 >= ValueToCheck <= 30

    movf    ValueToCheck,W
    sublw   d'15'                   ; Do calculation: 15 - ValueToCheck
    btfss   STATUS,C                ; CARRY set so ValueToCheck <= 15
    goto    ShowUnknown             ; When 15 > ValueToCheck < 20

ShowLow:                            ; When ValueToCheck <= 15
    movlw   Message_Low             ; Load WREG with message pointer
    goto    ShowMessage

ShowMid:
    movlw   Message_Mid             ; Load WREG with message pointer
    goto    ShowMessage

ShowHigh:
    movlw   Message_High            ; Load WREG with message pointer
    goto    ShowMessage

ShowUnknown:
    movlw   Message_Unknown         ; Load WREG with message pointer
ShowMessage:
;
; This is test code so no output
;
    nop     ; With breakpoint here. WREG now loaded with expected message pointer.
;
;
;
    incf    ValueToCheck,F
    goto    TestLoop

    END                             ;End program
...