AVR单片机学习按键与数码管的程序设计

2020-02-12来源: eefocus关键字:AVR单片机  学习按键  数码管

简介:按键与数码管的程序设计
AVR IO口的输入模式与上拉电阻
选择结构语句与按键的查询方式程序设计
数码管基本原理
扫描方式显示多位数码管



一、输入状态IO寄存器设置


1、DDRx 某一位置0,相应位的IO口被设置为输入


2、PORTx某一位置1,使能对应IO口相应位的上拉电阻


3、PINx的对应位是输入的数据,0或1


选择结构语句


一、关系运算符和关系表达式


小于< 小于等于<= 大于> 大于或等于== 不等于!=


二、逻辑运算符和逻辑表达式


逻辑与&&逻辑或||逻辑非!


三、if 语句结构


if(表达式1)语句1


else if(表达式2)语句2


else 语句3


四、switch 语句结构


switch(表达式)


{case 常量1:表达式1


case 常量2:表达式2


.........


default:表达式n}


按键的查询方式程序设计


一、PIND & (1<<6)


二、1<<6


1、1左移6位,即:0b01000000


怎么判断一个按键按下了呢?首先看下图是4个按键













第一个是PD2 上一段接VCC 其他都是一段接IO(PD3 PD6 PD7)口另一端接地线。


所以当按键闭合时候相应IO都输入一个0,当按键抬起来的时候IO输入多少呢?


所以这些IO口必须将上拉电阻进行使能,将按键打开相当于输入一个1.所以我们判断这3个按键按没按下去的话,就判断输入是不是0就行了。


对于第一个按键如果按下输入是1,当抬起来时候由于AVR内部不带下拉电阻的,所以按键打开时候输入是0.


所以就需要判断某一位是0,还是1.某一位是0还是1就用到了& 与运算了。 1 跟1 与就1 1 与0 就是0


上面代码(temp& (1<<6)) (temp & 0b01000000) temp本身值不变,只是结果来判断某一位是0还是1


比如:PD6 上的K3 因为PD6 所以 PIND &(1<<6)的结果就行了


三、PIND & (1<<6)


1、移除第6位之外其他位清零


2、第6位保持输入的值


四、与选择结构语句的结合


1、判断PIND & (1<<6)的值,执行相应代码



除非你上电之前一直讲按键按下,否则上电的一瞬间程序就执行到while(1);了所以要将他们加入到死循环里面如下图


这样就实现了按键的不停的检测。 其实DDRD 上电默认都是0 所以清0 置为输入也没有意义。


程序在if判断设置断点然后全速执行可以看到只要没有按键按下程序进不去断点,如果我们在板子上按下K3则如下图所示进入断点,再按下单步执行蜂鸣器响了如图。



所以这个程序就达到了我们的目的。


现在换一种判断 就是按键被按下而不是没被按下 用逻辑非


这样达到了预想的目标。但是这样只能判断一个按键如果多个按键怎么办呢?2种办法


一、采用if elseif else


if (){


elseif{


}


elseif {


}


else{




}


}


二、采用


switch (表达式){


case 相符合的条件 {


break;


}


case 相符合的条件{


break;


}


default{




}


}


一、用if 实现


#include

int main(void){

//PD6 设置为输入 K3

DDRD &= ~(1 << 6);

//输入状态下将数据寄存器使能上拉电阻

PORTD |= (1<<6);

//PD7 设置为输入 K4

DDRD &= ~(1 << 7);

//输入状态下将数据寄存器使能上拉电阻

PORTD |= (1<<7);

//PD2 设置为输入 K1

DDRD &= ~(1 << 2);

//输入状态下将数据寄存器使能上拉电阻

PORTD |= (1<<2);//这个上拉不上拉没关系因为上拉是百K的电阻所以开关打开还是认为是低电平

//PD3 设置为输入 K2

DDRD &= ~(1 << 3);

//输入状态下将数据寄存器使能上拉电阻

PORTD |= (1<<3);


//蜂鸣器PA3 设置方向寄存器为输出

DDRA |= (1<<3);

//蜂鸣器关掉

PORTA &= ~(1<<3);

//流水灯端口全部设为输出

DDRB = 0xff;

while(1){

//判断PIND 这位是否为1 为真的话就是按键没有按下

if (!(PIND & (1<<6))){ //本来没有按下 进入 现在变成了没有按下 不进入了取非了 被按下进入了 PD6

//按键被按下用蜂鸣器表示一下 PA3

PORTA |= (1<<3);

}

else if(!(PIND & (1<<7))){ //PD7 K4按下让流水灯产生动作 必须上面使能K4上拉电阻

PORTB |= (1<<0);//第一个灯发光 就是等于1

}

else if (PIND & (1<<2)){//因为按下的时候是低电平接的是电源

//第二个灯发光

PORTB |= (1<<1);

}

else if (!(PIND & (1<<3))){

//第三个灯发光

PORTB |= (1<<2);

}

else{

//变成了按键没有按下

PORTA &= ~(1<<3); //蜂鸣器

PORTB = 0;//灯

}

//看到没有按下一直响的,按下就不响了。

}

}


