#include "stm32f10x.h"
#include "delay.h"
#include "sys.h"
#include "oled.h"
#include "bmp.h"
#include "usart.h"
#include "JQ8X00.h"
#include <string.h>
#define SkipROM 0xCC
#define SearchROM 0xF0
#define ReadROM 0x33
#define MatchROM 0x55
#define AlarmROM 0xEC
#define StartConvert 0x44
#define ReadScratchpad 0xBE
#define WriteScratchpad 0x4E
#define CopyScratchpad 0x48
#define RecallEEPROM 0xB8
#define ReadPower 0xB4
#define EnableINT()
#define DisableINT()
#define DS_PRECISION 0x7f
#define DS_AlarmTH 0x64
#define DS_AlarmTL 0x8a
#define DS_CONVERT_TICK 1000
#define DS_PORT GPIOA
#define DS_DQIO GPIO_Pin_12
#define DS_RCC_PORT RCC_APB2Periph_GPIOA
#define ResetDQ() GPIO_ResetBits(DS_PORT,DS_DQIO)
#define SetDQ() GPIO_SetBits(DS_PORT,DS_DQIO)
#define GetDQ() GPIO_ReadInputDataBit(DS_PORT,DS_DQIO)
/*
初始化、读、写 时序操作
*/
///
// 总线在空闲状态为高电平
// 总线保持低电平超过480us,则总线上的组组件都复位
///
unsigned char ResetDS18B20(void)
{
unsigned char resport;
SetDQ();
delay_us(50);
ResetDQ();
delay_us(500);//总线保持低电平超过480us
SetDQ(); //释放总线
delay_us(40);//DS18B20wait15~60us之间,得到DS18B20的存在脉冲60-240us
//resport = GetDQ();
while(GetDQ());//一直等待接收,只有当接收到DQ被拉低才会退出循环
delay_us(500);//读到低电平后仍然要延时>480us,结束过程
SetDQ();//将总线释放
return resport;
}
///
// 写时序
//
///
void DS18B20WriteByte(unsigned char Dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
ResetDQ(); //总线由高变低电平,开始启动写入时隙
delay(5); //延时大于1us
if(Dat & 0x01)//将数据LSB传到总线
SetDQ();
else
ResetDQ();
delay_us(65);//写入时隙的持续时间至少为60us
SetDQ(); //单个写入时隙之间的周期>1us
delay_us(2);
Dat >> 1;
}
}
///
// 读时序
//
///
unsigned char DS18B20ReadByte(void)
{
unsigned char i,Dat;
SetDQ(); //第一位读取先置高5us延时
delay_us(5);
for(i=0;i<8;i++)//DS18B20输出的数据在读取时隙下降沿后的15us内有效
{
Dat >>= 1;
ResetDQ();//总线从高到低电平至少保持1us
delay_us(5);
SetDQ();//释放总线
delay_us(5);//延时后进行采样
if(GetDQ())
Dat |= 0x80;//只改变最高位为1
else
Dat &= 0x7f;//只改变最高位为0
delay_us(65);//读取时隙的持续时间为60us
SetDQ();
}
return Dat;
}
/*
64位激光ROM命令函数操作
五个ROM功能命令
1)读取ROM
2)匹配ROM
3)搜索ROM
4)跳过ROM DS18B20WriteByte(SkipROM);
5)报警搜索
成功执行ROM功能序列后,可以访问存储器和控制功能
*/
void ReadRom(unsigned char *Read_Addr)
{
unsigned char i;
ResetDS18B20(); //首先复位
DS18B20WriteByte(ReadROM);//写读ROM指令
for(i=0;i<8;i++)
{
*Read_Addr=DS18B20ReadByte(); //读取八个字节的内存
Read_Addr++;
}
}
/*
内存功能命令操作
DS18B20WriteByte(WriteScratchpad);
DS18B20WriteByte(ReadScratchpad);
DS18B20WriteByte(CopyScratchpad);
DS18B20WriteByte(StartConvert);
*/
void DS18B20Init(unsigned char Precision,unsigned char AlarmTH,unsigned char AlarmTL)
{
ResetDS18B20();
DS18B20WriteByte(SkipROM);
DS18B20WriteByte(WriteScratchpad);
DS18B20WriteByte(AlarmTL);
DS18B20WriteByte(AlarmTH);
DS18B20WriteByte(Precision);
ResetDS18B20();
DS18B20WriteByte(SkipROM); //如果寄生电源供电,则发出copy命令后上拉10ms
DS18B20WriteByte(CopyScratchpad);//parasite-powered寄生电源,器件由串行接口直接供电
while(!GetDQ());//只要DS18B20忙于将暂存器复制到E2,它就会在总线输出0,复制完成后返回1
}
void DS18B20StartConvert(void)
{
ResetDS18B20();
DS18B20WriteByte(SkipROM);
DS18B20WriteByte(StartConvert);
//只要DS18B20忙于转换温度,它就会在总线输出0,转换温度后返回1
}
void DS18B20_Configuration(void)
{
GPIO_InitTypeDef GPIO_Instructure;
RCC_APB2PeriphClockCmd(DS_RCC_PORT,ENABLE);
GPIO_InitStructure.GPIO_Pin = DS_DQIO;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DS_PORT,&GPIO_InitStructure);
}
void ds18b20_init(void)
{
DS18B20_Configuration();
DS18B20Init(DS_PRECISION,DS_AlarmTH,DS_AlarmTL);
DS18B20StartConvert();
}
float ds18b20_read(void)
{
unsigned char DL,DH;
unsigned short TemperatureData;
float Temperature;
DS18B20StartConvert();
while(!GetDQ());
ResetDS18B20();
DS18B20WriteByte(SkipROM);
DS18B20WriteByte(ReadScratchpad);
DL = DS18B20ReadByte();
DH = DS18B20ReadByte();
TemperatureData = DH;
TemperatureData <<= 8;
TemperatureData |=DL;
Temperature = (float)((float)TemperatureData * 0.0625);
return Temperature;
}
int WenDu;
int main(void)
{
delay_init();
ds18b20_init();
while(1)
{
WenDu = ds18b20_read();
delay_ms(500);
}
}
【DS18B20调用函数】
最新推荐文章于 2024-06-25 09:29:06 发布