实验二 人机交互接口实验
一、实验目的
1. 掌握多位数码管动态显示编程方法。
2. 掌握矩阵键盘编程方法。
二、实验内容
1. 验证课堂例题
编译下载运行课堂例题,查看运行结果。理解程序的编程思想和程序执行过程。
2. 设计程序
参考上述例题的编程思路,自行设计LED、数码管和矩阵键盘电路,对所设计的电路进行编程,实现按键控制流水灯模式并在数码管进行模式显示的程序编写与调试。
具体要求如下:
(1)初始状态下,数码管显示“P00001”,默认样式为样式1,流水灯不运行,LED全部点亮;
(2)按下1键后,LED按照模式1进行运行,立即改变,数码管显示“000001”;
(3)按下2键后,LED按照模式2进行运行,立即改变,数码管显示“000002”;
(4)按键A为启动/暂停键,控制当前样式下流水灯的启动和暂停,暂停时在数码管最左侧显示“P”,其它位不变。。
(5)按下其余按键,当前LED运行状态和数码管显示无变化。
样式1:每次仅一个LED熄灭,熄灭LED从L0至L7转移,如此循环运行。
样式2:每次仅一个LED熄灭,熄灭LED从L7至L0转移,如此循环运行。
在设计报告中,需进行总体设计思路描述,给出所涉及到的主程序、中断程序、关键功能子函数的流程图和设计代码。描述程序调试结果及出现的问题。
proteus仿真原理图
六位数码管选用型号为 7SEG-MPX6-CA 左侧8个引脚为段选引脚,控制数码管显示的具体内容(如0,1,2等等);右侧六个引脚为位选引脚,这个7SEG-MPX6-CA型号数码管为共阳极,所以对应引脚接入高电平代表这一位数码管将被点亮。
流水灯采用共阳极,单片机io低电平点亮。
单片机主频设置为8Mhz
源代码
#include <iom16v.h>
#include <macros.h>
#define uchar unsigned char
#define uint unsigned int
//#define interrupt_handler exter1:3
void delay(uint x)//延时函数
{
uint tt,hh;
for(tt=0;tt<x;tt++)
{
for(hh=0;hh<x;hh++);
}
// for(tt=0;tt<x;tt++);
}
uchar yangshi1[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};//样式1数组
uchar yangshi2[8]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};//样式2数组
uchar shumaguan[5]={0x03,0x9f,0x25,0x0d,0x31};///定义数码管显示数组,分别对应0123p
数码管显示函数
void shownumber(uint a,uint b)///变量a控制数码管第一位数值,b控制最后一位
{
uint z;
uint ii,jj;
DDRA=0xff;///数码管位选
for(ii=0;ii<48;ii++)///嵌套两次for循环,让数码管显示时间更长,代替流水灯中的延时函数
{
for(jj=0;jj<21;jj++)
{
for(z=0;z<125;z++)/第一位显示
{
PORTC=0x02;
PORTA=shumaguan[a];
}
for(z=0;z<10;z++)///中间4位显示
{
PORTC=0x3c;
PORTA=shumaguan[0];
}
for(z=0;z<25;z++)///最后一位显示的数字
{
PORTC=0x40;
PORTA=shumaguan[b];
}
}
}
}
uchar kind=1;///样式选择,初始状态为样式1
uchar k=0;///控制流水灯开始、停止的变量
uchar i=0;//数组内数据选择变量
uint pu=0;
uint q,p;///数码管第一位、最后一位显示的变量
void main(void)
{
DDRB=0xff;B口输出
PORTB=0x00;//初始状态为全低电平,led全亮
DDRC=0xff;///C口数码管位选
DDRD &=0x00;///PD输入
PORTD |=0xff;//PD上拉输入
/*开中断
*/
MCUCR |=0x02;
GICR |=BIT(6);
// DDRD&=~BIT(2);
// PORTD |=0X70;
SREG |=BIT(7);//打开全局中断
k=0;///初始状态不执行流水灯,
kind=1;//初始为样式1
p=1;///初始状态,数码管显示p00001
q=4;
while(1)进入死循环
{
shownumber(q,p);数码管第一位显示p,最后一位是q
if(PIND==0xfe)///判断k1是否按下
{
kind=1;
q=0;
p=1;
}
else if(PIND==0xfd)///判断k1是否按下
{
kind=2;
q=0;
p=2;///改变数码管显示的数字
}
else///k1键没有按动,执行当前流水灯
{
if(k==1)只有当k等于1,执行流水灯,
{
if(i<7)
{
i++;
}
else
{
i=0;
}
PORTB |=0xff;
switch(kind)执行当前样式流水灯
{
case 1:PORTB &=yangshi1[i];
//delay(210);
break;
case 2:PORTB &=yangshi2[i];
//delay(210);
break;
}
}
elsek等于0保持当前样式,暂停流水灯
{}
}
}
}
#pragma interrupt_handler int0_isr:2
void int0_isr(void)///中断0,改变变量k的值决定流水灯的执行或停止
{
if(k==0)
{
k=1;
q=0;//运行时,数码管第一位显示0
}
else
{
k=0;
q=4;//暂停时,数码管第一位显示p,其他位不变
}
}
代码中,流水灯未用到延时函数,原因是如果使用延时函数会影响到数码管动态显示,使得肉眼观察数码管只能看见最后一位,所以用延长数码管显示时间来代替延时函数,能起到与延时函数相同的效果
运行截图