STM32-指针和和

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

我正在学习如何使用寄存器对STM32 Nucleo F446RE板进行编程。

要知道寄存器的位置,我从数据表中获取边界地址和偏移量。但是,我无法计算它们的总和。我展示了一个例子:

volatile uint32_t *GPIOA = 0x0; // Initialization of the boundary adress
GPIOA = (uint32_t*)0x40020000; // Boundary adress from datasheet

volatile uint32_t *GPIOA_ODR = 0x0; // Initialization of GPIOA_ODR register
GPIOA_ODR = GPIOA +  (uint32_t*)0x14; // Calculation of GPIOA_ODR as the sum of the boundary adress and the offset (i.e. 0x14.

第5行给我一个错误,您知道如何正确计算吗?

非常感谢。

c pointers stm32 offset cpu-registers
3个回答
0
投票

我尝试过,但一无所获。如果我插入GPIOA_ODR = (uint32_t*)(0x40020000 + 0x14);,则可以使用,但是如果我插入GPIOA_ODR = (uint32_t*)(GPIOA + 0x14);,则无法使用。其他想法?

非常感谢您的回答。我正在使用的完整代码如下:

int main(int argc, char* argv[])
{
    /** RCC **/
    /* RCC */
    volatile uint32_t *RCC = 0x0;
    RCC = (uint32_t*)0x40023800;
    /* RCC_AHB1ENR */
    volatile uint32_t *RCC_AHB1ENR = 0x0;
    RCC_AHB1ENR = (uint32_t*)(0x40023800 + 0x30);
    *RCC_AHB1ENR |= 0x1;

    /** GPIOA **/
    /* GPIOA */
    volatile uint32_t *GPIOA = 0x0;
    GPIOA = (uint32_t*)0x40020000;
    /* GPIOA_MODER */
    volatile uint32_t *GPIOA_MODER = 0x0;
    GPIOA_MODER = (uint32_t*)(0x40020000 + 0x00);
    *GPIOA_MODER |= 1 << 16;
    *GPIOA_MODER &= ~(0 << 17);
    /* GPIOA_ODR */
    volatile uint32_t *GPIOA_ODR = 0x0;
    GPIOA_ODR = (uint32_t*)(GPIOA + 0x14);
    *GPIOA_ODR |= 1 << 8;
}

由于行GPIOA_ODR = (uint32_t*)(GPIOA + 0x14);,此代码无法正常工作。如果插入GPIOA_ODR = (uint32_t*)(0x40020000 + 0x14),它将正常工作。


0
投票

这是错误的。如果您想使用这种极为不便的方式:

#define GPIOA 0x4002000
#define ODR_OFFSET 0x14

#define GPIO_ODR (*(volatile uint32_t *)(GPIOA + ODR_OFFSET))

为什么#define不是指针?它对编译器更友好,并且节省了一次读取的内存。

https://godbolt.org/z/LdLLVN

#define GPIOA 0x4002000
#define ODR_OFFSET 0x14

#define GPIO_ODR (*(volatile uint32_t *)(GPIOA + ODR_OFFSET))

volatile uint32_t *pGPIO_ODR = (volatile uint32_t *)(GPIOA + ODR_OFFSET);

void foo(uint32_t x)
{
    GPIO_ODR = x;
}

void bar(uint32_t x)
{
    *pGPIO_ODR = x;
}

和结果代码

foo:
        ldr     r3, .L3
        str     r0, [r3, #20]
        bx      lr
.L3:
        .word   67117056
bar:
        ldr     r3, .L6
        ldr     r3, [r3]
        str     r0, [r3]
        bx      lr
.L6:
        .word   .LANCHOR0
pGPIO_ODR:
        .word   67117076

-1
投票

强制转换应在常量值之外,换句话说,您要添加GPIOA地址+ 14以生成新地址。所以演员必须在他们外面:

GPIOA_ODR = (uint32_t*)(GPIOA +  0x14);
© www.soinside.com 2019 - 2024. All rights reserved.