【问题标题】:C Bitwise Operation according to truth tableC根据真值表进行位运算
【发布时间】:2017-07-29 20:54:37
【问题描述】:

我的程序有8位寄存器,即PC0,PC1,PC2,PC3,PC4,PC5,PC6,PC7.

我不在乎PC0,PC1,PC2,PC3. 我想根据提到的真值表设置位:

             PC4    PC5   PC6 (Ports)
Row1 :        0      0     0         
Row2 :        0      0     1      
Row3 :        0      1     0      
Row4 :        0      1     1    
Row5 :        1      0     0     
Row6 :        1      0     1     

在设置位时不应更改 PC7 状态,并且应保持不变。我可以单独设置这些位,但需要立即设置它们。 这是我所做的:

void Set(unsigned char Row)
{
  if(Row == 1)
  {
   PC_ODR &= ~(0x40) //To Set 0 to PC6
   PC_ODR &= ~(0x20) //To Set 0 to PC5
   PC_ODR &= ~(0x10) //To Set 0 to PC4
  }

  if(Row == 2) 
  {
   PC_ODR |= 0x40   //To Set 1 the PC6
   PC_ODR &= ~(0x20) //To Set 0 to PC5
   PC_ODR &= ~(0x10) //To Set 0 to PC4
  }

 // ......So on for Row 3, 4,5,6
}

对于所有 6 行,代码会变得很长,有什么办法可以使用移位运算符和 AND / OR 运算符来简明扼要地完成工作。

【问题讨论】:

  • 设置:a |= (1 << bitpos),取消设置:a &= ~(1 << bitpos)
  • 我已经这样做了。
  • 使用按行索引的查找表。
  • 如果你应该只写入一次寄存器,那么你需要从它读取一次到一个临时变量中,设置和清除变量中的位,然后在最后写入一次寄存器。

标签: c bit


【解决方案1】:

仔细查看你的真值表并找到一些规则。

void Set(unsigned char Row){
    Row --;
    PC_ODR &= 0x8F;
    PC_ODR |= (0x01 & Row) << 6;
    PC_ODR |= (0x02 & Row) << 4;
    PC_ODR |= (0x04 & Row) << 2;
}

如果您向Row 提供值 7 和 8,这仍然有效,但如果您提供 9 或以上的数字,则可能会出错。


感谢 0andriy 对代码的小幅改进!

【讨论】:

  • 你可以直接使用来自Row的位:result |= (Row &amp; 0x2) &lt;&lt; 4;等等。
【解决方案2】:

所以你有:

             PC654 Decimal
Row1 :        000    0     
Row2 :        100    4
Row3 :        010    2  
Row4 :        110    6
Row5 :        001    1 
Row6 :        101    5

然后使用查找表:

void setRow(int row) {
  static int mask = 0x70; // binary mask for bits 456: 1110000
  static int rowData[7] = { 0/*dummy entry no row 0*/, 0, 4, 2, 6, 1, 5 };
  PC_ODR = (PC_ODR & ~mask) | rowData[row]<<4; // get original bits except 456 and combine with right value for 456
}

注意:不确定变量的类型,但您可以轻松适应。

【讨论】:

  • lut 足够小,可以使用八进制表示法编码为 24 位:05162400 &gt;&gt; row &amp; 7,可以预移位以与掩码 8f 对齐。
【解决方案3】:

从这里选择任何 8 位反转方法:http://graphics.stanford.edu/~seander/bithacks.html#BitReverseObvious 并将其包装到 reverse(),然后使用它:

假设基于 0 的行索引(第 1 行 = 0)做

PC_ODR |= (0xf | (reverse(row) >> 1))

else id 1-based row-indexing (row 1 = 1) 需要做

PC_ODR |= (0xf | (reverse(row - 1) >> 1))

【讨论】:

  • 但是你弄错了。请注意,位 0,1,2 映射到 6,5,4,而不是 4,5,6
  • @iBug:添加了必要的准备工作... ;-)
  • @iBug: 第一次反向row,然后使用我在结果中显示的内容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-03-23
  • 1970-01-01
  • 2015-03-25
  • 2020-10-12
  • 2023-01-30
  • 2013-09-06
  • 2013-06-26
相关资源
最近更新 更多