C 闪烁和中断项目
C Blink and Interrupt project
我卡住了,不知道从哪里开始。
修改给你的示例代码,使它的功能与之前编写的汇编代码一样。
B0 上的 LED 应该持续闪烁。每当您按下开关时,其他 3 个 LED 应显示计数序列中的下一个数字 0 -> 7,然后返回到 0。
-需要修改的示例代码C Blink和中断代码
#include <avr/io.h>
#define F_CPU 1000000UL // 1 MHz
#include <util/delay.h>
#include <avr/interrupt.h>
ISR(PCINT2_vect) { /* Run every time there is a change on button */
if (PIND & (1 << PIND0)) {
PORTD |= (1<<PORTD1);
PORTD |= (1<<PORTD2);
PORTD |= (1<<PORTD3);
_delay_ms(250);
PORTD &= ~ (1<<PORTD1);
PORTD &= ~ (1<<PORTD2);
PORTD &= ~ (1<<PORTD3);
}
}
void initInterrupt0(void) {
PCICR |= (1 << PCIE2); /* set pin-change interrupt for D pins */
PCMSK2 |= (1 << PCINT16); /* set mask to look for PCINT18 / PD2 */
sei(); /* set (global) interrupt enable bit */
}
int main(void)
{
// -------- Inits --------- //
DDRB |= (1<<DDB0);
DDRD |= (1<<DDD1);
DDRD |= (1<<DDD2);
DDRD |= (1<<DDD3);
initInterrupt0();
/* Blink code */
while (1)
{
_delay_ms(200);
PORTB |= (1<<PORTB0);
_delay_ms(1000);
PORTB &= ~ (1<<PORTB0);
_delay_ms(1000);
}
}
汇编代码
.include "m328pdef.inc"
.def mask = r16 ; mask register
.def ledR = r17 ; led register
.def oLoopR = r18 ; outer loop register
.def iLoopRl = r24 ; inner loop register low
.def iLoopRh = r25 ; inner loop register high
.equ oVal = 71 ; outer loop value
.equ iVal = 2048 ; inner loop value
.org 0x0000
rjmp start
.org 0x000A
rjmp Interupt
;start of blinking
start:
sbi DDRD, 1
sbi DDRD, 2
sbi DDRD, 3
cbi DDRD, 0
; interupt requirments
sei
lds r16, PCMSK2
ori r16, (1<<PCINT16)
sts PCMSK2, r16
lds r16, PCICR
ori r16, (1<<PCIE2)
sts PCICR, r16
clr r20
clr ledR ; clear led register
ldi mask,(1<<PINB0) ; load 00000001 into mask register
out DDRB,mask ; set PINB0 to output
blink:
eor ledR,mask ; toggle PINB0 in led register
out PORTB,ledR ; write led register to PORTB
ldi oLoopR,oVal ; initialize outer loop count
oLoop: ldi iLoopRl,LOW(iVal) ; intialize inner loop count in inner
ldi iLoopRh,HIGH(iVal) ; loop high and low registers
iLoop: sbiw iLoopRl,1 ; decrement inner loop registers
brne iLoop ; branch to iLoop if iLoop registers != 0
dec oLoopR ; decrement outer loop register
brne oLoop ; branch to oLoop if outer loop register != 0
rjmp blink ; jump back to start
;interupt code
Interupt :
sbic PIND, 0
rjmp skip ; if interupt has just happened skip everything under this
inc r20
andi r20, 0b00000111
mov r19, r20
lsl r19
in r18, PIND
cbr r18, 0b00001110
or r18, r19
out PortD, r18
skip:
reti
一般问题:
- 所有开关都必须去抖动。如果没有在带有 RC 滤波器的硬件中完成,则必须在软件中完成。
- 由于上述原因,在连接到开关的 GPIO 输入上启用中断是一个重大错误。如果您知道自己在做什么,您 可以 这样做,但这可能不是初学者的任务。参见 。
- ISR 中不能有 250 毫秒的忙延迟,这完全没有意义。在这种情况下,它会搞砸 LED 的闪烁频率并阻止按钮触发。
我卡住了,不知道从哪里开始。
修改给你的示例代码,使它的功能与之前编写的汇编代码一样。
B0 上的 LED 应该持续闪烁。每当您按下开关时,其他 3 个 LED 应显示计数序列中的下一个数字 0 -> 7,然后返回到 0。
-需要修改的示例代码C Blink和中断代码
#include <avr/io.h>
#define F_CPU 1000000UL // 1 MHz
#include <util/delay.h>
#include <avr/interrupt.h>
ISR(PCINT2_vect) { /* Run every time there is a change on button */
if (PIND & (1 << PIND0)) {
PORTD |= (1<<PORTD1);
PORTD |= (1<<PORTD2);
PORTD |= (1<<PORTD3);
_delay_ms(250);
PORTD &= ~ (1<<PORTD1);
PORTD &= ~ (1<<PORTD2);
PORTD &= ~ (1<<PORTD3);
}
}
void initInterrupt0(void) {
PCICR |= (1 << PCIE2); /* set pin-change interrupt for D pins */
PCMSK2 |= (1 << PCINT16); /* set mask to look for PCINT18 / PD2 */
sei(); /* set (global) interrupt enable bit */
}
int main(void)
{
// -------- Inits --------- //
DDRB |= (1<<DDB0);
DDRD |= (1<<DDD1);
DDRD |= (1<<DDD2);
DDRD |= (1<<DDD3);
initInterrupt0();
/* Blink code */
while (1)
{
_delay_ms(200);
PORTB |= (1<<PORTB0);
_delay_ms(1000);
PORTB &= ~ (1<<PORTB0);
_delay_ms(1000);
}
}
汇编代码
.include "m328pdef.inc"
.def mask = r16 ; mask register
.def ledR = r17 ; led register
.def oLoopR = r18 ; outer loop register
.def iLoopRl = r24 ; inner loop register low
.def iLoopRh = r25 ; inner loop register high
.equ oVal = 71 ; outer loop value
.equ iVal = 2048 ; inner loop value
.org 0x0000
rjmp start
.org 0x000A
rjmp Interupt
;start of blinking
start:
sbi DDRD, 1
sbi DDRD, 2
sbi DDRD, 3
cbi DDRD, 0
; interupt requirments
sei
lds r16, PCMSK2
ori r16, (1<<PCINT16)
sts PCMSK2, r16
lds r16, PCICR
ori r16, (1<<PCIE2)
sts PCICR, r16
clr r20
clr ledR ; clear led register
ldi mask,(1<<PINB0) ; load 00000001 into mask register
out DDRB,mask ; set PINB0 to output
blink:
eor ledR,mask ; toggle PINB0 in led register
out PORTB,ledR ; write led register to PORTB
ldi oLoopR,oVal ; initialize outer loop count
oLoop: ldi iLoopRl,LOW(iVal) ; intialize inner loop count in inner
ldi iLoopRh,HIGH(iVal) ; loop high and low registers
iLoop: sbiw iLoopRl,1 ; decrement inner loop registers
brne iLoop ; branch to iLoop if iLoop registers != 0
dec oLoopR ; decrement outer loop register
brne oLoop ; branch to oLoop if outer loop register != 0
rjmp blink ; jump back to start
;interupt code
Interupt :
sbic PIND, 0
rjmp skip ; if interupt has just happened skip everything under this
inc r20
andi r20, 0b00000111
mov r19, r20
lsl r19
in r18, PIND
cbr r18, 0b00001110
or r18, r19
out PortD, r18
skip:
reti
一般问题:
- 所有开关都必须去抖动。如果没有在带有 RC 滤波器的硬件中完成,则必须在软件中完成。
- 由于上述原因,在连接到开关的 GPIO 输入上启用中断是一个重大错误。如果您知道自己在做什么,您 可以 这样做,但这可能不是初学者的任务。参见 。
- ISR 中不能有 250 毫秒的忙延迟,这完全没有意义。在这种情况下,它会搞砸 LED 的闪烁频率并阻止按钮触发。