单片机原理实验报告

发布时间:2014-08-31 19:01:57   来源:文档文库   
字号:

单片

单片机原理及应用

实验报告

2011级计算机科学与技术

(嵌入式应用技术)



合肥师范学院实验报告

姓名:汪美玲 课程名称:单片机原理及应用 院(系):计算机科学与技术

专业/年级2011级计算机科学与技术(嵌入式应用技术)

实验一:流水灯实验

一、 实验目的:

通过对P3口地址的操作控制8LED流水点亮,从而认识单片机的存储器。

二、 实验原理图

实验参考电路图如下:

三、 参考实验程序

//流水灯实验

#include //包含单片机寄存器的头文件

sfr x=0xb0; //P3口在存储器中的地址是b0H 通过sfr可定义8051内核单片机

//的所有内部8位特殊功能寄存器,对地址x的操作也就是对P1口的操作

/****************************************

函数功能:延时一段时间

*****************************************/

void delay(void)

{

unsigned char i,j;

for(i=0;i<250;i++)

for(j=0;j<250;j++)

; //利用循环等待若干机器周期,从而延时一段时间

}

/*****************************************

函数功能:主函数

******************************************/

void main(void)

{

while(1)

{

x=0xfe; //第一个灯亮

delay(); //调用延时函数

x=0xfd; //第二个灯亮

delay(); //调用延时函数

x=0xfb; //第三个灯亮

delay(); //调用延时函数

x=0xf7; //第四个灯亮

delay(); //调用延时函数

x=0xef; //第五个灯亮

delay(); //调用延时函数

x=0xdf; //第六个灯亮

delay(); //调用延时函数

x=0xbf; //第七个灯亮

delay(); //调用延时函数

x=0x7f; //第八个灯亮

delay(); //调用延时函数

}

}

四、 实验思考题:

修改程序使LED灯为18灯亮——27灯亮——36灯亮——45灯亮,再将LED灯亮的顺序倒过来既:45灯亮——36灯亮——27灯亮——18灯亮,连续运行。

调试后的程序代码:

#include

sfr x=0xb0;

void delay(void)

{

int i,j;

for(i=0;i<250;i++)

for(j=0;j<250;j++)

;

}

void main(void)

{

while(1)

{

x=0x7e;

delay();

x=0xbd;

delay();

x=0xdb;

delay();

x=0xe7;

delay();

x=0xdb;

delay();

x=0xbd;

delay();

x=0x7e;

delay();

}

}

五、 实验总结

本次实验室我首次接触单片机仿真实验通过对P3口地址的操作控制8LED流水点亮,从而认识单片机的存储器。实验过程并不难,主要是理解实验原理。在完成思考题中,通过修改实验代码实现使LED灯为18灯亮——27灯亮——36灯亮——45灯亮,再将LED灯亮的顺序倒过来既:45灯亮——36灯亮——27灯亮——18灯亮,连续运行。在修改代码过程中认识到代码编写还不够熟练,在课后应该继续练习。

合肥师范学院实验报告

姓名:汪美玲 课程名称:单片机原理及应用 院(系):计算机科学与技术

专业/年级2011级计算机科学与技术(嵌入式应用技术)

实验中断实验

一、 实验目的:

通过对P3.2P3.3引脚的电平控制,实现外部中断处理,从而控制输出口P1的输出效果变化

二、 实验原理图

实验参考电路图如下:

图一

三、 参考实验程序

/用外中断0的中断方式进行数据采集和处理

#include //包含51单片机寄存器定义的头文件

sbit S=P3^2; //S位定义为P3.2

/*******************************************

函数功能:主函数

******************************************/

void main(void)

{

EA=1; //开放总中断

EX0=1; //允许使用外中断

IT0=1; //选择负跳变来触发外中断

P1=0xff;

while(1)

; //无限循环, 防止程序跑飞

}

/**************************************************************

函数功能:外中断T0的中断服务程序

**************************************************************/

void int0(void) interrupt 0 using 0 //外中断0的中断编号为0

{

P1=~P1; //每产生一次中断请求,P1取反一次。

}

图二

四、 实验思考题:

根据指导书中提供的原理图,自行设计一个外部中断实验,要求:

1. 两个外部中断全部用上;

2. 实验能体现不同中断优先级的中断源的相应情况;

3. 不同中断处理程序能输出不同的响应效果

//用外中断0的中断方式进行数据采集和处理

