光电与通信工程学院
课程设计报告书
课 设 名 称: 温度采集与显示系统 年级专业及班级: 姓 名: 学 号: 组 号:
1
温度采集与显示系统
摘要
温度是一种最基本的环境参数,也是一个十分重要的物理量,对它的测量与控制有十分重要的意义。随着现代工农业技术的发展及人们对生活环境要求的提高,人们也迫切需要检测与控制温度:如大气及空调房中温度的高低,直接影响着人们的身体健康;粮仓温度的检测,防止粮食发霉,最大限度地保持粮食原有新鲜品质,达到粮食保质保鲜的目的;工业易燃品的存放。
温度测量在物理实验、医疗卫生、食品生产等领域,尤其在热学试验中,有特别重要的意义。随着人们生活水平的不断提高,,人们对温度计的要求越来越高,传统的温度计功能单一、精度低,要为现代人工作、科研、生活、提供更好的更方便的设施就需要从单片机技术入手,一切向着数字化控制,智能化控制方向发展。
本次课程设计介绍了以STCC51单片机为核心的温度检测报警系统的工作原理和设计方法。温度信号由温度传感器芯片DS18B20采集,并以数字信号的方式传送给单片机,单片机再控制数码管驱动芯片74LS573驱动4位分立式数码管显示实时温度,当检测到的温度超出了给定的温度范围(默认下限为20℃,默认上限为35℃),系统将输出报警声。本系统的主要硬件电路包括:温度检测电路,数码管驱动电路,报警电路。另外本系统的软件部分占了很大的比重,主要的软件模块包括:温度传感器程序,数码管驱动及显示程序,报警程序。
关键词:温度测量,单片机,温度传感器
2
目 录
一、序论………………………………………………………………………………1 (一)设计背景与课程目的 ……………………………………………………… 1 (二)设计任务要求 ……………………………………………………………… 1 二、系统的主要功能及工作流程 ………………………………………………… 1 (一)系统具有以下功能 ………………………………………………………… 1 (二)系统的工作流程 …………………………………………………………… 2 三、硬件电路原理描述 …………………………………………………………… 2 (一)实验步骤 …………………………………………………………………… 2 (二)所用芯片及其功能………………………………………………… ……… 3
1、STCC52 ………………………………………………………………… 4 2、MAX232CPE ………………………………………………………………… 4 (三)硬件电路原理 ……………………………………………………………… 4
1、控制部分 ……………………………………………………………………4 2、测量部分 ……………………………………………………………………6 3、显示部分 ……………………………………………………………………7 4、报警部分 ……………………………………………………………………7 四、软件设计流程及描述 ………………………………………………………… 8 五、心得体会…………………………………………………………………………10 参考文献……………………………………………………………………………12 致谢 …………………………………………………………………………………13 附录
(一)系统总硬件电路原理图 ……………………………………………………14 (二)系统源程序代码(要有注释) ……………………………………………14
3
一、序论
(一)设计背景与课程目的
温度是一种最基本的环境参数,也是一个十分重要的物理量,对它的测量与控制有十分重要的意义。随着现代工农业技术的发展及人们对生活环境要求的提高,人们也迫切需要检测与控制温度:如大气及空调房中温度的高低,直接影响着人们的身体健康;粮仓温度的检测,防止粮食发霉,最大限度地保持粮食原有新鲜品质,达到粮食保质保鲜的目的;工业易燃品的存放。
本次课程设计介绍了以STCC51单片机为核心的温度检测报警系统的工作原理和设计方法。温度信号由温度传感器芯片DS18B20采集,并以数字信号的方式传送给单片机,单片机再控制数码管驱动芯片74LS573驱动4位分立式数码管显示实时温度,当检测到的温度超出了给定的温度范围(默认下限为20℃,默认上限为35℃),系统将输出报警声。本系统的主要硬件电路包括:温度检测电路,数码管驱动电路,报警电路。另外本系统的软件部分占了很大的比重,主要的软件模块包括:温度传感器程序,数码管驱动及显示程序,报警程序。
(二)设计任务要求
1、根据设计内容与要求,弄清系统及各个模块的工作流程,完成电路原理图,包括单片机最小系统模块、LCD显示模块、存储模块、串行口下载模块和电源模块,最终在万用板上焊接,完成整个系统硬件设计。
2、根据设计内容与要求,弄清系统及各个模块的工作流程,完成系统的软件设计,包括系统主程序、温度读取子程序、LCD显示子程序、存储子程序等,可使用汇编语言或是C语言编写,建议使用C语言编写。
3、首先使用Proteus进行仿真和调试,在仿真通过后,将程序通过串行口下载电路下载到单片机中,最终使得系统在脱机情况下,能稳定可靠地工作。
二、系统的主要功能及工作流程
(一)系统具有以下功能:
1、能正确检测温度; 2、在1602上实时显示温度;
3、每隔10秒采集一次温度数据并保存到AT24C02 4、按键按下后,可逐个显示之前采集到的数据;
5、其他功能可根据系统上的资源自行设定。
利用STCC52、DS18B20、LCD1602、AT24C02等元器件设计温度采集与
1
显示系统。
扩展功能:
温度超过设定值,蜂鸣器报警;时间日期的显示;按键按下,重新开始采集温度等等。
(二)系统的工作流程 总体设计框图:
显示温度采集(DBS18B20)单片机STCC51
阈值设定(键盘)报警(蜂鸣器)系统设计思路为以单片机为控制中心,通过实时采集温度传感器DBS18B20获得当前的温度值,通过LED显示当前温度,同时使用键盘设定温度阈值,当测定温度大于温度阈值后,利用蜂鸣器报警。系统包括包括单片机最小系统模块、LED显示模块、蜂鸣器报警模块、矩阵键盘模块、串行口下载模块和电源模块。
三、硬件电路原理描述
(1)实验步骤
系统的主要功能是实现温度信号的采集,在4位LED显示器上显示当前的温度和通道号。模拟现场两个点的温度巡回检测,温度范围0-510摄氏度。每隔0.5秒检测一次,经标度变换后送LED显示器显示,4路循环显示,每路持续两秒。
实验步骤如下:
1、从PC机引出两根电缆连接在试验平台上。 2、编写程序然后编译连接。
3、按照附录一电路图所示连接试验线路。
2
4、运行参考程序,观察LED显示器上的通道号和温度值。 (二)所用芯片及其功能
1、STCC52
STCC52RC引脚功能说明
VCC(40引脚):电源电压 VSS(20引脚):接地
P0端口(P0.0~P0.7,39~32引脚):P0口是一个漏极开路的8位双向I/O口。作为输出端口,每个引脚能驱动8个TTL负载,对端口P0写入“1”时,可以作为高阻抗输入。
P1端口(P1.0~P1.7,1~8引脚):P1口是一个带内部上拉电阻的8位双向I/O口。P1的输出缓冲器可驱动(吸收或者输出电流方式)4个TTL输入。
P2端口(P2.0~P2.7,21~28引脚):P2口是一个带内部上拉电阻的8位双向I/O端口。P2的输出缓冲器可以驱动(吸收或输出电流方式)4个TTL输入。
P3端口(P3.0~P3.7,10~17引脚):P3是一个带内部上拉电阻的8位双向I/O端口。P3的输出缓冲器可驱动(吸收或输出电流方式)4个TTL输入。
RST(9引脚):复位输入。当输入连续两个机器周期以上高电平时为有效,用来完成单片机单片机的复位初始化操作。看门狗计时完成后,RST引脚输出96个晶振周期的高电平。
ALE/(30引脚):地址锁存控制信号(ALE)是访问外部程序存储器时,锁存低8位地址的输出脉冲。
(29引脚):外部程序存储器选通信号是外部程序存储器选通信号。当ATC51RC从外部程序存储器执行外部代码时,在每个机器周期被激活两次,而访问外部数据存储器时,将不被激活。
VPP(31引脚):访问外部程序存储器控制信号。为使能从0000H到FFFFH的外部程序存储器读取指令,必须接GND。注意加密方式1时,将内部锁定位RESET。为
了执行内部程序指令,应该接VCC。在Flash编程期间,也接收12伏VPP电压。
XTAL1(19引脚):振荡器反相放大器和内部时钟发生电路的输入端。
3
XTAL2(18引脚):振荡器反相放大器的输入端。
2、MAX232CPE
MAX232CPE是16针SMD封装IC,用于完成 计算机232端口数据电平转换,连接CMOS电路的,换言之,如果离开它,我们就无法用软件监控电源状态了(需要串口返回信号)。而PIC16F870则为24脚8位CMOS闪存控制器。 用于可监控UPS当中。
MAX232CPE完成232电平与TTL电平转换,提供一个本地接口,为调试和维护提供方便。TXD接SX52的RA2脚,RXD接SX52的RA3脚,RS-RXD和RS-TXD是RS232电平,为标准串口电平。数据可以从串口输入到单片机SX52,SX52再把数据送到RTL8019AS传出去。用于嵌入式设备上的应用
(三)硬件电路原理
系统总硬件电路原理图见附录一
1、控制部分
控制部分是采用单片机STCC52。
STCC52是一种低功耗、高性能CMOS8位微控制器,具有8K 在系统可编程Flash 存储器。STCC52使用经典的MCS-51内核,但做了很多的改进使得芯片具有传统51单片机不具备的功能。在单芯片上,拥有灵巧的8 位CPU 和在系统可编程Flash,使得STCC52为众多嵌入式控制应用系统提供高灵活、超有效的解决方案。
具有以下标准功能:8k字节Flash,512字节RAM,32 位I/O 口线,看门狗定时器,内置4KB EEPROM,MAX810复位电路,3个16位定时器/计数器,4个外部中断,一个7向量4级中断结构(兼容传统51的5向量2级中断结构),全双工串行口。另外STCX52 可降至0Hz 静态逻辑操作,支持2种软件可选择节电模式。空闲模式下,CPU 停止工作,允许RAM、定时器/计数器、串口、中断继续工作。掉电保护方式下,RAM内容被保存,振荡器被冻结,单片机一切工作停止,直到下一个中断或硬件复位为止。最高运作频率35MHz,6T/12T可选。
4
单片机总控制电路如下图:
1.2 复位操作
本系统的复位电路采用按键电平复位方式,通过使复位端经电阻与Vcc电源接通而实现的,其电路如下图所示
上述电路图中的电阻、电容参数适用于6MHz晶振,能保证复位信号高电平持续时间大于2个机器周期。
1.3 STCC52主要功能,如下表所示 STCC52主要功能
5
主要功能特性 兼容MCS51指令系统 32个双向I/O口 3个16位可编程定时/计数器中断 2个串行中断 2个外部中断源 2个读写中断口线 低功耗空闲和掉电模式 STCC52管脚介绍:
① 主电源引脚(2根)
VCC(Pin40):电源输入,接+5V电源 GND(Pin20):接地线 ②外接晶振引脚(2根)
XTAL1(Pin19):片内振荡电路的输入端 XTAL2(Pin20):片内振荡电路的输出端 ③控制引脚(4根)
RST/VPP(Pin9):复位引脚,引脚上出现2个机器周期的高电平将使单片机复位。
ALE/PROG(Pin30):地址锁存允许信号 PSEN(Pin29):外部存储器读选通信号
EA/VPP(Pin31):程序存储器的内外部选通,接低电平从外部程序存储器读指令,接高电平则从内部程序存储器读指令。
④可编程输入/输出引脚(32根)
STCC52单片机有4组8位的可编程I/O口,分别位P0、P1、P2、P3口,每个口有8位(8根引脚),共32根。
PO口(Pin39~Pin32):8位双向I/O口线,名称为P0.0~P0.7 P1口(Pin1~Pin8):8位准双向I/O口线,名称为P1.0~P1.7 P2口(Pin21~Pin28):8位准双向I/O口线,名称为P2.0~P2.7 P3口(Pin10~Pin17):8位准双向I/O口线,名称为P3.0~P3.7 2、测量部分
测量部分我们采用美国DALLAS公司生产的DS18B20温度传感器。 2.1 DS18B20简介
DS18B20数字温度传感器,该产品采用美国DALLAS公司生产的
6
8K可反复擦写Flash ROM 256x8bit内部RAM 时钟频率0-24MHz 可编程UART串行通道 共6个中断源 3级加密位 软件设置睡眠和唤醒功能 DS18B20可组网数字温度传感器芯片封装而成,具有耐磨耐碰,体积小,使用方便,封装形式多样,适用于各种狭小空间设备数字测温和控制领域。 2.2封装及接线说明:
DS18B20芯片封装结构:
特点:独特的一线接口,只需要一条口线通信 多点能力,简化了分布式温度传感应用 无需外部元件 可用数据总线供电,电压范围为3.0V至5.5V无需备用电源 测量温度范围为-55 °C至+125 ℃。华氏相当于是-67 °F到257华氏度 -10 °C至+85 °C范围内精度为±0.5 °C 2.3 DS18B20控制方法 DS18B20有六条控制命令:
温度转换 44H:启动DS18B20进行温度转换 读暂存器 BEH:读暂存器9个字节内容
写暂存器 4EH:将数据写入暂存器的TH、TL字节 复制暂存器 48H:把暂存器的TH、TL字节写到E2RAM中
读电源供电方式 B4H:启动DS18B20发送电源供电方式的信号给主CPU
3、显示部分
内部的四个数码管共用a~dp这8根
数据线,为人们的使用提供了方便,因为里面有四个数码管,所以它有四个公共端,加上a~dp,共有12个引脚,下面便是一个共阴的四位数码管的内部结构图(共阳的与之相反)。引脚排列依然是从左下角的那个脚(1脚)开始,以逆时针方向依次为1~12脚,上图中的数字与之一一对应。
4、报警部分
本系统设计三个按键,采用查询方式,一个用于选择切换设置报警温度和当前温度,另外两个分别用于设置报警温度的加和减。
7
四、软件设计流程及描述
系统软件程序采用C51语言编写。本程序采用模块化程序方法,主要分为以下三个模块:
◆ LCD初始化显示模块 ◆ DS18B20数据采集模块 ◆ 温度报警上下限设置模块
整个系统的功能是由硬件电路配合软件来实现的,当硬件基本定型后软件的
功能也就基本定下来了。从软件的功能不同可分为两大块:第一块是对数字温度传感器的操作,通过单片机对DS18B20进复位,进行数据读取等操作;第二块是控制LED数码显示,将温度数据在LED上显示出来。
程序流程图设计 :
开始初始化LCD1602调用DS18B20模块调用报警模块温度显示主程序流程图 8
主机发出开始信号主机设置为输入模式N跳出DS18B20是否响应?Y等待480us接收数据拉低总线,延时45us释放总线DS18B20数据采集流程图 9
进入设置模式(按键)设置温度报警上下限TH与TL调用DS18B20模块Temp>=TH||Temp<=TL?NY报警(LED亮,蜂鸣器响)温度显示报警模块流程图 五、心得体会 硬件(庄春兰)
通过这次课程的课程设计,我深深的认识到自己的很多不足,在实际的动手焊接过程中,我发现自己还是有很多欠缺的,首先就是要进行排版,这是非常重要的,这关系到这个版的美观,以及走线的正确性。当然在焊接过程最需要的是认真,不仅需要分清楚器件的正反,更重要的是查清楚器件的管脚图,依照管脚图进行焊接,以及明白各个管脚的作用。再则,就是走线的问题,走线尽量走直线,但是由于焊锡的不足,所以我们的板通过导线来走线,这样可以省下很多焊锡,但是不足的是影响了作品的美观度。焊接的时候要求对每个节点焊接牢固,
1 0
避免出现虚焊这种现象。但是,当我们讲作品按照原理图连接完成的时候,发现只有LED亮,并且闪烁。电路出现不稳定的现在,LED上无显示。经排查,发现插头出现漏电的现象,另外接了一个导线,LED灯不闪烁。认真的用万用表测量了单片机的引脚之后发现芯片在插的时候有一个引脚没有插进去,重新弄了之后,LED灯可以显示数据,并且可以实现功能。
软件(王璇)
根据实验的要求,我对相关的知识进行了复习,查询了各个器件的相关资料,并且找到了适合的方案进行了程序的编写。首先根据课程设计的要求写好程序的流程图,然后再进行相关的功能扩张,在程序流程图的基础上根据芯片的功能写出相对应的程序和扩展功能程序,然后再进行不断的调试和相应的修改,来实现要求的功能。程序都是由各个子程序组成,为了让自己更好的理解自己的程序,我都在程序后面加注释,这样在程序出错的检查过程中可以更容易查找的到,也更简洁,更明白易懂。 在写程序时候由于中断程序出错导致无法实现功能,排除错误之后程序运行正常,通过这次的课程设计我明白了理论和实际相结合的重要性,设计都是自己从头到尾慢慢的修改出来的,这让我熟悉了整个设计的过程,更系统的锻炼了自己,从而对书本上所学的知识有了更具体的理解。
11
参考文献
[1]单片机原理及应用 ; 徐敏,刘建春,关健生;机械工业出版社 [2] 单片机原理及接口技术,李朝青编著,北京航空航天大学出版社; [3] 微机原理及接口技术,李顺增、吴国东、乔志伟,机械工业出版社; [4] 电子技术常用器件应用手册,陈汝全,机械工业出版社; [5] 单片机原理及接口技术,李朝青,北京航空航天大学出版社; [6] 单片机微型计算机及其应用,孙育才,东南大学出版社; [7] 基于单片机的自适应温度控制系统;叶丹
1 2
致谢
人生的成长历程始终是向前的。当一个阶段快要结束即将迈入另一个阶段时,自然需要对即将过去的进行思考和小结。自己一直在思考学业、职业、事业的哲学关系,也许本来就没有固定的答案和模式。需要的是对自己对时间、对生命的尊重和珍惜,同样需要对在我成长历程中、在人生某个阶段一直给予我帮助、指导、鼓励、支持、信任、爱护的人,表达真正的感谢。可以用客套、冠冕堂皇的话,也可以选择朴实。后者才更真挚,更深入心灵。
在这里我要感谢指导老师和同学对我的悉心指导与帮助。老师诲人不倦的精神,治学严谨的态度,让我无比钦佩。还要感谢大学期间遇到的其他老师,谢谢你们让我在学到知识的同时,也学到了如何做人,你们的言传身教将让我一生受用。
1 3
附录一
系统总硬件电路原理图
附录二
系统源程序代码 主程序
#include uint su,tt,mm,m,n; uchar buff[4]; unsigned char pDat[7],pDat1[7]; sbit s1=P3^0; 1 4 sbit s2=P3^1; sbit s3=P3^6; void main() { m=0; n=0; init(); EX0=1; //init_com(); //包含了对定时器0的设定 while(1) { write_sfm(10,miao); write_sfm(7,fen); write_sfm(4,shi); dis_temp(tt); dis_temp1(mm); keyscan(); } } void int_0() interrupt 0 { EA=0; IRcvStr(0xa0,n,&pDat1[0],8); //mm=pDat1[0]; //mm<<=8; //两个字节组合为1个字 //mm=mm|pDat1[1]; mm=pDat1[0]*100+pDat1[1]*10+pDat1[2]; pDat1[0]=0; pDat1[1]=0; pDat1[2]=0; n=n+8; EA=1; } void keyscan() { if(s1==0) { delay(5); 1 5 if(s1==0) { s1num++; while(!s1); if(s1num==1) { TR0=0; write_com(0x80+0x40+10); write_com(0x0f); } } if(s1num==2) { write_com(0x80+0x40+7); } if(s1num==3) { write_com(0x80+0x40+4); } if(s1num==4) { s1num=0; write_com(0x0c); TR0=1; } } if(s1num!=0) { if(s2==0) { delay(5); if(s2==0) { while(!s2); if(s1num==1) { miao++; if(miao==60) miao=0; write_sfm(10,miao); write_com(0x80+0x40+10);//指针回原位 1 6 } if(s1num==2) { fen++; if(fen==60) fen=0; write_sfm(7,fen); write_com(0x80+0x40+7);//指针回原位 } if(s1num==3) { shi++; if(shi==24) shi=0; write_sfm(4,shi); write_com(0x80+0x40+4);//指针回原位 } } } if(s3==0) { delay(5); if(s3==0) { while(!s3); if(s1num==1) { /* if(miao==0) { miao=59; write_sfm(10,miao); write_com(0x80+0x40+10); }*/ miao--; if(miao==-1) miao=59; write_sfm(10,miao); write_com(0x80+0x40+10); } if(s1num==2) { fen--; if(fen==-1) fen=59; 1 7 write_sfm(7,fen); write_com(0x80+0x40+7); } if(s1num==3) { shi--; if(shi==-1) shi=23; write_sfm(4,shi); write_com(0x80+0x40+4); } } } } } void timer0() interrupt 1 { TH0=(65536-50000)/256; TL0=(65536-50000)%256; su++; if(su==20) { su=0; tempchange(); tt=get_temp(); //pDat[0]=(uchar)((tt>>8)&0xff); //pDat[1]=(uchar)(tt&0xff); pDat[0]=tt/100; pDat[1]=(tt%100)/10; pDat[2]=tt%10; ISendStr(0xa0,m,&pDat[0],8); //存温度 m=m+8; pDat[0]=0; pDat[1]=0; pDat[2]=0; } count++; if(count==20) { count=0; miao++; 1 8 } } if(miao==60) { miao=0; fen++; if(fen==60) { fen=0; shi++; if(shi==24) { shi=0; } // write_sfm(4,shi); } //write_sfm(7,fen); } //write_sfm(10,miao); DS18B20复位函数 #include sbit ds=P2^2; //温度传感器信号线 //sbit beep=P2^3; //蜂鸣器 uint temp; float f_temp; void dsreset(void) //18B20复位,初始化函数 { uint i; ds=0; i=103; while(i>0)i--; ds=1; i=4; while(i>0)i--; } bit tempreadbit(void) //读1位函数 { uint i; bit dat; 1 9 ds=0;i++; //i++ 起延时作用 ds=1;i++;i++; dat=ds; i=8;while(i>0)i--; return (dat); } uchar tempread(void) //读1个字节 { uchar i,j,dat; dat=0; for(i=1;i<=8;i++) { j=tempreadbit(); dat=(j<<7)|(dat>>1); //读出的数据最低位在最前面,这样刚好一个字节在DAT里 } return(dat); } void tempwritebyte(uchar dat) //向18B20写一个字节数据 { uint i; uchar j; bit testb; for(j=1;j<=8;j++) { testb=dat&0x01; dat=dat>>1; if(testb) //写 1 { ds=0; i++;i++; ds=1; i=8;while(i>0)i--; } else { ds=0; //写 0 i=8;while(i>0)i--; ds=1; i++;i++; } 2 0 } } void tempchange(void) //DS18B20 开始获取温度并转换 { dsreset(); delay(1); tempwritebyte(0xcc); // 写跳过读ROM指令 tempwritebyte(0x44); // 写温度转换指令 } uint get_temp() //读取寄存器中存储的温度数据 { uchar a,b; dsreset(); delay(1); tempwritebyte(0xcc); tempwritebyte(0xbe); a=tempread(); //读低8位 b=tempread(); //读高8位 temp=b; temp<<=8; //两个字节组合为1个字 temp=temp|a; f_temp=temp*0.0625; //温度在寄存器中为12位 分辨率位0.0625° temp=f_temp*10+0.5; //乘以10表示小数点后面只取1位,加0.5是四舍五入 f_temp=f_temp+0.05; return temp; //temp是整型 } ////////////////////显示程序调用lcd中的write_sfm1 十位地址写4 个位为5 小数为7////////////////////////// void dis_temp(uint t) { uint i; i=t/100; write_sfm1(0,i); i=(t%100)/10; write_sfm1(1,i); i=t%10; write_sfm1(3,i); 2 1 } void dis_temp1(uint t) //显示储存的温度 { uint i; i=t/100; write_sfm1(9,i); i=(t%100)/10; write_sfm1(10,i); i=t%10; write_sfm1(12,i); } /*void init_com(void) { TMOD = 0x20; PCON = 0x00; SCON = 0x50; TH1 = 0xFd; TL1 = 0xFd; TR1 = 1; } void comm(char *parr) { do { SBUF = //发送数据 while(!TI); //等待发送完成标志为1 TI //标志清零 }while(*parr); //保持循环直到字符为'\\0' } */ ////////////////////////////////////////////// /*void warn(uint s,uchar led) //蜂鸣器报警声音 ,s控制音调{ uchar i;i=s; beep=0; P1=~(led); while(i--) 2 2 *parr++; =0; { dis_temp(get_temp()); } beep=1; P1=0XFF; i=s; while(i--) { dis_temp(get_temp()); } } void deal(uint t) { uchar i; if((t>warn_l2)&&(t<=warn_l1)) //大于25度小于27度 { warn(40,0x01); } else if(t<=warn_l2) //小于25度 { warn(10,0x03); } else if((t warn(40,0x04); } else if(t>=warn_h2) //大于32度 { warn(10,0x0c); } else { i=40; while(i--) { dis_temp(get_temp()); } } } */ /*************************此部分为AT2402的驱动程序使用I2C总线连接*************************************/ 2 3 #include //AT2402的功能函数 /******************************************************************* 向有子地址器件发送多字节数据函数 函数原型: bit ISendStr(UCHAR sla,UCHAR suba,ucahr *s,UCHAR no); 功能: 从启动总线到发送地址,子地址,数据,结束总线的全过程,从器件 地址sla,子地址suba,发送内容是s指向的内容,发送no个字节。 如果返回1表示操作成功,否则操作有误。 注意: 使用前必须已结束总线。 ********************************************************************/ bit ISendStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no) { unsigned char i; Start_I2c(); /*启动总线*/ SendByte(sla); /*发送器件地址*/ if(ack==0) return(0); SendByte(suba); /*发送器件子地址*/ if(ack==0)return(0); for(i=0;i Stop_I2c(); /*结束总线*/ return(1); } /******************************************************************* 向有子地址器件读取多字节数据函数 函数原型: bit RecndStr(UCHAR sla,UCHAR suba,ucahr *s,UCHAR no); 功能: 从启动总线到发送地址,子地址,读数据,结束总线的全过程,从器件 地址sla,子地址suba,读出的内容放入s指向的存储区,读no个字节。 如果返回1表示操作成功,否则操作有误。 注意: 使用前必须已结束总线。 ********************************************************************/ bit IRcvStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no) 2 4 { unsigned char i; Start_I2c(); /*启动总线*/ SendByte(sla); /*发送器件地址*/ if(ack==0)return(0); SendByte(suba); /*发送器件子地址*/ if(ack==0)return(0); Start_I2c(); /*重新启动总线*/ SendByte(sla+1); if(ack==0)return(0); for(i=0;i *s=RcvByte(); Ack_I2c(1); /*发送非应位*/ Stop_I2c(); /*结束总线*/ return(1); } LED程序 #include uchar code tablenum[]= \"01234567\"; uchar code table[]= \"00.0 || 00.0\"; uchar code table1[]=\" 00:00:00\"; void delay(uint z) { uint x,y; for(x=z;x>0;x--) for(y=110;y>0;y--); } void write_com(uchar com) 2 5 { rs=0; lcden=0; P0=com; delay(5); lcden=1; delay(5); lcden=0; } void write_date(uchar dat) { rs=1; lcden=0; P0=dat; delay(5); lcden=1; delay(5); lcden=0; } void init() { uchar num; lcden=0; // fen=59; // miao=53; // shi=23; write_com(0x38); write_com(0x0c); write_com(0x06); write_com(0x01); write_com(0x80); for(num=0;num<13;num++) { write_date(table[num]); delay(5); } write_com(0x80+0x40); for(num=0;num<12;num++) { write_date(table1[num]); delay(5); } 2 6 TMOD=0x01; TH0=(65536-50000)/256; TL0=(65536-50000)%256; EA=1; ET0=1; TR0=1; } void write_sfm(uchar add,uchar dat)//写地址和自动显示两位数时间 { uchar s,g; s=dat/10; g=dat%10; write_com(0x80+0x40+add); write_date(tablenum[s]); write_date(tablenum[g]); } void write_sfm1(uchar add,uchar dat) //写温度值十位地址写4 个位为5 小数为7 { write_com(0x80+add); write_date(tablenum[dat]); } /*************************此部分为I2C总线的驱动程序*************************************/ #include #define NOP() _nop_() /* 定义空指令 */ #define _Nop() _nop_() /*定义空指令*/ sbit SCL=P2^1; //I2C 时钟 sbit SDA=P2^0; //I2C 数据 bit ack; /*应答标志位*/ /******************************************************************* 起动总线函数 函数原型: void Start_I2c(); 功能: 启动I2C总线,即发送I2C起始条件. ********************************************************************/ 2 7 void Start_I2c() { SDA=1; /*发送起始条件的数据信号*/ _Nop(); SCL=1; _Nop(); /*起始条件建立时间大于4.7us,延时*/ _Nop(); _Nop(); _Nop(); _Nop(); SDA=0; /*发送起始信号*/ _Nop(); /* 起始条件锁定时间大于4μs*/ _Nop(); _Nop(); _Nop(); _Nop(); SCL=0; /*钳住I2C总线,准备发送或接收数据 */ _Nop(); _Nop(); } /******************************************************************* 结束总线函数 函数原型: void Stop_I2c(); 功能: 结束I2C总线,即发送I2C结束条件. ********************************************************************/ void Stop_I2c() { SDA=0; /*发送结束条件的数据信号*/ _Nop(); /*发送结束条件的时钟信号*/ SCL=1; /*结束条件建立时间大于4μs*/ _Nop(); _Nop(); _Nop(); _Nop(); _Nop(); SDA=1; /*发送I2C总线结束信号*/ _Nop(); _Nop(); _Nop(); _Nop(); } /******************************************************************* 2 8 字节数据发送函数 函数原型: void SendByte(UCHAR c); 功能: 将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对 此状态位进行操作.(不应答或非应答都使ack=0) 发送数据正常,ack=1; ack=0表示被控器无应答或损坏。 ********************************************************************/ void SendByte(unsigned char c) { unsigned char BitCnt; for(BitCnt=0;BitCnt<8;BitCnt++) /*要传送的数据长度为8位*/ { if((c< _Nop(); /*保证时钟高电平周期大于4μs*/ _Nop(); _Nop(); _Nop(); SCL=0; } _Nop(); _Nop(); SDA=1; /*8位发送完后释放数据线,准备接收应答位*/ _Nop(); _Nop(); SCL=1; _Nop(); _Nop(); _Nop(); if(SDA==1)ack=0; else ack=1; /*判断是否接收到应答信号*/ SCL=0; _Nop(); _Nop(); } /******************************************************************* 字节数据接收函数 函数原型: UCHAR RcvByte(); 2 9 功能: 用来接收从器件传来的数据,并判断总线错误(不发应答信号), 发完后请用应答函数应答从机。 ********************************************************************/ unsigned char RcvByte() { unsigned char retc; unsigned char BitCnt; retc=0; SDA=1; /*置数据线为输入方式*/ for(BitCnt=0;BitCnt<8;BitCnt++) { _Nop(); SCL=0; /*置时钟线为低,准备接收数据位*/ _Nop(); _Nop(); /*时钟低电平周期大于4.7μs*/ _Nop(); _Nop(); _Nop(); SCL=1; /*置时钟线为高使数据线上数据有效*/ _Nop(); _Nop(); retc=retc<<1; if(SDA==1) retc=retc+1; /*读数据位,接收的数据位放入retc中 */ _Nop(); _Nop(); } SCL=0; _Nop(); _Nop(); return(retc); } /******************************************************************** 应答子函数 函数原型: void Ack_I2c(bit a); 功能: 主控器进行应答信号(可以是应答或非应答信号,由位参数a决定) ********************************************************************/ void Ack_I2c(bit a) { if(a==0) SDA=0; /*在此发出应答或非应答信号 */ 3 0 else SDA=1; _Nop(); _Nop(); _Nop(); SCL=1; _Nop(); _Nop(); /*时钟低电平周期大于4μs*/ _Nop(); _Nop(); _Nop(); SCL=0; _Nop(); _Nop(); } /*清时钟线,钳住I2C总线以便继续接收*/ 3 1
因篇幅问题不能全部显示,请点此查看更多更全内容