STM32——SPI通信

文章目录

    • SPI(Serial Peripheral Interface)概述:
    • SPI的硬件连接:
    • SPI的特点和优势:
    • SPI的常见应用:
    • SPI的工作方式和时序图分析:
      • 工作模式
      • 传输模式与时序分析
      • 工作流程
    • SPI设备的寄存器结构和寄存器设置
      • SPI设备寄存器结构:
      • 常见的寄存器设置:
    • STM32F4xx SPI 模块特性
    • 如何调试SPI通信问题和故障排除

SPI(Serial Peripheral Interface)概述:

SPI是一种串行通信接口,用于在微控制器、传感器、存储器等设备之间进行数据传输。
SPI通信通常涉及一个主设备(Master)和一个或多个从设备(Slave),通过共享时钟信号和数据线进行通信。

SPI的硬件连接:

SPI使用四条信号线:时钟线(SCLK)、主设备输出线(MOSI)、主设备输入线(MISO)和片选线(SS)。
通信过程中,主设备通过时钟线产生时钟信号,控制数据传输的时序。
主设备通过MOSI线发送数据,而从设备通过MISO线返回响应数据。
片选线用于选择要与主设备进行通信的从设备。
在这里插入图片描述
一主一从连接
在这里插入图片描述
一主多从连接
在这里插入图片描述

SPI的特点和优势:

SPI支持高速的全双工数据传输、只需少量的信号线和硬件引脚、SPI可以连接多个从设备,每个从设备都有独立的片选线,方便扩展和集成多个设备、SPI通常用于设备之间的短距离通信,如同一个电路板上的通信。

SPI的常见应用:

存储器接口:SPI常用于与闪存、EEPROM等存储器设备进行通信。
传感器接口:许多传感器模块使用SPI接口与主控制器通信,如加速度计、陀螺仪等。
显示器接口:某些显示模块使用SPI接口进行数据传输。
无线通信模块:一些无线模块,如WiFi模块、蓝牙模块等,可以通过SPI与主控制器通信。

SPI的工作方式和时序图分析:

工作模式

配置SPI设备的参数,如时钟频率、数据位数和传输模式。本模块代码参考博客:https://blog.51cto.com/u_15903730/6163015
主模式(Master Mode):
在主模式下,一个主设备控制整个SPI通信过程。主设备负责生成时钟信号(SCLK)和控制片选信号(SS)来选择从设备,并通过MOSI线(Master Output Slave Input)向从设备发送数据。同时,主设备通过MISO线(Master Input Slave Output)接收从设备返回的数据。

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "stm32f4xx.h"#define SPIx            SPI1
#define GPIO_AF_SPIx     GPIO_AF5_SPI1
#define GPIO_CS         GPIO_Pin_4
#define GPIO_CLK        GPIO_Pin_5
#define GPIO_MISO       GPIO_Pin_6
#define GPIO_MOSI       GPIO_Pin_7void init_spi(void)
{SPI_InitTypeDef spi_init_struct;GPIO_InitTypeDef gpio_init_struct;/* Enable the SPI clock */RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);/* Enable the GPIO clock */RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);/* Configure the chip select pin as output */gpio_init_struct.GPIO_Mode = GPIO_Mode_OUT;gpio_init_struct.GPIO_OType = GPIO_OType_PP;gpio_init_struct.GPIO_Pin = GPIO_CS;gpio_init_struct.GPIO_PuPd = GPIO_PuPd_NOPULL;gpio_init_struct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &gpio_init_struct);/* Configure the SPI pins */gpio_init_struct.GPIO_Mode = GPIO_Mode_AF;gpio_init_struct.GPIO_OType = GPIO_OType_PP;gpio_init_struct.GPIO_Pin = GPIO_CLK | GPIO_MISO | GPIO_MOSI;gpio_init_struct.GPIO_PuPd = GPIO_PuPd_NOPULL;gpio_init_struct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &gpio_init_struct);/* Connect the SPI pins to their alternate functions */GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPIx);GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_SPIx);GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPIx);/* Configure the SPI peripheral */spi_init_struct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;spi_init_struct.SPI_CPHA = SPI_CPHA_1Edge;spi_init_struct.SPI_CPOL = SPI_CPOL_Low;spi_init_struct.SPI_CRCPolynomial = 7;spi_init_struct.SPI_DataSize = SPI_DataSize_8b;spi_init_struct.SPI_Direction = SPI_Direction_2Lines_FullDuplex;spi_init_struct.SPI_FirstBit = SPI_FirstBit_MSB;spi_init_struct.SPI_Mode = SPI_Mode_Master;spi_init_struct.SPI_NSS = SPI_NSS_Soft;SPI_Init(SPIx, &spi_init_struct);/* Enable the SPI peripheral */SPI_Cmd(SPIx, ENABLE);
}uint8_t spi_send_byte(uint8_t byte)
{/* Wait for any pending transfers to complete */while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET);/* Send the byte */SPI_I2S_SendData(SPIx, byte);/* Wait for the transfer to complete */while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_RXNE) == RESET);/* Return the received byte */return SPI_I2S_ReceiveData(SPIx);
}int main(void)
{uint8_t data;/* Initialize the SPI module */init_spi();/* Select the slave device */GPIO_ResetBits(GPIOA, GPIO_CS);/* Send some data */data = spi_send_byte(0xAA);printf("Received: 0x%02X\n", data);/* Deselect the slave device */GPIO_SetBits(GPIOA, GPIO_CS);return 0;
}

