busy的笔记 https://passport2.21ic.com/?99707 [收藏] [复制] [RSS]

日志

[原创]简洁的DS18B20驱动程序

已有 1051 次阅读2006-6-10 13:49 |系统分类:单片机


/* 


网络上已经有不少的18B20驱动程序了,


现在为你提供个我自己写的,编写规范的,


在实际工程上使用良好的代码.....


注意:


1、在实际的工程上,我用了光藕隔离了


MCU与DS18B20的通信,并且它们也是单独


提供电压的。因此MCU用了2个IO,一个读、一个写。


移植时,你需要定义MCU操作的IO口。


2、我的实际工程中只用到每度单位,你可以根据你的需要修改。


3、DS18B20_StartConvertTemp()与DS18B20_GetTemperature()之间


的正确调用要间隔>750MS。


4、没有使用CRC8校验,只使用了一些识别错误的BIT。


5、欢迎交流!zby8020@163.com


*/



/********************************************************************


** 工 程 名:
** 项目描述:


** 文 件 名:
** 版    本: V1.0
** 设 计 者: busy
** 设计日期:


** 功能描述:
** 使用注意:


** 编 译 器:
** 编译选项:


** 修 改 者:
** 修改描述:
** 修改日期:
** 版本变更:


********************************************************************/


// 当前宏定义


#define COM_ROM_READ     0X33 // ROM操作命令
#define COM_ROM_MATCH     0X55
#define COM_ROM_SKIP     0XCC
#define COM_ROM_SEARCH     0XF0
#define COM_ROM_ALARM     0XEC


#define COM_MEM_CONVERT_T    0X44 // 寄存器操作命令
#define COM_MEM_READ_SCR    0XBE
#define COM_MEM_WRITE_SCR    0X4E
#define COM_MEM_COPY_SCR    0X48
#define COM_MEM_RECALL_E    0XB8
#define COM_MEM_READ_POWER    0XB4


/*$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
** US延迟函数
** 注意:必须根据不同的MCU、晶体频率而做更改
*/
static void DS18B20_DelayUs(INT8U us) // @8MHZ
{
 for(; us>0; us--)
 {
  asm("nop");
  asm("nop");
 }
}


/*$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
** 启动时序,返回应答位
** (0)表示OK,否则错误
** 注意:
 (1)时序的准确性
 (2)开关全局中断
*/
static BOOLEAN DS18B20_Restart(void)
{
 BOOLEAN rBit;
 BOOLEAN gIE = 0;
 
 if( __get_SR_register() & GIE ) // 保存当前全局中断的状态
 {
  gIE = 1;
  __disable_interrupt();
 }
 
 DS18B20_CLR_OUT();
 DS18B20_DelayUs(200);
 DS18B20_DelayUs(200);
 DS18B20_DelayUs(200);
 DS18B20_SET_OUT();
 DS18B20_DelayUs(90);
 if( DS18B20_READ_IN() )
  rBit = 1;
 else
  rBit = 0;
 
 if( gIE ) // 恢复当前全局中断的状态
  __enable_interrupt();
 
 DS18B20_DelayUs(200);
 DS18B20_DelayUs(200);
 
 return(rBit);
}


/*$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
** DS18B20读位函数
** 注意:
 (1)时序的准确性
 (2)开关全局中断
*/
static BOOLEAN DS18B20_ReadBit(void)
{
 BOOLEAN rBit;
 BOOLEAN gIE = 0;
 
 if( __get_SR_register() & GIE ) // 保存当前全局中断的状态
 {
  gIE = 1;
  __disable_interrupt();
 }
 
 DS18B20_CLR_OUT();
 DS18B20_DelayUs(4);
 DS18B20_SET_OUT();
 DS18B20_DelayUs(4);
 if( DS18B20_READ_IN() )
  rBit = 1;
 else
  rBit = 0;
 DS18B20_DelayUs(60);
 
 if( gIE ) // 恢复当前全局中断的状态
  __enable_interrupt();
 
 return(rBit);
}


