本项目通过STM32MINI板去获取ds18620温度传感器的温度数据,再通过串口将温度数据传输给电脑。
一、ds18620温度传感器:
1.介绍:
DS18B20 是由 Dallas Semiconductor(现 Maxim Integrated)推出的数字温度传感器,采用 1-Wire 总线协议,仅需单根数据线即可通信,支持多点组网,广泛用于嵌入式系统和物联网设备。
补充:1-Wire 总线是一种由 Dallas Semiconductor(现 Maxim Integrated)设计的 单线通信协议,以极简的硬件成本实现双向数据传输,广泛应用于传感器、存储器等低带宽设备。
2.技术特性
①独特的单总线接口方式,DS18B20在与微处理器连接时仅需要一条口线即可实现微处理器与DS18B20的双向通讯。大大提高了系统的抗干扰性。
② 测温范围 -55℃~+125℃,精度为±0.5℃。
③支持多点组网功能,多个DS18B20可以并联在唯一的三线上,最多只能并联8个,实现多点测温,如果数量过多,会使供电电源电压过低,从而造成信号传输的不稳定。
④ 工作电源: 3.0~5.5V/DC (可以数据线寄生电源)。
⑤ 在使用中不需要任何外围元件。
⑥ 测量结果以9~12位数字量方式串行传送。
3.硬件连接:
4.读取温度的过程:
复位发SKIP ROM命令(0XCC)——》发开始转换命令(0X44)——》延时——》复位——》发送SKIP ROM命令(0XCC)——》发读存储器命令(0XBE)——》连续读出两个字节数据(即温度)——》结束。
二、程序部分
1.ds18620驱动与头文件:
ds18620.c:
#include "ds18b20.h"
#include "Delay.h"
//Mini STM32开发板
//DS18B20 驱动函数
//正点原子@ALIENTEK
//2010/6/17
//复位DS18B20
void DS18B20_Rst(void)
{
DS18B20_IO_OUT(); //SET PA0 OUTPUT
Clr_DS18B20_DQ_OUT; //拉低DQ
Delay_us(750); //拉低750us
Set_DS18B20_DQ_OUT; //DQ=1
Delay_us(15); //15US
}
//等待DS18B20的回应
//返回1:未检测到DS18B20的存在
//返回0:存在
u8 DS18B20_Check(void)
{
u8 retry=0;
DS18B20_IO_IN();//SET PA0 INPUT
while (DS18B20_DQ_IN&&retry<200)
{
retry++;
Delay_us(1);
};
if(retry>=200)return 1;
else retry=0;
while (!DS18B20_DQ_IN&&retry<240)
{
retry++;
Delay_us(1);
};
if(retry>=240)return 1;
return 0;
}
//从DS18B20读取一个位
//返回值:1/0
u8 DS18B20_Read_Bit(void) // read one bit
{
u8 data;
DS18B20_IO_OUT();//SET PA0 OUTPUT
Clr_DS18B20_DQ_OUT;
Delay_us(2);
Set_DS18B20_DQ_OUT;
DS18B20_IO_IN();//SET PA0 INPUT
Delay_us(12);
if(DS18B20_DQ_IN)data=1;
else data=0;
Delay_us(50);
return data;
}
//从DS18B20读取一个字节
//返回值:读到的数据
u8 DS18B20_Read_Byte(void) // read one byte
{
u8 i,j,dat;
dat=0;
for (i=1;i<=8;i++)
{
j=DS18B20_Read_Bit();
dat=(j<<7)|(dat>>1);
}
return dat;
}
//写一个字节到DS18B20
//dat:要写入的字节
void DS18B20_Write_Byte(u8 dat)
{
u8 j;
u8 testb;
DS18B20_IO_OUT();//SET PA0 OUTPUT;
for (j=1;j<=8;j++)
{
testb=dat&0x01;
dat=dat>>1;
if (testb)
{
Clr_DS18B20_DQ_OUT;// Write 1
Delay_us(2);
Set_DS18B20_DQ_OUT;
Delay_us(60);
}
else
{
Clr_DS18B20_DQ_OUT;// Write 0
Delay_us(60);
Set_DS18B20_DQ_OUT;
Delay_us(2);
}
}
}
//开始温度转换
void DS18B20_Start(void)// ds1820 start convert
{
DS18B20_Rst();
DS18B20_Check();
DS18B20_Write_Byte(0xcc);// skip rom
DS18B20_Write_Byte(0x44);// convert
}
//初始化DS18B20的IO口 DQ 同时检测DS的存在
//返回1:不存在
//返回0:存在
u8 DS18B20_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure; //GPIO
//RCC->APB2ENR|=1<<2; //使能PORTA口时钟
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE ); //使能PORTA口时钟
//GPIOA->CRL&=0XFFFFFFF0;//PORTA.0 推挽输出
//GPIOA->CRL|=0X00000003;
//GPIOA->ODR|=1<<0; //输出1
/* Configure PA0 */
GPIO_InitStructure.GPIO_Pin = DS18B20_DQ_OUT_PIN; //SPI CS
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DS18B20_DQ_OUT_PORT, &GPIO_InitStructure);
/* Deselect the PA0 Select high */
GPIO_SetBits(DS18B20_DQ_OUT_PORT,DS18B20_DQ_OUT_PIN);
DS18B20_Rst();
return DS18B20_Check();
}
//从ds18b20得到温度值
//精度:0.1C
//返回值:温度值 (-550~1250)
short DS18B20_Get_Temp(void) {
u8 TL, TH;
short tem;
DS18B20_Rst();
if (DS18B20_Check()) return 9999; // 检测失败
DS18B20_Write_Byte(0xCC); // 跳过ROM
DS18B20_Write_Byte(0xBE); // 读取暂存器
TL = DS18B20_Read_Byte(); // 低字节
TH = DS18B20_Read_Byte(); // 高字节
// 判断是否为负温度(最高位为1)
if (TH & 0x80) {
// 补码转换:取反后加1
tem = (TH << 8) | TL;
tem = ~tem + 1;
tem = -tem; // 转换为负数
} else {
tem = (TH << 8) | TL; // 正温度直接组合
}
// 计算实际温度(12位分辨率,0.0625/bit,放大10倍返回)
tem = tem * 0.0625 * 10; // 示例:25.6℃返回256
return tem;
}
#ifndef __DS18B20_H
#define __DS18B20_H
#include "stm32f10x.h"
//Mini STM32开发板
//DS18B20 驱动函数
//IO方向设置
#define DS18B20_IO_IN() {GPIOA->CRL&=0XFFFFFFF0;GPIOA->CRL|=8<<0;}
#define DS18B20_IO_OUT() {GPIOA->CRL&=0XFFFFFFF0;GPIOA->CRL|=3<<0;}
IO操作函数
//#define DS18B20_DQ_OUT PAout(0) //数据端口 PA0
#define DS18B20_DQ_OUT_PORT GPIOA
#define DS18B20_DQ_OUT_CLK RCC_APB2Periph_GPIOA
#define DS18B20_DQ_OUT_PIN GPIO_Pin_0
#define Set_DS18B20_DQ_OUT {GPIO_SetBits(DS18B20_DQ_OUT_PORT,DS18B20_DQ_OUT_PIN);}
#define Clr_DS18B20_DQ_OUT {GPIO_ResetBits(DS18B20_DQ_OUT_PORT,DS18B20_DQ_OUT_PIN);}
//#define DS18B20_DQ_IN PAin(0) //数据端口 PA0
#define DS18B20_DQ_IN_PORT GPIOA
#define DS18B20_DQ_IN_CLK RCC_APB2Periph_GPIOA
#define DS18B20_DQ_IN_PIN GPIO_Pin_0
#define DS18B20_DQ_IN (GPIO_ReadInputDataBit(DS18B20_DQ_IN_PORT, DS18B20_DQ_IN_PIN))
u8 DS18B20_Init(void);//初始化DS18B20
short DS18B20_Get_Temp(void);//获取温度
void DS18B20_Start(void);//开始温度转换
void DS18B20_Write_Byte(u8 dat);//写入一个字节
u8 DS18B20_Read_Byte(void);//读出一个字节
u8 DS18B20_Read_Bit(void);//读出一个位
u8 DS18B20_Check(void);//检测是否存在DS18B20
void DS18B20_Rst(void);//复位DS18B20
#endif
2、main.c
#include "stm32f10x.h"
#include "GPIO.H"
#include "Delay.h"
#include "ds18b20.h"
#include "Serial.h"
#include <stdio.h> // 添加stdio.h用于sprintf
int main(void) {
gpio_init(); // 初始化GPIO(包含串口GPIO配置)
Serial_Init(); // 显式初始化串口(确保波特率、中断等配置正确)
short temperature;
if (DS18B20_Init() == 0) {
while(1) {
DS18B20_Start(); // 启动温度转换
Delay_ms(750); // 等待转换完成
temperature = DS18B20_Get_Temp();
// 发送温度字符串
char buffer[32];
sprintf(buffer, "Temp: %d\r\n", temperature);
Serial_SendString(buffer);
if (temperature >= 250) {
GPIO_WriteBit(GPIOA, GPIO_Pin_8, 0); // 报警
} else {
GPIO_WriteBit(GPIOA, GPIO_Pin_8, 1); // 关闭报警
}
Delay_s(1);
}
} else {
while(1) {
GPIO_WriteBit(GPIOA, GPIO_Pin_8, 0);
Delay_ms(500);
GPIO_WriteBit(GPIOA, GPIO_Pin_8, 1);
Delay_ms(500);
Serial_SendString("Sensor Error!\r\n"); // 明确错误信息
}
}
}