PIC16F84A单片机延迟与切换功能问题及任务求助
任务1:在PORT.A0引脚生成1Hz方波
需求
编写汇编语言程序,在PORT A0引脚生成1Hz方波:
- a) 先实现无延迟的PORT A0引脚电平切换代码
- b) 添加纯软件延迟子程序实现1Hz方波所需的500ms延迟(禁止使用定时器中断实现延迟)
问题
尝试多种方法后,延迟子程序始终报错。
修正后的代码
__CONFIG _CONFIG1, _FOSC_HS & _WDTE_OFF & _PWRTE_ON & _BOREN_ON & _LVP_OFF & _CPD_OFF & _WRT_OFF & _DEBUG_OFF __CONFIG _CONFIG2, _CP_OFF ; 定义延迟变量 count1 EQU 0x20 count2 EQU 0x21 count3 EQU 0x22 START: bcf STATUS, RP0 ; 选择Bank 0 clrf PORTA ; 清空PORTA bsf STATUS, RP0 ; 切换到Bank 1 movlw b'11111110' ; 设置RA0为输出,其余为输入 movwf TRISA bcf STATUS, RP0 ; 切回Bank 0 MainLoop: bsf PORTA, 0 ; RA0置高 call Delay500ms ; 延迟500ms bcf PORTA, 0 ; RA0置低 call Delay500ms ; 延迟500ms goto MainLoop ; 循环 ; 500ms延迟子程序(基于HS晶振,以4MHz为例,需根据实际晶振校准) Delay500ms: movlw D'5' movwf count1 OuterLoop: movlw D'200' movwf count2 MiddleLoop: movlw D'250' movwf count3 InnerLoop: decfsz count3, f goto InnerLoop decfsz count2, f goto MiddleLoop decfsz count1, f goto OuterLoop return END
错误点说明
- 原代码未定义
count1、count2等延迟变量,汇编器会报错,需通过EQU指定寄存器地址 - 原代码错误配置了PORTB/TRISB,任务1只需操作PORTA/TRISA
- 1Hz方波需要500ms高低电平切换,原延迟逻辑未达到对应时长
任务2:PORT A端口增减计数器
需求
编写汇编代码,根据RA0和RA1输入引脚状态实现以下功能:
- RA1=0:计数器暂停
- RA1=1且RA0=0:每1秒从0000(RB7:4=0000)递增计数到1111,达到1111后循环回0000
- RA1=1且RA0=1:每1秒从1111递减计数到0000,达到0000后循环回1111
- 4位计数结果输出至RB7:4,RB7为最高位,RB4为最低位
问题
暂停功能正常,但无法实现递增/递减计数。
修正后的代码
__CONFIG _CONFIG1, _FOSC_HS & _WDTE_OFF & _PWRTE_ON & _BOREN_ON & _LVP_OFF & _CPD_OFF & _WRT_OFF & _DEBUG_OFF __CONFIG _CONFIG2, _CP_OFF ; 定义变量 count1 EQU 0x20 count2 EQU 0x21 count3 EQU 0x22 temp EQU 0x23 ORG 0x00 goto START ORG 0x04 ; 中断向量(本任务未使用中断) START: bcf STATUS, RP0 ; 选择Bank 0 clrf PORTB ; 清空PORTB movlw 0x00 movwf PORTB ; 初始化RB7:4为0000 bsf STATUS, RP0 ; 切换到Bank 1 movlw b'00001111' ; RB7:4为输出,RB3:0为输入 movwf TRISB movlw b'11111100' ; RA0、RA1为输入 movwf TRISA bcf STATUS, RP0 ; 切回Bank 0 MainLoop: btfsc PORTA, 1 ; 检测RA1,RA1=0则暂停 goto MainLoop btfsc PORTA, 0 ; RA0=1则跳转到递减计数 goto CountDown goto CountUp CountUp: call Delay1Sec ; 延迟1秒 movf PORTB, W andlw b'00001111' ; 保留低4位,避免被修改 movwf temp movlw b'00001111' addwf PORTB, W ; 仅对高4位递增(等价于PORTB + 0x10) andlw b'11110000' iorwf temp, W ; 合并低4位 movwf PORTB movf PORTB, W andlw b'11110000' xorlw b'11110000' ; 判断是否达到1111 btfss STATUS, Z goto MainLoop movlw b'00000000' ; 重置为0000 iorwf temp, W movwf PORTB goto MainLoop CountDown: call Delay1Sec ; 延迟1秒 movf PORTB, W andlw b'00001111' ; 保留低4位 movwf temp movlw b'11110000' sublw PORTB, W ; 仅对高4位递减(等价于PORTB - 0x10) andlw b'11110000' iorwf temp, W ; 合并低4位 movwf PORTB movf PORTB, W andlw b'11110000' btfsc STATUS, Z ; 判断是否达到0000 goto MainLoop movlw b'11110000' ; 重置为1111 iorwf temp, W movwf PORTB goto MainLoop ; 1秒延迟子程序(基于4MHz HS晶振,需根据实际晶振校准) Delay1Sec: movlw D'10' movwf count1 OuterDelay: movlw D'200' movwf count2 MiddleDelay: movlw D'250' movwf count3 InnerDelay: decfsz count3, f goto InnerDelay decfsz count2, f goto MiddleDelay decfsz count1, f goto OuterDelay return END
错误点说明
- 原代码未定义
count1、count2变量,汇编器会报错 - 递增/递减时直接操作
PORTB会修改低4位,需通过掩码保留低4位,仅操作高4位 - 递增逻辑错误:原代码
incf PORTB, F会让整个PORTB加1,而非仅高4位加1,导致计数混乱 - 递减逻辑错误:原代码
decf PORTB, F同样会修改低4位,且边界判断逻辑有误
内容的提问来源于stack exchange,提问作者user25136115
相关产品推荐
相关产品推荐