/*$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
** DS18B20写位函数
** 注意:
 (1)时序的准确性
 (2)开关全局中断
*/
static void DS18B20_WriteBit(BOOLEAN bVal)
{
 BOOLEAN gIE = 0;
 
 if( __get_SR_register() & GIE ) // 保存当前全局中断的状态
 {
  gIE = 1;
  __disable_interrupt();
 }
 
 DS18B20_CLR_OUT();
 DS18B20_DelayUs(7);
 if(bVal)
 {
  DS18B20_SET_OUT();
 }
 else
 {
  DS18B20_CLR_OUT();
 }
 DS18B20_DelayUs(60);
 DS18B20_SET_OUT();
 DS18B20_DelayUs(10);
 
 if( gIE ) // 恢复当前全局中断的状态
  __enable_interrupt();
}


/*$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
** 从DS18B20读字节数据
*/
static INT8U DS18B20_ReadByte(void)
{
 INT8U i, tmp=0;
 
 for(i=0; i<8; i++)
 {
  tmp >>= 1;
  if( DS18B20_ReadBit() )
   tmp |= 0x80;
 }
 return(tmp);
}


/*$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
** 往DS18B20内写字节数据
*/
static void DS18B20_WriteByte(INT8U val)
{
 INT8U i;
 
 for(i=0; i<8; i++)
 {
  if(val & 0x01)
   DS18B20_WriteBit(1);
  else
   DS18B20_WriteBit(0);
  val >>= 1;
 }
}


/*$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
** 启动温度转换函数
** 成功返回(0),否则(1)
** 注意:温度转换位数对应的最大转换时间
**   9BIT  = 93.75MS
**   10BIT = 187.5MS
**   11BIT = 375MS
**   12BIT = 750MS
*/
BOOLEAN DS18B20_StartConvertTemp(void)
{
 INT8U cnt = 5;
 
 while( --cnt && DS18B20_Restart() );
 if(cnt == 0)
  return(1);
  
 DS18B20_WriteByte(COM_ROM_SKIP);
 DS18B20_WriteByte(COM_MEM_CONVERT_T);
 
 return(0);
}


/*$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
** 读取温度,步长是1度C
** 成功返回(0),温度值写入有符号数*pTemp中;否则(1),无操作*pTemp。
** 注意:
 (1)自动识别DS18B20的温度转换位数BIT9-12,产生对应的温度
 (2)精度设定为1度C
 (3)包含寄存器某些位的正确检测
*/
BOOLEAN DS18B20_GetTemperature(INT8S *pTemp)
{
 INT16S temp;
 INT8U config;
 INT8U cnt = 5;
 
 while( --cnt && DS18B20_Restart() );
 if(cnt == 0)
  return(1);
  
 DS18B20_WriteByte(COM_ROM_SKIP);
 DS18B20_WriteByte(COM_MEM_READ_SCR);
 ((INT8U*)(&temp))[0] = DS18B20_ReadByte();
 ((INT8U*)(&temp))[1] = DS18B20_ReadByte();
 DS18B20_ReadByte();
 DS18B20_ReadByte();
 config = DS18B20_ReadByte(); // 忽略其它4字节,无CRC-8校验
 
 if((config & (~0x60)) != 0x1F) // 读数据错误判断
  return(1);
 if( (0x0000 != (0xF800 & temp)) && (0xF800 != (0xF800 & temp)) )
  return(1);
  
 switch(config & 0x60) // 识别温度转换位数并转化为度C
 {
  case 0x00: temp >>=1; break; // 9bit/0.5C
  case 0x20: temp >>=2; break; // 10bit/0.25C
  case 0x40: temp >>=3; break; // 11bit/0.125C
  case 0x60: temp >>=4; break; // 12bit/0.0625C
 }
 *pTemp = temp;
 
 return(0);
}


/*$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
** EOF
*/


路过

鸡蛋

鲜花

握手

雷人

发表评论 评论 (1 个评论)

回复 haha 2006-6-11 17:03

好,典型!!