找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1915|回复: 1
收起左侧

STM32F1的DS18B20驱动源码.c/.h文件

[复制链接]
ID:142059 发表于 2019-12-18 02:29 | 显示全部楼层 |阅读模式
基于标准库,只要带有标准库的gpio的库即可使用。经测试可用。和其他人的驱动不一样!带滤波!
51hei.png

单片机源程序如下:
  1. #include "ds18b20.h"
  2. /*
  3. 以下配置函数基于stm32f1标准库,如使用其他库或非f1的请修改3个函数(有标注)。
  4. */

  5. typedef struct
  6. {
  7.         char firstdatacheckokflag;
  8.         char firstenterndatacheckflag;
  9.         char firstdatacheckerrflag;
  10.         char firstdataCnt;
  11.         float firstdata;
  12.                
  13.         char firstEnterFlag;
  14.         float Temperature1Last;
  15.        
  16.         unsigned int Avgcounter;
  17.         unsigned int AvgAwscounter;
  18.         unsigned char ValAvgReset;      //=0 重置ValAvg统计
  19. }volatile TEMPDS18B;
  20. TEMPDS18B FisrtDs18b[DS18B20_NUM];

  21. struct DS18B20_SORT
  22. {
  23.         uint8_t NUM;
  24.         GPIO_TypeDef* GPIO[DS18B20_NUM];
  25.   uint16_t      Pin[DS18B20_NUM];
  26. }DS18B20_Sort={0,0,0};

  27. GPIO_TypeDef* DS18B20_PORT_GPIO;
  28. uint16_t      DS18B20_PORT_Pin;

  29. DS18B20 Ds18b20;
  30. void DS18B20_GPIO_Config(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x);
  31. void DS18B20_Mode_IPU(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x);
  32. void DS18B20_Mode_Out(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x);
  33. void DS18B20_Write_Byte(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x,u8 dat);//写入一个字节
  34. u8 DS18B20_Read_Byte(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x);//读出一个字节
  35. u8 DS18B20_Read_Bit(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x);//读出一个位
  36. u8 DS18B20_Answer_Check(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x);//检测是否存在DS18B20
  37. void DS18B20_Rst(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x);//复位DS18B20  

  38. u8 DNumGet(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x)
  39. {
  40.         u8 i=0,j=0,Dnum=0;
  41.         while(i<DS18B20_NUM)
  42.         {
  43.                 if(GPIOx==DS18B20_Sort.GPIO[i]){
  44.                 j=0;
  45.                 while(j<DS18B20_NUM){
  46.                 if(GPIO_Pin_x==DS18B20_Sort.Pin[j]){
  47.                 if(i==j) {
  48.                 Dnum=i;
  49.                 break; }}
  50.                 j++;}
  51.                 i++;}
  52.         }
  53.         return Dnum;
  54. }
  55. void DS18B20_ValAvgReset(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x)
  56. {
  57.   u8 Dnum;
  58.         Dnum=DNumGet(GPIOx,GPIO_Pin_x);       
  59.   FisrtDs18b[Dnum].ValAvgReset=0;
  60. }
  61. u8 DS18B20_FirstReadStateGet(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x)
  62. {
  63.   u8 Dnum;
  64.         Dnum=DNumGet(GPIOx,GPIO_Pin_x);
  65.   if(FisrtDs18b[Dnum].firstdatacheckokflag==1) return 1;
  66.         else return 0;       
  67. }

  68. void FirstReadDataCorrectCheck(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x)//检测第一次读取数的正确性
  69. {
  70.   int i;
  71.         u8 Dnum;
  72.         Dnum=DS18B20_Sort.NUM;
  73.        
  74.         FisrtDs18b[Dnum].firstdatacheckokflag=0;
  75.         FisrtDs18b[Dnum].firstenterndatacheckflag=0;
  76.         FisrtDs18b[Dnum].firstdatacheckerrflag=0;
  77.         FisrtDs18b[Dnum].firstdataCnt=0;
  78.         FisrtDs18b[Dnum].firstdata=0;
  79.         FisrtDs18b[Dnum].firstEnterFlag=0;
  80.         FisrtDs18b[Dnum].Temperature1Last=0;
  81.         FisrtDs18b[Dnum].ValAvgReset=1;
  82.         FisrtDs18b[Dnum].Avgcounter=2;
  83.         FisrtDs18b[Dnum].AvgAwscounter=2;
  84.         delay_us(1000*500);
  85.         for(i=0;i<10*C_Time;i++)
  86.         {
  87.                 if(FisrtDs18b[Dnum].firstdatacheckokflag==1) break;
  88.           DS18B20_Update(GPIOx,GPIO_Pin_x);
  89.                 delay_us(1000);
  90.         }
  91. }
  92. /*
  93. * 函数名:DS18B20_GPIO_Config
  94. * 描述  :配置DS18B20用到的I/O口
  95. * 输入  :无
  96. * 输出  :无
  97. */
  98. void DS18B20_GPIO_Config(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x) //非stm32f1_STD库需要修改的函数 1
  99. {
  100.         GPIO_InitTypeDef GPIO_InitStructure;       
  101.        
  102.         DS18B20_Sort.GPIO[DS18B20_Sort.NUM]=GPIOx;
  103.         DS18B20_Sort.Pin[DS18B20_Sort.NUM]=GPIO_Pin_x;
  104.         DS18B20_PORT_GPIO=GPIOx;
  105.         DS18B20_PORT_Pin=GPIO_Pin_x;
  106.         if(GPIOx==GPIOA)      RCC_APB2PeriphClockCmd(        RCC_APB2Periph_GPIOA, ENABLE );         //使能PORTA口时钟  
  107.         else if(GPIOx==GPIOB) RCC_APB2PeriphClockCmd(        RCC_APB2Periph_GPIOB, ENABLE );         //使能PORTB口时钟  
  108.         else if(GPIOx==GPIOC) RCC_APB2PeriphClockCmd(        RCC_APB2Periph_GPIOC, ENABLE );         //使能PORTC口时钟  
  109.         else if(GPIOx==GPIOD) RCC_APB2PeriphClockCmd(        RCC_APB2Periph_GPIOD, ENABLE );         //使能PORTD口时钟  
  110.         else if(GPIOx==GPIOE) RCC_APB2PeriphClockCmd(        RCC_APB2Periph_GPIOE, ENABLE );         //使能PORTE口时钟  
  111.         else if(GPIOx==GPIOF) RCC_APB2PeriphClockCmd(        RCC_APB2Periph_GPIOF, ENABLE );         //使能PORTF口时钟  
  112.         else if(GPIOx==GPIOG) RCC_APB2PeriphClockCmd(        RCC_APB2Periph_GPIOG, ENABLE );         //使能PORTG口时钟  

  113.         GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_x;
  114.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  //复用推挽输出
  115.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  116.         GPIO_Init(GPIOx, &GPIO_InitStructure);

  117.         GPIO_SetBits(GPIOx,GPIO_Pin_x); //引脚输出高
  118.        
  119.         FirstReadDataCorrectCheck(GPIOx,GPIO_Pin_x);//检测第一次读取数的正确性
  120.        
  121.         DS18B20_Sort.NUM++;
  122. }
  123. /*
  124. * 函数名:DS18B20_Mode_IPU
  125. * 描述  :使DS18B20-DATA引脚变为输入模式
  126. * 输入  :无
  127. * 输出  :无
  128. */
  129. void DS18B20_Mode_IPU(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x)//非stm32f1_STD库需要修改的函数 2
  130. {
  131.         GPIO_InitTypeDef GPIO_InitStructure;       
  132.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_x;  
  133.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;  //上拉输入
  134.         GPIO_Init(GPIOx, &GPIO_InitStructure);
  135. }
  136. /*
  137. * 函数名:DS18B20_Mode_Out
  138. * 描述  :使DS18B20-DATA引脚变为输出模式
  139. * 输入  :无
  140. * 输出  :无
  141. */
  142. void DS18B20_Mode_Out(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x)//非stm32f1_STD库需要修改的函数 3
  143. {
  144.         GPIO_InitTypeDef GPIO_InitStructure;       
  145.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_x;
  146.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  //复用推挽输出
  147.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  148.         GPIO_Init(GPIOx, &GPIO_InitStructure);

  149. }



  150. /*
  151. *主机给从机发送复位脉冲
  152. */
  153. void DS18B20_Rst(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x)          
  154. {        
  155.     /* IO设置为推挽输出*/       
  156.           DS18B20_Mode_Out(GPIOx,GPIO_Pin_x);
  157.           /*产生至少480us的低电平复位信号 */
  158.     GPIO_ResetBits(GPIOx,GPIO_Pin_x);  
  159.                 delay_us(480);  
  160.     /* 在产生复位信号后,需将总线拉高 */       
  161.     GPIO_SetBits(GPIOx,GPIO_Pin_x);
  162.           delay_us(15);   
  163. }

  164. /*
  165. * 检测从机给主机返回的应答脉冲
  166. *从机接收到主机的复位信号后,会在15~60us后给主机发一个应答脉冲
  167. * 0:成功
  168. * 1:失败
  169. */
  170. u8 DS18B20_Answer_Check(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x)           
  171. {   
  172.         u8 delay=0;
  173.         /* 主机设置为上拉输入 */
  174.         DS18B20_Mode_IPU(GPIOx,GPIO_Pin_x);
  175.         /* 等待应答脉冲(一个60~240us的低电平信号 )的到来
  176.          * 如果100us内,没有应答脉冲,退出函数,注意:从机接收到主机的复位信号后,会在15~60us后给主机发一个存在脉冲
  177.          */
  178.         while(GPIO_ReadInputDataBit(GPIOx,GPIO_Pin_x)&&delay<100)
  179.         {
  180.                 delay++;
  181.                 delay_us(1);
  182.         }         
  183.         /*经过100us后,如果没有应答脉冲,退出函数*/       
  184.         if(delay>=100)
  185.                 return 1;
  186.         else
  187.                 delay=0;
  188.         /*有应答脉冲,且存在时间不超过240us */
  189.         while (!GPIO_ReadInputDataBit(GPIOx,GPIO_Pin_x)&&delay<240)
  190.         {
  191.                 delay++;
  192.                 delay_us(1);
  193.         }
  194.         if(delay>=240)
  195.                 return 1;            
  196.           return 0;
  197. }

  198. //从DS18B20读取一个位
  199. //返回值:1/0
  200. u8 DS18B20_Read_Bit(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x)                          // read one bit
  201. {
  202.   u8 data;
  203.         DS18B20_Mode_Out(GPIOx,GPIO_Pin_x);
  204.         /* 读时间的起始:必须由主机产生 >1us <15us 的低电平信号 */
  205.   GPIO_ResetBits(GPIOx,GPIO_Pin_x);
  206.         delay_us(2);
  207.         GPIO_SetBits(GPIOx,GPIO_Pin_x);
  208.         delay_us(12);
  209.         /* 设置成输入,释放总线,由外部上拉电阻将总线拉高 */
  210.         DS18B20_Mode_IPU(GPIOx,GPIO_Pin_x);

  211.         if(GPIO_ReadInputDataBit(GPIOx,GPIO_Pin_x))
  212.                 data=1;
  213.   else
  214.                 data=0;         
  215.   delay_us(50);           
  216.   return data;
  217. }
  218. //从DS18B20读取一个字节
  219. //返回值:读到的数据
  220. u8 DS18B20_Read_Byte(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x)    // read one byte
  221. {        
  222.     u8 i,j,dat;
  223.     dat=0;
  224.         for(i=0; i<8; i++)
  225.         {
  226.                 j = DS18B20_Read_Bit(GPIOx,GPIO_Pin_x);               
  227.                 dat = (dat) | (j<<i);
  228.         }                                            
  229.     return dat;
  230. }
  231. /*
  232. * 写一个字节到DS18B20
  233. */
  234. void DS18B20_Write_Byte(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x,u8 dat)     
  235. {            
  236.   u8 j;
  237.   u8 testb;
  238.        
  239.         OSEnterDriver();
  240.        
  241.         DS18B20_Mode_Out(GPIOx,GPIO_Pin_x);//SET PA0 OUTPUT;
  242.   for (j=1;j<=8;j++)
  243.         {
  244.         testb=dat&0x01;
  245.         dat=dat>>1;
  246.         if (testb)
  247.         {
  248.             GPIO_ResetBits(GPIOx,GPIO_Pin_x);// Write 1
  249.             delay_us(10);                           
  250.             GPIO_SetBits(GPIOx,GPIO_Pin_x);
  251.             delay_us(50);            
  252.         }
  253.         else
  254.         {
  255.             GPIO_ResetBits(GPIOx,GPIO_Pin_x);// Write 0
  256.             delay_us(60);            
  257.             GPIO_SetBits(GPIOx,GPIO_Pin_x);   ///释放总线
  258.             delay_us(2);                          
  259.         }
  260.     }
  261. }

  262. //初始化DS18B20的IO口 DQ 同时检测DS的存在
  263. //返回1:不存在
  264. //返回0:存在             
  265. u8 DS18B20_Config(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x)
  266. {
  267.         u8 i=0;
  268.        
  269.         while(i<DS18B20_NUM)
  270.         {
  271.                 Ds18b20.ValMax[i]=-300; //不可修改
  272.                 Ds18b20.ValMin[i]=1000; //不可修改
  273.                 Ds18b20.ValMaxWarn[i]=WarnTemperatureMax;
  274.                 Ds18b20.ValMinWarn[i]=WarnTemperatureMin;
  275.                 i++;
  276.         }
  277.   DS18B20_GPIO_Config(GPIOx, GPIO_Pin_x);
  278.         DS18B20_Rst(GPIOx,GPIO_Pin_x);
  279.         return DS18B20_Answer_Check(GPIOx,GPIO_Pin_x);
  280. }  
  281. //从ds18b20得到温度值
  282. //精度:0.1C
  283. //返回值:温度值 (-550~1250)
  284. float DS18B20_Update(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x)
  285. {   
  286.     u8 TL,TH,Dnum=0;
  287.        
  288.           short Temperature;
  289.           float Temperature1;
  290.           float temp;
  291.           Dnum=DNumGet(GPIOx,GPIO_Pin_x);
  292.     DS18B20_Rst(GPIOx,GPIO_Pin_x);          
  293.           DS18B20_Answer_Check(GPIOx,GPIO_Pin_x);         
  294.     DS18B20_Write_Byte(GPIOx,GPIO_Pin_x,0xcc);// skip rom
  295.     DS18B20_Write_Byte(GPIOx,GPIO_Pin_x,0x44);// convert                 // ds1820 start convert
  296.     DS18B20_Rst(GPIOx,GPIO_Pin_x);
  297.     DS18B20_Answer_Check(GPIOx,GPIO_Pin_x);         
  298.     DS18B20_Write_Byte(GPIOx,GPIO_Pin_x,0xcc);// skip rom
  299.     DS18B20_Write_Byte(GPIOx,GPIO_Pin_x,0xbe);// convert            
  300.     TL=DS18B20_Read_Byte(GPIOx,GPIO_Pin_x); // LSB   
  301.     TH=DS18B20_Read_Byte(GPIOx,GPIO_Pin_x); // MSB  
  302.                 if( TH&0xfc)
  303.                 {
  304.                         Temperature=(TH<<8)|TL;
  305.                         Temperature1=(~ Temperature)+1;
  306.                         Temperature1*=0.0625;
  307.                 }
  308.                 else
  309.                 {
  310.                         Temperature1=((TH<<8)|TL)*0.0625;
  311.                 }
  312.                 Temperature1+=Deviatvalue;//校正
  313. /*-------------------------------判断第一次读取的数的正确性---------------------------------*/               
  314.                 if((Temperature1>TempMin)&&(Temperature1<TempMax))
  315.                 {
  316.                         if(FisrtDs18b[Dnum].firstdatacheckokflag==0)//第一次数据校验(保证用作第一次读取的数的正确性,如果第一次读取出的值是错误值将引起后面的误差)
  317.                         {
  318.                                 if(FisrtDs18b[Dnum].firstdatacheckerrflag==1)//判断是否读取错误(只要边续差值大于预定值则视为错误)
  319.                                 {
  320.                                   FisrtDs18b[Dnum].firstdataCnt=0;           //错误则重新开始计数
  321.                                         FisrtDs18b[Dnum].firstenterndatacheckflag=0;//错误则重新开始判断
  322.                                 }
  323.                           if(FisrtDs18b[Dnum].firstenterndatacheckflag==0)//保存第一个读取的数
  324.                                 {
  325.                                         FisrtDs18b[Dnum].firstenterndatacheckflag=1;//锁存第一个数
  326.                                   FisrtDs18b[Dnum].firstdata=Temperature1;//保存第一个数
  327.                                 }
  328.                                 else //从第二个数开始判断
  329.                                 {
  330.                                   if(Temperature1-FisrtDs18b[Dnum].firstdata<=D_Value)//如果本次值和上次值误差<=D_Value
  331.                                         {
  332.                                                 FisrtDs18b[Dnum].firstdata=Temperature1;//本次数赋值给上次值变量
  333.                                           FisrtDs18b[Dnum].firstdataCnt++;//计数+1
  334.                                         }
  335.                                         else //只要任何一次读数误差大于D_Value则置位失败,则重新判断,重新计数
  336.                                         {
  337.                                           FisrtDs18b[Dnum].firstdatacheckerrflag=1;
  338.                                         }
  339.                                 }
  340.                                 if(FisrtDs18b[Dnum].firstdataCnt>=C_Time) //连续读取的C_Time个数值之间的差值均<=D_Value则认为是正确值
  341.                                 {
  342.                                   FisrtDs18b[Dnum].firstdatacheckokflag=1;//置1表示本次检查的第一次值为正确值,予以通过
  343.                                 }
  344.                         }
  345. /*-----------------------------------------------------------------------------------------------*/                       
  346.                         if(FisrtDs18b[Dnum].firstdatacheckokflag==1)//在保证第一次的读出的数是正确的情况下,开始进行读取数值
  347.                         {
  348.                                 if(FisrtDs18b[Dnum].firstEnterFlag==0)//第一次读取温度检测
  349.                                 {
  350.                                         FisrtDs18b[Dnum].firstEnterFlag=1;
  351.                                         FisrtDs18b[Dnum].Temperature1Last=Temperature1;
  352.                                         Ds18b20.ValAvg[Dnum]=Temperature1;
  353.                                         Ds18b20.ValAvgAws[Dnum]=Temperature1;
  354.                                 }
  355.                                 else
  356.                                 {
  357.                                         if(Temperature1>=FisrtDs18b[Dnum].Temperature1Last) temp=Temperature1-FisrtDs18b[Dnum].Temperature1Last;
  358.                                         else temp=FisrtDs18b[Dnum].Temperature1Last-Temperature1;//求绝对值差值
  359.                                         if(temp>D_Value)//两次读取差值如果大于1,则认为是非正常值,返回上次的值
  360.                                         {
  361.                                                  Temperature1=FisrtDs18b[Dnum].Temperature1Last;
  362.                                         }
  363.                                         else
  364.                                         {
  365.                                                 FisrtDs18b[Dnum].Temperature1Last=Temperature1;//更新历史值
  366.                                         }
  367.                                 }
  368.                                 Ds18b20.Val[Dnum]=Temperature1;
  369.                                 if(FisrtDs18b[Dnum].ValAvgReset==0)
  370.                                 {
  371.                                         FisrtDs18b[Dnum].ValAvgReset=1;
  372.                                         FisrtDs18b[Dnum].Avgcounter=2;
  373.                                         Ds18b20.ValAvg[Dnum]=Ds18b20.Val[Dnum];
  374.                                 }
  375.                                 if(Ds18b20.Val[Dnum]>Ds18b20.ValAvg[Dnum]) Ds18b20.ValAvg[Dnum]+=(Ds18b20.Val[Dnum]-Ds18b20.ValAvg[Dnum])/FisrtDs18b[Dnum].Avgcounter;//计算临时平均值
  376.                                 else Ds18b20.ValAvg[Dnum]-=(Ds18b20.ValAvg[Dnum]-Ds18b20.Val[Dnum])/FisrtDs18b[Dnum].Avgcounter;//计算临时平均值       
  377.                                 if(Ds18b20.Val[Dnum]>Ds18b20.ValAvgAws[Dnum]) Ds18b20.ValAvgAws[Dnum]+=(Ds18b20.Val[Dnum]-Ds18b20.ValAvgAws[Dnum])/FisrtDs18b[Dnum].AvgAwscounter;//计算永久平均值
  378.                                 else Ds18b20.ValAvgAws[Dnum]-=(Ds18b20.ValAvgAws[Dnum]-Ds18b20.Val[Dnum])/FisrtDs18b[Dnum].AvgAwscounter;//计算永久平均值
  379.                                 if((FisrtDs18b[Dnum].Avgcounter+1)!=0)  FisrtDs18b[Dnum].Avgcounter++;//临时平均值计算次数
  380.                                 if((FisrtDs18b[Dnum].AvgAwscounter+1)!=0)  FisrtDs18b[Dnum].AvgAwscounter++;//永久平均值计算次数
  381.                                 if(Ds18b20.Val[Dnum]>Ds18b20.ValMax[Dnum]) Ds18b20.ValMax[Dnum]=Ds18b20.Val[Dnum];
  382.                                 if(Ds18b20.Val[Dnum]<Ds18b20.ValMin[Dnum]) Ds18b20.ValMin[Dnum]=Ds18b20.Val[Dnum];
  383.                         }
  384.                 }
  385.                
  386.                 OSExitDriver();
  387.                
  388.                 return Temperature1;        
  389. }
复制代码

所有资料51hei提供下载:
DS18B2多IO驱动(带滤波)—STM32.zip (5.75 KB, 下载次数: 25)
回复

使用道具 举报

ID:91165 发表于 2020-2-25 09:01 | 显示全部楼层
楼主辛苦了
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表