This is the MPASM code for blinking led using the TIMER0 interrupt in pic16f676. The pin 0 (RA0) of portA is not toggling to off position. please help...
这是使用Pic16f676中的TIMER0中断闪烁LED的MPASM代码。PORTA的针脚0(RA0)未切换到OFF位置。请帮帮我..。
I'm newbie to pic assembly, I would like to master pic. is there any pic prodigies please help me to learn...
我是拼图新手,我想掌握拼图。有没有摄影神童能帮我学习一下……
I need to blink at an interval of 1 sec.
CODE is:
我需要每隔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
It seems to bet the delay problem. But shuffling the pre-scalar and counter keeps led in on position. I need to On and Off Led.
这似乎是在押注延误问题。但洗牌前标量和计数器会让LED保持在适当的位置。我需要打开和关闭LED。
更多回答
Small point: the interrupt routine doesn't seem to reset the counter decremented with DECFSZ MyCount, 1
小问题:中断例程似乎没有重置用DECFSZ MyCount,1递减的计数器
@WeatherVane Vane.. you are right, but still the led connected to RA0 is always in on position.
@风向标..您是对的,但是连接到RA0的LED始终处于亮起的位置。
Grab the data sheet and calculate the period of the interrupt determining the blink frequency. I'm sure that it is by far too small to be visible by humans and you see a "half-on" LED.
抓起数据表,计算确定闪烁频率的中断周期。我敢肯定,到目前为止,它太小了,人类无法看到,而且你看到的是一个“半亮”的LED。
An oscilloscope is an invaluable tool for something like this.
对于这样的东西,示波器是一个无价的工具。
Welcome to Stack overflow, but please don't make rolling improvements to posted code. Otherwise there is no question remaining for others to see, and the comments won't be understood.
欢迎使用Stack Overflow,但请不要对发布的代码进行滚动改进。否则,其他人就不会看到任何问题,评论也不会被理解。
优秀答案推荐
Here are some problems I detected in your code...
以下是我在您的代码中发现的一些问题...
1. Wrong port initialization
As I have mentioned in this answer your init code lacks code for CMCON
, the register that controls the analog comparators modue. Here is how you should set it up correctly:
正如我在这个回答中提到的,您的初始化代码缺少CMCON的代码,CMCON是控制模拟比较器模块的寄存器。以下是您应该如何正确设置它:
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. Your timer setup will not give you a 1 second delay
You set the prescaler to 1:128, means that the timer will be incremented on every 128us.
Your timer reload value is 10, means that it will count 245 until it overflows. Then your overflow rate is 128us * 245 = 31360us
.
In order to produce 1 sec delay from this value you should use a helper variable and set it to 1000000 / 31360 = 31.8877
let's round it up to 32 in decimal. So you should load the MyCount
variable with 32 in order to generate a 1 sec delay in total.
But your actual value is 18 in decimal, that would make a 18 * 31360 = 564.480ms
which is approximately half a second.
您将预分频器设置为1:128,这意味着计时器将每128秒递增一次。您的计时器重载值为10,这意味着它将数到245,直到溢出。那么您的溢出率是128us*245=31360us。为了从这个值产生1秒的延迟,您应该使用一个helper变量并将其设置为1000000/31360=31.8877,让我们将其向上舍入为十进制的32。因此,您应该将MyCount变量加载为32,以生成总共1秒的延迟。但是您的实际值是十进制的18,那就是18*31360=564.480ms,大约是半秒。
3. Incorrect interrupt handling
Let's see your timer0 interrupt handler code first.
让我们先来看看您的定时器0中断处理程序代码。
ISR_HANDLER:
DECFSZ MyCount, 1
RETFIE
movlw 0x01
xorwf PORTA, F
BCF INTCON, TMR0IF
MOVLW d'10'
MOVWF TMR0
RETFIE
You should have cleared the timer0 flag everytime the timer0 hits the interrupt. But you clear it only when your counter reaches to zero. But here is the problem: the program will get stuck in the timer interrupt until its flag gets cleared. So the DECFSZ MyCount, 1
instruction will be executed very rapidly due to the successive calls to the timer interrupt, resulting in a very fast flashing of the output pin. Hence no eyes will catch it is flashing.
Another problem is that you don't reload the MyCount
's value after it reaches the zero. This will cause that the variable underflow to 255 and after the first time it always will keep counting down from 255.
您应该在每次定时器0命中中断时清除定时器0标志。但只有当你的计数器达到零时才能清除它。但这里有一个问题:程序将陷入计时器中断,直到其标志被清除。因此,由于对定时器中断的连续调用,DECFSZ MyCount,1指令将被非常快速地执行,从而导致输出引脚非常快地闪烁。因此,没有人会注意到它在闪烁。另一个问题是,在MyCount的值达到零之后,您不会重新加载它。这将导致变量下溢到255,并且在第一次之后,它将始终从255开始倒计时。
So what you should do is to clear the flag and reload the timer0 value everytime the interrupt gets hit, regardles the value of the counter. You should also reload the MyCount
value so that it keeps counting down from the calculated value. Finally the correct flow in the timer interrupt would be as following:
因此,您应该做的是清除标志,并在每次命中中断时重新加载timer0值,而不考虑计数器的值。您还应该重新加载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
Apply the above fixes into your code and try it again. Let me know the result.
将上述修复应用到您的代码中,然后重试。让我知道结果。
更多回答
YAY!! It works now. I calculated exact delay as per your advice... Since i selected 1:128 pre-scale. the calculation seems complicated. Thus I selected watchdog timer with 1:1 pre-scale. Interrupt ticks as every 256 times counted each 1us since I used 4MHZ. by decrementing usec(255) every time timer0 interrupt clicks and As "usec" variable reaches 0, another "sec" variable decrease from 16 to 0. thus total 255*255*16 1040400us =~1.04s. now there is another problem suffering. Using polling and turn on an led concted to RC5 led turns on for some times and automatically turns off.
耶!!它现在起作用了。我按照你的建议计算了准确的延误时间。因为我选择了1:128预比例尺。计算似乎很复杂。因此,我选择了1:1预刻度的看门狗定时器。自从我使用4 MHz以来,中断滴答作响,因为每256次都会计算每个1U。通过在每次定时器0中断点击时递减USEC(255),并且当“USEC”变量达到0时,另一个“SEC”变量从16减少到0。因此,总计255*255*16 1040400us=~1.04s。现在,还有另一个问题正在遭受折磨。使用轮询和打开连接到RC5 LED的LED打开一段时间,然后自动关闭。
我是一名优秀的程序员,十分优秀!