2017-07-29 20 views
2

我的计划有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运算得到的东西在短期完成。

+0

要设置:'a | =(1 << bitpos)',以取消设置:'a&=〜(1 << bitpos)' – iBug

+0

我已经完成了。 –

+0

使用按行索引的查找表。 –

回答

3

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

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

如果你提供值7和8 这仍然可以工作,但如果你提供了一些9或最多可能出错。


感谢0andriy与次改进的代码!

+0

您可以直接使用来自'Row'的位:'result | =(Row&0x2)<< 4;'等等。 – 0andriy

-1

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

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

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

基于1别的ID行索引(行1 = 1)需要做

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

但你说错了。请注意,位0,1,2映射到6,5,4,而不是4,5,6 – iBug

+0

@iBug:添加了必要的准备工作...... ;-) – alk

+0

@iBug:第1个反向'行',然后使用什么我展示了结果。 – alk

0

所以,你必须:

   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 
} 

注:不知道类型的变量,但你可以很容易适应。

+1

lut足够小,可以使用八进制表示法编码为24位:'05162400 >> row&7'可以预先移动以与掩模8f对齐。 –

+0

我完全同意但不想太棘手... –