DS18B20实验:神舟IV
DS18B20是由DALLAS半导体公司推出的一种的“一线总线”接口的温度传感器
移植了正点原子的驱动,单总线时序,在神舟IV进行验证,只改动了读取函数,之前返回short类型,我改成了float,正点原子在小数显示时用了/10,我没用液晶直接串口输出,printf %f 原子地址:http://openedv.com/posts/list/13366.htm
神舟板子上使用PE1作为DS18B20的DQ
另:DS18B20可以总线挂很多传感器,ROM指令也有四五个,可以查询,操作特定的某个器件,我这里只用了一颗DS18B20,所以用了最简单的初始化,读取温度值流程。
.h
1 //PE1作为DS18B20的DQ pin 2 #define DS18B20_OUT_High GPIO_SetBits(GPIOE, GPIO_Pin_1) 3 #define DS18B20_OUT_Low GPIO_ResetBits(GPIOE, GPIO_Pin_1) 4 #define DS18B20_DQ_IN GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_1)
DS18B20_IO
1 //PE1作为DS18B20的DQ pin 2 void DS18B20_IO_OUT(void) 3 { 4 GPIO_InitTypeDef GPIO_InitStructure; 5 //推挽输出 6 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; 7 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 8 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 9 GPIO_Init(GPIOE, &GPIO_InitStructure); 10 } 11 12 void DS18B20_IO_IN(void) 13 { 14 GPIO_InitTypeDef GPIO_InitStructure; 15 //上拉输入 16 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; 17 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; 18 GPIO_Init(GPIOE, &GPIO_InitStructure); 19 }
DS18B20_Rst
1 //复位DS18B20 2 void DS18B20_Rst(void) 3 { 4 DS18B20_IO_OUT(); //SET PA0 OUTPUT 5 DS18B20_OUT_Low; //拉低DQ 6 delay_us(750); //拉低750us 7 DS18B20_OUT_High; //DQ=1 8 delay_us(15); //15US 9 }
DS18B20_Check
1 //等待DS18B20的回应 2 //返回1:未检测到DS18B20的存在 3 //返回0:存在 4 u8 DS18B20_Check(void) 5 { 6 u8 retry=0; 7 DS18B20_IO_IN();//SET PA0 INPUT 8 while (DS18B20_DQ_IN&&retry<200) 9 { 10 retry++; 11 delay_us(1); 12 }; 13 if(retry>=200)return 1; 14 else retry=0; 15 while (!DS18B20_DQ_IN&&retry<240) 16 { 17 retry++; 18 delay_us(1); 19 }; 20 if(retry>=240)return 1; 21 return 0; 22 }
DS18B20_Init
1 //初始化DS18B20的IO口 DQ 同时检测DS的存在 2 //返回1:不存在 3 //返回0:存在 4 u8 DS18B20_Init(void) 5 { 6 GPIO_InitTypeDef GPIO_InitStructure; 7 8 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE); //使能PORTG口时钟 9 10 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; //PORTG.11 推挽输出 11 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 12 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 13 GPIO_Init(GPIOG, &GPIO_InitStructure); 14 15 GPIO_SetBits(GPIOE,GPIO_Pin_1); //输出1 16 17 DS18B20_Rst(); 18 19 return DS18B20_Check(); 20 }
DS18B20_Read_Bit
1 //从DS18B20读取一个位 2 //返回值:1/0 3 u8 DS18B20_Read_Bit(void) // read one bit 4 { 5 u8 data; 6 DS18B20_IO_OUT();//SET PA0 OUTPUT 7 DS18B20_OUT_Low; 8 delay_us(2); 9 DS18B20_OUT_High; 10 DS18B20_IO_IN();//SET PA0 INPUT 11 delay_us(12); 12 if(DS18B20_DQ_IN)data=1; 13 else data=0; 14 delay_us(50); 15 return data; 16 }
DS18B20_Read_Byte
1 //从DS18B20读取一个字节 2 //返回值:读到的数据 3 u8 DS18B20_Read_Byte(void) // read one byte 4 { 5 u8 i,j,dat; 6 dat=0; 7 for (i=1;i<=8;i++) 8 { 9 j=DS18B20_Read_Bit(); 10 dat=(j<<7)|(dat>>1); 11 } 12 return dat; 13 }
DS18B20_Write_Byte
1 //写一个字节到DS18B20 2 //dat:要写入的字节 3 void DS18B20_Write_Byte(u8 dat) 4 { 5 u8 j; 6 u8 testb; 7 DS18B20_IO_OUT();//SET PA0 OUTPUT; 8 for (j=1;j<=8;j++) 9 { 10 testb=dat&0x01; 11 dat=dat>>1; 12 if (testb) 13 { 14 DS18B20_OUT_Low;// Write 1 15 delay_us(2); 16 DS18B20_OUT_High; 17 delay_us(60); 18 } 19 else 20 { 21 DS18B20_OUT_Low;// Write 0 22 delay_us(60); 23 DS18B20_OUT_High; 24 delay_us(2); 25 } 26 } 27 }
DS18B20_Start
1 //开始温度转换 2 void DS18B20_Start(void)// ds1820 start convert 3 { 4 DS18B20_Rst(); 5 DS18B20_Check(); 6 DS18B20_Write_Byte(0xcc);// skip rom 7 DS18B20_Write_Byte(0x44);// convert 8 }
DS18B20_Get_Temp
1 //从ds18b20得到温度值 2 //精度:0.1C 3 //返回值:温度值 (-550~1250) 4 float DS18B20_Get_Temp(void) 5 { 6 float result; 7 u8 temp; 8 u8 TL,TH; 9 short tem; 10 DS18B20_Start (); // ds1820 start convert 11 DS18B20_Rst(); 12 DS18B20_Check(); 13 DS18B20_Write_Byte(0xcc);// skip rom 14 DS18B20_Write_Byte(0xbe);// convert 15 TL=DS18B20_Read_Byte(); // LSB 16 TH=DS18B20_Read_Byte(); // MSB 17 18 if(TH>7) 19 { 20 TH=~TH; 21 TL=~TL; 22 temp=0;//温度为负 23 }else temp=1;//温度为正 24 tem=TH; //获得高八位 25 tem<<=8; 26 tem+=TL;//获得底八位 27 // tem=(float)tem*0.0625;//转换 28 // if(temp)return tem; //返回温度值 29 // else return -tem; 30 31 result=tem*0.0625;//转换 32 if(temp)return result; //返回温度值 33 else return -result; 34 35 }
我们只需用两个函数DS18B20_Get_Temp和DS18B20_Init
main中调用DS18B20_Init()
之后我在按键2中断中读取温度输出
key2
1 extern u8 DS18B20Init_Flag; 2 void EXTI15_10_IRQHandler(void) 3 { 4 /* key2 */ 5 //以下代码实现按键2按下后在串口打印出当前时间 6 if(EXTI_GetITStatus(EXTI_Line10) != RESET) 7 { 8 Led_Turn_off_all(); 9 Led_Turn_on_2(); 10 printf("\n\r Key 2 interrupt \n\r"); 11 printf("\n\r Now is %d年 %d月 %d日 %d点 %d分 %d秒 ,星期%d\n\r",calendar.w_year,calendar.w_month,calendar.w_date,calendar.hour,calendar.min,calendar.sec,calendar.week); 12 13 if(DS18B20Init_Flag) printf("\r\n 当前温度值:%3.2f° \n\r",DS18B20_Get_Temp()); 14 else printf("\r\n 温度传感器DS18B20初始化失败 \n\r"); 15 /* Clear the EXTI Line 10 */ 16 EXTI_ClearITPendingBit(EXTI_Line10); 17 } 18
效果还不错