使用C语言对微控制器Atmega2560进行编程
Using C to program microcontroller Atmega2560
这是一个读取端口 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
进行或运算?这样,答案将类似于 ?1111???
。他为什么不使用 AND 而不是 OR?
*3:程序是否对'data'中的位和字节11000011
进行AND运算?这样,答案将类似于 ??0000 ??。这样做有什么意义?
*4: 为什么他向左移动 'data'
一次?这样答案就会像 ?0000??0.
*5:程序是否对 0x25
中的位和字节 01111000
进行与运算(结果为 0????000),然后与它的结果和数据中的位?这样,答案将类似于 00000000
!?!?!?
1:程序正在构建位域 0b00111100,然后用 ~ 运算符将其取反变成 0b11000011,然后将该值与 ptr 指向的地址的内容进行 AND 运算,然后将结果存储到指向的地址中通过 ptr.它清除数据方向寄存器的第 2 位到第 5 位,同时保持其他位不变。据推测,位值为 0 表示该引脚是输入。
2:程序正在构建位域 0b01111000,然后将该值与 ptr 指向的地址的内容进行 OR 运算,然后将结果存储到 ptr 指向的地址中。它设置数据方向寄存器的第 3 位到第 6 位,同时保持其他位不变。据推测,位值为 1 表示该引脚是输出。
3:程序将从数据地址读取的值与 0xb00111100 进行逻辑与操作,以清除位 0、1、6 和 7。程序只关注位 2 到位 5,而忽略其他位。
4: 程序正在将第 2 位到第 5 位的值向左移动一位,以便将其移动到第 3 位到第 6 位。
5:程序正在读取数据寄存器的内容,清除从数据寄存器中读取的第 3 位到第 6 位,然后对第 3 位到第 6 位的新值进行或运算,然后再写回数据寄存器。换句话说,它正在更新位 3 到 6 的值而不更改位 0、1、2 和 7 的值。
这些操作很常见:
data &= ~(bitfield)
清除 bitfield 指定的位而不改变其他位。
data |= bitfield
设置 bitfield 指定的位而不改变其他位。
这是一个读取端口 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
进行或运算?这样,答案将类似于 ?1111???
。他为什么不使用 AND 而不是 OR?
*3:程序是否对'data'中的位和字节11000011
进行AND运算?这样,答案将类似于 ??0000 ??。这样做有什么意义?
*4: 为什么他向左移动 'data'
一次?这样答案就会像 ?0000??0.
*5:程序是否对 0x25
中的位和字节 01111000
进行与运算(结果为 0????000),然后与它的结果和数据中的位?这样,答案将类似于 00000000
!?!?!?
1:程序正在构建位域 0b00111100,然后用 ~ 运算符将其取反变成 0b11000011,然后将该值与 ptr 指向的地址的内容进行 AND 运算,然后将结果存储到指向的地址中通过 ptr.它清除数据方向寄存器的第 2 位到第 5 位,同时保持其他位不变。据推测,位值为 0 表示该引脚是输入。
2:程序正在构建位域 0b01111000,然后将该值与 ptr 指向的地址的内容进行 OR 运算,然后将结果存储到 ptr 指向的地址中。它设置数据方向寄存器的第 3 位到第 6 位,同时保持其他位不变。据推测,位值为 1 表示该引脚是输出。
3:程序将从数据地址读取的值与 0xb00111100 进行逻辑与操作,以清除位 0、1、6 和 7。程序只关注位 2 到位 5,而忽略其他位。
4: 程序正在将第 2 位到第 5 位的值向左移动一位,以便将其移动到第 3 位到第 6 位。
5:程序正在读取数据寄存器的内容,清除从数据寄存器中读取的第 3 位到第 6 位,然后对第 3 位到第 6 位的新值进行或运算,然后再写回数据寄存器。换句话说,它正在更新位 3 到 6 的值而不更改位 0、1、2 和 7 的值。
这些操作很常见:
data &= ~(bitfield)
清除 bitfield 指定的位而不改变其他位。
data |= bitfield
设置 bitfield 指定的位而不改变其他位。