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

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” ”。
在这里插入图片描述

相关文章:

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

目录标题 前言1、串口中断接收固定帧头帧尾数据1.1、任务需求1.2、实现思路1.3、程序源码&#xff1a; 2、串口中断接收用定时器来判断帧结束3、串口中断接收数据空闲中断3.1、串口的空闲中断3.2、实现思路3.3、程序源码 4、串口的空闲中断DMA转运4.1、DMA简介4.2、DMA模式4.3、…...

L0、Linux常用命令

一、防火墙&#xff1a; 在 Linux 中&#xff0c;关闭防火墙可以使用不同的命令&#xff0c;这取决于你所使用的防火墙软件。在一些常见的 Linux 发行版中&#xff0c;防火墙可能是 iptables 或 firewalld两种&#xff1a; centos6使用iptables作为默认防火墙&#xff1b;cento…...

Golang实践录:读取toml配置

本文对 toml 文件进行解析。 下载 对于toml格式文件&#xff0c;golang 有很多库可以解释 yaml 文件&#xff0c;如toml、viper。由于 viper 可解析格式较多&#xff0c;本文采用该库。 toml语法规则 toml语法规则在官方中文文档上有说明&#xff0c;这里直接使用。 TOML 是…...

超大规模集成电路设计----基于阵列的可编程逻辑(七)

本文仅供学习&#xff0c;不作任何商业用途&#xff0c;严禁转载。本篇文章绝大部分资料来自中国科学院段成华教授PPT 超大规模集成电路设计----基于阵列的可编程逻辑&#xff08;七&#xff09; 7.1 引言7.1.1.回顾7.1.2. 数字逻辑系列Digital Logic Families7.1.3.从定制到半…...

深入探索FastAPI单元测试:使用TestClient轻松测试你的API

原文&#xff1a;深入探索FastAPI单元测试&#xff1a;使用TestClient轻松测试你的API-51CTO.COM 当使用FastAPI进行单元测试时&#xff0c;一个重要的工具是TestClient类。TestClient类允许我们模拟对FastAPI应用程序的HTTP请求&#xff0c;并测试应用程序的响应。这使我们能…...

基于ssm小型企业办公自动化系统论文

摘 要 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人们提供服务。针对小型企业办公信息管理混乱&#xff0c;出错率高&#xff0c;信息安全…...

CasADi - 最优控制开源 Python/MATLAB 库

系列文章目录 文章目录 系列文章目录前言一、介绍1.1 CasADi 是什么&#xff1f;1.2 帮助与支持1.3 引用 CasADi1.4 阅读本文档 二、获取与安装三、符号框架3.1 符号 SX3.1.1 关于命名空间的说明3.1.2 C 用户注意事项 3.2 DM3.3 符号 MX3.4 SX 和 MX 混合使用3.5 稀疏类3.5.1 获…...

Java中使用String字符串的注意事项

引言 介绍字符串在Java中的重要性和普遍性&#xff0c;以及本文将讨论的注意事项。 1. 字符串是不可变的 解释Java中字符串是不可变的概念&#xff0c;即一旦创建&#xff0c;字符串对象的值就不能被修改。强调在对字符串进行操作时应当创建新的字符串对象而不是修改原有的对…...

离线数仓构建案例一

数据采集 日志数据&#xff08;文件&#xff09;到Kafka 自己写个程序模拟一些用户的行为数据&#xff0c;这些数据存在一个文件夹中。 接着使用flume监控采集这些文件&#xff0c;然后发送给kafka中待消费。 1、flume采集配置文件 监控文件将数据发给kafka的flume配置文件…...

nginx优雅如何优雅的接管【跨域配置】

跨域问题太常见了&#xff0c;这里不做详细赘述。文章主要想说一下&#xff0c;如何统一管理和更好的来管理 跨域配置 跨域的常见配置有两种 后台代码设置和网关设置 1、后台代码设置 以springboot为例代码如下&#xff08;水一下文章长度...&#xff09; Configuration pu…...

远离危险的购买手机的渠道

今年上半年从淘宝特价版上面的官方旗舰店买了一个oppo手机&#xff0c;第一次买我打算不要了&#xff0c;所以就退了回去&#xff0c;过了几天我又觉得还是买一个比较好&#xff0c;所以就又买了一个&#xff0c;型号我绝不说了700-1000z这个价位的手机带个高通骁龙芯片的&…...

外包干了2个多月,技术明显有退步了。。。。。

先说一下自己的情况&#xff0c;本科生&#xff0c;19年通过校招进入武汉某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年国庆&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试…...

【Java项目管理工具】Maven

