一次小模块的使用过程-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模块的使用,如果大家有更好的想法和需求,也欢迎大家分享交流哈。
—END—
推荐阅读
【3】CPU中的程序是怎么运行起来的 必读
【5】阶段性文章总结分析
本公众号全部原创干货已整理成一个目录,回复[ 资源 ]即可获得。
一次小模块的使用过程-LC12S无线模块介绍的更多相关文章
- 第四课:seajs的模块编译_compile过程
最近比较闲,我就讲下seajs的模块编译_compile过程. 这里紧接着第三课的例子来讲解.首先是a.js的编译 Module.prototype._compile = function() { 1 ...
- 一个有趣的小例子,带你入门协程模块-asyncio
一个有趣的小例子,带你入门协程模块-asyncio 上篇文章写了关于yield from的用法,简单的了解异步模式,[https://www.cnblogs.com/c-x-a/p/10106031. ...
- Python3.x:logging模块对运行过程记录
Python3.x:logging模块对运行过程记录 示例: import logging # 设置 logger = logging.getLogger() #set loghandler #默认路 ...
- python基础之面向过程编程,模块
面向过程编程 面向过程的核心是过程,指的是解决问题的步骤,即先干什么再干什么,就好像设计一条流水线. 优点:复杂的问题流程化,进而简单化 缺点:可扩展性差,修改流水线的任意一个阶段,都会牵一发而动全身 ...
- insmod模块加载过程代码分析1【转】
转自:http://blog.chinaunix.net/uid-27717694-id-3966290.html 一.概述模块是作为ELF对象文件存放在文件系统中的,并通过执行insmod程序链接到 ...
- python_django_urls模块与views模块请求访问过程
diango接收到web请求后的在urls模块与views模块进行的过程操作: 匹配过程: urls拿到网址,在项目级urls中匹配,若在urlpatterns中存在,则跳转到应用级urls中匹配,若 ...
- Android studio中为项目添加模块依赖的过程
https://blog.csdn.net/cheng__lu/article/details/74574582 Android studio中为项目添加模块依赖的过程 1.点击菜单file>p ...
- Python笔记_第二篇_面向过程_第二部分_5.第三方模块的使用和自定模块(以Pillow模块为例)
1. 安装第三方模块: 打开黑屏终端: cmd: pip -verson pip - V C:\windows\system32>pip -V pip from c:\python37\lib\ ...
- python 中 模块,包, 与常用模块
一 模块 模块:就是一组功能的集合体, 我们的程序可以直接导入模块来复用模块里的功能 导入方式 一般为 : import 模块名 在python中, 模块一般分为四个通用类别 1使用python编写. ...
随机推荐
- linuix查端口
根据进程pid查端口:netstat -nap | grep pid 根据端口port查进程:netstat -nap | grep port 根据pid查找文件的启动位置 ps aux | gre ...
- 【剑指 Offer】08.二叉树的下一个节点
题目描述 给定一颗二叉树和其中的一个节点,找出中序遍历序列的下一个节点.树中的节点除了有两个分别指向左右节点的指针,还有一个指向父节点的指针. Java public class Solution08 ...
- LeetCode485 最大连续1的个数
给定一个二进制数组, 计算其中最大连续1的个数. 示例 1: 输入: [1,1,0,1,1,1] 输出: 3 解释: 开头的两位和最后的三位都是连续1,所以最大连续1的个数是 3. 注意: 输入的数组 ...
- Hystrix-服务降级-服务熔断-服务限流
Hystrix简介 Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时.异常等,Hystrix能够保证在一个依赖出问题的情况下,不会导致 ...
- node爬虫 -- 网页图片
相信大家都听说过爬虫,我们也听说过Python是可以很方便地爬取网络上的图片,但是奈何本人不会Python,就只有通过 Node 来实践一下了. 接下来看我如何 板砖 ! !!
- 【Oracle】10g rac如何开启归档和关闭归档
开启归档: 1.设置想设置的归档的位置,我们这里归档的位置为ASM磁盘组,磁盘组的名称为DATA alter system set log_archive_dest_1='location=+DATA ...
- Kubernetes CoreDNS 状态是 CrashLoopBackOff 报错
查看状态的时候,遇见coredns出现crashlookbackoff,首先我们来进行排错,不管是什么原因,查看coredns的详细信息,以及logs [root@k8s-master coredns ...
- STM32延时函数的四种方法
单片机编程过程中经常用到延时函数,最常用的莫过于微秒级延时delay_us()和毫秒级delay_ms().本文基于STM32F207介绍4种不同方式实现的延时函数. 1.普通延时 这种延时方式应该是 ...
- 对于Update Function Modules的一点说明
To be able to call a function module in an update work process, you must flag it in the Function Bui ...
- [CPP] STL 简介
STL 即标准模板库(Standard Template Library),是 C++ 标准库的一部分,里面包含了一些模板化的通用的数据结构和算法.STL 基于模版的实现,因此能够支持自定义的数据结构 ...