求教: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);
}
}
...全文
1202 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
吾啊 2020-03-14
  • 打赏
  • 举报
回复
楼主,你后来怎么解决的啊
  • 打赏
  • 举报
回复
换 了算法-最小二乘法,解决了这个问题?
sjjyyyy 2019-12-30
  • 打赏
  • 举报
回复
求修改后的程序,谢谢!
水浒传鲁智深 2018-01-05
  • 打赏
  • 举报
回复
我后来换 了算法-最小二乘法,解决了这个问题,谢谢指导!
of123 2017-10-19
  • 打赏
  • 举报
回复
冷端补偿问题。 你可以加上一个修正算法来弥补误差。例如,测试多个温点,记录误差,然后得出一条误差线,并用一条直线来接近它。算出误差直线的斜率,作为补偿基准。有点类似插值法的意思。 当然,你要能用密集的温点得到一个误差表的话,用查表法补偿也可以。

27,377

社区成员

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

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