cc2538之ds18b20

来源:互联网 发布:语言翻译软件 编辑:程序博客网 时间:2024/04/29 14:52

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