从模式(Slave Mode):
在从模式下,从设备被动地响应主设备的控制。从设备通过MISO线接收主设备发送的数据,并通过MOSI线向主设备返回数据。从设备在接收到有效的片选信号(SS)后才会响应数据传输。

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "stm32f4xx.h"#define SPIx            SPI1
#define GPIO_AF_SPIx     GPIO_AF5_SPI1
#define GPIO_CS         GPIO_Pin_4
#define GPIO_CLK        GPIO_Pin_5
#define GPIO_MISO       GPIO_Pin_6
#define GPIO_MOSI       GPIO_Pin_7void init_spi(void)
{SPI_InitTypeDef spi_init_struct;GPIO_InitTypeDef gpio_init_struct;/* Enable the SPI clock */RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);/* Enable the GPIO clock */RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);/* Configure the chip select pin as output */gpio_init_struct.GPIO_Mode = GPIO_Mode_OUT;gpio_init_struct.GPIO_OType = GPIO_OType_PP;gpio_init_struct.GPIO_Pin = GPIO_CS;gpio_init_struct.GPIO_PuPd = GPIO_PuPd_NOPULL;gpio_init_struct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &gpio_init_struct);/* Configure the SPI pins */gpio_init_struct.GPIO_Mode = GPIO_Mode_AF;gpio_init_struct.GPIO_OType = GPIO_OType_PP;gpio_init_struct.GPIO_Pin = GPIO_CLK | GPIO_MISO | GPIO_MOSI;gpio_init_struct.GPIO_PuPd = GPIO_PuPd_NOPULL;gpio_init_struct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &gpio_init_struct);/* Connect the SPI pins to their alternate functions */GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPIx);GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_SPIx);GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPIx);/* Configure the SPI peripheral */spi_init_struct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;spi_init_struct.SPI_CPHA = SPI_CPHA_1Edge;spi_init_struct.SPI_CPOL = SPI_CPOL_Low;spi_init_struct.SPI_CRCPolynomial = 7;spi_init_struct.SPI_DataSize = SPI_DataSize_8b;spi_init_struct.SPI_Direction = SPI_Direction_2Lines_FullDuplex;spi_init_struct.SPI_FirstBit = SPI_FirstBit_MSB;spi_init_struct.SPI_Mode = SPI_Mode_Slave;spi_init_struct.SPI_NSS = SPI_NSS_Hard;SPI_Init(SPIx, &spi_init_struct);/* Enable the SPI peripheral */SPI_Cmd(SPIx, ENABLE);
}uint8_t spi_receive_byte(void)
{/* Wait for any pending transfers to complete */while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET);/* Return the received byte */return SPI_I2S_ReceiveData(SPIx);
}void spi_send_byte(uint8_t byte)
{/* Wait for any pending transfers to complete */while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET);/* Send the byte */SPI_I2S_SendData(SPIx, byte);/* Wait for the transfer to complete */while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_RXNE) == RESET);/* Clear the receive buffer */SPI_I2S_ReceiveData(SPIx);
}int main(void)
{uint8_t data;/* Initialize the SPI module */init_spi();/* Wait for the chip select signal */while (GPIO_ReadInputDataBit(GPIOA, GPIO_CS) != Bit_RESET);/* Loop forever */while (1){/* Receive some data */data = spi_receive_byte();/* Process the data */printf("Received: 0x%02X\n", data);/* Send a response */spi_send_byte(0xAA);}return 0;
}

