Stm32串口搭配DMA实现自定义printf、scanf

前言:本文仅供学习参考使用,主要目的是让大家快速使用串口调试,文章所提及的GCC适用于Clion,Vscode等第三方编辑器的用户。作者有时间会继续更新^_^

一、GCC环境

1、标准库

(1)、使用方法

在主函数while(1)初始化中,添加Serial_Init();

int main(void) {Serial_Init();while (1) {}
}

在代码目录下创建USART文件夹,新建syscalls.c,sysmem.c,usart.c,usart.h四个文件,工程目录结构如下:
在这里插入图片描述
在CMakeLists中添加如下代码:

# include_directories(Core/USART) 根据USART文件夹实际路径进行修改
set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -Wl,-u_printf_float")
add_link_options( -specs=nosys.specs -specs=nano.specs)

使用u_scanf,u_printf来替代scanf,printf函数,用法一致。

(2)代码部分

syscalls.c
/********************************************************************************* @file      syscalls.c* @author    Auto-generated by STM32CubeIDE* @brief     STM32CubeIDE Minimal System calls file**            For more information about which c-functions*            need which of these lowlevel functions*            please consult the Newlib libc-manual******************************************************************************* @attention** Copyright (c) 2020-2024 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************//* Includes */
#include <sys/stat.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>
#include <sys/times.h>/* Variables */
extern int __io_putchar(int ch) __attribute__((weak));
extern int __io_getchar(void) __attribute__((weak));char *__env[1] = { 0 };
char **environ = __env;/* Functions */
void initialise_monitor_handles()
{
}int _getpid(void)
{return 1;
}int _kill(int pid, int sig)
{(void)pid;(void)sig;errno = EINVAL;return -1;
}void _exit (int status)
{_kill(status, -1);while (1) {}    /* Make sure we hang here */
}__attribute__((weak)) int _read(int file, char *ptr, int len)
{(void)file;int DataIdx;for (DataIdx = 0; DataIdx < len; DataIdx++){*ptr++ = __io_getchar();}return len;
}__attribute__((weak)) int _write(int file, char *ptr, int len)
{(void)file;int DataIdx;for (DataIdx = 0; DataIdx < len; DataIdx++){__io_putchar(*ptr++);}return len;
}int _close(int file)
{(void)file;return -1;
}int _fstat(int file, struct stat *st)
{(void)file;st->st_mode = S_IFCHR;return 0;
}int _isatty(int file)
{(void)file;return 1;
}int _lseek(int file, int ptr, int dir)
{(void)file;(void)ptr;(void)dir;return 0;
}int _open(char *path, int flags, ...)
{(void)path;(void)flags;/* Pretend like we always fail */return -1;
}int _wait(int *status)
{(void)status;errno = ECHILD;return -1;
}int _unlink(char *name)
{(void)name;errno = ENOENT;return -1;
}int _times(struct tms *buf)
{(void)buf;return -1;
}int _stat(char *file, struct stat *st)
{(void)file;st->st_mode = S_IFCHR;return 0;
}int _link(char *old, char *new)
{(void)old;(void)new;errno = EMLINK;return -1;
}int _fork(void)
{errno = EAGAIN;return -1;
}int _execve(char *name, char **argv, char **env)
{(void)name;(void)argv;(void)env;errno = ENOMEM;return -1;
}
sysmem.c
/********************************************************************************* @file      sysmem.c* @author    Generated by STM32CubeIDE* @brief     STM32CubeIDE System Memory calls file**            For more information about which C functions*            need which of these lowlevel functions*            please consult the newlib libc manual******************************************************************************* @attention** Copyright (c) 2024 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************//* Includes */
#include <errno.h>
#include <stdint.h>/*** Pointer to the current high watermark of the heap usage*/
static uint8_t *__sbrk_heap_end = NULL;/*** @brief _sbrk() allocates memory to the newlib heap and is used by malloc*        and others from the C library** @verbatim* ############################################################################* #  .data  #  .bss  #       newlib heap       #          MSP stack          #* #         #        #                         # Reserved by _Min_Stack_Size #* ############################################################################* ^-- RAM start      ^-- _end                             _estack, RAM end --^* @endverbatim** This implementation starts allocating at the '_end' linker symbol* The '_Min_Stack_Size' linker symbol reserves a memory for the MSP stack* The implementation considers '_estack' linker symbol to be RAM end* NOTE: If the MSP stack, at any point during execution, grows larger than the* reserved size, please increase the '_Min_Stack_Size'.** @param incr Memory size* @return Pointer to allocated memory*/
void *_sbrk(ptrdiff_t incr)
{extern uint8_t _end; /* Symbol defined in the linker script */extern uint8_t _estack; /* Symbol defined in the linker script */extern uint32_t _Min_Stack_Size; /* Symbol defined in the linker script */const uint32_t stack_limit = (uint32_t)&_estack - (uint32_t)&_Min_Stack_Size;const uint8_t *max_heap = (uint8_t *)stack_limit;uint8_t *prev_heap_end;/* Initialize heap end at first call */if (NULL == __sbrk_heap_end){__sbrk_heap_end = &_end;}/* Protect heap from growing into the reserved MSP stack */if (__sbrk_heap_end + incr > max_heap){errno = ENOMEM;return (void *)-1;}prev_heap_end = __sbrk_heap_end;__sbrk_heap_end += incr;return (void *)prev_heap_end;
}
usart.c

