assembly - 如何使用 PIC16F877A 比较一个值是否在多个范围之一内
问题描述
作业问题: 保持与作业#1 相同的所有内容,设计一个可以读取电位器设置并在 LCD 模块上显示高、中、低实时电压范围的系统。您的程序应显示实时电压 High=4.5 V 及以上,Medium=2.0V 和 3.0V 之间,Low=1.5V 及以下,并每 5 秒更新读数和显示以反映电位器上的变化。如果电压不在范围内,则 LCD 上显示“未知”。
我已经让 ASM 做所有事情,但能够为范围做“大于”、“小于”。我可以看到如何在 PIC 的 C 代码中执行此操作,但在 ASM 中看不到。任何帮助,将不胜感激。
开发板:ODU Microchip 的 uC 培训系统手册第 3 版:PIC16F877A 编码语言:MPLAB 中的 ASM(MPASM 汇编程序 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
我只需要帮助弄清楚如何让程序将 ASM 中范围内的电压显示到 LCD 上。任何帮助是极大的赞赏!谢谢你!
解决方案
首先,我要感谢 Peter Cordes 重新讨论这个话题。我们将看看我的回答是否值得。
用汇编语言与 PIC16F877A 进行关系比较会给新手带来问题。以下是我发现令人困惑的事情。
PIC16F 不进行有符号运算。
减法指令通过断言 NOT CARRY 来指示 BORROW。
操作码“SUBLW”让我对减法的顺序感到困惑。
从数据表中,我发现 CARRY 和 ZERO 标志是以下结果: (k - WREG) 用于文字常量“k”。
“SUBLW k”语句之后的文字常量“k”和 WREG 之间的关系在状态标志中表示为:
- 零设置,当'k' = WREG 时设置进位
- ZERO 清零,当 'k' > WREG 时设置 CARRY
- ZERO 清零, 'k' < WREG 时 CARRY 清零
通过对状态标志如何表现的更清晰的描述,工作代码如下所示:
;
; 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
推荐阅读
- flutter - Flutter - 定时器意外暂停
- angular - 增加模态的大小
- ios - 滚动类型为水平时的UICollectionview拖放问题
- javascript - 仅当省略号处于活动状态时才显示工具提示
- maven - 上传到 Nexus 的自定义 JAR 未从 settings.xml 中定义的 Nexus 公共组解析
- c# - 如何从 ASP.Net 核心 API 共享上传的文件
- php - 注册为服务的 Symfony 3.4 控制器抛出弃用警告
- python - 在字符串前打印 10 个字符
- java - 我如何确保添加到数组的对象的 ID 不存在而不会出现 nullpointerexception?
- c# - ASP.NET Web API 2 - 按查询字符串过滤 POST 请求