Stm32_串口的帧(不定长)数据接收

目录标题

  • 前言
  • 1、串口中断接收固定帧头帧尾数据
    • 1.1、任务需求
    • 1.2、实现思路
    • 1.3、程序源码:
  • 2、串口中断接收+用定时器来判断帧结束
  • 3、串口中断接收数据+空闲中断
    • 3.1、串口的空闲中断
    • 3.2、实现思路
    • 3.3、程序源码
  • 4、串口的空闲中断+DMA转运
    • 4.1、DMA简介
    • 4.2、DMA模式
    • 4.3、DMA资源
    • 4.4、DMA主要特征
    • 4.5、实现思路
    • 4.6程序源码:
  • 报错及解决:

前言

使用串口传输数据时,因为串口是异步通信协议,所以我们需要去判断哪是一帧完整的数据,并进行数据的处理。


接收不定长的数据以下几个主要有以下方法:

  • 加固定的帧头和帧尾
  • 串口中断接收+用定时器来判断帧结束
  • 串口中断接收+利用串口空闲中断来判断帧结束

1、串口中断接收固定帧头帧尾数据

1.1、任务需求

1、PC端通过串口1发送给单片机一个有固定帧头帧尾的数据包。
2、单片机利用串口中断接收数据并判断帧头帧尾。
3、当识别到对应的帧头帧尾时,将接收到的数据再发送给PC端。
4、清除接收缓存。

1.2、实现思路

  • 1、使能相关时钟
    使能相关GPIO所在APB2总线的时钟
    使能串口所在APB2总线的时钟

  • 2、初始化串口
    配置数据位个数、停止位个数、校验位、波特率等

  • 3、初始化GPIO
    配置RX、TX对应GPIO口。

  • 4、初始化串口中断
    配置中断通道,中断优先级等

  • 4、使能串口中断

  • 5、使能串口

  • 6、编写中断服务程序:

    • ①判断接收到的数据是否是帧头
    • ②若是帧头则将数据写入到缓冲区;若不是则无视,等待下一个数据。
    • ③当有帧头后,不断在后面接收到的数据中找帧尾。找到了则说明这一帧数据接收完成了。
    • ④将这一帧数据再通过printf发送回PC端。
    • ⑤清楚缓冲区数据,将索引清零。

1.3、程序源码:

usart.h

#ifndef __SERIAL_H__
#define __SERIAL_H__#include "stm32f10x.h"                  // Device header
#include <stdarg.h>
#include "stdio.h"
#include "string.h"#define USART1_ENABLE  1          //使能串口1      
#define USART1_BAUDRATE 9600      //串口1波特率
#define USART1_INTERRUPT_ENABLE 1  //使能串口1中断#define RECEIVE_BUF_MAX_SIZE 100  //单次最大接收字节数typedef struct{uint8_t Buffer[RECEIVE_BUF_MAX_SIZE];uint16_t Lenth;
}usart_data;
void Serial_Init(void);//串口初始化
#endif

usart.c

void Serial_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;NVIC_InitTypeDef NVIC_Structure;#if USART1_ENABLE  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//串口1在APB2总线上,串口2、3在APB1总线上RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;     //复用推挽输出GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStructure);GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;     //读。上拉输入GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStructure);USART_InitStructure.USART_BaudRate= USART1_BAUDRATE;USART_InitStructure.USART_HardwareFlowControl= USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode= USART_Mode_Tx|USART_Mode_Rx;USART_InitStructure.USART_Parity= USART_Parity_No;USART_InitStructure.USART_StopBits= USART_StopBits_1;USART_InitStructure.USART_WordLength= USART_WordLength_8b;USART_Init(USART1,&USART_InitStructure);
#if USART1_INTERRUPT_ENABLE	USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//使能串口1接受中断NVIC_Structure.NVIC_IRQChannel=USART1_IRQn;NVIC_Structure.NVIC_IRQChannelCmd=ENABLE;NVIC_Structure.NVIC_IRQChannelPreemptionPriority=1;//抢占优先级NVIC_Structure.NVIC_IRQChannelSubPriority=3;//响应优先级NVIC_Init(&NVIC_Structure);
#endifUSART_Cmd(USART1,ENABLE);
#endif
}int fputc(int ch,FILE *f)        //重构定向,printf直接打印到串口1
{USART_SendData(USART1,ch);	while(USART_GetFlagStatus(USARTx,USART_FLAG_TXE)==RESET);return ch;
}//串口一中断处理函数
usart_data usart1_rxdata;uint16_t data;
void USART1_IRQHandler(void)
{if(USART_GetITStatus(USART1,USART_IT_RXNE)==SET) //若发生串口中断{usart1_rxdata.Buffer[usart1_rxdata.Lenth++] = USART_ReceiveData(USART1);if(usart1_rxdata.Buffer[0]!='h') //判断帧头usart1_rxdata.Lenth =0;if((usart1_rxdata.Buffer[0]=='h')&&(usart1_rxdata.Buffer[usart1_rxdata.Lenth-1]=='e'))//判断帧头帧尾{printf("rx_data:%s\r\n",usart1_rxdata.Buffer);//将接收到的一帧数据再发送回去,做验证memset(usart1_rxdata.Buffer,'\0',usart1_rxdata.Lenth);usart1_rxdata.Lenth = 0;}	USART_ClearITPendingBit(USART1,USART_IT_RXNE);//清中断标志位}
}