#include "usart.h"uint8_t rx_buffer[BUFF_SIZE];
uint8_t tx_buffer[1];
volatile uint8_t Serial_RxFlag;void GPIO_Init_Config(void) {RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;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);
}void USART_Init_Config(void) {RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);USART_InitTypeDef USART_InitStructure;USART_InitStructure.USART_BaudRate = 115200;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);USART_Cmd(USART1, ENABLE);
}void DMA_Init_Config(DMA_Channel_TypeDef *DMA_Channel, uint32_t buffer,uint32_t direction, uint32_t bufferSize) {DMA_InitTypeDef DMA_InitStructure;RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); // Enable DMA1 clockDMA_DeInit(DMA_Channel);                           // Reset DMA channelDMA_InitStructure.DMA_PeripheralBaseAddr =(u32)(&USART1->DR);                        // Peripheral base addressDMA_InitStructure.DMA_MemoryBaseAddr = buffer; // Memory base addressDMA_InitStructure.DMA_DIR = direction;         // DMA transmit directionDMA_InitStructure.DMA_BufferSize = bufferSize; // DMA Channel buffer sizeDMA_InitStructure.DMA_PeripheralInc =DMA_PeripheralInc_Disable; // Peripheral address incrementedDMA_InitStructure.DMA_MemoryInc =DMA_MemoryInc_Enable; // Memory address incrementedDMA_InitStructure.DMA_PeripheralDataSize =DMA_PeripheralDataSize_Byte; // Peripheral data widthDMA_InitStructure.DMA_MemoryDataSize =DMA_MemoryDataSize_Byte;                        // Memory data widthDMA_InitStructure.DMA_Mode = DMA_Mode_Normal;       // DMA Channel modeDMA_InitStructure.DMA_Priority = DMA_Priority_High; // DMA Channel priorityDMA_InitStructure.DMA_M2M = DMA_M2M_Disable; // Memory-to-memory transferDMA_Init(DMA_Channel, &DMA_InitStructure);   // DMA initDMA_Cmd(DMA_Channel, ENABLE);                // Enable DMA channel
}void NVIC_Init_Config(void) {NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; // IRQ ChannelNVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =3;                                             // Preemption PriorityNVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // SubPriority PriorityNVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;    // Enable IRQ ChannelNVIC_Init(&NVIC_InitStructure);                    // Init NVIC
}void Serial_Init(void) {GPIO_Init_Config();USART_Init_Config();DMA_Init_Config(DMA1_Channel5, (u32)rx_buffer, DMA_DIR_PeripheralSRC,BUFF_SIZE);DMA_Init_Config(DMA1_Channel4, (u32)tx_buffer, DMA_DIR_PeripheralDST, 1);NVIC_Init_Config();USART_ITConfig(USART1, USART_IT_IDLE, ENABLE); // Enables Idle interruptUSART_GetFlagStatus(USART1, USART_FLAG_IDLE);  // Get Idle flagUSART_ReceiveData(USART1);                     // Get receive dataUSART_Cmd(USART1, ENABLE);                     // Enable USART1USART_DMACmd(USART1, USART_DMAReq_Rx | USART_DMAReq_Tx,ENABLE); // Enable DMA receive/transmit request
}void Usart_SendByte(uint8_t ch) {tx_buffer[0] = ch;DMA_Cmd(DMA1_Channel4, DISABLE); //关闭 USART1 TX DMA1 所指示的通道DMA_SetCurrDataCounter(DMA1_Channel4, 1); //设置 DMA 缓存的大小DMA_Cmd(DMA1_Channel4, ENABLE); //使能 USART1 TX DMA1 所指示的通道//等待发送结束while (!DMA_GetFlagStatus(DMA1_FLAG_TC4));DMA_ClearFlag(DMA1_FLAG_TC4);
}
void USART_SendString(const char *str) {unsigned int i = 0;while (*(str + i) != '\0') {Usart_SendByte(*(str + i));i++;}while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
}void USART1_IRQHandler(void) {if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {USART_ClearFlag(USART1, USART_FLAG_RXNE);USART_ClearITPendingBit(USART1, USART_IT_RXNE);}if (USART_GetITStatus(USART1, USART_IT_IDLE) != RESET) // Idle interrupt set{USART_GetITStatus(USART1, USART_IT_IDLE); // Get idle interrupt stateUSART_ReceiveData(USART1);                // Get USARTx received dataDMA_Cmd(DMA1_Channel5, DISABLE);          // Disable DMA channelDMA_SetCurrDataCounter(DMA1_Channel5, BUFF_SIZE); // Set data countDMA_Cmd(DMA1_Channel5, ENABLE);                  // Enable DMA channelSerial_RxFlag = 1;}
}
char *find_next_space_or_end(char *str) {while (*str != ' ' && *str != '\0') {str++;}return str;
}int str_to_num(char *start, char *end) {char temp[50];strncpy(temp, start, end - start);temp[end - start] = '\0';return atoi(temp);
}double str_to_double(char *start, char *end) {char temp[50];strncpy(temp, start, end - start);temp[end - start] = '\0';return atof(temp);
}void u_scanf(char *fmt, ...) {va_list ap;va_start(ap, fmt);char *start = rx_buffer;char *end;while (Serial_RxFlag == 0) {}Serial_RxFlag = 0;while (*fmt != '\0') {if (*fmt == '%') {fmt++;end = find_next_space_or_end(start);switch (*fmt) {case 'd': {int *ip = va_arg(ap, int *);*ip = str_to_num(start, end);} break;case 'l': {++fmt;if (*fmt == 'f') {double *fp = va_arg(ap, double *);*fp = str_to_double(start, end);}} break;case 'f': {float *fp = va_arg(ap, float *);*fp = (float)str_to_double(start, end);} break;case 'c': {int *cp = va_arg(ap, int *);*cp = start[0];} break;case 's': {char *sp = va_arg(ap, char *);strcpy(sp, rx_buffer);} break;}start = end + 1;}fmt++;}va_end(ap);
}
void u_printf(const char *format, ...) {va_list args;uint8_t buff[BUFF_SIZE];va_start(args, format);vsprintf(buff, format, args);USART_SendString(buff);va_end(args);
}
usart.h
#ifndef __USART_H
#define __USART_H
#include "stdlib.h"
#include "stm32f10x.h"
#include "stm32f10x_dma.h"
#include "string.h"
#include <math.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/types.h>
#define BUFF_SIZE 256
void Serial_Init(void);
void u_printf(const char *format, ...);
void u_scanf(char *fmt, ...);
#endif

