1. 程式人生 > >CC2530無線RF,串列埠透傳

CC2530無線RF,串列埠透傳

1.前言

本文將分析一個利用CC2530實現無線串列埠,文中將會列舉部分程式碼並對CC2530的具體操作進行分析。本文的具體的內容包括以下幾個部分:

  • CC2530是符合802.15.4標準的無線收發晶片,但是本文並沒有遵守802.15.4協議規則,在傳送過程中忽略了網路ID、源地址和目標地址等引數,在接收的過程中禁止了幀過濾。通過傳送和接收過程的處理使得CC2530無線部分的使用盡可能的簡單清晰,通過最少的程式碼說明問題。
  • 無線晶片的除錯具有一定的難度,一般存在傳送裝置和接收裝置。為了通過最簡單的程式碼說明無線晶片的使用,本文中僅編寫一種裝置程式碼同時實現傳送和接收功能。裝置的功能也相對簡單,CC2530從串列埠接收資料並把資料通過RF部分“無損”傳送,於此同時CC2530把從RF部分接收的資料通過串列埠“無損”傳送,通過這樣的方式實現無線串列埠。
  •  串列埠資料屬於“流”型資料包,RF部分屬於“幀”型資料包。在串列埠資料處理與分析中,一般採用特定的串列埠頭和長度的方式解析資料,但是本文采用通過串列埠時間間隔的方式接收資料,這種方法等同於modbus-RTU串列埠資料處理方法。通過這種檢測位元組資料時間間隔的方法使得CC2530的串列埠部分可以接收無特殊格式要求的資料,真正實現無線串列埠功能。

1.1實驗準備

為了實現無線串列埠功能,需要準備兩套CC2530模組和一個模擬器。如果條件允許可以增加一個模擬器,模擬器可以是CC Debugger也可以是SmartRF04EB,同時也可以準備一套CC2531 USBDongle做為嗅探器,抓取RF傳送資料做除錯分析。

 

1.2 實驗結果

本文主要實現了無線串列埠功能,通過串列埠除錯助手傳送位元組資料。例如通過串列埠向裝置A傳送Hello CC2530,裝置B可收到Hello CC2530,並把該字串通過串列埠除錯助手列印至螢幕。裝置B傳送Hello RF,裝置A同樣可以收到資料並列印至螢幕。

 

圖1.2.1(a-b) 裝置A和裝置B串列埠除錯介面

      圖中中括號包含的數字為RSSI結果,RSSI表示接收訊號強度,例如圖中的-28。RSSI結果的單位為dBm,dBm為絕對單位且參考的標準為1mW。

2.程式碼

RF部分的暫存器較多,需要耐心閱讀資料手冊和相關工具才可以完成設定。雖然RF部分的暫存器較多,但是還是藉助smartRF工具、資料手冊和示例程式碼,依然可以總結出使用CC2530無線部分的一般方法。

初始化部分包括接收資料包幀過濾控制,發射功率控制和通道選擇;藉助smartRF工具生成若干推薦值;開啟接收終端並進入接收狀態。

2.1 主函式

 

void main(void)
{
  P1SEL &= ~0x13; //功能:通用I/O,預設為通用I/O  P1.0 P1.1 P1.4設定為通用IO
  P1DIR |= 0x13; //方向:輸出   P1.0 P1.1 P1.4設定為輸出
  
//  P1DIR |= ( 1<< 4) | (1<<1);

  TX =0;
  RX =1;
  EA = 0;                                     // 暫時關閉全域性中斷
  SLEEPCMD &= ~0x04;                       
  while( !(SLEEPSTA & 0x40) );
  CLKCONCMD &= ~0x47;     // 設定系統時鐘為32MHz
  SLEEPCMD |= 0x04; 
      
  WDCTL = 0x00;     //將超時時間設定為1s,在IDLE模式寫CLR暫存器不會產生影響,因此直接賦值只會改變INT和MODE。
  WDCTL |= 0x08;    //將看門狗定時器設定為看門狗模式
  
  uart0_init();                                // 38400
  timer1_init();                              
  timer3_init();                               // 1s
  rf_init();                                   // RF
  
  EA = 1;                                      
  LED1 = 1;  
  uart0_sendbuf("20181025",8);    
  delay(1000);
  uart0_sendbuf(serial_rxbuf,4);

  while(1) 
  {
    WDCTL = 0xa0;     //在看門狗模式寫INT暫存器和MODE模式不會產生影響,因此直接賦值只會改變CLR
    WDCTL = 0x50;

    rx();
    if(Time_1s > 900)//超過十五分鐘未接收到資料,重新初始化串列埠及RF
    {
      Time_1s = 0;
      //uart0_init();                                //38400
      rf_init();   
    }
//   tx();
//   uart0_sendbuf(serial_rxbuf,4);
    delay(10);
  }
}

