CAN总线协议的理解以及移植stm32代码并使用

什么是CAN总线协议

是一种异步半双工的通讯协议,只有CAN_High与CAN_Low两条信号线。
有两种连接形式:闭环总线(高速)和开环总线(远距离)

他使用的是一种差分信号来传输电信号
所谓差分信号就是两条信号线电平之差,来传输电信号1/0,

该方式优点是抗干扰能力强、可以远距离传输,因为当信号线过长的时候电阻累积过大,使得传输到的电信号不准确,而差分信号是使用两条信号线电平差,两条信号线只要长度相似信号误差都不会很大。

电位差为0时为逻辑1,电位差>=2.0时为逻辑0。

CAN协议的协议层原理

协议层内规定了一个数据位有四个段,分别为:SS段、PTS段、PBS1段、PBS2段
1Tq为1个时基单元
在这里插入图片描述
SS段:是同步段,若通讯节点检测到总线上信号的跳变沿被包含在 SS 段的范围之内,则表示节点与总线的时序是同步的,当节点与总线同步时,采样点采集到的总线电平即可被确定为该位的电平。SS 段的大小固定为 1Tq。

PTS段:是传播时间段,这个时间段是用于补偿网络的物理延时时间。是总线上输入比较器延时和输出驱动器延时总和的两倍。PTS 段的大小可以为 1~8Tq。

PBS1段:PBS1 译为相位缓冲段,补偿SS段的误差,它的时间长度在重新同步的时候可以加长,如下图相位超前,既ss段比预计的时间超期一个时间基准,可以通过PBS1段校准。

PBS2段:这是另一个相位缓冲段,它的时间长度在重新同步时可以缩短,补偿整个数据对齐。
在这里插入图片描述

CAN报文

当节点1与节点2同时发送报文时,总线电平会有优先级,按照ID优先级选择其1
当节点1或节点2发现自身电平和总线电平不同时会停止发送报文,总线显性电平为0,有1和0时总线电平取0

帧种类及用途:

在这里插入图片描述

数据帧的结构

在这里插入图片描述
仲裁段:0为最高优先级,用于总线判断优先级
控制段:

  • RTR位为0表示数据帧(发送数据的),为1表示遥控帧(请求数据的)
  • IDE位为0表示标准格式,为1表示为扩展格式
  • DLE表示本报文的数据有多少个字节,4个数据位,不过只能写入0~8
  • SRR 位 ,只存在于扩展格式,它用于替代标准格式中的 RTR位。由于扩展帧中的 SRR 位为隐性位,RTR 在数据帧为显性位,所以在两个 ID 相同的标准格式报文与扩展格式报文中,标准格式的优先级较高。

CRC 段:为了保证报文的正确传输,CAN 的报文包含了一段 15 位的 CRC 校验码,一旦接收节点算出的CRC 码跟接收到的 CRC 码不同,则它会向发送节点反馈出错信息,利用错误帧请求它重新发送。CRC 部分的计算一般由 CAN 控制器硬件完成,出错时的处理则由软件控制最大重发数。在 CRC 校验码之后,有一个 CRC 界定符,它为隐性位,主要作用是把 CRC 校验码与后面的 ACK段间隔起来。

ACK 段:ACK 段包括一个 ACK 槽位,和 ACK 界定符位。类似 I2C 总线,在 ACK 槽位中,发送节点发送的是隐性位,而接收节点则在这一位中发送显性位以示应答。在 ACK 槽和帧结束之间由 ACK 界定符间隔开。

STM32的CAN外设

stm32f103c8芯片中带有CAN的控制器,但不带CAN的收发器,所以如果想用最小系统板进行CAN外设实验,需要自己连接CAN的收发器。

在这里插入图片描述

CAN内部框图剖析

有一下五个主要部分

  • CAN控制内核
  • CAN发送邮箱
  • CAN接收fifo
  • 验收筛选器
  • 整体控制逻辑

stm32的CAN外设寄存器

