裸机 Arduino C 代码不会让 LED 闪烁

问题描述 投票:0回答:1

我正在尝试以裸机、非 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
...
c arduino embedded avr bare-metal
1个回答
0
投票

看起来您已将指针转换为 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

© www.soinside.com 2019 - 2024. All rights reserved.