cc2538之ds18b20

18b20,很常见的传感器了,软件编写重点主要就是在one-wire总线的时序上,相关的时序可以参考ds18b20不多做赘述;

本次依然采用作者最熟悉的TinyOS平台+CC2538CB实现,由于ds18b20.c驱动文件直接采用c语言编程,contiki和RIOT也可直接使用,这里我就不移植过去测试了;源码在我的百度网盘

硬件连接:DQ使用PA5,(上拉)


首先TinyOS部分编写APP;代码如下:

 /*******************************************************************
 *附加实验3:DS18B20测温实验
 *节点需求数1
 *编译命令make cc2538cb
 ********************************************************************/

#include "printf.h"
#include "ds18b20.h"

module TestDS18B20C{
   uses interface Boot;
   uses interface Timer as Timer;
}
implementation
{
  unsigned long testdata=0;
  task void ds18b20_Task();
  
  void print_ds18b20(){
     unsigned short result;
     double  temp_data;
    
     result = ds18b20_read();
     printf("ds18b20:");
     printf(" %x   ", result);
     if( result < 0x800 ){
        temp_data = result;
     }
     else{
        printf("-");
        temp_data =(~result + 1) & 0x7ff;
     }
     temp_data = temp_data * 0.625 + 0.5;
     result = (unsigned short)(temp_data );
     printf(" %d", result/10);
     printf(".%d", result%10);
     printf("℃\n");
  }
  /***************************************************
  *启动事件
  ****************************************************/
  event void Boot.booted(){
    print_ds18b20();
    call Timer.startPeriodic( 5000 );
  }
/***************************************************
  *任务time1_Task
  ****************************************************/
  task void ds18b20_Task(){  
     print_ds18b20();
  }
  
  /***************************************************
  *Timer1定时时间到事件
  ****************************************************/
  event void Timer.fired()
  {
    /****提交time_Task任务***/
    post ds18b20_Task();
  }

  
}
代码逻辑简单,每5秒读取一次ds18b20的数据;计算后通过串口打印 出来

其中ds18b20_read在ds18b20.c中,代码如下:

#include "hw_memmap.h"
#include "gpio.h"
#include "hw_gpio.h"
#include "ds18b20.h" 

#define ReSet_18b20_DQ() do{GPIOPinTypeGPIOOutput(GPIO_A_BASE, GPIO_PIN_5); \
                     HWREG(GPIO_A_BASE + (GPIO_O_DATA + (GPIO_PIN_5 << 2))) &= (~(GPIO_PIN_5));}while(0)

#define Set_18b20_DQ() do{GPIOPinTypeGPIOOutput(GPIO_A_BASE, GPIO_PIN_5); \
                     HWREG(GPIO_A_BASE + (GPIO_O_DATA + (GPIO_PIN_5 << 2))) |= GPIO_PIN_5;}while(0) 

/*******************************************************************************
读取DS18B20 总线状态
*******************************************************************************/  
unsigned char  GetDQ(void){
   GPIOPinTypeGPIOInput(GPIO_A_BASE, GPIO_PIN_5);
   return  HWREG(GPIO_A_BASE + (GPIO_O_DATA + (GPIO_PIN_5 << 2)));
}
                    
/*******************************************************************************
复位DS18B20
*******************************************************************************/                    
unsigned long ResetDS18B20(void) { 
        unsigned char is_exsist;
        unsigned short delay;

        ReSet_18b20_DQ(); 
       
        delay = 1250;
	while(--delay);  //500us (该时间的时间范围可以从480到960微秒)
        Set_18b20_DQ(); 
        delay = 150;       
        while(--delay);
        is_exsist = 0;
        if(0 == GetDQ())
           is_exsist |= 1; 
      
        delay = 300;
	while(--delay);
	Set_18b20_DQ(); 
        return is_exsist;

} 

/*******************************************************************************
写一个字节到DS18B20
*******************************************************************************/  
void DS18B20WriteByte(unsigned char Dat) { 
    unsigned char i; 
    unsigned short delay;
    for(i = 8; i > 0; i--) { 
        ReSet_18b20_DQ(); 
        delay = 5;
	while(--delay); 
        if(Dat & 0x01) 
          Set_18b20_DQ(); 
        else 
          ReSet_18b20_DQ(); 
        delay = 130;
        while(--delay); 
        Set_18b20_DQ(); 
        delay = 5;
	while(--delay); 
        Dat >>= 1; 
     } 

} 
/*******************************************************************************
从DS18B20读取一个字节
*******************************************************************************/ 

unsigned char DS18B20ReadByte( ) { 
	unsigned char i,Dat = 0; 
        unsigned short delay;
         
        for(i = 8; i > 0; i--) { 
              Dat >>= 1; 
              ReSet_18b20_DQ(); 
              delay = 5;
	      while(--delay); 
              Set_18b20_DQ(); 
              delay = 5;
	      while(--delay); 
              if(GetDQ()) 
                Dat |= 0x80;  
              delay = 130;
	      while(--delay); 
              Set_18b20_DQ(); 

	} 
        return Dat; 
} 
/*******************************************************************************
读取DS18B20温度值,读取为两个字节,温度值为0XXXXX *0.0625°C
*******************************************************************************/  
unsigned short ds18b20_read(void){
       unsigned char  Temperature1L, Temperature1H; 
       unsigned short Temperature; 
       unsigned long delay;
        
	if(0 == ResetDS18B20()){
           return 0x88; //可以 自定义返回 未检测到ds18b20的接入
        }
        DS18B20WriteByte(SkipROM); 
        DS18B20WriteByte(StartConvert); 
        delay = 1800000;
	while(--delay); 
        ResetDS18B20();
        DS18B20WriteByte(SkipROM); 
	DS18B20WriteByte(ReadScratchpad); 
        Temperature1L= DS18B20ReadByte(); 
        Temperature1H= DS18B20ReadByte();
        
        ResetDS18B20();
        
        Temperature = 0;
        Temperature = Temperature1H;
        Temperature <<= 8;
        Temperature |= Temperature1L;
       
	return Temperature; 
}

编译后下载到cc2538cb节点运行效果如下图:

cc2538之ds18b20_第1张图片

需要注意的是可以去看cc2538的手册;IO口的读取真实电平必须先配置该IO口为输入,因为2538的IO口在输出状态下,不管实际电平是否变化,始终读取上一次软件output IO口的值


你可能感兴趣的:(cc2538,TinyOS例程实验)