这是一个程序,它读取端口A的引脚2到5,并将这些引脚的状态复制到端口B的输出引脚3到6,而不使用AVR库。该程序有效,但我需要一些帮助,了解它是如何工作的。我以他理解的方式评论它。提前谢谢!
PS:有用的信息:
0x21
- 端口A数据方向寄存器
0x24
- 端口B数据方向寄存器
0x20
- 端口A输入引脚地址
0x25
- 端口B数据寄存器
DDRx
,数据方向寄存器,用于确定端口的引脚是配置为输入还是输出;
PORTx
是用于设置输出引脚值的寄存器;
PINx
是读取输入引脚值的寄存器。
int main (void){
unsigned char *ptr,data;
ptr =(unsigned char*)0x21; //Points ptr to 0x21, which is the DDRA
*ptr &=~((1<<2)|(1<<3)|(1<<4)|(1<<5)); //*1
ptr =(unsigned char*)0x24; //Points ptr to 0x24, which is the DDRB
*ptr |=(1<<3)|(1<<4)|(1<<5)|(1<<6); //*2
for(;;){
ptr=(unsigned char*)0x20; //Points ptr to 0x20, which is the PINA
data=*ptr; //Saves the data from 0x20 to 'data'
data &= ~((1<<0)|(1<<1)|(1<<6)|(1<<7)); //*3
data <<=1; //*4
ptr=(unsigned char*)0x25; //Points ptr to 0x25, which is the PORTB
*ptr=(*ptr &~((1<<3)|(1<<4)|(1<<5)|(1<<6)))|data; //*5
}
return(0);
}
* 1:程序是否使用0x21
和字节00111100
的位进行AND运算?这样答案就像00????00
。我也不理解'~'
。
* 2:程序是否使用0x24和字节01111000
的位进行OR运算?这样答案就像?1111???
。为什么他不使用AND代替OR?
* 3:程序是否使用&#39;数据&#39;中的位进行AND操作?和字节11000011
?这样答案就像是0000 ??这样做的重点是什么?
* 4:为什么他将'data'
向左移一次?这样的答案就像是?0000 ?? 0。
* 5:程序是否使用0x25
和字节01111000
(结果为0 ???? 000)的位进行AND运算,然后对其结果进行OR运算和来自数据的位?这样答案就像00000000
!?!?!?
答案 0 :(得分:1)
1:程序正在构建位字段0b00111100,然后用〜运算符将其改为0b11000011,然后将该值与ptr指向的地址的内容进行AND运算,然后将结果存储到指向的地址中。 PTR。它清除数据方向寄存器的第2位到第5位,而其他位保持不变。据推测,位值为0表示引脚是输入。
2:程序正在构建位字段0b01111000,然后将该值与ptr指向的地址的内容进行或运算,然后将结果存储到ptr指向的地址中。它设置数据方向寄存器的第3位到第6位,而其他位保持不变。据推测,位值为1表示引脚是输出。
3:程序将从数据地址读取的值与0xb00111100进行AND运算,以清除0,1,6和7位。程序仅涉及位2到5,忽略其他位。
4:程序正在将第2位到第5位的值向左移位1位,以便将其移入第3位到第6位。
5:程序正在读取数据寄存器的内容,清除从数据寄存器读取的第3位到第6位,然后在将数据写回数据寄存器之前对第3位到第6位的新值进行“或”操作。 。换句话说,它更新位3到6的值而不改变位0,1,2和7的值。
这些操作很常见:
data &= ~(bitfield)
清除bitfield指定的位而不更改其他位。
data |= bitfield
设置bitfield指定的位而不更改其他位。