|
樓主 |
發表於 2014-3-24 10:03:21
|
顯示全部樓層
LCD顯示的溫度計終於出爐了!!
這是小改款 其中 ADC轉換由網路上取得的程式小修改,74HC595 串成四個這是 電子負載的程式取得的,LCD 驅動算是自己想出來的,每次顯示更新前都要把輸出清空成為 0XFF; 當CLOCK 轉態時候 所有7段顯示也要全部反向.
還有兩個問題 1.電源電壓變動對溫度改變影響頗大,因為 10K電阻與10K溫度NTC作分壓取出電壓來,電源變動會影響到分壓.
2.程式碼 1615byte 太大了,C 語言浮點運算改了又改沒有成功,有待 先進幫忙改一下程式,讓我模仿作為下一玩具的進步空間.
unsigned int transfer(unsigned char an)//溫度電阻=10k/(((N*2)/M)-1)
{
float PP,Kp,qq;
unsigned int Rt;
M=Read(an);// tc read out volt
N=Read(0);//2.5V參考電壓 P1^0
qq=2*N/5;//-----------------------順序有差異喔
PP=M/qq*1000;//----------------順序有差異喔
Kp=10000/((5000/PP)-1); //float caculate
Rt=Kp;
/* 這部分也行
float PP,Kp;
unsigned int Rt;
M=Read(an);// tc read out volt count
N=Read(0);//參考電壓count
PP=(M*2.5/N)*1000;//read an temp convert to mV
Kp=10000/(5000/PP-1); //float caculate
Rt=Kp;
*/
return Rt;//return thermo-resister value
}
整個程式
/*-----------------------------------------------
20140308想要使用8951 驅動LCD 因為LCD都有單獨的字節而且要顯示的部分還要與 CLK反向才會點亮
CLK頻率為 32 167 200HZ COM加上CLK頻率 若是COM有4個那麼CLK就要加到這四個上面,一但CLK為LO時候原先的字節就要~ 反過來
AD轉換port 一定要設定否則會影響到熱敏電阻值的電壓
電壓變動對溫度顯示影響很大,可能跟取樣電壓分壓有關20140324
------------------------------------------------*/
#include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include <intrins.h>
#define DataPort P1// display LED segment P1^1---a P1^2---b ...P1^7---g
#define DataPort2 P2
#define uchar unsigned char
#define uint unsigned int;
sfr ADC_CONTR = 0xBC; //替代15F204EA
sfr ADC_RES = 0xBD;
sfr ADC_RESL = 0xBE;
sfr P1M0 = 0x92;
sfr P1M1 = 0x91;
sfr P1ASF = 0x9D;
unsigned int code tempresist[]={28709,27421,26200,25042,23943,22899,21908, 20967, 20072, 19221, 18412, 17642, 16910,16213, 15549,14916,14314,13740,13192,12670,12172, 11696,11243, 10809, 10395,10000,9622,9261, 8916, 8585, 8269, 7967,7677,7400,7135,
6880, 6637, 6403, 6179, 5964, 5758, 5561, 5371, 5189, 5014, 4846, 4685, 4530, 4381, 4238, 4101, 3968, 3841, 3719,
3601, 3487, 3378, 3273, 3172, 3074, 2980, 2890, 2803, 2718, 2637, 2559, 2483, 2411, 2340, 2272, 2207, 2144, 2082, 2023, 1966, 1911, 1858, 1807, 1757, 1709, 1662, 1617, 1573, 1531, 1491, 1451, 1413,
1376, 1340, 1305, 1271, 1239, 1207, 1177, 1147, 1118, 1090, 1063,1037, 1011,987,963,939,917,895,874,853,833,813,794,776,758
};//b值3435 25度 10k
unsigned char code segment[10]={0x7e,0x0c,0xb6,0x9e,0xcc,0xda,0xfa,0x0e,0xfe,0xde};//
//unsigned char code grid[4]={0x02,0x04,0x08,0x10};// 100.0 位碼0>>100度 左移一位 0x7e,0x0c,0xb6,0x9e,0xcc,0xda,0xfa,0x0e,0xfe,0xde
unsigned int L,M,N,Q,ADC_DATA;//作為adc 計算溫度使用
unsigned char TempData[4];
bit ReadTempFlag;//定义读时间标志
sbit DriveBIT =P3^7;//接到P3^7
sbit SER = P3^4;// 74hc595 送出4組DATA給LCD 7段*4字使用
sbit Latch = P3^3;
sbit Clk = P3^2;
sbit DQ=P3^0;//ds18b20 端口
uchar K;//display count
//unsigned int aa,ba;
//unsigned int TempH,TempL,temp;//16bit temp 是剛剛讀取的溫度數值 TempH 是整數部分 TempL 是小數部分
void Send595(unsigned char Dat) ;//串到並呼叫程式
void Send4byte(unsigned char Dat1,unsigned char Dat2,unsigned char Dat3,unsigned char Dat4);//送出4byte 由小數開始先送出
void Trans4(void);//轉換溫度4位到顯示暫存器TempData[0~3]供顯示之用
void Display(void);//顯示程式 呼叫 送出4byte
void Init_Timer0(void);//定时器初始化
void DelayUs2x(uchar t);
void DelayMs(uchar t);
unsigned char Compare_tempres (unsigned int);
//unsigned int ReadTemperature(void);
//bit Init_DS18B20(void);
//uchar ReadOneChar(void);
//void WriteOneChar(uchar dat);
//void TempPRo (void);
unsigned int TP0,P0n;
unsigned char Rtemp0;
//74hc595 轉換的串—並處理
//*******************************************
void Send595(unsigned char Dat)
{
unsigned char i;
for (i=0;i<8;i++)
{
Clk=0;
SER=Dat & 0x80;
_nop_();
Dat<<=1;
Clk=1;
_nop_();
}
Latch=0;
_nop_();
_nop_();
Latch=1;
_nop_();
_nop_();
}
void Send4byte(unsigned char Dat1,unsigned char Dat2,unsigned char Dat3,unsigned char Dat4)
{
//最小位數先送出
Send595(Dat1);//MIN,0.1c
Send595(Dat2);//10MIN,1c
Send595(Dat3);//HR,10c
Send595(Dat4);//10HR,100c
}
//Send4byte(10hr,hr,10min,min);
void Trans4(void)//轉換溫度4位到顯示暫存器TempData[0~3]供顯示之用
{
if(Rtemp0/100==0)
TempData[0]=0;
else
TempData[0]=segment[Rtemp0/100]; //十位温度
if((Rtemp0/100==0)&&((Rtemp0%100)/10==0))//消隐
TempData[1]=0;//0 表示不顯示
else
TempData[1]=segment[(Rtemp0%100)/10]; //十位温度
// TempData[1]= TempData[1]|0x01;
TempData[2]=segment[(Rtemp0%100)%10]; //个位温度,带小数?
TempData[3]=segment[P0n];
TempData[3]= TempData[3]|0x01;
}
/* 顯示用函數 用於驅動595做成靜態顯示 LCD
顯示四位數字 1200 0最先送出1最後送出
8bit都要控制否則小數點會有亂顯示,lcd 接腳接地無效一定要驅動
*/
void Display(void)
{
Send4byte(0xff,0xff,0xff,0xff);//清除lcd的內容
if (DriveBIT==0)//為了反向 正向交互所以需要因應而把輸出作為互補
{
Send4byte(TempData[3],TempData[2],TempData[1],TempData[0]);
}
else
{
Send4byte(~TempData[3],~TempData[2],~TempData[1],~TempData[0]);
}
}
/*******************************************************************
adc程式
*******************************************************************/
unsigned int Read (unsigned char CHA){
unsigned char AD_FIN=0; //
CHA &= 0x07;
ADC_CONTR = 0x60;
_nop_();
ADC_CONTR |= CHA;
_nop_();
ADC_CONTR |= 0x80;
DelayMs(1);
ADC_CONTR |= 0x08;
_nop_();
_nop_();
_nop_();
_nop_();
while (AD_FIN ==0){
AD_FIN = (ADC_CONTR & 0x10);
}
ADC_CONTR &= 0xE7;
ADC_DATA=ADC_RES*4+ADC_RESL;
return (ADC_DATA);
}
unsigned int transfer(unsigned char an)//溫度電阻=10k/(((N*2)/M)-1)
{
float PP,Kp,qq;
unsigned int Rt;
M=Read(an);// tc read out volt
N=Read(0);//2.5V參考電壓 P1^0
qq=2*N/5;//-----------------------順序有差異喔
PP=M/qq*1000;//----------------順序有差異喔
Kp=10000/((5000/PP)-1); //float caculate
Rt=Kp;
/*
float PP,Kp;
unsigned int Rt;
M=Read(an);// tc read out volt count
N=Read(0);//參考電壓count
PP=(M*2.5/N)*1000;//read an temp convert to mV
Kp=10000/(5000/PP-1); //float caculate
Rt=Kp;
*/
return Rt;//return thermo-resister value
}
/*------------------------------------------------
定时器初始化子程序
------------------------------------------------*/
void Init_Timer0(void)
{
TMOD |= 0x01; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响
//TH0=0x00; //给定初值
//TL0=0x00;
EA=1; //总中断打开
ET0=1; //定时器中断打开
TR0=1; //定时器开关打开
}
/*------------------------------------------------
定时器中断子程序
------------------------------------------------*/
void Timer0_isr(void) interrupt 1
{
static unsigned int num;//cnt;
TH0=(65536-20000)/256; //重新赋值 20ms
TL0=(65536-20000)%256;
num++;
DriveBIT = (!DriveBIT);
Display();//every 10ms display 1 times
if(num==30) //減少更新次數
{
num=0;
ReadTempFlag=1; //读标志位置1
K++;
if(K>100)
{
K=0;
}
}
}
/*------------------------------------------------
uS延时函数,含有输入参数 unsigned char t,无返回值
unsigned char 是定义无符号字符变量,其值的范围是
0~255 这里使用晶振12M,精确延时请使用汇编,大致延时
长度如下 T=tx2+5 uS
------------------------------------------------*/
void DelayUs2x(uchar t)
{
while(--t);
}
/*------------------------------------------------
mS延时函数,含有输入参数 unsigned char t,无返回值
unsigned char 是定义无符号字符变量,其值的范围是
0~255 这里使用晶振12M,精确延时请使用汇编
------------------------------------------------*/
void DelayMs(uchar t)
{
while(t--)
{
//大致延时1mS
DelayUs2x(245);
DelayUs2x(245);
}
}
unsigned char Compare_tempres(unsigned int TR)
{
unsigned char cmp_cnt;
cmp_cnt =0;
while (TR<tempresist[cmp_cnt])
{
cmp_cnt++;
if (cmp_cnt>100)
break;
}
return cmp_cnt;
}
/*------------------------------------------------
主函数
------------------------------------------------*/
void main (void)
{
P1M0 = 0xff; //ad port 設定
P1M1 = 0x00; //P1.0
P1ASF=0xff; //all analog in put mode
DriveBIT=0;
Init_Timer0();
while (1) //主循环
{
if(ReadTempFlag==1)//每隔 10ms*500
{
ReadTempFlag=0;
DelayMs(250);
DelayMs(250);
TP0= transfer(1);//read chanel 2 resister value
Rtemp0=Compare_tempres(TP0);// 查表取出TP0的溫度值
P0n=((tempresist[Rtemp0-1]-TP0)*10)/(tempresist[Rtemp0-1]-tempresist[Rtemp0]);//換算小數點的值線性值
Trans4();//轉換成為4位數
}
}
}
|
評分
-
4
查看全部評分
-
|