Get清风单片机最小系统的设计与制作 单片机课程设计

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

单片机最小系统的设计与制作单片机课程设计
单片机课程设计报告——单片机最小系统的设计与制作
学院:信息与电气工程学院
姓名:马杰
学号:0804040234
指导老师:曾照福
设计时间:2021.5.30—2021.6.10
目录
摘要1
一、设计与制作目的2
二、设计与制作要求2
三、设计方案比拟说明3
四、原理说明5
4.1 单片机的选择5
4.2 显示电路6
4.3 4*4矩阵键盘电路和4个独立键盘电路7
4.4 存储电路8
4.6 LCD接口11
4.7 程序下载接口11
4.8 电源电路13
4.9 温度测量接口13
4.10 跳线电路13
五、程序流程图及说明错误!未定义书签。

六、程序清单及注释15
七、硬件调试及调试结果15
八、软件测试及其结果17
数码管测试17
8.2 键盘测试17
8.3 24C02存储电路测试18
8.4 DS1302 实时时钟电路测试18
8.5 DS18B20温度测量电路测试18
九、测试仪器及测试结果19
十、结果分析及设计心得20
参考文献21
附录1:原理图、PCB图以及实物图21 附录2:程序清单21
附录3:元器件清单86
摘要
随着单片机的应用越来越广泛,比方日常生活中的电冰箱、洗衣机、微波炉等等,都是用单片机作为MCU来控制这些器件,对于我们来说,学习单片机是非常有必要的,而单片机的最小系统更是我们学习单片机的根底。

此次需要设计的单片机最小系统中,除了电源电路、复位电路、晶振电路外,还需要4*4矩阵键盘、4个独立键盘、8位数码管显示电路、存储电路、实时时钟电路、温度测量接口、LCD接口、程序下载接口。

因为单片机只有32个口,所以这32口如何合理的分配给这些模块是本设计的重点,但是由于大多数同学编程还不是过硬,故最好选择直接用I/O进行控制的系统,而不要用锁存器等在编程中要设置相应模式的器件,这个要求使得对单片机的32个I/O如何分配的问题更加重要。

在设计完这个单片机最小系统后,最起码要实现以下功能:数码管能显示数字和字母;设置按键和数码管,当按下相应键时,可以在数码管上显示设置的数字和字母,如1、2、3、A、b等等;设置数码管能使其显示数字和字母;设置数码管和24C02芯片,能在掉电后还显示掉电之前的内容;设置DS1302芯片,
能用数码管或液晶显示年月日和实时时间;设置DS18B20芯片,能用数码管或液晶显示实时温度。

最终,为了训练一定的编程能力,将这些模块整合到一起用12864LCD实现一定的功能,因为设计过程中显示局部,数码管和液晶不能同时用,所以总的程序中没有将数码管显示表达出来。

一、设计与制作目的
(1) 能够独立地设计并制作出单片机的最小系统,培养自主学习能力、设计能力以及动手能力。

(2) 了解单片机的结构构造、主要功能等,并且能运用到实践中去。

(3) 培养解决问题的能力,多思考,勤动手。

(4) 培养编程能力。

二、设计与制作要求
〔1〕设计并绘制单片机最小系统电路原理图,并画好PCB图。

〔2〕制作PCB板并调试每一个模块〔含软硬件〕。

〔3〕用12864LCD来做显示。

主要显示的功能是:能够显示年、月、日、星期、时、分、秒,
并能通过独立键盘修改;能够显示实时温
度;显示“今天的事:X 件〞,能够通过矩
阵键盘修改X的值,并通过设置24C02使在
掉电的时候还能保存X的值。

〔4〕撰写设计与调试报告。

三、设计方案比拟说明
设计方案1:单片机选用52系列的,4*4键盘和四位一体数码管直接用HD7279A控制,但是这样写程序时比拟麻烦,还得考虑HD7279A的编程。

存储电路、实时时钟电路、温度测量电路采用直接连在I/O上的方式。

设计方案2:所有的模块都用I/O口直接控制,这样的接法有助于对编程还不是很熟悉的人使用,便于编写程序。

