C - AVR - 简单的PORTB,DDRB,PINB说明

时间:2014-01-08 11:00:11

标签: c avr atmega

我正在从事学校项目,需要使用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声明:

if (PINB & (1 << PINB0)){
    A = true;
}

有人可以解释一下'if statement'是如何工作的吗?为什么PINB & (1<< PINB0))

由于

4 个答案:

答案 0 :(得分:12)

你的意思是if-condition PINB & (1<< PINB0))是什么意思吗?

它检查PINB0 + 1中的PINB数字位(来自rhs)是否为ON(1)或OFF(0)。

例如。 (a & (1 << 2))检查a中的第3位是否为ON或OFF。在表达式中,使用了两个运算符<<按位左移和&按位,下面我解释了一个字节的示例:

  1. 10000 0001
  2. 左移后
  3. 1 << 2给出0000 0100
  4. a按位,0000 0100可以全部为0000 00000000 0100

    3A。如果全部为零,则条件为假(当a中的第三位为零时)  3B。如果按位的结果为0000 0100,则条件求值为真(当a中的第三位为1时)。

答案 1 :(得分:9)

微处理器使用内存映射将其硬件功能与软件连接。

基本上,内存中存在静态地址,硬件将使用这些地址来确定其功能。这些特定于制造商,零件,有时甚至是零件的配置方式。

该部件的数据表将告诉您控制不同功能的确切内存位置。但是,这通常非常繁琐。因此,数据表也(几乎)总是给内存中描述其功能的特定位置命名。这些名称再次是制造商和具体部件。

为了使程序员更容易使用此界面,人们(制造商或社区)通常会为这些内存位置创建宏。例如,你可以找到

// Clock Prescalar Register for ATMega328p
#define CLKPR *0x61

在与该部件关联的头文件中(例如AVR libc)。

现在,通过编写OSCCAL = 0b10000000(或者我想写的其他任何我想写的数据表中的规范),我可以直接访问和更改该部分的时钟预分频模块。

但是,我们常常对单个位的值感兴趣,而不是整个字节的值。因此,我们使用按位运算符(例如&|~<< >>)来“掩盖”我们感兴趣的位在操纵。

这提供了同时的优势,允许我们只从感兴趣的位读取值,同时不会无意中改变我们不打算切换的任何位。

宏也给出了很多位位置。例如,OSCCAL中的第7位被命名为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));

The Takeaway

通过使用预定义宏的这些不同的按位运算,我们可以使用这个静态存储器映射直接控制和查询硬件状态。

但是,要了解所有这些宏,您需要查阅(并阅读,重新读取和重新读取)数据表。幸运的是,您可以在自己的页面上免费获取可搜索的PDF文件!

答案 2 :(得分:5)

if (PINB & (1 << PINB0)){
        A = true;
    }

此代码检查PIN 0 in PORTB是否为HIGH or LOW。如果它很高则分配A = true; 在此,PINB - &gt;从PORTB, (1<<PINB0) - &gt;读取数据将第0位设为1并将AND这两个值都知道PORTB中的PIN 0是否为高。

答案 3 :(得分:5)

关于寄存器的含义,建议咨询

  • 您正在使用的设备的数据表和
  • 您正在使用的C编译器附带的头文件。

简而言之,最后一个字母(BD)表示您正在访问的端口:GPIO引脚按8组合在一起,以便每个端口有8个引脚。

DDRx是一种设置每个端口引脚方向的方法。

PORTxPINx用于输入和输出,但由于我习惯使用PORTA.INPORTB.DDRPORTD.OUT等,我不能告诉他们哪一个做了什么。

对于该语言的基础知识,有书籍和教程可以让您学习这门语言。