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   

效果还不错

原文地址:https://www.cnblogs.com/wwjdwy/p/3019832.html