基于51单片机、K型热电偶、MAX6675的8路温度显示系统
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
自动化工程训练课程设计
学院名称信息科学与工程学院
专业班级自动化1202班
姓名黎毅刚
指导老师刘芳
目录第一章绪论
第二章方案论证
2.1温度采集方案
2.2显示界面方案
第三章系统整体设计
3.1 系统总体分析
3.2设计原理
第四章各个元器件及芯片简介
4.1 AT89C51单片机介绍
4.2 K型热电偶简介
4.3 MAX6675简介
4.4 LCD12864简介
第五章各部分电路设计
5.1温度采集电路
5.2数据处理电路
5.3温度显示电路
5.4超限报警电路
第六章心得体会
附录1 硬件仿真图与运行效果展示附录2 软件代码
第一章绪论
在工业生产中,需要检测工艺生产线的温度,而且这个温度范围还很大。
该系统采集主要以Atmel公司的AT89C51单片机为控制处理核心,由它完成对数据的采集处理以及控制数据的无线传输。
AT89C51单片机是一种低功耗/低电压/高性能的8位单片机,片内带有一个8KB的可编程/可擦除/只读存储器。
无线收发一体数传MODEM模块PTR2000芯片性能优异,在业界居领先水平,它的显著特点是所需外围元件少,因而设计非常方便。
因此用来设计工业温度检测系统相当的合适。
在本文中,主要说明单片机与K型热电偶以及K型热电偶模数转换器—MAX6675的组合,形成单片机的温度检测系统。
包括:如何针对系统的需求选择合适的温度检测器件,如何根据选择的器件设计外围电路和单片机的接口电路,如何编写控制温度检测器件进行数据传输的单片机程序,并简要介绍数字温度传感器MAX6675的应用。
第二章方案论证
2.1温度采集方案
方案一:模拟温度传感器。
采用热敏电阻,将温度值转换为电压值,经运算放大器放大后送A/D转换器将模拟信号变换为数字信号,再由单片机经过比较计算得到温度值。
优点:应用广泛,特别是工程领域,采用不同的热敏电阻,可实现低温到超高温的测量。
缺点:必须采用高速高位A/D转换器,系统复杂,成本高,还以引进非线性误差,得通过软件差值修正
方案二:采用集成数字温度传感器DS18B20。
该传感器采用单总线接口,能方便的与单片机通信。
测温范围从-55到+125,测温精度9-12位可调,12位时最大转换时间为750ms,但是不满足本设计的要求。
缺点:不能实现高温测量。
方案三:采用K型热电偶与K型热电偶模数转换器—MAX6675的组合,该组合采用单总线接口,能方便的与单片机通信,测量范围从0到+1050度,测温精度为12位,完全满足本设计的要求,因此采用此方案。
2.2显示界面方案
方案一:用数码管显示,优点:结构简单,成本低。
缺点:只能显示一测量点和有限的符号。
方案二:采用LCD12864显示。
可以实现中英文操作提示,方便人机交换。
能同时显示多点温度值,使用方便,而且价格适中,本系统设计为多点温度采集情况可以采用。
第三章系统总体设计
3.1 系统总体分析
本系统采用的是K型热电偶采集温度,因此本设计有温度采集部分,数据处理部分,温度显示部分,故障显示并显示部分组成。
AT89C51单片机以及单片机的外围电路由晶振电路,复位电路,温度采集电路,温度显示电路,超限报警电路组成。
系统设计框图如下:
系统设计框图 3.2设计原理
温度采集部分
先使用K 型热电偶对环境温度进行检查,再经过K 型热电偶模数转换器
—MAX6675,进行温度转换,将环境温度转换成12位二进制数据采集进单片机,以便单片机进行数据处理。
在本系统中,由于是8路温度采集,因此使用串行的方式,依次对8路温度进行采集,并用单片机的P2口来传输与反馈数据。
数据处理部分
利用算法,在单片机中对采集到的数据进行处理,并转换成百、十、个位通
过P0口进行输出。
温度显示部分
通过调用LCD 的显示函数,将温度以两列的方式实时地显示在LCD 上。
超限报警部分
通过软件算法,检测8度的温度是否在100度到999度的范围内,一旦超过
这个范围,这进行故障报警,并在LCD 上显示“超温”或者“低温”,并且同时通过蜂鸣器以及LED 灯,来进行声光报警。
第四章各个元器件及芯片简介
4.1 AT89C51单片机介绍
AT89C51单片机简介
AT89C51是一种带4K字节闪烁可编程可擦除只读存储器(FPEROM—Falsh Programmable and Erasable Read Only Memory)的低电压,高性能CMOS8位微处理器,俗称单片机。
单片机的可擦除只读存储器可以反复擦除100次。
该器件采用ATMEL高密度非易失存储器制造技术制造,与工业标准的MCS-51指令集和输出管脚相兼容。
由于将多功能8位CPU和闪烁存储器组合在单个芯片中,ATMEL的AT89C51是一种高效微控制器,AT89C2051是它的一种精简版本。
1.主要特性:
1、与MCS-51 兼容
2、4K字节可编程闪烁存储器
3、1000写/擦循环数据保留时间10年
4、全静态工作,0Hz-24Hz·三级程序存储器锁定
5、128*8位内部RAM32可编程I/O线
6、两个16位定时器/计数器
7、5个中断源
8、可编程串行通道低功耗的闲置和掉电模式
9、片内振荡器和时钟电路
2.主要管脚说明:
P0口:P0口为一个8位漏级开路双向I/O口,每脚可吸收8TTL门电流。
当P1口的管脚第一次写1时,被定义为高阻输入。
P0能够用于外部程序数据存储器,它可以被定义为数据/地址的第八位。
P1口:P1口是一个内部提供上拉电
阻的8位双向I/O口,P1口缓冲器能接收输出4TTL门电流。
P1口管脚写入1后,被内部上拉为高,可用作输入,P1口被外部下拉为低电平时,将输出电流,这是由于内部上拉的缘故。
P2口:P2口为一个内部上拉电阻的8位双向I/O口,P2口缓冲器可接收,输出4个TTL门电流,当P2口被写“1”时,其管脚被内部上拉电阻拉高,且作为输入。
并因此作为输入时,P2口的管脚被外部拉低,将
输出电流。
P2口当用于外部程序存储器或16位地址外部数据存储器进行存取时,P2口输出地址的高八位。
P3口:P3口管脚是8个带内部上拉电阻的双向I/O口,可接收输出4个TTL门电流。
当P3口写入“1”后,它们被内部上拉为高电平,
并用作输入。
作为输入,由于外部下拉为低电平,P3口将输出电流(ILL)这是由于上拉的缘故。
4.2 K型热电偶简介
K型热电偶作为一种温度传感器,K型热电偶通常和显示仪表,记录仪表和电子调节器配套使用。
K型热电偶可以直接测量各种生产中从0℃到1300℃范围的液体蒸汽和气体介质以及固体的表面温度。
K型热电偶通常由感温元件、安装固定装置和接线盒等主要部件组成,K型热电偶是目前用量最大的廉金属热电偶,其用量为其他热电偶的总和。
K型热电偶丝直径一般为1.2~4.0mm。
K型热电偶具有线性度好,热电动势较大,灵敏度高,稳定性和均匀性较好,抗氧化性能强,价格便宜等优点,能用于氧化性惰性气氛中广泛为用户所采用。
热电偶测温由热电偶、连接导线及显示仪表三部分组成。
如果将热电偶的热端加热,使得冷、热两端的温度不同,则在该热电偶回路中就会产生热电势,这种物理现象就称为热电现象(即热电效应)。
在热电偶回路中产生的电势由温差电势和接触电势两部分组成。
接触电势:它是两种电子密度不同的导体相互接触时产生的一种热电势。
当两种不同的导体A和B相接触时,假设导体A和B的电子密度分别为NA和NB 并且NA>NB,则在两导体的接触面上,电子在两个方向的扩散率就不相同,由导体A扩散到导体B的电子数比从B扩散到A的电子数要多。
导体A失去电子而
显正电,导体B获得电子而显负电。
因此,在A、B两导体的接触面上便形成一个由A到B的静电场,这个电场将阻碍扩散运动的继续进行,同时加速电子向相反方向运动,使从B到A的电子数增多,最后达到动态平衡状态。
此时A、B之间也形成一电位差,这个电位差称为接触电势。
此电势只与两种导体的性质相接触点的温度有关,当两种导体的材料一定,接触电势仅与其接点温度有关。
温度越高,导体中的电子就越活跃,由A导体扩散到B导体的电子就越多,接触面处所产生的电动势就越大,即接触电势越大。
4.3 MAX6675简介
热电偶作为一种主要的测温元件,具有结构简单、制造容易、使用方便、测温范围宽、测温精度高等特点。
但是将热电偶应用在基于单片机的嵌入式系统领域时,却存在着以下几方面的问题。
①线性:热电偶输出热电势与温度之间的关系为非线性关系,因此在应用
时必须进行线性化处理。
②冷补偿:热电偶输出的热电势为冷端保持为0℃时与测量端差值,而在
实际应用中冷端的温度是随着环境温度而变化的,故需要进行冷端补
③数字化输出与嵌入式系统接口必然要采用数字化输出及数字化接口,而
作为模拟小信号测温元件的热电偶显然无法直接满足这个要求。
因此, 若将热电偶应用于嵌入式系统时, 须进行复杂的信号放大、AD转换、查表线性化、温度补偿及数字化输出接口等软硬件设计。
如果能将上述的功能集成到一个集成电路芯片中, 即采用单芯片来完成信号放大、冷端补偿、线性化及数字化输出功能, 则将大大简化热电偶在嵌入式领域的应用设计。
MAX6675性能及结构
Maxim公司新近推出的MAX6675是一复杂的单片热电偶数字转换器, 内部
具有信号调节放大器、12位的模拟数字化热电偶转换器、冷端补偿传感和校正、数字控制器、1个SPI兼容接口和1个相关的逻辑控制。
MAX6675内部集成有冷端补偿电路;带有简单的3位串行SPI接口;可将温度信号转换成12位数字量,
温度分辨率达0.25℃;内含热电偶断线检测电路。
冷端补偿的温度范围-20℃~80℃,它的温度分辨能力为0. 25 ℃,可以测量0℃~1023.75℃的温度,工作电压为3. 0~5. 5V。
MAX6675的主要特性如下:①简单的SPI串行口温度值输出;②0℃~+1024℃的测温范围;③12位0.25℃的分辨率;④片内冷端补偿;⑤高阻抗差动输入;⑥热电偶断线检测;⑦单一+5V的电源电压;⑧低功耗特性;⑨工作温度范围-20℃~+85℃;⑩2000V的ESD信号。
该器件采用8引脚SO帖片封装。
引脚排列如图1所示,引脚功能如下表所列。
MAX6675的工作原理与功能
根据热电偶测温原理,热电偶的输出热电势不仅与测量端的温度有关,而且与冷端的温度有关,使用硬件电路进行冷端补偿时,虽能部分改善测量精度,但由于热电偶使用环境的不同及硬件电路本身的局限性,效果并不明显;而使用软件补偿,通常是使用微处理机表格法或线性电路等方法来减小热电偶本身非线性带来的测量误差,但同时也增加了程序编制及调试电路的难度。
MAX6675对其内部元器件参数进行了激光修正,从而对热电偶的非线性进行了内部修正。
同时,MAX6675内部集成的冷端补偿电路、非线性校正电路、断偶检测电路都给K型热电偶的使用带来了极大方便,其工作原理如图2所示。
(1) 温度变换
MAX6675内部具有将热电偶信号转换为与ADC输入通道兼容电压的信号调节放大器,T+和T-输入端连接到低噪声放大器A1,以保证检测输入的高精度,同时是热电偶连接导线与干扰源隔离。
热电偶输出的热电势经低噪声放大器A1放大,再经过A2电压跟随器缓冲后,送至ADC的输入端。
在将温度电压值转换为相等价的温度值之前,它需要对热电偶的冷端进行补偿,冷端温度即是
MAX6675周围温度与0℃实际参考值之间的差值。
对于K型热电偶, 电压变化率为41µ/℃, 电压可由线性公式Vout=(41µ/℃)×(tR-tAMB)来近似热电偶的
特性。
上式中, Vout为热电偶输出电压(mV), tR是测量点温度,tAMB是周围温度。
(2)冷端补偿
热电偶的功能是检测热、冷两端温度的差值,热电偶热节点温度可在0℃~+1023.75℃范围变化。
冷端即安装MAX6675的电路板周围温度,比温度在-20℃~+85℃范围内变化。
当冷端温度波动时,MAX6675仍能精确检测热端的温度变化。
(3) 热补偿
在测温应用中,芯片自热将降低MAX6675温度测量精度,误大小依赖于MAX6675封装的热传导性、安装技术和通风效果。
为降低芯片自热引起的测量误差,可在布线时使用大面积接地技术提高MAX6675温度测量精度。
(4) 噪声补偿
MAX6675的测量精度对电源耦合噪声较敏感。
为降低电源噪声影响,可在MAX6675的电源引脚附近接入1只0.1μF陶瓷旁路电容。
(5)测量精度的提高
热电偶系统的测量精度可通过以下预防措施来提高:①尽量采用不能从测量区域散热的大截面导线;②如必须用小截面导线,则只能应用在测量区域,并且在无温度变化率区域用扩展导线;③避免受能拉紧导线的机械挤压和振动;④当热电偶距离较远时,应采用双绞线作热电偶连线;⑤在温度额定值范围内使用热电偶导线;⑥避免急剧温度变化;⑦在严劣环境中,使用合适的保护套以保证热电偶导线;⑧仅在低温和小变化率区域使用扩展导线;⑨保持热电偶电阻的事件
(6) SPI串行接口
MAX6675采用标准的SPI串行外设总线与MCU接口,且MAX6675只能作为从设备。
MAX6675 SO端输出温度数据的格式如图3所示,MAX6675 SPI接口时序
如图4所示。
MAX6675从SPI串行接口输出数据的过程如下:MCU使CS变低并提供时钟信号给SCK,由SO读取测量结果。
CS变低将停止任何转换过程;CS变高将启动一个新的转换过程。
一个完整串行接口读操作需16个时钟周期,在时钟的下降沿读16个输出位,第1位和第15位是一伪标志位,并总为0;第14位到第3位为以MSB到LSB顺序排列的转换温度值;第2位平时为低,当热电偶输入开放时为高,开放热电偶检测电路完全由MAX6675实现,为开放热电偶检测器操作,T-必须接地,并使能地点尽可能接近GND脚;第1位为低以提供MAX6675器件身份码,第0位为三态。
4.4 LCD12864简介
带中文字库的128X64 是一种具有4 位/8 位并行、2 线或3 线串行多种接口方式,内部含有国标一级、二级简体中文字库的点阵图形液晶显示模块;其显示分辨率为128×64, 内置8192 个16*16 点汉字,和128 个16*8 点ASCII 字符集.利用该模块灵活的接口方式和简单、方便的操作指令,可构成全中文人机交互图形界面。
可以显示8×4 行16×16 点阵的汉字. 也可完成图形显示.低电压低功耗是其又一显著特点。
由该模块构成的液晶显示方案与同类型的图形
点阵液晶显示模块相比,不论硬件电路结构或显示程序都要简洁得多,且该模块的价格也略低于相同点阵的图形液晶模块。
第五章各部分电路设计
5.1温度采集电路
5.1.1硬件部分
该部分为8路温度采集,采用K型热电偶与K型热电偶模数转换器—MAX6675互相搭配的方式,如下图所示:
以其中一路为例,MAX6675的冷热接收端分别于热电偶的冷热端相连,其串行数据输出端分别与单片机的P2口相连,如下图所示:
之后MAX6675的时钟信号端以及使能端分别与P1.0和P1.1端相连,如下图所示:
以上就是整个温度采集部分的硬件接线图
5.1.2软件部分
由于MAX6675采用的是12位二进制的串行数据输出的方式,而且,其有效的数据分别在3~~14位,因此需要进行串行数据的移位操作,以下为部分软件算法:
for(i=0;i<16;i++)
{ Temp_1<<=1;
_nop_();
SCK=1;
if(SO1==1){Temp_1=Temp_1|0x01;}
else Temp_1=Temp_1|0x00;
_nop_();
SCK=0;
_nop_();
}
Temp_1=Temp_1<<1;
Temp_1=Temp_1>>4;
Temp_1=Temp_1*1024/4096;
以上算法把数据左移移一位,然后再右移四位,从而得到完整的12位二进制温度数据。
5.2数据处理电路
5.2.1硬件部分
该部分数据处理主要在单片机内部进行,并且将处理后的数据从P0口输出到LCD进行显示,如下图所示:
5.2.2软件部分
将处理后的数据分别处理成百、十、个位进行输出,以下为部分软件算法:if(wendu1<=999&&wendu1>=100)
{
guzhang_flag1=0;
ge1=temp1%10;
temp1=temp1/10;
shi1=temp1%10;
bai1=temp1/10;
}
通过以上算法,就可以将数据分解成百、十、个,从而方便地在LCD上显示。
5.3温度显示电路
5.3.1硬件部分
该部分是通过LCD进行对温度数据的显示其使能端与P1口相连,数据输入端与P0口相连,如下图所示:
通过以上的连接,可以实现单片机对LCD的控制以及温度数据的显示。
5.3.2软件部分
LCD上的汉字以及数据,都需要使用相应的字模软件来对汉字和数据进行编码,并存储在相应的数组中,通过相应的函数调用,将所需显示的数据,按照相应的格式显示在LCD上,以下为部分软件算法:
汉字显示函数:
void Display_HZ(uchar screen,uchar page,uchar column,uchar *p)
{
uchar i;
SelectScreen(screen);
Set_page(page); //写上半页:16*8
Set_column(column*16); //控制列
for(i=0;i<16;i++) //控制16列的数据输出,左右各64个点,可显示4个汉字
{
write_LCD_data(p[i]); //汉字的上半部分
}
Set_page(page+1); //写下半页:16*8
Set_column(column*16); //控制列
for(i=0;i<16;i++) //控制16列的数据输出
{
write_LCD_data(p[i+16]); //汉字的下半部分
}
}
数字显示函数:
void Display_ASCII(uchar screen,uchar page,uchar column,uchar *p) //左右各64个点,可显示8个字符
{
uchar i;
SelectScreen(screen);
Set_page(page);
Set_column(column);
for(i=0;i<8;i++) //显示字符上半部分:8*8
{
write_LCD_data(p[i]);
}
Set_page(page+1); //显示字符下半部分:8*8
Set_column(column);
for(i=0;i<8;i++)
{
write_LCD_data(p[i+8]);
}
}
调用方式如下:
Display_HZ(1,0,2,huan);
Display_HZ(1,0,3,ying);
Display_ASCII(1,0,0*8,shuzi[10]);
Display_ASCII(1,0,1*8,shuzi[1]);
以下为LCD显示函数部分:(以1路为例)
void Disp_temp()
{
temp1=wendu1;
if(wendu1<=999&&wendu1>=100)
{
guzhang_flag1=0;
ge1=temp1%10;
temp1=temp1/10;
shi1=temp1%10;
bai1=temp1/10;
Display_ASCII(1,0,4*8,shuzi[bai1]);
Display_ASCII(1,0,5*8,shuzi[shi1]);
Display_ASCII(1,0,6*8,shuzi[ge1]);
Display_ASCII(1,0,7*8,shuzi[12]);
}
else if(wendu1>999)
{
guzhang_flag1=1;
Display_HZ(1,0,2,chao);
Display_HZ(1,0,3,wen);
}
else if(wendu1<100)
{
guzhang_flag1=1;
Display_HZ(1,0,2,di);
Display_HZ(1,0,3,wen);
}
通过以上的软件算法,可以直观的以两列的方式显示8路温度的数值,并且当出现温度超限时,还会出现文字提示报警。
5.4超限报警电路
5.4.1硬件部分
该部分硬件上由于是声光报警,因此需要蜂鸣器和LED灯,分别将这两个部件连接至P1.2和P3.4口,对其进行控制,如下图:
5.4.2软件部分
通过设立超限标志位,当出现超限时,对标志位进行置位,并通过判断标志位,来判断是否出现超限,并报警,部分软件算法如下:
if(guzhang_flag1==1||guzhang_flag2==1||guzhang_flag3==1||guzhang_f lag4==1||guzhang_flag5==1||guzhang_flag6==1||guzhang_flag7==1||guzhan g_flag8==1)
{
SOUND=1;
LED=1;
}
else
if(guzhang_flag1==0&&guzhang_flag2==0&&guzhang_flag3==0&&guzhang_flag 4==0&&guzhang_flag5==0&&guzhang_flag6==0&&guzhang_flag7==0&&guzhang_f lag8==0)
{
SOUND=0;
LED=0;
}
通过以上的软硬件结合,就能够顺利的实现超限报警功能。
第六章心得体会
通过这次工程训练课程设计,自己对理论知识的掌握有了更加深刻的体会。
记得刚开始拿到题目时,到网上搜索了一下,发现有很多温度检测的课程设计,心里还曾经暗暗地庆幸自己选了一个容易的题目,但是到后面做的时候,在发现老师给我们挖了一个坑。
首先,网上的资料没有这么宽的温度检测范围,其次就算有个别符合要求的温度范围,也只是一路的温度检测。
所以,在前期的设计中,自己真的是遇到了问题,不过,功夫不负有心人。
我先一个模块,一个模块的调试,首先需要解决的是温度检测范围的问题,因此经过一番查找,终于发现了MAX6675这个神奇的东西,得意解决了范围问题。
然后就是多路温度检测的问题,我先检测一路是否可行,后面发现一路确实可行,最后延伸到八路,反复的调整数据,终于解决了多路的问题。
最后是显示,还好自己曾经使用过LCD12864,上手也比较容易。
就是通过这样一个模块,一个模块的调试,最终把这个有点坑的题目给解决了。
在完成题目的那一刻,自己心中真的欣喜不已,当然其中还有一些不足,就是温度检测还会有一些误差,温度越高,误差越大,不过都在5度以内,以工业要求,应该是可行的。
还有就是如果有个上位机功能,系统功能会更加的实用一些。
总的来说,这次课设还是顺利地完成了,尽管其中还有一些不足,但是自己在单片机方面也进步了许多,希望在今后的学习生活中,能够不断地进步,最后感谢老师给我这次进步的机会,谢谢。
附录1 硬件仿真图
附录2 软件代码
以下是软件部分的结构截图,读者只需将相应的的软件部分复制,按截图的结构来搭构,就能组成一个完整的软件部分。
当然由于时间仓促,还有不足的地方,望读者改进。
main.c部分是主程序部分,对温度数据进行处理并换算,如下:
main.c
#include<reg51.h>
#include<intrins.h>
#include<hz.h>
#include<12864.h>
#define uchar unsigned char
#define uint unsigned int
sbit SO1=P2^0; //串行数据输入
sbit SO2=P2^1;
sbit SO3=P2^2;
sbit SO4=P2^3;
sbit SO5=P2^4;
sbit SO6=P2^5;
sbit SO7=P2^6;
sbit SO8=P2^7;
sbit LED=P3^4;
sbit SOUND=P1^2;
sbit SCK=P1^0;
sbit CS=P1^1;
uint j,h;
uchar
guzhang_flag1=0,guzhang_flag2=0,guzhang_flag3=0,guzhang_flag4=0,guzhang_flag5=0,guzhan g_flag6=0,guzhang_flag7=0,guzhang_flag8=0;
float wendu1,wendu2,wendu3,wendu4,wendu5,wendu6,wendu7,wendu8; void Re_Convert();
uint Re_Convert_1();
uint Re_Convert_2();
uint Re_Convert_3();
uint Re_Convert_4();
uint Re_Convert_5();
uint Re_Convert_6();
uint Re_Convert_7();
uint Re_Convert_8();
void Disp_temp();
uchar bai1=0,bai2=0,bai3=0,bai4=0,bai5=0,bai6=0,bai7=0,bai8=0; uchar shi1=0,shi2=0,shi3=0,shi4=0,shi5=0,shi6=0,shi7=0,shi8=0; uchar ge1=0,ge2=0,ge3=0,ge4=0,ge5=0,ge6=0,ge7=0,ge8=0;
uint P_Temp;
uint temp1,temp2,temp3,temp4,temp5,temp6,temp7,temp8;
uchar SO[8];
void delayms(uint z)
{
uchar y;
while(z--)
{ for(y=0;y<120;y++);}
}
uint Re_Convert_1()
{ uchar i;
unsigned long Temp_1;
Temp_1=0;
CS=1;
SCK=0;
_nop_();_nop_();
CS=0;
for(i=0;i<16;i++)
{ Temp_1<<=1;
_nop_();
SCK=1;
if(SO1==1){Temp_1=Temp_1|0x01;}
else Temp_1=Temp_1|0x00;
_nop_();
SCK=0;
_nop_();
}
Temp_1=Temp_1<<1;
Temp_1=Temp_1>>4;
Temp_1=Temp_1*1024/4096;
return(Temp_1);
}
uint Re_Convert_2()
{ uchar i;
unsigned long Temp_2;
Temp_2=0;
CS=1;
SCK=0;
_nop_();_nop_();
CS=0;
for(i=0;i<16;i++)
{ Temp_2<<=1;
_nop_();
SCK=1;
if(SO2==1){Temp_2=Temp_2|0x01;}
else Temp_2=Temp_2|0x00;
_nop_();
SCK=0;
_nop_();
}
Temp_2=Temp_2<<1;
Temp_2=Temp_2>>4;
Temp_2=Temp_2*1024/4096;
return(Temp_2);
}
uint Re_Convert_3()
{ uchar i;
unsigned long Temp_3;
Temp_3=0;
CS=1;
SCK=0;
_nop_();_nop_();
CS=0;
for(i=0;i<16;i++)
{ Temp_3<<=1;
_nop_();
SCK=1;
if(SO3==1){Temp_3=Temp_3|0x01;}
else Temp_3=Temp_3|0x00;
_nop_();
SCK=0;
_nop_();
}
Temp_3=Temp_3<<1;
Temp_3=Temp_3>>4;
Temp_3=Temp_3*1024/4096;
return(Temp_3);
}
uint Re_Convert_4()
{ uchar i;
unsigned long Temp_4;
Temp_4=0;
CS=1;
SCK=0;
_nop_();_nop_();
CS=0;
for(i=0;i<16;i++)
{ Temp_4<<=1;
_nop_();
SCK=1;
if(SO4==1){Temp_4=Temp_4|0x01;}
else Temp_4=Temp_4|0x00;
_nop_();
SCK=0;
_nop_();
}
Temp_4=Temp_4<<1;
Temp_4=Temp_4>>4;
Temp_4=Temp_4*1024/4096;
return(Temp_4);
}
uint Re_Convert_5()
{ uchar i;
unsigned long Temp_5;
Temp_5=0;
CS=1;
SCK=0;
_nop_();_nop_();
CS=0;
for(i=0;i<16;i++)
{ Temp_5<<=1;
_nop_();
SCK=1;
if(SO5==1){Temp_5=Temp_5|0x01;}
else Temp_5=Temp_5|0x00;
_nop_();
SCK=0;
_nop_();
}
Temp_5=Temp_5<<1;
Temp_5=Temp_5>>4;
Temp_5=Temp_5*1024/4096;
return(Temp_5);
}
uint Re_Convert_6()
{ uchar i;
unsigned long Temp_6;
Temp_6=0;
CS=1;
SCK=0;
_nop_();_nop_();
CS=0;
for(i=0;i<16;i++)
{ Temp_6<<=1;
_nop_();
SCK=1;
if(SO6==1){Temp_6=Temp_6|0x01;}
else Temp_6=Temp_6|0x00;
_nop_();
SCK=0;
_nop_();
}
Temp_6=Temp_6<<1;
Temp_6=Temp_6>>4;
Temp_6=Temp_6*1024/4096;
return(Temp_6);
}
uint Re_Convert_7()
{ uchar i;
unsigned long Temp_7;
Temp_7=0;
CS=1;
SCK=0;
_nop_();_nop_();
CS=0;
for(i=0;i<16;i++)
{ Temp_7<<=1;
_nop_();
SCK=1;
if(SO7==1){Temp_7=Temp_7|0x01;}
else Temp_7=Temp_7|0x00;
_nop_();
SCK=0;
_nop_();
}
Temp_7=Temp_7<<1;
Temp_7=Temp_7>>4;
Temp_7=Temp_7*1024/4096;
return(Temp_7);
}
uint Re_Convert_8()
{ uchar i;
unsigned long Temp_8;
Temp_8=0;
CS=1;
SCK=0;
_nop_();_nop_();
CS=0;
for(i=0;i<16;i++)
{ Temp_8<<=1;
_nop_();
SCK=1;
if(SO8==1){Temp_8=Temp_8|0x01;}
else Temp_8=Temp_8|0x00;
_nop_();
SCK=0;
_nop_();
}
Temp_8=Temp_8<<1;
Temp_8=Temp_8>>4;
Temp_8=Temp_8*1024/4096; return(Temp_8);
}
void Re_Convert()
{
wendu1=Re_Convert_1();
wendu2=Re_Convert_2();
wendu3=Re_Convert_3();
wendu4=Re_Convert_4();
wendu5=Re_Convert_5();
wendu6=Re_Convert_6();
wendu7=Re_Convert_7();
wendu8=Re_Convert_8();
}
void Disp_temp()
{
temp1=wendu1;
temp2=wendu2;
temp3=wendu3;
temp4=wendu4;
temp5=wendu5;
temp6=wendu6;
temp7=wendu7;
temp8=wendu8;
if(wendu1<=999&&wendu1>=100) {
guzhang_flag1=0;
ge1=temp1%10;
temp1=temp1/10;
shi1=temp1%10;
bai1=temp1/10;
Display_ASCII(1,0,4*8,shuzi[bai1]); Display_ASCII(1,0,5*8,shuzi[shi1]); Display_ASCII(1,0,6*8,shuzi[ge1]); Display_ASCII(1,0,7*8,shuzi[12]); }
else if(wendu1>999)
{
guzhang_flag1=1;
Display_HZ(1,0,2,chao);
Display_HZ(1,0,3,wen);
}
else if(wendu1<100)
{
guzhang_flag1=1;
Display_HZ(1,0,2,di);
Display_HZ(1,0,3,wen);
}
if(wendu2<=999&&wendu2>=100) {
guzhang_flag2=0;
ge2=temp2%10;
temp2=temp2/10;
shi2=temp2%10;
bai2=temp2/10;
Display_ASCII(1,2,4*8,shuzi[bai2]); Display_ASCII(1,2,5*8,shuzi[shi2]); Display_ASCII(1,2,6*8,shuzi[ge2]); Display_ASCII(1,2,7*8,shuzi[12]); }
else if(wendu2>999)
{
guzhang_flag2=1;
Display_HZ(1,2,2,chao);
Display_HZ(1,2,3,wen);
}
else if(wendu2<100)
{
guzhang_flag2=1;
Display_HZ(1,2,2,di);
Display_HZ(1,2,3,wen);
}
if(wendu3<=999&&wendu3>=100) {
guzhang_flag3=0;
ge3=temp3%10;
temp3=temp3/10;
shi3=temp3%10;
bai3=temp3/10;
Display_ASCII(1,4,4*8,shuzi[bai3]); Display_ASCII(1,4,5*8,shuzi[shi3]); Display_ASCII(1,4,6*8,shuzi[ge3]); Display_ASCII(1,4,7*8,shuzi[12]);
else if(wendu3>999)
{
guzhang_flag3=1;
Display_HZ(1,4,2,chao);
Display_HZ(1,4,3,wen);
}
else if(wendu3<100)
{
guzhang_flag3=1;
Display_HZ(1,4,2,di);
Display_HZ(1,4,3,wen);
}
if(wendu4<=999&&wendu4>=100) {
guzhang_flag4=0;
ge4=temp4%10;
temp4=temp4/10;
shi4=temp4%10;
bai4=temp4/10;
Display_ASCII(1,6,4*8,shuzi[bai4]); Display_ASCII(1,6,5*8,shuzi[shi4]); Display_ASCII(1,6,6*8,shuzi[ge4]); Display_ASCII(1,6,7*8,shuzi[12]); }
else if(wendu4>999)
{
guzhang_flag4=1;
Display_HZ(1,6,2,chao);
Display_HZ(1,6,3,wen);
}
else if(wendu4<100)
{
guzhang_flag4=1;
Display_HZ(1,6,2,di);
Display_HZ(1,6,3,wen);
}
if(wendu5<=999&&wendu5>=100) {
guzhang_flag5=0;
ge5=temp5%10;
temp5=temp5/10;
shi5=temp5%10;
bai5=temp5/10;
Display_ASCII(2,0,4*8,shuzi[bai5]); Display_ASCII(2,0,5*8,shuzi[shi5]); Display_ASCII(2,0,6*8,shuzi[ge5]); Display_ASCII(2,0,7*8,shuzi[12]);
}
else if(wendu5>999)
{
guzhang_flag5=1;
Display_HZ(2,0,2,chao);
Display_HZ(2,0,3,wen);
}
else if(wendu5<100)
{
guzhang_flag5=1;
Display_HZ(2,0,2,di);
Display_HZ(2,0,3,wen);
}
if(wendu6<=999&&wendu6>=100) {
guzhang_flag6=0;
ge6=temp6%10;
temp6=temp6/10;
shi6=temp6%10;
bai6=temp6/10;
Display_ASCII(2,2,4*8,shuzi[bai6]); Display_ASCII(2,2,5*8,shuzi[shi6]); Display_ASCII(2,2,6*8,shuzi[ge6]); Display_ASCII(2,2,7*8,shuzi[12]); }
else if(wendu6>999)
{
guzhang_flag6=1;
Display_HZ(2,2,2,chao);
Display_HZ(2,2,3,wen);
}
else if(wendu6<100)
{
guzhang_flag6=1;
Display_HZ(2,2,2,di);
Display_HZ(2,2,3,wen);
}
if(wendu7<=999&&wendu7>=100) {
guzhang_flag7=0;
ge7=temp7%10;
temp7=temp7/10;
shi7=temp7%10;
bai7=temp7/10;
Display_ASCII(2,4,4*8,shuzi[bai7]); Display_ASCII(2,4,5*8,shuzi[shi7]); Display_ASCII(2,4,6*8,shuzi[ge7]); Display_ASCII(2,4,7*8,shuzi[12]); }
else if(wendu7>999)
{
guzhang_flag7=1;
Display_HZ(2,4,2,chao);
Display_HZ(2,4,3,wen);
}
else if(wendu7<100)
{
guzhang_flag7=1;
Display_HZ(2,4,2,di);
Display_HZ(2,4,3,wen);
}
if(wendu8<=999&&wendu8>=100) {
guzhang_flag8=0;
ge8=temp8%10;
temp8=temp8/10;
shi8=temp8%10;
bai8=temp8/10;
Display_ASCII(2,6,4*8,shuzi[bai8]); Display_ASCII(2,6,5*8,shuzi[shi8]); Display_ASCII(2,6,6*8,shuzi[ge8]); Display_ASCII(2,6,7*8,shuzi[12]); }
else if(wendu8>999)
{
guzhang_flag8=1;
Display_HZ(2,6,2,chao);
Display_HZ(2,6,3,wen);
}
else if(wendu8<100)
{
guzhang_flag8=1;
Display_HZ(2,6,2,di);
Display_HZ(2,6,3,wen);
}
if(guzhang_flag1==1||guzhang_flag2==1||guzhang_flag3==1||guzhang_flag4==1||guzhang_flag5= =1||guzhang_flag6==1||guzhang_flag7==1||guzhang_flag8==1)
{
SOUND=1;
LED=1;
}
else
if(guzhang_flag1==0&&guzhang_flag2==0&&guzhang_flag3==0&&guzhang_flag4==0&&guzh ang_flag5==0&&guzhang_flag6==0&&guzhang_flag7==0&&guzhang_flag8==0)
{
SOUND=0;
LED=0;
}
}
void main()
{
init_LCD();
Display_interface();
delayms(2000);
ClearScreen(0);
while(1)
{
Re_Convert();
Disp_temp();
Display_kuohao();
}
}
REG51.H部分只是对51单片机个个端口的定义,不加入程序结构也可以,如下:/*--------------------------------------------------------------------------
REG51.H
Header file for generic 80C51 and 80C31 microcontroller.
Copyright (c) 1988-2002 Keil Elektronik GmbH and Keil Software, Inc.
All rights reserved.
--------------------------------------------------------------------------*/
#ifndef __REG51_H__
#define __REG51_H__
/* BYTE Register */ sfr P0 = 0x80;
sfr P1 = 0x90;
sfr P2 = 0xA0;
sfr P3 = 0xB0;
sfr PSW = 0xD0;
sfr ACC = 0xE0;
sfr B = 0xF0;
sfr SP = 0x81;
sfr DPL = 0x82;
sfr DPH = 0x83;
sfr PCON = 0x87;
sfr TCON = 0x88;
sfr TMOD = 0x89;
sfr TL0 = 0x8A;
sfr TL1 = 0x8B;
sfr TH0 = 0x8C;
sfr TH1 = 0x8D;
sfr IE = 0xA8;
sfr IP = 0xB8;
sfr SCON = 0x98;
sfr SBUF = 0x99;
/* BIT Register */ /* PSW */
sbit CY = 0xD7; sbit AC = 0xD6; sbit F0 = 0xD5;
sbit RS1 = 0xD4;
sbit RS0 = 0xD3;
sbit OV = 0xD2; sbit P = 0xD0;
/* TCON */
sbit TF1 = 0x8F;
sbit TR1 = 0x8E;
sbit TF0 = 0x8D;
sbit TR0 = 0x8C;
sbit IE1 = 0x8B;
sbit IT1 = 0x8A;
sbit IE0 = 0x89;
sbit IT0 = 0x88;
/* IE */
sbit EA = 0xAF;
sbit ES = 0xAC;
sbit ET1 = 0xAB;
sbit EX1 = 0xAA;
sbit ET0 = 0xA9;
sbit EX0 = 0xA8;
/* IP */
sbit PS = 0xBC;
sbit PT1 = 0xBB;
sbit PX1 = 0xBA;
sbit PT0 = 0xB9;
sbit PX0 = 0xB8;
/* P3 */
sbit RD = 0xB7;
sbit WR = 0xB6;
sbit T1 = 0xB5;
sbit T0 = 0xB4;
sbit INT1 = 0xB3;
sbit INT0 = 0xB2;
sbit TXD = 0xB1;
sbit RXD = 0xB0;
/* SCON */
sbit SM0 = 0x9F;
sbit SM1 = 0x9E;
sbit SM2 = 0x9D;
sbit REN = 0x9C;
sbit TB8 = 0x9B;
sbit RB8 = 0x9A;
sbit TI = 0x99;
sbit RI = 0x98;
#endif
INTRINS.H只是对数据的结构进行宏定义,如果你在主程序结构中已经定义,可以不要这部分,如下:
/*--------------------------------------------------------------------------
INTRINS.H
Intrinsic functions for C51.
Copyright (c) 1988-2004 Keil Elektronik GmbH and Keil Software, Inc.
All rights reserved.
--------------------------------------------------------------------------*/
#ifndef __INTRINS_H__
#define __INTRINS_H__
extern void _nop_ (void);
extern bit _testbit_ (bit);
extern unsigned char _cror_ (unsigned char, unsigned char);
extern unsigned int _iror_ (unsigned int, unsigned char);
extern unsigned long _lror_ (unsigned long, unsigned char);
extern unsigned char _crol_ (unsigned char, unsigned char);
extern unsigned int _irol_ (unsigned int, unsigned char);
extern unsigned long _lrol_ (unsigned long, unsigned char);
extern unsigned char _chkfloat_(float);
extern void _push_ (unsigned char _sfr);
extern void _pop_ (unsigned char _sfr);
#endif
hz.h存放的是12864需要显示的各数据的字模信息,如果读者需要修改字模信息,推荐使用LCD点阵提取工具zimo221,不过需要注意,这个字模提取工具下载安装之后,需要设置一下,如下图:(一定要这么设置,才不会显示乱码,注意!!!)
hz.h
unsigned char code shuzi[13][16]={/*-- 文字: 0 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00,
/*-- 文字: 1 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,
/*-- 文字: 2 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00,
/*-- 文字: 3 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00,
/*-- 文字: 4 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00,
/*-- 文字: 5 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00,
/*-- 文字: 6 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00,
/*-- 文字: 7 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,
/*-- 文字: 8 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00,
/*-- 文字: 9 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00, /*-- 文字: < --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
0x00,0x00,0x80,0x40,0x20,0x10,0x08,0x00,0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x00,
/*-- 文字: > --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
0x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00,0x00,0x20,0x10,0x08,0x04,0x02,0x01,0x00,
/*-- 文字: --*/ //空格
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, };
unsigned char code huan[]={
/*-- 文字: 欢--*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
0x04,0x24,0x44,0x84,0x64,0x9C,0x40,0x30,0x0F,0xC8,0x08,0x08,0x28,0x18,0x00,0x00, 0x10,0x08,0x06,0x01,0x82,0x4C,0x20,0x18,0x06,0x01,0x06,0x18,0x20,0x40,0x80,0x00,}; unsigned char code ying[]={
/*-- 文字: 迎--*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
0x40,0x40,0x42,0xCC,0x00,0x00,0xFC,0x04,0x02,0x00,0xFC,0x04,0x04,0xFC,0x00,0x00, 0x00,0x40,0x20,0x1F,0x20,0x40,0x4F,0x44,0x42,0x40,0x7F,0x42,0x44,0x43,0x40,0x00,}; unsigned char code shi[]={
/*-- 文字: 使--*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
0x80,0x60,0xF8,0x07,0x04,0xE4,0x24,0x24,0x24,0xFF,0x24,0x24,0x24,0xE4,0x04,0x00, 0x00,0x00,0xFF,0x00,0x80,0x81,0x45,0x29,0x11,0x2F,0x41,0x41,0x81,0x81,0x80,0x00,}; unsigned char code yong[]={
/*-- 文字: 用--*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
0x00,0x00,0xFE,0x22,0x22,0x22,0x22,0xFE,0x22,0x22,0x22,0x22,0xFE,0x00,0x00,0x00, 0x80,0x60,0x1F,0x02,0x02,0x02,0x02,0x7F,0x02,0x02,0x42,0x82,0x7F,0x00,0x00,0x00, };
unsigned char code zhi[]={
/*-- 文字: 智--*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
0x10,0x94,0x53,0x32,0x1E,0x32,0x52,0x10,0x00,0x7E,0x42,0x42,0x42,0x7E,0x00,0x00, 0x00,0x00,0x00,0xFF,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0xFF,0x00,0x00,0x00,0x00,}; unsigned char code neng[]={
/*-- 文字: 能--*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
0x08,0xCC,0x4A,0x49,0x48,0x4A,0xCC,0x18,0x00,0x7F,0x88,0x88,0x84,0x82,0xE0,0x00, 0x00,0xFF,0x12,0x12,0x52,0x92,0x7F,0x00,0x00,0x7E,0x88,0x88,0x84,0x82,0xE0,0x00, };。