一次小模块的使用过程-LC12S无线模块介绍

网络 通信技术
最近帮人做了个小设备,使用了无线模块、触摸芯片,主要功能就是把触摸按键的信号无线传到控制继电器输出,MCU是STM8系列的芯片,其中使用过程中调试无线模块LC21S觉得挺好用的,就写了这篇文章。

[[380994]]

前言:

最近帮人做了个小设备,使用了无线模块、触摸芯片,主要功能就是把触摸按键的信号无线传到控制继电器输出,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()函数。

设置模式下的代码:

定义一个设置协议的结构体:

  1. typedef struct __attribute__((__packed__)){ 
  2.     u16 head;                 // 
  3.     u16 self_id;                 // 
  4.     u16 net_id;                 // 
  5.     u8 nc1;               // 
  6.     u8 rf_power;          // 
  7.     u8 nc2;               // 
  8.     u8 rf_baud;          // 
  9.     u8 nc3;               // 
  10.     u8 rf_chn;          // 
  11.     u16 nc4;               // 
  12.     u8 nc5;               // 
  13.     u8 length;               // 
  14.     u8 nc6;               // 
  15. }SetSend;  

拉低SET引脚,进入设置模式:

  1. u8 SetNrf(void)// 
  2.        GPIO_ResetBits(SET_PORT, SET_PIN); 
  3.        GPIO_ResetBits(CS_PORT, CS_PIN); 
  4.  
  5.       u8 *p1 = malloc(18); 
  6.       memset(p1,0x00,18); 
  7.  
  8.       SetSend *p = (SetSend*)p1; 
  9.  
  10.       p->head= 0xaa5A; 
  11.       p->self_id = 0x2233; 
  12.       p->net_id = 0x1122; 
  13.       p->rf_power = 0x00; 
  14.       p->rf_baud = 0x04; 
  15.       p->rf_chn = 0x64; 
  16.       p->length = 0x12;       
  17.       p1[sizeof(SetSend)] = CheckSum((u8*)p, sizeof(SetSend)); 
  18.       USART_Transmit_String( sizeof(SetSend)+1,p1); 
  19.  
  20. #if DEBUG_DPRINT 
  21.       u8 *str = malloc(20); 
  22.       hex_str((u8*)p, sizeof(SetSend)+1, str); 
  23.       USART_Transmit_String(20,str); 
  24. //      printf("--->:%s\r\n", str); 
  25.       free(str); 
  26. #endif 
  27.  
  28.       free(p1); 
  29.       return 1; 
  30.        

数据透传的函数,这个时候SET引脚拉高,这个函数部分是我自己写的一个简单的3byte的sta状态发送。大家可以按照自己的实际使用情况进行修改。

  1. void nrf_send_normal_data(u16 sta) 
  2.       GPIO_SetBits(SET_PORT, SET_PIN); 
  3.       u8 *p1 = malloc(3); 
  4.       memset(p1,0x00,3); 
  5.       memset(p1,0xAA,1);       
  6.       memcpy(p1+1,&sta,2); 
  7.       USART_Transmit_String(3,p1); 
  8.       free(p1); 
  9.  

芯片初始化之后不能立即使用,需要等待几十ms才能正常工作,所以需要稍微等待一下。

