一次小模塊的使用過程-LC12S無線模塊介紹
前言:
最近幫人做了個小設備,使用了無線模塊、觸摸芯片,主要功能就是把觸摸按鍵的信號無線傳到控制繼電器輸出,MCU是STM8系列的芯片,其中使用過程中調試無線模塊LC21S覺得挺好用的,就寫了這篇文章。
模塊介紹:
LC12S 采用最新 2.4G SOC 技術,特點是免開發,視距 120 米,收發一體無需切換,串口透明傳 輸,提供通信協議,可迅速調試成功。用戶只要了解串口通信,無需復雜的無線通訊知識,就能完成無 線通信產品的開發。沒有數據包大小限制,延時短,半雙工通訊,抗干擾能力強。
- 2.4GHz ISM 頻段,使用無須申請
- 最大輸出功率 12dBm
- 接收靈敏度-95dBm
- 發射工作電流 40mA@12dBm
- 接收工作電流 24mA
- 睡眠電流 3.5uA
- 標準 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模塊的使用,如果大家有更好的想法和需求,也歡迎大家分享交流哈。
本文轉載自微信公眾號「羽林君」,可以通過以下二維碼關注。轉載本文請聯系羽林君公眾號。