【问题标题】:How to define a pointer to a port address如何定义指向端口地址的指针
【发布时间】:2013-09-24 02:56:10
【问题描述】:

我在使用 atmega328p 的结构和定义时遇到了一点问题。

我有以下代码:

typedef struct {
    char port;
    unsigned char pin;
    unsigned long timestamp;
} BUTTONS;

BUTTONS button_1;
BUTTONS button_2;
BUTTONS button_3;

BUTTONS* button[BUTTONS_ID_COUNT] = {&button_1,&button_2,&button_3};

void Button_init(void){

    button[BUTTONS_ID_1]->port = PINB;
    button[BUTTONS_ID_1]->pin = PINB4;
    button[BUTTONS_ID_1]->timestamp = 0;
}

unsigned char Button_instantRead(int id){
    //return PINB & (1 << PINB4);
    return button[id]->port & (1 << button[id]->pin);
}

我想使用我的Button_instantRead() 来读取任何端口,只需给它一个 ID 号。我使用我的 init 函数来设置哪个引脚与哪个端口相关联。但是由于某种原因,当我调用 Button_instantRead() 函数时,即使按下开关,我也没有得到 1。

我使用注释行在我的主文件中尝试了我的配置,一切正常。

我在return 行中做错了什么?

经过一番谷歌搜索后,我发现char 可能不是引用端口的正确类型。我想我会更适合指向端口地址的第一个元素的指针,但我不知道该怎么做,也找不到答案。

【问题讨论】:

  • 猜测:确保要读取 pin,您传递的是 ID=0,而不是 ID=1。仔细检查强制性嵌入头文件中 PINB4 和 PINB 的大小和类型,确保它们匹配。
  • 糟糕,我应该说假设 BUTTONS_ID_1=0 这可能是。
  • 怀疑PINB4不在0到31的范围内。如果是这样,1 &lt;&lt; PINB4不是你想要的。
  • 初始化时只读取端口的值。

标签: c microcontroller avr-gcc


【解决方案1】:

我建议先查找PINB 的定义。我发现 this link 到一个似乎引用了正确头文件的 power point 演示文稿。

值得注意的文件是:

  1. sfr_defs.h
  2. iom328p.h

定义自己的指向 PINB 的指针所需的所有信息都驻留在此处。

以下内容应如您所愿:

typedef struct {
    volatile uint8_t * port;
    uint8_t pin;
    unsigned long timestamp;
} BUTTONS;

BUTTONS button_1;
BUTTONS button_2;
BUTTONS button_3;

BUTTONS* button[BUTTONS_ID_COUNT] = {&button_1,&button_2,&button_3};

void Button_init(void){
    button[BUTTONS_ID_1]->port = &PINB;
    button[BUTTONS_ID_1]->pin = PINB4;
    button[BUTTONS_ID_1]->timestamp = 0;
}

unsigned char Button_instantRead(int id){
    //return PINB & (1 << PINB4);
    return *(button[id]->port) & (1 << button[id]->pin);
}

注意端口是一个指针。

编辑:

我不得不检查自己是否使用了 volatile 结构成员,发现 this SO questionthis other SO question 非常有趣。

编辑 2:

如果您使用的是 gcc(我认为您不是,因为它是 AVR,但我可能是错的)您可以跳过找出 PINB 的确切类型的步骤并且声明你的结构如下:

typedef struct {
    typeof(PINB)* port;
    uint8_t pin;
    unsigned long timestamp;
};

typeof operator 是 C 语言的 gcc 扩展,因此您可能无法使用它,但最好了解它。

【讨论】:

  • 我正在使用 avr-gcc,所以 typeof 运算符应该可以正常工作。
【解决方案2】:

PINB 不稳定吗?这不是端口的实际读取吗?如果是这样,您读取的是Button_init 中的端口值,而不是Button_instantRead 中的值。

也就是说button[id]-&gt;port包含了你在Button_init中读到的端口的值,而不是一些以后可以用到的PINB的引用。

注意:我已经好几年没有做 atmega 的东西了。

你可以这样重新编码:

unsigned char Button_instantRead(int id){
    switch(id) {
        case ID_A: return PINA & (1 << button[id]->pin);
        case ID_B: return PINB & (1 << button[id]->pin);
        // etc
    }
}

【讨论】:

  • 这显然是一个很好的解决方法,但我仍然想知道我需要做什么才能将 PINB 分配给我的 button.port 并能够根据我的输入端口的状态
  • 找到 PINB 的#define。它在一个头文件中。当您在分配的右侧有 PINB 时,它会读取端口。因此,您不能将其分配给“稍后阅读”或某些相关概念。读取端口时需要引用 PINB。
  • @CharlieBurns 但您始终可以使用指向PINB 的指针来读取PINB 本身并避免额外的switch 语句。
  • @nonsensical 取决于如何定义 PINB。但是,是的,我明白你的意思。间接。哦,我现在看到你的答案了。不错。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-01-24
  • 1970-01-01
  • 2018-12-23
  • 1970-01-01
  • 1970-01-01
  • 2020-12-30
  • 1970-01-01
相关资源
最近更新 更多