2、串口中断接收+用定时器来判断帧结束

暂时不写

3、串口中断接收数据+空闲中断

3.1、串口的空闲中断

空闲中断USART_IT_IDLE,俗称帧中断,即第一帧数据接收完毕到第二帧数据开始接收期间存在一个空闲状态(就是没数据接收的状态),检测到此空闲状态后即执行中断程序。进入中断程序即意味着已经接收到一组完整帧数据,仅需及时对数据处理或将数据转移出缓冲区即可。
相较于上面的利用固定帧头和帧尾来判断完整数据帧,这种方法更为使用,通过利用空闲中断,对于没有固定帧头和帧尾的数据我们也能准确接收了。

3.2、实现思路

  • 1、使能相关时钟
    使能相关GPIO所在APB2总线的时钟
    使能串口所在APB2总线的时钟
  • 2、初始化串口
    配置数据位个数、停止位个数、校验位、波特率等
  • 3、初始化GPIO
    配置RX、TX对应GPIO口。
  • 4、初始化串口中断
    配置中断通道,中断优先级等
  • 4、使能串口中断
  • 5、使能串口的空闲中断
  • 5、使能串口
  • 6、编写中断服务程序:
    • ①判断中断类型:串口中断、串口的空闲中断
    • ②若是串口中断,就将接收的数据存入缓冲区。然后清除中断标志
    • ③若是串口的空闲中断,则说明这一帧数据接收完了后面就是数据处理了。
    • ④数据处理完后,就将数据缓冲区清除,将索引号清零。
    • ⑤清除串口空闲中断标志位(通过读串口的SR和DR寄存器)

3.3、程序源码

usart.h

#ifndef __SERIAL_H__
#define __SERIAL_H__#include "stm32f10x.h"                  // Device header
#include <stdarg.h>
#include "stdio.h"
#include "string.h"#define USART1_ENABLE  1                
#define USART1_BAUDRATE 9600
#define USART1_INTERRUPT_ENABLE 1
#define USART1_IDLE_INTERRUPT_ENABLE 1#define RECEIVE_BUF_MAX_SIZE 100  //单次最大接收字节数typedef struct{uint8_t Buffer[RECEIVE_BUF_MAX_SIZE];uint16_t Lenth;
}usart_data;void Serial_Init(void);//串口初始化
#endif

usart.c