还有就是,数码管的显示内容远少于LCD 可显示的内容,数码管可显示的内容LCD也可显示,所以选择了数码管和LCD不同时使用方式。

存储电路、实时时钟电路、温度测量电路采用跳线方式,当不用其中的一个模块或者要用这个口来做其他事时,可以将这个口的跳线帽取掉,从而到达一口多用又不会混淆的目的。

经过比拟选择了方案2。

所示。

图3.1 硬件原理框图
该单片机最小系统包括了复位电路、晶振电路、电源电路、8位共阴极数码管、4*4矩阵键盘、4位独立键盘、24C02存储电路、DS1302实时时钟电路、1602和12864LCD 接口、18B20温度测量接口,还加了4个I/O 口的扩展和电源正负极的扩展,功能已经很齐全,下面主要阐述一下引脚分配问题。

因为单片机的四个口都加了上拉电阻,所以在遇到有些要加上拉电阻的元器件时不必再考虑在其电路模块中加上拉电阻。

4*4键盘采用P1.0~P1.3来控制其四行,P1.4~P1.7来控制其四列;4个独立按键用的是P1.4~P1.7来控制的;8位共阴极数码管的位选
VCC GND RST STC89C52单片机 P3口 P1口 P2口
P0口 晶振电路
串口下载
复位电路
4个独立
4*4矩阵
1602、
四位一体共接电1602、四位一体共电源电路
用P0口来控制,段选用8个PNP做驱动,用P2口控制;前面已经讨论过,LCD能显示的内容远比数码管能显示的多,所以用了P0和P2来控制LCD,LCD和数码管不能同时用,在板子上用了跳线,当跳线冒盖上时,采用数码管显示,此时不能用LCD显示,当跳线冒拿下时,用LCD显示,此时,不能用数码管显示;24C02存储电路串行数据/地址和串行时钟两个端口用P3.4和P3.5控制;DS1302实时时钟电路串行时钟输入、数据输入输出口、复位脚分别用P1.0、P1.1和P1.2来控制,虽然和键盘一局部行复用,但是因为控制方式不同,所以不会有影响;18B20采用P3.3〔外部中断1〕控制。

通过以上分析可以看出,除P3口外,每个口利用都很充分,而且这样直接控制的方式便于我们编程。

四、原理说明
4.1 单片机的选择
市面上单片机的种类非常多,经过思考,为结合实际应用,选择了由宏晶公司生产的STC89C52,它的主要特性有:
MCS-51兼容
●与
字节可编程闪烁存储器
●8K
内部RAM
●512
可编程I/O线
●32
16位定时器/计数器
●三个
个中断源
●6
●可编程串行通道
1000写/擦循环
●寿命:
10年
●数据保存时间:
0Hz-24MHz
●全静态工作:
●三级程序存储器锁定
●低功耗的闲置和掉电模式
●片内振荡器和时钟电路
STC89C52的最小系统电路图如图4.1所示。

图4.1 STC89C52的最小系统电路图
为了方便扩展,在单片机的四个I/O口上都加了10K的上拉电阻和排针,其电路图如图4.2、图4.3所示。

图4.2 上拉电阻电路图
图4.3 口扩展排针电路图
4.2 显示电路
显示电路选用了四位一体共阳极LED数码管,LED 数码管的位选驱动用S8550的PNP三极管,段选那么是加了200欧姆的电阻。

数码管是一种半导体发光器件,其根本单元是发
光二极管,是单片机系统中最常用的一种显示输出,主要用于单片机控制中的数据输出和状态信息显示。

共阳极数码管是将所有发光二极管的阳极接在一起作为公共端COM,当公共端接低电平时,某一段阳极上的电平为“1〞时,该段点亮,电平为“0〞时,该段熄灭。

其中1、2、3、4是位选端,a、b、c、d、e、f、g、dp是段选端。

加上驱动,其电路图如图4.4所示。

图4.4 数码管显示电路图
4.3 4*4矩阵键盘电路和4个独立键盘电路
键盘是单片机应用系统中使用最广泛的一种数据输入设备。

键盘是一组按键的组合。

键通常是一种常开型按钮开关,常态下键的两个触点处于断开状态,按下键时它们才闭合〔短路〕。

