延迟和切换问题

问题描述 投票:0回答:1

PIC16a84f

任务 1:在 PORT.A0 上创建 1 Hz 方波 编写一个汇编语言程序,在端口 A0 上创建 1 Hz 方波。 a) 首先编写代码以立即切换 PORT A0 b) 然后添加一个延迟子程序以产生所需的延迟。您无权使用 延迟子程序的定时器中断。

我不断收到关于我的延迟的错误,但我尝试了很多方法,但仍然错误

任务 2:端口 A 上的向上/向下计数器 这个任务的目标是编写一个可以从0000开始每1秒计数的汇编代码 到 1111 或根据 2 个输入 RA0 和 RA1 以相反的顺序从 1001 到 0000 表 1. 当计数达到最大值(向上计数为 1111)或最小值(0000 向下计数),计数将循环回到另一端(再次从0000开始计数 向上,或再次从 1111 开始倒计时)。应发送计数的 4 位输出 输出 RB7:4,其中 RB7 作为 MSB,RB4 作为 LSB。

对于这个我无法向上或向下计数,在暂停期间它可以工作

任务 1 的代码:

__CONFIG    _CONFIG1, _FOSC_HS & _WDTE_OFF & _PWRTE_ON & _PWRTE_OFF & _BOREN_ON & _LVP_OFF & _CPD_OFF & _WRT_OFF & _DEBUG_OFF
__CONFIG    _CONFIG2, _CP_OFF

开始: bcf 状态,RP0 ;选择银行 0 clrf 端口 B ;清除端口B movlw 0x00;将 PORTB 初始化为 0 movwf 端口B movlw b'00001111';将 RB7:4 设置为输出,RB3:0 设置为输入 movwf TRISB movlw b'11111100';将 RA0 和 RA1 设置为输入 movwf 特丽莎

主循环: btfsc PORTA,1;检查 RA1 是否为低电平(计数器禁用) 转到主循环;如果 RA1 较低,则不执行任何操作

btfsc   PORTA, 0           ; Check if RA0 is low (count down)
goto    CountDown
goto    CountUp

计数: 调用 Delay1Sec ;等待1秒 incf PORTB,F;增量端口B movf PORTB, W andlw b'11110000';屏蔽低 4 位 xorlw b'11110000';检查是否是1111 btfss 状态,Z ;如果不是1111,则跳过下一行 movlw b'00000000';如果是 1111,则重置为 0000 movwf 端口B 转到主循环

倒计时: 调用 Delay1Sec ;等待1秒 decf PORTB, F ;减少 PORTB movf PORTB, W andlw b'11110000';屏蔽低 4 位 btfsc 状态,Z ;如果结果不为 0000,则跳过下一行 movlw b'11110000';如果为 0000,则设置为 1111 movwf 端口B 转到主循环

延迟1秒: ;此处实现大约 1 秒的延迟 ;这个延迟环只是一个占位符,应该进行校准 movlw D'255' movwf 计数1 外延迟循环: movlw D'255' movwf 计数2 内部延迟循环: decfsz count2, f 转到内部延迟循环 decfsz 计数 1, f 转到外延迟循环 返回

END

任务 2 的代码:

ORG     0x00
goto    START

ORG     0x04                ; Interrupt vector

开始: bcf 状态,RP0 ;选择银行 0 clrf 端口 B ;清除端口B movlw 0x00;将 PORTB 初始化为 0 movwf 端口B movlw b'00001111';将 RB7:4 设置为输出,RB3:0 设置为输入 movwf TRISB movlw b'11111100';将 RA0 和 RA1 设置为输入 movwf 特丽莎

主循环: btfsc PORTA,1;检查 RA1 是否为低电平(计数器禁用) 转到主循环;如果 RA1 较低,则不执行任何操作

btfsc   PORTA, 0           ; Check if RA0 is low (count down)
goto    CountDown
goto    CountUp

计数: 调用 Delay1Sec ;等待1秒 incf PORTB,F;增量端口B movf PORTB, W andlw b'11110000';屏蔽低 4 位 xorlw b'11110000';检查是否是1111 btfss 状态,Z ;如果不是1111,则跳过下一行 movlw b'00000000';如果是 1111,则重置为 0000 movwf 端口B 转到主循环