---------------------------------------------------------------


二、用switch 来实现就需要一次性将这四位读回来。 代码如下


#include

int main(void){

//PD6 设置为输入 K3

DDRD &= ~(1 << 6);

//输入状态下将数据寄存器使能上拉电阻

PORTD |= (1<<6);

//PD7 设置为输入 K4

DDRD &= ~(1 << 7);

//输入状态下将数据寄存器使能上拉电阻

PORTD |= (1<<7);

//PD2 设置为输入 K1

DDRD &= ~(1 << 2);

//输入状态下将数据寄存器使能上拉电阻

PORTD |= (1<<2);//这个上拉不上拉没关系因为上拉是百K的电阻所以开关打开还是认为是低电平

//PD3 设置为输入 K2

DDRD &= ~(1 << 3);

//输入状态下将数据寄存器使能上拉电阻

PORTD |= (1<<3);

//蜂鸣器PA3 设置方向寄存器为输出

DDRA |= (1<<3);

//蜂鸣器关掉

PORTA &= ~(1<<3);

//流水灯端口全部设为输出

DDRB = 0xff;

while(1){

//首先一次性将这4个位都读回来 2 3 6 7 脚

switch(PIND & 0b11001100) {

case 0b11001100: {//只有第一个按键按下 0b11001100 接的电源按下是1

//LED 0 发光

PORTB |= (1<<0);

break;

}

case 0b11000000: {//只有第 二个按键按下 0b11001100 接的电源抬起是0

//LED 0 发光

PORTB |= (1<<1);

break;

}

case 0b10001100: {//只有第三个按键按下 0b11001100 接的电源抬起是0

//LED 0

PORTB |= (1<<2);

break;

}

case 0b01001100: {//只有第四个按键按下 0b11001100 接的电源抬起是0

//LED 0 发光

PORTB |= (1<<3);

break;

}

default :{ //都没有按下 0b11001000 因为有下拉

//变成了按键没有按下

PORTA &= ~(1<<3); //蜂鸣器

PORTB = 0;//灯


break;

}

}


//判断PIND 这位是否为1 为真的话就是按键没有按下


}

}


-------------------------------------------------------------------------


以上都是查询方式因为都是在while循环一边一边的查询,按键有动作就执行相应的代码这样很耽误CPU的时间的,在下一篇博客我会稍微降讲用中断的方式来编写按键的程序。下面继续说呵呵、


八段数码管


一、八段数码管


1、八段数码管由八段LED构成


2、各LED阴极或阳极并在一起,称为“位选线”:共阴、共阳


3、其余8个引脚各自引出,称为“段选线”,各段可以分别控制






记住一般一位的数码管有10个脚


个人理解:(其中2脚是连在一起的是公共端。其他8个是段选 比如1、6接电源 其他接IO口个人理解的)


多位合一的数码管


一、多位合一的数码管


1、将多个八段数码管的段选线分别并在一起,位选线引出如下图



由上图看出是4位 应该是8个段选线(7段加一个点) 4个位选线 共12根线 。


com0 ---- com3 是位选


a-g 加 dp 是段选。


多位数码管的使用


1、多位数码管的各个位均可以单独显示不同的数据,但一个时刻只能点亮一位、(点快点人眼看不出来)


2、依次点亮多位数码管中的各个位,由于人眼的视觉暂留效应,看起来是同时点亮