通常,键盘有编码和非编码两种。

编码键盘通过硬件电路产生被按按键的键码和一个选通脉冲。

选通脉冲可作为CPU的中断请求信号。

这种键盘使用方便,所需程序简单,但硬件电路复杂,常不被单片机采用。

非编码键盘按组成结构又可分为独立式键盘和矩阵式键盘。

独立式键盘的工作过程与矩阵式键盘类似,无论是硬件结构还是软件设计都比拟简单。

矩阵式键盘电路连接复杂,但提高了I/O口利用率,软件编程较
复杂,适用于需使用大量按键的场合。

在此单片机中,用了4*4的非编码矩阵式键盘,其电路图如图4.5所示。

图4.5 4*4矩阵键盘电路
独立键盘电路图如图4.6所示。

图4.6 独立键盘电路图
4.4 存储电路
顾名思义,存储电路就是在掉电之后存储当前数据,当下次上电时,还能保持上次掉电时的数据。

I2C总线接口EEPROM存储器是一种采用I²C总线接口的串行总线存储器,这类存储器具有体积小、引脚少、功耗低、工作电压范围宽等特点。

在单片机系统中使用较多的EEPROM存储器是24系列串行EEPROM。

其具有型号多、容量大、支持I²C总线协议、占用单片机I/O端口少,芯片扩展方便、读写简单等优点。

在这个存储电路中,采取的主芯片是AT24C02,具有256个字节。

其特性为:
●与400KHz I²C总线兼容

●低功耗
CMOS技术
●写保护功能:当
WP为高电平时进入写保护状态
●页写缓冲器
●自定时擦写周期
编程/擦除周期
●1000000
100年
●可保存数据
脚DIP、SOIC或TSSOP封装
●8
●温度范围:商业级、工业级和汽车级
其引脚功能为:
A0、A1、A2:器件地址选择。

在此电路图中将它们全部接地了。

SDA :串行数据/地址。

SCL :串行时钟。

WP :写保护。

VSS :地
AT24C02支持I²C总线数据传送协议,I²C总线协议规定,任何将传送到总线的器件作为发送器。

任何从总线接收的器件为接收器。

数据传送是由产生串行时钟和所有起始停止信号的主器件控制的。

主器件和从器件都可以作为发送器或接收器,但由主器件控制传送数据的模式。

其电路图如图4.7所示。

图4.7 存储电路
4.5 实时时钟电路
在此电路中采取的主芯片是DS1302。

DS1302是美国DALLAS公司推出的一种高性能、低功耗的实时时钟芯片,附加31字节静态RAM,采用SPI三线接口与CPU 进行通信,并可采用突发方式一次传送多个字节的时钟信号和RAM数据。

实时时钟可提供秒、分、时、日、星期、月和年,小月与大月可以自动调整,且具有闰年补偿功能。

工作电压~5.5V。

采用双电源供电〔主电源和备用电源〕,可设置备用电源充电方式,提供了对后备电源进行涓细电流充电的能力。

其引脚功能为:
Vcc1 :备用电池端。

Vcc2 :5V电源。

当Vcc2>Vcc1+0.2V时,由Vcc2
向DS1302供电,当Vcc2< Vcc1时,由
Vcc1向DS1302供电。

SCLK :串行时钟输入。

I/O :数据输入输出口。

CE/RST :复位脚。

Z的晶振〕。

GND :地。

其电路图如图4.8所示。

图4.8实时时钟电路图
4.6 LCD接口
显示仅仅只有LED数码管,有时候不能满足显示要求,如要显示字符、文字、图片等,仅仅是数码管是显示不出来的,所以在此系统中,增加了1602LCD 接口和12864LCD接口,以方便外扩。

为了能调整背光,用了10K的电位器。

1602LCD接口电路图如图4.9所示,12864LCD接口电路图如图4.10所示。

图4.9 1602LCD接口电路图图4.10 12864LCD接口电路图
4.7 程序下载接口
STC89C52所采用的程序下载方式是串口下载,其主要芯片是MAX232。

该产品是由德州仪器公司〔TI〕推出的一款兼容RS232标准的芯片。