主要使用的功能:

  • DBF调试冻结功能:可设置CAN处于工作状态或者禁止收发状态,静止收发时仍可访问接收FIFO的数据
  • TTCM:生成时间戳,在CAN_RDTxR和CAN_TDTxR中保存
  • ABOM:自动离线管理,在节点检测到它发送错误或者接收错误超过一定值时会自动进入离线状态。
  • AWUM:自动唤醒,如果软件进入CAN外设的低功耗模式,如果使能了该功能,当CAN总线检测到活动时自动换醒。
  • NART:自动重传,报文发送失败会自动重传至成功为止
  • RFLM:锁定模式,使能该模式的话,只有6个接收FIFO如果6个满了还未处理则第7个来时不接入FIFO,否则会覆盖第一个FIFO
  • TXFP:报文发送优先级判断方法:ID优先级/时序优先级

寄存器

工作模式寄存器CAN_BTR

寄存器的31位30位分别控制两个模式在这里插入图片描述
31位:是否静默
30位:是否回环
23-20位:TS2,表示TSS2占用多少个时间单元,TSS2=Tq*(TS2+1)
19-15位:TS1,与上同理
25-24位:SJW,定义每次可活动增减TS1与TS2数据位的最大值(调整时序时最大增减的时间单元个数)
9-0位:BRP,波特率分频器Tq=(BRP+1)*tPCLK

其他寄存器

  • 标识符寄存器CAN_ITxR:存储发送报文的ID、扩展ID,IDE位和RTR位,其中的TMIDxR_TxRQ位置1即可以发送数据
  • 数据长度控制寄存器CAN_TDTxR:存储待发送报文的DLC段
  • 低位数据寄存器CAN_TDLxR:存储发送报文的Date0~Date3
  • 高位数据寄存器CAN_TDHxR:存储发送报文的Date4~Date7

CAN的接收邮箱

每个CAN有两个接收FIFO邮箱,每个邮箱有3级
两个FIFO接收邮箱公用28个筛选器组(f103是14个、f105是28个)
Alt

掩码模式

一个筛选器有两个寄存器,在上图的掩码映射中,写入1就代表ID寄存器中的这一位需要筛选,如果全写入0,即不筛选。

stm32的CAN代码移植使用

在hal_can.h文件中

#define GPIO_CAN_RX_Pin                 GPIO_Pin_8
#define GPIO_CAN_TX_Pin                 GPIO_Pin_9

初始化CAN的GPIO重定义引脚

/****************************************************************************
*@*名称 : hal_CAN_GPIO_Config
*@*功能 : CAN的引脚口(PB8R/9T)
*@*形参 : 无
*@*返回值 : 无
****************************************************************************/
static void hal_CAN_GPIO_Config(void)
{
	GPIO_InitTypeDef  GPIO_InitStruct_CAN_TX;
	GPIO_InitTypeDef  GPIO_InitStruct_CAN_RX;
	

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	GPIO_PinRemapConfig(GPIO_Remap1_CAN1,ENABLE);
	
	GPIO_InitStruct_CAN_TX.GPIO_Pin = GPIO_CAN_TX_Pin ;
	GPIO_InitStruct_CAN_TX.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStruct_CAN_TX.GPIO_Speed = GPIO_Speed_50MHz;	
	
	GPIO_Init(GPIOB,&GPIO_InitStruct_CAN_TX);
	
	GPIO_InitStruct_CAN_RX.GPIO_Pin = GPIO_CAN_RX_Pin ;
	GPIO_InitStruct_CAN_RX.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStruct_CAN_RX.GPIO_Speed = GPIO_Speed_50MHz;	
	
	GPIO_Init(GPIOB,&GPIO_InitStruct_CAN_RX);
}

初始化CAN的模式

这里需要提一下,因为核心板没有CAN的接收器,如果要验证功能,要使用回环模式