#include //包含51单片机寄存器定义的头文件

sbit S=P3^2; //S位定义为P3.2

void main(void)

{

EA=1; //开放总中断

EX0=1; //允许使用外中断

EX1=1;

IT0=1; //选择负跳变来触发外中断

IT1=1;

PX0=0;

PX1=1;

P1=0xff;

while(1)

; //无限循环, 防止程序跑飞

}

函数功能:外中断T0的中断服务程序

void int0(void) interrupt 0 using 0 //外中断0的中断编号为0

{

P1=~P1; //每产生一次中断请求,P1取反一次。

}

void int1(void) interrupt 2 using 1 //外中断0的中断编号为0

{

P1=0xf0;

}

五、 实验总结

本次试验是通过对P3.2P3.3引脚的电平控制,实现外部中断处理,从而控制输出口P1的输出效果变化。通过运行参考程序实现实验效果较轻松。在思考题中,要求能利用两个外部中断,体现不同中断优先级的中断源的相应情况。根据给出实验原理内容,加上一个新的中断在主函数中,设置关于中断的响应初始化设置,采用EX0=1EX1=1来允许两个中断,PX0=0PX1=1来区分中断的优先级。本次实验后还需继续复习有关中断的相关内容,才能更好理解其中原理。

合肥师范学院实验报告

姓名:汪美玲 课程名称:单片机原理及应用 院(系):计算机科学与技术

专业/年级2011级计算机科学与技术(嵌入式应用技术)

定时器/计数器实验

一、实验目的

通过使用定时器T0的中断来控制P2.0引脚的的LED的灯闪烁,要求闪烁时间2S,既亮1 S,灭1 S

二、实验原理图

实验参考电路图如下(注释,下图只有D1等闪烁,既亮1 S,灭1 S)

图一

三、参考实验程序

#include // 包含51单片机寄存器定义的头文件

sbit D1=P2^0; //D1位定义为P2.0引脚

unsigned char Countor; //设置全局变量,储存定时器T0中断次数

/**************************************************************

函数功能:主函数

**************************************************************/

void main(void)

{

EA=1; //开总中断

ET0=1; //定时器T0中断允许

TMOD=0x01; //使用定时器T0的模式2

TH0=(65536-50000)/256; //定时器T0的高8位赋初值

TL0=(65536-50000)%256; //定时器T0的高8位赋初值

TR0=1; //启动定时器T0

Countor=0; //0开始累计中断次数

while(1)//无限循环等待中断

;

}

/**************************************************************

函数功能:定时器T0的中断服务程序

**************************************************************/

void Time0(void) interrupt 1 using 0 //"interrupt"声明函数为中断服务函数

//其后的1为定时器T0的中断编号;0表示使用第0组工作寄存器

{

Countor++; //中断次数自加1

if(Countor==20) //若累计满20次,即计时满1s

{

D1=~D1; //按位取反操作,将P2.0引脚输出电平取反

Countor=0; //Countor0,重新从0开始计数

TH0=(65536-50000)/256; //定时器T0的高8位重新赋初值

TL0=(65536-50000)%256; //定时器T0的高8位重新赋初值

}

}

四、实验思考题

修改程序使用定时器T1的中断方式来控制P2.0 P2.1引脚的LED分别以200mshe 800ms的周期闪烁

图二

调试后的程序代码:

#include

sbit D1=P2^0;

sbit D2=P2^1;

unsigned char Countor1,Countor2;

void main(void)

{

EA=1;

ET0=1;

TMOD=0x01;

TH0=(65536-50000)/256;

TL0=(65536-50000)%256;

TR0=1;

Countor1,Countor2=0;

while(1)

;

}

void Time0(void) interrupt 1 using 0

{ Countor1++;Countor2++;

if(Countor1==2)

{ D1=~D1;

Countor1=0;

}

if(Countor2==8)

{ D2=~D2;

Countor2=0;

}

TH0=(65536-50000)/256;

TL0=(65536-50000)%256;

}

、实验总结

本次试验通过使用定时器T0的中断来控制P2.0引脚的的LED的灯闪烁,要求闪烁时间2S,既亮1 S,灭1 S思考题中,修改程序使用定时器T1的中断方式来控制P2.0 P2.1引脚的LED分别以200mshe 800ms的周期闪烁。通过本次试验更加直观形象的理解了定时器/计数器的相关知识。

合肥师范学院实验报告