由于电脑串口是-10V~+10V,而一般的单片机应用系统的信号是TTL 电平0~+5V,MAX232就是用来进行电平转换的,该器件包含2驱动器、2接收器和一个电压发生器电路提供TIA/EIA-232-F电平。

该器件符合TIA/EIA-232-F标准,每一个接收器将TIA/EIA-232-F电平转换成5V TTL/CMOS电平,每一个发送器将TTL/CMOS 电平转换成TIA/EIA-232-F电平。

其主要特性为:
5V电源工作。

●单
工艺技术。

●LinBiCMOSTM
●两个驱动器及两个接收器。

30V输入电平。

●±
8mA。

●低电源电流,典型值是
ANSI标准EIA/TIA-232-E及ITU推荐●符合甚至优于
标准V.28。

保护大于MIL-STD-883标准的2000V
●ESD
其引脚功能分为三局部:
第一局部是电荷泵电路。

由1、2、3、4、5、6脚和4只电容构成。

功能是产生+12V和-12V两个电源,提供应RS-232串口电平的需要。

第二局部是数据转换通道。

由7、8、9、10、11、12、13、14脚构成两个数据通道。

其中13脚〔R1IN〕、12脚〔R1OUT〕、11脚〔T1IN〕、14脚〔T1OUT〕为第一数据通道。

8脚〔R2IN〕、9脚〔R2OUT〕、10脚〔T2IN〕、7脚〔T2OUT〕为第二数据通道。

TTL/CMOS数据从T1IN、T2IN输入转换成RS-232数据从T1OUT、T2OUT送到电脑DB9插头;DB9插头的RS-232数据从R1IN、R2IN 输入转换成TTL/CMOS数据后从R1OUT、R2OUT输出。

第三局部是供电。

15脚GND、16脚VCC〔+5V〕。

其电路图如图4.11所示。

图4.11程序下载接口电路图
4.8 电源电路
电源电路采用了外部供电方式,因变压器是5V的,所以不用7805来稳压和变压,其电路图如图4.12所示。

图4.12 电源电路图〔图不全〕
另外,为扩展需要,还用排针引出了电源的正负极。

4.9 温度测量接口
为了测量温度方便,在系统上设计了一个温度测量接口,DS18B20芯片可以直接插在接口上,这样当芯片坏的时候可以方便更换。

其电路图如图4.13所示。

图4.13温度测量接口电路图
4.10 跳线电路
为了更好的利用单片机的I/O口,将24C02 和DS1302接到单片机上的引脚做了跳线,这样,当没加跳线冒时,被它们利用的I/O口可以被其他器件所利用。

要指出的是,在本系统中,数码管和液晶是不能共用的,所以,将数码管的三极管驱动中接电源的引
脚也做了跳线处理,这样在使用液晶时,将跳线冒拔掉,就可以使用了。

其电路图如图4.14所示。

图4.14 跳线电路图
五、程序流程图及说明
各芯片初始化之后,扫描SET键,假设按下那么进入调整秒、分、时、星期、年、月的子程序,这个子程序中还有一个增键和减键的子程序,用以调整时间值,按下UP键是增加,按下DOWN键是减少,假设在调整过程中按下OUT键,那么跳出调整,回到屏幕显示;假设没有按下SET键,那么进入正常的屏幕显示。

设置矩阵键盘按键,当按下相应键可修改X的值并保存在24C02中。

六、程序清单及注释 见附录2。

七、硬件调试及调试结果
因为是要做PCB 板,所以布局要合理。

布局一般都采用就近原那么,这样的方法使得布线可以少绕很多弯路,使板面看起来整齐一点。

当我将所有的模块都布好后,直接将各个线的数据写好规那么后,自动布线即可。

当板子做出来后,就开始对一些硬件模块进行调试,首先要做的是,检查板子上是否存在断路和短路问题。

这一步非常重要,因为一旦焊上元器件再去检
初始化
SET 键按下?
调整秒、分、时、
星期、日、月、年
12864LCD 显
示 矩阵键盘相应数字按下? 修改“今天的事X 件〞
的X 值并保存在
24C02中 Out 键按下?
跳出调整