#include "Serial.h"
void Serial_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;NVIC_InitTypeDef NVIC_Structure;#if USART1_ENABLE  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//串口1在APB2总线上,串口2、3在APB1总线上RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;     //复用推挽输出GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStructure);GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;     //读。上拉输入GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStructure);USART_InitStructure.USART_BaudRate= USART1_BAUDRATE;USART_InitStructure.USART_HardwareFlowControl= USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode= USART_Mode_Tx|USART_Mode_Rx;USART_InitStructure.USART_Parity= USART_Parity_No;USART_InitStructure.USART_StopBits= USART_StopBits_1;USART_InitStructure.USART_WordLength= USART_WordLength_8b;USART_Init(USART1,&USART_InitStructure);#if USART1_INTERRUPT_ENABLE	USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//使能串口1接受中断NVIC_Structure.NVIC_IRQChannel=USART1_IRQn;NVIC_Structure.NVIC_IRQChannelCmd=ENABLE;NVIC_Structure.NVIC_IRQChannelPreemptionPriority=1;//抢占优先级NVIC_Structure.NVIC_IRQChannelSubPriority=3;//响应优先级NVIC_Init(&NVIC_Structure);#if USART1_IDLE_INTERRUPT_ENABLE  USART_ITConfig(USART1,USART_IT_IDLE,ENABLE);//使能串口1的空闲中断
#endif#endifUSART_Cmd(USART1,ENABLE);
#endif
}
//=================================================================
int fputc(int ch,FILE *f)        //重构定向,printf直接打印到串口1
{Serial_Sendbyte(USART1,ch);return ch;
}//串口一中断
usart_data usart1_rxdata;uint16_t data;
void USART1_IRQHandler(void)
{uint16_t clear;if(USART_GetITStatus(USART1,USART_IT_RXNE)==SET){usart1_rxdata.Buffer[usart1_rxdata.Lenth++] = USART_ReceiveData(USART1);if(usart1_rxdata.Lenth>RECEIVE_BUF_MAX_SIZE)usart1_rxdata.Lenth =0;USART_ClearITPendingBit(USART1,USART_IT_RXNE);}else if(USART_GetITStatus(USART1,USART_IT_IDLE)==SET)//串口空闲中断{printf("rx_data:%s\r\n",usart1_rxdata.Buffer);memset(usart1_rxdata.Buffer,'\0',usart1_rxdata.Lenth);usart1_rxdata.Lenth = 0;clear = USART1->SR;clear = USART1->DR;}}

4、串口的空闲中断+DMA转运

4.1、DMA简介

直接存储器访问(Direct Memory Access),简称DMA。DMA是CPU一个用于数据从一个地址空间到另一地址空间“搬运”(拷贝)的组件,数据拷贝过程不需CPU干预,数据拷贝结束则通知CPU处理。因此,大量数据拷贝时,使用DMA可以释放CPU资源。

4.2、DMA模式

DMA数据拷贝过程,典型的有:
(1)内存—>内存,内存间拷贝;
(2)外设—>内存,如uart、spi、i2c等总线接收数据过程;
(3)内存—>外设,如uart、spi、i2c等总线发送数据过程。

4.3、DMA资源

STM32F1系列的MCU有两个DMA控制器(DMA2只存在于大容量产品中),DMA1有7个通道,DMA2有5个通道,每个通道专门用来管理来自于一个或者多个外设对存储器的访问请求。还有一个仲裁器来协调各个DMA请求的优先权。
在这里插入图片描述
在这里插入图片描述

4.4、DMA主要特征

  • 每个通道都直接连接专用的硬件 DMA 请求,每个通道都同样支持软件触发。这些功能通过软件来配置。
  • 在同一个 DMA 模块上,多个请求间的优先权可以通过软件编程设置(共有四级:很高、高、中等和低),优先权设置相等时由硬件决定(请求 0 优先于请求 1 ,依此类推,可以参考STM32数据手册)。
  • 独立的源和目标数据区的传输宽度(字节、半字、全字),模拟打包和拆包的过程。源和目标地址必须按数据传输宽度对齐。
  • 支持循环的缓冲器管理(会把原来的数据覆盖)。
  • 每个通道都有 3 个事件标志(DMA 半传输, DMA 传输完成和 DMA 传输出错),这 3 个事件标志逻辑或成为一个单独的中断请求。
  • 存储器和存储器间的传输(仅 DMA2 可以)。
  • 外设和存储器、存储器和外设之间的传输
  • 闪存、SRAM 、外设的 SRAM 、APB1 、APB2 和 AHB 外设均可作为访问的源和目标。
  • 可编程的数据传输数目:最大为65535。

高波特率传输场景下,串口非常有必要使用DMA。

4.5、实现思路

  • 1、使能相关时钟
    使能相关GPIO所在APB2总线的时钟
    使能串口所在APB2总线的时钟
    使能DMA1时钟
  • 2、初始化串口
    配置数据位个数、停止位个数、校验位、波特率等
  • 3、初始化GPIO
    配置RX、TX对应GPIO口。
  • 4、初始化串口空闲中断
    配置中断通道,中断优先级等
  • 5、使能串口的空闲中断
  • 6、配置初始化DMA1。
  • 7、使能串口1的DMA接收;使能DMA1的TX通道(DMA1_Channel4)
  • 8、使能串口
  • 9、编写中断服务程序:
    • ①判断中断类型:串口的空闲中断
    • ②清除串口空闲中断标志位(通过读串口的SR和DR寄存器)
    • ③关闭DMA通道
    • ④进行数据处理(置标志位等)
    • ⑤重新设置 DMA 传输数据长度
    • ⑥使能DMA通道

4.6程序源码:

usart.h

#ifndef __SERIAL_H__
#define __SERIAL_H__#include "stm32f10x.h"                  // Device header
#include <stdarg.h>
#include "stdio.h"
#include "string.h"#define USART1_ENABLE  1                
#define USART1_BAUDRATE 9600
#define USART1_INTERRUPT_ENABLE 1
#define USART1_IDLE_INTERRUPT_ENABLE 1
#define USART1_DMA_TX_ENABLE 0
#define USART1_DMA_RX_ENABLE 1#define USART_BUF_MAX_SIZE 100  //单次最大接收字节数typedef struct{uint8_t Buffer[USART_BUF_MAX_SIZE];uint16_t Lenth;
}usart_data;void Serial_Init(void);//串口初始化
#endif

