一次小模塊的使用過程-LC12S無線模塊介紹

前言:

最近幫人作了個小設備,使用了無線模塊、觸摸芯片,主要功能就是把觸摸按鍵的信號無線傳到控制繼電器輸出,MCU是STM8系列的芯片,其中使用過程當中調試無線模塊LC21S以爲挺好用的,就寫了這篇文章。微信

做者:良知猶存框架

轉載受權以及圍觀:歡迎添加微信公衆號:羽林君函數


模塊介紹:

LC12S 採用最新 2.4G SOC 技術,特色是免開發,視距 120 米,收發一體無需切換,串口透明傳
輸,提供通訊協議,可迅速調試成功。用戶只要瞭解串口通訊,無需複雜的無線通信知識,就能完成無
線通訊產品的開發。沒有數據包大小限制,延時短,半雙工通信,抗干擾能力強。測試

● 2.4GHz ISM 頻段,使用無須申請3d

● 最大輸出功率 12dBm指針

● 接收靈敏度-95dBm調試

● 發射工做電流 40mA@12dBmcode

● 接收工做電流 24mAorm

● 睡眠電流 3.5uAblog

● 標準 TTL 電平 UART 串口

● 工做頻率可設置,多個模塊頻分複用,互不干擾

● 通信協議轉換及射頻收發切換自動完成,用戶無須干預,簡單易用

● 通信速率 0.6kbps -38.4kbps,用戶可經過 AT 指令配置

引腳介紹:

引腳 引腳名稱 引腳功能 描述
1 VCC 電源 電源(接 2.2~3.6V)典型 3.3V
2 RXT 模塊數據輸出(TTL 電平) 串口通訊數據接收
3 TXD 模塊數據輸入(TTL 電平) 串口通訊數據發送
4 SET 設置位 配置參數使能(低電平使能參數配置,高電平進入透傳模式,其中懸空爲高電平)
5 CS 休眠 引腳接低電平時工做,高電平進入休眠模式,其中懸空爲高電平
6 GND 電源 接地

基本配置:

設置模式:

一旦進入設置狀態,SET 引腳配置必須是低電平,CS 引腳必須接低電平,且串口設置必須是數據位
8,波特率 9600,校驗位 N,中止位 1,空中速率 1Mbps。由於初始化默認設置就是如此,若是後續你設置了本身的波特率,這個時候你須要把串口設置按照你修改後的配置來設置。

透傳模式:

上電後,當 CS引腳接低電,進入工做模式,SET 腳是設置參數標誌位,這個時候咱們能夠進行懸空或者拉高處理,讓模塊進入透傳數據模式。

設置模式數據的協議格式:

在官方的手冊裏面有關於協議內容的說明,其中有一些數據是保留位,默認發0x00就能夠。

如圖所示,咱們能夠看到數據長度是18個byte,其中包括設備ID(Self ID)、組網ID(Net ID )、發射功率(RF Power)、通信波特率設置(Baud 1Byte)、無線通信通道設置(RF CHN)、設置時的通信數據長度(Lenght 1Byte)、累加校驗位(CheckSum);其中設置時的通信數據長度是固定的18byte因此此處默認爲0x12。

其餘部分的設置參數,在手冊中各有體現,其中組網ID須要按照本身定義的ID區間進行設置,由於這個惟一性會影響到你的模塊組網狀況。

其他的設置我設置參數我就不進行截圖表示了,你們能夠看一下相應的手冊。

測試設置發送數據:

0xaa+0x5a+模塊 ID+組網 ID(ID 必須相同)+0x00+RF 發射功率+0x00+串口速率
+0x00+RF 信道選擇+0x00+0x00+0x12(字節長度)+0x00+和校驗字節
注意:和校驗字節=全部參數累加的字節

發送:
AA 5A 22 33 11 22 00 01 00 04 00 64 00 00 00 12 00 07

--->

參考後面的數據表格,以上配置參數設置無線模塊爲:
RF 發射功率:10dbm
串口速率:9600bps
RF 信道:100
模塊 ID:0x2233
組網 ID:0x1122
和校驗字節:07

接收: 設置完成後模塊會返回相應數據
AA 5B 47 00 11 22 00 01 00 04 00 64 00 00 00 12 00 FA

<---

串口調試助手的信息:

實際設備鏈接狀況:

設置模式接線示意圖:

透傳模式接線示意圖:

代碼實現:

由於模式使用比較簡單,初始化好設備串口外設,再把CS引腳和SET配置一下,就能夠開始使用了,若是你只是簡單測試,那你可能只須要使用默認設置,只是進行數據的透傳,那你能夠直接忽略這部分設置的代碼部分,直接看nrf_send_normal_data()函數。

設置模式下的代碼


定義一個設置協議的結構體:

typedef struct __attribute__((__packed__)){
    u16 head;                 //
    u16 self_id;                 //
    u16 net_id;                 //
    u8 nc1;               //
    u8 rf_power;          //
    u8 nc2;               //
    u8 rf_baud;          //
    u8 nc3;               //
    u8 rf_chn;          //
    u16 nc4;               //
    u8 nc5;               //
    u8 length;               //
    u8 nc6;               //
}SetSend;

