请教DS18B20测到的温度怎样显示到12864上(串行方式)

两把刷子飞啊飞 2012-09-01 09:30:32
我用的是力天电子的arm7 lpc2148这块板子,别的什么功能都没有,自己就只想测一下温度,但12864上却一直显示25.5这个数字,也不会改变,请问大家这是怎么回事啊,我用的12864是不带中文字库的,哪位大侠给个程序让小弟参考一下
程序如下
#include <NXP/iolpc2148.h>
//管脚宏定义(省略)

//接口声明(省略)

//LCD Define
#define LCD_A 1<<30 //命令数据选择端,高电平:数据 低电平:命令
#define LCD_CLK 1<<4 //时钟端
#define LCD_DATA MOSI //数据端
#define B_LED 1<<13 //背光

#define Sclk_L() IO0CLR |=LCD_CLK //时钟高电平
#define Sclk_H() IO0SET |=LCD_CLK //时钟低电平
#define Res_L() HC595_DATA &=~(1<<2);Write595() //复位低电平
#define Res_H() HC595_DATA |=(1<<2); Write595() //复位高电平
#define Data_L() IO0CLR |=LCD_DATA //数据低电平
#define Data_H() IO0SET |=LCD_DATA //数据高电平
#define CS_L() HC595_DATA &=~1; Write595() //片选低电平
#define CS_H() HC595_DATA |=1; Write595() //片选高电平
#define Write_C() IO0CLR |=LCD_A //选择写命令
#define Write_D() IO0SET |=LCD_A //选择写数据
#define Writecommand
//系统时钟
#define Fosc 11059200 //晶振时钟【Hz】
#define Fcclk (Fosc * 4) //系统频率,必须为Fosc的整数倍
#define Fpclk (Fcclk / 4) * 1 //VPB时钟频率,只能为(Fcclk/4)的1~4倍
unsigned int datas;
unsigned int times;
unsigned int bak;
//函数声明
//函数声明
void Delayn(unsigned long n);
void DelaynUs(unsigned int n);
void Write595();
void HC595_Init(void);
void Lcd_Init(void);
void Lcd_display_HZ(unsigned char x,unsigned char y,unsigned char *p);
void LcdCls(unsigned char data);
void Setxy(unsigned char x,unsigned char y);
void show_string1616(unsigned char x,unsigned char y,unsigned *string,unsigned char string_lenth);
void RTCInit (void);
void SendTimeRtc(void);
void LcdShow1216(unsigned char x,unsigned char y,unsigned char *p);
void DS_Reset (void);
void Tmp_Change(void);
void display(unsigned int temp);
float tmp(void);
//全局变量
unsigned int HC595_DATA=0xFFFFFFFF;
unsigned char num1216[][24]=
{{0x00,0xFC,0xFE,0x06,0x06,0x86,0x46,0x26,0x16,0xFE,0xFC,0x00,0x00,0x3F,0x7F,0x68,0x64,0x62,0x61,0x60,0x60,0x7F,0x3F,0x00},//0
{0x00,0x00,0x00,0x00,0x08,0xFE,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x7F,0x00,0x00,0x00,0x00,0x00}, //1
{0x00,0x3C,0x3E,0x06,0x06,0x06,0x06,0x86,0xC6,0x7E,0x3C,0x00,0x00,0x60,0x70,0x78,0x6C,0x66,0x63,0x61,0x60,0x60,0x60,0x00}, //2
{0x00,0x3C,0x3E,0x06,0x06,0xC6,0xC6,0xC6,0xC6,0xFE,0x3C,0x00,0x00,0x3C,0x7C,0x60,0x60,0x60,0x60,0x60,0x60,0x7F,0x3F,0x00}, //3
{0x00,0x00,0x80,0xE0,0x78,0x1E,0x06,0xFE,0xFE,0x00,0x00,0x00,0x00,0x1E,0x1F,0x19,0x18,0x18,0x18,0x7F,0x7F,0x18,0x18,0x00}, //4
{0x00,0xFE,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x86,0x00,0x00,0x3C,0x7C,0x60,0x60,0x60,0x60,0x60,0x60,0x7F,0x3F,0x00}, //5
{0X00,0xFC,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xCE,0x8C,0x00,0x00,0x3F,0x7F,0x60,0x60,0x60,0x60,0x60,0x60,0x7F,0x3F,0x00}, //6
{0x00,0x1E,0x1E,0x06,0x06,0x06,0x06,0x86,0xE6,0x7E,0x1E,0x00,0x00,0x00,0x00,0x00,0x60,0x78,0x1E,0x07,0x01,0x00,0x00,0x00}, //7
{0x00,0x7C,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xFE,0x7C,0x00,0x00,0x3F,0x7F,0x60,0x60,0x60,0x60,0x60,0x60,0x7F,0x3F,0x00}, //8
{0x00,0xFC,0xFE,0x06,0x06,0x06,0x06,0x06,0x06,0xFE,0xFC,0x00,0x00,0x31,0x73,0x63,0x63,0x63,0x63,0x63,0x63,0x7F,0x3F,0x00}, //9
{0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00}, //-
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //space
{0x00,0x00,0x00,0x00,0x18,0x3C,0x3C,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //.
};
//num1216[][]是个二维数组

main()
{
char a;
HC595_Init(); //初始化74HC595
IO0DIR |=LCD_A|B_LED|LCD_CLK; //初始化IO口
Lcd_Init(); //初始化液晶屏
LcdCls(0x00);//清屏
Delayn(20000000);
while(1)
{
Tmp_Change(); //数据开始转换
DelaynUs(1000); //延时等待1000us,即1ms
a=tmp(); //读取数据
display(a); //显示得到的温度数据
DelaynUs(2000000);//等待1s

}
}
//PLL初始化(省略)

//初始化595接口
void HC595_Init(void)
{
IO0DIR |= MOSI|RCK;
IO1DIR |= SCLK;
IO1CLR |= SCLK;
IO0DIR |= RCK;

HC595_DATA =0xFFFFFFFF;Write595();

}
//写字节
void WriteByte(unsigned char data)
{
unsigned char i;
//IO0CLR;
for(i=0;i<8;i++)
{
if(data&0x01) IO0SET=MOSI;
else IO0CLR =MOSI;
IO1SET=SCLK;
data>>=1;
IO1CLR=SCLK;
}
//IO0SET=RCK;
}
//刷新595的数据
void Write595()
{
IO0CLR=RCK;
WriteByte(HC595_DATA&0xff);
WriteByte((HC595_DATA&0xff00)>>8);
WriteByte((HC595_DATA&0xff0000)>>16);
WriteByte((HC595_DATA&0xff000000)>>24);
IO0SET=RCK;
}

//延时周期数
void Delayn(unsigned long n)
{
while(n--);
}
//向SPI总线上写一个字节的数据
void LCDWriteByte(unsigned char data)
{
unsigned char i,s;
s=data;
for(i=0;i<8;i++)
{ //Delayn(1000000); //自己加的
if(s&0x80) Data_H();
else Data_L();
Sclk_H();
s<<=1;
Sclk_L();
}
}
//向液晶屏写数据
void WriteData(unsigned char Data)
{
Write_D();
CS_L();
LCDWriteByte(Data);
CS_H();
}
//向液晶屏写命令
void WriteCommand(unsigned char Command)
{
Write_C();
CS_L();
LCDWriteByte(Command);
CS_H();
}
//打开液晶背光 0:关闭 1:打开
void Lcd_BackLed(unsigned char on)
{
if(on==1)
{
IO0CLR=B_LED; //打开背光
}
else if(on==0)
{
IO0SET=B_LED; //关闭背光
}
}
//液晶复位
void Lcd_Reset(void)
{
Res_L();
Delayn(10000000);
Res_H();
}
//列顺序翻转,左右翻转 0:正常 1:翻转
void Lcd_ColRev(unsigned char i)
{
WriteCommand(0xa0|(i&0x01));
}
//清屏
void LcdCls(unsigned char data)
{
unsigned char i,j;
for(i=0;i<9;i++)
{
Setxy(0,i);
for(j=0;j<128;j++)
{
WriteData(data);

}
}
}
//液晶初始化
void Lcd_Init(void)
{
Lcd_Reset(); //液晶复位
//Lcd_BackLed(0);
Lcd_BackLed(1); //打开液晶背光
WriteCommand(0xaf); //打开显示
WriteCommand(0x40); //指定显示RAM的行地址,起始行为:0然后63,62,....2,1依次减小
WriteCommand(0xa1); //ADC正常???
WriteCommand(0xa6); //没有反白,正常显示
WriteCommand(0xa4); //全屏显示
WriteCommand(0xa2); //设置LCD的偏压比
WriteCommand(0xc0); //正常:意思是下端为0,往上依次为63,62....
WriteCommand(0x2f); //电源设置
WriteCommand(0x24); //粗调对比度
WriteCommand(0x81); //
WriteCommand(0x24); //后两个相当于细调对比度

Lcd_ColRev(1); //左右翻转
}

//选择列x,页y
void Setxy(unsigned char x,unsigned char y)
{
unsigned char tmp=0;
y=y&0x0F; //把页号变换为0XB0……0XB7的页定位码
y=y|0xb0;
tmp=x;
tmp>>=4; //变换出列号的定位码高低4位
tmp|=0x10;
x&=0x0F;
WriteCommand(y); //写页定位码
WriteCommand(tmp);//写列定位码(高)
WriteCommand(x); //写列定位码(低)
}

void LcdShow1216(unsigned char x,unsigned char y,unsigned char *p) //显示1216点阵
{
unsigned char i;
Setxy(x,y); //设置坐标
for(i=0; i<12; i++) //写上半个点阵
{
WriteData(*p++);
}
y+=1; //设置坐标(页地址加1)
Setxy(x,y);
for(i=0; i<12; i++) //写下半个点阵
{
WriteData(*p++);
}

}

/*****************以下是18B20相关函数******************/

//DS18B20复位初始化
void DS_Reset (void)
{
DS_OUT(); //端口设置为输出
DS_L(); //主机发送一个低电平
DelaynUs(800);//800us(指低电平延续的时间,下同)
DS_IN(); //端口设置为输入
DelaynUs(500);//延时500us
/*if(DS_R!=0)
sendsStr("There is no DS18B20\n");
else sendStr("Init DS18B20 success\n")

*/
while(DS_R()==0);//等待低电平过去
}

//DS18B20读一位数据
unsigned char tmpreadbit(void)
{
unsigned char dat;
DS_OUT(); //端口设置为输出
DS_L(); //DS=0
Delayn(1); //2us
DS_IN(); //端口设置为输入,以让DS18B20把数据传输到单总线上
if(DS_R()==0)
dat=0;
else
dat=1;//接下来要对总线进行采样检测
DelaynUs(50);//
return (dat);
}

//DS18B20读一个字节数据
unsigned char tmpread(void)
{
unsigned char dat,i,j;
dat=0;
for(i=1;i<=8;i++)
{
j=tmpreadbit();
dat=(j<<7)|(dat>>1);
}
return(dat);
}

//写数据
void tmpwritebyte(unsigned char dat)
{
unsigned char j;
unsigned char testb;
for(j=1;j<=8;j++)
{
testb=dat&0x01;//(利用与运算取出要写的第0位二进制数据)
dat=dat>>1; //将此位右移1位,为的是使dat中将要取出的位始终位于第0位
if(testb) //testb如果为1,(以下部分不是很懂)
{
DS_OUT();
DS_L(); //DS=0,写周期一开始作为主机先把总线拉低1us表示写周期开始
//Delayn(1);
DS_IN(); //input
DelaynUs(60);
}
else //write 0
{
DS_OUT();
DS_L();
DelaynUs(45);
DS_IN();
DelaynUs(2);
}
}
}

//DS18B20begin change,转换数据
void Tmp_Change(void)
{
DS_Reset();
DelaynUs(1000);
tmpwritebyte(0xcc); //address all drivers on bus(跳过ROM,忽略64位ROM地址,直接向 DS18B20发温度变换命令)
tmpwritebyte(0x44); // initiates a single temperature conversion,启动DS18B20进
//行温度转换,转换时间最长为500ms(典型为200ms)结果存入内部9字节RAM中
}

//get the temperature 读取温度值
float tmp (void)
{
float tt;
unsigned int temp;
unsigned char a,b;
DS_Reset(); //复位DS18B20(主机发出复位操作并接收DS18B20的应答存在脉冲)
DelaynUs(1000);
tmpwritebyte(0xcc);// 跳过ROM,忽略64位ROM地址,直接向DS18B20发温度变换命令
tmpwritebyte(0xbe);//读暂存器,读内部RAM中9字节的内容(即读温度),如果只想读取温
//度数据,那在读完第0和第1个数据后就不在理会后面DS18B20发出的数据即可,
//读取的数据是低位在前的

a=tmpread(); //连续两次调用tmpread(),把最先发出的两个字节读回
b=tmpread(); //这两个字节分别是温度的高字节和低字节
temp=b; //先把高8位数据赋予temp
temp<<=8; //把以上的8位数据从temp低八位移到高八位
temp=temp|a; //两字节合成一个整型变量
tt=temp*0.0625; //将测到的数值乘以0.0625即可得到实际温度,DS18B20可以精确到0.0625度
temp=tt*10+0.5; //放大十倍,目的是将小数点后第一位也转换为可显示数字 ,0.5是干嘛的呢?应该是精度差,
return temp; //具体是哪个地方呢?

}
void display(unsigned int temp)
{
unsigned int t1,t2,t3,t; //t0.t1,t2
t1=temp/100; //取十位
t2=temp%100/10; //取个位
t3=temp%10; //取小数位
LcdShow1216(42,6,num1216[t1]); //在第42列,第6页显示十位
LcdShow1216(58,6,num1216[t2]);
LcdShow1216(74,6,num1216[12]); //在74列,第6也显示"."
LcdShow1216(90,6,num1216[t3]);

}

//读取ROM中的数据
void readrom(void) //read the serial
{
DS_Reset(); //复位DS18B20
DelaynUs(1000);
tmpwritebyte(0x33); //读DS18B20 ROM中的编码(即读64位地址)
tmpread(); //连续两次调用tmpread(),把最先发出的两个字节读回
tmpread();
}
//延时函数也省略
...全文
182 1 打赏 收藏 转发到动态 举报
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
怎么没人啊

21,597

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 驱动开发/核心开发
社区管理员
  • 驱动开发/核心开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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