AVR单片机学习五按键与数码管的程序设计.docx
- 文档编号:5901597
- 上传时间:2023-01-02
- 格式:DOCX
- 页数:17
- 大小:603.04KB
AVR单片机学习五按键与数码管的程序设计.docx
《AVR单片机学习五按键与数码管的程序设计.docx》由会员分享,可在线阅读,更多相关《AVR单片机学习五按键与数码管的程序设计.docx(17页珍藏版)》请在冰豆网上搜索。
AVR单片机学习五按键与数码管的程序设计
AVR单片机学习(五)按键与数码管的程序设计
按键与数码管的程序设计
AVRIO口的输入模式与上拉电阻
选择结构语句与按键的查询方式程序设计
数码管基本原理
扫描方式显示多位数码管
一、输入状态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
第一个是PD2上一段接VCC其他都是一段接IO(PD3
PD6PD7)口另一端接地线。
所以当按键闭合时候相应IO都输入一个0,当按键抬起来的时候IO输入多少呢?
所以这些IO口必须将上拉电阻进行使能,将按键打开相当于输入一个1.所以我们判断这3个按键按没按下去的话,就判断输入是不是0就行了。
对于第一个按键如果按下输入是1,当抬起来时候由于AVR内部不带下拉电阻的,所以按键打开时候输入是0.
所以就需要判断某一位是0,还是1.某一位是0还是1就用到了&与运算了。
1跟1
与就11与0就是0
上面代码(temp&(1
(temp&0b01000000)temp本身值不变,只是结果来判断某一位是0还是1
比如:
PD6
上的K3
因为PD6所以PIND
&(1
三、PIND&(1
除非你上电之前一直讲按键按下,否则上电的一瞬间程序就执行到while
(1);了所以要将他们加入到死循环里面如下图
这样就实现了按键的不停的检测。
其实DDRD上电默认都是0
所以清0置为输入也没有意义。
程序在if判断设置断点然后全速执行可以看到只要没有按键按下程序进不去断点,如果我们在板子上按下K3则如下图所示进入断点,再按下单步执行蜂鸣器响了如图。
所以这个程序就达到了我们的目的。
现在换一种判断就是按键被按下而不是没被按下用逻辑非
这样达到了预想的目标。
但是这样只能判断一个按键如果多个按键怎么办呢?
2种办法
一、采用ifelseifelse
if(){
elseif{
}
elseif{
}
else{
}
}
二、采用
switch(表达式){
case相符合的条件
{
break;
}
case相符合的条件{
break;
}
default{
}
}
一、用if实现
#include
intmain(void){
//PD6设置为输入K3
DDRD&=~(1//输入状态下将数据寄存器使能上拉电阻
PORTD|=(1//PD7设置为输入K4
DDRD&=~(1
//输入状态下将数据寄存器使能上拉电阻
PORTD|=(1//PD2设置为输入K1
DDRD&=~(1
//输入状态下将数据寄存器使能上拉电阻
PORTD|=
(1//PD3设置为输入K2
DDRD&=~(1
//输入状态下将数据寄存器使能上拉电阻
PORTD|=(1//蜂鸣器PA3设置方向寄存器为输出
DDRA|=(1//蜂鸣器关掉
PORTA&=~(1//流水灯端口全部设为输出
DDRB=0xff;
while
(1){
//判断PIND这位是否为1
为真的话就是按键没有按下
if(!
(PIND&
(1
被按下进入了PD6
//按键被按下用蜂鸣器表示一下
PA3
PORTA
|=(1}
elseif(!
(PIND&
(1
K4按下让流水灯产生动作必须上面使能K4上拉电阻
PORTB|=
(1}
elseif(PIND&
(1//第二个灯发光
PORTB|=
(1}
elseif(!
(PIND&
(1//第三个灯发光
PORTB|=
(1}
else{
//变成了按键没有按下
PORTA&=~(1PORTB=
0;//灯
}
//看到没有按下一直响的,按下就不响了。
}
}
---------------------------------------------------------------
二、用switch来实现就需要一次性将这四位读回来。
代码如下
#include
intmain(void){
//PD6设置为输入K3
DDRD&=~(1//输入状态下将数据寄存器使能上拉电阻
PORTD|=(1//PD7设置为输入K4
DDRD&=~(1
//输入状态下将数据寄存器使能上拉电阻
PORTD|=(1//PD2设置为输入K1
DDRD&=~(1
//输入状态下将数据寄存器使能上拉电阻
PORTD|=
(1//PD3设置为输入K2
DDRD&=~(1
//输入状态下将数据寄存器使能上拉电阻
PORTD|=(1//蜂鸣器PA3设置方向寄存器为输出
DDRA|=(1//蜂鸣器关掉
PORTA&=~(1//流水灯端口全部设为输出
DDRB=0xff;
while
(1){
//首先一次性将这4个位都读回来
2367脚
switch(PIND
&0b11001100){
case
0b11001100:
{//只有第一个按键按下0b11001100
接的电源按下是1
//LED
0发光
PORTB
|=(1break;
}
case
0b11000000:
{//只有第二个按键按下0b11001100
接的电源抬起是0
//LED
0发光
PORTB
|=(1break;
}
case
0b10001100:
{//只有第三个按键按下0b11001100
接的电源抬起是0
//LED
0
PORTB
|=(1break;
}
case
0b01001100:
{//只有第四个按键按下0b11001100
接的电源抬起是0
//LED
0发光
PORTB
|=(1break;
}
default
:
{//都没有按下
0b11001000因为有下拉
//变成了按键没有按下
PORTA&=~(1
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输出一个1PA5PA6PA7全都输出0
这样我们选中第0个第一位数码管此时在PB口上输出的数据就会显示在数码管上面。
编写程序:
设置一个断点然后再单步调试(F10)。
看看它显示的是那一段。
同时流水灯也亮了,因为是同一个IO口。
这样对应PB上的每一段都找到了。
好了这样我们就去编写一下数码管的段码;
首先是显示1
只要将需要点亮的各个段置1就实现了段码的功能,具体的编写过程自己去画画看
这是我自己用数组的形式定义的。
首先是什么类型的数组名称元素个数
0-9
A-F
全部显示出来就是16个元素,一个字符型数加一个逗号分开。
一直放16个,使用时候要从第0个开始下标从0开始的。
#include
intmain(void){
//PD6设置为输入K3
DDRD&=~(1//输入状态下将数据寄存器使能上拉电阻
PORTD|=(1//PD7设置为输入K4
DDRD&=~(1
//输入状态下将数据寄存器使能上拉电阻
PORTD|=(1//PD2设置为输入K1
DDRD&=~(1
//输入状态下将数据寄存器使能上拉电阻
PORTD|=(1//PD3设置为输入K2
DDRD&=~(1
//输入状态下将数据寄存器使能上拉电阻
PORTD|=(1//蜂鸣器PA3设置方向寄存器为输出
DDRA|=(1//蜂鸣器关掉
PORTA&=~(1//数码管全部置为输出
DDRB=0xff;
//位选线高四位全部置1也是输出因为是置其中4位所以用|=
DDRA|=0Xf0;
charscandata[16]={
0b10101111,//0
0b10100000,//1
0b11000111,//2
0b11100110,//3
0b11100000,//4
0b01101110,//5
0b01101111,//6
0b10100010,//7
0b11101111,//8
0b11101110,//9
0b11100111,//A
0b01101101,//b
0b00001111,//c
0b11000001,//d
0b01001111,//E
0b01001111//F
};
while
(1){
//数码管也需要扫描所以也用死循环
while
(1)
//先将数码管的第一位点亮
选中位选
PORTA
|=(1
//再将数据送到PB口上哪一段对应哪一位
要事先测量下编一个程序测量下
PORTB=
scandata[0];//显示0
PORTB=
scandata[1];//显示1
PORTB=
scandata[2];//显示2
PORTB=
scandata[3];//显示3
PORTB=
scandata[4];//显示4
PORTB=
scandata[5];//显示5
PORTB=
scandata[6];//显示6
PORTB=
scandata[7];//显示7
PORTB=
scandata[8];//显示8
PORTB=
scandata[9];//显示9
PORTB=
scandata[10];//显示A
PORTB=
scandata[11];//显示B
PORTB=
scandata[12];//显示C
PORTB=
scandata[13];//显示D
PORTB=
scandata[14];//显示E
PORTB=
scandata[15];//显示F
}
}
//这就是数码管用段码显示。
那么怎么对数码管扫描显示呢?
我们可以遵循这样一个顺序,首先将数码管位选中,送数据PORTA
选中
PORTB送上数据然后打开相应这一位。
让他显示出来,显示出来之后呢?
再让这一位熄灭可以把所有四位都熄灭
位选PORTA&0x0f;高四位清0这样就完成了数码管的高四位显示。
#include
intmain(void){
intj;
//PD6设置为输入K3
DDRD&=~(1//输入状态下将数据寄存器使能上拉电阻
PORTD|=(1//PD7设置为输入K4
DDRD&=~(1
//输入状态下将数据寄存器使能上拉电阻
PORTD|=(1//PD2设置为输入K1
DDRD&=~(1
//输入状态下将数据寄存器使能上拉电阻
PORTD|=(1//PD3设置为输入K2
DDRD&=~(1
//输入状态下将数据寄存器使能上拉电阻
PORTD|=(1//蜂鸣器PA3设置方向寄存器为输出
DDRA|=(1//蜂鸣器关掉
PORTA&=~(1//数码管全部置为输出
DDRB=0xff;
//位选线高四位全部置1也是输出因为是置其中4位所以用|=
DDRA|=0Xf0;
charscandata[16]={
0b10101111,//0
0b10100000,//1
0b11000111,//2
0b11100110,//3
0b11100000,//4
0b01101110,//5
0b01101111,//6
0b10100010,//7
0b11101111,//8
0b11101110,//9
0b11100111,//A
0b01101101,//b
0b00001111,//c
0b11000001,//d
0b01001111,//E
0b01001111//F
};
while
(1){
//数码管也需要扫描所以也用死循环
while
(1)
//先将数码管的第一位点亮
选中位选
PORTA
|=(1
//再将数据送到PB口上哪一段对应哪一位
要事先测量下编一个程序测量下
PORTB=
scandata[0];//显示0
for
(j=0;jPORTA&=
0x0f;
PORTA|=
(1PORTB=
scandata[1];
PORTA&=
0x0f;
for
(j=0;jPORTA|=
(1PORTB=
scandata[2];
PORTA&=
0x0f;
for
(j=0;jPORTA|=
(1PORTB=
scandata[3];
for
(j=0;jPORTA&=
0x0f;
//单步仿真看看
就是1位亮了0熄灭2位亮1熄灭
3位亮2熄灭4位亮3
熄灭一直循环
//全速执行看看显示4个数字
可以看到亮度不怎么亮的,因为点亮熄灭只有那么一小段时间是发光的
//所以如果要增加亮度只需要加一个延时程序
声明一个变量j在看效果全速执行亮度是明显增加了
//这就是数码管程序扫描的程序设计
}
}
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- AVR 单片机 学习 按键 数码管 程序设计