倒计时: 调用 Delay1Sec ;等待1秒 decf PORTB, F ;减少 PORTB movf PORTB, W andlw b'11110000';屏蔽低 4 位 btfsc 状态,Z ;如果结果不为 0000,则跳过下一行 movlw b'11110000';如果为 0000,则设置为 1111 movwf 端口B 转到主循环

延迟1秒: ;此处实现大约 1 秒的延迟 ;这个延迟环只是一个占位符,应该进行校准 movlw D'255' movwf 计数1 外延迟循环: movlw D'255' movwf 计数2 内部延迟循环: decfsz count2, f 转到内部延迟循环 decfsz 计数 1, f 转到外延迟循环 返回

END

任务 1:PORT.A0 上的 1 Hz 方波

任务 2:表 1(https://i.sstatic.net/UmUhy95E.png)

assembly mplab
1个回答
0
投票

首先要注意的是,这个答案的代码量比你的家庭作业所需的代码量要多得多。提交此信息,您的作业就会失败。

此代码确实符合您任务的“字母”,但它在一个应用程序中完成所有这些任务。

不使用定时器中断的规定有点问题,但没有任何地方说你不能使用定时器来确定实际时间已经过去了多少。

我怀疑你的老师希望你做大量繁琐的指令周期计数来创建一个可调用的延迟函数。

该代码使用了您的讲师可能没有提到的技术,因此,在您能够向自己解释该代码的工作原理之前,不要让您的讲师认为您编写了它。

;
; File:     main.S
; Target:   PIC16F84A
; Author:   dan1138
; Date:     2024-05-30
; Compiler: pic-as v2.45
; IDE:      MPLABX v6.15
;
; Add this line in the project properties box, pic-as Global Options -> Additional options:
;   -Wa,-a -Wl,-pPor_Vec=0h,-pIsr_Vec=4h
;
; Description:
;
;   Homework example
;   See: https://stackoverflow.com/questions/78504317/issue-with-the-delay-and-the-toggle

;   Task 1: 
;       Create a 1 Hz Square Waveform on PORTA bit 0 
;       Write an assembly language program to create a 1 Hz square waveform on PORT A0. 
;           a) First write your code to toggle PORT A0 without any delay 
;           b) Then add a delay subroutine to produce the required delay. 
;       You are not allowed to use Timer Interrupt for the delay subroutine.
;
;   Task 2: 
;       Up/Down Counter on PORT A 
;       The goal of this task is to write an assembly code which can count 
;       every 1 second from 0000 to 1111 or in reverse order from 1001 to 0000 
;       based on the 2 inputs RA1 and RA2 shown in the Table 1. 
;
;       When the counting has reaches maximum (1111 for count up) or 
;       minimum (0000 for count down), the counting will loop back to 
;       the other end (start from 0000 again for count up, 
;       or start from 1111 again for count down). 
;
;       The 4-bit output of the counting should be sent to outputs RB7:4, 
;       where RB7 as MSB and RB4 as LSB.
;
;   Table 1:
;           +-------+-------+-------------------------+
;           :    Input      :         output          :
;           +-------+-------+-------------------------+
;           :  RA1  :  RA2  :     Counting(RB7:4)     :
;           +-------+-------+-------------------------+
;           :   0   :   0   :         paused          :
;           +-------+-------+-------------------------+
;           :   0   :   1   :        Count up         :
;           +-------+-------+-------------------------+
;           :   1   :   0   :       Count down        :
;           +-------+-------+-------------------------+
;           :   1   :   1   : Reset to 0000 and pause :
;           +-------+-------+-------------------------+
;
;                           PIC16F84A
;                   +----------:_:----------+
;    Button_2 <>  1 : RA2               RA1 : 18 <> Button_1
;             <>  2 : RA3               RA0 : 17 <> One_Hz_Output
;             <>  3 : RA4/T0CKI        OSC1 : 16 <- 4MHz crystal
;    ICSP_VPP ->  4 : MCLR             OSC2 : 15 -> 4MHz crystal
;         GND ->  5 : GND               VDD : 14 <- 5v0
;             <>  6 : RB0/INT       PGD/RB7 : 13 <> LED_3/ICSP_PGD
;             <>  7 : RB1           PGC/RB6 : 12 <> LED_2/ICSP_PGC
;             <>  8 : RB2               RB5 : 11 <> LED_1
;             <>  9 : RB3               RB4 : 10 <> LED_0
;                   +-----------------------:
;                            DIP-18

    PROCESSOR   16F84A
    PAGEWIDTH   132
    RADIX       DEC

