基于STM8的DS18B20检测

3 篇文章 0 订阅
1 篇文章 0 订阅

本人实力菜,望大佬手下留情,随手一记。

最近要鼓捣出5V的ds18b20用stm8采集,网上一搜发现大部分都是把数据端直接接到3.3的引脚,我也这么做的。

用的DS18B20为淘宝外面有钢管的那种,系统板为STM8L051,第一次接触stm8先去找的库函数,以附件形式粘贴到下面。用IAR建工程一搜一大把。

单总线协议因为只有一条线,时序很重要,肯定要使用延时函数,用的原子哥的延时函数,,照搬原子哥的代码:http://www.openedv.com/posts/list/17347/htm

记得定义头文件时加上 #include "stm8l15x_conf.h",不然会报错

#include "delay.h"

volatile u8 fac_us=0;

void delay_init(u8 clk)
{
  if(clk>16)fac_us=(16-4)/4;
  else if(clk>4)fac_us=(clk-4)/4;
  else fac_us=1;
}

void delay_us(u16 nus)
{
  __asm(
"PUSH A          \n"    //1T,压栈
"DELAY_XUS:      \n"
"LD A,fac_us     \n"    //1T,fac_us加载到累加器A
"DELAY_US_1:     \n"
"NOP             \n"    //1T,nop延时
"DEC A           \n"    //1T,A--
"JRNE DELAY_US_1 \n"    //不等于0,则跳转(2T)到DELAY_US_1继续执行,若等于0,则不跳转(1T).
"NOP             \n"    //1T,nop延时
"DECW X          \n"    //1T,x--
"JRNE DELAY_XUS  \n"    //不等于0,则跳转(2T)到DELAY_XUS继续执行,若等于0,则不跳转(1T).
"POP A           \n"    //1T,出栈
);
}

void delay_ms(u32 nms)
{
  u8 t;
  if(nms>65)
  {
    t=nms/65;
    while(t--)delay_us(65000);
    nms=nms%65;
  }
  delay_us(nms*1000);
}

因为我没有显示的东西,只能用printf,在参考大佬「C_Aya」的文章,原文链接:https://blog.csdn.net/baweiyaoji/article/details/72812045  成功弄出来后,可以正常打印字符串,但一遇到带参数的printf立马内存爆炸,然后又在参考大佬「Dancer__Sky」的文章,原文链接:https://blog.csdn.net/Dancer__Sky/article/details/82284961得以成功打印。记得自己的头文件不要定义成这个名字"stdarg.h",我都不记得C有这个头文件了,不然你无法调用C的stdarg.h,将会出现错误。

现在就到了最关键的时候了,这一部分我参考的大佬石破天开 https://blog.csdn.net/u012166958/article/details/84872480

// 复位,主机给从机发送复位脉冲
void DS18B20_Rst(void)
{
  DS18B20_Mode_Out();
  delay_us(2);
  DS18B20_DQ_OUT_Low;		// 产生至少480us的低电平复位信号
  delay_us(700);
  DS18B20_DQ_OUT_High;	// 在产生复位信号后,需将总线拉高
  delay_us(3);
}

// 写1字节到DS18B20
void DS18B20_Write_Byte(u8 dat)
{
  u8 j;
  u8 testb;
  DS18B20_Mode_Out();
  for (j = 1; j <= 8; j++)
  {
    testb = dat & 0x01;
    dat = dat >> 1;
    if (testb)
    {
      DS18B20_DQ_OUT_Low;// 写1
      delay_us(2);
      DS18B20_DQ_OUT_High;
      delay_us(80);
    }
    else
    {
      DS18B20_DQ_OUT_Low;// 写0
      delay_us(78);
      DS18B20_DQ_OUT_High;// 释放总线
      delay_us(2);
    }
}

这两部分延时不太一样,贴出来大家可以试一试。注意引脚输入不要弄错成浮空输入。

DS18B20 2.0版本,在之前基础上添加了查询序列号

当只有一个DS18B20的时候

void DS18B20_Search_Rom(void) //函数位置放在初始化下方 ,读取单个设备的序列号
{
  DS18B20_Write_Byte(0x33);
  delay_us(2);
  for(u8 j = 0; j <8; j++)
  {
    address[j] = DS18B20_Read_Byte();
  }
}    //重复读取可能有点问题,建议放在while上边

有多个DS18B20时,参考大佬 https://blog.csdn.net/u012166958/article/details/84872480

void DS18B20_Search_Rom(void)
{
  u8 ReadBit,data;
  u8 i,j,t = 0 ;
  u8 chongtuwei;
  u8 zhan[5];
  u8 Sequence[64];//序列码 
  DS18B20_Struct.ID_Num = 0;
  do
  {
//    DS18B20_Rst();   //这里我加上会出问题,所以我注释掉了
//    delay_us(450);
    DS18B20_Write_Byte(0xF0);
    delay_us(2);
    for(i = 0;i < 8;i++)
    {
      data =0;
      for(j = 0;j < 8;j++)
      {
        ReadBit = DS18B20_Read_2Bit();
        ReadBit = ReadBit & 0x03;
        data >>=1;
        if(ReadBit == 0x01)	//读到的数据位0 写0 此位为0的器件响应
        {
          DS18B20_Write_Bit(0);
          Sequence[(i * 8 + j)] = 0;
        }else if(ReadBit == 0x02)//读到的数据位1 写1 此位为1的器件响应
        {
          data = data|0x80;
          DS18B20_Write_Bit(1);
          Sequence[i * 8 + j] = 1;
        }else if(ReadBit == 0x00)	//读到的数据位0,有冲突位,判断冲突位
        {
                //如果冲突位大于栈顶写0,小于栈顶写以前数据,等于栈顶写1
          chongtuwei = i * 8 + j + 1;
          if(chongtuwei > zhan[t])
          {
                  DS18B20_Write_Bit(0);
                  Sequence[(i * 8 + j)] = 0;
                  zhan[++t] = chongtuwei;
          }else if (chongtuwei < zhan[t])
          {
                  data = data|((Sequence[(i * 8 + j)]&0x01)<<7);
                  DS18B20_Write_Bit(Sequence[(i * 8 + j)]);
          }else if(chongtuwei == zhan[t])
          {
                  data = data|0x80;
                  DS18B20_Write_Bit(1);
                  Sequence[(i * 8 + j)] = 1;
                  t--;
          }
        }else 	//没搜索到
        {
        
        }
      } 
      DS18B20_Struct.DS18B20_ID[DS18B20_Struct.ID_Num][i] = data;
    }
    DS18B20_Struct.ID_Num++;//保存搜索到的个数
  }while(zhan[t] !=0&&(DS18B20_Struct.ID_Num < ROM_ID)); 
}

主函数

void main(void)
{
  sys_clock_init();//16MHZ工作
  GPIO_Init(GPIOD,GPIO_Pin_0,GPIO_Mode_Out_PP_Low_Fast);//配置D0的工作模式  
  usart_init(115200);
  delay_init(16);
  while(DS18B20_Init());//初始化加检测
  DS18B20_Search_Rom();
  while (1)
  { 
    
    //DS18B20_Init();
    i = DS18B20_Get_Temp();
    
    mprintf("temp=%f",i);
    
  }
}

 

最后大体是这个效果 版本1.0

  • 2
    点赞
  • 4
    收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:书香水墨 设计师:CSDN官方博客 返回首页
评论 1

打赏作者

萌新小白YXY

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

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

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

打赏作者

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

抵扣说明:

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

余额充值