《点位关系对应的多点温度测量问题的最终结果》过去的多点温度测量并显示模型,Proteus模拟时LCD1602上一阵温度值,前后无序的显示以后你搞不清哪个DS18B20对应哪个温度值,这样造成很难实用。
我对程序进行了研究解读后发现,DS18B20的每个器件的序列号都是存在的,只是没有对应图中的模型号,比如:
U5是ROMData5={0x28,0x34, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0x52}; //U5其温度是25.5度, U4是ROMData4={0x28,0x32, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0xE0}; //U4其温度是17.0度, 那么,只要查询到序列号给定对应的器件号,并将器件号和温度存储在数据结构中即可。
其他的我就不多说了,请看我的具体做法。
第一、 改变数据结构,增加器件号。
在DS18B20.h内存储着数据结构,在数据结构中增加了btNumber这保证了,前面的数据都跟“检测头编号”对应成了一组数据。
当然你可以再增加检测头名称和检测位置等,这样就更实用了。
第二、 调试系列号与检测头编号的一致对应性 在DS18B20.c现在屏蔽的这一块是用来做Proteus单步调节读取序列码的。对于有脉冲时间要求的数据读取或存储来说,如果不调试根本不知道结果是什么。
当你通过调试发现可以对应的时候,你就可以把两者关联起来了。
第三、 序列号与器件号对应存储程序 程序在DS18B20.c中,对于八个器件进行序列号查询,并将查询结果与检测头编号一一对应起来,并存储。
当然也可以利用该程序存储你自己定义的比如检测头名称和检测位置等。
第四、 设置温度显示框架 在Main.c的主程序循环显示中,先显示框架结构。如不满意可自行调整。
第五、 设置温度数值显示架构 在Main.c的主程序中,有一个数据值显示结构,它是与框架结构对应的。
第六、 仿真运行的结果如下
个别显示的温度值,是因为放不下所以进行了收缩,从而造成字体变形。如U8=-18.6收缩以后看起来有点像-13.5’C。等你仿真实际看时就会正常。 温度显示结构如图。如果想显示其他内容,那就需要自行安排了。
第七、 Keil C程序结构
第八、 压缩文件结构 这样做的目的是避免你在改动程序的时候,改错了,你又找不回来源程序。最后你不得不放弃。这样在Keil C下永远存储着一套正确的程序,你可以在Code下放心修改了。而且这种存储结构会让你思路更加清晰。
Main.C:
- #include <Intrins.h>
- #include <AT89X52.H>
- #include "DS1602.h"
- #include "DS18B20.h"
- TEMPDATA m_TempData;
- //数据处理子程序
- void DataProcess()
- {
- m_TempData = ReadTemperature();
- // DisplayOne(1, 4, m_TempData.btNumber, 1);
- if (m_TempData.btNegative)
- {
- DisplayOne(1, 6, '-', 0);
- }
- else
- {
- DisplayOne(1, 6, m_TempData.btThird, 1);
- }
- DisplayOne(1, 7, m_TempData.btSecond, 1);
- DisplayOne(1, 8, m_TempData.btFirst, 1);
- DisplayOne(1, 10, m_TempData.btDecimal, 1);
- DisplayOne(2, 3, m_TempData.btNumber, 1);
- }
- void main()
- {
- //GetROMSequence();
- unsigned char a=0;
- Clear();
- Init();
- DisplayString(0, 0, " Temperature");
- DisplayOne(1, 9, '.', 0);
- DisplayOne(1, 11, '`', 0);
- DisplayOne(1, 12, 'C', 0);
- DisplayOne(2, 2, 'U', 0);
- DisplayOne(2, 4, '=', 0);
- while (1)
- {
- a++;
- if(a > 9) a = 0;
- DataProcess();
- }
- }
DS18B20.C://头文件包含
- #include <AT89X52.H>
- #include <Intrins.h>
- #include "DS18B20.h"
- //引脚定义
- sbit DQ = P2^7; //数据线端口
- //DS18B20序列号,通过调用GetROMSequence()函数在P1口读出(读8次)
- const unsigned char code ROMData1[8] = {0x28, 0x33, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0xD7}; //U1
- const unsigned char code ROMData2[8] = {0x28, 0x30, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0x8E}; //U2
- const unsigned char code ROMData3[8] = {0x28, 0x31, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0xB9}; //U3
- const unsigned char code ROMData4[8] = {0x28, 0x32, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0xE0}; //U4
- const unsigned char code ROMData5[8] = {0x28, 0x34, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0x52}; //U5
- const unsigned char code ROMData6[8] = {0x28, 0x35, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0x65}; //U6
- const unsigned char code ROMData7[8] = {0x28, 0x36, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0x3C}; //U7
- const unsigned char code ROMData8[8] = {0x28, 0x37, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0x0B}; //U8
- //延时16us子函数
- void Delay16us()
- {
- unsigned char a;
- for (a = 0; a < 4; a++);
- }
- //延时60us子函数
- void Delay60us()
- {
- unsigned char a;
- for (a = 0; a < 18; a++);
- }
- //延时480us子函数
- void Delay480us()
- {
- unsigned char a;
- for (a = 0; a < 158; a++);
- }
- //延时240us子函数
- void Delay240us()
- {
- unsigned char a;
- for (a = 0; a < 78; a++);
- }
- //延时500ms子函数
- void Delay500ms()
- {
- unsigned char a, b, c;
- for (a = 0; a < 250; a++)
- for (b = 0; b < 3; b++)
- for (c = 0; c < 220; c++);
- }
- //芯片初始化
- void Initialization()
- {
- while(1)
- {
- DQ = 0;
- Delay480us(); //延时480us
- DQ = 1;
- Delay60us(); //延时60us
- if(!DQ) //收到ds18b20的应答信号
- {
- DQ = 1;
- Delay240us(); //延时240us
- break;
- }
- }
- }
- //写一个字节(从低位开始写)
- void WriteByte(unsigned char btData)
- {
- unsigned char i, btBuffer;
- for (i = 0; i < 8; i++)
- {
- btBuffer = btData >> i;
- if (btBuffer & 1)
- {
- DQ = 0;
- _nop_();
- _nop_();
- DQ = 1;
- Delay60us();
- }
- else
- {
- DQ = 0;
- Delay60us();
- DQ = 1;
- }
- }
- }
- //读一个字节(从低位开始读)
- unsigned char ReadByte()
- {
- unsigned char i, btDest;
- for (i = 0; i < 8; i++)
- {
- btDest >>= 1;
- DQ = 0;
- _nop_();
- _nop_();
- DQ = 1;
- Delay16us();
- if (DQ) btDest |= 0x80;
- Delay60us();
- }
- return btDest;
- }
- //序列号匹配
- void MatchROM(const unsigned char *pMatchData)
- {
- unsigned char i;
- Initialization();
- WriteByte(MATCH_ROM);
- for (i = 0; i < 8; i++) WriteByte(*(pMatchData + i));
- }
- //得到64位ROM序列(在P1口显示,必须与Proteus联调且在单步调试下才能得到)
- /*void GetROMSequence()
- {
- unsigned char i;
- Initialization();
- WriteByte(READ_ROM);
- for (i = 0; i < 8; i++)
- P1 = ReadByte();
- }*/
- //读取温度值
- TEMPDATA ReadTemperature()
- {
- TEMPDATA TempData;
- unsigned int iTempDataH;
- unsigned char btDot, iTempDataL;
- static unsigned char i = 0;
- TempData.btNegative = 0; //为0温度为正
- i++;
- if (i == 9) i = 1;
- Initialization();
- WriteByte(SKIP_ROM); //跳过ROM匹配
- WriteByte(TEMP_SWITCH); //启动转换
- Delay500ms(); //调用一次就行
- Delay500ms();
- Initialization();
- //多个芯片的时候用MatchROM(ROMData)换掉WriteByte(SKIP_ROM)
- switch (i)
- {
- case 1 : MatchROM(ROMData1); TempData.btNumber = 1; break; //匹配1
- case 2 : MatchROM(ROMData2); TempData.btNumber = 2; break; //匹配2
- case 3 : MatchROM(ROMData3); TempData.btNumber = 3; break; //匹配3
- case 4 : MatchROM(ROMData4); TempData.btNumber = 4; break; //匹配4
- case 5 : MatchROM(ROMData5); TempData.btNumber = 5; break; //匹配5
- case 6 : MatchROM(ROMData6); TempData.btNumber = 6; break; //匹配6
- case 7 : MatchROM(ROMData7); TempData.btNumber = 7; break; //匹配7
- case 8 : MatchROM(ROMData8); TempData.btNumber = 8; break; //匹配8
- }
- //WriteByte(SKIP_ROM); //跳过ROM匹配(单个芯片时用这句换掉上面的switch)
- WriteByte(READ_MEMORY); //读数据
- iTempDataL = ReadByte();
- iTempDataH = ReadByte();
- iTempDataH <<= 8;
- iTempDataH |= iTempDataL;
- if (iTempDataH & 0x8000)
- {
- TempData.btNegative = 1;
- iTempDataH = ~iTempDataH + 1; //负数求补
- }
- //为了省去浮点运算带来的开销,而采用整数和小数部分分开处理的方法(没有四舍五入)
- btDot = (unsigned char)(iTempDataH & 0x000F); //得到小数部分
- iTempDataH >>= 4; //得到整数部分
- btDot *= 5; //btDot*10/16得到转换后的小数数据
- btDot >>= 3;
- //数据处理
- TempData.btThird = (unsigned char)iTempDataH / 100;
- TempData.btSecond = (unsigned char)iTempDataH % 100 / 10;
- TempData.btFirst = (unsigned char)iTempDataH % 10;
- TempData.btDecimal = btDot;
- return TempData;
- }
复制代码
DS18B20.h:
#ifndef __DS18B20_H__#define __DS18B20_H__
//ROM操作命令#define READ_ROM 0x33 //读ROM #define SKIP_ROM 0xCC //跳过ROM #define MATCH_ROM 0x55 //匹配ROM #define SEARCH_ROM 0xF0 //搜索ROM #define ALARM_SEARCH 0xEC //告警搜索
//存储器操作命令#define ANEW_MOVE 0xB8 //重新调出E^2数据#define READ_POWER 0xB4 //读电源#define TEMP_SWITCH 0x44 //启动温度变换 #define READ_MEMORY 0xBE //读暂存存储器#define COPY_MEMORY 0x48 //复制暂存存储器#define WRITE_MEMORY 0x4E //写暂存存储器
//数据存储结构typedef struct tagTempData{ unsigned char btThird; //百位数据 unsigned char btSecond; //十位数据 unsigned char btFirst; //个位数据 unsigned char btDecimal; //小数点后一位数据 unsigned char btNegative; //是否为负数 unsigned char btNumber; //检测头编号 }TEMPDATA;
//芯片初始化void Initialization();
//写一个字节(从低位开始写)void WriteByte(unsigned char btData);
//读一个字节(从低位开始读)unsigned char ReadByte();
//序列号匹配void MatchROM(const unsigned char *pMatchData);
//读取温度值TEMPDATA ReadTemperature();
//得到64位ROM序列void GetROMSequence();
#endif
|