下述代码为stm32在rt-thread平台下通过DS18B20采集温度的代码,温度较之实际温度扩大了10倍
static rt_thread_t ds18b20_tid=NULL;
///* 引脚编号,通过查看设备驱动文件drv_gpio.c确定 */
#define DS18B20_DQ 2 /* PA11 */
//复位DS18B20
void DS18B20_Rst(void)
{
rt_pin_mode(DS18B20_DQ, PIN_MODE_OUTPUT);// 引脚为输出模式
rt_pin_write(DS18B20_DQ, PIN_LOW); //拉低DQ
rt_hw_us_delay(750); //拉低750us(480 ~ 960us)
rt_pin_mode(DS18B20_DQ, PIN_MODE_INPUT); //设置为输入,即可释放总线的占用
//进入接收模式,等待应答信号。
}
//等待DS18B20的回应
//返回1:未检测到DS18B20的存在 返回0:存在
//等待了30us, 从机回应为108us,正常。
uint8_t DS18B20_Check(void)
{
uint8_t retry=0;
//------------------等待时间----------------------------------
rt_hw_us_delay(15); //15 ~60us 等待
while (rt_pin_read(DS18B20_DQ)&&retry<100) //最多还等待100us
{
retry++;
rt_hw_us_delay(1);
};
if(retry>=100) return 1; //100us未响应,则判断未检测到
else retry=0;
//----------------------从机拉低时间开始----------------------
while (!rt_pin_read(DS18B20_DQ)&&retry<240)
{
retry++;
rt_hw_us_delay(1);
};
if(retry>=240) return 1; //最长拉低240us
return 0;
}
//写一个字节到DS18B20
//dat:要写入的字节
void DS18B20_Write_Byte(uint8_t dat)
{
uint8_t j;
uint8_t testb;
rt_pin_mode(DS18B20_DQ, PIN_MODE_OUTPUT); // DQ引脚为输出模式
// dat = 0xaa;
for (j=1;j<=8;j++)
{
testb=dat&0x01;
dat=dat>>1;
if (testb) //输出高
{
rt_pin_write(DS18B20_DQ, PIN_LOW); //拉低DQ,主机输出低电平
rt_hw_us_delay(2); //延时2us
rt_pin_write(DS18B20_DQ, PIN_HIGH); //主机输出高电平
rt_hw_us_delay(60); //延时60us
}
else //输出低
{
rt_pin_write(DS18B20_DQ, PIN_LOW); //拉低DQ,主机输出低电平
rt_hw_us_delay(60); //延时60us
rt_pin_write(DS18B20_DQ, PIN_HIGH); //主机输出高电平
rt_hw_us_delay(2); //延时2us
}
}
rt_pin_mode(DS18B20_DQ, PIN_MODE_INPUT); //设置为输入,释放总线
}
//从DS18B20读取一个位
//返回值:1/0
uint8_t DS18B20_Read_Bit(void) // read one bit
{
uint8_t data;
rt_pin_mode(DS18B20_DQ, PIN_MODE_OUTPUT); // DQ引脚为输出模式
rt_pin_write(DS18B20_DQ, PIN_LOW); //拉低DQ,主机输出低电平
rt_hw_us_delay(2); //延时2us
rt_pin_mode(DS18B20_DQ, PIN_MODE_INPUT); //设置为输入,释放总线
rt_hw_us_delay(1);//延时1us
if(rt_pin_read(DS18B20_DQ))
data=1;//读取总线数据
else
data=0;
rt_hw_us_delay(60); //延时60us(读一位至少60us)
return data;
}
//从DS18B20读取一个字节
//返回值:读到的数据
uint8_t DS18B20_Read_Byte(void) // read one byte
{
uint8_t i,j,dat;
dat=0;
for (i=1;i<=8;i++)
{
j=DS18B20_Read_Bit();
dat=(j<<7)|(dat>>1);
}
return dat;
}
//开始温度转换
void DS18B20_Start(void)// ds1820 start convert
{
DS18B20_Rst();
DS18B20_Check();
DS18B20_Write_Byte(0xcc); // skip rom
DS18B20_Write_Byte(0x44); // convert
}
//从ds18b20得到温度值
//精度:0.5度
//返回值:温度值 (-550~1250)
int16_t DS18B20_Get_Temp(void)
{
uint8_t temp; //用来判断符号
uint8_t TL,TH;
uint16_t tem;
rt_base_t level;
level = rt_hw_interrupt_disable(); //API:进入临界区,退出前系统不会发生任务调度
DS18B20_Start (); // ds1820 start convert
rt_hw_interrupt_enable(level); //API:退出临界区
rt_thread_mdelay(800); //等待转换完成
level = rt_hw_interrupt_disable(); //API:进入临界区,退出前系统不会发生任务调度
DS18B20_Rst(); //复位
DS18B20_Check();
DS18B20_Write_Byte(0xcc); // skip rom
DS18B20_Write_Byte(0xbe); // 读取命令
TL=DS18B20_Read_Byte();
TH=DS18B20_Read_Byte();
rt_hw_interrupt_enable(level); //API:退出临界区
if(TH>7)
{
TH=~TH;
TL=~TL;
temp=0;//温度为负
}else temp=1;//温度为正
tem=TH; //获得高八位
tem<<=8;
tem+=TL;//获得底八位
tem=(float)tem*0.625;//转换
if(temp)
return tem; //返回温度值斤斤计较军军军军军
else
return -tem;
rt_kprintf("temp:%d\n",tem);
}
void ds18b20_tid_entry(void *parameter)
{
int16_t dat;
float dat1;
while(1)
{
rt_thread_mdelay(1000); //1s读取一次
dat = DS18B20_Get_Temp();
dat1=dat*0.1;
LOG_I("temp : %d\n",dat);//读取温度数据并发送到串口。
if(dat>270)
{
rt_thread_mdelay(1000);
LOG_I("aaaa");
rt_pin_write(LED_458_PIN , PIN_HIGH);
}else
{
rt_pin_write(LED_458_PIN , PIN_LOW);
}
//
// if(dat>50)
// {
// rt_thread_mdelay(1000);
// rt_pin_write(LED_458_PIN , PIN_LOW);
// LOG_I("BBBB");
rt_pin_write(LED_458_PIN , PIN_HIGH);
//
// }
}
}
void ds18b20_init(void)
{
/* 创建线程1,红色LED闪烁线程*/
ds18b20_tid = rt_thread_create("ds18b20_thread", //线程名字
ds18b20_tid_entry, //线程入口函数
RT_NULL, //线程入口参数
THREAD_STACK_SIZE, //堆栈大小,
THREAD_PRIORITY, //线程优先级
THREAD_TIMESLICE); //时间片长度
/* 如果获得线程控制块,启动这个线程 */
/* 如果获得线程控制块,启动这个线程 */
// if (ds18b20_tid != RT_NULL)
// rt_thread_startup(ds18b20_tid);
}