3、如下图是电路图 硬件电路是下图设计的






它的每一段相当于一个发光二极管,电流大约是10个mA左右(5--10)mA,因此段选可以直接用单片机的IO驱动是足够的不论是拉电流还是灌电流,这里面我们用的是一个共阴极的数码管,因此应该是向外拉电流,而段选线我们可以计算下段选线上最大电流时多少?假设每段都点亮没段是10mA的话,那么位选线上也就是10*8 = 80mA 所以我们不能用IO口,一般的单片机不可能输出这么大的电流,所以我采用一个三极管来进行驱动,共阴极的数码管一般要用NPN型的数码管,它的接法如下图的样子。




再来张清楚点的下图





可以看到C0 接的是COM0位选线,IO口通过1K电阻接到三极管基极上,如果IO是个高电平的话电流就通过三极管到射极流下来的,因此三极管达到饱和,CO点相当于导通相当于接地。4个段选分别接到PA4到PA7 四个IO口上因此我们写程序首先将PA4 输出一个1 PA5 PA6 PA7 全都输出0 这样我们选中第0个第一位数码管此时在PB口上输出的数据就会显示在数码管上面。编写程序:





设置一个断点然后再单步调试(F10)。看看它显示的是那一段。同时流水灯也亮了,因为是同一个IO口。这样对应PB上的每一段都找到了。


好了这样我们就去编写一下数码管的段码;


首先是显示1 只要将需要点亮的各个段置1就实现了段码的功能,具体的编写过程自己去画画看



这是我自己用数组的形式定义的。


首先是什么类型的数组 名称 元素个数


0-9


A-F


全部显示出来就是16个元素,一个字符型数加一个逗号分开。一直放16个,使用时候要从第0个开始下标从0开始的。


#include

