结构和联合中的访问元素

时间:2018-07-12 10:54:46

标签: c header-files microcontroller

我正在为微控制器编写自己的库(头文件)。我想访问以下示例中的元素。我该如何实现?

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)

然后在 main.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 = ...;

3 个答案:

答案 0 :(得分:2)

首先,您声明了一个名为PWR_CR的联合和一个名为PWR_CR的宏,这将发生冲突。别那样
我们可以通过删除结构PWR_CR_tag并将其声明为并集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;
}

充当全局变量。但是,我肯定会删除宏,并为易失性对象声明一个全局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标头一样,为什么不像hal一样使用PWR->CR,例如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是“实现定义的类型”平台上的位域”,我希望您在该结构的gcc编译器上使用__attribute__((__packed__))

答案 1 :(得分:0)

这取决于您的控制器体系结构。 在16位计算机上的地址:

#include <stdint.h>

struct PWR_CR_tag {
    union {
        uint32_t R;                 //Addr. 0x40007004
        struct {
            uint32_t VOS;           //Addr. 0x40007014
            uint32_t FPDS;          //Addr. 0x40007012
            uint32_t DBP;           //Addr. 0x40007010
            uint32_t PLS;           //Addr. 0x4000700E
            uint32_t PVDE;          //Addr. 0x4000700C
            uint32_t CSBF;          //Addr. 0x4000700A
            uint32_t CWUF;          //Addr. 0x40007008
            uint32_t PDDS;          //Addr. 0x40007006
            uint32_t LPDS;          //Addr. 0x40007004
        } B;
    } PWR_CR;
};

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

答案 2 :(得分:0)

不确定define试图实现什么(注意,它的名称与您试图在main中声明的变量类型相同(难怪它不会编译)为它扩展为:

//PWR_CR test;
//expanded to:
(*(volatile struct PWR_CR_tag *) 0x40007004) test;

但是,如果您更改define的名称,则可以将其用作:

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

//no need to declare a variable 

PWR_test.PWR_CR.R = 2;
PWR_test.PWR_CR.B.VOS = 1;

我希望那是你想要的。