否 是



开始
查板子的断路、短路问题就比拟麻烦。

因为制作过程的问题,我的板子断路很多,我将漆刮开后,用废弃的电阻引脚和锡丝将断路的地方重新连接。

采用这样的方法来补救,使板面看起来整洁一些。

而短路,那么是直接将短路的地方刮断就好。

接下来查看各个模块的供电是否正常,即能否工作。

我先查了电源,当插上电源后,电源指示灯亮,说明电源工作正常。

然后我用万用表测试了几个芯片的电源,发现它们的工作电压都是5.16V,说明这几个芯片都能正常工作。

然后测试串口下载接口。

用串口下载线连接单片机和电脑,用STC-ISP软件来下载程序后发现,能够下载程序了,说明串口下载接口测试成功。

再者测试复位电路。

当按键没有按下之前,用万用表测试RST电压为0,按下开关,测试RST电压是5.16V,说明复位电路能正常工作。

还有几个模块,如4*4矩阵键盘、4个独立键盘、存储电路、数码管、DS1302等就要用软件来测试,才能看出是否工作。

注意,在测试过程中,万用表的作用是非常大的,每一条线,都得用万用表来测试其是否导通,还有就是是否与边上的线或引脚短路。

在测试过程中,要时
刻用万用表记录一些引脚的电压、电阻等值。

八、软件测试及其结果
首先采用的是模块测试,最后再将这些模块整合到一起,用12864LCD来做显示。

整合后主要显示的功能是:能够显示年、月、日、星期、时、分、秒,并能通过独立键盘修改;能够显示实时温度;显示“今天的事:X 件〞,能够通过矩阵键盘修改X的值,并通过设置24C02使在掉电的时候还能保存X的值。

8.1数码管测试
数码管的测试主要是看其位选和段选都能否工作。

位选接的是P2.0~P2.7,,因为是共阳极数码管,所以要使相应段亮,那么置该位为0。

我所编写的程序是4个数码管依次显示0、1、2、3、4、5、6、7、8、9、A、b、C、d、E、F。

用相应程序测试后,数码管能显示所要显示的数字和字符,证明数码管是好的。

8.2 键盘测试
矩阵键盘的测试主要通过键盘扫描方式加上数码管显示,当按下键时,数码管显示相应的字型,这里总共有16个键,让其显示0、1、2、3、4、5、6、7、8、9、A、b、C、d、E、F 。

独立按键有四个,按键让
数码管显示0、1、2、3 。

用相应程序测试后,按相应的键能使数码管显示所要显示的数字和字符,证明矩阵键盘和独立按键都是好的。

8.3 24C02存储电路测试
该模块测试还是和数码管相结合,编写程序使数码管两位显示00~99,每个数字间隔一秒,显示到99后再从0开始,依次循环,当掉电后再插电,数码管显示从掉电前的数字开始。

用相应程序测试后,数码管在00~99之间循环显示,掉电后再上电,还是从掉电前显示的数字开始显示,说明24C02是好的。

8.4 DS1302 实时时钟电路测试
该模块的测试是与12864LCD相结合的,编写程序,使12864LCD显示年、月、日、小时、分、秒,且掉电之后时钟会继续走,不会每次都初始化。

用相应程序测试后,能实现上述功能,说明DS1302是好的。

8.5 DS18B20温度测量电路测试
该模块的测试是与数码管相结合的,编写程序,使数码管显示实时温度。

用相应程序测试后,能实现上述功能,说明DS18B20是好的。

九、测试仪器及测试结果
测试仪器:万用表、5V电源、烙铁。

测试结果见表9.1所示。

表9.1时钟测试结果
SET键按下次
数UP键按
一次
DOWN键
按一次
OUT键
按下
1 秒数加
1
秒数减1
跳出
调整
2 分数加
1
分数减1
跳出
调整
3 时数加
1
时数减1
跳出
调整
4 星期数
加1
星期数
减1
跳出
调整
5 日数加
1
日数减1
跳出
调整
6 月数加
1
月数减1
跳出
调整
7 年数加年数减1 跳出
1 调整
8 跳出调

跳出调