#include <xc.inc>

; PIC16F84A Configuration Bit Settings
  CONFIG  FOSC = HS             ; Oscillator Selection bits (HS oscillator)
  CONFIG  WDTE = OFF            ; Watchdog Timer (WDT disabled)
  CONFIG  PWRTE = OFF           ; Power-up Timer Enable bit (Power-up Timer is disabled)
  CONFIG  CP = OFF              ; Code Protection bit (Code protection disabled)
;
; Skip macros
;
skpndc  MACRO
    btfsc   STATUS,STATUS_DC_POSITION
        ENDM

skpdc   MACRO
    btfss   STATUS,STATUS_DC_POSITION
        ENDM
skpnc  MACRO
    btfsc   STATUS,STATUS_C_POSITION
        ENDM

skpc   MACRO
    btfss   STATUS,STATUS_C_POSITION
        ENDM

skpnz  MACRO
    btfsc   STATUS,STATUS_Z_POSITION
        ENDM

skpz   MACRO
    btfss   STATUS,STATUS_Z_POSITION
        ENDM
;
; Power-On-Reset entry point
;
    PSECT   Por_Vec,global,class=CODE,delta=2
    global  resetVec
resetVec:
    goto    main
;
;   Data space use by interrupt handler to save context
    PSECT   Isr_Data,global,class=RAM,space=1,delta=1,noexec
;
    GLOBAL  WREG_save,STATUS_save,PCLATH_save
    GLOBAL  Segments
;
WREG_save:      ds      1
STATUS_save:    ds      1
PCLATH_save:    ds      1
Segments:       ds      2
;
;   Interrupt vector and handler
    PSECT   Isr_Vec,global,class=CODE,delta=2
    GLOBAL  IsrVec
;
IsrVec:
    movwf   WREG_save
    swapf   STATUS,W
    movwf   STATUS_save
    movf    PCLATH,W
    movwf   PCLATH_save
;
IsrHandler:

;
IsrExit:
    movf    PCLATH_save,W
    movwf   PCLATH
    swapf   STATUS_save,W
    movwf   STATUS
    swapf   WREG_save,F
    swapf   WREG_save,W
    retfie                      ; Return from interrupt
;
;objects in bank 0 memory, note PIC16F84 does not have banked memory
    PSECT   MainData,global,class=RAM,space=1,delta=1,noexec
    GLOBAL  T0_Sample,TicksInTenthSecCount,TenthSecondCount,OneSecondCount
    GLOBAL  SW_Flags
    GLOBAL  BTN_sample,BTN_stable,BTN_change,BTN_bounce

T0_Sample:      ds      1
#define T0_COUNTS_PER_TICK 125
#define TICKS_PER_TENTH_SEC 25
TicksInTenthSecCount: ds    1
TenthSecondCount:     ds    1
OneSecondCount:       ds    1
#define SW_1          SW_Flags,0
#define SW_1_MASK     0x01
#define SW_2          SW_Flags,1
#define SW_2_MASK     0x02
SW_Flags:       ds      1
#define DEBOUNCE_COUNT  2
#define BTN1_POSITION   1
#define BTN1_MASK       0x02
#define BTN2_POSITION   2
#define BTN2_MASK       0x04
BTN_sample:     ds      1
BTN_stable:     ds      1
BTN_change:     ds      1
BTN_bounce:     ds      1
;
; Applicaiton initialization
    PSECT   MainCode,global,class=CODE,delta=2
