将 MSP430 的所有端口用作一个大端口 - 可能吗?

Using all ports of MSP430 as one big port - is it possible?

如果我把MSP430的所有端口作为一个端口使用会更方便。 我在想也许要溢出寄存器直到下一个内存地址,但它不起作用(或者我做的不对)。

要访问 PORT2BIT0,我尝试了类似的方法:

P1OUT |= 0x80000000000;

因为在内存中P2OUT(0x0029)是P1OUT(0x0021)之后的8个地址, 那些是中间的 8 位寄存器。所以 8x8=64.

我知道我可以使用这样的偏移量访问 P2OUT

*(char *)(0x0021 + 0x0008)  |=  BIT0;

我想给自己定义一个从 1 到 13 的 GPIO 列表,然后打开和关闭它们而不检查 GPIO11 是打开 PORT2 还是打开 PORT1 ,我想要一条命令搞定一切。

有可能吗?

P1OUT |= 0x80000000000;

这不起作用,因为

  1. 你没有正确计算位数:

    P1OUT |= 0x10000000000000000;
    
  2. P1OUT 是一个 8 位寄存器,因此编译器会丢弃除最低八位以外的所有寄存器。您必须使用足够大的数据类型(并且您要设置的位是内存中的第 65 位,因此您需要大于 64 位的类型):

    *(uint128_t*)&P1OUT |= 0x10000000000000000;
    
  3. 没有 128 位类型。

你可以通过另一层间接获得你想要的:

volatile uint8_t * const ports[] = { &P1OUT, &P2OUT, &P3OUT };

static inline void setGPIO(unsigned int number)
{
    *ports[number / 8] |= 1 << (number % 8);
}

不,多余的数据不会从一个内存地址溢出到下一个内存地址。如果将数据写入 8 位地址,多余的(最高有效位)位将被截断。

有几种方法可以解决这个问题。您可以为每个端口位设置一组函数,例如

write_GPIO_11(int bitval) {             // pass 0 or 1
    if (bitval)
        P2OUT |= 0x08;
    else
        P2OUT &= 0xF7;
}

或者有单独的函数 set_GPIO_11clear_GPIO_11,这对于 inline 函数来说会更有效率和更好。

你也可以使用宏

#define GP11_ON (P2OUT |= 0x08)

...

GP11_ON;

但是既然你谈到从一个端口溢出到下一个端口,我想知道你是否也想用一条指令写入所有 13 位(这必须是 16 位值)。这不能通过一次写入完成,但您可以进行一次函数调用,这又可以是 inline.

write_GPIO_bits(unsigned int bitvals) {
    P1OUT = bitvals;
    P2OUT = bitvals >> 8;
}

以此类推

我使用以下方法:

"hardware_config.h":

#define CONCAT_(a, b) a##b

#define BITSET(p, m) (CONCAT(p, OUT) |= m)

#define LEDGN_PORT P1
#define LEDGN_MASK 0x01

辅助函数最好放在不同的头文件中。

用法:

BITSET(LEDGN_PORT, LEDGN_MASK);

这不会增加程序代码的开销。