/****************************************************************************
*@*名称 : hal_CAN_Mode_Config
*@*功能 : 定义CAN模块的模式
*@*形参 : 无
*@*返回值 : 无
****************************************************************************/
static void hal_CAN_Mode_Config(void)
{
	CAN_InitTypeDef	GAN_InitStruct_Mode;
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);

	/*CAN寄存器初始化*/
	CAN_DeInit(CAN1);
	CAN_StructInit(&GAN_InitStruct_Mode);
	
	GAN_InitStruct_Mode.CAN_Mode = CAN_Mode_Normal; //普通工作模式,CAN_Mode_LoopBack为回环模式
	GAN_InitStruct_Mode.CAN_SJW = CAN_SJW_1tq; //可活动时间单元1tq
	GAN_InitStruct_Mode.CAN_BS1 = CAN_BS1_5tq;
	GAN_InitStruct_Mode.CAN_BS2 = CAN_BS2_3tq;
	/*CAN单元初始化*/
	GAN_InitStruct_Mode.CAN_TTCM=DISABLE;			   //MCR-TTCM  关闭时间触发通信模式使能
	GAN_InitStruct_Mode.CAN_ABOM=ENABLE;			   //MCR-ABOM  自动离线管理 
	GAN_InitStruct_Mode.CAN_AWUM=ENABLE;			   //MCR-AWUM  使用自动唤醒模式
	GAN_InitStruct_Mode.CAN_NART=DISABLE;			   //MCR-NART  禁止报文自动重传	  DISABLE-自动重传
	GAN_InitStruct_Mode.CAN_RFLM=DISABLE;			   //MCR-RFLM  接收FIFO 锁定模式  DISABLE-溢出时新报文会覆盖原有报文  
	GAN_InitStruct_Mode.CAN_TXFP=DISABLE;			   //MCR-TXFP  发送FIFO优先级 DISABLE-优先级取决于报文标示符 
	
	/* CAN Baudrate = 1 MBps (1MBps已为stm32的CAN最高速率) (CAN 时钟频率为 APB1 = 36 MHz) */
	GAN_InitStruct_Mode.CAN_Prescaler =4;		   BTR-BRP 波特率分频器  定义了时间单元的时间长度 36/(1+5+3)/4=1 Mbps
	
	CAN_Init(CAN1,&GAN_InitStruct_Mode)
}

初始化筛选器

/****************************************************************************
*@*名称 : hal_CAN_Filter_Config
*@*功能 : 初始化CAN模块的过滤器
*@*形参 : 无
*@*返回值 : 无
****************************************************************************/
static void hal_CAN_Filter_Config(void)
{
	CAN_FilterInitTypeDef GAN_InitStruct_Filter0;
	CAN_FilterInitTypeDef GAN_InitStruct_Filter1;
	
	GAN_InitStruct_Filter0.CAN_FilterActivation = ENABLE;			//使能筛选器
	GAN_InitStruct_Filter0.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0 ;				//筛选器被关联到FIFO0
	GAN_InitStruct_Filter0.CAN_FilterIdHigh = (((CAN_TargetID<<3)|CAN_Id_Extended|CAN_RTR_Data))>>16;
	GAN_InitStruct_Filter0.CAN_FilterIdLow = ((CAN_TargetID<<3)|CAN_Id_Extended|CAN_RTR_Data);
	GAN_InitStruct_Filter0.CAN_FilterMaskIdHigh = 0xFFFF;			//筛选器高16位每位必须匹配
	GAN_InitStruct_Filter0.CAN_FilterMaskIdLow= 0xFF00;			//筛选器低16位每位必须匹配
	GAN_InitStruct_Filter0.CAN_FilterMode = CAN_FilterMode_IdMask;		//工作在掩码模式
	GAN_InitStruct_Filter0.CAN_FilterNumber = 0;
	GAN_InitStruct_Filter0.CAN_FilterScale = CAN_FilterScale_32bit;	//筛选器位宽为单个32位。
	
	CAN_FilterInit(&GAN_InitStruct_Filter0);
	/*CAN通信中断使能*/
	
	
	GAN_InitStruct_Filter1.CAN_FilterActivation = ENABLE;			//使能筛选器
	GAN_InitStruct_Filter1.CAN_FilterFIFOAssignment = CAN_Filter_FIFO1 ;				//筛选器被关联到FIFO1
	GAN_InitStruct_Filter1.CAN_FilterIdHigh = ((CAN_FIFO1_ID<<3)|CAN_Id_Extended|CAN_RTR_Data)>>16;
	GAN_InitStruct_Filter1.CAN_FilterIdLow = ((CAN_FIFO1_ID<<3)|CAN_Id_Extended|CAN_RTR_Data);
	GAN_InitStruct_Filter1.CAN_FilterMaskIdHigh = 0xFFFF;			//筛选器高16位每位必须匹配
	GAN_InitStruct_Filter1.CAN_FilterMaskIdLow= 0xFF00;			//筛选器低16位每位必须匹配
	GAN_InitStruct_Filter1.CAN_FilterMode = CAN_FilterMode_IdMask;		//工作在掩码模式
	GAN_InitStruct_Filter1.CAN_FilterNumber = 2;
	GAN_InitStruct_Filter1.CAN_FilterScale = CAN_FilterScale_32bit;	//筛选器位宽为单个32位。
	
	CAN_FilterInit(&GAN_InitStruct_Filter1);
	/*CAN通信中断使能*/
	CAN_ITConfig(CAN1, CAN_IT_FMP1, ENABLE);
	CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);
}

