v_ADCregs->rADCCON=((1<<14)//AD预分频使能 |(prescaler<<6)//分频因子设为49 |(1<<3)//通道为AIN1 |(0<<2)//Normal操作模式 |(0<<1)//AD转换不能从读操作开始 );
上面这段程序就是典型的移位赋值寄存器的操作。
下面的图是其对应的寄存器datasheet:
由上可见[13:6]这8个bit用来设置分频因子的,程序中用了49<<6这一句来进行设置,而49转为二进制是110001,只有6bit,而更为关键的是[13:6]这8bit的初始状态是0xFF,可参见上图,那么,采用49<<6对这8个bit赋值后应该会变成11110001,这就成了241了,不是49了!
所以我想,是不是这种移位赋值的方法只适用于初始状态为0的bit或bit组,如果初始状态不为零,恐怕不能直接用这种方法赋值,而需要将其先赋零后再采用这种方法赋值。
还有另外一种赋值寄存器的方法,就是直接赋值,比如一个16bit的寄存器,可以直接=0xf13c(随便写的,没有具体意义),但我觉得这种方法不适用于上面图中的ADCCON寄存器,为什么这么说?因为它的[15]位是表示AD转换状态的,是只读的(Read-only),我们不能赋,最后一位[0]是手动控制AD开始用的,我们不想目前不想赋,而用直接赋值的话不管写什么值总会影响到这两位。
不能用直接赋值,可以用另外一种移位赋值,就是“与非赋值法”,分析一下上面的程序,其实我们想要的结果无非是下面这样:
bit | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
值 | X | 1 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | X |
X表示暂时忽略不管,先将需要取零的位赋值:
ADCCON &= ~((3<<12)|(7<<7)|(3<<4)|(3<<1));
再对其中需要取1的位赋值:
ADCCON |= ((1<<14)|(3<<10)|(1<<6)|(1<<3));
这样既得到了预期的效果,又没有影响到其他的位。
新手的胡思乱想,不当之处,还望高人指点。