当前位置: 首页 > wzjs >正文

怎样手机网站建设广东疫情最新消息

怎样手机网站建设,广东疫情最新消息,wordpress 苹果电脑,个人备案做非经营性网站文章目录 一、场景描述二、框架搭建设计思路通信协议设计2号单片机通讯框架框架优化建议 三、2号单片机的通讯框架如何处理消息丢失和重传?消息丢失与重传机制设计改进的通信协议重传机制实现关键机制说明优化建议 一、场景描述 有3个单片机进行通讯,分…

文章目录

  • 一、场景描述
  • 二、框架搭建
      • 设计思路
      • 通信协议设计
      • 2号单片机通讯框架
      • 框架优化建议
  • 三、2号单片机的通讯框架如何处理消息丢失和重传?
      • 消息丢失与重传机制设计
      • 改进的通信协议
      • 重传机制实现
      • 关键机制说明
      • 优化建议

一、场景描述

有3个单片机进行通讯,分别为1号,2号,3号。
1号与2号可以通讯,2号与3号可以通讯。

那么如果1号想通过2号,与3号进行通讯。

如何搭建2号的通讯框架,保证1号的通讯能够及时给3号,同时3号也能及时应答给1号。使用串口通讯,协议自定

二、框架搭建

设计思路

为了实现三个单片机之间的可靠中继通信,2号单片机需要设计一个高效的通讯框架。关键在于如何处理串口接收、消息转发和应答机制,同时保证消息的实时性和可靠性。

通信协议设计

首先需要定义一个简单但功能完整的通信协议:

消息格式: [SOF][源地址][目标地址][消息ID][长度][数据][CRC]- SOF: 起始字节 (0xAA)- 源地址: 发送方ID (1,2,3)- 目标地址: 接收方ID (1,2,3)- 消息ID: 标识消息类型 (0x01-命令, 0x02-数据, 0x03-应答)- 长度: 数据字段长度- 数据: 消息内容- CRC: 校验字节

2号单片机通讯框架

下面是2号单片机的通讯框架实现,使用状态机处理消息接收,使用双缓冲区实现消息转发:

