我正在研究学校项目,需要使用AVR atmega控制器学习C语言的基础知识.
我不明白一切都是如何建立的.例如PORTB,PORTD,DDRB; DDRD,PINB,PIND等等.我不知道if语句,while循环等是如何工作的.
有人可以给我一个简短的解释吗?
我有一些代码行......
DDRB = 0b00000011; // I know that here DDRB is set to input/output
并且if语句:
if (PINB & (1 << PINB0)){ A = true; }
有人可以解释一下这个"if语句"是如何工作的吗?为什么PINB & (1<< PINB0))
?
谢谢
if (PINB & (1 << PINB0)){ A = true; }
此代码检查是否PIN 0 in PORTB
是HIGH or LOW
.如果是高然后分配A = true;
在这里,PINB
- >读取数据PORTB, (1<<PINB0)
- >写第0位为1 AND
的值都知道PIN 0无论PORTB
是高还是不行.
你的意思是条件是什么PINB & (1<< PINB0))
?
它检查PINB0 + 1
数字位(来自rhs)是ON(1)in PINB
还是OFF(0).
例如.(a & (1 << 2))
检查第3位是ON a
还是OFF.在表达式中,两个运算符<<
按位左移和&
按位使用,下面我解释了一个字节的例子:
1
是 0000 0001
1 << 2
左移后给出 0000 0100
a
按位和同时0000 0100
给出全零0000 0000
或0000 0100
3A.如果全为零,则条件为假(当第三位a
为零时).
3B.如果是按位的结果,0000 0100
那么条件的计算结果为真(当第三位a
为1时).
对于寄存器的含义,建议咨询
您正在使用的设备的数据表
您正在使用的C编译器附带的头文件.
简而言之,最后一个字母(B
,D
)表示您正在访问的端口:GPIO引脚按8组合在一起,因此每个端口有8个引脚.
DDRx
是一种设置每个端口引脚方向的方法.
PORTx
和PINx
用于输入和输出,但我习惯了使用PORTA.IN
,PORTB.DDR
,PORTD.OUT
等,我不能由他们做什么的心脏告诉.
对于该语言的基础知识,有书籍和教程可以让您学习这门语言.
微处理器使用存储器映射将其硬件功能与软件连接.
基本上,内存中存在静态地址,硬件将使用这些地址来确定其功能.这些特定于制造商,零件,有时甚至是零件的配置方式.
该部件的数据表将告诉您控制不同功能的确切内存位置.但是,这通常非常繁琐.因此,数据表也(几乎)总是给内存中描述其功能的特定位置命名.这些名称再次是制造商和部分特定的.
为了使程序员更容易使用这个界面,人们(制造商或社区)通常会为这些内存位置创建宏.例如,你可以找到
// Clock Prescalar Register for ATMega328p #define CLKPR *0x61
在与该部件关联的头文件中(例如AVR libc).
现在,通过写入OSCCAL = 0b10000000
(或者我想写的任何其他可以通过数据表中的规范进行编写的内容),我可以直接访问和更改此部分的时钟预分频模块.
但是,我们常常对单个位的值感兴趣,而不是整个字节的值.其结果是,我们使用位运算符(如&
,|
,~
,<<
>>
),以"掩模"关,我们有兴趣操纵比特.
这提供了同时的优势,允许我们只从感兴趣的位读取值,同时不会无意中改变我们不打算切换的任何位.
宏也给出了许多位位置.例如,第7位OSCCAL
被命名CLKPCE
(再次,来自数据表).
CLKPCE很可能是通过以下方式定义的(至少在AVR libc中 - 标准各不相同):
#define CLKPCE 7
因为它定义了到达内部所需位所需的位移OSCCAL
.
为了谈谈这里的一点,我可以做几件事.
要设置该位,我们希望将其设为1,而不影响任何其他位.为此,我们使用OR掩码,如下所示:
OSCCAL = (OSCCAL | (1 << CLKPCE));
我将留给你审查位操作符,看看它是如何工作的.
在这里,我们希望将其设为0,而不影响其他位.它看起来像这样:
OSCCAL = (OSCCAL & ~(1 << CLKPCE));
在查询时,我们想要一个表达式,如果该位置位(1)则返回非零值,如果该位被清除则返回0(0).它看起来像这样:
(OSCCAL & (1 << CLKPCE));
通过使用预定义宏的这些不同的按位运算,我们可以使用此静态存储器映射直接控制和查询硬件状态.
但是,要了解所有这些宏,您需要查阅(并阅读,重新读取和重新读取)数据表.幸运的是,您可以在您的部分页面上免费搜索Atmel的可搜索PDF文件!