移植MQTT客户端项目Day3

昨天写完了USART1的初始化代码和读写函数,我在结尾的时候说:发送数据采用死等待的方式,这没毛病,而接收数据采用中断的方式。但这里是有问题的,如果某个任务想要读取USART数据,但不知道数据什么时候会发送过来,如果直接采用while(1)死等的方式,则会让MCU在相当长的时间内空转,效率很低。我们暂时先不考虑这个问题,先把中断函数读取到的字节存入缓冲区,这里就有问题了:缓冲区分配多大内存?分配多了,空间浪费;分配少了,数据溢出。我们希望这个缓冲区能够复用,这就是环形缓冲区。

一.环形缓冲区

    1.为什么要使用环形缓冲区?上面说到,缓冲区分配多大内存?分配多了,空间浪费;分配少了,数据溢出,我们希望这个缓冲区能够复用。也就是说写数据到了末尾可以从头开始继续写,而不用去分配新的内存。

    2.环形缓冲区的设计。缓冲区由一个结构体组成,其成员为:线性数组,读指针和写指针。数据结构本质上有两种:线性和链式结构,本项目不使用链式结构因为单片机资源和性能有限,而链表的遍历和空间分配比较麻烦,因此直接使用数组,并增加读指针和写指针作为读写位置标志。

    3.环形缓冲区的使用过程。假设现在向缓冲区写数据,写指针不断向后移动。之后开始读数据,读指针 也不断向后移动,一直将写指针的数据读走,此时所有的数据都读完了,后面位置的数据是未知的,缓冲区空。现在向缓冲区写数据,写指针一直写到了BUF_SIZE-1的位置,此时如果要继续写, 写指针应该回到0位置,继续写,一直写到读指针的前一个位置。此时就不能继续写了,因为后面的数据写入了但没来得及读走,继续写会覆盖原来的数据,造成数据丢失。

    4.环形缓冲区的实质。环形缓冲区就是为了复用内存资源而设计的,其读写过程就是读指针和写指针相互追赶的过程。当读指针移动比较快,赶上了写指针时,环形缓冲区空,后面的数据是未知的不能读;当写指针移动比较快,移动到读指针的前一个位置时,环形缓冲区满,后面的数据还没来得及读走,不能继续写。

    5.环形缓冲区实例程序

typedef struct ring_buf {
	unsigned char ring_buffer[BUF_SIZE];
	unsigned int pW;
	unsigned int pR;
} ring_buffer;

void ring_buffer_init(ring_buffer* dst_buf)
{
	/* 写位置和读位置都初始化为0 */
	dst_buf->pR = 0;
	dst_buf->pW = 0;
}

int8_t ring_buffer_read(unsigned char* c, ring_buffer* dst_buf)
{
	
	if (dst_buf->pR != dst_buf->pW)
	{
		*c = dst_buf->ring_buffer[dst_buf->pR];
		//第一次写pR指针更新时因为惯性思维直接写了dst_buf->pR ++
		//这样显然不对,会造成数组越界
		//采用(dst_buf->pR + 1) % BUF_SIZE的方式即实现了循环移动,又不会越界
		//因为取模操作本身就是在一个区间内循环
		dst_buf->pR = (dst_buf->pR + 1) % BUF_SIZE; 
		return 0;
	}
	return -1;
}

void ring_buffer_write(unsigned char c, ring_buffer* dst_buf)
{
	/* 写入之前要先判空,缓冲区非空则可以写入;否则忽略掉数据 */
	unsigned int write_pos = (dst_buf->pW + 1) % BUF_SIZE;
	if (write_pos != dst_buf->pR)
	{
		dst_buf->ring_buffer[dst_buf->pW] = c;
		dst_buf->pW = write_pos;
	}
}

   测试程序:第一个问题没有解决,作者此时也不知道怎么判断环形缓冲区接收到了数据。但是作者突发奇想,假如确定中断函数先写数据,过一段时间后在读缓冲区就可以测试了。怎么实现呢?答案是延时,在MCU上电后,PC迅速发送数据给MCU,而MCU延时10秒后在读缓冲区。

int main(void)
{
	OLED_Init();
	myUSART1_Init();
	ring_buffer_init(&buffer);
	
	myUSART1_Write('A');
	
	Delay_s(10);
	
	ring_buffer_read(&RxData1, &buffer);
	ring_buffer_read(&RxData2, &buffer);
	
	OLED_ShowHexNum(1, 1, RxData1, 2);
	OLED_ShowHexNum(2, 1, RxData2, 2);
}