传输模式与时序分析

时钟极性和相位(Clock Polarity and Phase):
SPI接口还具有时钟极性(CPOL)和时钟相位(CPHA)的设置。CPOL定义了时钟信号在空闲状态时的电平,可以是高电平(CPOL=1)或低电平(CPOL=0)。CPHA定义了数据采样的时机,可以是在时钟信号的上升沿(CPHA=0)或下降沿(CPHA=1)进行采样。
根据CPOL和CPHA的不同组合,可以有四种不同的时钟极性和相位模式,分别为:

模式0:CPOL=0,CPHA=0
模式1:CPOL=0,CPHA=1
模式2:CPOL=1,CPHA=0
模式3:CPOL=1,CPHA=1

时钟极性和相位的设置需要主设备和从设备之间保持一致,以确保正确的数据传输。SPI 总线有四种工作方式(SP0, SP1, SP2, SP3),其中使用的最为广泛的是 SPI0 和和 SPI3 方式

读取数据方式:
00 起始电平为低电平—>数据采样(读数据)在第一个边沿,时钟线从低到高跳变的时候,数据线保持不变,这时候读数据,时钟线从高到底跳变的时候,数据线可以变化,发送数据,所以上升沿读,下降沿写

01 起始电平为低电平—>数据采样(读数据)在第二个边沿,时钟线从低到高跳变的时候,数据线可以变化,发送数据,时钟线从高到底跳变的时候,数据线保持不变,这时候读数据,所以上升沿写,下降沿读

10 起始电平是高点平—>数据采样(读数据)在第一个边沿,时钟线从高到低跳变的时候,数据线保持不变,这时候读数据,时钟线从低到高跳变的时候,数据线可以变化,发送数据,所以,下降沿读,上升沿写

11 起始电平是高点平—>数据采样(读数据)在第二个边沿,时钟线从高到低跳变的时候,数据线可以变化,发送数据,时钟线从低到高跳变的时候,数据线保持不变,这时候读数据,所以,下降沿写,上升沿读
在这里插入图片描述
每次传输数据的宽度为 8bit,上升沿发送、下降沿接收、高位先发送。
上升沿到来的时候,MOSI 上的电平将被发送到从设备的寄存器中。
下降沿到来的时候,MISO 上的电平将被接收到主设备的寄存器中。

在这里插入图片描述