#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>// 定义系统常量
#define SOF             0xAA
#define DEVICE_ID_1     0x01
#define DEVICE_ID_2     0x02
#define DEVICE_ID_3     0x03// 消息类型定义
#define MSG_CMD         0x01
#define MSG_DATA        0x02
#define MSG_ACK         0x03// 消息缓冲区大小
#define MAX_MSG_LENGTH  64
#define BUFFER_SIZE     5// 消息结构体
typedef struct {uint8_t src_addr;uint8_t dst_addr;uint8_t msg_id;uint8_t length;uint8_t data[MAX_MSG_LENGTH];uint8_t crc;
} Message;// 接收状态机枚举
typedef enum {RX_STATE_IDLE,RX_STATE_SOF,RX_STATE_SRC,RX_STATE_DST,RX_STATE_MSGID,RX_STATE_LENGTH,RX_STATE_DATA,RX_STATE_CRC
} RxState;// 全局变量
static Message rx_buffer[BUFFER_SIZE];
static Message tx_buffer[BUFFER_SIZE];
static uint8_t rx_head = 0;
static uint8_t rx_tail = 0;
static uint8_t tx_head = 0;
static uint8_t tx_tail = 0;
static RxState rx_state = RX_STATE_IDLE;
static uint8_t rx_index = 0;
static uint8_t crc_calculated = 0;// 串口初始化函数
void UART1_Init(void) {// 配置1号串口(与1号单片机通信)// 波特率、中断等配置
}void UART2_Init(void) {// 配置2号串口(与3号单片机通信)// 波特率、中断等配置
}// CRC校验计算
uint8_t calculate_crc(uint8_t *data, uint8_t length) {uint8_t crc = 0;for (uint8_t i = 0; i < length; i++) {crc ^= data[i];}return crc;
}// 发送消息函数
void send_message(Message *msg, uint8_t uart_id) {uint8_t buffer[MAX_MSG_LENGTH + 6];uint8_t index = 0;buffer[index++] = SOF;buffer[index++] = msg->src_addr;buffer[index++] = msg->dst_addr;buffer[index++] = msg->msg_id;buffer[index++] = msg->length;for (uint8_t i = 0; i < msg->length; i++) {buffer[index++] = msg->data[i];}buffer[index++] = calculate_crc(buffer, index);// 根据uart_id选择发送串口if (uart_id == 1) {// 通过UART1发送buffer} else {// 通过UART2发送buffer}
}// 1号串口接收中断处理函数
void UART1_RX_IRQHandler(void) {uint8_t data = UART1_ReadByte();switch (rx_state) {case RX_STATE_IDLE:if (data == SOF) {rx_state = RX_STATE_SOF;crc_calculated = data;}break;case RX_STATE_SOF:rx_buffer[rx_head].src_addr = data;rx_state = RX_STATE_SRC;crc_calculated ^= data;break;case RX_STATE_SRC:rx_buffer[rx_head].dst_addr = data;rx_state = RX_STATE_DST;crc_calculated ^= data;break;case RX_STATE_DST:rx_buffer[rx_head].msg_id = data;rx_state = RX_STATE_MSGID;crc_calculated ^= data;break;case RX_STATE_MSGID:rx_buffer[rx_head].length = data;rx_state = RX_STATE_LENGTH;crc_calculated ^= data;rx_index = 0;break;case RX_STATE_LENGTH:rx_buffer[rx_head].data[rx_index++] = data;crc_calculated ^= data;if (rx_index >= rx_buffer[rx_head].length) {rx_state = RX_STATE_CRC;}break;case RX_STATE_CRC:if (data == crc_calculated) {// 消息接收成功,加入接收缓冲区rx_head = (rx_head + 1) % BUFFER_SIZE;}rx_state = RX_STATE_IDLE;break;}
}// 3号串口接收中断处理函数(与UART1_RX_IRQHandler类似)
void UART2_RX_IRQHandler(void) {// 实现类似UART1_RX_IRQHandler的逻辑// 将接收到的消息存入rx_buffer
}// 主循环中的消息处理函数
void process_messages(void) {Message msg;// 处理从1号单片机接收的消息while (rx_tail != rx_head) {msg = rx_buffer[rx_tail];// 如果消息是给3号的,转发到3号if (msg.dst_addr == DEVICE_ID_3) {// 修改源地址为2号msg.src_addr = DEVICE_ID_2;send_message(&msg, 2);  // 通过UART2发送到3号}// 如果消息是给1号的(来自3号的应答),转发到1号else if (msg.dst_addr == DEVICE_ID_1) {// 修改源地址为2号msg.src_addr = DEVICE_ID_2;send_message(&msg, 1);  // 通过UART1发送到1号}rx_tail = (rx_tail + 1) % BUFFER_SIZE;}
}// 主函数
int main(void) {UART1_Init();UART2_Init();// 启用中断UART1_EnableIRQ();UART2_EnableIRQ();while (1) {// 处理消息转发process_messages();// 其他任务// ...}
}

框架优化建议

  1. 优先级机制:为紧急消息设置高优先级,优先处理和转发。

  2. 流量控制:当缓冲区满时,发送忙信号给发送方,防止消息丢失。

  3. 超时重传:对重要消息实现超时重传机制,确保消息可靠传输。

  4. 状态监控:添加通信状态监控,统计消息收发成功率,便于故障排查。

  5. 中断处理优化:尽量减少中断处理时间,关键数据复制到缓冲区后尽快退出中断。

通过以上设计,2号单片机可以高效地实现1号和3号之间的消息中继,同时保证通信的实时性和可靠性。

三、2号单片机的通讯框架如何处理消息丢失和重传?

消息丢失与重传机制设计

为了处理消息丢失和实现可靠重传,2号单片机的通讯框架需要增加确认机制、超时处理和消息缓存功能。以下是具体实现方案:

改进的通信协议

在原有协议基础上增加序列号和确认应答:

消息格式: [SOF][源地址][目标地址][消息ID][序列号][长度][数据][CRC]- 序列号: 8位递增数字(0-255),用于标识消息- 确认应答(ACK)格式: [SOF][源地址][目标地址][MSG_ACK][序列号][0][CRC]

重传机制实现

以下是改进后的2号单片机通讯框架代码,增加了消息缓存和重传机制:

#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>// 定义系统常量
#define SOF             0xAA
#define DEVICE_ID_1     0x01
#define DEVICE_ID_2     0x02
#define DEVICE_ID_3     0x03// 消息类型定义
#define MSG_CMD         0x01
#define MSG_DATA        0x02
#define MSG_ACK         0x03// 消息缓冲区大小
#define MAX_MSG_LENGTH  64
#define TX_BUFFER_SIZE  10
#define RX_BUFFER_SIZE  10
#define MAX_RETRIES     3
#define RETRY_TIMEOUT   100  // 毫秒// 消息结构体
typedef struct {uint8_t src_addr;uint8_t dst_addr;uint8_t msg_id;uint8_t seq_num;uint8_t length;uint8_t data[MAX_MSG_LENGTH];uint8_t crc;uint32_t timestamp;  // 发送时间戳uint8_t retries;     // 重试次数bool awaiting_ack;   // 是否等待确认
} Message;// 接收状态机枚举
typedef enum {RX_STATE_IDLE,RX_STATE_SOF,RX_STATE_SRC,RX_STATE_DST,RX_STATE_MSGID,RX_STATE_SEQ,RX_STATE_LENGTH,RX_STATE_DATA,RX_STATE_CRC
} RxState;// 全局变量
static Message tx_buffer[TX_BUFFER_SIZE];  // 发送缓冲区(用于重传)
static Message rx_buffer[RX_BUFFER_SIZE];  // 接收缓冲区
static uint8_t tx_head = 0;
static uint8_t tx_tail = 0;
static uint8_t rx_head = 0;
static uint8_t rx_tail = 0;
static RxState rx_state = RX_STATE_IDLE;
static uint8_t rx_index = 0;
static uint8_t crc_calculated = 0;
static uint8_t next_seq_num = 0;  // 下一个发送的序列号// 串口初始化函数
void UART1_Init(void) {// 配置1号串口(与1号单片机通信)// 波特率、中断等配置
}void UART2_Init(void) {// 配置2号串口(与3号单片机通信)// 波特率、中断等配置
}// CRC校验计算
uint8_t calculate_crc(uint8_t *data, uint8_t length) {uint8_t crc = 0;for (uint8_t i = 0; i < length; i++) {crc ^= data[i];}return crc;
}// 发送消息函数
void send_message(Message *msg, uint8_t uart_id, bool store_for_retry) {uint8_t buffer[MAX_MSG_LENGTH + 7];uint8_t index = 0;buffer[index++] = SOF;buffer[index++] = msg->src_addr;buffer[index++] = msg->dst_addr;buffer[index++] = msg->msg_id;buffer[index++] = msg->seq_num;buffer[index++] = msg->length;for (uint8_t i = 0; i < msg->length; i++) {buffer[index++] = msg->data[i];}buffer[index++] = calculate_crc(buffer, index);// 根据uart_id选择发送串口if (uart_id == 1) {// 通过UART1发送buffer} else {// 通过UART2发送buffer}// 如果需要存储用于重传if (store_for_retry && msg->msg_id != MSG_ACK) {// 复制消息到发送缓冲区memcpy(&tx_buffer[tx_head], msg, sizeof(Message));tx_buffer[tx_head].timestamp = get_current_time();  // 获取当前时间tx_buffer[tx_head].retries = 0;tx_buffer[tx_head].awaiting_ack = true;tx_head = (tx_head + 1) % TX_BUFFER_SIZE;}
}// 1号串口接收中断处理函数
void UART1_RX_IRQHandler(void) {uint8_t data = UART1_ReadByte();switch (rx_state) {case RX_STATE_IDLE:if (data == SOF) {rx_state = RX_STATE_SOF;crc_calculated = data;}break;// 其他状态处理...(与之前类似)case RX_STATE_CRC:if (data == crc_calculated) {// 消息接收成功,加入接收缓冲区if (rx_buffer[rx_head].msg_id == MSG_ACK) {// 处理确认应答,标记对应消息已确认process_ack(&rx_buffer[rx_head]);} else {// 普通消息,转发并发送本地ACKforward_message(&rx_buffer[rx_head]);send_ack(rx_buffer[rx_head].src_addr, rx_buffer[rx_head].seq_num);}rx_head = (rx_head + 1) % RX_BUFFER_SIZE;}rx_state = RX_STATE_IDLE;break;}
}// 3号串口接收中断处理函数
void UART2_RX_IRQHandler(void) {// 与UART1_RX_IRQHandler类似,处理来自3号的消息
}// 处理确认应答
void process_ack(Message *ack) {uint8_t index = tx_tail;while (index != tx_head) {if (tx_buffer[index].awaiting_ack && tx_buffer[index].seq_num == ack->seq_num &&tx_buffer[index].dst_addr == ack->src_addr) {// 标记消息已确认tx_buffer[index].awaiting_ack = false;break;}index = (index + 1) % TX_BUFFER_SIZE;}
}// 转发消息
void forward_message(Message *msg) {Message forward_msg;memcpy(&forward_msg, msg, sizeof(Message));if (msg->dst_addr == DEVICE_ID_3) {// 转发到3号forward_msg.src_addr = DEVICE_ID_2;send_message(&forward_msg, 2, true);} else if (msg->dst_addr == DEVICE_ID_1) {// 转发到1号forward_msg.src_addr = DEVICE_ID_2;send_message(&forward_msg, 1, true);}
}// 发送确认应答
void send_ack(uint8_t dst_addr, uint8_t seq_num) {Message ack_msg;ack_msg.src_addr = DEVICE_ID_2;ack_msg.dst_addr = dst_addr;ack_msg.msg_id = MSG_ACK;ack_msg.seq_num = seq_num;ack_msg.length = 0;if (dst_addr == DEVICE_ID_1) {send_message(&ack_msg, 1, false);} else {send_message(&ack_msg, 2, false);}
}// 检查并重传超时消息
void check_and_retransmit(void) {uint32_t current_time = get_current_time();uint8_t index = tx_tail;while (index != tx_head) {if (tx_buffer[index].awaiting_ack && (current_time - tx_buffer[index].timestamp > RETRY_TIMEOUT)) {// 检查重试次数if (tx_buffer[index].retries >= MAX_RETRIES) {// 达到最大重试次数,处理失败handle_transmission_failure(&tx_buffer[index]);tx_buffer[index].awaiting_ack = false;} else {// 重传消息tx_buffer[index].retries++;tx_buffer[index].timestamp = current_time;if (tx_buffer[index].dst_addr == DEVICE_ID_1) {send_message(&tx_buffer[index], 1, false);} else {send_message(&tx_buffer[index], 2, false);}}}index = (index + 1) % TX_BUFFER_SIZE;}// 清理已确认的消息while (tx_tail != tx_head && !tx_buffer[tx_tail].awaiting_ack) {tx_tail = (tx_tail + 1) % TX_BUFFER_SIZE;}
}// 处理传输失败
void handle_transmission_failure(Message *msg) {// 可以实现错误日志记录或通知上层应用
}// 获取当前时间(伪代码,需根据实际硬件实现)
uint32_t get_current_time(void) {// 返回系统时间(毫秒)return 0;
}// 主循环中的消息处理函数
void process_messages(void) {// 检查并重传超时消息check_and_retransmit();// 处理接收缓冲区中的消息while (rx_tail != rx_head) {// 处理消息...rx_tail = (rx_tail + 1) % RX_BUFFER_SIZE;}
}// 主函数
int main(void) {UART1_Init();UART2_Init();// 启用中断UART1_EnableIRQ();UART2_EnableIRQ();while (1) {// 处理消息转发和重传process_messages();// 其他任务// ...}
}

关键机制说明

  1. 序列号管理

    • 每个消息分配唯一序列号(0-255循环)
    • 用于识别重复消息和匹配ACK应答
  2. 确认应答机制

    • 接收方收到消息后发送ACK应答
    • ACK包含原始消息的序列号
    • 发送方维护待确认消息列表
  3. 超时重传

    • 设置合理的超时时间(RETRY_TIMEOUT)
    • 超过时间未收到ACK则重传
    • 限制最大重试次数(MAX_RETRIES)
  4. 消息缓存

    • 使用环形缓冲区存储待确认消息
    • 消息包含发送时间戳和重试次数

优化建议

  1. 滑动窗口协议

    • 扩展当前实现,支持多消息并发发送
    • 增加窗口大小参数,提高吞吐量
  2. 动态超时调整

    • 根据网络状况动态调整超时时间
    • 实现往返时间(RTT)测量
  3. 流量控制

    • 当发送缓冲区满时拒绝接收新消息
    • 实现基于窗口的流量控制机制
  4. 错误恢复

    • 实现序列号回滚机制
    • 处理序列号溢出情况

通过以上机制,2号单片机可以有效处理消息丢失问题,确保1号和3号之间的通信可靠性。

http://www.dtcms.com/wzjs/346542.html

相关文章:

  • 专业网站定制流程高质量外链代发
  • 西安免费做网站机构优化大师客服
  • 六安网站建设培训长沙专业seo优化公司
  • java eclipse做网站软件开发网
  • 众筹网站开发怎样做网络推广营销
  • 网站开发需要注意什么抖音seo优化怎么做
  • 做b2b网站管理系统网络运营推广
  • 青海省制作网站专业建立网站的主要步骤
  • 开发公司工程部奖励规定杭州seo网站推广
  • 网站特效怎么做郑州网站seo服务
  • 抄底券网站怎么做的国内建站平台有哪些
  • 珠海网站建设易搜互联百度关键词规划师入口
  • wordpress 关键词屏蔽seo销售话术开场白
  • 经销商自己做网站合适吗营销型公司网站建设
  • 网站制作推广方案百度手机怎么刷排名多少钱
  • 用电脑做服务器制作网站百度如何搜索网址
  • 凡客网站建设chatgpt 网站
  • 做网站图片路径做缓存吗谷歌seo关键词优化
  • 给客户做一个网站ppt怎么做广东东莞疫情最新情况
  • 网站建设与维护的国家定价标准惠州seo推广外包
  • 哈密市建设局网站app推广怎么联系一手代理
  • 上海网站制作开发公司2345网址导航电脑版官网
  • 网站建好了seo怎么做全网营销图片
  • 安徽省建设监理协会网站网络销售有哪些
  • 建设网站的成本有哪些网站推广的方法
  • 如何做简洁网站长沙百度首页优化排名
  • 网站提供哪些服务网站建设方案书
  • 设计网站公司咨询亿企邦唐山seo
  • 网上拿手工做的网站信息流广告怎么投放
  • 国内做香港视频网站关键词竞价排名