STM32
直播中

早知

9年用户 1180经验值
擅长:光电显示 存储技术
私信 关注
[问答]

如何去实现NRF24L01和节点互相进行通信呢

如何去实现NRF24L01和节点互相进行通信呢?其代码该怎样去实现?

回帖(2)

张一珠

2021-12-16 10:52:29
NRF24L01和节点通信
根据MQTT协议自己写的库,自动连接,可以发布消息,订阅,取消订阅,PingReq





MQ MqttClient_SetDefaultReceivedCallBack(MQTTCLIENTRECVCALLBACK pFun)
{
    ReceivedHandler=pFun;
}
void OnMessageReceived(u8* topic, u8* payload, u8 type)//回调函数
{
    if(ReceivedHandler)
    {
        ReceivedHandler(topic, payload, type);
    }
}
u16 GetMessageIdentifier()
{
    if (MessageIdentifier == 0x7FFF)
        MessageIdentifier = 0x0000;
    MessageIdentifier++;
    return MessageIdentifier;
}
void MqttClient_Connect()
{
    len=GetData_Connet(send_buff);
    MqttConnect_SendMessage(send_buff,len);
}
//主函数调用或定时器1s调用
void MqttClient_AutoReconnect()
{
    static u32 reTimer=0;
    if(ConnectState==Disconnected)
    {
        if(Get_RunTime()-reTimer>500)//5s
        {
            MqttClient_Connect();
        }
    }
}
void MqttClient_DisConnet(void)
{
    len=GetData_DisConnet(send_buff);
    MqttConnect_SendMessage(send_buff,len);
    ConnectState = Disconnected;
}
void MqttClient_Publish(u8* topic,u8* data,u8 qos,u8 retain)
{
    u16 num;
    if(qos>0) num=GetMessageIdentifier();
    else num=0;
    len=GetData_PUBLISH(send_buff,0,qos,retain,topic,num,data);
    MqttConnect_SendMessage(send_buff,len);
    PingDateTime=Get_RunTime();
}
void MqttClient_Subscribe(u8* topic,u8 qos)
{
    len=GetData_SUBSCRIBE(send_buff,GetMessageIdentifier(),topic,qos);
    MqttConnect_SendMessage(send_buff,len);
}
void MqttClient_Unsubscribe(u8* topic)
{
    len=GetData_UNSUBSCRIBE(send_buff,GetMessageIdentifier(),topic);
    MqttConnect_SendMessage(send_buff,len);
}
//定时器1s调用
void MqttClient_PingReq(void)
{
    if(ConnectState==Connected&&Get_RunTime()-PingDateTime>6000)
    {
        len=GetData_PINGREQ(send_buff);
        MqttConnect_SendMessage(send_buff,len);
        PingDateTime=Get_RunTime();
    }
}
void Puback(u16 identifier)
{
    len=GetData_PUBACK(send_buff,identifier);
    MqttConnect_SendMessage(send_buff,len);
}
void Pubrec(u16 identifier)
{
    len=GetData_PUBREC(send_buff,identifier);
    MqttConnect_SendMessage(send_buff,len);
}
void Pubrel(u16 identifier)
{
    len=GetData_PUBREL(send_buff,identifier);
    MqttConnect_SendMessage(send_buff,len);
}
void Pubcomp(u16 identifier)
{
    len=GetData_PUBCOMP(send_buff,identifier);
    MqttConnect_SendMessage(send_buff,len);
}
void MqttClient_DecodeMessage(u8* buffer)//解码消息
{
    u8 FixedHead_MessageType = ((buffer[0] & 0xf0) >> 4);
    u8 FixedHead_Dup = ((buffer[0] & 0x08) >> 3) > 0;
    u8 FixedHead_Qos = ((buffer[0] & 0x06) >> 1);   
    u8 FixedHead_Retain = (buffer[0] & 0x01) > 0;
    u8 RemaingLength = buffer[1];
    u8 ReturnCode;
   
    lenindex=2;
    PingDateTime = Get_RunTime();
    switch (FixedHead_MessageType)
    {
        case MQTT_TypeCONNACK://正确连接返回20 02 00 00
            if(RemaingLength==2)
                ReturnCode = buffer[3];
            else ReturnCode = 0xFF;
            if (ReturnCode == BrokerUnavailable ||
                ReturnCode == IdentifierRejected ||
                ReturnCode == UnacceptedProtocolVersion ||
                ReturnCode == NotAuthorized ||
                ReturnCode == BadUsernameOrPassword)
            {
                ConnectState = Disconnecting;
                ConnectState = Disconnected;
            }
            else
            {
                ConnectState = Connected;
                OnMessageReceived("", "", MQTT_TypeCONNACK);
            }
            break;
        case MQTT_TypePUBLISH:
            if(RemaingLength>2)
            {
                topiclen=buffer[lenindex++]<<8;
                topiclen=buffer[lenindex++];
            }
            MemSet(topic,0,sizeof(topic));
            BlockCopy(buffer,lenindex,topic,0,topiclen);
            lenindex+=topiclen;
            if(FixedHead_Qos>0)
            {
                msgIdentifier=buffer[lenindex++]<<8;
                msgIdentifier=buffer[lenindex++];
            }
            payloadLen=RemaingLength-lenindex-2;
            MemSet(payload,0,sizeof(payload));
            BlockCopy(buffer,lenindex,payload,0,payloadLen);
            lenindex+=payloadLen;
            if (FixedHead_Qos == 0)//Level 0 最多分发一次
            {
                OnMessageReceived(topic, payload, MQTT_TypePUBLISH);
            }
            else if (FixedHead_Qos == 1)//Level 1 至少分发一次
            {
                Puback(msgIdentifier);//(QoS 1)(服务端发布)
                if(!FixedHead_Dup)
                {
                    OnMessageReceived(topic, payload, MQTT_TypePUBLISH);
                }
            }
            else if (FixedHead_Qos == 2)//Level 2 只分发一次
            {
                //PUBREC – 发布收到(QoS 2,第一步)(服务端发布)
                Pubrec(msgIdentifier);
                //AddPublishMsg(topic, payload, msgIdentifier);
                OnMessageReceived(topic, payload, MQTT_TypePUBLISH);
            }
            break;
        case MQTT_TypePUBACK:
            //发布完成(QoS 1)(客户端发布)
            OnMessageReceived("", "", MQTT_TypePUBACK);
            break;
        case MQTT_TypePUBREC:
            //PUBREC – 发布收到(QoS 2,第一步)(客户端发布)
            msgIdentifier=buffer[lenindex++]<<8;
            msgIdentifier=buffer[lenindex++];
            //PUBREL – 发布释放(QoS 2,第二步)(客户端发布)
            Pubrel(msgIdentifier);
            break;
        case MQTT_TypePUBREL:
            //PUBREL – 发布释放(QoS 2,第二步)(服务端发布)
            msgIdentifier=buffer[lenindex++]<<8;
            msgIdentifier=buffer[lenindex++];
            //PUBCOMP – 发布完成(QoS 2,第三步)(服务端发布)
            Pubcomp(msgIdentifier);
            //根据msgIdentifier从PublishMsg列表读topic,payload
            //OnMessageReceived(topic, payload, MQTT_TypePUBCOMP);
            //发布完成,删除消息
            //RemovePublishMsg(msgIdentifier);
            break;
        case MQTT_TypePUBCOMP:
            //PUBCOMP – 发布完成(QoS 2,第三步)(客户端发布)
            msgIdentifier=buffer[lenindex++]<<8;
            msgIdentifier=buffer[lenindex++];
            OnMessageReceived("", "", MQTT_TypePUBCOMP);
            break;
        case MQTT_TypeSUBACK:
            //订阅成功
            OnMessageReceived("", "", MQTT_TypeSUBACK);
            break;
        case MQTT_TypeUNSUBACK:
            //取消订阅成功
            OnMessageReceived("", "", MQTT_TypeUNSUBACK);
            break;
        case MQTT_TypeDISCONNECT:
            //OnMessageReceived("", "", MQTT_TypeDISCONNECT);
            ConnectState = Disconnecting;
            MqttConnect_CloseConnect();
            ConnectState = Disconnected;
            break;
    }
}
//获取数据包
//固定头
unsigned char GetData_FixedHead(unsigned char MesType, unsigned char DupFlag, unsigned char QosLevel, unsigned char Retain)
{
    unsigned char dat = 0;
    dat = (MesType & 0x0f) << 4;
    dat |= (DupFlag & 0x01) << 3;
    dat |= (QosLevel & 0x03) << 1;
    dat |= (Retain & 0x01);
    return dat;
}
//获取连接的数据包
//正确连接返回20 02 00 00
u16 GetData_Connet(unsigned char *buff,unsigned char *clientId,unsigned char *userName,unsigned char *password)
{
    unsigned int i, len, lennum = 0;
   
    buff[lennum++] = GetData_FixedHead(MQTT_TypeCONNECT, 0, 0, 0);
    buff[lennum++] = 0x00;//最后计算长度
    buff[lennum++] = 0x00;
    buff[lennum++] = 0x04;
    buff[lennum++] = 'M';
    buff[lennum++] = 'Q';
    buff[lennum++] = 'T';
    buff[lennum++] = 'T';
    buff[lennum++] = 0x04;//协议级别 Protocol Level
    buff[lennum++] = 0 | (MQTT_StaCleanSession << 1)
                       | (MQTT_StaWillFlag << 2)
                       | (MQTT_StaWillQoS << 3)
                       | (MQTT_StaWillRetain << 5)
                          | (MQTT_StaPasswordFlag << 6)
                       | (MQTT_StaUserNameFlag << 7);//连接标志
    buff[lennum++] = MQTT_KeepAlive >> 8;
    buff[lennum++] = MQTT_KeepAlive;
    len = strlen((char*)clientId);
    buff[lennum++] = len >> 8;
    buff[lennum++] = len;
    for (i = 0; i
    {
        buff[lennum++] = clientId;
    }
    if (MQTT_StaWillFlag)
    {
        len = strlen(MQTT_WillTopic);
        buff[lennum++] = len >> 8;
        buff[lennum++] = len;
        for (i = 0; i         {
            buff[lennum++] = MQTT_WillTopic;
        }
        len = strlen(MQTT_WillMessage);
        buff[lennum++] = len >> 8;
        buff[lennum++] = len;
        for (i = 0; i         {
            buff[lennum++] = MQTT_WillMessage;
        }
    }
    if (MQTT_StaUserNameFlag)
    {
        len = strlen((char*)userName);
        buff[lennum++] = len >> 8;
        buff[lennum++] = len;
        for (i = 0; i         {
            buff[lennum++] = userName;
        }
    }
    if (MQTT_StaPasswordFlag)
    {
        len = strlen((char*)password);
        buff[lennum++] = len >> 8;
        buff[lennum++] = len;
        for (i = 0; i         {
            buff[lennum++] = password;
        }
    }
    buff[1] = lennum - 2;
    return lennum;
}
//获取断开连接的数据包
u8 GetData_DisConnet(unsigned char *buff)
{
    buff[0] = 0xe0;
    buff[1] = 0;
    return 2;
}
//心跳请求的数据包
//成功返回d0 00
u8 GetData_PINGREQ(unsigned char *buff)
{
    buff[0] = 0xc0;
    buff[1] = 0;
    return 2;
}

举报

曹雪

2021-12-16 10:52:36
//订阅主题的数据包 Num:主题序号 RequestedQoS:服务质量要求0,1或2
//返回90 0x 00 Num RequestedQoS 0x00-QoS0 0x01QoS1 0x02-QoS2 0x80-Failure失败
u16 GetData_SUBSCRIBE(unsigned char *buff, unsigned int Num, const char *Topic, unsigned char RequestedQoS)
{
    unsigned int i, len = 0, lennum = 0;
    buff[lennum++] = 0x82;
    buff[lennum++] = 0x00;//最后计算长度
    buff[lennum++] = Num >> 8;//消息标识符
    buff[lennum++] = Num;
    len = strlen(Topic);
    buff[lennum++] = len >> 8;
    buff[lennum++] = len;
    for (i = 0; i     {
        buff[lennum++] = Topic;
    }
    buff[lennum++] = RequestedQoS;
    buff[1] = lennum - 2;
    return lennum;
}
//取消订阅主题的数据包 Num:主题序号
//成功返回B0 02 00 00
u16 GetData_UNSUBSCRIBE(unsigned char *buff, unsigned int Num, const char *Topic)
{
    unsigned int i, len = 0, lennum = 0;
    buff[lennum++] = 0xA2;
    buff[lennum++] = 0x00;//最后计算长度
    buff[lennum++] = Num >> 8;//消息标识符
    buff[lennum++] = Num;
    len = strlen(Topic);
    buff[lennum++] = len >> 8;
    buff[lennum++] = len;
    for (i = 0; i     {
        buff[lennum++] = Topic;
    }
    buff[1] = lennum - 2;
    return lennum;
}
//获取发布消息的数据包
//返回 QoS0 无响应
//QoS1 PUBACK 40 02 00 00
//QoS2 PUBREC 50 02 00 00 PUBREC报文是对QoS等级2的PUBLISH报文的响应(QoS2,第1步)
u16 GetData_PUBLISH(unsigned char *buff, unsigned char dup, unsigned char qos, unsigned char retain, const char *topic, unsigned int identifier,const char *msg)
{
    unsigned int i, len = 0, lennum = 0;
    buff[lennum++] = GetData_FixedHead(MQTT_TypePUBLISH, dup, qos, retain);
    buff[lennum++] = 0x00;//最后计算长度
    len = strlen(topic);
    buff[lennum++] = len >> 8;
    buff[lennum++] = len;
    for (i = 0; i     {
        buff[lennum++] = topic;
    }
    if (qos > 0)
    {
        buff[lennum++] = identifier >> 8;//只有当QoS等级是1或2时,报文标识符(Packet Identifier)字段才能出现在PUBLISH报文中。
        buff[lennum++] = identifier;
    }
    len = strlen(msg);
    for (i = 0; i     {
        buff[lennum++] = msg;
    }
    buff[1] = lennum - 2;
    return lennum;
}
u8 GetData_PUBACK(unsigned char *buff, unsigned int identifier)
{
    buff[0] = 0x40;
    buff[1] = 0x02;
    buff[2] = identifier >> 8;;
    buff[3] = 0x00;
    return 4;
}
u8 GetData_PUBREC(unsigned char *buff, unsigned int identifier)
{
    buff[0] = 0x50;
    buff[1] = 0x02;
    buff[2] = identifier >> 8;
    buff[3] = identifier;
    return 4;
}
//获取发布释放(QoS2,第2步)的数据包
//PUBREL报文是对PUBREC报文的响应
//返回70 02 00 00 PUBCOMP报文是对PUBREL报文的响应(QoS2,第3步)
u8 GetData_PUBREL(unsigned char *buff, unsigned int identifier)
{
    buff[0] = 0x62;
    buff[1] = 0x02;
    buff[2] = identifier >> 8;
    buff[3] = identifier;
    return 4;
}
u8 GetData_PUBCOMP(unsigned char *buff, unsigned int identifier)
{
    buff[0] = 0x70;
    buff[1] = 0x02;
    buff[2] = identifier >> 8;
    buff[3] = identifier;
    return 4;
}
举报

更多回帖

×
20
完善资料,
赚取积分