串口接收解析部分,这部分代码就仁者见仁智者见智了,大家可以用很多种方法实现,我只是贴了一下我写的代码部分,仅供参考。其中NRF_RestTime()函数是在定时器中计时,用来区分不同的数据帧。

  1. u8  USART_RX_BUF[USART_MAX_RECV_LEN]; 
  2. u16 USART_RX_STA=0; 
  3.  
  4. u8 NRF_RecvdData(void) 
  5.  u8 ret = 0; 
  6.  if((USART_RX_STA&(1<<15)) != 0) 
  7.   ret = 1; 
  8.  return ret; 
  9. u16 NRF_RcvLen(void) 
  10.  return (USART_RX_STA & 0x7FFF); 
  11. u8* NRF_RcvBuff(void) 
  12.  return USART_RX_BUF; 
  13.  
  14. void NRF_ClsRecvd(void) 
  15.  USART_RX_STA = 0; 
  16.  
  17.  
  18. typedef struct  __attribute__((__packed__)) 
  19.   u32 stat    :1; 
  20.   u32 timOut  :1; 
  21.   u32 cunt    :15; 
  22.   u32 des     :15; 
  23. }TboxTimTypeDef; 
  24. TboxTimTypeDef gNRFTimeManage; 
  25. #define TON   (1) 
  26. #define TOFF  (0) 
  27.  
  28. void TimerManageInit(TboxTimTypeDef *t,u8 stat,u16 destim) 
  29.   t->des  = destim; 
  30.   t->stat = stat; 
  31.   t->cunt = 0; 
  32.   t->timOut = 0; 
  33. void NRF_RestTime(void) 
  34.       if(gNRFTimeManage.stat == TON) 
  35.       { 
  36.               (gNRFTimeManage.cunt < gNRFTimeManage.des)?(gNRFTimeManage.cunt++):\ 
  37.                       (TimerManageInit(&gNRFTimeManage,TOFF,0),USART_RX_STA |=1<<15); 
  38.       }  
  39.  
  40. void NRF_Irq(void) 
  41.    u8 res;        
  42.  if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) 
  43.  {   
  44.   res =USART_ReceiveData8(USART1); 
  45.                 #if 0 
  46.   USART_SendData8(USART1,res); 
  47.   #endif 
  48.  
  49.        
  50.                 if((USART_RX_STA & ~(1<<15))<USART_MAX_RECV_LEN) 
  51.                 { 
  52.                       TimerManageInit(&gNRFTimeManage,TON,5); 
  53.                       USART_RX_BUF[USART_RX_STA++]=res;    
  54.                 }else  
  55.                 { 
  56.                         USART_RX_STA|=1<<15;     
  57.                 }  
  58.           } 
  59.  USART_ClearITPendingBit(USART1,USART_IT_RXNE); 
  60.  
  61. void Parse_NRF(void) 
  62.    
  63.     if(NRF_RcvLen()>2) 
  64.     { 
  65.       u16 len = NRF_RcvLen();  
  66.       u8 *p = NRF_RcvBuff(); 
  67.       u8 pos = 0; 
  68.       u16 *sta = (u16*)(p+1); 
  69.       while(pos < len){ 
  70.         if(*p == 0xAA) 
  71.         { 
  72.            
  73.           relay_ctrl(*sta); 
  74.           p += 3; 
  75.           pos +=3; 
  76.         } 
  77.         else
  78.           p++; 
  79.           pos++; 
  80.         } 
  81.       } 
  82.       USART_RX_STA = 0; 
  83.     } 
  84.    

设备展示

主机端:

从机端:

结语

这就是我分享的LC12S模块的使用,如果大家有更好的想法和需求,也欢迎大家分享交流哈。

本文转载自微信公众号「羽林君」,可以通过以下二维码关注。转载本文请联系羽林君公众号。

 

责任编辑:武晓燕 来源: 羽林君
相关推荐

2012-01-12 10:01:28

模块

2022-11-22 13:00:38

2015-08-27 09:15:35

2009-03-20 10:58:47

2023-12-05 08:33:44

滴滴故障k8s

2022-09-15 10:02:58

测试软件

2022-09-14 15:40:03

接口解决

2014-08-01 14:06:45

2010-09-07 11:16:14

SQL语句

2010-03-23 08:56:38

Python随机数模块

2010-04-12 16:28:41

无线通信模块

2011-06-28 10:41:50

DBA

2019-08-26 09:50:09

2017-12-19 14:00:16

数据库MySQL死锁排查

2023-10-10 12:05:45

2010-03-22 15:38:46

Python常用模块

2018-07-20 08:44:21

Redis内存排查

2021-08-19 09:50:53

Java内存泄漏

2021-11-23 21:21:07

线上排查服务

2020-04-08 10:30:19

Linux 攻击 安全
点赞
收藏

51CTO技术栈公众号