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)
首先要注意的是,这个答案的代码量比你的家庭作业所需的代码量要多得多。提交此信息,您的作业就会失败。
此代码确实符合您任务的“字母”,但它在一个应用程序中完成所有这些任务。
不使用定时器中断的规定有点问题,但没有任何地方说你不能使用定时器来确定实际时间已经过去了多少。
我怀疑你的老师希望你做大量繁琐的指令周期计数来创建一个可调用的延迟函数。
该代码使用了您的讲师可能没有提到的技术,因此,在您能够向自己解释该代码的工作原理之前,不要让您的讲师认为您编写了它。
;
; 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,所以这取决于你。