下载地址(CODE):
https://pan.baidu.com/s/1LNfCTK7itR-JbkzU9mJPUg
实现效果:
小baby在楼上自己睡觉的时候,声音传感器开启,当发现有动静,通过LORA(无线串口)将信号通知到楼下的蜂鸣器接收端。
通过开关控制模块是否启用
通信协议:
9600 N 8 1
标识头:5A AB
包类型:01
数据长度:01
数据内容
校验位:采用亦或校验
1#协议
启用模块
5A AB 01 01 01 F0
禁用模块
5A AB 01 01 00 F1
执行成功回馈
5A AB 01 01 64 95
2#协议
声音传感器:on
5A AB 02 01 01 F3
声音传感器:off
5A AB 02 01 00 F2
执行成功回馈
5A AB 02 01 64 96
代码片段:
按键去抖动(不使用delay,无延时)
int GpioInput::CheckDigitalStatus1()
{
if ((0 != checkIndex) && (millis() - checkTime) <= checkInterval) return -1;// 过滤中间时段的数据
int state = digitalRead(pin);
Serial.print(String(state) + ",");
if (state != stateTemp)
{
checkIndex = 0;
stateOld = stateTemp;
}
else
{
if (state != stateOld)
{
checkIndex++;
checkTime = millis();
}
}
stateTemp = state;
int ret = -1;
if (checkIndex == checkCount)
{
checkIndex = 0;
if (stateOld != state)
{
stateOld = state;
ret = state;
}
}
return ret;
}
监测指定电平(不使用delay,无延时)
int GpioInput::CheckDigitalStatus2(int val)
{
if ((0 != checkIndex) && (millis() - checkTime) <= checkInterval) return -1;// 过滤中间时段的数据
int state = digitalRead(pin);
//Serial.print(String(state) + ",");
if (state == val)
{
checkIndex++;
checkTime = millis();
}
else
{
checkIndex = 0;
}
int ret = -1;
if (checkIndex == checkCount)
{
checkIndex = 0;
ret = state;
}
return ret;
}
对串口数据进行垃圾包,掉包,粘包处理
void MySerial::SerialRecv()
{
if (softSerial->available() > 0)
{
while ((softSerial->available() > 0))
{
byte inByte = softSerial->read();
//Serial.println(inByte);
bBuffer.Put(&inByte, 1);
}
}
ProtocolHandle();
}
bool MySerial::ProtocolHandle()
{
if (!bBuffer.HasRemaining()) return false;
int iPosition = bBuffer.GetPosition();
byte head1 = 0; byte head2 = 0; bool heardok = false;
while (bBuffer.HasRemaining())
{
head1 = bBuffer.GetByte(); if (bBuffer.GetWaitRecvRemain()) { bBuffer.SetPosition(iPosition); return false; }
if (HEAD1 == head1)
{
iPosition = bBuffer.GetPosition() - 1;
head2 = bBuffer.GetByte(); if (bBuffer.GetWaitRecvRemain()) { bBuffer.SetPosition(iPosition); return false; }
if (HEAD2 == head2)
{
heardok = true;
break;
}
else
{
Serial.println("Error,Unable to parse the serial data(2):Position=" + String(iPosition) + ",Head2=" + String(head2));
}
}
else
{
Serial.println("Error,Unable to parse the serial data(1):Position=" + String(iPosition) + ",Head1=" + String(head1));
}
}
if (!heardok) return false;
byte cmd = bBuffer.GetByte(); if (bBuffer.GetWaitRecvRemain()) { bBuffer.SetPosition(iPosition); return false; };
byte len = bBuffer.GetByte(); if (bBuffer.GetWaitRecvRemain()) { bBuffer.SetPosition(iPosition); return false; }
SerialRecBuf source = bBuffer.GetByteArray(len); if (bBuffer.GetWaitRecvRemain()) { bBuffer.SetPosition(iPosition); return false; }
byte check = bBuffer.GetByte(); if (bBuffer.GetWaitRecvRemain()) { bBuffer.SetPosition(iPosition); return false; }
byte check_crc = CalcCheck2(head1, head2, cmd, len, source.byRxBuf);
if (check != check_crc)
{
Serial.println("Error,CRC:check=" + String(check) + ",check_crc=" + String(check_crc));
}
else
{
switch (cmd)
{
case 1:
// 是否启用
if (1 == source.dwLength)
{
Work = source.byRxBuf[0];
if (0 == Work || 1 == Work)
{
softSerial->write(protocol_01_work_ok, 6);
}
else if (100 == Work)
{
Work = result_01_work;
}
}
Serial.println("protocol 1 ok,Work:" + String(Work));
break;
case 2:
// 声音传感器状态
Serial.println("protocol 2 ok");
if (1 == source.dwLength)
{
Speak = source.byRxBuf[0];
// if (0 == Speak || 1 == Speak)
// {
// softSerial->write(protocol_02_voice_ok, sizeof(protocol_02_voice_ok)/sizeof(protocol_02_voice_ok[0]));
// }
}
Serial.println("protocol 1 ok,Speak:" + String(Speak));
break;
}
}
if (!bBuffer.HasRemaining()) bBuffer.Clear();
return true;
}