这里我打开了两个接收FIFO
打开两个接收FIFO时需要注意:
该筛选器关联到的FIFO:GAN_InitStruct_Filter1.CAN_FilterFIFOAssignment
筛选器编号:GAN_InitStruct_Filter1.CAN_FilterNumber
这里不要配置好了一个,另一个就直接复制结构体导致错误了。

筛选器掩码配置要注意:因为低3位是配置RTR的标志位,高29位才是掩码ID配置,所以一开始将掩码ID左移3位,然后在或上IDE 位标志“宏 CAN_ID_EXT”以及RTR 位标
“宏 CAN_RTR_DATA”然后再赋值入筛选器的高八位和低八位

GAN_InitStruct_Filter0.CAN_FilterIdHigh = (((CAN_TargetID<<3)|CAN_Id_Extended|CAN_RTR_Data))>>16;
GAN_InitStruct_Filter0.CAN_FilterIdLow = ((CAN_TargetID<<3)|CAN_Id_Extended|CAN_RTR_Data);
GAN_InitStruct_Filter0.CAN_FilterMaskIdHigh = 0xFFFF; //筛选器高16位每位必须匹配
GAN_InitStruct_Filter0.CAN_FilterMaskIdLow= 0xFF00; //筛选器低16位每位必须匹配

初始化CAN的外设中断NVIC

/****************************************************************************
*@*名称 : hal_CAN_NVIC_Config
*@*功能 : 初始化CAN模块的中断
*@*形参 : 无
*@*返回值 : 无
****************************************************************************/
static void hal_CAN_NVIC_Config(void)
{
	  NVIC_InitTypeDef NVIC_InitStructure;
    /* Configure one bit for preemption priority */
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
    /*中断设置*/
    NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;	   //CAN1 RX0中断
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;		   //抢占优先级0
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;			   //子优先级为0
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
	
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
    /*中断设置*/
    NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX1_IRQn;	   //CAN1 RX0中断
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;		   //抢占优先级0
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;			   //子优先级为1
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

这里要注意,想要打开两个FIFO的中断是有区别的
FIFO0的中断通道名称是:USB_LP_CAN1_RX0_IRQn
FIFO1的中断通道名称是:CAN1_RX1_IRQn

FIFO0的中断函数名称是:void USB_LP_CAN1_RX0_IRQHandler(void)
FIFO1的中断函数名称是:void CAN1_RX1_IRQHandler(void)

CAN发送函数

/****************************************************************************
*@*名称 : CAN_SetMsg
*@*功能 : 配置CAN的发送信箱进行发送
*@*形参 : CanTxMsg型的结构体地址,发送的拓展ID,发送的数据存放地址
*@*返回值 : 无
****************************************************************************/
void CAN_SetMsg(CanTxMsg *TxMessage,uint32_t EXT_ID ,uint8_t* Data)
{	  
	uint8_t ubCounter = 0;

  //TxMessage.StdId=0x00;						 
  TxMessage->ExtId=EXT_ID;					 //使用的扩展ID
  TxMessage->IDE=CAN_ID_EXT;					 //扩展模式
  TxMessage->RTR=CAN_RTR_DATA;				 //发送的是数据
  TxMessage->DLC=8;							 //数据长度为8字节
	
	/*设置要发送的数据0-7*/
	for (ubCounter = 0; ubCounter < 8; ubCounter++)
  {
    TxMessage->Data[ubCounter] = Data[ubCounter];
  }
	
	
	CAN_Transmit(CAN1, TxMessage);//将TMIDxR_TxRQ标志位置1,发送CAN发送邮箱的报文发送出去
}

接收中断函数编写

/****************************************************************************
*@*名称 : USB_LP_CAN1_RX0_IRQHandler
*@*功能 : CAN模块的FIFO0接收中断函数
*@*形参 : 无
*@*返回值 : 无
****************************************************************************/
void USB_LP_CAN1_RX0_IRQHandler(void)
{
	/*从邮箱中读出报文*/
	CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);

	/* 比较ID是否为0x1111 */ 
	if((RxMessage.ExtId >= 0x1110) && (RxMessage.IDE==CAN_ID_EXT) && (RxMessage.DLC==8) )
	{
		CAN_flag = 1; 					       //接收成功  
	}
	else
	{
		CAN_flag = 0; 					   //接收失败
	}
}

