基于標準庫,只要帶有標準庫的gpio的庫即可使用。經測試可用。和其他人的驅動不一樣!帶濾波!
51hei.png (2.71 KB, 下載次數: 56)
下載附件
2019-12-18 15:40 上傳
單片機源程序如下:
- #include "ds18b20.h"
- /*
- 以下配置函數基于stm32f1標準庫,如使用其他庫或非f1的請修改3個函數(有標注)。
- */
- typedef struct
- {
- char firstdatacheckokflag;
- char firstenterndatacheckflag;
- char firstdatacheckerrflag;
- char firstdataCnt;
- float firstdata;
-
- char firstEnterFlag;
- float Temperature1Last;
-
- unsigned int Avgcounter;
- unsigned int AvgAwscounter;
- unsigned char ValAvgReset; //=0 重置ValAvg統計
- }volatile TEMPDS18B;
- TEMPDS18B FisrtDs18b[DS18B20_NUM];
- struct DS18B20_SORT
- {
- uint8_t NUM;
- GPIO_TypeDef* GPIO[DS18B20_NUM];
- uint16_t Pin[DS18B20_NUM];
- }DS18B20_Sort={0,0,0};
- GPIO_TypeDef* DS18B20_PORT_GPIO;
- uint16_t DS18B20_PORT_Pin;
- DS18B20 Ds18b20;
- void DS18B20_GPIO_Config(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x);
- void DS18B20_Mode_IPU(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x);
- void DS18B20_Mode_Out(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x);
- void DS18B20_Write_Byte(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x,u8 dat);//寫入一個字節
- u8 DS18B20_Read_Byte(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x);//讀出一個字節
- u8 DS18B20_Read_Bit(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x);//讀出一個位
- u8 DS18B20_Answer_Check(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x);//檢測是否存在DS18B20
- void DS18B20_Rst(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x);//復位DS18B20
- u8 DNumGet(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x)
- {
- u8 i=0,j=0,Dnum=0;
- while(i<DS18B20_NUM)
- {
- if(GPIOx==DS18B20_Sort.GPIO[i]){
- j=0;
- while(j<DS18B20_NUM){
- if(GPIO_Pin_x==DS18B20_Sort.Pin[j]){
- if(i==j) {
- Dnum=i;
- break; }}
- j++;}
- i++;}
- }
- return Dnum;
- }
- void DS18B20_ValAvgReset(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x)
- {
- u8 Dnum;
- Dnum=DNumGet(GPIOx,GPIO_Pin_x);
- FisrtDs18b[Dnum].ValAvgReset=0;
- }
- u8 DS18B20_FirstReadStateGet(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x)
- {
- u8 Dnum;
- Dnum=DNumGet(GPIOx,GPIO_Pin_x);
- if(FisrtDs18b[Dnum].firstdatacheckokflag==1) return 1;
- else return 0;
- }
- void FirstReadDataCorrectCheck(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x)//檢測第一次讀取數的正確性
- {
- int i;
- u8 Dnum;
- Dnum=DS18B20_Sort.NUM;
-
- FisrtDs18b[Dnum].firstdatacheckokflag=0;
- FisrtDs18b[Dnum].firstenterndatacheckflag=0;
- FisrtDs18b[Dnum].firstdatacheckerrflag=0;
- FisrtDs18b[Dnum].firstdataCnt=0;
- FisrtDs18b[Dnum].firstdata=0;
- FisrtDs18b[Dnum].firstEnterFlag=0;
- FisrtDs18b[Dnum].Temperature1Last=0;
- FisrtDs18b[Dnum].ValAvgReset=1;
- FisrtDs18b[Dnum].Avgcounter=2;
- FisrtDs18b[Dnum].AvgAwscounter=2;
- delay_us(1000*500);
- for(i=0;i<10*C_Time;i++)
- {
- if(FisrtDs18b[Dnum].firstdatacheckokflag==1) break;
- DS18B20_Update(GPIOx,GPIO_Pin_x);
- delay_us(1000);
- }
- }
- /*
- * 函數名:DS18B20_GPIO_Config
- * 描述 :配置DS18B20用到的I/O口
- * 輸入 :無
- * 輸出 :無
- */
- void DS18B20_GPIO_Config(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x) //非stm32f1_STD庫需要修改的函數 1
- {
- GPIO_InitTypeDef GPIO_InitStructure;
-
- DS18B20_Sort.GPIO[DS18B20_Sort.NUM]=GPIOx;
- DS18B20_Sort.Pin[DS18B20_Sort.NUM]=GPIO_Pin_x;
- DS18B20_PORT_GPIO=GPIOx;
- DS18B20_PORT_Pin=GPIO_Pin_x;
- if(GPIOx==GPIOA) RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE ); //使能PORTA口時鐘
- else if(GPIOx==GPIOB) RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE ); //使能PORTB口時鐘
- else if(GPIOx==GPIOC) RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE ); //使能PORTC口時鐘
- else if(GPIOx==GPIOD) RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOD, ENABLE ); //使能PORTD口時鐘
- else if(GPIOx==GPIOE) RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOE, ENABLE ); //使能PORTE口時鐘
- else if(GPIOx==GPIOF) RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOF, ENABLE ); //使能PORTF口時鐘
- else if(GPIOx==GPIOG) RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOG, ENABLE ); //使能PORTG口時鐘
-
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_x;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //復用推挽輸出
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOx, &GPIO_InitStructure);
- GPIO_SetBits(GPIOx,GPIO_Pin_x); //引腳輸出高
-
- FirstReadDataCorrectCheck(GPIOx,GPIO_Pin_x);//檢測第一次讀取數的正確性
-
- DS18B20_Sort.NUM++;
- }
- /*
- * 函數名:DS18B20_Mode_IPU
- * 描述 :使DS18B20-DATA引腳變為輸入模式
- * 輸入 :無
- * 輸出 :無
- */
- void DS18B20_Mode_IPU(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x)//非stm32f1_STD庫需要修改的函數 2
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_x;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉輸入
- GPIO_Init(GPIOx, &GPIO_InitStructure);
- }
- /*
- * 函數名:DS18B20_Mode_Out
- * 描述 :使DS18B20-DATA引腳變為輸出模式
- * 輸入 :無
- * 輸出 :無
- */
- void DS18B20_Mode_Out(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x)//非stm32f1_STD庫需要修改的函數 3
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_x;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //復用推挽輸出
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOx, &GPIO_InitStructure);
- }
- /*
- *主機給從機發送復位脈沖
- */
- void DS18B20_Rst(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x)
- {
- /* IO設置為推挽輸出*/
- DS18B20_Mode_Out(GPIOx,GPIO_Pin_x);
- /*產生至少480us的低電平復位信號 */
- GPIO_ResetBits(GPIOx,GPIO_Pin_x);
- delay_us(480);
- /* 在產生復位信號后,需將總線拉高 */
- GPIO_SetBits(GPIOx,GPIO_Pin_x);
- delay_us(15);
- }
- /*
- * 檢測從機給主機返回的應答脈沖
- *從機接收到主機的復位信號后,會在15~60us后給主機發一個應答脈沖
- * 0:成功
- * 1:失敗
- */
- u8 DS18B20_Answer_Check(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x)
- {
- u8 delay=0;
- /* 主機設置為上拉輸入 */
- DS18B20_Mode_IPU(GPIOx,GPIO_Pin_x);
- /* 等待應答脈沖(一個60~240us的低電平信號 )的到來
- * 如果100us內,沒有應答脈沖,退出函數,注意:從機接收到主機的復位信號后,會在15~60us后給主機發一個存在脈沖
- */
- while(GPIO_ReadInputDataBit(GPIOx,GPIO_Pin_x)&&delay<100)
- {
- delay++;
- delay_us(1);
- }
- /*經過100us后,如果沒有應答脈沖,退出函數*/
- if(delay>=100)
- return 1;
- else
- delay=0;
- /*有應答脈沖,且存在時間不超過240us */
- while (!GPIO_ReadInputDataBit(GPIOx,GPIO_Pin_x)&&delay<240)
- {
- delay++;
- delay_us(1);
- }
- if(delay>=240)
- return 1;
- return 0;
- }
- //從DS18B20讀取一個位
- //返回值:1/0
- u8 DS18B20_Read_Bit(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x) // read one bit
- {
- u8 data;
- DS18B20_Mode_Out(GPIOx,GPIO_Pin_x);
- /* 讀時間的起始:必須由主機產生 >1us <15us 的低電平信號 */
- GPIO_ResetBits(GPIOx,GPIO_Pin_x);
- delay_us(2);
- GPIO_SetBits(GPIOx,GPIO_Pin_x);
- delay_us(12);
- /* 設置成輸入,釋放總線,由外部上拉電阻將總線拉高 */
- DS18B20_Mode_IPU(GPIOx,GPIO_Pin_x);
- if(GPIO_ReadInputDataBit(GPIOx,GPIO_Pin_x))
- data=1;
- else
- data=0;
- delay_us(50);
- return data;
- }
- //從DS18B20讀取一個字節
- //返回值:讀到的數據
- u8 DS18B20_Read_Byte(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x) // read one byte
- {
- u8 i,j,dat;
- dat=0;
- for(i=0; i<8; i++)
- {
- j = DS18B20_Read_Bit(GPIOx,GPIO_Pin_x);
- dat = (dat) | (j<<i);
- }
- return dat;
- }
- /*
- * 寫一個字節到DS18B20
- */
- void DS18B20_Write_Byte(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x,u8 dat)
- {
- u8 j;
- u8 testb;
-
- OSEnterDriver();
-
- DS18B20_Mode_Out(GPIOx,GPIO_Pin_x);//SET PA0 OUTPUT;
- for (j=1;j<=8;j++)
- {
- testb=dat&0x01;
- dat=dat>>1;
- if (testb)
- {
- GPIO_ResetBits(GPIOx,GPIO_Pin_x);// Write 1
- delay_us(10);
- GPIO_SetBits(GPIOx,GPIO_Pin_x);
- delay_us(50);
- }
- else
- {
- GPIO_ResetBits(GPIOx,GPIO_Pin_x);// Write 0
- delay_us(60);
- GPIO_SetBits(GPIOx,GPIO_Pin_x); ///釋放總線
- delay_us(2);
- }
- }
- }
- //初始化DS18B20的IO口 DQ 同時檢測DS的存在
- //返回1:不存在
- //返回0:存在
- u8 DS18B20_Config(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x)
- {
- u8 i=0;
-
- while(i<DS18B20_NUM)
- {
- Ds18b20.ValMax[i]=-300; //不可修改
- Ds18b20.ValMin[i]=1000; //不可修改
- Ds18b20.ValMaxWarn[i]=WarnTemperatureMax;
- Ds18b20.ValMinWarn[i]=WarnTemperatureMin;
- i++;
- }
- DS18B20_GPIO_Config(GPIOx, GPIO_Pin_x);
- DS18B20_Rst(GPIOx,GPIO_Pin_x);
- return DS18B20_Answer_Check(GPIOx,GPIO_Pin_x);
- }
- //從ds18b20得到溫度值
- //精度:0.1C
- //返回值:溫度值 (-550~1250)
- float DS18B20_Update(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x)
- {
- u8 TL,TH,Dnum=0;
-
- short Temperature;
- float Temperature1;
- float temp;
- Dnum=DNumGet(GPIOx,GPIO_Pin_x);
- DS18B20_Rst(GPIOx,GPIO_Pin_x);
- DS18B20_Answer_Check(GPIOx,GPIO_Pin_x);
- DS18B20_Write_Byte(GPIOx,GPIO_Pin_x,0xcc);// skip rom
- DS18B20_Write_Byte(GPIOx,GPIO_Pin_x,0x44);// convert // ds1820 start convert
- DS18B20_Rst(GPIOx,GPIO_Pin_x);
- DS18B20_Answer_Check(GPIOx,GPIO_Pin_x);
- DS18B20_Write_Byte(GPIOx,GPIO_Pin_x,0xcc);// skip rom
- DS18B20_Write_Byte(GPIOx,GPIO_Pin_x,0xbe);// convert
- TL=DS18B20_Read_Byte(GPIOx,GPIO_Pin_x); // LSB
- TH=DS18B20_Read_Byte(GPIOx,GPIO_Pin_x); // MSB
- if( TH&0xfc)
- {
- Temperature=(TH<<8)|TL;
- Temperature1=(~ Temperature)+1;
- Temperature1*=0.0625;
- }
- else
- {
- Temperature1=((TH<<8)|TL)*0.0625;
- }
- Temperature1+=Deviatvalue;//校正
- /*-------------------------------判斷第一次讀取的數的正確性---------------------------------*/
- if((Temperature1>TempMin)&&(Temperature1<TempMax))
- {
- if(FisrtDs18b[Dnum].firstdatacheckokflag==0)//第一次數據校驗(保證用作第一次讀取的數的正確性,如果第一次讀取出的值是錯誤值將引起后面的誤差)
- {
- if(FisrtDs18b[Dnum].firstdatacheckerrflag==1)//判斷是否讀取錯誤(只要邊續差值大于預定值則視為錯誤)
- {
- FisrtDs18b[Dnum].firstdataCnt=0; //錯誤則重新開始計數
- FisrtDs18b[Dnum].firstenterndatacheckflag=0;//錯誤則重新開始判斷
- }
- if(FisrtDs18b[Dnum].firstenterndatacheckflag==0)//保存第一個讀取的數
- {
- FisrtDs18b[Dnum].firstenterndatacheckflag=1;//鎖存第一個數
- FisrtDs18b[Dnum].firstdata=Temperature1;//保存第一個數
- }
- else //從第二個數開始判斷
- {
- if(Temperature1-FisrtDs18b[Dnum].firstdata<=D_Value)//如果本次值和上次值誤差<=D_Value
- {
- FisrtDs18b[Dnum].firstdata=Temperature1;//本次數賦值給上次值變量
- FisrtDs18b[Dnum].firstdataCnt++;//計數+1
- }
- else //只要任何一次讀數誤差大于D_Value則置位失敗,則重新判斷,重新計數
- {
- FisrtDs18b[Dnum].firstdatacheckerrflag=1;
- }
- }
- if(FisrtDs18b[Dnum].firstdataCnt>=C_Time) //連續讀取的C_Time個數值之間的差值均<=D_Value則認為是正確值
- {
- FisrtDs18b[Dnum].firstdatacheckokflag=1;//置1表示本次檢查的第一次值為正確值,予以通過
- }
- }
- /*-----------------------------------------------------------------------------------------------*/
- if(FisrtDs18b[Dnum].firstdatacheckokflag==1)//在保證第一次的讀出的數是正確的情況下,開始進行讀取數值
- {
- if(FisrtDs18b[Dnum].firstEnterFlag==0)//第一次讀取溫度檢測
- {
- FisrtDs18b[Dnum].firstEnterFlag=1;
- FisrtDs18b[Dnum].Temperature1Last=Temperature1;
- Ds18b20.ValAvg[Dnum]=Temperature1;
- Ds18b20.ValAvgAws[Dnum]=Temperature1;
- }
- else
- {
- if(Temperature1>=FisrtDs18b[Dnum].Temperature1Last) temp=Temperature1-FisrtDs18b[Dnum].Temperature1Last;
- else temp=FisrtDs18b[Dnum].Temperature1Last-Temperature1;//求絕對值差值
- if(temp>D_Value)//兩次讀取差值如果大于1,則認為是非正常值,返回上次的值
- {
- Temperature1=FisrtDs18b[Dnum].Temperature1Last;
- }
- else
- {
- FisrtDs18b[Dnum].Temperature1Last=Temperature1;//更新歷史值
- }
- }
- Ds18b20.Val[Dnum]=Temperature1;
- if(FisrtDs18b[Dnum].ValAvgReset==0)
- {
- FisrtDs18b[Dnum].ValAvgReset=1;
- FisrtDs18b[Dnum].Avgcounter=2;
- Ds18b20.ValAvg[Dnum]=Ds18b20.Val[Dnum];
- }
- if(Ds18b20.Val[Dnum]>Ds18b20.ValAvg[Dnum]) Ds18b20.ValAvg[Dnum]+=(Ds18b20.Val[Dnum]-Ds18b20.ValAvg[Dnum])/FisrtDs18b[Dnum].Avgcounter;//計算臨時平均值
- else Ds18b20.ValAvg[Dnum]-=(Ds18b20.ValAvg[Dnum]-Ds18b20.Val[Dnum])/FisrtDs18b[Dnum].Avgcounter;//計算臨時平均值
- if(Ds18b20.Val[Dnum]>Ds18b20.ValAvgAws[Dnum]) Ds18b20.ValAvgAws[Dnum]+=(Ds18b20.Val[Dnum]-Ds18b20.ValAvgAws[Dnum])/FisrtDs18b[Dnum].AvgAwscounter;//計算永久平均值
- else Ds18b20.ValAvgAws[Dnum]-=(Ds18b20.ValAvgAws[Dnum]-Ds18b20.Val[Dnum])/FisrtDs18b[Dnum].AvgAwscounter;//計算永久平均值
- if((FisrtDs18b[Dnum].Avgcounter+1)!=0) FisrtDs18b[Dnum].Avgcounter++;//臨時平均值計算次數
- if((FisrtDs18b[Dnum].AvgAwscounter+1)!=0) FisrtDs18b[Dnum].AvgAwscounter++;//永久平均值計算次數
- if(Ds18b20.Val[Dnum]>Ds18b20.ValMax[Dnum]) Ds18b20.ValMax[Dnum]=Ds18b20.Val[Dnum];
- if(Ds18b20.Val[Dnum]<Ds18b20.ValMin[Dnum]) Ds18b20.ValMin[Dnum]=Ds18b20.Val[Dnum];
- }
- }
-
- OSExitDriver();
-
- return Temperature1;
- }
復制代碼
所有資料51hei提供下載:
DS18B2多IO驅動(帶濾波)—STM32.zip
(5.75 KB, 下載次數: 25)
2019-12-18 02:28 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|