跳出
调整
按相应矩阵键盘设定的数字键,X的值变成相应的数字,并且掉电后再插上电,还是掉电之前的数字。

十、结果分析及设计心得
经过程序调试,可以看出该单片机系统是完全可以正常工作的。

通过该设计,使我对单片机的了解更进了一步,先前只是理论上的认识,通过本次设计,使我对各个元器件有了实质上的认识,真正的理论和实际相结合,认识到了理论和实际相结合的重要性。

在本次设计中,做 PCB板,使我对PCB的制作流程有了一定的了解。

在这之前只是会画PCB图,不知道真正的PCB板是怎么制作的。

而在这之后,对于PCB 的制作流程已经根本掌握,对以后将会有一定作用。

然后就是自学能力。

在设计这个最小系统之前,虽然对于单片机有一定了解,但是要设计出一个好的系统,单靠之前的知识是不够的,还要靠自己学习,而知识的主要来源就是网络和书本,这也就考验了我们的查找文献能力。

网络上的查找主要是百度和Google,在这里查找要懂得使用对的关键字,还有查找一定要全
面,尽量查找PDF文件。

书本主要是跟单片机有关的书籍。

但是使用这些资源的过程中,要多思考,因为这些资源不一定全是对的,要自己会分辨。

再者是编程能力。

编程在单片机学习中非常重要的。

通过本次设计,我对编程的一些根本要诀有了进一步的了解,最好也是分模块,最后用到主程序中,这样的编程看起来非常整洁易懂。

最后就是解决问题的能力。

遇到问题不能老靠别人,也要通过自己的力量来解决问题。

在设计中,我遇到了不少问题,首先我会分析这个问题的关键在哪里,然后找出解决的方法,可以通过分析解决,也可以上网查找相关资料解决等等。

本次设计后,我所要到达的目的已经根本到达。