关于文章最开始的问题,作者准备明天再解决,see you tommrow@.@

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: MQTT客户端 for Window是一种在Windows操作系统上运行的MQTT协议的客户端软件。MQTT(Message Queuing Telemetry Transport)是一种轻量级的、开放的、基于发布/订阅的消息传输协议,常用于物联网(IoT)应用中。 MQTT客户端 for Window可以通过与MQTT代理服务器进行通信,实现设备之间的数据传输和通信。它具有以下特点: 1. 轻量级:MQTT协议非常轻量级,可以在带宽较低和计算能力有限的设备上运行,而不会造成过多的资源占用。 2. 简单易用:MQTT客户端 for Window提供了友好的用户界面,使用户可以方便地创建、配置和管理MQTT连接和订阅。 3. 灵活的发布/订阅模式:MQTT客户端 for Window基于发布/订阅模式,使得设备可以订阅感兴趣的主题(Topic),并接收来自其他设备或服务器的相应消息。 4. 可扩展性:MQTT客户端 for Window支持多种设备和平台,可以与各种硬件设备和操作系统兼容,具有很好的可扩展性。 5. 安全性:MQTT客户端 for Window支持MQTT协议的加密和数据传输的安全性,可以通过SSL/TLS协议进行安全通信。 总之,MQTT客户端 for Window是一种在Windows操作系统上运行的MQTT协议的客户端软件,它可以帮助用户轻松实现设备之间的通信和数据传输,非常适用于物联网应用场景。 ### 回答2: MQTT客户端是一种用于连接到MQTT代理服务器的应用程序,可以在Windows操作系统上运行。它允许用户通过MQTT协议与其他设备或应用程序进行实时的、双向的通信。 MQTT客户端可用于多种不同的应用场景,比如物联网(IoT)、传感器网络、远程监控等。它可以与各种设备进行通信,包括传感器、智能家居设备、工业控制器等。 在Windows上使用MQTT客户端,用户可以配置代理服务器的连接参数,如IP地址、端口号、订阅主题等。一旦与代理服务器建立连接,MQTT客户端可以发布(publish)和订阅(subscribe)消息。发布消息表示客户端向代理服务器发送消息,而订阅消息表示客户端接收代理服务器发布的消息。 MQTT客户端可以通过不同的方式实现,例如使用各种编程语言编写的自定义应用程序,或者使用现有的MQTT客户端软件,如MQTT.fx、mosquitto_pub等。这些软件通常提供了直观的用户界面,方便用户进行操作和监控。 总之,MQTT客户端在Windows操作系统上的使用非常灵活和方便,可以帮助用户轻松地构建与其他设备和应用程序之间的实时通信连接。它是物联网和传感器网络等领域中不可或缺的组件,为用户提供了许多有用的功能和服务。 ### 回答3: MQTT客户端是一种用于与MQTT(Message Queuing Telemetry Transport)代理服务器通信的应用程序。在Windows操作系统上,有许多不同的MQTT客户端可供选择,以满足不同用户的需求。 首先,Eclipse Paho是一个非常受欢迎的MQTT客户端,具有跨平台的特性,包括适用于Windows的版本。它提供了丰富的功能,使开发人员能够轻松地与MQTT代理服务器进行通信,包括发布和订阅消息、设置QoS(Quality of Service)级别、处理断开连接、处理消息保留等。 其次,HiveMQ是另一个流行的MQTT客户端,也提供了适用于Windows的版本。HiveMQ具有高度可扩展性和可靠性,并提供诸如消息路由、消息处理、会话管理等高级功能。它还支持一些高级协议和功能,如MQTT 5.0、请求/响应模式等。 此外,有一些其他适用于Windows的MQTT客户端,如MQTT.fx、MQTT Explorer等,它们提供了直观的图形用户界面,用于连接和交互。这些客户端通常支持易于配置的用户界面、消息发布/订阅、主题过滤等基本功能,以及一些高级功能,如SSL/TLS安全连接、多个代理服务器支持等。 无论选择哪个MQTT客户端,用户都可以根据自己的需求和偏好来决定。这些客户端都提供了易于使用的界面和强大的功能,使得使用MQTT协议进行通信变得更加方便和灵活。无论是开发人员还是普通用户,都可以通过这些客户端享受到MQTT技术所带来的便利和强大能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值