总结

在以上函数中我打开了两个接收FIFO,希望能一次性接收6个CAN的报文,但在实际实验中,连续发送6个报文,只能接收3个成功。
查了好久的原因还是没有解决该问题,如果有大佬知道为什么,希望能帮我解惑。

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

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

相关文章

Linux防火墙firewalld(粗糙版)

上篇是iptables的增删改查 自定义链&#xff1a; systemctl stop firewalld setenforce 0 iptables -N lmn iptables -vnL iptables -t filter -vnL 修改链名&#xff1a; iptables -E lmn ky01 iptables -t filter -vnL iptables -t filter -I ky01 -p icmp -j ACCEP…

蓝桥杯每日一题2023.11.8

题目描述 题目分析 对于输入的abc我们可以以a为年也可以以c为年&#xff0c;将abc,cab,cba这三种情况进行判断合法性即可&#xff0c;注意需要排序去重&#xff0c;所以考虑使用set 此处为纯模拟的写法&#xff0c;但使用循环代码会更加简洁。 方法一&#xff1a; #include&…

基于java web的计算机office课程平台设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

无人机航迹规划:七种智能优化算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划--提供MATLAB代码

一、七种算法&#xff08;DBO、LO、SWO、COA、LSO、KOA、GRO&#xff09;简介 1、蜣螂优化算法DBO 蜣螂优化算法&#xff08;Dung beetle optimizer&#xff0c;DBO&#xff09;由Jiankai Xue和Bo Shen于2022年提出&#xff0c;该算法主要受蜣螂的滚球、跳舞、觅食、偷窃和繁…

阿里云Intel Xeon Platinum可扩展处理器性能说明

阿里云Intel Xeon Platinum可扩展处理器性能如何&#xff1f;目前云服务器ECS经济型e实例采用该款CPU型号&#xff0c;正好阿里云服务器网购买了一台2核CPU、2G内存、3M固定带宽、40G ESSD Entry云盘&#xff0c;一年优惠价99元&#xff0c;第二年续费不涨价依旧是99元一年&…

Idea安装使用教程~

在本文中&#xff0c;我们将提供关于如何安装 IntelliJ IDEA 的详细步骤。如果您是初学者或只是想尝试一下 IDEA&#xff0c;我们建议您下载 Community 版。如果您需要更多高级功能&#xff0c;可以选择 Ultimate 版。 步骤一&#xff1a;下载 IntelliJ IDEA 首先&#xff0c;…

使用表单登录方法模拟登录通信人家园,要求发送登录请求后打印出来的用户名下的用户组类别

目标网站&#xff1a;https://www.txrjy.com/forum.php 一、进入网页&#xff0c;右键“检查” 二、输入用户名和密码&#xff0c;点击“登录”&#xff0c;点击“Network”,上划加载项找到蓝色框中的内容 三、点击第一个加载项&#xff0c;找到URL 四、相关代码&#xff1a; …

渗透必备:Proxifier玩转代理

目录 0# 概述 1# Proxifier介绍 2# 操作过程 2.1 配置代理服务器 2.2 配置代理规则 3# Proxifier玩转代理 3.0 配置说明 3.1 通过Proxifier进行内网渗透 3.2 通过Proxifier将VM虚拟机代理 3.3 通过Proxifier进行小程序抓包 3.4 补充 4# 总结 0# 概述 在日常的渗透过…

Pytorch模型使用与修改、保存与加载

模型的使用及修改、保存与加载 以图像处理中torchvision为例&#xff0c;PyTorch通过torchvision.models模块提供了更多的预训练模型. 在图像分类当中&#xff0c;包括许多模型 import torchvision import warnings import torch warnings.filterwarnings("ignore&quo…

C++ 代码实例:并查集简单创建工具

