求教:PROTEUS仿真MAX6675测温用LCD显示有误差是怎么回事

水浒传鲁智深 2017-10-15 12:30:11
自己编写了keilc程序,并用PROTEUS搭建了一个简单的测温电路,发现用LCD1602显示温度和热电偶温度有10度左右的差别。等温度到几百度后,误差又稍微减小了,但在热电偶温度为10度时,显示温度为0度左右,这是为什么呢?求教高手指点一下


/***************************************************
MAX6675测试程序
****************************************************/
#include <REG52.H>
#include "intrins.h"//_nop_();延时函数用

#define uchar unsigned char
#define uint unsigned int


sbit SO = P2^4; //P3.6口与SO相连
sbit SCK = P2^5; //P3.4口与SCK相连
sbit CS = P2^6; //P3.5口与CS相连

sbit wx = P2^5; // ??
sbit dx = P2^6; //??

const unsigned char DevID = 1; //本机设备ID
unsigned char buffer; //串口接收缓冲区
unsigned char rcv_buffer[20];
unsigned char send_buffer[20];
unsigned char flag_ok = 0; //接收完毕的标识
unsigned int MAX6675_Temp;
unsigned char Flag_connect;
unsigned char CRCH,CRCL;
unsigned char wd[2]; //wd[]:BCD码的温度
unsigned char flag_dis; //显示刷新的标识

unsigned char dis[4] = { 0x00, 0x00, 0x00,0x00 };
unsigned char code SMG[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e};



unsigned char data disdata[5];
int t_zhi=0;
/*********************!!!!1014待修改!!!1*********************************/
//温度值读取程序
unsigned int ReadMAX6675() //从MAX6675读取温度
{
unsigned char count;
unsigned int Value;
CS=0; //置低,使能MAX6675
SCK=0;
Value=0;
_nop_() ;
_nop_();
_nop_();
_nop_();
for(count=0;count<16;count++) //获取16位MSB
{
Value=Value<<1; //左移
SCK=1; //sck置高
_nop_() ;
_nop_();
_nop_();
_nop_();
if(SO==1) //取当前值
Value|=0x01;
SCK=0;
}
CS=1; //关闭MAX6675
return Value;
}

/*********************延时函数-毫秒*********************************/

void DelayMs(unsigned int i) //一个延时函数,这个函数在11.0592M晶振下的延时时间大概为1ms
{
unsigned int j,k;
for(j=i; j>0; j--)
for(k=114; k>0; k--);
}


/**********************************************************
LCD1602 DRIVER

File Name: LCD1602.H
**********************************************************/

#ifndef LCD_CHAR_1602_2009_6_28
#define LCD_CHAR_1602_2009_6_28

#include <intrins.h>
sbit LcdRs = P2^0; //定义端口
sbit LcdRw = P2^1;
sbit LcdEn = P2^2;
#define DBPort P1


/********************************************************
内部等待函数
********************************************************/
unsigned char LCD_Wait(void)
{
LcdRs=0;
LcdRw=1; _nop_();
LcdEn=1; _nop_();

LcdEn=0;
return DBPort;
}
/*******************************************************
向LCD写入命令或数据
*******************************************************/
#define LCD_COMMAND 0 // Command
#define LCD_DATA 1 // Data
#define LCD_CLEAR_SCREEN 0x01 // 清屏
#define LCD_HOMING 0x02 // 光标返回原点
void LCD_Write(bit style, unsigned char input)
{
LcdEn=0;
LcdRs=style;
LcdRw=0; _nop_();
DBPort=input; _nop_();//注意顺序
LcdEn=1; _nop_();//注意顺序
LcdEn=0; _nop_();
LCD_Wait();
}

/*****************************************************
设置显示模式
*****************************************************/
#define LCD_SHOW 0x04 //显示开
#define LCD_HIDE 0x00 //显示关

#define LCD_CURSOR 0x02 //显示光标
#define LCD_NO_CURSOR 0x00 //无光标

#define LCD_FLASH 0x01 //光标闪动
#define LCD_NO_FLASH 0x00 //光标不闪动

void LCD_SetDisplay(unsigned char DisplayMode)
{
LCD_Write(LCD_COMMAND, 0x08|DisplayMode);
}

/***************************************************
设置输入模式
***************************************************/
#define LCD_AC_UP 0x02
#define LCD_AC_DOWN 0x00 // default

#define LCD_MOVE 0x01 // 画面可平移
#define LCD_NO_MOVE 0x00 //default

void LCD_SetInput(unsigned char InputMode)
{
LCD_Write(LCD_COMMAND, 0x04|InputMode);
}