main:
    clrf    INTCON
    BANKSEL TRISB
    movlw   0x0F
    movwf   TRISB
    movlw   0xFE                ; RA0 output, RA1,RA2 inputs
    movwf   TRISA
    movlw   0x84                ; TMR0 clock source Fosc/4, TMR0 prescale 1:32
    movwf   OPTION_REG

    banksel TMR0
    clrf    TMR0
    clrf    T0_Sample
    movlw   TICKS_PER_TENTH_SEC
    movwf   TicksInTenthSecCount
    movlw   10
    movwf   TenthSecondCount
    clrf    OneSecondCount

    clrf    BTN_sample
    clrf    BTN_stable
    clrf    BTN_change
    clrf    BTN_bounce
    clrf    SW_Flags
;
; Application process loop
AppLoop:
    call    Wait4ms
;
; debounce switches
    call    BTN_Poll
    iorlw   0
    skpnz               ; Skip if a button changed state
    goto    Count4msTicks
;
; Process button inputs
    movf    BTN_stable,W
    andwf   BTN_change,F
    btfsc   BTN_change,BTN2_POSITION
    bsf     SW_2        ; buttin 2 changed to pressed
    btfsc   BTN_change,BTN1_POSITION
    bsf     SW_1        ; buttin 1 changed to pressed
    clrf    BTN_change
;
; Process when button changed to pressed
    btfsc   SW_1
    call    SW_1_Process
    btfsc   SW_2
    call    SW_2_Process
;
; count 4ms ticks
Count4msTicks:
;
    decfsz  TicksInTenthSecCount,F
    goto    AppLoop
    movlw   TICKS_PER_TENTH_SEC
    movwf   TicksInTenthSecCount
;
; count tenths of seconds
    movf    TenthSecondCount,F
    skpz    
    decfsz  TenthSecondCount,F
    goto    AppLoop
    movlw   10
    movwf   TenthSecondCount
;
; do one Hz toggle on PORTA
    movlw   1
    xorwf   PORTA,F

    btfsc   BTN_stable,BTN1_POSITION
    goto    ButtonPressed
    btfsc   BTN_stable,BTN2_POSITION
    goto    ButtonPressed
;
; No buttons pressed,  state pause
    goto    ShowCount
ButtonPressed:
    btfss   BTN_stable,BTN1_POSITION
    goto    ButtonOneNotPressed
    btfss   BTN_stable,BTN2_POSITION
    goto    ButtonOneNotPressed
;
; Both buttons pressed, state Reset pause
    clrf    OneSecondCount
    goto    ShowCount
ButtonOneNotPressed:
    btfsc   BTN_stable,BTN2_POSITION
    incf    OneSecondCount,F
    btfsc   BTN_stable,BTN1_POSITION
    decf    OneSecondCount,F
ShowCount:
    swapf   OneSecondCount,W
    andlw   0xF0
    xorwf   PORTB,W
    xorwf   PORTB,F
    goto    AppLoop
;
; ============================================
; Button changed to pressed event processing
SW_1_Process:
    bcf     SW_1
    return
;
SW_2_Process:
    bcf     SW_2
    return
;
; ============================================
; Button polling
;
; poll buttons
; Returns: WREG = 0, no buttons changed
;          WREG = 1, buttons changed
BTN_Poll:
    clrw
    btfsc   PORTA,1
    iorlw   BTN1_MASK
    btfsc   PORTA,2
    iorlw   BTN2_MASK
    xorwf   BTN_sample,W
    skpnz
    goto    BTN_debounce
    xorwf   BTN_sample,F
    movlw   DEBOUNCE_COUNT
    movwf   BTN_bounce
    retlw   0
BTN_debounce:
    movf    BTN_bounce,F
    skpnz
    goto    BTN_debounce_done
    decfsz  BTN_bounce,F
    retlw   0
BTN_debounce_done:
    movf    BTN_sample,W
    xorwf   BTN_stable,W
    skpnz
    retlw   0
    iorwf   BTN_change,F
    xorwf   BTN_stable,F
    retlw   1
;
; Wait 4 milliseconds
Wait4ms:
    movf    T0_Sample,W
    subwf   TMR0,W
    sublw   T0_COUNTS_PER_TICK
    skpnc
    goto    Wait4ms
    movlw   T0_COUNTS_PER_TICK
    addwf   T0_Sample,F
    return

    END     resetVec

这确实可以在 MPLABX 模拟器中运行,但我不使用 Proteus,所以这取决于你。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.