说到DS18B20,开始玩单片机时接触的第一个外围器件就是它了,虽不能说精通其操作,但对其流程也早已了然于心了。既然助学板上有DS18B20,肯定要拿来把玩了。
不说太多废话,只说说俺在调试时遇到的困惑
I/O模拟单总线访问DS18B20,最关键的就是时序了。对于51单片机好办,因为知道指令的执行周期,所以可以用软件延时做到精确的控制,但在ARM上指令不再有固定的执行周期,也就无法估算软件延时的时间了。
俺先把一起自己用过的51程序移植过来,改了端口和延时,花了很长时间也没成功,
找来网友“烈火狂龙”的程序,移植过来仍然不行,很纳闷,又找来网友“lixiaoxu2meng”的程序,这次干脆直接拷贝,不做任何改动,下载后能读出温度了!
比较俺前后的程序,发现俺的程序操作流程和lixiaoxu2meng的几乎一模一样,可俺自个写的程序就是读不出温度,作为菜鸟,只能暂时作罢,纠结下去也没有意义。这次只是把以前学的整合一下。
若有精力一定要研究研究李老师是如何用uart操作ds18b20 的
言归正传,简单介绍下程序功能:开机LCD显示“菜农助学板 祝愿园地 越来越红火” 按下K1显示温度,按下K2显示18B20的内部ID,长按K1显示欢迎界面,长按K2显示“新春快乐”
ds18b20程序:
/***************************************************/
/* 参照lixiaoxu2meng\烈火狂龙的程序修改而成 */
/* 移值于其它MCU时,注意修改端口和延时函数 */
/* 2012.02.02-01(调试通过) zxcscm*/
/***************************************************/
#include "ds1.h"
//extern unsigned int value;
unsigned int temp_value;
extern unsigned char DS18B20_sign_flag=0;
/*************************************************************************************
** Function name: ds1820reset
** Descriptions: DS18B20初始化
** input parameters: none
** output parameters: none
** Returned value: none
*************************************************************************************/
void ds1820reset()
{
/*step1:首先主机产生RESET脉冲*/
DQ_OUTPUT; //将DQ引脚设置为输出
CLR_DQ; //DQ引脚输出低电平(即拉低至少为480us)
delay_ds18b20(300); //精确延时 大于480us
SET_DQ; //DQ引脚输出高电平(即释放数据线)
/*step2:等待15~60us后 DS18B20将把数据线拉低60~240us 以作为应答*/
DQ_INPUT; //将DQ引脚设置为输入
while(DQ_STATE); //如果没有应答也一直等待(注意在while里可加上超时处理 以免通信出错 而造成死机)
while(!DQ_STATE); //应答后等待(注意在while里可加上超时处理 以免通信出错 而造成死机)
/*step3:释放数据线,并延时480us(因为等待与应答必须大于480us才算整个初始化完成)*/
SET_DQ; //DQ引脚输出高电平(即释放数据线)
delay_ds18b20(300); //为了保证初始化完成 在延时480us
}
/*************************************************************************************
** Function name: ds1820rd
** Descriptions: DS18B20 读数据
** input parameters: none
** output parameters: none
** Returned value: none
*************************************************************************************/
unsigned char ds1820rd()//读数据
{
unsigned char i=0;
unsigned char dat = 0;
for (i=8;i>0;i--)
{
DQ_OUTPUT;//将DQ引脚设置为输出
CLR_DQ;//DQ引脚输出低电平(即拉低)
delay_ds18b20(2);
dat>>=1;
SET_DQ;//DQ引脚输出高电平
DQ_INPUT;//将DQ引脚设置为输入
delay_ds18b20(2);
if(DQ_STATE)
dat|=0x80;
delay_ds18b20(40);//大于60us
}
DQ_OUTPUT;
SET_DQ; //放数据线
return(dat);
}
/*************************************************************************************
** Function name: ds1820rd
** Descriptions: DS18B20 写数据
** input parameters: none
** output parameters: none
** Returned value: none
*************************************************************************************/
void ds1820wr(unsigned char wdata)//写数据
{
unsigned char i=0;
for (i=8; i>0; i--)
{
DQ_OUTPUT; //将DQ引脚设置为输出
CLR_DQ; //DQ引脚输出低电平(小于15us )
delay_ds18b20(2); //延时小于15us
if(wdata&0x01) SET_DQ; //DQ引脚输出高电平
else CLR_DQ; //DQ引脚输出低电平
delay_ds18b20(40); //延时大于60us
SET_DQ; //DQ引脚输出高电平
wdata>>=1;
}
}
extern void GetRom_DS18B20(unsigned char *p)
{
unsigned char i;
ds1820reset();
//if(Reset_DS18B20()==0xff)
{
ds1820wr(0x33);
for(i=8;i>0;i--)
{
*p++=ds1820rd(); //由低位到高位读
}
}
}
/*extern void ReadRom_DS18B20(unsigned char rom[8])
{
unsigned char i;
if(Reset_DS18B20()==0xff)
{
WriteByte_DS18B20(ds18b20_ReadRom);
for(i=8;i>0;i--)
{
rom[i-1]=ReadByte_DS18B20();
}
}
}
************************************************************************************
** Function name: read_temp
** Descriptions: 读取温度值并将读到的温度进行处理
** input parameters: none
** output parameters: none
** Returned value: none
*************************************************************************************/
extern unsigned int read_temp()//读取温度值并转换
{
unsigned char a,b;
temp_value = 0;
ds1820reset();
ds1820wr(0xcc);//跳过读序列号
ds1820wr(0x44);//启动温度转换
ds1820reset();
ds1820wr(0xcc);//跳过读序列号
ds1820wr(0xbe);//读取温度
a=ds1820rd();
b=ds1820rd();
temp_value=b;
temp_value<<=8;
temp_value=temp_value|a;
if(temp_value<0x0fff) //如果为正数
DS18B20_sign_flag=0;
else //如果为负数
{
temp_value=~temp_value+1;
DS18B20_sign_flag=1;
}
temp_value=temp_value*(0.625);//温度值扩大10倍,精确到1位小数
return(temp_value);
}
/*************************************************************************************
** Function name: delay_ms
** Descriptions: 1ms(晶振为12MHZ)延时子程序
** input parameters: count
** output parameters: 无
** Returned value: 无
*************************************************************************************/
void delay_ms(unsigned int count)
{
unsigned int i,j;
for(i=count;i>0;i--)
for(j=2395;j>0;j--);
}
/*************************************************************************************
** Function name: delay_ms
** Descriptions: 大约40us(晶振为12MHZ)延时子程序
** input parameters: count
** output parameters: 无
** Returned value: 无
*************************************************************************************/
void delay_ds18b20(unsigned int count)
{
unsigned int i,j;
for(i=count;i>0;i--)
for(j=2;j>0;j--);
}
其他程序感兴趣的请见工程包
04-DS18B20_LCD.rar
(827.08 KB)
开机画面:
按下K1显示温度:
按下K2显示ID:
长按K2:
|