標(biāo)題:
STM32F1的DS18B20驅(qū)動源碼.c/.h文件
[打印本頁]
作者:
Angle145
時(shí)間:
2019-12-18 02:29
標(biāo)題:
STM32F1的DS18B20驅(qū)動源碼.c/.h文件
基于標(biāo)準(zhǔn)庫,只要帶有標(biāo)準(zhǔn)庫的gpio的庫即可使用。經(jīng)測試可用。和其他人的驅(qū)動不一樣!帶濾波!
51hei.png
(2.71 KB, 下載次數(shù): 56)
下載附件
2019-12-18 15:40 上傳
單片機(jī)源程序如下:
#include "ds18b20.h"
/*
以下配置函數(shù)基于stm32f1標(biāo)準(zhǔn)庫,如使用其他庫或非f1的請修改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);//寫入一個(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);//檢測是否存在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)//檢測第一次讀取數(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口
* 輸入 :無
* 輸出 :無
*/
void DS18B20_GPIO_Config(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x) //非stm32f1_STD庫需要修改的函數(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);//檢測第一次讀取數(shù)的正確性
DS18B20_Sort.NUM++;
}
/*
* 函數(shù)名:DS18B20_Mode_IPU
* 描述 :使DS18B20-DATA引腳變?yōu)檩斎肽J?br />
* 輸入 :無
* 輸出 :無
*/
void DS18B20_Mode_IPU(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x)//非stm32f1_STD庫需要修改的函數(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 />
* 輸入 :無
* 輸出 :無
*/
void DS18B20_Mode_Out(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin_x)//非stm32f1_STD庫需要修改的函數(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ù)位信號 */
GPIO_ResetBits(GPIOx,GPIO_Pin_x);
delay_us(480);
/* 在產(chǎn)生復(fù)位信號后,需將總線拉高 */
GPIO_SetBits(GPIOx,GPIO_Pin_x);
delay_us(15);
}
/*
* 檢測從機(jī)給主機(jī)返回的應(yīng)答脈沖
*從機(jī)接收到主機(jī)的復(fù)位信號后,會在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的低電平信號 )的到來
* 如果100us內(nèi),沒有應(yīng)答脈沖,退出函數(shù),注意:從機(jī)接收到主機(jī)的復(fù)位信號后,會在15~60us后給主機(jī)發(fā)一個(gè)存在脈沖
*/
while(GPIO_ReadInputDataBit(GPIOx,GPIO_Pin_x)&&delay<100)
{
delay++;
delay_us(1);
}
/*經(jīng)過100us后,如果沒有應(yīng)答脈沖,退出函數(shù)*/
if(delay>=100)
return 1;
else
delay=0;
/*有應(yīng)答脈沖,且存在時(shí)間不超過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 的低電平信號 */
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;
}
/*
* 寫一個(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í)檢測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ò)誤則重新開始計(jì)數(shù)
FisrtDs18b[Dnum].firstenterndatacheckflag=0;//錯(cuò)誤則重新開始判斷
}
if(FisrtDs18b[Dnum].firstenterndatacheckflag==0)//保存第一個(gè)讀取的數(shù)
{
FisrtDs18b[Dnum].firstenterndatacheckflag=1;//鎖存第一個(gè)數(shù)
FisrtDs18b[Dnum].firstdata=Temperature1;//保存第一個(gè)數(shù)
}
else //從第二個(gè)數(shù)開始判斷
{
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表示本次檢查的第一次值為正確值,予以通過
}
}
/*-----------------------------------------------------------------------------------------------*/
if(FisrtDs18b[Dnum].firstdatacheckokflag==1)//在保證第一次的讀出的數(shù)是正確的情況下,開始進(jìn)行讀取數(shù)值
{
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,則認(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ū)動(帶濾波)—STM32.zip
(5.75 KB, 下載次數(shù): 25)
2019-12-18 02:28 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
作者:
HWL0541
時(shí)間:
2020-2-25 09:01
樓主辛苦了
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1