单片
单片机原理及应用
实验报告
专 业 2011级计算机科学与技术
(嵌入式应用技术)
学 号
姓 名
合肥师范学院实验报告
姓名:汪美玲 课程名称:单片机原理及应用 院(系):计算机科学与技术
专业/年级:2011级计算机科学与技术(嵌入式应用技术)
实验一:流水灯实验
一、 实验目的:
通过对P3口地址的操作控制8位LED流水点亮,从而认识单片机的存储器。
二、 实验原理图
实验参考电路图如下:
三、 参考实验程序
//流水灯实验
#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口地址的操作控制8位LED流水点亮,从而认识单片机的存储器。实验过程并不难,主要是理解实验原理。在完成思考题中,通过修改实验代码实现使LED灯为18灯亮——27灯亮——36灯亮——45灯亮,再将LED灯亮的顺序倒过来既:45灯亮——36灯亮——27灯亮——18灯亮,连续运行。在修改代码过程中认识到代码编写还不够熟练,在课后应该继续练习。
合肥师范学院实验报告
姓名:汪美玲 课程名称:单片机原理及应用 院(系):计算机科学与技术
专业/年级:2011级计算机科学与技术(嵌入式应用技术)
实验二:中断实验
一、 实验目的:
通过对P3.2、P3.3引脚的电平控制,实现外部中断处理,从而控制输出口P1的输出效果变化。
二、 实验原理图
实验参考电路图如下:
图一
三、 参考实验程序
/用外中断0的中断方式进行数据采集和处理
#include
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
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.2、P3.3引脚的电平控制,实现外部中断处理,从而控制输出口P1的输出效果变化。通过运行参考程序实现实验效果较轻松。在思考题中,要求能利用两个外部中断,体现不同中断优先级的中断源的相应情况。根据给出实验原理内容,加上一个新的中断。在主函数中,设置关于中断的响应初始化设置,采用EX0=1,EX1=1来允许两个中断,PX0=0;PX1=1来区分中断的优先级。本次实验后还需继续复习有关中断的相关内容,才能更好理解其中原理。
合肥师范学院实验报告
姓名:汪美玲 课程名称:单片机原理及应用 院(系):计算机科学与技术
专业/年级:2011级计算机科学与技术(嵌入式应用技术)
实 验 三:定时器/计数器实验
一、实验目的
通过使用定时器T0的中断来控制P2.0引脚的的LED的灯闪烁,要求闪烁时间2S,既亮1 S,灭1 S。
二、实验原理图
实验参考电路图如下(注释,下图只有D1等闪烁,既亮1 S,灭1 S):
图一
三、参考实验程序
#include
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; //将Countor清0,重新从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
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
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循环显示设计
一、 实验目的:
采用1602型LCD循环显示字符串“Welcome to Heifei Normal University”。其中LCD显示模式为:
16*2显示、5*7点阵、8位数据口;
显示开、有光标开且光标闪烁;
光标右移,字符不移。
二、 实验原理图
实验参考电路图如下:
三、 参考实验程序
//用LCD循环右移显示" Welcome to Heifei Normal University "
#include
#include
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();
}
/*****************************************************
函数功能:判断液晶模块的忙碌状态
返回值:result。result=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; //根据规定,RS和R/W同时为低电平时,可以写入指令
RW=0;
E=0; //E置低电平(根据表8-6,写指令时,E为高脉冲,
// 就是让E从0到1发生正跳变,所以应先置"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为高脉冲,
// 就是让E从0到1发生正跳变,所以应先置"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
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();
}
/*函数功能:判断液晶模块的忙碌状态
返回值:result。result=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; //根据规定,RS和R/W同时为低电平时,可以写入指令
RW=0;
E=0; //E置低电平(根据表8-6,写指令时,E为高脉冲,
// 就是让E从0到1发生正跳变,所以应先置"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为高脉冲,
// 就是让E从0到1发生正跳变,所以应先置"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);
}
}
五 实验总结:
本次实验采用1602型LCD循环显示字符串“Welcome to Heifei Normal University”。其中LCD显示模式为:16*2显示、5*7点阵、8位数据口;显示开、有光标开且光标闪烁;光标右移,字符不移。在实验过程中遇到一些问题:LCD显示的字符没有居中,需要修改代码中各个字符显示的地址。最终修改代码,而是在显示的字符中加入别的符号来调整字符位置。试验后认识到自己对实验原理掌握不够,需复习教材中相关内容。
合肥师范学院实验报告
姓名:汪美玲 课程名称:单片机原理及应用 院(系):计算机科学与技术
专业/年级:2011级计算机科学与技术(嵌入式应用技术)
实 验 七:简易计算器
一、 实验目的
掌握89C51单片机开发应用系统的方法和应用程序的编写和调试
要求:由P1口输出字形码,P0口输出字位码。先将存放于30H单元的数值个位七段码由P1口输出,同时P0口输出使数值个位显示数码管点亮的字位码。由于采用的是共阳数码管,所以只有该位数码管对应的P0.0为1,其他位P0.1-P0.3位0,点亮延时10MS。然后P1口输出数值十位七段码,P0.1位1,数值十位数码管点亮,延时10MS。接着P1口输出数值百位七段码,P0.2为1,数值百位数码管点亮,延时10MS。最后P1口输出数值千位七段码,P0.3为1,数值千位数码管点亮,延时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格式