自己撰寫了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=https://bbs.csdn.net/topics/0;
_nop_() ;
_nop_();
_nop_();
_nop_();
for(count=0;count<16;count++) //獲取16位MSB
{
Value=https://bbs.csdn.net/topics/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=https://bbs.csdn.net/topics/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=https://bbs.csdn.net/topics/ReadMAX6675();
testD2=GetCurrentTemp(TempValue);
TempValue=https://bbs.csdn.net/topics/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);
}
}
uj5u.com熱心網友回復:
冷端補償問題。你可以加上一個修正演算法來彌補誤差。例如,測驗多個溫點,記錄誤差,然后得出一條誤差線,并用一條直線來接近它。算出誤差直線的斜率,作為補償基準。有點類似插值法的意思。
當然,你要能用密集的溫點得到一個誤差表的話,用查表法補償也可以。
uj5u.com熱心網友回復:
我后來換 了演算法-最小二乘法,解決了這個問題,謝謝指導!uj5u.com熱心網友回復:
求修改后的程式,謝謝!uj5u.com熱心網友回復:
換 了演算法-最小二乘法,解決了這個問題?uj5u.com熱心網友回復:
樓主,你后來怎么解決的啊轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/50496.html
標籤:單片機/工控
下一篇:推桿電機電源選擇