拉低SET引腳,進入設置模式:

u8 SetNrf(void)//
{
       GPIO_ResetBits(SET_PORT, SET_PIN);
       GPIO_ResetBits(CS_PORT, CS_PIN);

      u8 *p1 = malloc(18);
      memset(p1,0x00,18);

      SetSend *p = (SetSend*)p1;

      p->head= 0xaa5a;
      p->self_id = 0x2233;
      p->net_id = 0x1122;
      p->rf_power = 0x00;
      p->rf_baud = 0x04;
      p->rf_chn = 0x64;
      p->length = 0x12;      
      p1[sizeof(SetSend)] = CheckSum((u8*)p, sizeof(SetSend));
      USART_Transmit_String( sizeof(SetSend)+1,p1);

#if DEBUG_DPRINT
      u8 *str = malloc(20);
      hex_str((u8*)p, sizeof(SetSend)+1, str);
      USART_Transmit_String(20,str);
//      printf("--->:%s\r\n", str);
      free(str);
#endif

      free(p1);
      return 1;
      
}

數據透傳的函數,這個時候SET引腳拉高,這個函數部分是我本身寫的一個簡單的3byte的sta狀態發送。
你們能夠按照本身的實際使用狀況進行修改。

void nrf_send_normal_data(u16 sta)
{
      GPIO_SetBits(SET_PORT, SET_PIN);
      u8 *p1 = malloc(3);
      memset(p1,0x00,3);
      memset(p1,0xAA,1);      
      memcpy(p1+1,&sta,2);
      USART_Transmit_String(3,p1);
      free(p1);

}

芯片初始化以後不能當即使用,須要等待幾十ms才能正常工做,因此須要稍微等待一下。

串口接收解析部分,這部分代碼就仁者見仁智者見智了,你們能夠用不少種方法實現,我只是貼了一下我寫的代碼部分,僅供參考。
其中NRF_RestTime()函數是在定時器中計時,用來區分不一樣的數據幀。

u8  USART_RX_BUF[USART_MAX_RECV_LEN];
u16 USART_RX_STA=0;

u8 NRF_RecvdData(void)
{
	u8 ret = 0;
	if((USART_RX_STA&(1<<15)) != 0)
		ret = 1;
	return ret;
}
u16 NRF_RcvLen(void)
{
	return (USART_RX_STA & 0x7FFF);
}
u8* NRF_RcvBuff(void)
{
	return USART_RX_BUF;
}

void NRF_ClsRecvd(void)
{
	USART_RX_STA = 0;
}


typedef struct  __attribute__((__packed__))
{
  u32 stat    :1;
  u32 timOut  :1;
  u32 cunt    :15;
  u32 des     :15;
}TboxTimTypeDef;
TboxTimTypeDef gNRFTimeManage;
#define TON   (1)
#define TOFF  (0)

void TimerManageInit(TboxTimTypeDef *t,u8 stat,u16 destim)
{
  t->des  = destim;
  t->stat = stat;
  t->cunt = 0;
  t->timOut = 0;
}
void NRF_RestTime(void)
{
      if(gNRFTimeManage.stat == TON)
      {
              (gNRFTimeManage.cunt < gNRFTimeManage.des)?(gNRFTimeManage.cunt++):\
                      (TimerManageInit(&gNRFTimeManage,TOFF,0),USART_RX_STA |=1<<15);
      }	
}

void NRF_Irq(void)
{
  	u8 res;	      
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
	{	 
		res =USART_ReceiveData8(USART1);
                #if 0
		USART_SendData8(USART1,res);
		#endif

      
                if((USART_RX_STA & ~(1<<15))<USART_MAX_RECV_LEN)
                {
                      TimerManageInit(&gNRFTimeManage,TON,5);
                      USART_RX_BUF[USART_RX_STA++]=res;		 
                }else 
                {
                        USART_RX_STA|=1<<15;				
                } 
          }
	USART_ClearITPendingBit(USART1,USART_IT_RXNE);
}

void Parse_NRF(void)
{
  
    if(NRF_RcvLen()>2)
    {
      u16 len = NRF_RcvLen(); 
      u8 *p = NRF_RcvBuff();
      u8 pos = 0;
      u16 *sta = (u16*)(p+1);
      while(pos < len){
        if(*p == 0xAA)
        {
          
          relay_ctrl(*sta);
          p += 3;
          pos +=3;
        }
        else{
          p++;
          pos++;
        }
      }
      USART_RX_STA = 0;
    }
  
}

設備展現

主機端:

從機端:

結語

這就是我分享的LC12S模塊的使用,若是你們有更好的想法和需求,也歡迎你們分享交流哈。

—END—

推薦閱讀

【1】C++的智能指針你瞭解嗎?

【2】嵌入式底層開發的軟件框架簡述

【3】CPU中的程序是怎麼運行起來的 必讀

【4】C++的匿名函數(lambda表達式)

【5】階段性文章總結分析

本公衆號所有原創乾貨已整理成一個目錄,回覆[ 資源 ]便可得到。

相關文章
相關標籤/搜索