STM32 FreeRTOS DS18B20 驱动 使用ROM检查

前言

最近移植了FreeRTOS, 这里记录下FreeRTOS下温度传感器的简单驱动, 顺便试试看rom验证

硬件定义, 接口较为简单只需要一个GPIO, 根据硬件手册配置

//定义DS18B20引脚信息
#define DS18B20_PIN				GPIO_Pin_11 
//输入和输出的位带操作
#define  DS18B20_DQ_OUT			PGout(11)
#define  DS18B20_DQ_IN			PGin(11)

初始化逻辑

	//定义GPIOG11为推挽输出
	void DS18B20_IO_OUT(void) {
		GPIO_InitTypeDef GPIO_Config;
		GPIO_Config.GPIO_Pin = DS18B20_PIN;
		GPIO_Config.GPIO_Mode = GPIO_Mode_Out_PP; //推挽
		GPIO_Config.GPIO_Speed = GPIO_Speed_50MHz;
		GPIO_Init(GPIOG, &GPIO_Config);
	}
	
	//定义GPIOG11为上拉输入
	void DS18B20_IO_IN(void) {
		GPIO_InitTypeDef GPIO_Config;
		GPIO_Config.GPIO_Pin = DS18B20_PIN;
		GPIO_Config.GPIO_Mode = GPIO_Mode_IPU;  //上拉输入
	 	GPIO_Init(GPIOG, &GPIO_Config);
	}

	//使能 GPIOG 时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG, ENABLE);
	
	//默认推挽输出
	DS18B20_IO_OUT();
	

读写入字节核心驱动

//读1字节数据函数
u8 DS18B20_Read_Byte(void) {
	u8 i;
	u8 data = 0;
	for(i = 0; i < 8; i++) {
		taskENTER_CRITICAL();
		DS18B20_IO_OUT(); //配为输出
		DS18B20_DQ_OUT = 0; //清零
		delay_us(2);
		DS18B20_IO_IN();    //配为输入
		delay_us(8);
		data |= DS18B20_DQ_IN << i;  //从低位开始一位一位的获取保存到data中
		delay_us(50);	   //延时等待传输下一个bit位
		taskEXIT_CRITICAL();
	}
	return data;
}

//定义发送1字节函数, 1线总线数据传输, 注意时序要求较高容易被干扰
void DS18B20_Write_Byte(u8 data) {
	u8 i;
	DS18B20_IO_OUT();       //配置为输出准备开始发送数据

	for(i = 0; i < 8; i++) {
		taskENTER_CRITICAL();  //锁住 一线总线时序比较敏感需要加锁, 应尽快解锁
		if(data & 0x01) {     //写1操作
			DS18B20_DQ_OUT = 0; //拉低
			delay_us(2);
			DS18B20_DQ_OUT = 1; //拉高
			delay_us(60);				//此时外设完成数据1的采样
		} else {	//写0操作
			DS18B20_DQ_OUT = 0; //拉低
			delay_us(60);
			DS18B20_DQ_OUT = 1; //拉高,此时外设完成数据0的采样
			delay_us(2);
		}
		taskEXIT_CRITICAL();//解锁
		data >>= 1;
	}
}

重置逻辑

//定义初始化复位函数,需参考时序图
u8 DS18B20_Reset(void) {
	u8 retry = 0;
	DS18B20_IO_OUT();   //先配置为输出
	DS18B20_DQ_OUT = 0;	//拉低电平
	delay_us(500);
	DS18B20_DQ_OUT = 1; //拉高电平
	delay_us(30);
	taskENTER_CRITICAL(); //临界区处理
	//检测应答信号
	DS18B20_IO_IN();    //配置为输入, 开始等待响应
	while(DS18B20_DQ_IN && retry < 40) {  // 先等待 低电平 最大40 微秒
		retry++;
		delay_us(1);
	}
	retry=0;
	while(!DS18B20_DQ_IN && retry < 250) { //等待 高电平 最大 250 微秒
		retry++;
		delay_us(1);
	}
	taskEXIT_CRITICAL();
	if(retry >= 240){  //根据白皮书不得超过240
		printf("DS18B20 reset failed.\n");
	    return 0;
	}
	else {
		return 1;
	}
}

取得 rom 和检查

// crc8 计算
u8 CRC_CalcLowCrc8(u8 *pdat, u16 len)
{
	unsigned char j;
	unsigned char crc = 0x00;
	while(len--)
	{
			crc ^= (*pdat++);
			for (j=8; j>0; --j)
			{ 
				if (crc & 0x01)
					crc = (crc >> 1) ^ 0x8C;
				else
					crc = (crc >> 1);
			}
	}

	return crc;
}

// 取得 rom 然后检查crc
void DS18B20_GetRom(u8 rom[]) {
	if (rom[8] == 0) {
		s8 i = 0;
		//复位
		DS18B20_Reset();
		//发送Read ROM命令
		DS18B20_Write_Byte(0x33);
		for(i = 0;i < 8 ;i++) {
			rom[i] = DS18B20_Read_Byte();
		}
		print_log("Temp Rom Copy: length = 8");
		print_mem(rom, 8);
		print_info("CRC is %#x\r\n Start Test...", rom[7]);
		
		if(rom[7] == CRC_CalcLowCrc8(rom, 7)) {
			print_log("Matched");
			rom[8] = 1;  //标记已经初始化
		}
		print_log("");
	}
}

最后取得温度

// 默认的rom
static u8 rom0[9];
//定义获取温度值的函数
float DS18B20_GetTemperature() {
	u16 temp = 999; // 默认999
	u16 temp_lsb = 0, temp_msb = 0; //暂存温度值的低字节和高字节
#ifdef USE_ROM
	u8 i;
#endif

#ifdef USE_ROM
	DS18B20_GetRom(rom0);  //这里自动取得rom0, 也可以改为传其他rom
#endif
	//复位
	if(DS18B20_Reset()) {
#ifdef USE_ROM
		DS18B20_Write_Byte(0x55);
		for(i=0;i<8;i++){
			DS18B20_Write_Byte(rom0[i]);
		}
#else
		DS18B20_Write_Byte(0xCC);  //只有一个温度传感器, 则可以跳过rom检查
#endif
		//发送温度转换命令,温度值保存到byte0和byte1内存中
		DS18B20_Write_Byte(0x44);
		//复位
		if(DS18B20_Reset()) {
	#ifdef USE_ROM
			DS18B20_Write_Byte(0x55);  
			for(i=0;i<8;i++){
				DS18B20_Write_Byte(rom0[i]);
			}
	#else
			DS18B20_Write_Byte(0xCC);
	#endif
			//发送读内存命令
			DS18B20_Write_Byte(0xBE);
			//读取byte0和byte1
			temp_lsb = DS18B20_Read_Byte();
			temp_msb = DS18B20_Read_Byte();
			// 合并得到温度的数字量
			temp = (temp_msb << 8) | temp_lsb;
			//负数转换
			if((temp & 0xF800) == 0xF800) {
				temp = ((~temp) + 1) * -1;
			}
		}
	}

	return temp * 0.0625;   //最后乘以倍率
}

参考效果

在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Potcutre

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值