我正在尝试以裸机、非 IDE 方式在 Arduino 上学习嵌入式 C...并且我尝试以不同的方式自己编写一些
avr/io.h
宏。我尝试使用直接内存地址(有效)和带有位字段的结构指针(这不起作用)来闪烁 LED。
F_CPU 宏已定义。
直接内存地址(按预期工作):
#include <util/delay.h>
int main (void) {
*(volatile unsigned char*) 0x24 |= 1 << 5;
while(1) {
*(volatile unsigned char*) 0x25 |= 1 << 5;
_delay_ms(500);
*(volatile unsigned char*) 0x25 &= ~(1 << 5);
_delay_ms(500);
}
return 0;
}
编译器汇编:
main:
...
.L__stack_usage = 0
sbi 0x4,5
.L2:
sbi 0x5,5
ldi r18,lo8(1599999)
ldi r24,hi8(1599999)
ldi r25,hlo8(1599999)
1: subi r18,1
sbci r24,0
sbci r25,0
brne 1b
rjmp .
nop
cbi 0x5,5
ldi r18,lo8(1599999)
ldi r24,hi8(1599999)
ldi r25,hlo8(1599999)
1: subi r18,1
sbci r24,0
sbci r25,0
brne 1b
rjmp .
nop
rjmp .L2
...
位域方式的结构(不起作用,LED只是亮起):
#include <util/delay.h>
typedef unsigned char byte;
volatile struct {
volatile byte PINB0: 1;
volatile byte PINB1: 1;
volatile byte PINB2: 1;
volatile byte PINB3: 1;
volatile byte PINB4: 1;
volatile byte PINB5: 1;
volatile byte PINB6: 1;
volatile byte PINB7: 1;
} *__ATMEGA_328P_PINB = (void*) 0x23;
volatile struct {
volatile byte DDB0: 1;
volatile byte DDB1: 1;
volatile byte DDB2: 1;
volatile byte DDB3: 1;
volatile byte DDB4: 1;
volatile byte DDB5: 1;
volatile byte DDB6: 1;
volatile byte DDB7: 1;
} *__ATMEGA_328P_DDRB = (void*) 0x24;
volatile struct {
volatile byte PORTB0: 1;
volatile byte PORTB1: 1;
volatile byte PORTB2: 1;
volatile byte PORTB3: 1;
volatile byte PORTB4: 1;
volatile byte PORTB5: 1;
volatile byte PORTB6: 1;
volatile byte PORTB7: 1;
} *__ATMEGA_328P_PORTB = (void*) 0x25;
int main (void) {
__ATMEGA_328P_DDRB->DDB5 = 1;
while(1) {
__ATMEGA_328P_PORTB->PORTB5 = 1;
_delay_ms(500);
__ATMEGA_328P_PORTB->PORTB5 = 0;
_delay_ms(500);
}
return 0;
}
编译器汇编:
main:
...
.L__stack_usage = 0
lds r30,__ATMEGA_328P_DDRB
lds r31,__ATMEGA_328P_DDRB+1
ld r24,Z
ori r24,lo8(1<<5)
st Z,r24
.L2:
lds r30,__ATMEGA_328P_PORTB
lds r31,__ATMEGA_328P_PORTB+1
ld r24,Z
ori r24,lo8(1<<5)
st Z,r24
ldi r18,lo8(1599999)
ldi r24,hi8(1599999)
ldi r25,hlo8(1599999)
1: subi r18,1
sbci r24,0
sbci r25,0
brne 1b
rjmp .
nop
lds r30,__ATMEGA_328P_PORTB
lds r31,__ATMEGA_328P_PORTB+1
ld r24,Z
andi r24,lo8(~(1<<5))
st Z,r24
ldi r18,lo8(1599999)
ldi r24,hi8(1599999)
ldi r25,hlo8(1599999)
1: subi r18,1
sbci r24,0
sbci r25,0
brne 1b
rjmp .
nop
rjmp .L2
...
看起来您已将指针转换为 void* 并且将其视为 16 位指针而不是 8 位。
lds r30,__ATMEGA_328P_PORTB
lds r31,__ATMEGA_328P_PORTB+1
看看 __ATMEGA_328P_PORTB 的数据表中写入的内容,我认为它看起来像这样
__ATMEGA_328P_PINB:
.word 35
__ATMEGA_328P_DDRB:
.word 36
__ATMEGA_328P_PORTB:
.word 37
所以它实际上会将 0x2425 加载到 Z 寄存器中,而不是预期的 0x24