(3)总结

可以看出在代码中u_scanf比较繁琐,使用自定义函数来实现,并未使用自带的vsscanf来重构,如果你想要使用vsscanf的话,还需要添加-u_scanf_float链接标志(同上),但是vsscanf函数会导致输入字符串时无法正常读取空格.


以上版本存在问题,请替换usart.c,usart.h为如下代码,使用方法直接使用printf以及scanf,注意在CMakeLists中添加-u_scanf_float链接标志

usart.c

#include "usart.h"/*根据需要取消注释对应宏定义*/
#define DBUG_1
//#define DBUG_2#if defined(DBUG_1)
#define DBUG_USART USART1
#define DBUG_PORT GPIOA
#define RX_PIN GPIO_Pin_10
#define TX_PIN GPIO_Pin_9
#define RCC_APB2Periph_DBUG_PORT RCC_APB2Periph_GPIOA
#define DBUG_RX_CHANNEL DMA1_Channel5
#define DBUG_TX_CHANNEL DMA1_Channel4
#define DBUG_RX_FLAG DMA1_FLAG_TC5
#define DBUG_TX_FLAG DMA1_FLAG_TC4
#elif defined(DBUG_2)
#define DBUG_USART USART2
#define DBUG_PORT GPIOA
#define RX_PIN GPIO_Pin_3
#define TX_PIN GPIO_Pin_2
#define RCC_APB2Periph_DBUG_PORT RCC_APB2Periph_GPIOA
#define DBUG_RX_CHANNEL DMA1_Channel6
#define DBUG_TX_CHANNEL DMA1_Channel7
#define DBUG_RX_FLAG DMA1_FLAG_TC6
#define DBUG_TX_FLAG DMA1_FLAG_TC7
#endifuint8_t rx_buffer[1];
uint8_t tx_buffer[1];
volatile uint8_t Serial_RxFlag;void GPIO_Init_Config(void) {RCC_APB2PeriphClockCmd(RCC_APB2Periph_DBUG_PORT, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Pin = TX_PIN;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(DBUG_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Pin = RX_PIN;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(DBUG_PORT, &GPIO_InitStructure);
}void USART_Init_Config(void) {
#if defined(DBUG_1)RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
#elif defined(DBUG_2)RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
#endifUSART_InitTypeDef USART_InitStructure;USART_InitStructure.USART_BaudRate = 115200;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(DBUG_USART, &USART_InitStructure);USART_Cmd(DBUG_USART, ENABLE);
}void DMA_Init_Config(DMA_Channel_TypeDef *DMA_Channel, uint32_t buffer,uint32_t direction, uint32_t bufferSize) {DMA_InitTypeDef DMA_InitStructure;RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);DMA_DeInit(DMA_Channel);DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&DBUG_USART->DR);DMA_InitStructure.DMA_MemoryBaseAddr = buffer;DMA_InitStructure.DMA_DIR = direction;DMA_InitStructure.DMA_BufferSize = bufferSize;DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;DMA_InitStructure.DMA_Priority = DMA_Priority_High;DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;DMA_Init(DMA_Channel, &DMA_InitStructure);DMA_Cmd(DMA_Channel, ENABLE);
}void Serial_Init(void) {GPIO_Init_Config();USART_Init_Config();DMA_Init_Config(DBUG_RX_CHANNEL, (u32)rx_buffer, DMA_DIR_PeripheralSRC, 1);DMA_Init_Config(DBUG_TX_CHANNEL, (u32)tx_buffer, DMA_DIR_PeripheralDST, 1);USART_Cmd(DBUG_USART, ENABLE);USART_DMACmd(DBUG_USART, USART_DMAReq_Rx | USART_DMAReq_Tx, ENABLE);setvbuf(stdin, NULL, _IONBF, 0);
}#if (defined(__GNUC__) && !defined(__CC_ARM))
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#define GETCHAR_PROTOTYPE int __io_getchar(void)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#define GETCHAR_PROTOTYPE int fgetc(FILE *f)
#endif /* __GNUC__ */PUTCHAR_PROTOTYPE {*tx_buffer = ch;while (DMA_GetCurrDataCounter(DBUG_TX_CHANNEL) != 0) {};DMA_Cmd(DBUG_TX_CHANNEL, DISABLE);DMA_SetCurrDataCounter(DBUG_TX_CHANNEL, 1);DMA_Cmd(DBUG_TX_CHANNEL, ENABLE);while (!DMA_GetFlagStatus(DBUG_TX_FLAG));DMA_ClearFlag(DBUG_TX_FLAG);return ch;
}
GETCHAR_PROTOTYPE {DMA_Cmd(DBUG_RX_CHANNEL, DISABLE);DMA_SetCurrDataCounter(DBUG_RX_CHANNEL, 1);DMA_Cmd(DBUG_RX_CHANNEL, ENABLE);while (!DMA_GetFlagStatus(DBUG_RX_FLAG));DMA_ClearFlag(DBUG_RX_FLAG);return *rx_buffer;
}
usart.h
#ifndef __USART_H
#define __USART_H
#include "delay.h"
#include "stdlib.h"
#include "stm32f10x.h"
#include "stm32f10x_dma.h"
#include "string.h"
#include <math.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/types.h>
void Serial_Init(void);#endif

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

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

