|
基于標(biāo)準(zhǔn)庫(kù),只要帶有標(biāo)準(zhǔn)庫(kù)的gpio的庫(kù)即可使用。經(jīng)測(cè)試可用。和其他人的驅(qū)動(dòng)不一樣!帶濾波!
51hei.png (2.71 KB, 下載次數(shù): 56)
下載附件
2019-12-18 15:40 上傳
單片機(jī)源程序如下:
- #include "ds18b20.h"
- /*
- 以下配置函數(shù)基于stm32f1標(biāo)準(zhǔn)庫(kù),如使用其他庫(kù)或非f1的請(qǐng)修改3個(gè)函數(shù)(有標(biāo)注)。
- */
- 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統(tǒng)計(jì)
- }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);//寫(xiě)入一個(gè)字節(jié)
- u8 DS18B20_Read_Byte(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x);//讀出一個(gè)字節(jié)
- u8 DS18B20_Read_Bit(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x);//讀出一個(gè)位
- u8 DS18B20_Answer_Check(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x);//檢測(cè)是否存在DS18B20
- void DS18B20_Rst(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x);//復(fù)位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)//檢測(cè)第一次讀取數(shù)的正確性
- {
- 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);
- }
- }
- /*
- * 函數(shù)名:DS18B20_GPIO_Config
- * 描述 :配置DS18B20用到的I/O口
- * 輸入 :無(wú)
- * 輸出 :無(wú)
- */
- void DS18B20_GPIO_Config(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x) //非stm32f1_STD庫(kù)需要修改的函數(shù) 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口時(shí)鐘
- else if(GPIOx==GPIOB) RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE ); //使能PORTB口時(shí)鐘
- else if(GPIOx==GPIOC) RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE ); //使能PORTC口時(shí)鐘
- else if(GPIOx==GPIOD) RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOD, ENABLE ); //使能PORTD口時(shí)鐘
- else if(GPIOx==GPIOE) RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOE, ENABLE ); //使能PORTE口時(shí)鐘
- else if(GPIOx==GPIOF) RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOF, ENABLE ); //使能PORTF口時(shí)鐘
- else if(GPIOx==GPIOG) RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOG, ENABLE ); //使能PORTG口時(shí)鐘
-
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_x;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //復(fù)用推挽輸出
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOx, &GPIO_InitStructure);
- GPIO_SetBits(GPIOx,GPIO_Pin_x); //引腳輸出高
-
- FirstReadDataCorrectCheck(GPIOx,GPIO_Pin_x);//檢測(cè)第一次讀取數(shù)的正確性
-
- DS18B20_Sort.NUM++;
- }
- /*
- * 函數(shù)名:DS18B20_Mode_IPU
- * 描述 :使DS18B20-DATA引腳變?yōu)檩斎肽J?br />
- * 輸入 :無(wú)
- * 輸出 :無(wú)
- */
- void DS18B20_Mode_IPU(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x)//非stm32f1_STD庫(kù)需要修改的函數(shù) 2
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_x;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉輸入
- GPIO_Init(GPIOx, &GPIO_InitStructure);
- }
- /*
- * 函數(shù)名:DS18B20_Mode_Out
- * 描述 :使DS18B20-DATA引腳變?yōu)檩敵瞿J?br />
- * 輸入 :無(wú)
- * 輸出 :無(wú)
- */
- void DS18B20_Mode_Out(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x)//非stm32f1_STD庫(kù)需要修改的函數(shù) 3
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_x;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //復(fù)用推挽輸出
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOx, &GPIO_InitStructure);
- }
- /*
- *主機(jī)給從機(jī)發(fā)送復(fù)位脈沖
- */
- void DS18B20_Rst(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x)
- {
- /* IO設(shè)置為推挽輸出*/
- DS18B20_Mode_Out(GPIOx,GPIO_Pin_x);
- /*產(chǎn)生至少480us的低電平復(fù)位信號(hào) */
- GPIO_ResetBits(GPIOx,GPIO_Pin_x);
- delay_us(480);
- /* 在產(chǎn)生復(fù)位信號(hào)后,需將總線拉高 */
- GPIO_SetBits(GPIOx,GPIO_Pin_x);
- delay_us(15);
- }
- /*
- * 檢測(cè)從機(jī)給主機(jī)返回的應(yīng)答脈沖
- *從機(jī)接收到主機(jī)的復(fù)位信號(hào)后,會(huì)在15~60us后給主機(jī)發(fā)一個(gè)應(yīng)答脈沖
- * 0:成功
- * 1:失敗
- */
- u8 DS18B20_Answer_Check(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x)
- {
- u8 delay=0;
- /* 主機(jī)設(shè)置為上拉輸入 */
- DS18B20_Mode_IPU(GPIOx,GPIO_Pin_x);
- /* 等待應(yīng)答脈沖(一個(gè)60~240us的低電平信號(hào) )的到來(lái)
- * 如果100us內(nèi),沒(méi)有應(yīng)答脈沖,退出函數(shù),注意:從機(jī)接收到主機(jī)的復(fù)位信號(hào)后,會(huì)在15~60us后給主機(jī)發(fā)一個(gè)存在脈沖
- */
- while(GPIO_ReadInputDataBit(GPIOx,GPIO_Pin_x)&&delay<100)
- {
- delay++;
- delay_us(1);
- }
- /*經(jīng)過(guò)100us后,如果沒(méi)有應(yīng)答脈沖,退出函數(shù)*/
- if(delay>=100)
- return 1;
- else
- delay=0;
- /*有應(yīng)答脈沖,且存在時(shí)間不超過(guò)240us */
- while (!GPIO_ReadInputDataBit(GPIOx,GPIO_Pin_x)&&delay<240)
- {
- delay++;
- delay_us(1);
- }
- if(delay>=240)
- return 1;
- return 0;
- }
- //從DS18B20讀取一個(gè)位
- //返回值: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);
- /* 讀時(shí)間的起始:必須由主機(jī)產(chǎn)生 >1us <15us 的低電平信號(hào) */
- GPIO_ResetBits(GPIOx,GPIO_Pin_x);
- delay_us(2);
- GPIO_SetBits(GPIOx,GPIO_Pin_x);
- delay_us(12);
- /* 設(shè)置成輸入,釋放總線,由外部上拉電阻將總線拉高 */
- 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讀取一個(gè)字節(jié)
- //返回值:讀到的數(shù)據(jù)
- 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;
- }
- /*
- * 寫(xiě)一個(gè)字節(jié)到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 同時(shí)檢測(cè)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;//校正
- /*-------------------------------判斷第一次讀取的數(shù)的正確性---------------------------------*/
- if((Temperature1>TempMin)&&(Temperature1<TempMax))
- {
- if(FisrtDs18b[Dnum].firstdatacheckokflag==0)//第一次數(shù)據(jù)校驗(yàn)(保證用作第一次讀取的數(shù)的正確性,如果第一次讀取出的值是錯(cuò)誤值將引起后面的誤差)
- {
- if(FisrtDs18b[Dnum].firstdatacheckerrflag==1)//判斷是否讀取錯(cuò)誤(只要邊續(xù)差值大于預(yù)定值則視為錯(cuò)誤)
- {
- FisrtDs18b[Dnum].firstdataCnt=0; //錯(cuò)誤則重新開(kāi)始計(jì)數(shù)
- FisrtDs18b[Dnum].firstenterndatacheckflag=0;//錯(cuò)誤則重新開(kāi)始判斷
- }
- if(FisrtDs18b[Dnum].firstenterndatacheckflag==0)//保存第一個(gè)讀取的數(shù)
- {
- FisrtDs18b[Dnum].firstenterndatacheckflag=1;//鎖存第一個(gè)數(shù)
- FisrtDs18b[Dnum].firstdata=Temperature1;//保存第一個(gè)數(shù)
- }
- else //從第二個(gè)數(shù)開(kāi)始判斷
- {
- if(Temperature1-FisrtDs18b[Dnum].firstdata<=D_Value)//如果本次值和上次值誤差<=D_Value
- {
- FisrtDs18b[Dnum].firstdata=Temperature1;//本次數(shù)賦值給上次值變量
- FisrtDs18b[Dnum].firstdataCnt++;//計(jì)數(shù)+1
- }
- else //只要任何一次讀數(shù)誤差大于D_Value則置位失敗,則重新判斷,重新計(jì)數(shù)
- {
- FisrtDs18b[Dnum].firstdatacheckerrflag=1;
- }
- }
- if(FisrtDs18b[Dnum].firstdataCnt>=C_Time) //連續(xù)讀取的C_Time個(gè)數(shù)值之間的差值均<=D_Value則認(rèn)為是正確值
- {
- FisrtDs18b[Dnum].firstdatacheckokflag=1;//置1表示本次檢查的第一次值為正確值,予以通過(guò)
- }
- }
- /*-----------------------------------------------------------------------------------------------*/
- if(FisrtDs18b[Dnum].firstdatacheckokflag==1)//在保證第一次的讀出的數(shù)是正確的情況下,開(kāi)始進(jìn)行讀取數(shù)值
- {
- if(FisrtDs18b[Dnum].firstEnterFlag==0)//第一次讀取溫度檢測(cè)
- {
- 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;//求絕對(duì)值差值
- if(temp>D_Value)//兩次讀取差值如果大于1,則認(rèn)為是非正常值,返回上次的值
- {
- 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;//計(jì)算臨時(shí)平均值
- else Ds18b20.ValAvg[Dnum]-=(Ds18b20.ValAvg[Dnum]-Ds18b20.Val[Dnum])/FisrtDs18b[Dnum].Avgcounter;//計(jì)算臨時(shí)平均值
- if(Ds18b20.Val[Dnum]>Ds18b20.ValAvgAws[Dnum]) Ds18b20.ValAvgAws[Dnum]+=(Ds18b20.Val[Dnum]-Ds18b20.ValAvgAws[Dnum])/FisrtDs18b[Dnum].AvgAwscounter;//計(jì)算永久平均值
- else Ds18b20.ValAvgAws[Dnum]-=(Ds18b20.ValAvgAws[Dnum]-Ds18b20.Val[Dnum])/FisrtDs18b[Dnum].AvgAwscounter;//計(jì)算永久平均值
- if((FisrtDs18b[Dnum].Avgcounter+1)!=0) FisrtDs18b[Dnum].Avgcounter++;//臨時(shí)平均值計(jì)算次數(shù)
- if((FisrtDs18b[Dnum].AvgAwscounter+1)!=0) FisrtDs18b[Dnum].AvgAwscounter++;//永久平均值計(jì)算次數(shù)
- 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;
- }
復(fù)制代碼
所有資料51hei提供下載:
DS18B2多IO驅(qū)動(dòng)(帶濾波)—STM32.zip
(5.75 KB, 下載次數(shù): 25)
2019-12-18 02:28 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
|
|