工作流程

  1. SPI通信工作流程
    1)硬件连接:
    首先,确保SPI主机(如微控制器)和SPI从机(外部设备)之间正确连接。通常,SPI通信需要四根线:SCLK(时钟线)、MOSI(主机输出从机输入线)、MISO(主机输入从机输出线)和SS(从机选择线)。
    2)主机配置:
    主机(如微控制器)需要配置SPI控制器的相关寄存器或寄存器位,以设置通信参数,如时钟速率、数据位顺序、数据传输模式等。
    3)选择从机:
    主机通过设置SS线(从机选择线)来选择要与之通信的从机。如果有多个从机连接到同一总线,主机需要选择其中一个从机与之通信,常通过将SS线拉低来选中对应的从机。
    4)数据传输:
    SPI通信是全双工的,数据可以同时在主机和从机之间传输。
    主机通过SCLK线发送时钟信号,驱动数据传输的时序。主机在每个时钟周期的上升沿或下降沿将数据位推送到MOSI线上,发送给从机。从机在相应的时钟边沿读取MOSI线上的数据位,并将响应的数据位推送到MISO线上,供主机读取。数据传输可以按照指定的字节、位数或连续传输的方式进行。
    5)传输完成:
    传输完成后,可以继续进行下一次传输或者释放SPI总线。

SPI设备的寄存器结构和寄存器设置

SPI设备寄存器结构:

控制寄存器(Control Register):控制SPI设备的操作模式、时钟频率、数据位顺序等设置。
状态寄存器(Status Register):提供SPI设备的状态信息,如传输完成标志、错误标志等。
数据寄存器(Data Register):用于存储要发送或接收的数据。

常见的寄存器设置:

操作模式(Mode):SPI设备通常支持多种操作模式,如主模式(Master Mode)和从模式(Slave Mode)。通过控制寄存器的相关位,选择适当的模式。
时钟频率(Clock Frequency):SPI设备的通信速率由时钟频率决定。控制寄存器中的时钟分频位或配置寄存器可以用于设置合适的时钟频率。
时钟极性和相位(Clock Polarity and Phase):SPI设备的时钟极性(CPOL)和时钟相位(CPHA)设置决定了数据采样和传输的时机。通过控制寄存器的相关位设置CPOL和CPHA。
数据位顺序(Data Bit Order):SPI设备可以支持先传输最高有效位(MSB)或先传输最低有效位(LSB)。寄存器中的位序设置可以用于选择合适的数据位顺序。
中断使能(Interrupt Enable):SPI设备通常支持中断功能,用于通知主设备有数据可用或传输完成。中断使能位可以在控制寄存器中设置。
具体参考技术文档、参考文档、数据手册来确定产品的使用。

STM32F4xx SPI 模块特性

1) 由 SPI 模块中 SCLK、MOSI 和 MISO 三线组成全双工同步传输
2) 支持数据传输位宽为 8 位数据或 16 位数据
3) 可以通过软件设置 SPI 模块为主机模式或从机模式
4) 可以对 SPI 的时钟源进行分频,来做为作为主机或从机时的通讯速度(分频最大值为 fPCLK/2),但 STM32F401xE 的 SPI 模块最大通信速度为 42MHz (spi1,spi4)或者 21Mhz(spi2,spi3)。
5) 可以使用软件对 SPI 的通讯时序(时钟极性和时钟相位)进行选择
6) 可以对 SPI 数据传输顺序进行选择为最先移位 MSB 或 LSB
7) SPI 模块的中断源为:SPI 数据发送和接收、主模式故障、数据上溢(过载)以及 CRC 错误
8) SPI 可以利用 DMA 功能对数据进行每次 1 字节发送和接收。
在这里插入图片描述

如何调试SPI通信问题和故障排除

掌握常见的SPI通信错误和解决方法,如时钟频率不匹配、数据线连接错误等。
1.串口显示内容但是乱码:时钟频率两端不匹配,重新调频率
2.无现象或者本来有现象后来突然中断通信:数据线是否连接错误,附近是否有信号干扰,检查电源线是否未连接好
3.冲突和协议错误:和板子的协议不匹配,先查看协议,检查硬件连接是否正确,确保SPI主设备和从设备之间的通信协议和数据格式设置正确。检查SPI设备的地址、片选信号等设置是否正确。确保主设备和从设备之间的通信时序和协议一致。检查设备的文档和规格说明,确保了解正确的配置和操作方法。

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

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

相关文章

Linux四种I/O模型

