您好,歡迎來電子發(fā)燒友網(wǎng)! ,新用戶?[免費注冊]

您的位置:電子發(fā)燒友網(wǎng)>電子元器件>傳感器>

淺析CC2530下ZigBee協(xié)議棧中添加BH1750數(shù)字光照傳感器

2018年10月07日 11:51 網(wǎng)絡(luò)整理 作者:工程師譚軍 用戶評論(0
  數(shù)字傳感器
?
  數(shù)字傳感器是指將傳統(tǒng)的模擬式傳感器經(jīng)過加裝或改造A/D轉(zhuǎn)換模塊,使之輸出信號為數(shù)字量(或數(shù)字編碼)的傳感器,主要包括:放大器、A/D轉(zhuǎn)換器、微處理器CPU)、存儲器、通訊接口、溫度測試電路等,在微處理器和傳感器變得越來越便宜的今天,全自動或半自動(通過人工指令進行高層次操作,自動處理低層次操作)系統(tǒng)可以包含更多智能性功能,能從其環(huán)境中獲得并處理更多不同的參數(shù)。
?
  特點
?
  1、先進的A/D轉(zhuǎn)換技術(shù)和智能濾波算法,在滿量程的情況下仍可保證輸出碼的穩(wěn)定。
?
  2、可行的數(shù)據(jù)存儲技術(shù),保證模塊參數(shù)不會丟失。
?
  3、良好的電磁兼容性能。
?
  4、傳感器的性能采用數(shù)字化誤差補償技術(shù)和高度集成化電子元件,用軟件實現(xiàn)傳感器的線性、零點、溫漂、蠕變等性能參數(shù)的綜合補償,消除了人為因素對補償?shù)挠绊?,大大提高了傳感器綜合精度和可靠性。
?
  5、傳感器的輸出一致性誤差可以達到0.02%以內(nèi)甚至更高,傳感器的特性參數(shù)可完全相同,因而具有良好的互換性。
?
  6、采用A/D轉(zhuǎn)換電路、數(shù)字化信號傳輸和數(shù)字濾波技術(shù),傳感器的抗干擾能力增加,信號傳輸距離遠,提高了傳感器的穩(wěn)定性。
?
  7、數(shù)字傳感器能自動采集數(shù)據(jù)并可預(yù)處理、存儲和記憶,具有唯一標記,便于故障診斷。
?
  8、傳感器采用標準的數(shù)字通訊接口,可直接連入計算機,也可與標準工業(yè)控制總線連接,方便靈活。
?
  9, 數(shù)字傳感器是將AD,EPROM,DIE(指還未封裝的傳感器芯片,屬于裸片,大小介于cell和chip之間),封裝在一塊用PCB,金屬塊或陶瓷板上的集成。通過各種溫度,壓力點的校準,計算出DIE的線性,再利用AD去補償?shù)姆椒庸ざ傻摹?/div>
?
  應(yīng)用及前景
?
  在微處理器和傳感器變得越來越便宜的今天,全自動或半自動(通過人工指令進行高層次操作,自動處理低層次操作)系統(tǒng)可以包含更多智能性功能,能從其環(huán)境中獲得并處理更多不同的參數(shù)。尤其是MEMS(微型機電系統(tǒng))技術(shù),它使數(shù)字傳感器的體積非常微小并且能耗與成本也很低。以納米碳管或其它納米材料制成的納米傳感器同樣具有巨大的潛力 [1] 。
?
  即使在萌芽階段,人們?nèi)匀徽J為在不久的將來數(shù)字傳感器對電子市場具有重要的推動作用。制作數(shù)字傳感器的接口以及支持用于數(shù)字傳感器網(wǎng)絡(luò)的形式多樣的通訊協(xié)議都是對技術(shù)工藝的巨大挑戰(zhàn)。傳感器的非均質(zhì)特性和其操作條件的多樣化也對技術(shù)工藝提出了巨大的挑戰(zhàn)。
