|
#include<reg52.h>
#include <intrins.h>
typedef unsigned char uint8;
#define uint unsigned int
#define uchar unsigned char
sbit DQ = P3^3; // 定義DQ引腳為P3.3
uchar code Bw[10]= {0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};//百位編碼
ucharcodeXsw[16]={0x30,0x31,0x31,0x32,0x33,0x33,0x34,0x34,0x35,0x36,0x36,0x37,0x38,0x38,0x39,0x39};//小數(shù)位編碼
sbit RS = P2^0 ;
sbit RW = P2^1 ;
sbit EN = P2^2 ;
sbit BUSY = P0^7;
uchar wendu;
uchar temp_g,temp_d;
unsigned char code word1[]={"Temperature:"};
void delay(uint xms)
{
uint i,j;
for(i=xms;i>0;--i)
for(j=110;j>0;--j);
}
void Delayus(int t) //在11.059MHz的晶振條件下調(diào)用本函數(shù)需要24μs ,然后每次計(jì)數(shù)需16μs
{
int s;
for (s=0; s<t;s++);
}
void wait(void)// 等待繁忙標(biāo)志
{
P0 = 0xFF;
do
{
RS = 0;
RW = 1;
EN = 0;
EN = 1;
}while (BUSY == 1);
EN = 0;
}
void w_dat(uint8 dat)// 寫(xiě)數(shù)據(jù)
{
wait();
EN = 0;
P0 = dat;
RS = 1;
RW = 0;
EN = 1;
EN = 0;
}
void w_cmd(uint8 cmd)// 寫(xiě)命令
{
wait();
EN = 0;
P0 = cmd;
RS = 0;
RW = 0;
EN = 1;
EN = 0;
}
void w_string(uint8 addr_start, uint8 *p)// 發(fā)送字符串到LCD
{
w_cmd(addr_start);
while (*p != '\0')
{
w_dat(*p++);
}
}
void Init_LCD1602(void)// 初始化1602
{
w_cmd(0x38); // 16*2顯示,5*7點(diǎn)陣,8位數(shù)據(jù)接口
w_cmd(0x0c); // 顯示器開(kāi)、光標(biāo)開(kāi)、光標(biāo)允許閃爍
w_cmd(0x06); // 文字不動(dòng),光標(biāo)自動(dòng)右移
w_cmd(0x01); // 清屏
}
uchar Reset()//完成單總線的復(fù)位操作。
{
uchar d;
DQ = 0; // 將 DQ 線拉低
Delayus(29); // 保持 480μs .復(fù)位時(shí)間為480μs,因此延時(shí)時(shí)間為(480-24)/16 = 28.5,取29μs。
DQ = 1; // DQ返回高電平
Delayus(3); // 等待存在脈沖.經(jīng)過(guò)70μs之后檢測(cè)存在脈沖,因此延時(shí)時(shí)間為(70-24)/16 = 2.875,取3μs。
d = DQ; // 獲得存在信號(hào)
Delayus(25); // 等待時(shí)間隙結(jié)束
return(d); // 返回存在信號(hào),0 = 器件存在, 1 = 無(wú)器件
}
void write_bit(uchar bitval)//向單總線寫(xiě)入1位值:bitval
{
DQ = 0; // 將DQ 拉低開(kāi)始寫(xiě)時(shí)間隙
if(bitval==1)
DQ =1; // 如果寫(xiě)1,DQ 返回高電平
Delayus(5);// 在時(shí)間隙內(nèi)保持電平值,
DQ = 1; // Delayus函數(shù)每次循環(huán)延時(shí)16μs,因此Delayus(5)=5*16+24=104μs
}
void ds18write_byte(char val)//向單總線寫(xiě)入一個(gè)字節(jié)值:val
{
uchar i;
uchar temp;
for (i=0; i<8; i++)// 寫(xiě)入字節(jié), 每次寫(xiě)入一位
{
temp = val>>i;
temp &= 0x01;
write_bit(temp);
}
Delayus(5);
}
uchar read_bit()//從單總線上讀取一位信號(hào),所需延時(shí)時(shí)間為15μs,因此無(wú)法調(diào)用前面定義
{ //的Delayus()函數(shù),而采用一個(gè)for()循環(huán)來(lái)實(shí)現(xiàn)延時(shí)。
uchar i;
DQ = 0; //將DQ 拉低開(kāi)始讀時(shí)間隙
DQ = 1; // 然后返回高電平
for (i=0; i<3; i++); // 延時(shí)15μs
return(DQ); // 返回 DQ 線上的電平值
}
uchar ds18read_byte()//從單總線讀取一個(gè)字節(jié)的值
{
uchar i;
uchar value = 0;
for (i=0;i<8;i++)
{ // 讀取字節(jié),每次讀取一個(gè)字節(jié)
if(read_bit())
value|=0x01<<i; // 然后將其左移
Delayus(6);
}
return(value);
}
int Readtemperature()//如果單總線節(jié)點(diǎn)上只有一個(gè)器件則可以直接掉用本函數(shù)。如果節(jié)點(diǎn)上有多個(gè)器
{ //件,為了避免數(shù)據(jù)沖突,應(yīng)使用Match ROM函數(shù)來(lái)選中特定器件。
uchar temp_d,temp_g,k,get[2],temp;
Reset();
ds18write_byte(0xcc); // 跳過(guò) ROM
ds18write_byte(0x44); // 啟動(dòng)溫度轉(zhuǎn)換
Delayus(5);
Reset();
ds18write_byte(0xcc); // 跳過(guò) ROM
ds18write_byte(0xbe); // 讀暫存器
for (k=0;k<2;k++)
{
get[k]=ds18read_byte();
}
temp_d = get[0];//低位
temp_g = get[1];//高位
if((temp_g&0xf0)==0xf0) //正負(fù)號(hào)判斷
{
temp_d=~temp_d;
if(temp_d==0xff) //保證-48(1111110100000000)、-32和-16顯示正常
{
temp_d=temp_d+0x01;//00000000
temp_g=~temp_g;//00000010
temp_g=temp_g+0x01;//00000011
}
else
{
temp_d=temp_d+0x01;
temp_g=~temp_g;
}
w_cmd(0xc5);
w_dat(Xsw[temp_d&0x0f]); //查表得小數(shù)位的值
temp=((temp_d&0xf0)>>4)|((temp_g&0x0f)<<4);
w_cmd(0xc1);
w_dat(0x2d);//負(fù)號(hào)
}
else //正數(shù)
{
w_cmd(0xc5);
w_dat(Xsw[temp_d&0x0f]); //查表得小數(shù)位的值
temp=((temp_d&0xf0)>>4)|((temp_g&0x0f)<<4);
w_cmd(0xc1);
w_dat(Bw[temp/100]);
}
return temp;
}
main()
{
Init_LCD1602();
w_string(0x80,word1);
while (1)
{
wendu=Readtemperature();
temp_g=wendu%100/10+'0';
temp_d=wendu%10+'0';
w_cmd(0xc2);
delay(2);
w_dat(temp_g);
delay(2);
w_dat(temp_d);
delay(2);
w_cmd(0xc4);
delay(2);
w_dat(0x2e);//小數(shù)點(diǎn)
delay(2);
w_cmd(0xc6);
delay(2);
w_dat(0xdf);//溫度符號(hào)
delay(2);
w_dat(0x43);
}
}
卡爾曼濾波部分代碼
#include "KalmanFilter.h"
float R=0.999f;
float Q=0.001f;
float x0=0.0f;
float p0=1555.0f;
float k,x,p;
float KalmanFilter(float Measure)
{
x=x0;
p=p0+Q;
k=p/(p+R);
x=x+k*(Measure-x);
p=(1-k)*p;
p0=p;
x0=x;
return x;
}
#include "KalmanFilter.h"
float R=0.999f;
float Q=0.001f;
float x0=0.0f;
float p0=1555.0f;
float k,x,p;
float KalmanFilter(float Measure)
{
x=x0;
p=p0+Q;
k=p/(p+R);
x=x+k*(Measure-x);
p=(1-k)*p;
p0=p;
x0=x;
return x;
}
|
-
仿真圖.png
(26.88 KB, 下載次數(shù): 72)
下載附件
2020-1-6 23:13 上傳
|