c - 访问结构体和 union 体中的元素

标签 c header-files microcontroller

我正在为微 Controller 编写自己的库(头文件)。我想访问如下例所示的元素。我怎样才能实现这个目标?

myLibrary.h:

#include <stdint.h>

struct PWR_CR_tag {
    union {
        uint32_t R;
        struct {
            uint32_t VOS:1;
            uint32_t FPDS:1;
            uint32_t DBP:1;
            uint32_t PLS:3;
            uint32_t PVDE:1;
            uint32_t CSBF:1;
            uint32_t CWUF:1;
            uint32_t PDDS:1;
            uint32_t LPDS:1;
        } B;
    } PWR_CR;
};

#define PWR_CR (*(volatile struct PWR_CR_tag *) 0x40007004)

然后在 ma​​in.c 中(给出一个 ERROR):

#include <stdio.h>
#include <myLibrary.h>

int main() {
    PWR_CR test; // this gives ERROR expected ‘;’ before ‘test’

    test.R = // write to address 0x40007004
    test.B.VOS = // write to address 0x40007004 with offset 0xE (=0x40007012)

    return 0;
}

如何才能实现 PWR_CR test; 不会失败,并且我将能够访问 test.Rtest.B.VOS 等寄存器,...

所以,我正在尝试实现这样的目标:

// led struct
GPIO_InitTypeDef GPIO_LedInitStructure;

// configure led
GPIO_LedInitStructure.GPIO_Pin = ...; 
GPIO_LedInitStructure.GPIO_Mode = ...;
GPIO_LedInitStructure.GPIO_Speed = ...; // for example GPIO_Speed_2Mhz
GPIO_LedInitStructure.GPIO_OType = ...;
GPIO_LedInitStructure.GPIO_PuPd = ...;

最佳答案

首先,您声明了一个名为 PWR_CR 的 union 体和名为 PWR_CR 的宏这会发生冲突。不要这样做。
我们可以通过删除 struct PWR_CR_tag 并将其声明为 union PWR_CR_tag 来修复您的一些代码,从而从 PWR_CR_tag 结构中删除 PWR_CR 成员。
我们也可以将变量声明移至宏并使用 variable.R = smth;使用您当前的代码:

union PWR_CR_tag {
        uint32_t R;
        struct {
            uint32_t VOS:1;
            uint32_t FPDS:1;
            uint32_t DBP:1;
            uint32_t PLS:3;
            uint32_t PVDE:1;
            uint32_t CSBF:1;
            uint32_t CWUF:1;
            uint32_t PDDS:1;
            uint32_t LPDS:1;
        } B;
};

#define test (*(volatile union PWR_CR_tag *)0x40007004)

int main() {
    test.R = 0x00; // write to address 0x40007004
    test.B.VOS = 0x01 // write to address 0x40007004 with offset (at least) 0xE (=0x40007012)    (or offset WORD_SIZE-(at least) 0xE depending on machine endianess and padding bytes)
    return 0;
}

就像一个全局变量一样。不过,我肯定会删除该宏,并声明一个指向 volatile 对象的全局 const 指针变量,以获得更清晰的代码,并通知程序员他正在取消引用指针:

static volatile union PWR_CR_tag * const PWR_CR = (void*)0x40007004;

int main() {
    PWR_CR->R = 0; // write to address 0x40007004
    PWR_CR->B.VOS = 1; // write to address 0x40007004 with offset 0xE (=0x40007012)
    return 0;
}
PS。但你提到GPIO_InitTypeDef ,这是stm32 hal库中声明的类型。既然您似乎知道 STM32 和 hal header ,为什么不使用 PWR->CR就像 hal 所做的那样,例如 here ?你会犯更少的错误,你会轻松地将你的程序移动到另一条stm32线,从而编程速度更快?

#include "stm32l0xx.h"
int main() {
    PWR->CR = 0x00;
    MODIFY_REG(PWR->CR, PWR_CR_VOS, 0b10);
    // or better:
    LL_PWR_SetRegulVoltageScaling(0b10);
    return 0;
}

说到错误,我猜VOS是2位而不是1位(至少在stm32l1和l0上),如果是stm32,我认为你的结构需要从结构的开头开始填充位,希望你知道你的目标的字节顺序平台并考虑到这一点,编译器可能会在位域之间插入任意数量的填充字节,因此您只能希望它不会,声明具有 uint32_t 类型的位域不符合标准,除非 uint32_t 是“实现定义的类型”对于您的平台上的位字段”,我希望您使用 __attribute__((__packed__))在该结构上使用 gcc 编译器。

关于c - 访问结构体和 union 体中的元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51303823/

相关文章:

objective-c - 应将各种变量和方法类型放在 header 中的位置

c - 对函数 C 的 undefined reference

delay - 我们可以为 dspic33ep256mu814 Controller 的 mplab 中的 xc16 中的 _delay_ms 添加延迟函数的限制是多少?

linux - 如何通过串口烧写STM32

c - 车辆避障传感器

python - 如何嵌入 Evince?

c++ - 在 C/C++ 的 ODBC 程序中找不到 SQL.H 和 SQLEXT.H

c - 使用 char** 的项目(声明后初始化后)

c - 信号量实现

c - 使用C程序查找给定字符串中的反向单词