int main(void){

//PD6 设置为输入 K3

DDRD &= ~(1 << 6);

//输入状态下将数据寄存器使能上拉电阻

PORTD |= (1<<6);

//PD7 设置为输入 K4

DDRD &= ~(1 << 7);

//输入状态下将数据寄存器使能上拉电阻

PORTD |= (1<<7);

//PD2 设置为输入 K1

DDRD &= ~(1 << 2);

//输入状态下将数据寄存器使能上拉电阻

PORTD |= (1<<2);//这个上拉不上拉没关系因为上拉是百K的电阻所以开关打开还是认为是低电平

//PD3 设置为输入 K2

DDRD &= ~(1 << 3);

//输入状态下将数据寄存器使能上拉电阻

PORTD |= (1<<3);

//蜂鸣器PA3 设

[1] [2]
关键字:AVR单片机  学习按键  数码管 编辑:什么鱼 引用地址:http://news.eeworld.com.cn/mcu/ic487960.html 本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:基于AVR的激光测距机综合性能检测设备设计
下一篇:基于Atmega64L的心率监测系统中MCU的设计

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

AVR单片机实现对步进电机的细分控制及其应用
受负载变化的影响,即给电机某相线圈加一脉冲信号,电机则转过一个步距角。这一线性关系的存在,加上步进电机只有周期性的误差而无累积误差等特点,使得在速度、位置等控制领域用步进电机来控制变得非常简单。虽然步进电机已被广泛地应用,但步进电机并不像普通的直流电机、交流电机那样在常规下使用。它必须在双环形脉冲信号、功率驱动电路等组成控制系统下使用。仪表步进电机属于步进电机中体积、功耗较小的类别,可以由单片机或专用芯片的引脚直接驱动,不需外接驱动器,因而在仪表中被用于指针的旋转控制。步进电机的细分技术是一种电子阻尼技术,其主要目的是提高电机的运转精度,实现步进电机步距角的高精度细分。其基本概念为:步进电机通过细分驱动器的驱动,其步距角变小了。如驱动器
发表于 2020-02-08
AVR单片机实现对步进电机的细分控制及其应用
AVR单片机熔丝位的配置
(1)在AVR的器件手册中,对熔丝位使用已编程(Programmed)和未编程(Unprogrammed)定义熔丝位的状态, “Unprogrammed”表示熔丝状态为“1”(禁止);“Programmed”表示熔丝状态为“0”(允许)。因此,配置熔丝位的过程实际上是 “配置熔丝位成为未编程状态“1”或成为已编程状态“0””。(2)在使用通过选择打钩“√”方式确定熔丝位状态值的编程工具软件时,请首先仔细阅读软件的使用说明,弄清楚“√”表示设置熔丝位状态为“0”还是为“1”。(3)使用CVAVR中的编程下载程序时应特别注意,由于CVAVR编程下载界面初始打开时,大部分熔丝位的初始状态定义为“1”,因此不要使用其编程菜单选项中的
发表于 2020-02-08
AVR单片机性能简介
什么是AVR单片机?AVR单片机有什么优点?为什么要选择AVR单片机?AVR单片机是ATMEL公司研制开发的一种新型单片机,它与51单片机、PIC单片机相比具有一系列的优点:1:在相同的系统时钟下AVR运行速度最快;2: 芯片内部的Flsah、EEPROM、SRAM容量较大;3:所有型号的Flash、EEPROM都可以反复烧写、全部支持在线编程烧写(ISP);4:多种频率的内部RC振荡器、上电自动复位、看门狗、启动延时等功能,零外围电路也可以工作;5:每个IO口都可以以推换驱动的方式输出高、低电平,驱动能力强;6:内部资源丰富,一般都集成AD、DA模数器;PWM;SPI、USART、TWI、I2C通信口;丰富的中断源等。目前支持
发表于 2020-02-08
AVR单片机硬件电路设计方法详解
,以便以后升级AVR内的软件。JTAG仿真接口设计仿真接口也是使用双排2*5插座。需要四只10K的上拉电阻。重要说明:实际应用时,如果你不想使用JTAG仿真,并且不想受四只10K的上拉电阻的影响,可以将JP1-JP4断开。电源设计AVR单片机最常用的是5V与3.3V两种电压。本线路以开关切换两种电压,并且以双色二极管指示(5V时为绿灯,3.3V时为红灯)。二极管D1防止用户插错电源极性。D2可以允许用户将电压倒灌入此电路内,不会损坏1117-ADJ。1117-ADJ的特性为1脚会有50uA的电流输出,1-2脚会有1.25V电压。利用这个特点,可以计算出输出电压:当 SW开关打向左边时,R6上的电流为 1.25/0.33
发表于 2020-02-08
AVR单片机硬件电路设计方法详解
AVR单片机主要的特性
AVR的主要特性高可靠性、功能强、高速度、低功耗和低价位 , 一直是衡量单片机性能的重要指标,也是单片机占领市场、赖以生存的必要条件。早期单片机主要由于工艺及设计水平不高、功耗高和抗干扰性能差等原因,所以采取稳妥方案:即采用较高的分频系数对时钟分频,使得指令周期长,执行速度慢。以后的 CMOS单片机虽然采用提高时钟频率和缩小分频系数等措施,但这种状态并未被彻底改观(51以及51兼容)。此间虽有某些精简指令集单片机(RISC)问世,但依然沿袭对时钟分频的作法。AVR单片机的推出,彻底打破这种旧设计格局,废除了机器周期,抛弃复杂指令计算机(CISC)追求指令完备的做法;采用精简指令集,以字作为指令长度单位,将内容丰富的操作数与操作
发表于 2020-02-07
AVR单片机学习SPI串行口与DS1302
之间怎样进行互联呢?我们看以采用下面的这种方法。来看下电路图上图的PB5 PB6 PB7是单片机的三个I/O口。 可以看他它的第二功能是SPI功能PB5可以看到MOSI M是主 S 是从 意思就是主机输出 从机输入同理PB6 MISO 是主机输入从机输出也就是AVR的SPI正常工作的时候PB6这个引脚它应该是处于一个输入的状态PB5应该是一个输出的状态。我们就将PB5 与PB6之间串上一个10K的电阻然后再将PB6直接接到I/O上,下面我们可以简单的分析一下原理图是怎样正常工作的,首先这个DS1302对它处于写的状态的时候呢,DS1302的I/O口是处于输入的,而PB6呢也是一个输入口始终是一个输入口。
发表于 2020-02-07
AVR单片机学习SPI串行口与DS1302
小广播
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2020 EEWORLD.com.cn, Inc. All rights reserved