分析:

初始化IO口,設定為通用IO、輸出模式,分別為LED燈、PA、LNA。

初始化看門狗,做產品並非做實驗,軟體開門狗必須使用,以防宕機。

初始化串列埠,定時器1,定時器3,RF。定時器1用於串列埠接收,定時器3用於計時。

whilexu迴圈中實時監測是否接收到串列埠資料,收到則立即RF傳送。以及判斷shif是否連續15分鐘內都沒接收到RF資料,若無則重新初始化RF。(此機制是因為長時間射頻收發,會出現各種干擾導致接收不到RF資料,但可正常發射,程式正常執行。15分鐘為實際專案需求,根據實際情況選擇。

2.2 RF傳送及接收

void rf_send( char *pbuf , int len)
{
  int i=0;
  RFST = 0xE3;                      // RF接收使能 ISRXON 
  // 等待發送狀態不活躍 並且 沒有接收到SFD
  while( FSMSTAT1 & (( 1<<1 ) | ( 1<<5 ))); 
  
  RFIRQM0 &= ~(1<<6);               // 禁止接收資料包中斿  
  IEN2 &= ~(1<<0);                  // 清除RF全域性中斷

  RFST = 0xEE;                      // 清除傳送緩衝區 ISFLUSHTX
  RFIRQF1 = ~(1<<1);                // 清除傳送完成標忿
  // 填充緩衝匿填充過程需要增勢位元組,CRC校驗自動填充
  RFD = len + 2;        
  for (int i = 0; i < len; i++) 
  {
    RFD = *pbuf++;
  }

  RFST = 0xE9;                      // 傳送資料包 ISTXON
  while (!(RFIRQF1 & (1<<1))) // 等待發送完房  RFIRQF1 = ~(1<<1);                // 清除傳送完成標誌位
  {
   i++;
   if( i > 50 )//增加退出機制,受干擾會死在此迴圈中
   {
      i=0;
      break;
   }  
   WDCTL = 0xa0;     //在看門狗模式寫INT暫存器和MODE模式不會產生影響,因此直接賦值只會改變CLR
   WDCTL = 0x50;
   delay(100);
  }
       
  
  RFIRQM0 |= (1<<6);                // RX接收中斷
  IEN2 |= (1<<0); 
}

分析:

除主函式中while的死迴圈,其他任何地方的while死迴圈都要特別注意,比如此處實際除錯中發現會程式卡死在等待發送完成,因此增加了退出機制。然而退出機制的時間判斷亦不可隨意設定,過短會導致每次傳輸資料長度收限制。本人因對程式時間概念不重視,導致此bug困惑許久。實測此延時時間至少可傳送100個數據。

void rf_receive_isr()
{
  int rf_rx_len = 0;
  int rssi = 0;
  char crc_ok = 0;

  rf_rx_len = RFD - 2;                        //長度去除兩位元組附加結果
  rf_rx_len &= 0x7F;
  for (int i = 0; i < rf_rx_len; i++)
  {
    rf_rx_buf[i] = RFD;                      //連續讀取接收緩衝區內容
  }
  
  rssi = RFD - 73;                             //讀取RSSI結果
  crc_ok = RFD;                              //讀取CRC校驗結果 BIT7
 
  RFST = 0xED;                                 //清除接收緩衝區
  if( crc_ok & 0x80 )
  {
    LED1 ^= 1; 
    Time_1s = 0;
    uart0_sendbuf( rf_rx_buf , rf_rx_len);    
    comtx(rssi );
  }
  else
  {
    uart0_sendbuf("\r\nCRC Error\r\n",12);
  }
}

分析: 

RF接收函式,接收到的資料自帶兩位硬體CRC校驗,即crc_ok。校驗通過認為是有效資料,將計時清零,LED燈反轉,串列埠傳送出接收到的資料,併發送出rssi。

 

3.備註

PA:功率放大器                     發射前置高電平,發射結束立即置低電平。

LNA: 低噪聲放大器                發射前置低電平,發射結束立即置高電平。

(不可操作失誤,否則導致資料接收異常)