文章目录 前言代码仓库代码说明main.cppMakefile 结果总结参考资料作者的话 前言 C 代码实例&#xff1a;并查集简单创建工具。 代码仓库 yezhening/Programming-examples: 编程实例 (github.com)Programming-examples: 编程实例 (gitee.com) 代码 说明 简单地创建并查集注…

软件测试|PO设计模式在 UI 自动化中的实践

PO的思想最早是2013年由IT大佬Martin Flower提出的&#xff1a;https://martinfowler.com/bliki/PageObject.html 没错&#xff0c;就是他 — 没错&#xff0c;就是他 — 在他的文章里有这样一张经典样图,图片中展示了测试代码中直接操作HTML元素和使用PO模式将page对象封装成…

“锡安主义”贝尔福宣言希伯来抵抗运动犹太启蒙改革运动奋锐党闪米特人雅利安人

目录 “锡安主义” 贝尔福宣言 希伯来抵抗运动 犹太启蒙改革运动 奋锐党 闪米特人 雅利安人 “锡安主义” “锡安主义”是一种政治和民族运动&#xff0c;旨在支持并促进犹太人建立自己的国家并在历史上与宗教上的祖先之地——巴勒斯坦地区建立一个独立的国家。这一运动…

C++11常用特性

目录 1、{}初始化 2、auto 3、decltype 4、nullptr 5、范围for 6、STL容器 7、右值引用 ①左值引用和右值引用 ②移动构造 ③移动赋值 ④万能引用与完美转发 8、新的类功能 9、可变模版参数 10、lambda表达式 捕捉列表的使用 [val]&#xff1a;传值捕捉 [&…

GPTZero:论文打假神器

记住这张脸他是全美学生的公敌。 别的学生在AI大浪潮间翻云覆雨&#xff0c;有的用GPT代写作业&#xff0c;有的用GPT代工论文&#xff0c;大家都忙的不亦乐乎。 正在大家都在欢呼雀跃跟作业拜拜时&#xff0c;就是这个小伙&#xff0c;普林斯顿大学的华裔小天才Edward Tian…

C++/Qt 小知识记录4

工作中遇到的一些小问题&#xff0c;总结的小知识记录&#xff1a;C/Qt 小知识4 mysql导入*.sql文件提示连接超时等问题mysql局域网内访问VLC低版本的匹配QLineEdit的正则表达式限制获取windows下已加载磁盘盘符QLabel自动换行QElapsedTimer间隔计时自定义Class作为Key需要重载…

Spark SQL

Spark SQL 本文来自 B站 黑马程序员 - Spark教程 &#xff1a;原地址 第一章 SparkSql快速入门 1.1 什么是SparkSql Spark Sql is Spark’s module for working with strutured data. Spark Sql是Spark的模块&#xff0c;用于处理海量结构化数据 限量&#xff1a;结构化数据…

Tomcat的类加载器

详情可以参考&#xff1a;https://tomcat.apache.org/tomcat-10.1-doc/class-loader-howto.html 简要说明 Tomcat安装了多种类加载器&#xff0c;以便容器的不同部分、容器中的应用访问能够不同的类和资源。 在Java环境中&#xff0c;类加载器被组织为父-子树的形式。通常情况…

文件包含漏洞培训

CTF介绍 MISC(Miscellaneous)类型,即安全杂项,题目或涉及流量分析、电子取证、人肉搜索、数据分析等等。CRYPTO(Cryptography)类型,即密码学,题目考察各种加解密技术,包括古典加密技术、现代加密技术甚至出题者自创加密技术。PWN类型,PWN在黑客俚语中代表着攻破、取得权限…

技术分享 | app自动化测试(Android)-- 属性获取与断言

断言是 UI 自动化测试的三要素之一&#xff0c;是 UI 自动化不可或缺的部分。在使用定位器定位到元素后&#xff0c;通过脚本进行业务操作的交互&#xff0c;想要验证交互过程中的正确性就需要用到断言。 常规的UI自动化断言 分析正确的输出结果&#xff0c;常规的断言一般包…

Qt实现动态桌面小精灵(含源码)

目录 一、设计思路 二、部分源码演示 三、源码地址 🌈write in front🌈 🧸大家好,我是三雷科技.希望你看完之后,能对你有所帮助,不足请指正!共同学习交流. 🆔本文由三雷科技原创 CSDN首发🐒 如需转载还请通知⚠️ 📝个人主页:三雷科技🧸—CSDN博客 🎁欢…