相信玩过51的童鞋应该都玩过DS18B20吧,虽然用在ARM11上面,但是操作还是一样,多了一点就是读写IO前需要切换IO方向,其实51在读取之前需要切换到高电平的,这个一般由编译器完成的,
/************************************************************************************************************* * 文件名: ds18b20.c * 功能: S3C6410 DS18B20驱动 * 作者: [email protected] * 创建时间: 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:失败 *依赖 : 底层宏定义 *作者 : [email protected] *时间 : 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数据 *参数 : 无 *返回 : 数据 *依赖 : 底层宏定义 *作者 : [email protected] *时间 : 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写数据 *参数 : 数据 *返回 : 无 *依赖 : 底层宏定义 *作者 : [email protected] *时间 : 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温度 *参数 : 无 *返回 : 温度值 *依赖 : 底层宏定义 *作者 : [email protected] *时间 : 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进行延时的 * 作者: [email protected] * 创建时间: 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 *返回 : 无 *依赖 : 底层宏定义 *作者 : [email protected] *时间 : 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 *返回 : 无 *依赖 : 底层宏定义 *作者 : [email protected] *时间 : 20120918 *最后修改时间: 20120918 *说明 :调用定时器0进行延时的,那么定时器0就不能使用了,延时误差<1ms *************************************************************************************************************************/ void Delay_MS(u32 Delay) { while(Delay --) { Delay_US(1000); } }