将 MSP430 的所有端口用作一个大端口 - 可能吗?
Using all ports of MSP430 as one big port - is it possible?
如果我把MSP430的所有端口作为一个端口使用会更方便。
我在想也许要溢出寄存器直到下一个内存地址,但它不起作用(或者我做的不对)。
要访问 PORT2 的 BIT0,我尝试了类似的方法:
P1OUT |= 0x80000000000;
因为在内存中P2OUT(0x0029)是P1OUT(0x0021)之后的8个地址,
那些是中间的 8 位寄存器。所以 8x8=64.
我知道我可以使用这样的偏移量访问 P2OUT:
*(char *)(0x0021 + 0x0008) |= BIT0;
我想给自己定义一个从 1 到 13 的 GPIO 列表,然后打开和关闭它们而不检查 GPIO11 是打开 PORT2 还是打开 PORT1 ,我想要一条命令搞定一切。
有可能吗?
P1OUT |= 0x80000000000;
这不起作用,因为
你没有正确计算位数:
P1OUT |= 0x10000000000000000;
P1OUT
是一个 8 位寄存器,因此编译器会丢弃除最低八位以外的所有寄存器。您必须使用足够大的数据类型(并且您要设置的位是内存中的第 65 位,因此您需要大于 64 位的类型):
*(uint128_t*)&P1OUT |= 0x10000000000000000;
- 没有 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_11
和 clear_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);
这不会增加程序代码的开销。
如果我把MSP430的所有端口作为一个端口使用会更方便。 我在想也许要溢出寄存器直到下一个内存地址,但它不起作用(或者我做的不对)。
要访问 PORT2 的 BIT0,我尝试了类似的方法:
P1OUT |= 0x80000000000;
因为在内存中P2OUT(0x0029)是P1OUT(0x0021)之后的8个地址, 那些是中间的 8 位寄存器。所以 8x8=64.
我知道我可以使用这样的偏移量访问 P2OUT:
*(char *)(0x0021 + 0x0008) |= BIT0;
我想给自己定义一个从 1 到 13 的 GPIO 列表,然后打开和关闭它们而不检查 GPIO11 是打开 PORT2 还是打开 PORT1 ,我想要一条命令搞定一切。
有可能吗?
P1OUT |= 0x80000000000;
这不起作用,因为
你没有正确计算位数:
P1OUT |= 0x10000000000000000;
P1OUT
是一个 8 位寄存器,因此编译器会丢弃除最低八位以外的所有寄存器。您必须使用足够大的数据类型(并且您要设置的位是内存中的第 65 位,因此您需要大于 64 位的类型):*(uint128_t*)&P1OUT |= 0x10000000000000000;
- 没有 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_11
和 clear_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);
这不会增加程序代码的开销。