18:(标准库)DMA二:DMA+串口收发数据

DMA+串口收发数据

  • 1、DMA+串口发送数据
  • 2、DMA中断+串口接收定长数据包
  • 3、串口空闲中断+DMA接收不定长数据包

1、DMA+串口发送数据

在这里插入图片描述
当串口的波特率大于115200时,可以通过DMA1进行数据搬运,以防止数据的丢失。如上图所示:UART1的Tx发送请求使用DMA1的通道4,UART1的Rx接收数据请求使用DMA1的通道5。
①串口发送时:当UART1的发送数据寄存器TDR中没有数据时,就会向DMA1的通道4申请数据搬运,DMA1将缓冲区的数据搬运到TDR数据寄存器中,然后串口将数据发送出去。

②串口接收时:当UART1的接收数据寄存器RDR中有数据时,就会向DMA1的通道5申请数据搬运,DMA1将数据从RDR寄存器中搬运到缓冲区中。

【注意】数据的搬运和数据的发送的过程都不需要CPU参与,CPU只参与串口UART1和DMA1通道1的配置
①UART.c文件的代码如下:

#include "UART.h"

uint8_t Buff[Buffer_Size];//定义数据缓冲区
/**
 * 串口1的初始化函数
 */
void UART1_Init(void)
{
    /* 开启串口的UART1的时钟 */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

    /* 开启串口的GPIO的时钟 */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    /* 配置串口1的引脚 */
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;// 复用推挽输出
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;// 浮空输入
    GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* 配置串口1的模式 */
    USART_InitTypeDef USART_InitStruct;
    USART_InitStruct.USART_BaudRate = 115200;
    USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;// 不使用硬件流控制
    USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;// 收发模式
    USART_InitStruct.USART_Parity = USART_Parity_No;// 无奇偶校验位
    USART_InitStruct.USART_StopBits = USART_StopBits_1;// 1个停止位
    USART_InitStruct.USART_WordLength = USART_WordLength_8b;// 8个数据位
    USART_Init(USART1, &USART_InitStruct);
    
    /* 使能串口DMA发送请求 */
    USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);
    
    /* 使能串口1 */
    USART_Cmd(USART1, ENABLE);
}

②UART.h文件的代码如下:

#ifndef __UART_H
#define __UART_H
#include "stm32f10x.h"
#include "stdio.h"

#define Buffer_Size 256
extern uint8_t Buff[Buffer_Size];//定义数据缓冲区

void UART1_Init(void);

#endif

③MyDMA.c文件的代码如下:

#include "MyDMA.h"
#include "UART.h"
/**
 * DMA1的通道4的初始化 
 */
void DMA1_Init(void)
{
    /* 1、使能DMA1的时钟 */
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

    /* 2、配置DMA1的通道1 */
    DMA_InitTypeDef DMA_InitStruct;
	DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&(USART1->DR);    //“外设站点”的起始地址
	DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//数据宽度,8位
	DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;       //外设站点地址是否自增,这里选择不自增,因为搬运到数据寄存器TDR中
	
	DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)Buff;                 //“内存站点”起始地址
	DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;        //数据宽度,8位
	DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;                //目的站点地址是否自增,自增
	
	DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralDST;                     //搬运方向的选择(目的地选择),这里选择内存站点--->外设站点:DMA_DIR_PeripheralDST
	DMA_InitStruct.DMA_BufferSize = 0;                                  //传输计数器的大小,代表搬运数据的个数,先置为0
	DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;                          //是否自动重装,这里选择不自动重装
	DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;                           //是否软件触发,这里选择不是,由硬件触发
	DMA_InitStruct.DMA_Priority = DMA_Priority_Medium;                  //优先级,这里选择中等
	DMA_Init(DMA1_Channel4,&DMA_InitStruct);                            //配置DMA1的通道4
	
//	DMA_Cmd(DMA1_Channel4,ENABLE);                                      //使能DMA1的通道4
	DMA_Cmd(DMA1_Channel4,DISABLE);                                     //先失能DMA1的通道4
}
   
/**
 * DMA1开启搬运函数
 */
