单片机原理与应用

课程名称:    单片机原理与应用

设计题目:    LCD电子钟

院    系:    电子信息工程学院

班    级:    自动化0706

设 计 者:    全宏宇

指导教师:

一,设计目标

LCD显示电子钟的基本功能

1,实现时钟功能;

2,实现闹铃功能;

3,实现秒表功能;

4,具有一定的计时精度。

LCD显示电子钟的基本要求

1,掌握单片机开发编程设计的基本流程;

2,了解Keil及Proteus软件的基本使用;

3,了解LCD的基本使用;

4,学习单片机硬件制作。

二,具体实现

1,软件平台

1)Keil编程

Keil 的开发工具的使用的基本过程:

○1创建 C 或汇编语言的源程序;

○2编译或汇编源文件;

○3纠正源文件中的错误;

○4从编译器和汇编器连接目标文件;

○5测试连接的应用程序。

2)Proteus仿真

Proteus软件不仅具有其它EDA工具软件的仿真功能,还能仿真单片机及外围器件。它是目前最好的仿真单片机及外围器件的工具。在编译方面,它也支持IAR,Keil,PLAB等多种编译器。

2,硬件开发平台

JD51开发板的基本资料

○1 LED 电路,8 只独立LED 发光管,可做指示或各种闪烁效果用。

○2 数码管电路,4只共阳一体8 段数码显示管,可实现各种数据显示,如计数、时钟等。

○3蜂鸣器电路,可用于设计各种提示音、演奏音乐等。

○4键盘电路,学习按键控制相关编程。

○5 LCD 显示电路,编程控制LCD 显示。

○6串口电路,学习编程实现JD51 和PC 或其他符合该通信协议的电路之间的通信。

○7红外电路,通过选配的红外遥控器,学习红外解码并可实现红外遥控JD51。

○8 温度模块电路,采用一线式温度传感器实现温度的采集并可显示在数码管或者LCD 上,通过温度数据处理便可实现温度控制器功能。

○9除了以上提到的可编程电路本学习板还有一些常用的不可编程电路,包括电源电路、复位电路、晶振电路等。

本次LCD电子钟实验用到其中的蜂鸣器,按键,LCD显示接口。

3,总体设计

1)        基本资源的使用

本次实验采用了89C52型单片机,1602LCD液晶显示屏,蜂鸣器。为了实现时钟,定时,闹钟,秒表的功能,用到了单片机的外部中断,计时器中断,及

I/O端口.

资源        功能

外部中断        外部中断INT1            模式选择(时钟,调时,秒表,闹钟)

外部中断INT0            秒表的暂停,清零

定时器        定时器T0            秒表,时钟定时基准

定时器T1            音乐闹铃的音符产生

I/O端口        P1,P2            LCD接口,蜂鸣器

2)软件仿真

(1)程序设计的一些关键问题(具体参照后面的程序清单)

○1建立Keil工程时,注意对程序编译环境进行设置;

设置内容包括器件,频率,产生hex文件等。

○2LCD管脚及控制字;

LCD管脚的定义

控制字

1602液晶模块的读写操作,屏幕和光标的操作都是通过指令编程来实现的。

指令1:清显示,指令码01H,光标复位到地址00H位置

指令2:光标复位,光标返回到地址00H

指令3:光标和显示位置设置I/D,光标移动方向,高电平右移,低电平左移,S:屏幕上所有文字是否左移或右移,高电平表示有效,低电平表示无效。

指令4:显示开关控制。D:控制整体的显示开与关,高电平表示开显示,低电平表示关显示。C:控制光标的开与关,高电平表示有光标,低电平表示无光标 B:控制光标是否闪烁,高电平闪烁,低电平不闪烁。

指令5:光标或显示移位 S/C :高电平时显示移动的文字,低电平时移动光标

