您尚未登录。

楼主 # 2022-01-13 01:15:03

缥缈九哥
会员
注册时间: 2020-05-09
已发帖子: 76
积分: 92

基于华芯微特SWM181CB的DS18B20温度传感器的1-wire驱动程序

还是直接上代码吧:

/********************************************************************************
 * @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;
}
//代码完毕

离线

#1 2022-01-13 13:31:03

LinjieGuo
Moderator
注册时间: 2019-07-24
已发帖子: 565
积分: 570
个人网站

Re: 基于华芯微特SWM181CB的DS18B20温度传感器的1-wire驱动程序

@缥缈九哥
九哥,还可以使用串口转单总线时序,节省CPU资源。
但是我具体不知道怎么做......(狗头保命)

离线

页脚

工信部备案:粤ICP备20025096号 Powered by FluxBB

感谢为中文互联网持续输出优质内容的各位老铁们。 QQ: 516333132, 微信(wechat): whycan_cn (哇酷网/挖坑网/填坑网) service@whycan.cn