OK6410开发板裸机DS18B20驱动
扫描二维码
随时随地手机看文章
相信玩过51的童鞋应该都玩过DS18B20吧,虽然用在ARM11上面,但是操作还是一样,多了一点就是读写IO前需要切换IO方向,其实51在读取之前需要切换到高电平的,这个一般由编译器完成的,
/*************************************************************************************************************
* 文件名: ds18b20.c
* 功能: S3C6410 DS18B20驱动
* 作者: cp1300@139.com
* 创建时间: 2012年9月17日22:45
* 最后修改时间:2012年9月17日
* 详细: 需要延时函数支持
* 注意延时精度尽可能的高
* 读取的时候不要长时间的被中断,因为1wire对时间要求很严格
*************************************************************************************************************/
#include "system.h"
#include "timer.h"
#include "delay.h"
#include "ds18b20.h"
//DS18B20使用的是GPIOE0
#define Set18b20IOout() (rGPECON |= 1) //设置DS18B20 IO为输出,
#define Set18b20IOin() (rGPECON &= (~0xf)) //设置DS18B20 IO为浮空输入,
#define Read18b20IO() ((rGPEDAT & BIT0) ? 1 : 0) //读取DS18B20 IO
#define Write18b20IO(x) (x ? (rGPEDAT |= BIT0) : (rGPEDAT &= ~BIT0)) //写DS18B20 IO
/*************************************************************************************************************************
*函数 : u8 DS18B20_Reset(void)
*功能 : 复位DS18B20
*参数 : 无
*返回 : 0:成功;1:失败
*依赖 : 底层宏定义
*作者 : cp1300@139.com
*时间 : 20120917
*最后修改时间: 20120917
*说明 :无
*************************************************************************************************************************/
u8 DS18B20_Reset(void)
{
u8 i = 0;
Set18b20IOout(); //主机端口推挽输出模式
Write18b20IO(1);
Delay_US(1);
Write18b20IO(0); //拉低总线480us~240us
Delay_US(500); //>480US延时
Write18b20IO(1);
Delay_US(2); //复位完成
Set18b20IOin(); //主机端口浮空输入模式
while(Read18b20IO()) //等待低电平应答信号
{
i ++;
Delay_US(1);
if(i > 100)
return 1; //等待超时,初始化失败,返回1;
}
Delay_US(250); //跳过回复信号
return 0x00; //检测到DS18B20,并且初始化成功
}
/*************************************************************************************************************************
*函数 : u8 DS18B20_ReadData(void)
*功能 : 读取DS18B20数据
*参数 : 无
*返回 : 数据
*依赖 : 底层宏定义
*作者 : cp1300@139.com
*时间 : 20120917
*最后修改时间: 20120917
*说明 :无
*************************************************************************************************************************/
u8 DS18B20_ReadData(void)
{
u8 i,data = 0;
for(i = 0;i < 8;i ++)
{
Set18b20IOout(); //主机端口推挽输出模式
Write18b20IO(0); //拉低总线10-15us
data >>= 1;
Delay_US(12);
Write18b20IO(1); //释放总线
Set18b20IOin(); //主机端口浮空输入模式
Delay_US(1);
if(Read18b20IO()) //读取数据,读取后大约延时40-45us
data |= 0x80;
Delay_US(42);
}
return data;
}
/*************************************************************************************************************************
*函数 : void DS18B20_WriteData(u8 data)
*功能 : 向DS18B20写数据
*参数 : 数据
*返回 : 无
*依赖 : 底层宏定义
*作者 : cp1300@139.com
*时间 : 20120917
*最后修改时间: 20120917
*说明 :无
*************************************************************************************************************************/
void DS18B20_WriteData(u8 data)
{
u8 i;
Set18b20IOout(); //主机端口推挽输出模式
for(i = 0;i < 8;i ++)
{
Write18b20IO(0); //拉低总线10-15us
Delay_US(12);
Write18b20IO(data & 0x01); //写入数据位,保持20-45us
Delay_US(30);
Write18b20IO(1); //释放总线
data >>= 1;
Delay_US(2);
}
}
/*************************************************************************************************************************
*函数 : s16 DS18B20_ReadTemper(void)
*功能 : 读取DS18B20温度
*参数 : 无
*返回 : 温度值
*依赖 : 底层宏定义
*作者 : cp1300@139.com
*时间 : 20120917
*最后修改时间: 20120917
*说明 :温度值扩大了100倍,温度值是个有符号数.
*************************************************************************************************************************/
s16 DS18B20_ReadTemper(void)
{
u8 th, tl;
s16 data;
if(DS18B20_Reset())
{
return 0xffff; //返回错误
}
DS18B20_WriteData(0xcc); //跳过读序列号
DS18B20_WriteData(0x44); //启动温度转换
DS18B20_Reset();
DS18B20_WriteData(0xcc); //跳过读序列号
DS18B20_WriteData(0xbe); //读取温度
tl = DS18B20_ReadData(); //读取低八位
th = DS18B20_ReadData(); //读取高八位
data = th;
data <<= 8;
data |= tl;
data *= 6.25; //温度值扩大100倍,精确到2位小数
return data;
}
DS18B20.H
#ifndef DS18B20_H_
#define DS18B20_H_
s16 DS18B20_ReadTemper(void); //读取DS18B20温度
#endif /*DS18B20_H_*/
DELAY.C
/*************************************************************************************************************
* 文件名: delay.c
* 功能: 延时函数,调用定时器1进行延时的
* 作者: cp1300@139.com
* 创建时间: 2012年9月17日22:32
* 最后修改时间:2012年9月17日
* 详细: 延时误差1-2us,使用定时器1
* 不能在中断服务程序中使用
*************************************************************************************************************/
#include "system.h"
#include "timer.h"
#include "delay.h"
/*************************************************************************************************************************
*函数 : void Delay_US(u32 Delay)
*功能 : US延时
*参数 : Delay:延时时间,单位US
*返回 : 无
*依赖 : 底层宏定义
*作者 : cp1300@139.com
*时间 : 20120917
*最后修改时间: 20120917
*说明 :调用定时器0进行延时的,那么定时器0就不能使用了,延时误差1US
*************************************************************************************************************************/
void Delay_US(u32 Delay)
{
rTCFG0 |= 65; //定时器0预分频65+1,由PCLK=66提供时钟,66分频产生1MHz的定时器时钟
rTCON &= (~0xff); //清除设置
rTCON |= BIT3; //定时器0自动更新使能
rTCNTB0 = Delay; //重装值
rTINT_CSTAT |= BIT5; //清除中断标志
rTINT_CSTAT &= ~BIT0; //关闭定时器0中断
//以下操作启动定时器0
rTCON |= BIT1; //手动更新
rTCON &= ~BIT1; //结束手动更新
rTCON |= BIT0; //启动定时器0
while(!(rTINT_CSTAT & BIT5)); //等待延时到达
rTINT_CSTAT |= BIT5; //清除中断标志
}
/*************************************************************************************************************************
*函数 : void Delay_MS(u32 Delay)
*功能 : MS延时
*参数 : Delay:延时时间,单位US
*返回 : 无
*依赖 : 底层宏定义
*作者 : cp1300@139.com
*时间 : 20120918
*最后修改时间: 20120918
*说明 :调用定时器0进行延时的,那么定时器0就不能使用了,延时误差<1ms
*************************************************************************************************************************/
void Delay_MS(u32 Delay)
{
while(Delay --)
{
Delay_US(1000);
}
}
后面将这个程序移植到LINUX上面当做DS18B20驱动