还是直接上代码吧:
/********************************************************************************
* @file ds18b20.c *
* @brief The Driver code for DS18B20 with SWM181CBT6 *
* @version 1.0.0 *
* @date 2018/09/19 19:26:35 *
* *
* @note *
* Copyright (C) 2000-2018 PM9GZY by yuanxihua@21cn.com. All rights reserved. *
********************************************************************************/
/* Includes --------------------------------------------------------------------*/
#include "main.h"
/*
_________________________________________________
| SWM181CBT6 DS18B20 |
| |
| DATA - PC2 <---> DQ0 |
|_______________________________________________|
*/
/* Private typedef -----------------------------------------------------------*/
#define SkipROM 0xCC //跳过ROM
#define SearchROM 0xF0 //搜索ROM
#define ReadROM 0x33 //读ROM
#define MatchROM 0x55 //匹配ROM
#define AlarmROM 0xEC //告警ROM
#define StartConvert 0x44 //开始温度转换,在温度转换期间总线上输出0,转换结束后输出1
#define ReadScratchpad 0xBE //读寄存器的9个字节
#define WriteScratchpad 0x4E //写寄存器的温度告警TH和TL
#define CopyScratchpad 0x48 //将寄存器的温度告警复制到EEPROM,在复制期间总线上输出0,复制完后输出1
#define RecallEEPROM 0xB8 //将EEPROM的温度告警复制到寄存器中,复制期间输出0,复制完成后输出1
#define ReadPower 0xB4 //读电源的供电方式:0为寄生电源供电;1为外部电源供电
/* Private define ------------------------------------------------------------*/
#define PC2 PIN2
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
//void delay_us(uint32_t us)
//{
// int32_t t=SysTick->VAL-(us*CyclesPerUs);
// if(t<0){t+=SysTick->LOAD;while((SysTick->CTRL&SysTick_CTRL_COUNTFLAG_Msk)==0){;}}
// while(SysTick->VAL>t){;}
//}
//1.初始化
uint8_t DS18B20_init(uint32_t n)
{
uint32_t i=0,ret=1;
GPIO_Init(GPIOC, n, 1, 1, 0, 0); //DQ 配置为输出引脚,开启上拉,推挽输出
GPIO_SetBit(GPIOC, n); //DQ=1;
delay_us(900); //稍作延时
//开始初始化
GPIO_ClrBit(GPIOC, n); //DQ=0;
delay_us(540); //延时540us
GPIO_SetBit(GPIOC, n); //DQ=1;
GPIO_Init(GPIOC, n, 0, 1, 0, 0); //DQ 配置为输入引脚,开启上拉
delay_us(60); //稍作延时
while(GPIO_GetBit(GPIOC, n)) //等待DS18B20拉低总线
{
delay_us(1);
if(i++>240){ret=0;break;} //初始化失败
}
GPIO_Init(GPIOC, n, 1, 1, 0, 0); //DQ 配置为输出引脚,开启上拉,推挽输出
GPIO_SetBit(GPIOC, n); //DQ=1;
delay_us(480);
return ret; //初始化成功
}
//2.写字节
void write_byte(uint32_t n,uint8_t dat) //写一个字节
{
uint8_t i;
for(i=0;i<8;i++)
{
GPIO_ClrBit(GPIOC, n); //DQ=0; 总线拉低1us
delay_us(1);
if(dat&0x01){GPIO_SetBit(GPIOC, n);} //取最低位写入
else{GPIO_ClrBit(GPIOC, n);}
delay_us(60); //延时60us
GPIO_SetBit(GPIOC, n); //DQ=1; 释放总线
delay_us(1);
dat=dat>>1; //从低位开始写
}
}
//3.读字节
uint8_t read_byte(uint32_t n) //读一个字节
{
uint8_t i,dat=0;
for(i=0;i<8;i++)
{
GPIO_ClrBit(GPIOC, n); //DQ=0; 总线拉低1us
delay_us(1);
GPIO_SetBit(GPIOC, n); //DQ=1; 释放总线
GPIO_Init(GPIOC, n, 0, 1, 0, 0); //DQ 配置为输入引脚,开启上拉
delay_us(2); //延时等待数据稳定 5
dat=dat>>1; //从最低位开始读
if(GPIO_GetBit(GPIOC, n)){dat|=0x80;} //每次读一位
else{dat&=0x7f;}
delay_us(30); //等待读取数据稳定
GPIO_Init(GPIOC, n, 1, 1, 0, 0); //DQ 配置为输出引脚,开启上拉,推挽输出
GPIO_SetBit(GPIOC, n); //DQ=1; 释放总线
delay_us(1);
}
return dat;
}
//4.按位CRC运算
//Purpose: To calculate an 8-bit CRC based on a polynomial and the series
// of data bytes
//Note: Polynomial used x^8 + x^5 + x^4 + 1 = 10001100
//Inputs: A pointer to an array of the data bytes and an uint8_t saying how many
// bytes there are in the data array
//Outputs: An uint8_t which is the calculated CRC
uint8_t OneWireCRC8(uint8_t *buf, uint8_t len)
{
#define CRC8_POLYNOMIAL 0x8C
uint8_t crc=0,val=0,inb,mix;
while(len--){inb=*buf++;if(inb){val=1;}for(uint8_t i=8;i;i--){mix=(crc^inb)&0x01;crc>>=1;if(mix){crc^=CRC8_POLYNOMIAL;}inb>>=1;}}
if(!val){return 0xFF;} /* If all bytes are 0, return a different CRC so that the test will fail */
return crc;
}
//5.读温度
uint16_t read_temper(uint32_t n)
{
uint16_t temp=0xffff;uint8_t data[9],crc,ret;ret=ret;
ret=DS18B20_init(n);
write_byte(n,0xcc); //跳过ROM操作命令
write_byte(n,0x44); //发送启动温度转换命令
delay_us(2000);
ret=DS18B20_init(n);
write_byte(n,0xcc); //跳过ROM操作命令
write_byte(n,0xbe); //发送读温度寄存器命令
delay_us(2000);
for(int i=0;i<9;i++){data[i]=read_byte(n);} //read Scratchpad Memory of DS
crc=OneWireCRC8(data,8); //calculate crc
if(crc==data[8]){temp=((uint16_t)data[1]<<8)|data[0];} //compare : calculate with received
return temp; //返回温度值
}
//6.温度转换
float temper_change(uint32_t n)
{
int32_t temper;float tp;
temper=read_temper(n);
printf("temper=0x%04x\n\r",temper);
if(temper<0) //考虑负温度的情况
{
temper=temper-1;
temper=~temper;
}
tp=temper/16; //16位温度转换成10进制的温度
temper=tp*100+0.5; //留两个小数点,并四舍五入
printf("DS18B20=%3.2f\n\r",tp);
return temper;
}
//代码完毕
离线