void UART1_DMA1_Transport(uint16_t DataNumber)
{
    /* 1、失能DMA1 */
    DMA_Cmd(DMA1_Channel4,DISABLE); 
    
    /* 2、先设置传输计数器的计数值 */
    DMA_SetCurrDataCounter(DMA1_Channel4, DataNumber);
    
    /* 3、使能DMA1 */
    DMA_Cmd(DMA1_Channel4,ENABLE);   
    
    /* 4、等待搬运完成 */
    while(!DMA_GetFlagStatus(DMA1_FLAG_TC4));   //等待DMA1通道4全部搬运完成
	DMA_ClearFlag(DMA1_FLAG_TC4);               //手动清除标志位 
}

④MyDMA.h文件的代码如下:

#ifndef __MyDMA_H
#define __MyDMA_H
#include "stm32f10x.h"

void DMA1_Init(void);
void UART1_DMA1_Transport(uint16_t DataNumber);

#endif

⑤主函数main.c文件的代码如下:

#include "stm32f10x.h"                 
#include "Delay.h"
#include "UART.h"
#include "MyDMA.h"

#define DataNumber 10 //定义需要发送的数据个数

int main(void)
{
    for(uint8_t i = 0; i<DataNumber; i++)//先向缓冲区里面填入数据
    {
        Buff[i] = i;
    }
    
    UART1_Init();
    DMA1_Init();
    UART1_DMA1_Transport(DataNumber);     //开始搬运数据 
    
	while(1)
	{ 
        
	}
}

在这里插入图片描述

2、DMA中断+串口接收定长数据包

①UART.c文件的代码如下:

#include "UART.h"

uint8_t Buff[Buffer_Size];  //定义数据缓冲区
uint16_t Length = 10;       //定义定长数据包长度
uint8_t Flag = 0;           //传输完成标志位
/**
 * 串口1的初始化函数
 */
void UART1_Init(void)
{
    /* 开启串口的UART1的时钟 */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

    /* 开启串口的GPIO的时钟 */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    /* 配置串口1的引脚 */
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;        // 复用推挽输出
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;  // 浮空输入
    GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* 配置串口1的模式 */
    USART_InitTypeDef USART_InitStruct;
    USART_InitStruct.USART_BaudRate = 115200;
    USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;// 不使用硬件流控制
    USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;                // 收发模式
    USART_InitStruct.USART_Parity = USART_Parity_No;                            // 无奇偶校验位
    USART_InitStruct.USART_StopBits = USART_StopBits_1;                         // 1个停止位
    USART_InitStruct.USART_WordLength = USART_WordLength_8b;                    // 8个数据位
    USART_Init(USART1, &USART_InitStruct);
    
    /* 使能串口DMARx接收请求 */
    USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);
    
    /* 使能串口1 */
    USART_Cmd(USART1, ENABLE);
}

/**
 * 串口发送多个字节的数据
 */
void USART_SendArray(uint8_t *array, uint16_t len)
{
    /* 发送一组数据 */
    for (uint16_t i = 0; i < len; i++)
    {
        USART_SendChar(array[i]);
    }
}

②UART.h文件的代码如下:

#ifndef __UART_H
#define __UART_H
#include "stm32f10x.h"
#include "stdio.h"

#define Buffer_Size 256
extern uint8_t Buff[Buffer_Size];//定义数据缓冲区
extern uint16_t Length;
extern uint8_t Flag;

void UART1_Init(void);
void USART_SendArray(uint8_t *array, uint16_t len);

#endif

③MyDMA.c文件的代码如下:

#include "MyDMA.h"
#include "UART.h"
/**
 * DMA1通道5的初始化
 */