usart.c

#include "Serial.h"usart_data usart1_rxdata;
usart_data usart_txdata;void Serial_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;NVIC_InitTypeDef NVIC_Structure;DMA_InitTypeDef DMA_InitStructure;
#if USART1_ENABLE  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//串口1在APB2总线上,串口2、3在APB1总线上RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;     //复用推挽输出GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStructure);GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;     //读。上拉输入GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStructure);USART_InitStructure.USART_BaudRate= USART1_BAUDRATE;USART_InitStructure.USART_HardwareFlowControl= USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode= USART_Mode_Tx|USART_Mode_Rx;USART_InitStructure.USART_Parity= USART_Parity_No;USART_InitStructure.USART_StopBits= USART_StopBits_1;USART_InitStructure.USART_WordLength= USART_WordLength_8b;USART_Init(USART1,&USART_InitStructure);#if USART1_INTERRUPT_ENABLE	|USART1_IDLE_INTERRUPT_ENABLENVIC_Structure.NVIC_IRQChannel=USART1_IRQn;NVIC_Structure.NVIC_IRQChannelCmd=ENABLE;NVIC_Structure.NVIC_IRQChannelPreemptionPriority=1;//抢占优先级NVIC_Structure.NVIC_IRQChannelSubPriority=3;//响应优先级NVIC_Init(&NVIC_Structure);
#if USART1_INTERRUPT_ENABLEUSART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//使能串口1接受中断
#endif #if USART1_IDLE_INTERRUPT_ENABLE  USART_ITConfig(USART1,USART_IT_IDLE,ENABLE);//使能串口1的空闲中断
#endif#endif#if USART1_DMA_TX_ENABLE/*Usart1_TX_DMA_config,从存储区到USART1->DR*/RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);DMA_DeInit(DMA1_Channel4);DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(USART1->DR);   //外设站点起始地址DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设站点地址不自增DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)usart_txdata.Buffer;//存储器站点起始地址DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //存储器站点自增DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;    //存储器站点到外设站点   //传输方向DMA_InitStructure.DMA_BufferSize = USART_BUF_MAX_SIZE;//缓冲区大小,传输计数器DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;  //普通模式,不循环DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  //失能(不是存储器到存储器)DMA_InitStructure.DMA_Priority = DMA_Priority_High; //优先级DMA_Init(DMA1_Channel4, &DMA_InitStructure);USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE); //使能串口1的DMA发送DMA_Cmd(DMA1_Channel4,ENABLE); //使能DMA1的TX通道(DMA1_Channel4)#endif
#if USART1_DMA_RX_ENABLE/*Usart1_RX_DMA_config,从USART1->DR到存储区*/RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);DMA_DeInit(DMA1_Channel5);DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(USART1->DR);   //外设站点起始地址DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设站点地址不自增DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)usart1_rxdata.Buffer;//存储器站点起始地址DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //存储器站点自增DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;    //外设站点到存储器站点   //传输方向DMA_InitStructure.DMA_BufferSize = USART_BUF_MAX_SIZE;//缓冲区大小,传输计数器DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;  //普通模式,不循环DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  //失能(不是存储器到存储器)DMA_InitStructure.DMA_Priority = DMA_Priority_High; //优先级DMA_Init(DMA1_Channel5, &DMA_InitStructure);USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE); //使能串口1的DMA接收DMA_Cmd(DMA1_Channel5,ENABLE); //使能DMA1的TX通道(DMA1_Channel4)#endifUSART_Cmd(USART1,ENABLE);
#endif
}//串口一中断
void USART1_IRQHandler(void)
{uint16_t clear;if(USART_GetITStatus(USART1,USART_IT_IDLE)==SET){clear = USART1->SR;clear = USART1->DR;DMA_Cmd(DMA1_Channel5, DISABLE);  // 关闭 DMA 通道usart1_rxdata.Lenth = sizeof(usart1_rxdata.Buffer) - DMA_GetCurrDataCounter(DMA1_Channel5);  // 计算接收到的数据长度printf("rx_data:%s\r\n",usart1_rxdata.Buffer);memset(usart1_rxdata.Buffer,'\0',usart1_rxdata.Lenth);DMA_SetCurrDataCounter(DMA1_Channel5, sizeof(usart1_rxdata.Buffer));  // 重新设置 DMA 传输数据长度DMA_Cmd(DMA1_Channel5, ENABLE);  // 使能 DMA 通道}}

报错及解决:

int fputc(int ch,FILE *f)        //重构定向,printf直接打印到串口1
{USART_SendData(USART1,ch);	while(USART_GetFlagStatus(USARTx,USART_FLAG_TXE)==RESET);return ch;
}

我们在使用上面的程序进行printf重构定向时,需要注意以下两点:
1、在“魔法棒”—>"Target"中,将”USB Micro LIB“勾选上,否则会出现不能正常打印甚至单片机直接进入硬件错误中断宕机的情况。
在这里插入图片描述

2、需要添加头文件 #include “stdio.h”,否则会出现报错“error: unknown type name “FILE” ”。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/211868.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于ssm人事管理信息系统论文

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本人事管理信息系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据信息…

c++函数模板STL详解

函数模板 函数模板语法 所谓函数模板&#xff0c;实际上是建立一个通用函数&#xff0c;其函数类型和形参类型不具体指定&#xff0c;用一个虚拟的类型来代表。这个通用函数就称为函数模板。 凡是函数体相同的函数都可以用这个模板来代替&#xff0c;不必定义多个函数&#xf…

外包干了3个月,技术倒退2年。。。

先说情况&#xff0c;大专毕业&#xff0c;18年通过校招进入湖南某软件公司&#xff0c;干了接近6年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试&#xf…

轻量封装WebGPU渲染系统示例<40>- 多层材质的Mask混合(源码)

当前示例源码github地址: https://github.com/vilyLei/voxwebgpu/blob/feature/rendering/src/voxgpu/sample/MaskTextureEffect.ts 当前示例运行效果: 两层材质效果: 三层材质效果: 此示例基于此渲染系统实现&#xff0c;当前示例TypeScript源码如下&#xff1a; export c…

rename--统一的PRF

基本概念 将ARF/PRF进行合并&#xff0c;合同之后的不见&#xff0c;称之为统一的PRF(Physical Register File);存储的是speculative的&#xff0c;以及正确的&#xff08;retire&#xff09;寄存器值&#xff1b; 使用free list&#xff0c;存储PRF中&#xff0c;哪些寄存器是…

布隆过滤器及其在Java中的实际应用

前言 布隆过滤器一直是面试中的重点&#xff0c;本篇文章将深入探讨Java中的布隆过滤器的底层思想&#xff0c;包括它的工作原理、优缺点等。同时&#xff0c;我们将结合一个小实际案例&#xff0c;来给大家展示布隆过滤器在解决实际问题中的应用。 布隆过滤器简单介绍 在数…

一对一互相聊天

服务端 package 一对一用户;import java.awt.BorderLayout; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.Vector;…

【自动化测试】pytest 用例执行中print日志实时输出

author: jwensh date: 20231130 pycharm 中 pytest 用例执行中 print 日志 standout 实时命令行输出 使用场景 在进行 websocket 接口进行测试的时候&#xff0c;希望有一个 case 是一直执行并接受接口返回的数据 def on_message(ws, message):message json.loads(message)…

计算UDP报文CRC校验的总结

概述 因公司项目需求&#xff0c;遇到需要发送带UDP/IP头数据包的功能&#xff0c;经过多次尝试顺利完成&#xff0c;博文记录以备忘。 环境信息 操作系统 ARM64平台的中标麒麟Kylin V10 工具 tcpdump、wireshark、vscode 原理 请查看大佬的博文 UDP伪包头定义&#x…

2023年第十六届山东省职业院校技能大赛中职组“网络安全”赛项竞赛正式试题

第十六届山东省职业院校技能大赛中职组 “网络安全”赛项竞赛试题 目录 一、竞赛时间 二、竞赛阶段 三、竞赛任务书内容 &#xff08;一&#xff09;拓扑图 &#xff08;二&#xff09;A模块基础设施设置/安全加固&#xff08;200分&#xff09; &#xff08;三&#xf…

Docker安装Elasticsearch以及ik分词器

Elasticsearch 是一个分布式、RESTful 风格的搜索和数据分析引擎&#xff0c;能够解决不断涌现出的各种用例。作为 Elastic Stack 的核心&#xff0c;Elasticsearch 会集中存储您的数据&#xff0c;让您飞快完成搜索&#xff0c;微调相关性&#xff0c;进行强大的分析&#xff…

C#图像处理OpenCV开发指南(CVStar,07)——通用滤波(Filter2D)的实例代码

1 函数定义 void Filter2D (Mat src, Mat dst, int ddepth, InputArray kernel, Point anchor Point(-1,-1), double delta 0, int borderType BORDER_DEFAULT ) 1.1 原型 #include <opencv2/imgproc.hpp> Convolves an image wit…

【msg_msg】corCTF2021-msgmsg 套题

前言 该套题共两题&#xff0c;一道简单模式 fire_of_salvation&#xff0c;一道困难模式 wall_of_perdition&#xff0c;都是关于 msg_msg 的利用的。这题跟之前的 TPCTF2023 core 的很像&#xff08;应该是 TPCTF2023 core 跟他很像&#xff0c;bushi&#xff09;。 其中 f…

Elasticsearch:什么是大语言模型(LLM)?

大语言模型定义 大语言模型 (LLM) 是一种深度学习算法&#xff0c;可以执行各种自然语言处理 (natural language processing - NLP) 任务。 大型语言模型使用 Transformer 模型&#xff0c;并使用大量数据集进行训练 —— 因此规模很大。 这使他们能够识别、翻译、预测或生成文…

Linux 存储管理

内容概述 磁盘结构分区类型管理分区管理文件系统挂载设备管理swap空间&#xff08;用来缓解内存空间不足情况&#xff09;RAID 管理LVM管理LVM快照 1 磁盘结构 1.1 设备文件 块设备文件&#xff1a;数据的访问单位是块Block&#xff0c;一个块的IO 字符设备文件&#xff1a…

springboot 整合security并且配置swagger 时,无法访问/doc.html

参考文档&#xff1a; https://blog.csdn.net/qq_43340419/article/details/120312937解决方案&#xff1a;需要在WebSecurityConfig 中 配置允许匿名访问的路径 .antMatchers("/v2/api-docs","/swagger-resources/configuration/ui","/swagger-res…

备忘录模式 rust和java的实现

文章目录 备忘录模式介绍实现javarustrust仓库 备忘录模式 备忘录&#xff08;Memento&#xff09;模式的定义&#xff1a;在不破坏封装性的前提下&#xff0c;捕获一个对象的内部状态&#xff0c;并在该对象之外保存这个状态&#xff0c;以便以后当需要时能将该对象恢复到原先…

设计模式——七大设计原则

设计模式——七大设计原则 1、单一职责原则&#xff08;SRP&#xff09;2、开放封闭原则&#xff08;OCP&#xff09;3、依赖倒转原则&#xff08;DIP&#xff09;4、里氏替换原则 (LSP)5、接口隔离原则 (ISP)6、合成/聚合复用原则 (CARP)7、迪米特法则 (LoD) 了解 设计模式 的…

Qt/C++音视频开发57-切换音视频轨道/切换节目流/分别切换音频视频轨道

一、前言 对各种音视频文件格式的支持&#xff0c;是一个播放器的基础功能。一般的音视频文件只有1路流&#xff0c;比如音频文件只有1路音频流&#xff0c;视频文件只有1路音频1路视频流&#xff0c;实践过程中发现&#xff0c;还有一种ts格式的文件&#xff0c;可能有多路流…

Python包管理器PIP用法大全

pip是Python的包管理器&#xff0c;用于安装和管理Python包。以下是一些常用的基本的pip命令&#xff0c;分享给大家&#xff0c;希望对大家使用pip有所帮助。 文章目录 pip installpip uninstallpip listpip searchpip downloadpip configpip freezepip checkpip wheelpip ha…