相关文章

嵌入式学习-M4的基本定时器

基本介绍 框图分析 时钟选择 计数器结构 开启重装载值寄存器的影子寄存器的工作时序图 未开启重装载值寄存器的影子寄存器的工作时序图 更新事件以及中断 相关寄存器 相关库函数

全球排名第一的质量管理(QMS)系统介绍,100%免费开源

什么是Odoo全程质量管理&#xff1f; 开源智造Odoo免费开源质量管理系统将政策、标准和实践规范化并自动化&#xff0c;以最小的开销提供最高质量的产品。快速轻松地选择要执行的测试&#xff0c;设置参数以评估结果&#xff0c;并定义接收时和生产过程中的测试策略。Odoo会自动…

OpenNJet产品体验:探索无限可能

文章目录 前言一、OpenNJet是什么&#xff1f;二、OpenNJet特性和优点三、OpenNJet功能规划四、OpenNJet快速上手五、OpenNJet的使用总结 前言 现代社会网络高速发展&#xff0c;同时也迎来了互联网发展的高峰&#xff0c;OpenNJet作为一个基于NGINX的面向互联网和云原生应用提…

网络安全等级保护测评指标解读(2.0)

网络安全等级保护2.0测评指标解读&#xff1a; 1、物理和环境安全 2、网络和通信安全 3、设备和计算安全 4、应用和数据安全 5、安全策略和管理制度 6、安全管理机构和人员 7、安全建设管理 8、安全运维管理 软件资料清单列表部分文档&#xff1a; 工作安排任务书&#xff0c;…

