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<TMilli> 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的手册;IO口的读取真实电平必须先配置该IO口为输入,因为2538的IO口在输出状态下,不管实际电平是否变化,始终读取上一次软件output IO口的值


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
下面是将 DS18B20 温度传感器读取的温度值显示到 LCD1602 液晶屏幕上的 C 代码示例: ``` #include <stdio.h> #include <stdlib.h> #include <wiringPi.h> #include <lcd.h> #include <stdint.h> #include <unistd.h> #define LCD_RS 3 // Register select pin #define LCD_E 0 // Enable Pin #define LCD_D4 6 // Data pin 4 #define LCD_D5 1 // Data pin 5 #define LCD_D6 5 // Data pin 6 #define LCD_D7 4 // Data pin 7 #define TEMP_SENSOR_PIN 2 // DS18B20温度传感器的数据引脚 int main() { int lcd; // 定义LCD句柄 int fd, i, j; uint8_t data[12]; float temp_c, temp_f; if (wiringPiSetup() == -1) // 初始化wiringPi库 exit(1); lcd = lcdInit(2, 16, 4, LCD_RS, LCD_E, LCD_D4, LCD_D5, LCD_D6, LCD_D7, 0, 0, 0, 0); // 初始化LCD屏幕 if (lcd == -1) { printf("lcdInit failed!\n"); exit(1); } while (1) { fd = open("/sys/bus/w1/devices/28-000008d88ff4/w1_slave", O_RDONLY); // 打开DS18B20温度传感器的数据文件 if (fd == -1) { printf("Could not open DS18B20 data file!\n"); exit(1); } read(fd, data, 12); // 读取数据 close(fd); // 关闭文件 temp_c = (float)((data[9] << 8) | data[8]) / 1000.0; // 解析温度值 temp_f = (temp_c * 1.8) + 32.0; // 将温度值转换为华氏度 lcdClear(lcd); // 清空LCD屏幕 // 将温度值显示到LCD屏幕上 lcdPosition(lcd, 0, 0); lcdPrintf(lcd, "Temp: %.1f%cC", temp_c, 223); lcdPosition(lcd, 0, 1); lcdPrintf(lcd, "Temp: %.1f%cF", temp_f, 223); sleep(1); // 延时1秒钟 } return 0; } ``` 上述代码使用了 `wiringPi` 库和 `lcd` 库来控制 LCD1602 液晶屏幕。同时,使用了 Linux 系统下的文件读取操作 `/sys/bus/w1/devices/28-000008d88ff4/w1_slave` 来读取 DS18B20 温度传感器的温度值。读取到温度值后,将其转换为摄氏度和华氏度并显示在 LCD 屏幕上,每隔1秒钟更新一次。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值