void DMA1_Init(void)
{
    /* 1、使能DMA1的时钟 */
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

    /* 2、配置DMA1的通道1 */
    DMA_InitTypeDef DMA_InitStruct;
	DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&(USART1->DR);    //外设站点的起始地址
	DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//数据宽度,8位
	DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;       //外设站点地址是否自增,这里选择不自增,因为搬运到数据寄存器TDR中
	
	DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)Buff;                 //内存站点起始地址
	DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;        //数据宽度,8位
	DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;                //目的站点地址是否自增,自增
	
	DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;                     //搬运方向的选择(目的地选择),这里选择外设站点--->内存站点:DMA_DIR_PeripheralSRC
	DMA_InitStruct.DMA_BufferSize = Length;                             //传输计数器的大小,代表搬运数据的个数
	DMA_InitStruct.DMA_Mode = DMA_Mode_Circular;                        //是否自动重装,这里选择自动重装
	DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;                           //是否软件触发,这里选择不是,由硬件触发
	DMA_InitStruct.DMA_Priority = DMA_Priority_Medium;                  //优先级,这里选择中等
	DMA_Init(DMA1_Channel5,&DMA_InitStruct);                            //配置DMA1的通道5
    
    /* 3、使能DMA1通道5搬运完成中断和NVIC */
	DMA_ITConfig(DMA1_Channel5, DMA_IT_TC, ENABLE);
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
    NVIC_InitTypeDef NVIC_InitStruct;
    NVIC_InitStruct.NVIC_IRQChannel = DMA1_Channel5_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStruct);
    
	DMA_Cmd(DMA1_Channel5,ENABLE);                                      //使能DMA1的通道5
}
   
/**
 * DMA1开启搬运函数
 */
//void UART1_DMA1_Transport(uint16_t DataNumber)
//{
//    /* 1、失能DMA1 */
//    DMA_Cmd(DMA1_Channel4,DISABLE); 
//    
//    /* 2、先设置传输计数器的计数值 */
//    DMA_SetCurrDataCounter(DMA1_Channel4, DataNumber);
//    
//    /* 3、使能DMA1 */
//    DMA_Cmd(DMA1_Channel4,ENABLE);   
//    
//    /* 4、等待搬运完成 */
//    while(!DMA_GetFlagStatus(DMA1_FLAG_TC4));   //等待通道4搬运完成
//	  DMA_ClearFlag(DMA1_FLAG_TC4);               //手动清除标志位 
//}

/**
 * DMA1通道5传输完成的中断服务函数
 */
void DMA1_Channel5_IRQHandler(void)
{
    if(DMA_GetFlagStatus(DMA1_FLAG_TC5))
    {
        DMA_ClearFlag(DMA1_FLAG_TC5);   //清除通道5的标志位
        Flag = 1;
    }      
}

④主函数main.c文件的代码如下:

#include "stm32f10x.h"                 
#include "Delay.h"
#include "UART.h"
#include "MyDMA.h"

int main(void)
{
    UART1_Init();
    DMA1_Init();
 
	while(1)
	{ 
        if(Flag)
        {  
            Flag = 0;
            USART_SendArray(Buff, Length); 
        }       
	}
}

在这里插入图片描述

3、串口空闲中断+DMA接收不定长数据包

①UART.c文件的代码如下:

#include "UART.h"

uint8_t Buff[Buffer_Size];  //定义数据缓冲区
uint8_t Flag = 0;           //传输完成标志位
uint16_t Index = 0;         //定义接收到的数据个数
/**
 * 串口1的初始化函数
 */
void UART1_Init(void)
{
    /* 开启串口的UART1的时钟 */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

    /* 开启串口的GPIO的时钟 */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    /* 配置串口1的引脚 */
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;        // 复用推挽输出
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;  // 浮空输入
    GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* 配置串口1的模式 */
    USART_InitTypeDef USART_InitStruct;
    USART_InitStruct.USART_BaudRate = 115200;
    USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;// 不使用硬件流控制
    USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;                // 收发模式
    USART_InitStruct.USART_Parity = USART_Parity_No;                            // 无奇偶校验位
    USART_InitStruct.USART_StopBits = USART_StopBits_1;                         // 1个停止位
    USART_InitStruct.USART_WordLength = USART_WordLength_8b;                    // 8个数据位
    USART_Init(USART1, &USART_InitStruct);
    
    /* 使能串口DMARx接收请求 */
    USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);
    
    /* 使能串口IDLE空闲中断和NVIC */
    USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
    NVIC_InitTypeDef NVIC_InitStruct;
    NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStruct);
    
    /* 使能串口1 */
    USART_Cmd(USART1, ENABLE);
}