姓名:汪美玲 课程名称:单片机原理及应用 院(系):计算机科学与技术

专业/年级2011级计算机科学与技术(嵌入式应用技术)

串行口实验

一、 实验目的:

本实验要求单片机U1通过其串行口TXD向单片机U2发送一个数据“oxab”。利用集成电路MAX232将单片机的输出信号转化成能够识别的信号针对发送的实例,再设计一个单片机接受送出数据的过程

二、 实验原理图

单片机发送数据实验参考电路图如图(1):

图(1

三、 参考实验程序

//单片机U1发送数据

#include //包含单片机寄存器的头文件

unsigned char code Tab[ ]={0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F};

//流水灯控制码,该数组被定义为全局变量

/*函数功能:向U2发送一个字节数据*/

void Send(unsigned char dat)

{

SBUF=dat;

while(TI==0)

;

TI=0;

}

/*函数功能:延时约150ms*/

void delay(void)

{ unsigned char m,n;

for(m=0;m<200;m++)

for(n=0;n<250;n++)

;

}

/*函数功能:主函数*/

void main(void)

{ unsigned char i;

TMOD=0x20; //TMOD=0010 0000B,定时器T1工作于方式2

SCON=0x40; //SCON=0100 0000B,串口工作方式1

PCON=0x00; //PCON=0000 0000B,波特率9600

TH1=0xfd; //根据规定给定时器T1赋初值

TL1=0xfd; //根据规定给定时器T1赋初值

TR1=1; //启动定时器T1

while(1)

{ for(i=0;i<8;i++) //模拟检测数据

{

Send(Tab[i]); //发送数据i

delay(); //150ms发送一次数据

}

}

}

//单片机U2接收数据

#include

unsigned char Receive(void)

{ unsigned char dat;

while(RI==0)

;

RI=0;

dat=SBUF;

return dat;

}

void main(void)

{

// unsigned char i;

TMOD=0x20; //TMOD=0010 0000B,定时器T1工作于方式

SCON=0x50; //SCON=0101 0000B,串口工作方式

PCON=0x00; //PCON=0000 0000B,波特率

TH1=0xfd; //根据规定给定时器T1赋初值

TL1=0xfd; //根据规定给定时器T1赋初值

TR1=1; //启动定时器T1

REN=1;//允许接受

while(1)

{

/*

for(i=0;i<8;i++) //模拟检测数据

{

Send(Tab[i]); //发送数据i

delay(); //150ms发送一次数据

}

*/

P1=Receive();

}

}

四、 实验总结

本次实验通过本实验要求单片机U1通过其串行口TXD向单片机U2发送一个数据“oxab”。利用集成电路MAX232将单片机的输出信号转化成能够识别的信号在实验中编写接收端单片机U2时遇到了一定困难,通过实验指导书上发送端U1的代码和在老师的指导下顺利完成。

合肥师范学院实验报告

姓名:汪美玲 课程名称:单片机原理及应用 院(系):计算机科学与技术

专业/年级2011级计算机科学与技术(嵌入式应用技术)

实验五:键盘扫描识别实验

一、 实验目的:

设计一个4X4的矩阵键盘,键盘的号码0~15,要求编写出一个键盘输入扫描程序,要求单片机能根据键盘排列顺序,能将按下去键盘号正确识别出来,并采用两个数码管分别键盘号码的个位和十位。

二、 实验原理图

实验参考电路图如下:

图一

三、 参考实验程序

#include //包含51单片机寄存器定义的头文件

sbit P14=P1^4;

sbit P15=P1^5;

sbit P16=P1^6;

sbit P17=P1^7;

unsigned char code Tab[ ]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //数字0~9的段码

unsigned char keyval;

/**************************************************************

函数功能:数码管动态扫描延时

**************************************************************/

void led_delay(void)

{

unsigned char j;

for(j=0;j<200;j++)

;

}

/**************************************************************

函数功能:按键值的数码管显示子程序

**************************************************************/

void display(unsigned char k)

{

P2=0xbf;

P0=Tab[k/10];

led_delay();

P2=0x7f;

P0=Tab[k%10];

led_delay();

}

/**************************************************************

函数功能:软件延时子程序

**************************************************************/

void delay20ms(void)

{

unsigned char i,j;

for(i=0;i<100;i++)

for(j=0;j<60;j++)

;

}

/**************************************************************

函数功能:主函数

**************************************************************/

void main(void)

{

EA=1;

ET0=1;

TMOD=0x01;

TH0=(65536-500)/256;

TL0=(65536-500)%256;

TR0=1;

keyval=0x00;

while(1)

{

display(keyval);

}

}

/**************************************************************

函数功能:定时器0的中断服务子程序,进行键盘扫描,判断键位

**************************************************************/

void time0_interserve(void) interrupt 1 using 1

{

TR0=0;

P1=0xf0;

if((P1&0xf0)!=0xf0)

delay20ms();

if((P1&0xf0)!=0xf0)

{

P1=0xfe;

if(P14==0)

keyval=1;

if(P15==0)

keyval=2;

if(P16==0)

keyval=3;

if(P17==0)

keyval=4;

P1=0xfd;

if(P14==0)

keyval=5;

if(P15==0)

keyval=6;

if(P16==0)

keyval=7;

if(P17==0)

keyval=8;

P1=0xfb;

if(P14==0)

keyval=9;

if(P15==0)

keyval=10;

if(P16==0)

keyval=11;

if(P17==0)

keyval=12;

P1=0xf7;

if(P14==0)

keyval=13;

if(P15==0)

keyval=14;

if(P16==0)

keyval=15;

if(P17==0)

keyval=16;

}

TR0=1;

TH0=(65536-500)/256;

TL0=(65536-500)%256;

}

四、 实验思考题:

修改实验电路图和实验程序和设计电路,改成静态显示

电路图:

图二

调试后的程序代码:

#include //包含51单片机寄存器定义的头文件

sbit P14=P1^4;

sbit P15=P1^5;

sbit P16=P1^6;

sbit P17=P1^7;

unsigned char code Tab[ ]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //数字0~9的段码

unsigned char keyval;

/**************************************************************

函数功能:按键值的数码管显示子程序

**************************************************************/

void display(unsigned char k)

{

P2=0x3f;

P0=Tab[k/10];

P3=Tab[k%10];

}

/**************************************************************

函数功能:软件延时子程序

**************************************************************/

void delay20ms(void)

{

unsigned char i,j;

for(i=0;i<100;i++)

for(j=0;j<60;j++)

;

}

/**************************************************************

函数功能:主函数

**************************************************************/

void main(void)

{

EA=1;

ET0=1;

TMOD=0x01;

TH0=(65536-500)/256;

TL0=(65536-500)%256;

TR0=1;

keyval=0x00;

while(1)

{

display(keyval);

}

}

/**************************************************************

函数功能:定时器0的中断服务子程序,进行键盘扫描,判断键位

**************************************************************/

void time0_interserve(void) interrupt 1 using 1

{

TR0=0;

P1=0xf0;

if((P1&0xf0)!=0xf0)

delay20ms();

if((P1&0xf0)!=0xf0)

{

P1=0xfe;

if(P14==0)

keyval=1;

if(P15==0)

keyval=2;

if(P16==0)

keyval=3;

if(P17==0)

keyval=4;

P1=0xfd;

if(P14==0)

keyval=5;

if(P15==0)

keyval=6;

if(P16==0)

keyval=7;

if(P17==0)

keyval=8;

P1=0xfb;

if(P14==0)

keyval=9;

if(P15==0)

keyval=10;

if(P16==0)

keyval=11;

if(P17==0)

keyval=12;

P1=0xf7;

if(P14==0)

keyval=13;

if(P15==0)

keyval=14;

if(P16==0)

keyval=15;

if(P17==0)

keyval=16;

}

TR0=1;

TH0=(65536-500)/256;

TL0=(65536-500)%256;

}

实验总结:

本次试验内容为设计一个4X4的矩阵键盘,键盘的号码0~15。这个试验把我们在日常生活中使用的键盘融入单片机学习中,让我们将学到的内容加以实践。本实验分为动态显示和静态显示,我们应该对其进行区分,并掌握其中原理。

合肥师范学院实验报告

姓名:汪美玲 课程名称:单片机原理及应用 院(系):计算机科学与技术

专业/年级2011级计算机科学与技术(嵌入式应用技术)

六:LCD循环显示设计

一、 实验目的:

采用1602LCD循环显示字符串“Welcome to Heifei Normal University”。其中LCD显示模式为:

16*2显示、5*7点阵、8位数据口;

显示开、有光标开且光标闪烁;

光标右移,字符不移。

二、 实验原理图

实验参考电路图如下:

三、 参考实验程序

//LCD循环右移显示" Welcome to Heifei Normal University "

#include //包含单片机寄存器的头文件

#include //包含_nop_()函数定义的头文件

sbit RS=P2^0; //寄存器选择位,将RS位定义为P2.0引脚

sbit RW=P2^1; //读写选择位,将RW位定义为P2.1引脚

sbit E=P2^2; //使能信号位,将E位定义为P2.2引脚

sbit BF=P0^7; //忙碌标志位,,将BF位定义为P0.7引脚

unsigned char code string[ ]={" Welcome to Heifei Normal University "};

/*****************************************************

函数功能:延时1ms

(3j+2)*i=(3×33+2)×10=1010(微秒),可以认为是1毫秒

***************************************************/

void delay1ms()

{

unsigned char i,j;

for(i=0;i<10;i++)

for(j=0;j<33;j++)

;

}

/*****************************************************

函数功能:延时若干毫秒

入口参数:n

***************************************************/

void delay(unsigned char n)

{

unsigned char i;

for(i=0;i

delay1ms();

}

/*****************************************************

函数功能:判断液晶模块的忙碌状态

返回值:resultresult=1,忙碌;result=0,不忙

***************************************************/

unsigned char BusyTest(void)

{

bit result;

RS=0; //根据规定,RS为低电平,RW为高电平时,可以读状态

RW=1;

E=1; //E=1,才允许读写

_nop_(); //空操作

_nop_();

_nop_();

_nop_(); //空操作四个机器周期,给硬件反应时间

result=BF; //将忙碌标志电平赋给result

E=0;

return result;

}

/*****************************************************

函数功能:将模式设置指令或显示地址写入液晶模块

入口参数:dictate

***************************************************/

void WriteInstruction (unsigned char dictate)

{

while(BusyTest()==1); //如果忙就等待

RS=0; //根据规定,RSR/W同时为低电平时,可以写入指令

RW=0;

E=0; //E置低电平(根据表8-6,写指令时,E为高脉冲,

// 就是让E01发生正跳变,所以应先置"0"

_nop_();

_nop_(); //空操作两个机器周期,给硬件反应时间

P0=dictate; //将数据送入P0口,即写入指令或地址

_nop_();

_nop_();

_nop_();

_nop_(); //空操作四个机器周期,给硬件反应时间

E=1; //E置高电平

_nop_();

_nop_();

_nop_();

_nop_(); //空操作四个机器周期,给硬件反应时间

E=0; //E由高电平跳变成低电平时,液晶模块开始执行命令

}

/*****************************************************

函数功能:指定字符显示的实际地址

入口参数:x

***************************************************/

void WriteAddress(unsigned char x)

{

WriteInstruction(x|0x80); //显示位置的确定方法规定为"80H+地址码x"

}

/*****************************************************

函数功能:将数据(字符的标准ASCII)写入液晶模块

入口参数:y(为字符常量)

***************************************************/

void WriteData(unsigned char y)

{

while(BusyTest()==1);

RS=1; //RS为高电平,RW为低电平时,可以写入数据

RW=0;

E=0; //E置低电平(根据表8-6,写指令时,E为高脉冲,

// 就是让E01发生正跳变,所以应先置"0"

P0=y; //将数据送入P0口,即将数据写入液晶模块

_nop_();

_nop_();

_nop_();

_nop_(); //空操作四个机器周期,给硬件反应时间

E=1; //E置高电平

_nop_();

_nop_();

_nop_();

_nop_(); //空操作四个机器周期,给硬件反应时间

E=0; //E由高电平跳变成低电平时,液晶模块开始执行命令

}

/*****************************************************

函数功能:对LCD的显示模式进行初始化设置

***************************************************/

void LcdInitiate(void)

{

delay(15); //延时15ms,首次写指令时应给LCD一段较长的反应时间

WriteInstruction(0x38); //显示模式设置:16×2显示,5×7点阵,8位数据接口

delay(5); //延时5ms 

WriteInstruction(0x38);

delay(5);

WriteInstruction(0x38);

delay(5);

WriteInstruction(0x0f); //显示模式设置:显示开,有光标,光标闪烁

delay(5);

WriteInstruction(0x06); //显示模式设置:光标右移,字符不移

delay(5);

WriteInstruction(0x01); //清屏幕指令,将以前的显示内容清除

delay(5);

}

void main(void) //主函数

{ unsigned char i;

LcdInitiate(); //调用LCD初始化函数

delay(10);

while(1)

{

WriteInstruction(0x01);//清显示:清屏幕指令

WriteAddress(0x00); // 设置显示位置为第一行的第5个字

i = 0;

while(string[i] != '\0')

{ // 显示字符

WriteData(string[i]);

i++;

delay(150);

}

for(i=0;i<4;i++)

delay(250);

}

}

四、 实验思考题:

试编写LCD12864显示初始化程序,设计电路,采用汉字取模,使LCD循环显示字符串hefei normal university和个人学号、姓名。

要求:

1. 字符分为两行,居中显示

2. 字符从左向右缓慢移动

调试后的程序代码:

#include //包含单片机寄存器的头文件

#include //包含_nop_()函数定义的头文件

sbit RS=P2^0; //寄存器选择位,将RS位定义为P2.0引脚

sbit RW=P2^1; //读写选择位,将RW位定义为P2.1引脚

sbit E=P2^2; //使能信号位,将E位定义为P2.2引脚

sbit BF=P0^7; //忙碌标志位,,将BF位定义为P0.7引脚

unsigned char code string[ ]={" *********1110441057********"};

unsigned char code string1[ ]={" ********wangmeiling********"};

/*函数功能:延时1ms

(3j+2)*i=(3×33+2)×10=1010(微秒),可以认为是1毫秒*/

void delay1ms()

{

unsigned char i,j;

for(i=0;i<10;i++)

for(j=0;j<33;j++)

;

}

/*****************************************************

函数功能:延时若干毫秒 入口参数:n

***************************************************/

void delay(unsigned char n)

{ unsigned char i;

for(i=0;i

delay1ms();

}

/*函数功能:判断液晶模块的忙碌状态

返回值:resultresult=1,忙碌;result=0,不忙*/

unsigned char BusyTest(void)

{

bit result;

RS=0; //根据规定,RS为低电平,RW为高电平时,可以读状态

RW=1;

E=1; //E=1,才允许读写

_nop_(); //空操作

_nop_();

_nop_();

_nop_(); //空操作四个机器周期,给硬件反应时间

result=BF; //将忙碌标志电平赋给result

E=0;

return result;

}

/*函数功能:将模式设置指令或显示地址写入液晶模块 入口参数:dictate*/

void WriteInstruction (unsigned char dictate)

{ while(BusyTest()==1); //如果忙就等待

RS=0; //根据规定,RSR/W同时为低电平时,可以写入指令

RW=0;

E=0; //E置低电平(根据表8-6,写指令时,E为高脉冲,

// 就是让E01发生正跳变,所以应先置"0"

_nop_();

_nop_(); //空操作两个机器周期,给硬件反应时间

P0=dictate; //将数据送入P0口,即写入指令或地址

_nop_();

_nop_();

_nop_();

_nop_(); //空操作四个机器周期,给硬件反应时间

E=1; //E置高电平

_nop_();

_nop_();

_nop_();

_nop_(); //空操作四个机器周期,给硬件反应时间

E=0; //E由高电平跳变成低电平时,液晶模块开始执行命令

}

/*函数功能:指定字符显示的实际地址 入口参数:x*/

void WriteAddress(unsigned char x)

{

WriteInstruction(x|0x80); //显示位置的确定方法规定为"80H+地址码x"

}

/*函数功能:将数据(字符的标准ASCII)写入液晶模块

入口参数:y(为字符常量)*/

void WriteData(unsigned char y)

{ while(BusyTest()==1);

RS=1; //RS为高电平,RW为低电平时,可以写入数据

RW=0;

E=0; //E置低电平(根据表8-6,写指令时,E为高脉冲,

// 就是让E01发生正跳变,所以应先置"0"

P0=y; //将数据送入P0口,即将数据写入液晶模块

_nop_();

_nop_();

_nop_();

_nop_(); //空操作四个机器周期,给硬件反应时间

E=1; //E置高电平

_nop_();

_nop_();

_nop_();

_nop_(); //空操作四个机器周期,给硬件反应时间

E=0; //E由高电平跳变成低电平时,液晶模块开始执行命令

}

/*函数功能:对LCD的显示模式进行初始化设置*/

void LcdInitiate(void)

{

delay(15); //延时15ms,首次写指令时应给LCD一段较长的反应时间

WriteInstruction(0x38); //显示模式设置:16×2显示,5×7点阵,8位数据接口

delay(5); //延时5ms 

WriteInstruction(0x38);

delay(5);

WriteInstruction(0x38);

delay(5);

WriteInstruction(0x0f); //显示模式设置:显示开,有光标,光标闪烁

delay(5);

WriteInstruction(0x06); //显示模式设置:光标右移,字符不移

delay(5);

WriteInstruction(0x01); //清屏幕指令,将以前的显示内容清除

delay(5);

}

void main(void) //主函数

{

unsigned char i,j;

LcdInitiate(); //调用LCD初始化函数

delay(10);

while(1)

{

WriteInstruction(0x01);//清显示:清屏幕指令

WriteAddress(0x00); // 设置显示位置为第一行的第5个字

i = 0;

while(string[i] != '\0')

{ // 显示字符

WriteData(string[i]);

i++;

delay(150);

}

WriteAddress(0x40); // 设置显示位置为第一行的第5个字

j = 0;

while(string1[j] != '\0')

{ // 显示字符

WriteData(string1[j]);

j++;

delay(150);

}

for(i=0;i<4;i++)

delay(250);

}

}

实验总结:

本次实验采用1602LCD循环显示字符串“Welcome to Heifei Normal University”。其中LCD显示模式为:16*2显示、5*7点阵、8位数据口;显示开、有光标开且光标闪烁;光标右移,字符不移。在实验过程中遇到一些问题:LCD显示的字符没有居中,需要修改代码中各个字符显示的地址。最终修改代码,而是在显示的字符中加入别的符号来调整字符位置。试验后认识到自己对实验原理掌握不够,需复习教材中相关内容。

合肥师范学院实验报告

姓名:汪美玲 课程名称:单片机原理及应用 院(系):计算机科学与技术

专业/年级2011级计算机科学与技术(嵌入式应用技术)

七:简易计算器

一、 实验目的

掌握89C51单片机开发应用系统的方法和应用程序的编写和调试

要求:由P1口输出字形码,P0口输出字位码。先将存放于30H单元的数值个位七段码由P1口输出,同时P0口输出使数值个位显示数码管点亮的字位码。由于采用的是共阳数码管,所以只有该位数码管对应的P0.01,其他位P0.1-P0.30,点亮延时10MS。然后P1口输出数值十位七段码,P0.11,数值十位数码管点亮,延时10MS。接着P1口输出数值百位七段码,P0.21,数值百位数码管点亮,延时10MS。最后P1口输出数值千位七段码,P0.31,数值千位数码管点亮,延时10MS

二、 实验原理图

三、 参考实验程序

#include

#include

#define uchar unsigned char

#define uint unsigned int

char translate(int keycode);

void arithmetic();

void init_LCM();

void write_data(char ddata);

void write_com(char command);

void check_BF();

void clearLCD();

void display(long a);

void dealerror();

void dataoverflow();

void dealquyu();

uchar Keyscan(void);

void Delay_1ms(uint x) ;

/***定义变量和数组*******/

long x=0,y=0,num=0;

int operators,input,iny=0;

char key;

char error[5]="error";

char overflow[8]="overflow";

sbit EN=P3^4;

sbit R_W=P3^5;

sbit RS=P3^6;

/******主函数******/

main()

{

uchar Key_Value = 16, Key_Temp1, Key_Temp2;

EA=1;

EX0=1;

IT0=1;

P2 = 0xff;

display(0);

init_LCM();

write_data(0x30+num);

while(1)

{

P2 = 0xff;

Key_Temp1=Keyscan(); //先读入按键

if(Key_Temp1!= 16) //如果有键按下

{

Delay_1ms(10); //延时一下

Key_Temp2 = Keyscan(); //再读一次按键

if (Key_Temp1 == Key_Temp2)

{//必须是两次相等

Delay_1ms(10);

Key_Value= Key_Temp1; //才保存下来,这就是消除抖动

key=translate(Key_Value);

if(key<='9'&&key>='0') //判断按下的键是否为数值

{

num=num*10+(key-'0');

if (operators>0)

{

y=num;

iny=1;

}

else

x=num;

if(num<134217728&&num>-134217728) //当前数值是否超出限定范围

{

display(num);

}

else

dataoverflow();

}

else

{

switch(key)

{

case 'c':

x=0;

y=0;

num=0;

iny=0;

operators=0;

display(num);

break;

case '=':

arithmetic();

iny=0;

operators=0;

num=0;

break;

case '+':

if (operators)

arithmetic();

operators=1;

num=0;

break;

case '-':

if (operators)

arithmetic();

operators=2;

num=0;

break;

case '*':

if (operators)

arithmetic();

operators=3;

num=0;

break;

case '/':

if (operators)

arithmetic();

operators=4;

num=0;

break;

}

}

while(Keyscan()<16) //等待按键释放

{

//display(Key_Value); //等待期间显示键值

}

//display(Key_Value);

}

}

//display(num);

}

}

/***键值转化为键盘上按键值函数******/

uchar Keyscan(void)

{

uchar i, j, temp, Buffer[4] = {0xef, 0xdf, 0xbf, 0x7f};

for(j = 0; j < 4; j++)

{ //循环四次

P2 = Buffer[j]; //P1高四位分别输出一个低电平

temp = 0x01; //计划先判断P1.0

for(i = 0; i < 4; i++)

{ //循环四次

if(!(P2 & temp)) //P1低四位,截取1

return (i + j * 4); //返回取得的按键值

temp <<= 1; //判断的位,左移一位

}

}

return 16; //判断结束,没有键按下,返回16

}

char translate(int keycode)

{

switch(keycode)

{

case 0:

return '7';

break;

case 1:

return '4';

break;

case 2:

return '1';

break;

case 3:

return 'c';

break;

case 4:

return '8';

break;

case 5:

return '5';

break;

case 6:

return '2';

break;

case 7:

return '0';

break;

case 8:

return '9';

break;

case 9:

return '6';

break;

case 10:

return '3';

break;

case 11:

return '=';

break;

case 12:

return '/';

break;

case 13:

return '*';

break;

case 14:

return '-';

break;

case 15:

return '+';

break;

//case 16:

//return ' ';

//break;

}

}

/***算术运算函数****/

void arithmetic()

{

if (iny)

{

switch(operators)

{

case 1:

x=x+y;

num=x;

if(num<134217728&&num>-134217728)

{

display(num);

}

else

dataoverflow();

break;

case 2:

x=x-y;

num=x;

if(num<134217728&&num>-134217728)

{

display(num);

}

else

dataoverflow();

break;

case 3:

x=x*y;

num=x;

if(num<134217728&&num>-134217728)

{

display(num);

}

else

dataoverflow();

break;

case 4:

if (y==0)

dealerror();

else

if (x%y!=0)

{

dealquyu();

}

else

{

x=x/y;

num=x;

if(num<134217728&&num>-134217728)

{

display(num);

}

else

dataoverflow();

}

break;

}

y=0;

}

}

/**LCD显示程序设计/*LCD初始化函数******/

void init_LCM()

{

write_com(0x30);

write_com(0x30);

write_com(0x30);

write_com(0x38);

write_com(0x08);

write_com(0x01);

write_com(0x06);

write_com(0x0e);

}

/***********LCD写数据函数*************/

void write_data(char ddata)

{

RS=1;/*写指令*/

R_W=0;

EN=1;/*使能信号开*/

P1=ddata;/*将数据送入p1*/

EN=0;/*使能信号关*/

check_BF();

}

/*LCD写指令函数**/

void write_com(char command)

{

RS=0;/*写指令*/

R_W=0;

EN=1;/*使能信号开*/

P1=command;/*将数据送入p1*/

EN=0;/*使能信号关*/

check_BF();

}

/**LCD检查忙碌函数***/

void check_BF()

{

char i,x=0x80;

P1=0xff;

while(x&0x80)

{

RS=0;

R_W=1;

EN=1;

x=P1;

EN=0;

for (i=0;i<10;i++);

}

EN=0;/*关闭使能信号*/

}

/**********LCD清屏函数**********/

void clearLCD()

{

write_com(0x01);

}

/**LCD显示函数**********/

void display(long a)

{

long temp,b,c=-1;

int lenth=1,i,j;

clearLCD();

if(a<0)

{

a=a*c;

write_data('-');

}

temp=a;

while((temp=temp/10)!=0)

{

lenth++;

}

for(i=lenth;i>0;i--)

{

b=1;

for(j=0;j

{

b=b*10;

}

write_data(0x30+a/b);

a=a%b;

本文来源:https://www.2haoxitong.net/k/doc/24b886a4941ea76e58fa0498.html

《单片机原理实验报告.doc》
将本文的Word文档下载到电脑,方便收藏和打印
推荐度:
点击下载文档

文档为doc格式