?
  現(xiàn)在系統(tǒng)設(shè)計所包含的傳感器和處理器越來越多。隨著傳感器和處理器價格的不斷降低,取代機械控制結(jié)構(gòu)的閾值也在不斷變化。在系統(tǒng)中選擇正確的傳感器組合和處理算法可以顯著地降低原材料及能耗的費用并提高系統(tǒng)的總體性能。目前,不斷提高操作的簡化程度和延長能源的使用壽命變得越來越重要,尤其是如今越來越多的傳感器網(wǎng)絡(luò)動輒就配置1000或更多的傳感器節(jié)點。

  項目里需要獲得光照強度,之前用的是光敏電阻,但是光敏電阻實在不精確,換用BH1750數(shù)字光照傳感器。網(wǎng)上購買后,送的資料都是單片機的,移植到ZigBee協(xié)議棧里面,時序有些問題,在網(wǎng)上找的一些資料,很雜亂。主要出現(xiàn)兩個問題:一、讀取不到數(shù)據(jù);二、讀取到的數(shù)據(jù)是亂的。

  仔細研究之后,發(fā)現(xiàn),第一個問題讀不到數(shù)據(jù),八成是延時函數(shù)有差別;第二個問題,一直以為是時序的問題,糾結(jié)了很久還是沒弄好,后來突然想把數(shù)據(jù)處理的地方單獨弄出來測試,結(jié)果正是這里,采集到數(shù)據(jù),轉(zhuǎn)為字符串的時候,數(shù)據(jù)類型跟所需要的數(shù)據(jù)類型有差,最大范圍不同,可能每個人宏或者自定義的數(shù)據(jù)類型都不太一樣,所以移植過來的時候,雖然名字一樣,但是實際上定義的時候不一樣,導(dǎo)致使用的時候不容易發(fā)現(xiàn)問題。

  下面貼上代碼。(之前在網(wǎng)上看到別人做的bh1750,想問他買代碼,結(jié)果告訴我一個代碼要我80,瞬間無語,還好自己弄出來了 ,共享給大家,也給自己提個醒,最是覺得沒有問題的地方,往往就是問題所在,需時刻抱有懷疑的態(tài)度)

  BH1750.h:

  #ifndef __BH1750_H

  #define __BH1750_H

  #include 《ioCC2530.h》

  #define st(x) do { x } while (__LINE__ == -1)

  #define HAL_IO_SET(port, pin, val) HAL_IO_SET_PREP(port, pin, val)

  #define HAL_IO_SET_PREP(port, pin, val) st( P##port##_##pin## = val; )

  #define HAL_IO_GET(port, pin) HAL_IO_GET_PREP( port,pin)

  #define HAL_IO_GET_PREP(port, pin) ( P##port##_##pin)

  #define LIGHT_SCK_0() HAL_IO_SET(1,3,0)

  #define LIGHT_SCK_1() HAL_IO_SET(1,3,1)

  #define LIGHT_DTA_0() HAL_IO_SET(1,1,0)

  #define LIGHT_DTA_1() HAL_IO_SET(1,1,1)

  #define LIGHT_DTA() HAL_IO_GET(1,1)

  #define LIGHT_SCK() HAL_IO_GET(1,3)

  #define SDA_W() (P1DIR |=(1 《《 1) )

  #define SDA_R() (P1DIR &=~(1 《《 1) )

  #define LIGHT_INIT() \

  do{ \

  P1SEL &= ~0x08; \

  P1DIR |=0x08; \

  P1_3 = 1; \

  \

  P1SEL &= ~0x02; \

  P1DIR |= 0x02; \

  P1_1 = 1; \

  }while(0)

  extern unsigned short get_light(void);

  #endif // __BH1750_H

  BH1750.c:

  #include “BH1750.h”

  #include “OnBoard.h”

  void halMcuWaitUs(uint16 usec)

  {

  while(usec--)

  {

  asm(“nop”);

  asm(“nop”);

  asm(“nop”);

  asm(“nop”);

  asm(“nop”);

  asm(“nop”);

  asm(“nop”);

  asm(“nop”);

  asm(“nop”);

  asm(“nop”);

  }

  }

  //以ms延時

  void halMcuWaitMs(uint16 msec)

  {

  while(msec--)

  halMcuWaitUs(1000);

  }

  void delay_us()

  {

  halMcuWaitUs(1);

  // MicroWait(1);

  }

  void delay_5us()

  {

  halMcuWaitUs(5);

  //MicroWait(5);

  }

  void delay_10us()

  {

  halMcuWaitUs(10);

  //MicroWait(10);

  }

  void delay_nms(int n)

  {

  halMcuWaitMs(n);

  }

  /****************************/

  static void start_i2c(void)

  {

  SDA_W() ;

  LIGHT_DTA_1();//

  LIGHT_SCK_1() ;//

  delay_us() ;

  LIGHT_DTA_0() ;

  delay_us() ;

  LIGHT_SCK_0() ;

  delay_us() ;

  //delay() ;

  }

  static void stop_i2c(void)

  {

  SDA_W() ;

  LIGHT_DTA_0() ;

  delay_us();

  LIGHT_SCK_1() ;

  delay_us();

  LIGHT_DTA_1() ;

  delay_us();

  LIGHT_SCK_0() ;

  delay_us();

  }

  static char i2c_send(unsigned char val)

  {

  int i;

  char error=0;

  SDA_W();

  for(i=0x80;i》0;i/=2)

  {

  if(val&i)

  LIGHT_DTA_1();

  else

  LIGHT_DTA_0();

  delay_us();

  LIGHT_SCK_1() ;

  delay_us();

  LIGHT_SCK_0() ;

  delay_us();

  }

  LIGHT_DTA_1();

  SDA_R();

  delay_us();

  //delay_us();

  LIGHT_SCK_1() ;

  delay_us();

  if(LIGHT_DTA())

  error=1;

  delay_us();

  LIGHT_SCK_0() ;

  return error;

  }

  static char i2c_read(char ack)

  {

  int i;

  char val=0;

  LIGHT_DTA_1();

  //SDA_R();

  for(i=0x80;i》0;i/=2)

  {

  LIGHT_SCK_1() ;

  delay_us();

  SDA_R();

  //SDA_W();

  //LIGHT_DTA_0();

  //LIGHT_DTA_0() ;

  //delay_us();

  if(LIGHT_DTA())

  val=(val|i);

  delay_us();

  //SDA_R();

  LIGHT_SCK_0() ;

  delay_us();

  }

  SDA_W();

  if(ack)

  LIGHT_DTA_0();

  else

  LIGHT_DTA_1();

  delay_us();

  LIGHT_SCK_1() ;

  delay_us();

  LIGHT_SCK_0() ;

  LIGHT_DTA_1();

  return val;

  }

  unsigned short get_light(void)

  {

  unsigned char ack1=1;

  unsigned char ack2=1;

  unsigned char ack3=1;

  unsigned char ack4=1;

  unsigned char ack5=1;

  unsigned char ack6=1;

  unsigned char ack7=1;

  unsigned char t0;

  unsigned char t1;

  unsigned short t;

  P1DIR |= (1 《《 1);

  delay_nms(200);

  start_i2c();

  ack1=i2c_send(0x46);

  if(ack1)

  return 255;

  ack2=i2c_send(0x01);

  if(ack2)

  return 254;

  stop_i2c(); //init

  start_i2c();

  ack3=i2c_send(0x46);

  if(ack3)

  return 253;

  ack4=i2c_send(0x01);

  if(ack4)

  return 252;

  stop_i2c();//power

  start_i2c();

  ack5=i2c_send(0x46);

  if(ack5)

  return 251;

  ack6=i2c_send(0x10);

  if(ack6)

  return 250;

  stop_i2c();

  delay_nms(1500);

  start_i2c();

  ack7=i2c_send(0x47);

  if(ack7)

  return 249;

  t0 = i2c_read(1);

  t1 = i2c_read(0);

  stop_i2c();

  t = ((short)t0)《《8;

  t |= t1;

  return t;

  }

  在主函數(shù)中加入以下函數(shù)(注意,此處就是最容易忽視的地方,uint應(yīng)該是unsigned int,不能是范圍太小的類型):

  char wan,qian,bai,shi,ge;

  void conversion(unsigned int temp_data)

  {

  wan=(uint)temp_data/10000 ;

  temp_data=temp_data%10000;

  qian=(uint)temp_data/1000 ;

  temp_data=temp_data%1000;

  bai=(uint)temp_data/100;

  temp_data=temp_data%100;

  shi=(uint)temp_data/10;

  temp_data=temp_data%10;

  ge=(uint)temp_data;

  }

  調(diào)用光照獲取函數(shù),講數(shù)據(jù)轉(zhuǎn)為字符串:

  uint32 w;

  w = get_light()/1.2;

  conversion(w);

  char buf[5];

  buf[0] = wan + 48;

  buf[1] = qian + 48;

  buf[2] = bai + 48;

  buf[3] = shi + 48;

  buf[4] = ge + 48;


非常好我支持^.^

(0) 0%

不好我反對

(0) 0%

( 發(fā)表人:金巧 )

      發(fā)表評論

      用戶評論
      評價:好評中評差評

      發(fā)表評論,獲取積分! 請遵守相關(guān)規(guī)定!

      ?