指令6:功能设置命令 DL:高电平时为4位总线,低电平时为8位总线 N:低电平时为单行显示,高电平时为双行显示,F:低电平时显示5X7的点阵字符,高电平时显示5X10的显示字符。

指令7:字符发生器RAM地址设置。

指令8:DDRAM地址设置。

指令9:读忙信号和光标地址 BF:忙标志位,高电平表示忙,此时模块不能接收命令或数据,如果为低电平表示不忙。

○3LCD实现滚动显示;

方法一:采用LCD1602控制命令,显示后画面移动一个字符;

方法二:循环使用显示不同位置,形成滚动效果。

○5秒表

主要是产生计时基准0.01秒,有了基准之后需要解决的问题是如何实现有效的暂停,清零(达到精准动作),采用中断是很不错的结果。

○6闹铃

主要是如何实现闹铃关闭的逻辑,if(f&&g)语句可以实现这一动作。

○7提高计时精度

本程序除了调时模式外,其他模式的时候时钟都在跑动,提高了因模式转换而导致的时间精度降低。

(2)Proteus仿真

在Proteus中画出如下电路图,添加hex文件,进行虚拟仿真。

2)        开发板运行调试

在JD51板上烧制程序,根据实际的效果,对中断的反应时间,显示效果做出了调整,整体效果不错,只是音乐的效果不佳,主要是由于如果将蜂鸣器换成扬声器效果会好些,还可以在程序中增加节拍来增加音乐效果。

4,硬件制作

根据仿真电路图购买元件进行焊接,下载程序效果后,液晶显示器显示乱码,检查电路后已无连接错误,但功能依然没有实现,相关检查在进行中。

三,设计体会

本次课程设计系统地学习了单片编程开发及实际电路的制作。学习了Keil的C语言编程的基本知识,Proteus仿真软件的模拟仿真,JD51开发实验板的使用,本次课设,时间了较多的其他案例,比较全面的掌握了单片机的运营,包括编程,电路,LCD器件等,在知识上有了很多的长进。

本次课程设计还有很多其他收获,锻炼了自学的能力,特别是动手实践方面的东西,让我深深感受到理论与实际的差距,实际当中会有一些小的问题,这些问题是意想不到的,需要去思考,去解决,这是很锻炼人的。

四,程序

#include

#include

#define uchar unsigned char

#define ulong unsigned long

#define uint  unsigned int

uchar idata     welcome[16]={"    clock       "};                //定义第一行显示数组

uchar idata   lwelcome[16]={"      clock     "};                //定义第一行显示数组

uchar idata   llwelcome[16]={"        clock   "};                //定义第一行显示数组

uchar idata  lllwelcome[16]={"          clock "};                //定义第一行显示数组

uchar  idata  sslcdtimer[16]={"    00:00:00    "};

uchar  idata tsslcdtimer[16]={"    00:00:00    "};

uchar  idata   lcdtimer[16]={"    00:00:00    "};                //定义第二行显示数组

uchar  idata  mlcdtimer[16]={"    00:  :      "};                //定义第二行显示数组

uchar  idata   hlcdtimer[16]={"      :00:      "};                //定义第二行显示数组

uchar  idata  setlcdtimer[16]={"    00:01:00    "};

uchar timecount;

uchar temps;

bit timeflag;

bit sstimeflag;

sbit ring=P2^0;//蜂鸣闹铃

sbit e=P2^7;//LCD显示器E

sbit rw=P2^6;//LCD显示器RW

sbit rs=P2^5;//LCD显示器RS

sbit P10=P1^0; //测试用闪灯

sbit Key=P3^2;//秒表暂停,清零

sbit Key0=P3^3;//调时,设定闹钟时间,秒表选择

sbit Key1=P3^4;//调时,设定闹钟时间改变

uchar th1_f; //在中断中装载的T0的值高8位

uchar tl1_f; //在中断中装载的T0的值低8位

uint m=0;

uint n=0;

ulong i;

uint f=0,g=1;

