为什么我在 AVR 中的中断无法正常工作?

Why my interrupt in AVR does not work correctly?

本文关键字:常工作 工作 AVR 中断 为什么      更新时间:2023-10-16

编辑:它正在工作

我正在与PC进行Atmega8通信编程。我使用 Treminal v1.9b 发送和接收"消息"。这是我的代码:

#include <avr/io.h>
#include <stdlib.h>
#include <util/delay.h>
#include <string.h>
#include <avr/interrupt.h>
#include <stdlib.h>
void print_char(char letter)
{
if( bit_is_set(UCSRA, UDRE) )
{
_delay_ms(10);
UDR=letter;
loop_until_bit_is_set(UCSRA, TXC);
}
}
volatile char what = 'x';
int main(void)
{
DDRC |= (1<<PC0);
DDRC |= (1<<PC1);
DDRC |= (1<<PC2);
UBRRL = 12;//4800 1mhz
UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<RXCIE);
UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
sei();
PORTC ^= (1<<PC1);
while(1)
{
print_char(what);
PORTC ^= (1<<PC0);
_delay_ms(100);
}
}
ISR(USART_RXC_vect)
{
what = UDR;
PORTC ^= (1<<PC2);
}

打开uC后,在控制台(终端v1.9b(中出现"x",尝试发送任何内容后,"x"停止弹出。就像程序挂起或中断没有返回主程序一样。(将任何内容发送到 uC 后,给定的值应显示在控制台中(。

当 uC 接通时,PC1 处的 LED 亮起,PC0 处的 LED 闪烁,PC2 处的 LED 变暗。将任何字符发送到uC后:PC0处的led是暗的,PC1处的led是发光的,PC2处是暗的。好像功能ISR((没有启动。

问题出在哪里?

.iss 文件:

usb2.elf:     file format elf32-avr
Sections:
Idx Name          Size      VMA       LMA       File off  Algn
0 .text         00000106  00000000  00000000  00000074  2**1
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data         00000002  00800060  00000106  0000017a  2**0
CONTENTS, ALLOC, LOAD, DATA
Disassembly of section .text:
00000000 <__vectors>:
0:   29 c0           rjmp    .+82        ; 0x54 <__ctors_end>
2:   00 00           nop
4:   3a c0           rjmp    .+116       ; 0x7a <__bad_interrupt>
6:   00 00           nop
8:   38 c0           rjmp    .+112       ; 0x7a <__bad_interrupt>
a:   00 00           nop
c:   36 c0           rjmp    .+108       ; 0x7a <__bad_interrupt>
e:   00 00           nop
10:   34 c0           rjmp    .+104       ; 0x7a <__bad_interrupt>
12:   00 00           nop
14:   32 c0           rjmp    .+100       ; 0x7a <__bad_interrupt>
16:   00 00           nop
18:   30 c0           rjmp    .+96        ; 0x7a <__bad_interrupt>
1a:   00 00           nop
1c:   2e c0           rjmp    .+92        ; 0x7a <__bad_interrupt>
1e:   00 00           nop
20:   2c c0           rjmp    .+88        ; 0x7a <__bad_interrupt>
22:   00 00           nop
24:   2a c0           rjmp    .+84        ; 0x7a <__bad_interrupt>
26:   00 00           nop
28:   28 c0           rjmp    .+80        ; 0x7a <__bad_interrupt>
2a:   00 00           nop
2c:   55 c0           rjmp    .+170       ; 0xd8 <__vector_11>
2e:   00 00           nop
30:   24 c0           rjmp    .+72        ; 0x7a <__bad_interrupt>
32:   00 00           nop
34:   22 c0           rjmp    .+68        ; 0x7a <__bad_interrupt>
36:   00 00           nop
38:   20 c0           rjmp    .+64        ; 0x7a <__bad_interrupt>
3a:   00 00           nop
3c:   1e c0           rjmp    .+60        ; 0x7a <__bad_interrupt>
3e:   00 00           nop
40:   1c c0           rjmp    .+56        ; 0x7a <__bad_interrupt>
42:   00 00           nop
44:   1a c0           rjmp    .+52        ; 0x7a <__bad_interrupt>
46:   00 00           nop
48:   18 c0           rjmp    .+48        ; 0x7a <__bad_interrupt>
4a:   00 00           nop
4c:   16 c0           rjmp    .+44        ; 0x7a <__bad_interrupt>
4e:   00 00           nop
50:   14 c0           rjmp    .+40        ; 0x7a <__bad_interrupt>
...
00000054 <__ctors_end>:
54:   11 24           eor r1, r1
56:   1f be           out 0x3f, r1    ; 63
58:   cf e5           ldi r28, 0x5F   ; 95
5a:   d4 e0           ldi r29, 0x04   ; 4
5c:   de bf           out 0x3e, r29   ; 62
5e:   cd bf           out 0x3d, r28   ; 61
00000060 <__do_copy_data>:
60:   10 e0           ldi r17, 0x00   ; 0
62:   a0 e6           ldi r26, 0x60   ; 96
64:   b0 e0           ldi r27, 0x00   ; 0
66:   e6 e0           ldi r30, 0x06   ; 6
68:   f1 e0           ldi r31, 0x01   ; 1
6a:   02 c0           rjmp    .+4         ; 0x70 <.do_copy_data_start>
0000006c <.do_copy_data_loop>:
6c:   05 90           lpm r0, Z+
6e:   0d 92           st  X+, r0
00000070 <.do_copy_data_start>:
70:   a2 36           cpi r26, 0x62   ; 98
72:   b1 07           cpc r27, r17
74:   d9 f7           brne    .-10        ; 0x6c <.do_copy_data_loop>
76:   0c d0           rcall   .+24        ; 0x90 <main>
78:   44 c0           rjmp    .+136       ; 0x102 <_exit>
0000007a <__bad_interrupt>:
7a:   c2 cf           rjmp    .-124       ; 0x0 <__vectors>
0000007c <_Z10print_charc>:
7c:   5d 9b           sbis    0x0b, 5 ; 11
7e:   07 c0           rjmp    .+14        ; 0x8e <_Z10print_charc+0x12>
80:   e4 ec           ldi r30, 0xC4   ; 196
82:   f9 e0           ldi r31, 0x09   ; 9
84:   31 97           sbiw    r30, 0x01   ; 1
86:   f1 f7           brne    .-4         ; 0x84 <_Z10print_charc+0x8>
88:   8c b9           out 0x0c, r24   ; 12
8a:   5e 9b           sbis    0x0b, 6 ; 11
8c:   fe cf           rjmp    .-4         ; 0x8a <_Z10print_charc+0xe>
8e:   08 95           ret
00000090 <main>:
90:   1f 93           push    r17
92:   cf 93           push    r28
94:   df 93           push    r29
96:   a0 9a           sbi 0x14, 0 ; 20
98:   a1 9a           sbi 0x14, 1 ; 20
9a:   a2 9a           sbi 0x14, 2 ; 20
9c:   8c e0           ldi r24, 0x0C   ; 12
9e:   89 b9           out 0x09, r24   ; 9
a0:   88 e9           ldi r24, 0x98   ; 152
a2:   8a b9           out 0x0a, r24   ; 10
a4:   86 e8           ldi r24, 0x86   ; 134
a6:   80 bd           out 0x20, r24   ; 32
a8:   85 b7           in  r24, 0x35   ; 53
aa:   81 60           ori r24, 0x01   ; 1
ac:   85 bf           out 0x35, r24   ; 53
ae:   8b b7           in  r24, 0x3b   ; 59
b0:   80 64           ori r24, 0x40   ; 64
b2:   8b bf           out 0x3b, r24   ; 59
b4:   78 94           sei
b6:   85 b3           in  r24, 0x15   ; 21
b8:   92 e0           ldi r25, 0x02   ; 2
ba:   89 27           eor r24, r25
bc:   85 bb           out 0x15, r24   ; 21
be:   11 e0           ldi r17, 0x01   ; 1
c0:   c8 ea           ldi r28, 0xA8   ; 168
c2:   d1 e6           ldi r29, 0x61   ; 97
c4:   80 91 60 00     lds r24, 0x0060
c8:   d9 df           rcall   .-78        ; 0x7c <_Z10print_charc>
ca:   85 b3           in  r24, 0x15   ; 21
cc:   81 27           eor r24, r17
ce:   85 bb           out 0x15, r24   ; 21
d0:   ce 01           movw    r24, r28
d2:   01 97           sbiw    r24, 0x01   ; 1
d4:   f1 f7           brne    .-4         ; 0xd2 <main+0x42>
d6:   f6 cf           rjmp    .-20        ; 0xc4 <main+0x34>
000000d8 <__vector_11>:
d8:   1f 92           push    r1
da:   0f 92           push    r0
dc:   0f b6           in  r0, 0x3f    ; 63
de:   0f 92           push    r0
e0:   11 24           eor r1, r1
e2:   8f 93           push    r24
e4:   9f 93           push    r25
e6:   85 b3           in  r24, 0x15   ; 21
e8:   94 e0           ldi r25, 0x04   ; 4
ea:   89 27           eor r24, r25
ec:   85 bb           out 0x15, r24   ; 21
ee:   8c b1           in  r24, 0x0c   ; 12
f0:   80 93 60 00     sts 0x0060, r24
f4:   9f 91           pop r25
f6:   8f 91           pop r24
f8:   0f 90           pop r0
fa:   0f be           out 0x3f, r0    ; 63
fc:   0f 90           pop r0
fe:   1f 90           pop r1
100:   18 95           reti
00000102 <_exit>:
102:   f8 94           cli
00000104 <__stop_program>:
104:   ff cf           rjmp    .-2         ; 0x104 <__stop_program>

如您所见,在生成的向量表中:

00000000 <__vectors>:
0:   29 c0           rjmp    .+82        ; 0x54 <__ctors_end>
2:   00 00           nop
4:   3a c0           rjmp    .+116       ; 0x7a <__bad_interrupt>
6:   00 00           nop
8:   38 c0           rjmp    .+112       ; 0x7a <__bad_interrupt>
a:   00 00           nop
...
2c:   55 c0           rjmp    .+170       ; 0xd8 <__vector_11>
2e:   00 00           nop

每个中断向量使用 2 个单词:一个用于rjmp,一个填充nop

因此,第 12 个向量位于 addrees 0x002C(或0x16词地址(。

表 18的数据表中,中断向量部分在 ATmega8 的第46页中,您可以看到,在 ATmega8 中,每个向量只分配一个单词(对于rjmp指令来说就足够了,它允许跳转到 4Kwords 地址空间内的任何地址(。

因此,USART,RXC向量应放置在0x0B字地址(或0x0016字节地址(处。

换句话说,您的编译环境设置不正确,可能是您选择了错误的CPU。

当实际中断发生时,执行向量 at(字节地址0x0016

16:   00 00           nop
18:   30 c0           rjmp    .+96        ; 0x7a <__bad_interrupt>

导致跳过nop操作并跳转到__bad_interrupt标签:

0000007a <__bad_interrupt>:
7a:   c2 cf           rjmp    .-124       ; 0x0 <__vectors>

这会导致程序停止