一.四种模型 阻塞式IO&#xff0c;非阻塞式IO&#xff0c;信号驱动IO&#xff0c;IO多路复用 二.阻塞式IO 特点&#xff1a;最简单&#xff0c;最常用&#xff0c;效率低 阻塞I/O 模式是最普遍使用的I/O 模式 系统默认状态&#xff0c;套接字建立后所处于的模式就是阻塞I/O 模式…

国家网络安全周2023时间是什么时候?有什么特点?谁举办的?

国家网络安全周2023时间是什么时候&#xff1f; 2023年国家网络安全宣传周将于9月11日至17日在全国范围内统一开展。其中开幕式等重要活动将在福建省福州市举行。今年网安周期间&#xff0c;除开幕式外&#xff0c;还将举行网络安全博览会、网络安全技术高峰论坛、网络安全微视…

【Git】万字git与gitHub

&#x1f384;欢迎来到边境矢梦的csdn博文&#x1f384; &#x1f384;本文主要梳理在git和GitHub时的笔记与感言 &#x1f384; &#x1f308;我是边境矢梦&#xff0c;一个正在为秋招和算法竞赛做准备的学生&#x1f308; &#x1f386;喜欢的朋友可以关注一下&#x1faf0;&…

【FAQ】安防监控/视频汇聚/云存储/智能视频分析平台EasyCVR显示CPU过载,如何解决?

视频云存储/安防监控/视频汇聚平台EasyCVR基于云边端智能协同&#xff0c;支持海量视频的轻量化接入与汇聚、转码与处理、全网智能分发、视频集中存储等。安防视频监控系统EasyCVR拓展性强&#xff0c;视频能力丰富&#xff0c;具体可实现视频监控直播、视频轮播、视频录像、云…

线性代数的本质(四)——行列式