参考文献
[1] 郭天祥.51单片机C语言教程[M].北京:电子工业出版社,2021.
[2] 杨恢先,黄辉先.单片机原理及应用[M].北京:人民邮电出版社,2006.
附录1:原理图、PCB图以及实物图
附录2:程序清单
#include <REG51.H>
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char
sbit DS1302_CLK = P1^0; //实时时钟时钟线引脚
sbit DS1302_IO = P1^1; //实时时钟数据线引脚
sbit DS1302_RST = P1^2; //实时时钟复位线引脚
sbit DQ = P3^3; //温度传送数据IO口
sbit ACC0 = ACC^0;
sbit ACC7 = ACC^7;
uchar
hide_sec,hide_min,hide_hour,hide_day,hide_week ,hide_month,hide_year; //秒,分,时到日,月,年位闪的计数
sbit Set = P1^4; //模式切换键对应实验板K5
sbit Up = P1^5; //加法按钮对应实验板K6 sbit Down= P1^6; //减法按钮对应实验板K7 sbit out = P1^7; //立刻跳出调整模式按钮对应实验板K8
uchar done,count,temp,up_flag,down_flag;
uchar temp_value,temp1_value; //temp_value温度值正数局部 temp1_value温度值
小数局部
uchar TempBuffer[8],week_value[3],c[1];
#define OP_READ 0xa1 //器件地址以及读取操作,
0xa1即为1010 0001
#define OP_WRITE 0xa0 //器件地址以及写入操作,
0xa1即为1010 0000
//uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0x
f8,0x80,0x90};//定义数码管的显示0~9
uchar sec=0,key; //定义计数值,每过一
秒,sec加1
//uint count1; //定义中断次数
//bit write=0; //写24C08的标志
//sbit shiwei=P2^4; //十位选通定义
//sbit gewei=P2^5; //个位选通定义
void show_time(); //液晶显示程序
//****************************************
//12864液晶显示局部子程序模块
//****************************************
sbit rs = P2^0;
sbit rw = P2^1;
sbit e = P2^2;
#define lcddata P0
sbit busy=P0^7; //lcd busy bit
void wr_d_lcd(uchar content);
void wr_i_lcd(uchar content);
void clrram_lcd (void);
void init_lcd(void);
void busy_lcd(void);
void rev_row_lcd(uchar row);
void rev_co_lcd(uchar row,uchar col,uchar mode); void clr_lcd(void);
void wr_co_lcd(uchar row,uchar col,uchar lcddata1,uchar lcddtta2);
void wr_row_lcd(uchar row,char *p);
//**********************************
//液晶初始化
//**********************************
void init_lcd(void)
{
wr_i_lcd(0x06); /*光标的移动方向*/
wr_i_lcd(0x0c); /*开显示,关游标*/ }
//*********************************** //填充液晶DDRAM全为空格
//********************************** void clrram_lcd (void)
{
wr_i_lcd(0x30);
wr_i_lcd(0x01);
}
//*********************************** //对液晶写数据
//content为要写入的数据
//*********************************** void wr_d_lcd(uchar content)
{
busy_lcd();
rs=1;
rw=0;
lcddata=content;
e=1;
;
e=0;
}
//******************************** //对液晶写指令
//content为要写入的指令代码
//***************************** void wr_i_lcd(uchar content)
{
busy_lcd();
rs=0;
rw=0;
lcddata=content;
e=1;
;
e=0;
}
//******************************** //液晶检测忙状态
//在写入之前必须执行
//******************************** void busy_lcd(void)
{
lcddata=0xff;
rs=0;
rw=1;
e =1;
while(busy==1);
e =0;
}
//********************************
//指定要显示字符的坐标
//*******************************
void gotoxy(unsigned char y, unsigned char x) {
if(y==1)
wr_i_lcd(0x80|x);
if(y==2)
wr_i_lcd(0x90|x);
if(y==3)
wr_i_lcd((0x80|x)+8);
if(y==4)
wr_i_lcd((0x90|x)+8);
}
//**********************************
//液晶显示字符串程序
//********************************** void print(uchar *str)
{
while(*str!='\0')
{
wr_d_lcd(*str);
str++;
}
}
//*********************************** //DS1302时钟局部子程序模块
//*********************************** typedef struct __SYSTEMTIME__
{
uchar Second;
uchar Minute;
uchar Hour;
uchar Week;
uchar Day;
uchar Month;
uchar Year;
uchar DateString[11];
uchar TimeString[9];
}SYSTEMTIME; //定义的时间类型
SYSTEMTIME CurrentTime;
#define AM(X) X
#define PM(X) (X+12) // 转成24小时制
#define DS1302_SECOND 0x80 //时钟芯片的存放器位置,存放时间
#define DS1302_MINUTE 0x82
#define DS1302_HOUR 0x84
#define DS1302_WEEK 0x8A
#define DS1302_DAY 0x86
#define DS1302_MONTH 0x88
#define DS1302_YEAR 0x8C
//**********************************
//实时时钟写入一字节(内部函数)
//**********************************
void DS1302InputByte(uchar d)
{
uchar i;
ACC = d;
for(i=8; i>0; i--)
{
DS1302_IO = ACC0; //相当于汇编中的 RRC
DS1302_CLK = 1;
DS1302_CLK = 0;
ACC = ACC >> 1;
}
}
//*************************************
//实时时钟读取一字节(内部函数)
//*************************************
uchar DS1302OutputByte(void)
{
uchar i;
for(i=8; i>0; i--)
{
ACC = ACC >>1; //相当于汇编中的 RRC
ACC7 = DS1302_IO;
DS1302_CLK = 1;
DS1302_CLK = 0;
}
return(ACC);
}
//**************************************
//ucAddr: DS1302地址, ucData: 要写的数据
//**************************************
void Write1302(uchar ucAddr, uchar ucDa)
{
DS1302_RST = 0;
DS1302_CLK = 0;
DS1302_RST = 1;
DS1302InputByte(ucAddr); // 地址,命令
DS1302InputByte(ucDa); // 写1Byte数据
DS1302_CLK = 1;
DS1302_RST = 0;
}
//**************************************
//读取DS1302某地址的数据
//************************************** uchar Read1302(uchar ucAddr)
{
uchar ucData;
DS1302_RST = 0;
DS1302_CLK = 0;
DS1302_RST = 1;
DS1302InputByte(ucAddr|0x01); // 地址,命令
ucData = DS1302OutputByte(); // 读1Byte数据
DS1302_CLK = 1;
DS1302_RST = 0;
return(ucData);
}
//******************************************
//获取时钟芯片的时钟数据到自定义的结构型数组
//****************************************** void DS1302_GetTime(SYSTEMTIME *Time)
{
uchar ReadValue;
ReadValue = Read1302(DS1302_SECOND);
Time->Second = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);//转换为相应的10进制数
ReadValue = Read1302(DS1302_MINUTE);
Time->Minute = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_HOUR);
Time->Hour = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_DAY);
Time->Day = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_WEEK);
Time->Week = ((ReadValue&0x10)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_MONTH);
Time->Month = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_YEAR);
Time->Year = ((ReadValue&0xf0)>>4)*10 + (ReadValue&0x0F);
}
//******************************************
//将时间年,月,日,星期数据转换成液
//晶显示字符串,放到数组里DateString[]
//****************************************** void DateToStr(SYSTEMTIME *Time)
{
uchar
tab[ ]={0XD2,0XBB,0XB6,0XFE,0XC8,0XFD,0XCB,0XC 4,0XCE,0XE5,0XC1,0XF9,0XC8,0XD5};
if(hide_year<2) //这里的if,else语句都是判断位闪烁,<2显示数据,>2就不显示,输出字符串为 2007/07/22
{
Time->DateString[0] = '2';
Time->DateString[1] = '0';
Time->DateString[2] = Time->Year/10 + '0';
Time->DateString[3] = Time->Year%10 + '0';
}
else
{
Time->DateString[0] = ' ';
Time->DateString[1] = ' ';
Time->DateString[2] = ' ';
Time->DateString[3] = ' ';
}
Time->DateString[4]='-';
if(hide_month<2)
{
Time->DateString[5] = Time->Month/10 + '0';
Time->DateString[6] = Time->Month%10 + '0';
}
else
{
Time->DateString[5] = ' ';
Time->DateString[6] = ' ';
}
Time->DateString[7]='-';
if(hide_day<2)
{
Time->DateString[8] = Time->Day/10 + '0';
Time->DateString[9] = Time->Day%10 + '0';
}
else
{
Time->DateString[8] = ' ';
Time->DateString[9] = ' ';
}
if(hide_week<2)
{
week_value[0] =tab[2*(Time->Week%10)-2]; //星期的数据另外放到 week_value[]数组里,跟年,月,日的分开存放,因为等一下要在最后显示
week_value[1] =tab[2*(Time->Week%10)-1];
}
else
{
week_value[0] = ' ';
week_value[1]=' ';
}
week_value[2] = '\0';
Time->DateString[10] = '\0'; //字符串末尾加'\0' ,判断结束字符
}
//******************************************
//将时,分,秒数据转换成液晶
//显示字符放到数组 TimeString[]
//*****************************************
void TimeToStr(SYSTEMTIME *Time)
{ if(hide_hour<2)
Time->TimeString[0] = Time->Hour/10 + '0';
Time->TimeString[1] = Time->Hour%10 + '0';
}
else
{
Time->TimeString[0] = ' ';
Time->TimeString[1] = ' ';
}
Time->TimeString[2] = ':';
if(hide_min<2)
{
Time->TimeString[3] = Time->Minute/10 + '0';
Time->TimeString[4] = Time->Minute%10 + '0';
}
else
{
Time->TimeString[3] = ' ';
Time->TimeString[4] = ' ';
}
Time->TimeString[5] = ':';
if(hide_sec<2)
Time->TimeString[6] = Time->Second/10 + '0';
Time->TimeString[7] = Time->Second%10 + '0'; }
else
{
Time->TimeString[6] = ' ';
Time->TimeString[7] = ' ';
}
Time->TimeString[8] = '\0';
}
//******************************
//时钟芯片初始化
//******************************
void Initial_DS1302(void)
{
uchar Second=Read1302(DS1302_SECOND);
if(Second&0x80) //判断时钟芯片是否关闭
{
Write1302(0x8e,0x00); //写入允许
Write1302(0x8c,0x07); //以下写入初始化时间。

相关文档
最新文档