/**
 * 串口发送一个字节的数据
 */
void USART_SendChar(uint8_t ch)
{
    /* 发送一个字节的数据 */
    USART_SendData(USART1, ch);

    /* 等待发送数据寄存器为空 */
    while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}

/**
 * 串口发送一个字符串的数据
 */
void USART_SendString(uint8_t *str)
{
    /* 发送多个字节的数据 */
    while (*str!= '\0')
    {
        USART_SendChar(*str++);
    }
}

/**
 * 串口发送多个字节的数据
 */
void USART_SendArray(uint8_t *array, uint16_t len)
{
    /* 发送一组数据 */
    for (uint16_t i = 0; i < len; i++)
    {
        USART_SendChar(array[i]);
    }
}

/**
 * 对printf函数进行重定向
 */
int fputc(int ch, FILE *f)
{
    /* 等待发送数据寄存器为空 */
    while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
    
    /* 发送一个字节的数据 */
    USART_SendData(USART1, (uint8_t)ch);
    return ch;
}

/**
 * 串口1的空闲中断服务函数
 */
void USART1_IRQHandler(void)
{
    uint8_t Receive_Data;
    if(USART_GetFlagStatus(USART1, USART_FLAG_IDLE))
    {   
        Receive_Data = USART1->SR;
        Receive_Data = USART1->DR; //清除中断标志位IDLE
        
//      Index = Buffer_Size - DMA_GetCurrDataCounter(DMA1_Channel5);//获取接收到的数据个数
        Index = Buffer_Size -(DMA1_Channel5->CNDTR);                //获取接收到的数据个数
        Flag = 1;
        
        /* 重新给DMA传输计数器设置值:让第二个数据包从缓冲区第一位开始存储 */
        DMA_Cmd(DMA1_Channel5,DISABLE);                             
        DMA_SetCurrDataCounter(DMA1_Channel5, Buffer_Size); 
        DMA_Cmd(DMA1_Channel5,ENABLE);                              //使能DMA1的通道5
    }
}

②UART.h文件的代码如下:

#ifndef __UART_H
#define __UART_H
#include "stm32f10x.h"
#include "stdio.h"

#define Buffer_Size 256
extern uint8_t Buff[Buffer_Size];//定义数据缓冲区
extern uint8_t Flag;
extern uint16_t Index;

void UART1_Init(void);
void USART_SendChar(uint8_t ch);
void USART_SendString(uint8_t *str);
void USART_SendArray(uint8_t *array, uint16_t len);

#endif

③MyDMA.c文件的代码如下:

#include "MyDMA.h"
#include "UART.h"
/**
 * DMA1通道5的初始化
 */

void DMA1_Init(void)
{
    /* 1、使能DMA1的时钟 */
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

    /* 2、配置DMA1的通道1 */
    DMA_InitTypeDef DMA_InitStruct;
	DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&(USART1->DR);    //外设站点的起始地址
	DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//数据宽度,8位
	DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;       //外设站点地址是否自增,这里选择不自增,因为搬运到数据寄存器TDR中
	
	DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)Buff;                 //内存站点起始地址
	DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;        //数据宽度,8位
	DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;                //目的站点地址是否自增,自增
	
	DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;                     //搬运方向的选择(目的地选择),这里选择外设站点--->内存站点:DMA_DIR_PeripheralDST
	DMA_InitStruct.DMA_BufferSize = Buffer_Size;                        //传输计数器的大小,代表搬运数据的个数
	DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;                          //是否自动重装,这里选择不自动重装,接收一个数据包,在空闲中断里面重装
	DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;                           //是否软件触发,这里选择不是,由硬件触发
	DMA_InitStruct.DMA_Priority = DMA_Priority_Medium;                  //优先级,这里选择中等
	DMA_Init(DMA1_Channel5,&DMA_InitStruct);                            //配置DMA1的通道5
    
	DMA_Cmd(DMA1_Channel5,ENABLE);                                      //使能DMA1的通道5
}

④主函数main.c文件的代码如下:

#include "stm32f10x.h"                 
#include "Delay.h"
#include "UART.h"
#include "MyDMA.h"