HCIA和HCIP区别大吗?小白请看这

华为认证以其专业性和实用性受到了业界的广泛认可。 HCIA、HCIP、HCIP这三个级别&#xff0c;你会选哪个&#xff1f;IE含金量不用多说&#xff0c;IA还是IP&#xff0c;你会纠结吗。 但面对这两个级别的认证&#xff0c;初学者或者“小白”们可能会感到困惑&#xff1a;两者…

python “名称空间和作用域” 以及 “模块的导入和使用”

七、名称空间和作用域 可以简单理解为存放变量名和变量值之间绑定关系的地方。 1、名称空间 在 Python 中有各种各样的名称空间&#xff1a; 全局名称空间&#xff1a;每个程序的主要部分定义了全局的变量名和变量值的对应关系&#xff0c;这样就叫做全局名称空间 局部名称…

Ajax额

原生Ajax xml 已被json取代 http 请求方法urlhttp版本号 network 谷歌浏览器查看请求报文和响应报文 F12 network header里面有 请求头 响应头 点击view source 可以查看请求响应行 请求体在请求行头下面 get请求有url参数&#xff0c;请求体变为query String…

基于springboot实现的家具销售电商平台

开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&…

超分辨率技术

何为超分辨率&#xff1f; 超分辨率技术&#xff08;Super Resolution&#xff09;&#xff1a;通过硬件或软件的方法提高图像或视频帧的分辨率&#xff0c; 通过一系列低分辨率图像获取到高分辨率图像的过程。 功能介绍&#xff1a;提升图像或视频分辨率最高至8K&#xff0c;…

C#窗体程序设计笔记:如何调出控件工具箱,并设置控件的属性

文章目录 调出控件工具箱设置控件属性 调出控件工具箱 使用Visual Studio打开C#解决方案后&#xff0c;初始界面如下图所示&#xff1a; 接着&#xff0c;在上方的菜单栏依次选择“视图”“工具箱”&#xff0c;即可打开工具箱&#xff0c;如下图所示&#xff1a; 设置控件属…

前端CSS3基础1(新增长度单位,盒子模型,背景,边框,文本属性,渐变,字体,2D变换,3D变换)

前端CSS3基础1&#xff08;新增长度单位&#xff0c;盒子模型&#xff0c;背景&#xff0c;边框&#xff0c;文本属性&#xff0c;渐变&#xff0c;字体&#xff0c;2D变换&#xff0c;3D变换&#xff09; CSS3 新增长度单位CSS3 新增盒子模型相关属性box-sizing怪异盒模型box-…

【VMware】vSphere 8.0 安装和设置简介

本信息的目标读者为熟悉虚拟机技术和数据中心操作并具有丰富经验的 Windows 或 Linux 系统管理员。 vSphere 8.0 提供了各种安装和设置选项&#xff0c;这些选项定义了相应的任务序列。 vSphere 的两个核心组件是 ESXi 和 vCenter Server。ESXi 是可用于创建和运行虚拟机和虚拟…