uint j,k;

uchar code freq[3][14]=

{

{0xF2,0x42,

0xF3,0xC1,

0xF5,0x17,

0xF5,0xB6,

0xF6,0xD0,

0xF7,0xD1,

0xF8,0xB6},

{0xF9,0x21,

0xF9,0xE0,

0xFA,0x8B,

0xFA,0xD7,

0xFB,0x68,

0xFB,0xE8,

0xFC,0x5B },

{0xFC,0x8D,

0xFC,0xEE,

0xFD,0x44,

0xFD,0x6D,

0xFD,0xB4,

0xFD,0xF4,

0xFE,0x2D},

};         //音乐频率表,低音,中音,高音,系统振荡频率11.0592MHz

uint code song1[]={26,25,23,25,31,26,25,26,23,25,26,25,23,22,21,16,25,23,22,22,23,23,23,26,23,22,21,25,23,22,21,16,21,15,26,25,23,25,31,26,25,26,23,25,26,25,23,22,21,16,25,23,22,22,23,23,23,26,23,22,21,25,23,22,21,16,21,15};

//编制音乐

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

//软件延时函数(系统晶振为11.0592MHz),延时时间约为40μs

//入口条件:无符号整型变量del1,最终的延时时间为(del1*40)μs

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

void delay(uint del1)

{

uchar del2;

for(;del1>0;del1--)

for(del2=10;del2>0;del2--);

}

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

//液晶显示器判忙函数

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

void busy()

{

uchar temp;

temp=0x00;

rs=0;

rw=1;

while((temp&0x80)==0x80)

{

P0=0xff;

e=1;

temp=P0;

e=0;

}

}

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

//向液晶显示器写命令函数

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

void WR_Com(uchar temp)

{

busy();

rs=0;

rw=0;

P0=temp;

e=1;

e=0;

}

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

//向液晶显示器写数据函数

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

void WR_Data(uchar num)

{

busy();

rs=1;

rw=0;

P0=num;

e=1;

e=0;

}

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

//向液晶显示器写入显示数据函数

//入口条件:液晶显示器行首地址(指示第一行还是第二行)和待显示数组的首地址

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

//void disp_lcdchar(uchar addr,uchar temp1)

//{

//    WR_Com(addr);

//        delay(100);

//        WR_Data(temp1);

//}

void disp_lcd(uchar addr,uchar *temp1)

{

uchar i;

WR_Com(addr);

delay(100);

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

{

WR_Data(temp1[i]);

delay(100);

}

}

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

//液晶显示器初始化函数

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

void lcd_ini()

{

char i;

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

{

P0=0x30;

rs=0;

rw=0;

e=1;

e=0;

delay(100);

}

P0=0x38;

rs=0;

rw=0;

e=1;

e=0;

delay(100);

}

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

//液晶显示器复位函数

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

void lcd_Reset()

{

WR_Com(0x01);

delay(100);

WR_Com(0x06);

delay(100);

WR_Com(0x0c);

delay(100);

}

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

//外部中断函数,秒表暂停,清零

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

void modess() interrupt 0 using 0

{

delay(10000);

n++;

if(n==3)

n=0;

}

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

//外部中断函数,模式选择

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

void modepp() interrupt 2  using 1

{

delay(30000);

m++;

if(m==6)

n=0;

if(m==7)

m=0;

}

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

//定时/计数器中断函数,1S及0.01S

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

void timer0() interrupt 1  using 2

{

TH0=0xdc;

TL0=0x23;

sstimeflag=1;

if(--timecount==0)

{

timecount=100;

timeflag=1;

}

}

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

//定时/计数器中断函数,装入音乐频率计数初值

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

void timer1() interrupt 3  using 3

{

TL1=tl1_f;TH0=th1_f; //调入预定时值

ring=!ring; //取反音乐输出IO

}

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

//主函数

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

void main()