int main(void)
{
    UART1_Init();
    DMA1_Init();
 
	while(1)
	{ 
        if(Flag)
        {  
            Flag = 0;
            USART_SendArray(Buff, Index);   
        }       
	}
}

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2024 java大厂面试复习总结(一)(持续更新)

10年java程序员&#xff0c;2024年正好35岁&#xff0c;2024年11月公司裁员&#xff0c;记录自己找工作时候复习的一些要点。 java基础 hashCode()与equals()的相关规定 如果两个对象相等&#xff0c;则hashcode一定也是相同的两个对象相等&#xff0c;对两个对象分别调用eq…

深度学习5

一、模型保存与加载 1、序列化方式 保存方式&#xff1a;torch.save(model, "model.pkl") 打开方式&#xff1a;model torch.load("model.pkl", map_location"cpu") ​ import torch import torch.nn as nnclass MyModle(nn.Module):def __ini…

Redis五大基本类型——Zset有序集合命令详解(命令用法详解+思维导图详解)

目录 一、Zset有序集合类型介绍 二、常见命令 1、ZADD 2、ZCARD 3、ZCOUNT 4、ZRANGE 5、ZREVRANGE 6、ZRANGEBYSCORE 7、ZREVRANGEBYSCORE 8、ZPOPMAX 9、ZPOPMIN 10、ZRANK 11、ZREVRANK 12、ZSCORE 13、ZREM 14、ZREMRANGEBYRANK 15、ZREMRANGEBYSCORE 16…

ARM架构 AArch64 基础知识介绍

介绍 aarch64是 ARM 架构的 64 位版本&#xff0c;它是 ARMv8 架构的一部分&#xff0c;被设计用来提供更高的性能和更大的地址空间&#xff0c;同时保持与 32 位 ARM 架构的兼容性。AArch64 是 ARMv8 的 64 位指令集架构&#xff08;ISA&#xff09;&#xff0c;它提供了丰富的…

Rust中Tracing 应用指南

欢迎来到这篇全面的Rust跟踪入门指南。Rust 的tracing是一个用于应用程序级别的诊断和调试的库。它提供了一种结构化的、异步感知的方式来记录日志和跟踪事件。与传统的日志记录相比&#xff0c;tracing能够更好地处理复杂的异步系统和分布式系统中的事件跟踪&#xff0c;帮助开…

极狐GitLab 17.6 正式发布几十项与 DevSecOps 相关的功能【三】

GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署极狐GitLab。 学习极狐GitLab 的相关资料&#xff1a; 极狐GitLab 官网极狐…

WinFrom调用webapi接口另一个方法及其应用实例

1.调用接口方法 代码如下&#xff1a; public class WebAPI{#region WebAPI调用 public async Task<string> Call_Webapi(string Url, string Json) //url传入的是接口名称&#xff0c;json传入的是接口参数{string responseBody string.Empty; //responseBod…

elasticsearch的索引模版使用方法

5 索引模版⭐️⭐️⭐️⭐️⭐️ 索引模板就是创建索引时要遵循的模板规则索引模板仅对新创建的索引有效&#xff0c;已经创建的索引并不受索引模板的影响 5.1 索引模版的基本使用 1.查看所有的索引模板 GET 10.0.0.91:9200/_index_template2.创建自定义索引模板 xixi &…

从零开始学GeoServer源码(二)添加支持arcgis切片功能

文章目录 参考文章环境背景1、配置打包好的程序1.1、下载GeoServer的war包1.2、下载GeoWebCache1.3、拷贝jar包1.4、修改配置文件1.4.1、拷贝geowebcache-arcgiscache-context.xml1.4.2、修改geowebcache-core-context.xml1.4.3、修改geowebcache-servlet.xml 1.5、配置切片信息…

Redis 可观测最佳实践

Redis 介绍 Redis 是一个开源的高性能键值对&#xff08;key-value&#xff09;数据库。它通常用作数据库、缓存和消息代理。Redis 支持多种类型的数据结构&#xff0c;Redis 通常用于需要快速访问的场景&#xff0c;如会话缓存、全页缓存、排行榜、实时分析等。由于其高性能和…

HarmonyOs鸿蒙开发实战(21)=>组件间通信@ohos/liveeventbus