/***************************************************
初始化LCD
***************************************************/
void LCD_Initial()
{
LcdEn=0;
LCD_Write(LCD_COMMAND,0x38); //8位数据端口,2行显示,5*7点阵
LCD_Write(LCD_COMMAND,0x38);
LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR); //开启显示, 无光标
LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN); //清屏
LCD_SetInput(LCD_AC_UP|LCD_NO_MOVE); //AC递增, 画面不动
}

/***********************************************
液晶字符输入的位置
************************************************/
void GotoXY(unsigned char x, unsigned char y)
{
if(y==0)
LCD_Write(LCD_COMMAND,0x80|x);
if(y==1)
LCD_Write(LCD_COMMAND,0x80|(x-0x40));
}

/************************************************
将字符输出到液晶显示
************************************************/
void Print(unsigned char *str)
{
while(*str!='\0')
{
LCD_Write(LCD_DATA,*str);
str++;
}
}
#endif



void LCD_write_data(unsigned char dat)
{
DelayMs(1);
LcdRs=1;
LcdRw=0;
LcdEn=1;
DBPort=dat;
LcdEn=0;

}

unsigned int GetCurrentTemp(unsigned int CurrentValue) //获取当前温度
{
unsigned int TempValue;
TempValue=CurrentValue;
if(TempValue&0x8000) //D15=1;标识位错
{return 0; }
return 1;
if(TempValue&0x0004) //D2=1;热电偶开路
{return 1;}
return 0;
}

void tempdisp() //温度值显示
{ unsigned char i;
unsigned int TempValue;
unsigned int testD2;
int xiaoshu;
TempValue=ReadMAX6675();
testD2=GetCurrentTemp(TempValue);
TempValue=ReadMAX6675();
TempValue&=0x7ff8; //取D14位到D3的值
TempValue>>=3; //转换温度值
xiaoshu= (TempValue*1023.75/4095)*10-327;
t_zhi=xiaoshu/10;
disdata[0]=xiaoshu/10000+0x30; //千位数
xiaoshu=xiaoshu%10000;
disdata[1]=xiaoshu/1000+0x30; //百位数
xiaoshu=xiaoshu%1000;
disdata[2]=xiaoshu/100+0x30; //十位数
xiaoshu=xiaoshu%100;
disdata[3]=xiaoshu/10+0x30; //个位数
xiaoshu=xiaoshu%10;
disdata[4]=xiaoshu/1+0x30; //十分位
// LCD_set_position(68);
GotoXY(4,1);
for(i=0;i<4;i++)
LCD_write_data(disdata[i]); //显示千百十个位
LCD_write_data('.'); //显示小数点
LCD_write_data(disdata[4]); //显示十分位
LCD_write_data(0xDF); //显示dot
LCD_write_data(0x43); //显示C

}
/**********************************/


void main(void)
{
DelayMs(1);
LCD_Initial(); //LCD 初始化
DelayMs(6);
GotoXY(0,0);
Print("temperature TEST");
while(1)
{
tempdisp();
DelayMs(5);
}
}
...全文
1169 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
吾啊 2020-03-14
  • 打赏
  • 举报
回复
楼主,你后来怎么解决的啊
  • 打赏
  • 举报
回复
换 了算法-最小二乘法,解决了这个问题?
sjjyyyy 2019-12-30
  • 打赏
  • 举报
回复
求修改后的程序,谢谢!
水浒传鲁智深 2018-01-05
  • 打赏
  • 举报
回复
我后来换 了算法-最小二乘法,解决了这个问题,谢谢指导!
of123 2017-10-19
  • 打赏
  • 举报