{

P10=1;

lcd_ini();

lcd_Reset();

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

{

temps=welcome[i];

disp_lcdchar(0x80+1,temps); //LCD 单字符从左到右显示

delay(10000);

}*/

disp_lcd(0x80,welcome);

delay(10000);

disp_lcd(0x80,lwelcome);

delay(10000);

disp_lcd(0x80,llwelcome);

delay(10000);

disp_lcd(0x80,lllwelcome);

delay(10000);

disp_lcd(0x80,llwelcome);

delay(10000);

disp_lcd(0x80,lwelcome);

delay(10000);

disp_lcd(0x80,welcome);        //LCD滚动显示

delay(10000);

disp_lcd(0xc0,lcdtimer);

P10=0;

TMOD=0x11;

TH0=0xdc;

TL0=0x23;

TR0=1;

IE=0x86;

timeflag=0;         //1秒计时标志

sstimeflag=0; //0.01秒计时标志

timecount=100;

while(1)

{

while(m==6)//秒表

{

IE=0x87;

if(n==0) //秒表跑动

{

if(sstimeflag==1)

{

sstimeflag=0;

sslcdtimer[11]+=1;

if(sslcdtimer[11]>=0x3a)

{

sslcdtimer[11]=0x30;

sslcdtimer[10]+=1;

if(sslcdtimer[10]>=0x3a)

{

sslcdtimer[10]=0x30;

sslcdtimer[8]+=1;

if(sslcdtimer[8]>=0x3a)

{

sslcdtimer[8]=0x30;

sslcdtimer[7]+=1;

if(sslcdtimer[7]>=0x36)

{

sslcdtimer[7]=0x30;

}

}

}

}

disp_lcd(0xc0,sslcdtimer);

}

if(n==1)//秒表暂停

{

disp_lcd(0xc0,sslcdtimer);

}

if(n>=2)//秒表清零

{

disp_lcd(0xc0,tsslcdtimer);

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

sslcdtimer[i]=tsslcdtimer[i];

}

}

}

while(m==0||m>=3) //时钟程序,只要不是调时,就一直运行

{

IE=0x86;

if(timeflag==1)

{

timeflag=0;

lcdtimer[11]+=1;

if(lcdtimer[11]>=0x3a)

{

lcdtimer[11]=0x30;

lcdtimer[10]+=1;

if(lcdtimer[10]>=0x36)

{

lcdtimer[10]=0x30;

lcdtimer[8]+=1;

if(lcdtimer[8]>=0x3a)

{

lcdtimer[8]=0x30;

lcdtimer[7]+=1;

if(lcdtimer[7]>=0x36)

{

lcdtimer[7]=0x30;

lcdtimer[5]+=1;

if(lcdtimer[5]>=0x3a)

{

lcdtimer[5]=0x30;

lcdtimer[4]+=1;

if(lcdtimer[4]>=0x33&&lcdtimer[5]>=0x35)

{

lcdtimer[5]=0x30;

lcdtimer[4]=0x30;

}

}

}

}

}

}

}

if(m==0)

{

disp_lcd(0xc0,lcdtimer);

if(!Key1)//关掉闹钟

{

g=0;

}

if(lcdtimer[8]==setlcdtimer[8]&&lcdtimer[7]==setlcdtimer[7]&&lcdtimer[5]==setlcdtimer[5]&&lcdtimer[4]==setlcdtimer[4])

f=1;  //开启闹钟 ,播放音乐

if(f&&g)

{

/*ring=1;

delay(10000);

ring=0;

f=0; */

IE=0x8e;

j=song1[i]/10-1;

k=2*(song1[i]%10-1);

th1_f=freq[j][k]; //取出对应的定时值送给T0

tl1_f=freq[j][++k];

TR1=1;

for(n=0;n<50000;n++); //音符间延时

i++;

TR1=0;

f=0;

}

}

}

while(m==1)          //调时分

{

if(!Key1)

{

delay(10000);

timeflag=0;

lcdtimer[8]+=1;

if(lcdtimer[8]>=0x3a)

{

lcdtimer[8]=0x30;

lcdtimer[7]+=1;

if(lcdtimer[7]>=0x36)

{

lcdtimer[7]=0x30;

}

}

}

disp_lcd(0xc0,lcdtimer);

delay(8000);

mlcdtimer[11]=lcdtimer[11];

mlcdtimer[10]=lcdtimer[10];

mlcdtimer[5]=lcdtimer[5];

mlcdtimer[4]=lcdtimer[4];

disp_lcd(0xc0,mlcdtimer);

}

while(m==2)  //调时时

{

if(!Key1)

{

delay(10000);

lcdtimer[5]+=1;

if(lcdtimer[5]>=0x3a)

{

lcdtimer[5]=0x30;

lcdtimer[4]+=1;

}

if(lcdtimer[4]==0x32&&lcdtimer[5]>=0x34)

{

lcdtimer[5]=0x30;

lcdtimer[4]=0x30;

}

}

disp_lcd(0xc0,lcdtimer);

delay(8000);

hlcdtimer[11]=lcdtimer[11];

hlcdtimer[10]=lcdtimer[10];

hlcdtimer[8]=lcdtimer[8];

hlcdtimer[7]=lcdtimer[7];

disp_lcd(0xc0,hlcdtimer);

}

while(m==3)//显示闹铃时间

{

if(!Key1)

{

delay(10000);

}

disp_lcd(0xc0,setlcdtimer);

}

while(m==4) //调闹铃分

{

if(!Key1)

{

delay(10000);

setlcdtimer[8]+=1;

if(setlcdtimer[8]>=0x3a)

{

setlcdtimer[8]=0x30;

setlcdtimer[7]+=1;

if(setlcdtimer[7]>=0x36)

{

setlcdtimer[7]=0x30;

}

}

}

disp_lcd(0xc0,setlcdtimer);

delay(8000);

mlcdtimer[11]=setlcdtimer[11];

mlcdtimer[10]=setlcdtimer[10];

mlcdtimer[5]=setlcdtimer[5];

mlcdtimer[4]=setlcdtimer[4];

disp_lcd(0xc0,mlcdtimer);

}

while(m==5)//调闹铃时

{

if(!Key1)

{

delay(10000);

setlcdtimer[5]+=1;

if(setlcdtimer[5]>=0x3a)

{

setlcdtimer[5]=0x30;

setlcdtimer[4]+=1;

}

if(setlcdtimer[4]==0x32&&setlcdtimer[5]>=0x34)

{

setlcdtimer[5]=0x30;

setlcdtimer[4]=0x30;

}

}

disp_lcd(0xc0,setlcdtimer);

delay(8000);

hlcdtimer[11]=setlcdtimer[11];

hlcdtimer[10]=setlcdtimer[10];

hlcdtimer[8]=setlcdtimer[8];

hlcdtimer[7]=setlcdtimer[7];

disp_lcd(0xc0,hlcdtimer);

}

}

}

