如何在ATmega16上读取数字输入?


18

要读取ATmega16上的数字输入(按钮),我该怎么办?我必须启用上拉电阻还是可以使用10 kohm电阻?一些简单的代码是什么?只需简单的“在按下时打开LED指示灯”即可。

有初学者的教程吗?我曾尝试使用谷歌搜索和AVR Freaks,但是所有事情都演变成一场战斗,我没有得到答案。我真的还没有找到关于这些东西的任何教程。大量的特定信息,但是关于我的AVR微控制器却并非如此简单...


4
几乎在任何初学者的教程中都可以找到答案,我担心这里的完整答案会损害您的理解而不是帮助。您已经做了哪些先前的工作来学习?
Yann Vernier,2010年

不知道您是看过我的帖子还是看得见它(抱歉,这个站点还是有点困惑……)但是我知道代码,可以说我的问题是:我只是将引脚连接到GND及其低端吗?
好奇

2
为什么不编辑您的帖子以更准确地反映这一点,并将以下帖子也包含在原始帖子中。
阿摩司(Amos)2010年

AVR Freaks页面上尝试从头开始的AVR教程。您会在那找到更多的东西。
莱昂·海勒2010年

Answers:


24

巴西的问候!

首先,感谢乔比的例子。其次,他的例子只有一个小错误。数字0x20不正确。它应该是0x04。另外,作为建议,我不会在代码中使用十六进制数字,例如0xFB,0x20或0x04。我建议使用io.h中找到的PIN端口定义以及头文件引用的其他端口定义。我在下面重写了乔比的示例,并为初学者提供了一些注释。

# include <avr/io.h>

int main (void)
{
    // set all pins on PORTB for output
    DDRB = 0xFF;

    // set port pin PORTD2 as input and leave the others pins 
    // in their originally state (inputs or outputs, it doesn't matter)
    DDRD &= ~(1 << PD2);        // see comment #1

    while (1) 
    {
        if (PIND & (1<<PD2))    // see comment #2
            PORTB |= (1<<PB2);  // see comment #3
        else
            PORTB &= ~(1<<PB2); // see comment #4
    }
    return 0;
}

/ *

给初学者的评论

评论#1:(1 << PD2)生成二进制00000100。操作“〜”翻转所有数字,即二进制现在为11111011。最后,&=在DDRD和11111011之间应用逻辑“ AND”,并再次放置结果在DDRD内存中。注意:运算符“ AND”对DDRD存储器中的每个位进行操作,并将其与上述二进制数进行比较。如果DDRD中的位为0,并且二进制位中同一位的位为1,则结果位为0;如果DDRD为1,二进制中的位为1,则结果位为1;如果DDRD中的位为1或0,二进制中的位为0,则结果位始终为0。总而言之,命令DDRD&=〜(1 << PD2)仅将位PD2更改为零,而其他位(零或一个)保持不变。这似乎有点复杂,但是在您习惯了它之后,这是在不改变其他位的情况下改变一个位的最佳方法。

注释#2:(1 << PD2)生成二进制00000100。使用注释#1中描述的相同逻辑“与”,命令“ PIND&0000100”仅检查PIND2(我们连接按钮的输入引脚)设置为高)。由于二进制位设置为0,且所有其他引脚将为FALSE,并且由于二进制位#2设置为1,因此只有在PD2输入设置为高电平时IF语句才为TRUE,而在PD2输入设置为FALSE时则为FALSE。设置为低。

注释3:遵循注释1中解释的逻辑,此命令将端口PORTB中的输出引脚PINB2设置为高电压。如果您的LED用约300欧姆的电阻正确连接到了此引脚端口,并且该电阻已接地,则LED应该亮起。

注释4:LED指示灯应出于前面注释中所述的相同原因关闭。

最终考虑因素:

a)为避免在未按下按钮(开路)时输入引脚PD2中的电压振荡,强烈建议放置一个下拉电阻(1 kOhm或更高),以免LED意外亮起到这种随机的电压振荡。

b)免责声明:此处描述的思想仅用于教育目的,在咨询电子专家之前,不得在任何实际系统中使用它们。

* /


3
我不鼓励您提供电子邮件,因为通过电子邮件进行通信会使通信变得私密。所以没有其他人可以受益。但是,如果您真的想提供私人通信电子邮件,那么最好的方法是在您的个人资料中。
Daniel Grillo

反之亦然-#3关闭LED,#4打开LED吗?
sitilge '16

2

https://www.mainframe.cx/~ckuethe/avr-c-tutorial/

https://www.mainframe.cx/~ckuethe/avr-c-tutorial/#digital-in

#include <avr/io.h>

/*
 * Assumptions:
 *  - LED connected to PORTB.2
 *  - Switch connected to PORTD.2
 */

int main (void)
{
    /* set PORTB for output*/
    DDRB = 0xFF;
    /* set PORTD for input*/
    DDRD &= 0xFB;
    PORTD |= 0x04;

    while (1) {
        if (PIND & 0x04)
            PORTB &= ~0x20;
        else
            PORTB |= 0x20;
    }
    return 0;
}

感谢@joby Taffey提供的链接。我正在搜索EEPROM功能,并且从以下主机获得了很多帮助:mainframe.cx/~ckuethe/avr-c-tutorial/lesson11.c非常感谢。
比沙尔·波德尔



0

处理来自机械开关的数字输入时,还需要考虑的其他事项是触点弹跳-将应该是单按钮的按钮更改为看起来像多次按钮的按钮。

对于诸如在按下按钮时打开LED之类的事情,您可能不必担心抖动。对于有些复杂的事情(例如在按钮上切换LED),必须进行反跳。

Jack Ganssle有一个不错的反跳指南

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.