C 从4到2位创建一个字节(8位)

C 从4到2位创建一个字节(8位),c,algorithm,binary,spi,dma,C,Algorithm,Binary,Spi,Dma,我试图找出一种方法,尽可能多地利用我的微控制器(32kb)中有限的内存,并寻求一种算法的建议或指针,该算法执行我正在尝试的操作 一些背景:我直接从DMA向SPI(串行外围接口)发送曼彻斯特编码的比特。由于我可以将数据存储到DMA中的最小单元是一个字节(8位),因此我必须将我的1表示为0b11110000,将我的0表示为0b00001111。这基本上意味着对于每一位信息,我需要使用一个字节(8位)的内存。这是非常低效的 如果我可以减少这个值,使我的1表示为0b10,我的0表示为0b01,那么我只需

我试图找出一种方法,尽可能多地利用我的微控制器(32kb)中有限的内存,并寻求一种算法的建议或指针,该算法执行我正在尝试的操作

一些背景:我直接从DMA向SPI(串行外围接口)发送曼彻斯特编码的比特。由于我可以将数据存储到DMA中的最小单元是一个字节(8位),因此我必须将我的1表示为0b11110000,将我的0表示为0b00001111。这基本上意味着对于每一位信息,我需要使用一个字节(8位)的内存。这是非常低效的

如果我可以减少这个值,使我的1表示为0b10,我的0表示为0b01,那么我只需要对每1位内存使用1/4字节(2位),这对我的解决方案很好

现在,如果我可以以位的形式保存到DMA,这不会是一个问题,但我当然需要使用字节。所以我知道我的问题的解决方案是收集8位(或者在我的例子中是42位),然后作为一个字节存储到DMA

问题:

有解决这个问题的标准方法吗

如何从4个2位数字的集合中创建8位数字?但我不想把这些数字相加,而是想把它们收集在一起时的实际情况

例如:我有以下4个2位数字(请记住,0b10表示1,0b01表示0)(此外,这些数字存储的类型对解决方案是开放的,因为显然不存在2位类型)

编号1:0b01编号2:0b10编号3:0b10编号4:0b01

我想从中创建以下8位数字:

8位编号:0b01 10 10 01或不带空格0b01101001(0x69)


我正在用c进行编程似乎您可以打包四个数字
a
b
c
d
,它们的值都是零或一,如下所示:

64 * (a + 1) + 16 * (b + 1) + 4 * (c + 1) + (d + 1)

这是利用了一个事实,即
x+1
对两位整数进行编码:1变成0b10,0变成0b01。

这是曼彻斯特编码,所以0b11110000和0b0001111应该是唯一的候选。如果是,则将内存减少8倍

uint8_t PackedByte = 0;
for (i=0; i<8; i++) {
  PackedByte <<= 1;
  if (buf[i] == 0xF0) //  0b11110000
    PackedByte++;
}
uint8\u t PackedByte=0;
对于(i=0;i要从(a、b、c、d)获取abcd数字,您需要将数字移动到它们的位置,或者:-


(aI觉得位移位实现会更清晰:
(a+1)你是怎么这么快回答这个问题的?惊讶和感激,你可能刚刚帮我把我的内存使用量减少了4倍!谢谢Macattack,请随意添加这个作为答案,我使用哪一个我都会注意到滴答声。抱歉,Kerrek,我在滴答声上跳了枪…但你的速度仍然让我印象深刻!太好了,但你可以去一个tter!并行执行所有添加:
((((你好,朋友,我不知道这是怎么回事,因为我需要一个上升沿来表示0,一个下降沿来表示1。我如何用曼彻斯特编码的1位来表示这一点?@Remixed123对不起。我的答案是集中在接收而不是发送。我仍然认为你可以使用1个压缩位来指示SPI的下一个8位,如下所示。)0b11110000或OB000011111。更大的挑战是用曼彻斯特编码的数据读取SPI。发送时,您正在进行4x过采样。如果您也在接收类似的数据,这个答案可能会有所帮助。如果我可以使用1位来指示SPI的下一个8位,那就太好了。我不确定我的微控制器是否具有该级别的sPI可配置性。这个功能有名字吗?这样我就可以在我的微控制器的数据表中搜索它。关于接收端,这是一堆(截至2048年)单独的自寻址集成电路。它们各自获取数据包的一部分并将其余部分传递。不。我建议发送的是,在要发送的数据缓冲区中,您一次提取1位,然后向SPI发送一个8位字节0b11110000或0b00001111。如果您不能一次告诉SPI 8位,请设置一个8位的本地缓冲区d每次需要发送一个位时,从那里开始,根据需要根据数据缓冲区中的下一个位使用0b11110000或0b00001111补充该8位缓冲区。好的,实际上这是一种有趣的方法。我需要看看是否可以在不中断通信或计时的情况下发送数据。通过设置一个计时器,但是让它在一个恒定的流中不间断地发送可能很困难。
uint8_t PackedByte = 0;
for (i=0; i<8; i++) {
  int upper = BitCount(buf[i] >> 4);
  int lower = BitCount(buf[i] & 0xF);
  if (upper > lower)
    PackedByte++;
  else if (upper == lower)
    Hande_Indeterminate();
}