1 /* DS18B20时钟端口、引脚定义 */ 2 #define DS18B20 GPIOC 3 #define DS18B20_Onboard (GPIO_Pin_15) 4 #define DS18B20_PORT_RCC RCC_APB2Periph_GPIOC 5 #define ds_count 20 6 7 ///IO操作函数 8 #define DS18B20_DQ_OUT PCout(15) 9 #define DS18B20_DQ_IN PCin(15) 10 11 #define dsmax 6 //最多允许温度传感器的数量
配置DS18B20初始化函数,输入配置,输出配置,参考DS18B20数据手册:
1 void DS18B20_Reset(void) 2 { 3 DS18B20_IO_OUT(); //SET PC15 OUTPUT 4 DS18B20_DQ_OUT=0; //拉低DQ 5 delay_us(750); //拉低750us 6 DS18B20_DQ_OUT=1; //DQ=1 7 delay_us(35); //35US 8 } 9 10 u8 DS18B20_Check(void) 11 { 12 u8 retry=0; 13 DS18B20_IO_IN();//SET PC15 INPUT 14 while(DS18B20_DQ_IN&&retry<200) 15 { 16 retry++; 17 delay_us(1); 18 }; 19 if(retry>=200) return 1; 20 else retry = 0; 21 while (!DS18B20_DQ_IN && retry <240) 22 { 23 retry++; 24 delay_us(1); 25 }; 26 if(retry>=240) return 1; 27 return 0; 28 } 29 30 u8 DS18B20_Init(void) 31 { 32 GPIO_InitTypeDef GPIO_InitStructure; 33 RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO,ENABLE ); 34 PWR_BackupAccessCmd( ENABLE );/* 允许修改RTC和后备寄存器*/ 35 RCC_LSEConfig( RCC_LSE_OFF ); /* 关闭外部低速时钟,PC14+PC15可以用作普通IO*/ 36 BKP_TamperPinCmd(DISABLE); /* 关闭入侵检测功能,PC13可以用作普通IO*/ 37 38 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15; 39 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; 40 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 41 GPIO_Init(GPIOC, &GPIO_InitStructure); 42 43 PWR_BackupAccessCmd(DISABLE);/* 禁止修改RTC和后备寄存器*/ 44 //BKP_ITConfig(DISABLE); /* 禁止TAMPER 中断*/ 45 46 DS18B20_Reset(); 47 return DS18B20_Check(); 48 } 49 50 /******************************************************************************* 51 * 函 数 名 : DS18B20_IO_IN 52 * 函数功能 : DS18B20_IO输入输出配置 53 * 输 入 : 无 54 * 输 出 : 无 55 *******************************************************************************/ 56 void DS18B20_IO_IN(void) 57 { 58 GPIO_InitTypeDef GPIO_InitStructure; 59 PWR_BackupAccessCmd( ENABLE );/* 允许修改RTC和后备寄存器*/ 60 RCC_LSEConfig( RCC_LSE_OFF ); /* 关闭外部低速时钟,PC14+PC15可以用作普通IO*/ 61 BKP_TamperPinCmd(DISABLE); /* 关闭入侵检测功能,PC13可以用作普通IO*/ 62 63 GPIO_InitStructure.GPIO_Pin=DS18B20_Onboard; 64 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU; 65 GPIO_Init(DS18B20,&GPIO_InitStructure); 66 67 PWR_BackupAccessCmd(DISABLE);/* 禁止修改RTC和后备寄存器*/ 68 } 69 70 void DS18B20_IO_OUT(void) 71 { 72 GPIO_InitTypeDef GPIO_InitStructure; 73 PWR_BackupAccessCmd( ENABLE );/* 允许修改RTC和后备寄存器*/ 74 RCC_LSEConfig( RCC_LSE_OFF ); /* 关闭外部低速时钟,PC14+PC15可以用作普通IO*/ 75 BKP_TamperPinCmd(DISABLE); /* 关闭入侵检测功能,PC13可以用作普通IO*/ 76 77 GPIO_InitStructure.GPIO_Pin=DS18B20_Onboard; 78 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_2MHz; 79 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; 80 GPIO_Init(DS18B20,&GPIO_InitStructure); 81 82 PWR_BackupAccessCmd(DISABLE);/* 禁止修改RTC和后备寄存器*/ 83 }
对DS18B20,按位、按字节读取和写数据:
1 u8 DS18B20_Read_Bit(void) // read one bit 2 { 3 u8 data; 4 DS18B20_IO_OUT();//SET PC15 OUTPUT 5 DS18B20_DQ_OUT=0; 6 delay_us(2); 7 DS18B20_DQ_OUT=1; 8 DS18B20_IO_IN();//SET PC15 INPUT 9 delay_us(12); 10 if(DS18B20_DQ_IN)data=1; 11 else data=0; 12 delay_us(50); 13 return data; 14 } 15 16 u8 DS18B20_Read_Byte(void) // read one byte 17 { 18 u8 i,j,dat; 19 dat=0; 20 for (i=1; i<=8; i++) 21 { 22 j=DS18B20_Read_Bit(); 23 dat=(j<<7)|(dat>>1); 24 } 25 return dat; 26 } 27 28 u8 DS18B20_Read_2Bit(void) //read 2 bits 29 { 30 u8 i,dat; 31 dat=0; 32 for(i = 0;i < 2;i ++) 33 { 34 dat <<= 1; 35 if(DS18B20_Read_Bit()) 36 { 37 dat = dat|1; 38 } 39 } 40 return dat; 41 } 42 43 void DS18B20_Write_Bit(u8 dat) //write one bit 44 { 45 u8 testb; 46 DS18B20_IO_OUT();//SET PG11 OUTPUT; 47 testb=dat&0x01; 48 if (testb) 49 { 50 DS18B20_DQ_OUT=0;// Write 1 51 delay_us(2); 52 DS18B20_DQ_OUT=1; 53 delay_us(60); 54 } 55 else 56 { 57 DS18B20_DQ_OUT=0;// Write 0 58 delay_us(60); 59 DS18B20_DQ_OUT=1; 60 delay_us(2); 61 } 62 } 63 64 void DS18B20_Write_Byte(u8 dat) //write one byte 65 { 66 u8 j; 67 u8 testb; 68 DS18B20_IO_OUT();//SET PC15 OUTPUT; 69 for (j=1; j<=8; j++) 70 { 71 testb=dat&0x01; 72 dat=dat>>1; 73 if (testb) 74 { 75 DS18B20_DQ_OUT=0;// Write 1 76 delay_us(2); 77 DS18B20_DQ_OUT=1; 78 delay_us(60); 79 } 80 else 81 { 82 DS18B20_DQ_OUT=0;// Write 0 83 delay_us(60); 84 DS18B20_DQ_OUT=1; 85 delay_us(2); 86 } 87 } 88 }
不匹配序号读取温度:
1 u8 DS18B20_GetTemperature() 2 { 3 u16 temp; 4 u8 a,b; 5 u8 value; 6 7 DS18B20_Reset(); 8 DS18B20_Check(); 9 DS18B20_Write_Byte(0xcc);// skip rom 10 DS18B20_Write_Byte(0xbe);// 读存储器命令转换 11 12 a=DS18B20_Read_Byte(); // LSB 13 b=DS18B20_Read_Byte(); // MSB 14 15 temp=b; 16 temp=(temp<<8)+a; 17 18 if((temp&0xf800)==0xf800) 19 { 20 temp=(~temp)+1; 21 value=temp*0.0625 + 128; //如果小于0,则加128,负值范围:128~255 22 } 23 else 24 { 25 value=temp*0.0625; //正值的范围:0~127(ds18b20的测温范围:-55~125摄氏度) 26 } 27 return value; 28 }
读序号并匹配序号,读温度:
u8 dsnum = 0; //温度传感器的数量 u8 ds_ID[dsmax][8] = {0}; //ID u8 dstemp[dsmax] = {0}; //温度 /********************************************/ u8 DS18B20_SearchROM() //搜索18B20 { u8 n,i,j,temp,CTW,num; u8 rom[64]; u8 stack[dsmax]; u8 id=0; n = 0; num = 0; do { DS18B20_Reset(); DS18B20_Check(); DS18B20_Write_Byte(0xf0); for(i=0; i<dsmax; i++) //按字节 { for(j=0; j<8; j++) //按位 { temp = DS18B20_Read_2Bit(); temp &= 0x03; id >>=1; if(temp == 0x01) //这里先读的是0,后读的是1,表示有器件连接,并且它们这一位均是0 { DS18B20_Write_Bit(0); rom[(i*8+j)] = 0; } else if(temp ==0x02) { id |= 0x80; DS18B20_Write_Bit(1); rom[(i*8+j)] = 1; } else if(temp == 0x00) //有冲突位 { CTW = i*8+j+1; if(CTW > stack[n]) //冲突位大于栈顶,写0 { DS18B20_Write_Bit(0); rom[(i*8+j)] = 0; zhan[++n] = CTW; } else if(CTW < stack[n]) { id |= ((rom[(i*8+j)] & 0x01) << 7); DS18B20_Write_Bit(rom[(i*8+j)]); } else if(CTW == stack[n]) { id |= 0x80; DS18B20_Write_Bit(1); rom[(i*8+j)] = 1; n--; } } else { return num; } delay_us(5); } ds_ID[num][i] = id; //ds18B20的id64位 id = 0; } num++; } while((stack[n] != 0) && (num < dsmax)); dsnum = num; return num; } u8 DS18B20_GetDsTemperature(u8 dsID[8]) { u16 temp,n; u8 a,b; u8 value; DS18B20_Reset(); DS18B20_Check(); DS18B20_Write_Byte(0xcc);// skip rom DS18B20_Write_Byte(0x44);// 启动温度转换 DS18B20_Reset(); DS18B20_Check(); DS18B20_Write_Byte(0x55); //发送匹配 for(n=0; n<8; n++) { DS18B20_Write_Byte(dsID[n]); } delay_us(10); DS18B20_Write_Byte(0xbe);// 读存储器命令转换 a=DS18B20_Read_Byte(); // LSB b=DS18B20_Read_Byte(); // MSB temp=b; temp=(temp<<8)+a; if((temp&0xf800)==0xf800) { temp=(~temp)+1; value=temp*0.0625 + 128; } else { value=temp*0.0625; } return value; }
注意点:精度,时延,求平均值时数据溢出