从一个寄存器读取某些位并写入另一个寄存器的某些位

Posted

技术标签:

【中文标题】从一个寄存器读取某些位并写入另一个寄存器的某些位【英文标题】:Read certain bits from one register and write into certain bits of another 【发布时间】:2020-12-14 05:35:27 【问题描述】:

我正在寻找实现 read_and_write 的原型,但无法正确完成。任何帮助表示赞赏。我能够提取位。

在下面的 write_val1 代码中,我的意图是仅将 final_val 的前 9 位写入 read_data。 read_data 的其余 7 位应保持不变。 write_val1 = 0x0080 的预期输出

与 write_val2 类似,我的意图是仅将 final_val 中的下 8 位写入 read_data。 read_data 的其余 8 位应保持不变。 write_val2 = 0x2700 的预期输出

与 write_val3 类似,我的意图是仅将 final_val 中的下 3 位 (010) 写入 read_data 的位置 [11:13],而其余的 read_data 保持不变。

预期输出 = 0x5448 ;例如:pick 010 提取的位 from write_val3; 0x3048 = 0111 0000 0100 1000; 0x5048 = 0101 0000 0100 1000

#include <stdio.h>
#include <stdint.h>

 // Extracts n bits from a given position in LSB. 
int bitExtracted(uint16_t read_data, uint8_t n_bits, uint8_t pos) 
 
    return (((1 << n_bits) - 1) & (read_data >> (pos - 1))); 
 

void read_and_write(uint32_t* final_val, uint16_t* write_val, uint8_t start_pos, uint8_t end_pos)

    uint32_t temp = *final_val;
    *write_val = (uint16_t) ((temp >> start_pos) & ((1 << end_pos) - 1)); // store the desired number of bits in write_val
    *final_val = (temp >> end_pos); //shift final_val by end_pos since those bits are already written
    printf("\n temp %x, write_val %x, final_val %x ", temp, *write_val, *final_val);
    


void main() 

    uint16_t read_data = 0x0; //assume some read value
    uint16_t ext_val1 = bitExtracted(read_data, 9, 1);  //Read BITS [8:0] from read_data
    uint8_t ext_val2 = bitExtracted(read_data, 8, 1);   //Read BITS [7:0] from read_data
    uint8_t ext_val3 = bitExtracted(read_data, 3, 5);   //Read BITS [7:4] from read_data
    uint32_t final_val = 0x0; //Stores 20 extracted bits from val1, val2 and val3 into final_val (LSB to MSB in order)
    uint16_t write_val1, write_val2, write_val3;
    uint8_t start_pos = 0, end_pos =8;
    ext_val1 = 0x80, ext_val2 = 0x0, ext_val3 = 0x2;
    final_val = (ext_val1 | (ext_val2 << 9) | (ext_val3 << 17));
    printf ("\n final_val %x", final_val);
    
    //Read first 9 bits of final_val and write only into [8:0] position of existing read_data
    read_and_write(&final_val, &write_val1, 0, 9); 
    read_data = 0x80;
    write_val1 = write_val1 | read_data;
    
    //Read next 8 bits of final_val and write only into [7:0] position of existing read_data
    start_pos = 0;
    end_pos = 7;
    read_data = 0x27b7;
    read_and_write(&final_val, &write_val2, start_pos, end_pos);
    write_val2 = write_val2 | read_data;

    //Read next 3 bits of final_val and write only into[13:11] position of existing read_data
    start_pos = 11;
    end_pos = 13;
    read_data = 0x3048;
    read_and_write(&final_val, &write_val3, start_pos, end_pos);
    write_val3 = write_val3 | read_data;
    printf ("\n val1 0x%x val2 0x%x val3 0x%x final_val 0x%x", write_val1, write_val2, ext_val3, final_val);

【问题讨论】:

函数bitExtracted中,函数参数n_bitspos是什么意思? pos 是要提取的第一位的位置,n_bits 是要提取的总位数吗? pos 是从零开始的索引还是从一开始的索引?也就是说least significant bit的位置是0还是1?评论 Read BITS [8:0] 到底是什么意思?这是否意味着您要提取第 0 位(最低有效位)直到第 8 位(包括第 8 位)? 我假设它是基于 1 的索引。读取 BITS [8:0] 意味着我想提取第 0 位到第 8 位,包括第 8 位。 顺便说一句:(1 &lt;&lt; n_bits) - 1 不能在 sizeof(int) == 2 所在的平台上与 n_bits == 16 一起使用,即在 16 位平台上。此尺寸是 ISO C 标准所允许的。但是,在大多数现代平台上,sizeof(int) &gt;= 4,所以这应该不是问题。请参阅integer promotions 了解更多信息。 @ManaswiSingh final_val 已经存储了值。我只需要写入 write_val1、write_val2、write_val3;将从 final_val 中提取。 @ManaswiSingh。我假设 final_val 已经具有按顺序写入的值。我还没有为此添加代码。 【参考方案1】:

如果您希望 read_and_write() 函数能够更改函数的前两个输入的值(例如 final_valwrite_val1),那么它们应该作为指向函数的指针传递。因此,您的函数原型应如下所示:

void read_and_write(uint32_t* final_val, uint16* write_val1, uint8_t start_pos, uint8_t end_pos);

在你的主代码中调用函数时,你需要使用&amp;来获取变量的地址。所以你打电话给他们:

read_and_write(&amp;final_val, &amp;write_val1, start_pos, end_pos);

对于读写部分,它与您在bitExtracted 函数中所做的非常相似。

uint32_t temp = *final_val;
*write_val = (uint16_t) ((temp >> start_pos) & ((1 << end_pos) - 1)); // store the desired number of bits in write_val

*final_val = (temp >> end_pos); //shift final_val by end_pos since those bits are already written 

* 是为了尊重指针并访问存储在特定位置的数据。请注意,您还需要对 write_val 进行 (uint16_t) 强制转换,因为类型需要匹配。

【讨论】:

以上是关于从一个寄存器读取某些位并写入另一个寄存器的某些位的主要内容,如果未能解决你的问题,请参考以下文章

CPU处于保护模式时如何读/写硬盘?

从vim的寄存器中删除换行符?

从 zip 文件中读取文件并将其写入另一个文件时面临的问题

Recyclerview - OnCreateViewholder - 在某些情况下如何返回“null”

C# modbus 一次性读取多个寄存器数据 数据会混乱

LabVIEW实现Modbus通信