1.简介 LiveEventBus是一款消息总线&#xff0c;具有生命周期感知能力&#xff0c;支持Sticky&#xff0c;支持跨进程&#xff0c;支持跨APP发送消息。 2.下载安装 ohpm install ohos/liveeventbus 3.订阅&#xff0c;注册监听 4.发送事件 5. 完成 > 记得关注博主&#xff…

深度学习使用LSTM实现时间序列预测

大家好&#xff0c;LSTM是一种特殊的循环神经网络&#xff08;RNN&#xff09;架构&#xff0c;它被设计用来解决传统RNN在处理长序列数据时的梯度消失和梯度爆炸问题&#xff0c;特别是在时间序列预测、自然语言处理和语音识别等领域中表现出色。LSTM的核心在于其独特的门控机…

用Tauri框架构建跨平台桌面应用:1、Tauri快速开始

Tauri 是一个构建适用于所有主流桌面和移动平台的轻快二进制文件的框架。开发者们可以集成任何用于创建用户界面的可以被编译成 HTML、JavaScript 和 CSS 的前端框架&#xff0c;同时可以在必要时使用 Rust、Swift 和 Kotlin 等语言编写后端逻辑。 Tauri 是什么&#xff1f; |…

Elasticsearch对于大数据量(上亿量级)的聚合如何实现?

大家好&#xff0c;我是锋哥。今天分享关于【Elasticsearch对于大数据量&#xff08;上亿量级&#xff09;的聚合如何实现&#xff1f;】面试题。希望对大家有帮助&#xff1b; Elasticsearch对于大数据量&#xff08;上亿量级&#xff09;的聚合如何实现&#xff1f; 1000道 …

C语言:C语言实现对MySQL数据库表增删改查功能

基础DOME可以用于学习借鉴&#xff1b; 具体代码 #include <stdio.h> #include <mysql.h> // mysql 文件&#xff0c;如果配置ok就可以直接包含这个文件//宏定义 连接MySQL必要参数 #define SERVER "localhost" //或 127.0.0.1 #define USER "roo…

Learn Git Branching 学习笔记

网址&#xff1a;Learn Git Branching 一、基础篇 1.1 git commit 1.1.1 示例&#xff08;git commit&#xff09; git commit 1.1.2 题目&#xff08;两次提交记录&#xff09; git commit git commit 前 后 1.2 git branch 1.2.1 示例&#xff08;git branch <>、git …

设计模式:责任链实现数据流风格的数据处理

数据流风格 数据流风格是软件架构中的一种风格&#xff0c;主要是面向数据&#xff0c;用于进行流式的数据处理&#xff1b;数据流风格的代表有管道-过滤器风格和批处理序列风格&#xff0c;这里主要是指管道-过滤器风格。 管道-过滤器风格就像其名字一样&#xff0c;是以一个…

BERT简单理解;双向编码器优势

目录 BERT简单理解 一、BERT模型简单理解 二、BERT模型使用举例 三、BERT模型的优势 双向编码器优势 BERT简单理解 (Bidirectional Encoder Representations from Transformers)模型是一种预训练的自然语言处理(NLP)模型,由Google于2018年推出。以下是对BERT模型的简…

摄像头原始数据读取——V4L2(mmap模式,V4L2_MEMORY_MMAP)

摄像头原始数据读取——V4L2(mmap模式,V4L2_MEMORY_MMAP) 内存映射模式&#xff0c;是将设备在内核态申请的用于存储视频数据的物理内存映射到用户空间&#xff0c;使得用户应用程序可以直接访问和操作设备数据物理内存&#xff0c;避免了数据的拷贝。因此采集速度较快&#x…

SpringCloud框架学习(第五部分:SpringCloud Alibaba入门和 nacos)

目录 十二、SpringCloud Alibaba入门简介 1. 基本介绍 2.作用 3.版本选型 十三、 SpringCloud Alibaba Nacos服务注册和配置中心 1.简介 2.各种注册中心比较 3.下载安装 4.Nacos Discovery服务注册中心 &#xff08;1&#xff09; 基于 Nacos 的服务提供者 &#xf…