c语言实验报告绘制钟表,单片机时钟程序实验报告相关推荐

  1. 华理c语言设计网上作业,华理c程序实验报告(共9篇).doc

    华理c程序实验报告(共9篇) 华理c程序实验报告(共9篇) 2011华理<C语言实验报告> C程序设计课程 实验报告册 所在学院 班 级 学 号 姓 名 任(来自:www.XIelw.Co ...

  2. java万年历开题报告_基于单片机的万年历开题报告.doc

    基于单片机的万年历开题报告.doc 还剩 13页未读, 继续阅读 下载文档到电脑,马上远离加班熬夜! 亲,喜欢就下载吧,价低环保! 内容要点: 基于单片机的万年历开题报告,考.动手制作的能力,我们在其 ...

  3. 从左到右的流水灯单片机课程设计实验报告c语言版,流水灯_单片机课程设计-实验-LED流水灯.doc...

    实验 LED流水灯 P0口作输出口,经74LS244驱动,接8只发光二极管LED0-LED7.当单片机的引脚输出为低电平时发光二极管点亮,为高电平时息灭.编写程序,使8个发光二极管循环点亮,时间间隔约 ...

  4. c51为啥要宏定义时钟_51单片机时钟实训报告

    时.分.秒计时器设计 一.任务及要求 用 51 单片机设计时.分.秒计时器,具体要求如下. 1 . 具有时.分.秒计时功能和 8 位数码管显示功能,显示格式为: "时-分-秒" : ...

  5. 计算机图形学上机报告绘制圆,计算机图形学上机实验报告

    实验一:基本图形的绘制 一.实验目的与要求 (1)理解glut程序框架: (2)理解窗口到视区的变换 ; (3)理解OpenGL实现动画的原理: (4)添加代码实现中点Bresenham算法画直线: ...

  6. c51单片机时钟c语言程序,89c51 C语言单片机 时钟程序

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 谁可以帮忙在这个程序里加个闹钟程序 刚学不懂 顺便讲解一下 谢了 #include #include unsigned char code digit[1 ...

  7. c语言485通讯源程序,51单片机485通信实验C语言源代码实现

    #include #include sbit RS485=P3^7;   //定义485的使能脚 bit SendFlag; unsigned int ReData,SenData; /******* ...

  8. c语言时钟ppt单片机,89c51 C语言单片机 时钟程序

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 谁可以帮忙在这个程序里加个闹钟程序 刚学不懂 顺便讲解一下 谢了 #include #include unsigned char code digit[1 ...

  9. 树莓派基础实验32:DS1302实时时钟模块实验

    一.介绍   现在有很多流行的串行时钟芯片,如DS1302,DS1307,PCF8485等,由于简单的接口,低成本和易用性,他们被广泛应用于电话.传真.便携式仪器等产品领域.在本实验中,我们将使用DS ...

最新文章

  1. Visual Studio 2005 Beta2 简体中文版发布
  2. 单核工作法13:永不拖延(上)
  3. 排序算法——归并排序
  4. python数据分析_使用Python进行数据分析
  5. 搜索NLP行业模型和轻量化客户定制
  6. OJ1004: 三位数的数位分离
  7. c语言异或运算符_计算机中C语言的-运算符
  8. 012-centos6.5配置静态ip
  9. 从一个实例(整数幂指数)进行算法时间复杂度的分析
  10. Html中文字过多,单行超出和多行超出显示省略号
  11. echo -e <<EOF $()三种操作的意义
  12. 通过注册表快速清理残留的软件
  13. gd公文文件转换成pdf格式
  14. 2018美赛建模总结+Latex标准美赛模板分享
  15. 实现手机扫描二维码登录
  16. 【智能控制】linkboy带你花式开灯
  17. 微信java精简版低内存_微信精简版低内存apk-微信精简版2019下载v7.0.6 安卓版-腾牛安卓网...
  18. Python文件IO处理技巧: 读写、重定向、间隔符、路径、存在性与文件列表
  19. Android微信支付遇到的大坑
  20. GAN小结(BEGAN EBGAN WGAN CycleGAN conditional GAN DCGAN PGGAN VAEGAN)

热门文章

  1. Mycat之——实现MySQL垂直分库
  2. 国科大高级人工智能2020-2021年期末试题回顾
  3. python写通讯录_Python:利用字典编写通讯录
  4. 如何拿到牛逼公司的面试邀请?
  5. 基于西门子1200PLC模拟量测温案例2
  6. 【动态内存管理】(超详解,附带面试题)
  7. 医疗物联网平台架构图
  8. python贷款还款预测
  9. 游戏配音背后的秘密—后期处理
  10. Mac安装淘宝镜像权限问题的解决方式