文章目录 行列式二阶行列式 n n n 阶行列式行列式的性质克拉默法则行列式的几何理解 行列式 二阶行列式 行列式引自对线性方程组的求解。考虑两个方程的二元线性方程组 { a 11 x 1 a 12 x 2 b 1 a 21 x 1 a 22 x 2 b 2 \begin{cases} a_{11}x_1a_{12}x_2b_1 \\ a_{21}x_…

无涯教程-JavaScript - COLUMNS函数

描述 COLUMNS函数返回数组或引用中的列数。 语法 COLUMNS (array)争论 Argument描述Required/OptionalarrayAn array or array formula, or a reference to a range of cells for which you want the number of Columns.Required Notes COLUMNS(1:1)返回Excel中的列数,即…

【python手写算法】numpy实现简易神经网络和反向传播算法【1】

import numpy as npdef dense(A,W):Znp.matmul(A,W)#矩阵乘法return 1/(1np.exp(-Z))if __name__ __main__:leanring_rate100Anp.array([[200.0,17.0]])# Wnp.array([[1,-3,5],# [-2,4,-6]])# bnp.array([[-1,1,2]])W1 np.array([[0., -10, 4],[-1,3,2]])W2np.ar…

STM32单片机——串口通信(轮询+中断)

STM32单片机——串口通信&#xff08;轮询中断&#xff09; 串口通信相关概念HAL库解析及CubeMX工程配置与程序设计常用函数介绍CubeMX工程配置HAL库程序设计&#xff08;轮询中断&#xff09;轮询数据收发中断收发数据 固件库程序设计及实现固件库配置流程结构体配置及初始化程…

React复习日志大纲

文章目录 React基础篇创建项目启动项目项目目录说明调整项目src剩余目录01基本使用02 列表渲染03 条件渲染04 样式处理05 函数和类组件创建和渲染06 事件绑定07 事件对象e08 传递额外参数09 组件状态修改10 受控组件11 非受控组件12 组件通信父传子13 Props说明14 组件通信子传…

Golang代码漏洞扫描工具介绍——govulncheck

Golang Golang作为一款近年来最火热的服务端语言之一&#xff0c;深受广大程序员的喜爱&#xff0c;笔者最近也在用&#xff0c;特别是高并发的场景下&#xff0c;golang易用性的优势十分明显&#xff0c;但笔者这次想要介绍的并不是golang本身&#xff0c;而且golang代码的漏洞…

Linux网络编程

一.协议 1.1什么是协议 从应用的角度出发&#xff0c;协议可理解为“规则”&#xff0c;是数据传输和数据的解释的规则。 假设&#xff0c;A、B双方欲传输文件。规定: 第一次&#xff0c;传输文件名&#xff0c;接收方接收到文件名&#xff0c;应答OK给传输方; 第二次&#xff…

【每日一题】34. 在排序数组中查找元素的第一个和最后一个位置

34. 在排序数组中查找元素的第一个和最后一个位置 - 力扣&#xff08;LeetCode&#xff09; 给你一个按照非递减顺序排列的整数数组 nums&#xff0c;和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。 如果数组中不存在目标值 target&#xff0c;返回 […

vscode-server

1know_host清除 2 删除服务器里的home/user/.vscode-server&#xff08;不是根root下的vscode-server&#xff09;&#xff0c;删除时用户名保持一致。 3 ssh配置文件 /etc/ssh/sshd_config[想改变,使用root&#xff0c;修改文件权限] 4 删除修改后&#xff0c;重启Windows下…

打造生产级Llama大模型服务

对于任何想要尝试人工智能或本地LLM&#xff0c;又不想因为意外的云账单或 API 费用而感到震惊的人&#xff0c;我可以告诉你我自己的旅程是如何的&#xff0c;以及如何开始使用廉价的消费级硬件执行Llama2 推理 。 这个项目一直在以非常活跃的速度发展&#xff0c;这使得它非…

父域 Cookie实现sso单点登录

单点登录&#xff08;Single Sign On, SSO&#xff09;是指在同一帐号平台下的多个应用系统中&#xff0c;用户只需登录一次&#xff0c;即可访问所有相互信任的应用系统。Cookie 的作用域由 domain 属性和 path 属性共同决定。在 Tomcat 中&#xff0c;domain 属性默认为当前域…

Python浪漫星空

系列文章 序号文章目录直达链接1浪漫520表白代码https://want595.blog.csdn.net/article/details/1306668812满屏表白代码https://want595.blog.csdn.net/article/details/1297945183跳动的爱心https://want595.blog.csdn.net/article/details/1295031234漂浮爱心https://wan…

校园网web免认真,大量服务器

服务器加满了&#xff0c;没有几个人来&#xff0c;传点图片看实力 什么方法解web认证方式校园网&#xff1f; 一般的校园网是对学生免费开放的&#xff0c;假如你是学生输入学号密码上网就是了&#xff0c;假如你不是那就是想蹭网了&#xff0c;再假如你不想让管理员或上网行为…

数据分享|R语言逻辑回归、线性判别分析LDA、GAM、MARS、KNN、QDA、决策树、随机森林、SVM分类葡萄酒交叉验证ROC...

全文链接:http://tecdat.cn/?p27384 在本文中&#xff0c;数据包含有关葡萄牙“Vinho Verde”葡萄酒的信息&#xff08;点击文末“阅读原文”获取完整代码数据&#xff09;。 介绍 该数据集&#xff08;查看文末了解数据获取方式&#xff09;有1599个观测值和12个变量&#xf…

pdf添加水印

给pdf文件添加水印 引入依赖 <dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.13.3</version></dependency>添加水印 package com.it2.pdfdemo02.util;import com.itextpdf.tex…

用 Pytest+Allure 生成漂亮的 HTML 图形化测试报告

本篇文章将介绍如何使用开源的测试报告生成框架 Allure 生成规范、格式统一、美观的测试报告。 通过这篇文章的介绍&#xff0c;你将能够&#xff1a; 将 Allure 与 Pytest 测试框架相结合&#xff1b; 如何定制化测试报告内容 执行测试之后&#xff0c;生成 Allure 格式的测…