如何反转存储在内存地址的位?
How to invert the bits of stored at memory address?
我正在尝试通过光耦合器电平转换器发送 SPI 数据。 (基本上是把3.3v信号转成5v信号)
在此过程中,电平转换器翻转所有位(反相逻辑)而不是使用另一个反相器来重新对齐信号,我决定简单地将反相位从 SPI 端口发送出去会更容易。
为此,我将芯片上的模式 select 设置为高电平有效并更改了时钟极性。现在我试图对我发送的数据进行位翻转。
unsigned short* tx;
unsigned short* rx;
while(!feof(data_file)){
fread(buffer, 2, 80, data_file);
tx = buffer;
for(int i = 0; i < 80; i++){
(*tx)= ~(*tx); //added this line
spi.transfer((unsigned char*) tx,(unsigned char*) rx, 2);
(*rx)= ~(*rx); //also added this line
printf("0x%04x\n", *rx);
pinControl.selectChip(i%8);
usleep(5);
}
在添加这个之前有很好的干净输出
收到的数据:
0x04cb
0x04cb
0x04cb
0x04cb
0x04cb
0x04cb
0x04cb
0x050b
0x050b
0x050b
0x050b
反转后:
0xfd36
0x02c9
0xfd36
0x02c9
0xfd36
0x02c9
0xfd36
0x02c9
0xfd36
0x02c9
0xfd36
0x02c9
0xfd36
0x02c9
注意我发送的数据是单调递增的,所以第二个输出不正确。
我的假设是
(*tx) = ~(*tx)
实际上并没有反转位。
所以我试图验证这个理论。
unsigned short* tx;
unsigned short* rx;
(*tx)=4;
std::cout << *tx << endl;
std::cout << ~(*tx) << endl;
(*tx) = ~(*tx);
std::cout << (*tx);
产量:
4
-5 <-- this is ~4 correct
65531 <-- this is unexpected
您的两个代码示例中的问题都是指针使用不正确。
您正确声明了指针,但没有为它们分配有效的内存地址。
例如,当您这样做时:
unsigned short* tx;
(*tx)=4;
tx
包含一些随机地址,因为您没有分配它。
因此,当您 de-reference 它并尝试将 4 放在下一行时,无法判断这个 4 的实际位置。
tx
中可能存在值 0 或接近它的值,您的程序将崩溃 (SEGFAULT)。
或者,其他一些代码可能正在使用此内存,并将覆盖该值,这可以解释为什么您突然得到 65531,尽管它与之前的值无关。
在调用SPI的代码示例中,存在两个问题:
你永远不会在循环中推进 tx
指针,所以你总是反转并发送相同的两个字节。
您没有为 rx
指针分配任何有效内存,因此与您的测试一样,数据会随机放置,您的程序可能会随机崩溃。
最后,最重要的问题是:您是如何声明 buffer
的?
如果它以与 rx
和 tx
相同的方式声明,那么即使从文件中读取也可能无法正常工作。
这是您的代码的一个版本:
unsigned short tx;
unsigned short rx;
while(fread(&tx, 2, 1, data_file) > 0) {
tx = ~tx;
spi.transfer(&tx, &rx, 2);
rx = ~rx; //also added this line
printf("0x%04x\n", rx);
pinControl.selectChip(i % 8);
usleep(5);
}
rx
是未初始化的指针。它恰好指向一些恰好有效的可访问内存位置。您需要将其指向一个缓冲区,就像您对 tx
.
所做的那样
您的程序(假设)从一个文件中读取 80 个字的数据,因此其目的可能是通过 spi.transfer
传输这些数据。但是,您的循环虽然计算了 80 个单词,但并未增加 tx
和 rx
指针。
因此,您正在做的是反复反转 buffer[0]
的位,其中 tx
始终指向。同样,rx
一直指向相同的未知内存位置,该位置已切换。
您看到的重复值对:
0xfd36
0x02c9
实际上是彼此按位取反。如果你知道十六进制数字和二进制半字节之间的对应关系,这是显而易见的。
您还必须测试 fread
的 return 值。 fread
return它能够读取多少元素,可能低至零。
while (!feof(...))
模式不正确。 feof(f)
对于尚未尝试输入操作的新打开的流始终为 false。
stdio
范例是 I/O 操作的 return 值必须单独测试。如果输入操作失败,可能是由于数据结束,或由于某些 I/O 错误。在流 f
上输入失败后,两个标志 feof(f)
或 ferror(f)
之一为真以区分 end-of-data 和 I/O 错误。
我正在尝试通过光耦合器电平转换器发送 SPI 数据。 (基本上是把3.3v信号转成5v信号)
在此过程中,电平转换器翻转所有位(反相逻辑)而不是使用另一个反相器来重新对齐信号,我决定简单地将反相位从 SPI 端口发送出去会更容易。
为此,我将芯片上的模式 select 设置为高电平有效并更改了时钟极性。现在我试图对我发送的数据进行位翻转。
unsigned short* tx;
unsigned short* rx;
while(!feof(data_file)){
fread(buffer, 2, 80, data_file);
tx = buffer;
for(int i = 0; i < 80; i++){
(*tx)= ~(*tx); //added this line
spi.transfer((unsigned char*) tx,(unsigned char*) rx, 2);
(*rx)= ~(*rx); //also added this line
printf("0x%04x\n", *rx);
pinControl.selectChip(i%8);
usleep(5);
}
在添加这个之前有很好的干净输出 收到的数据:
0x04cb
0x04cb
0x04cb
0x04cb
0x04cb
0x04cb
0x04cb
0x050b
0x050b
0x050b
0x050b
反转后:
0xfd36
0x02c9
0xfd36
0x02c9
0xfd36
0x02c9
0xfd36
0x02c9
0xfd36
0x02c9
0xfd36
0x02c9
0xfd36
0x02c9
注意我发送的数据是单调递增的,所以第二个输出不正确。
我的假设是
(*tx) = ~(*tx)
实际上并没有反转位。
所以我试图验证这个理论。
unsigned short* tx;
unsigned short* rx;
(*tx)=4;
std::cout << *tx << endl;
std::cout << ~(*tx) << endl;
(*tx) = ~(*tx);
std::cout << (*tx);
产量:
4
-5 <-- this is ~4 correct
65531 <-- this is unexpected
您的两个代码示例中的问题都是指针使用不正确。 您正确声明了指针,但没有为它们分配有效的内存地址。
例如,当您这样做时:
unsigned short* tx;
(*tx)=4;
tx
包含一些随机地址,因为您没有分配它。
因此,当您 de-reference 它并尝试将 4 放在下一行时,无法判断这个 4 的实际位置。
tx
中可能存在值 0 或接近它的值,您的程序将崩溃 (SEGFAULT)。
或者,其他一些代码可能正在使用此内存,并将覆盖该值,这可以解释为什么您突然得到 65531,尽管它与之前的值无关。
在调用SPI的代码示例中,存在两个问题:
你永远不会在循环中推进
tx
指针,所以你总是反转并发送相同的两个字节。您没有为
rx
指针分配任何有效内存,因此与您的测试一样,数据会随机放置,您的程序可能会随机崩溃。
最后,最重要的问题是:您是如何声明 buffer
的?
如果它以与 rx
和 tx
相同的方式声明,那么即使从文件中读取也可能无法正常工作。
这是您的代码的一个版本:
unsigned short tx;
unsigned short rx;
while(fread(&tx, 2, 1, data_file) > 0) {
tx = ~tx;
spi.transfer(&tx, &rx, 2);
rx = ~rx; //also added this line
printf("0x%04x\n", rx);
pinControl.selectChip(i % 8);
usleep(5);
}
rx
是未初始化的指针。它恰好指向一些恰好有效的可访问内存位置。您需要将其指向一个缓冲区,就像您对 tx
.
您的程序(假设)从一个文件中读取 80 个字的数据,因此其目的可能是通过 spi.transfer
传输这些数据。但是,您的循环虽然计算了 80 个单词,但并未增加 tx
和 rx
指针。
因此,您正在做的是反复反转 buffer[0]
的位,其中 tx
始终指向。同样,rx
一直指向相同的未知内存位置,该位置已切换。
您看到的重复值对:
0xfd36
0x02c9
实际上是彼此按位取反。如果你知道十六进制数字和二进制半字节之间的对应关系,这是显而易见的。
您还必须测试 fread
的 return 值。 fread
return它能够读取多少元素,可能低至零。
while (!feof(...))
模式不正确。 feof(f)
对于尚未尝试输入操作的新打开的流始终为 false。
stdio
范例是 I/O 操作的 return 值必须单独测试。如果输入操作失败,可能是由于数据结束,或由于某些 I/O 错误。在流 f
上输入失败后,两个标志 feof(f)
或 ferror(f)
之一为真以区分 end-of-data 和 I/O 错误。