assembly 为什么LED灯不 Flink ,而是一直亮着?

rjzwgtxy  于 7个月前  发布在  Flink
关注(0)|答案(1)|浏览(73)

这是使用图16f676中的TIMER0中断使LED Flink 的MPASM代码。端口A的引脚0(RA0)未切换到关闭位置。请帮帮我
我是新手图片组装,我想掌握图片。有没有什么绘画天才,请帮助我学习……
我需要每隔1秒眨眼一次。代码是:

#include "p16F676.inc"
 
    __CONFIG _FOSC_INTRCIO & _WDTE_OFF & _PWRTE_OFF & _MCLRE_OFF & _BOREN_OFF & _CP_OFF & _CPD_OFF
    MyCount   EQU       0x20    
    RES_VECT    CODE 0x0000     
        GOTO    CODE_INIT     
    
    ISR     CODE 0x0004     
        GOTO    ISR_HANDLER     
    
    ;MAIN_PROG   CODE    
    CODE_INIT:          
        CALL    PORT_INIT       
        CALL    TIMER_INIT      
        GOTO    IDLE_LOOP       
    
    ISR_HANDLER:   
        DECFSZ    MyCount, 1        
        RETFIE
        movlw 0x01 
        xorwf PORTA, F    
        BCF     INTCON, TMR0IF  
        MOVLW   d'10'       
        MOVWF   TMR0        
        RETFIE      
    IDLE_LOOP:
        NOP
        NOP             
        NOP
        NOP
        GOTO    IDLE_LOOP   
    PORT_INIT:
        BSF     STATUS, RP0 
        MOVLW   b'00000000'     
        MOVWF   ADCON1      
        MOVWF   ANSEL       
        MOVWF   TRISA       
        RETURN   
    TIMER_INIT:
        CLRWDT          
        MOVLW   b'00000110'     
        MOVWF   OPTION_REG    
        BSF     INTCON, GIE     
        BSF     INTCON, TMR0IE    
        BCF     STATUS, RP0   
        MOVLW   d'18'       
        MOVWF   MyCount     
    
        BCF     INTCON, TMR0IF  
        MOVLW   d'10'       
        MOVWF   TMR0        
        RETURN    
        END

它似乎打赌延迟的问题。但 Shuffle 的前标量和计数器保持领先的地位。我需要打开和关闭LED。

x7rlezfr

x7rlezfr1#

下面是我在你的代码中发现的一些问题。

1.端口初始化错误

正如我在this answer中提到的,您的init代码缺少CMCON的代码,CMCON是控制模拟比较器modue的寄存器。以下是您应该如何正确设置它:

BCF     STATUS,RP0  ;Bank 0
CLRF    PORTA       ;Init PORTA
MOVLW   05h         ;Set RA<2:0> to
MOVWF   CMCON       ;digital I/O
BSF     STATUS,RP0  ;Bank 1
CLRF    ANSEL       ;digital I/O
CLRF    TRISA       ;set all pins as outputs
BCF     STATUS,RP0  ;Bank 0

2.您的计时器设置不会给您给予1秒的延迟

将预分频器设置为1:128,意味着计时器将每128 us递增一次。
您的计时器重新加载值为10,意味着它将计数245,直到溢出。那么溢出率是128us * 245 = 31360us
为了从这个值产生1秒的延迟,你应该使用一个辅助变量,并将其设置为1000000 / 31360 = 31.8877,让我们将其舍入为十进制的32。因此,您应该将MyCount变量加载为32,以生成总共1秒的延迟。
但你的实际值是十进制的18,这将使18 * 31360 = 564.480ms大约是半秒。

3.错误的中断处理

让我们先看看你的定时器0中断处理程序代码。

ISR_HANDLER:   
    DECFSZ  MyCount, 1        
    RETFIE
    movlw   0x01 
    xorwf   PORTA, F    
    BCF     INTCON, TMR0IF  
    MOVLW   d'10'       
    MOVWF   TMR0        
    RETFIE

每次计时器0触发中断时,您都应该清除计时器0标志。但只有当计数器归零时才能清除。但问题来了:则程序将在定时器中断中卡住,直到其标志被清除。因此,DECFSZ MyCount, 1指令将由于对定时器中断的连续调用而非常快速地执行,从而导致输出引脚非常快速地 Flink 。因此,没有眼睛会抓住它 Flink 。
另一个问题是,在MyCount的值为零后,您不会重新加载它。这将导致变量下溢到255,并且在第一次之后,它总是从255开始倒数。
因此,你应该做的是清除标志,并重新加载计时器0值每次中断得到命中,计数器的值。您还应该重新加载MyCount值,以便它从计算值开始倒数。最后,定时器中断的正确流程如下:

ISR_HANDLER
    bcf     INTCON, TMR0IF
    movlw   d'10'
    BANKSEL TMR0    ; Make sure you're in correct data bank
    decfsz  MyCount, 1
    retfie
    movlw   d'32'
    BANKSEL MyCount ; Again make sure you're in correct bank
    movwf   MyCount
    ; PORTA and MyCount are in the same bank since MyCount's address is 0x20
    movlw   1
    xorwf   PORTA, F ; Toggle output due to 1 sec time out
    retfie

将上述修复应用到您的代码中,然后重试。告诉我结果。

相关问题