Maven 文章目录 Maven一、简介二、安装和配置三、GAVP四、IDEA Maven Java Web工程五、插件、命令、生命周期六、依赖配置七、构建配置八、依赖传递与依赖冲突九、Maven工程继承和聚合关系9.1 工程继承关系9.2 工程聚合关系 十、Maven私服10.1 Nexus下载安装10.2 Nexus上的各种…...

solidity案例详解(六)服务评价合约

有服务提供商和用户两类实体&#xff0c;其中服务提供商部署合约&#xff0c;默认诚信为true&#xff0c;用户负责使用智能合约接受服务及评价&#xff0c;服务提供商的评价信息存储在一个映射中&#xff0c;可以根据服务提 供商的地址来查找评价信息。用户评价信息&#xff0c…...

使用kubeadm搭建高可用的K8s集群

文章目录 1. 安装要求2. 准备环境3. 所有master节点部署keepalived3.1 安装相关包和keepalived3.2配置master节点3.3 启动和检查 4. 部署haproxy4.1 安装4.2 配置4.3 启动和检查 5. 所有节点安装Docker/kubeadm/kubelet5.1 安装Docker5.2 添加阿里云YUM软件源5.3 安装kubeadm&a…...

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…...

c++函数模板STL详解

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

Java利用UDP实现简单群聊

一、创建新项目 首先新建一个新的项目&#xff0c;并按如下操作 二、实现代码 界面ChatFrame类 package 群聊; import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.net.InetAddress; public abstract class ChatFrame extends JFrame { p…...

fastapi.templating与HTMLResponse

要声明一个模板对象&#xff0c;应将存储html模板的文件夹作为参数提供。在当前工作目录中&#xff0c;我们将创建一个 “templates “目录。 templates Jinja2Templates(directory“templates”) 我们现在要把这个页面的HTML代码渲染成HTMLResponse。让我们修改一下hello()函…...

当初为什么选择计算机这类的行业?

CSDN给了这么一个话题&#xff1a; 还记得当初自己为什么选择计算机&#xff1f; 当初你问我为什么选择计算机&#xff0c;我笑着回答&#xff1a;“因为我梦想成为神奇的码农&#xff01;我想像编织魔法一样编写程序&#xff0c;创造出炫酷的虚拟世界&#xff01;”谁知道&…...

label-studio的使用教程(导入本地路径)

文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...

Spring Boot 实现流式响应(兼容 2.7.x)

在实际开发中&#xff0c;我们可能会遇到一些流式数据处理的场景&#xff0c;比如接收来自上游接口的 Server-Sent Events&#xff08;SSE&#xff09; 或 流式 JSON 内容&#xff0c;并将其原样中转给前端页面或客户端。这种情况下&#xff0c;传统的 RestTemplate 缓存机制会…...

边缘计算医疗风险自查APP开发方案

核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八

现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet&#xff0c;点击确认后如下提示 最终上报fail 解决方法 内核升级导致&#xff0c;需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...

LeetCode - 394. 字符串解码

题目 394. 字符串解码 - 力扣&#xff08;LeetCode&#xff09; 思路 使用两个栈&#xff1a;一个存储重复次数&#xff0c;一个存储字符串 遍历输入字符串&#xff1a; 数字处理&#xff1a;遇到数字时&#xff0c;累积计算重复次数左括号处理&#xff1a;保存当前状态&a…...

家政维修平台实战20:权限设计

目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系&#xff0c;主要是分成几个表&#xff0c;用户表我们是记录用户的基础信息&#xff0c;包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题&#xff0c;不同的角色&#xf…...

BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践

6月5日&#xff0c;2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席&#xff0c;并作《智能体在安全领域的应用实践》主题演讲&#xff0c;分享了在智能体在安全领域的突破性实践。他指出&#xff0c;百度通过将安全能力…...

图表类系列各种样式PPT模版分享

图标图表系列PPT模版&#xff0c;柱状图PPT模版&#xff0c;线状图PPT模版&#xff0c;折线图PPT模版&#xff0c;饼状图PPT模版&#xff0c;雷达图PPT模版&#xff0c;树状图PPT模版 图表类系列各种样式PPT模版分享&#xff1a;图表系列PPT模板https://pan.quark.cn/s/20d40aa…...

用机器学习破解新能源领域的“弃风”难题

音乐发烧友深有体会&#xff0c;玩音乐的本质就是玩电网。火电声音偏暖&#xff0c;水电偏冷&#xff0c;风电偏空旷。至于太阳能发的电&#xff0c;则略显朦胧和单薄。 不知你是否有感觉&#xff0c;近两年家里的音响声音越来越冷&#xff0c;听起来越来越单薄&#xff1f; —…...