回复
冷端补偿问题。 你可以加上一个修正算法来弥补误差。例如,测试多个温点,记录误差,然后得出一条误差线,并用一条直线来接近它。算出误差直线的斜率,作为补偿基准。有点类似插值法的意思。 当然,你要能用密集的温点得到一个误差表的话,用查表法补偿也可以。
第一章:AVR单片机C语言程序设计概述 1.1 AVR单片机简介 1.2 AVR Studio+WinAVR开发环境安装及应用 1.3 AVR-GCC程序设计基础 1.4 程序与数据内存访问 1.5 I/O端口编程 1.6 外设相关寄存器及应用 1.7 中断服务程序 1.8 GCC在AVR单片机应用系统开发中的优势 第二章:PROTEUS操作基础 2.1 PROTEUS操作界面简介 2.2 仿真电路原理图设计 2.3 元件选择 2.4 仿真运行 2.5 PROTEUS与AVR Studio的联合调试 2.6 PROTEUS在AVR单片机应用系统开发中的优势 第三章:基础程序设计 3.1 闪烁的LED 3.2 左右来回的流水灯 3.3 花样流水灯 3.4 LED模拟交通灯 3.5 单只数码管循环显示0~9 3.6 8只数码管滚动显示单个数字 3.7 8只数码管显示多个不同字符 3.8 K1~K4控制LED移位 3.9 数码管显示4×4键盘矩阵按键 3.10 数码管显示拨码开关编码 3.11 继电器控制照明设备 3.12 开关控制报警器 3.13 按键发音 3.14 INT0中断计数 3.15 INT0及INT1中断计数 3.16 TIMER0控制单只LED闪烁 3.17 TIMER0控制的流水灯 3.18 TIMER0控制数码管扫描显示 3.19 TIMER1控制交通指示灯 3.20 TIMER1与TIMER2控制十字路口秒计时显示屏 3.21 用工作于计数方式的T/C0实现100以内的按键计数 3.22 用定时器设计的门铃 3.23 报警器与旋转灯 3.24 100000秒以内的计时程序 3.25 用TIMER1输入捕获功能设计的频率计 3.26 用工作于异步模式的T/C2控制的可调式数码管电子钟 3.27 TIMER1定时器比较匹配中断控制音阶播放 3.28 用TIMER1输出比较功能调节频率输出 3.29 TIMER1控制的PWM脉宽调制器 3.30 数码管显示两路A/D转换结果 3.31 模拟比较器测试 3.32 EEPROM读写与数码管显示 3.33 Flash程序空间中的数据访问 3.34 单片机与PC机双向串口通讯仿真 3.35 看门狗应用 第四章:硬件应用 4.1 74HC138与74HC154译码器应用 4.2 74HC595串入并出芯片应用 4.3 用74LS148与74LS21扩展中断 4.4 62256扩展内存 4.5 用8255实现接口扩展 4.6 可编程接口芯片8155应用 4.7 可编程外围定时计数器8253应用 4.8 数码管BCD解码驱动器7447与4511应用 4.9 8×8LED点阵屏显示数字 4.10 8位数码管段位复用串行驱动芯片MAX6951应用 4.11串行共阴显示驱动器MAX7219与7221应用 4.12 16段数码管演示 4.13 16键解码芯片74C922应用 4.14 1602字符液晶测试程序 4.15 1602液晶显示DS1302实时时钟 4.16 1602液晶工作于四位模式实时显示当前时间 4.17 2×20串行字符液晶演示 4.18 LGM12864液晶显示程序 4.19 PG160128A液晶图文演示 4.21 TG126410液晶串行模式演示 4.21 用带SPI接口的MCP23S17扩展16位通用IO端口 4.22 用TWI接口控制MAX6953驱动4片5×7点阵显示器 4.23 用TWI接口控制MAX6955驱动16段数码管显示 4.24 用DAC0832生成多种波形 4.25 用带SPI接口的数模转换芯片MAX515调节LED亮度 4.26 正反转可控的直流电机 4.27正反转可控的步进电机 4.28 DS18B20温度传感器测试 4.29 SPI接口温度传感器TC72应用测试 4.30 SHT75温湿度传感器应用 4.31 用SPI接口读写AT25F1024 4.32 用TWI接口读写24C04 4.33 MPX4250压力传感器测试 4.34 MMC存储卡测试 4.35 红外遥控发射与解码仿真 第五章:综合设计 5.1 多首电子音乐的选播 5.2 电子琴仿真 5.3 普通电话机拨号键盘应用 5.4 手机键盘仿真 5.5 数码管模拟显示乘法口诀 5.6 用DS1302与数码管设计的可调电子钟 5.7 用DS1302与LGM12864设计的可调式中文电子日历 5.8 用PG12864LCD设计的指针式电子钟 5.9 高仿真数码管电子钟 5.10 1602LCD显示的秒表 5.11 用DS18B20与MAX6951驱动数码管设计的温度报警器 5.12 用1602LCD与DS18B20设计的温度报警器 5.13 温控电机在L298驱动下改变速度与方向运行 5.14 PG160128中文显示日期时间及带刻度显示当前温度 5.15 液晶屏曲线显示两路模数转换结果 5.16 用74LS595与74LS154设计的16×16点阵屏 5.17 用8255与74LS154设计的16×16点阵屏 5.18 8×8LED点阵屏仿电梯数字滚动显示 5.19 用内置EEPROM与1602液晶设计的MD5加密电子密码锁 5.20 12864LCD显示24C08保存的开机画面 5.21 12864LCD显示EPROM27C256保存的开机画面 5.22 IIC-AT24C1024×2硬字库应用 5.23 SPI-AT25F2048硬件字库应用 5.24 带液晶显示的红外遥控调速仿真 5.25 能接收串口信息的带中英文硬字库的80×16点阵显示屏 5.26 用AVR与1601LCD设计的计算器 5.27 电子秤仿真设计 5.28 模拟射击训练游戏 5.29 PC机通过485远程控制单片机 5.30 用IE访问AVR+RTL8019设计的以太网应用系统

27,370

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