STM32—CAN通信

news2024/11/25 11:00:17

文章目录

  • 一、CAN通信简介
    • 1.1 CAN简介
    • 1.2 CAN协议特点
    • 1.3 CAN通信的帧类型
    • 1.4 数据帧结构
    • 1.5 CAN的位时序
    • 1.6 CAN的仲裁功能
  • 二、STM32F1的CAN
    • 2.1 bxCAN简介
    • 2.2 bxCAN工作模式
      • 2.2.1 初始化模式
      • 2.2.2 正常模式
      • 2.2.3 睡眠模式
      • 2.2.4 静默模式
      • 2.2.5 环回模式
    • 2.3 位时序和波特率
  • 三、CAN配置步骤
  • 四、实战项目
    • 4.1 CAN初始化
    • 4.2 CAN发送
    • 4.3 CAN接收
    • 4.4 CAN收发测试
    • 4.5 补充说明

一、CAN通信简介

1.1 CAN简介

CAN全称是Controller Area Network,控制器局域网络,是ISO国际标准化的串行通信协议。CAN是国际上应用最广泛的现场总线之一。CAN通信只有两根信号线,分别是CAN_H和CAN_L,CAN 控制器根据这两根线上的电位差来判断总线电平。总线申平分为显性电平和隐性申平,二者必居其一。发送方通过使总线电平发生变化,将消息发送给接收方。

  • 2.0V---------逻辑0------显性电平
  • 0 V-----------逻辑1------隐性电平

CAN总线遵从“线与”机制,显性电平可以覆盖隐性电平。这就导致只有所有节点都发送隐形电平时总线才处于隐性状态
CAN通信示意图

1.2 CAN协议特点

  • 多主控
    在总线空闲时所有单元都可以发送消息。当两个以上单元发送消息时,会根据标识符(ID)决定发送的优先级。
  • 通信速度较快,最高可达1Mbps。通信距离较远
    当速度为1Mbps时,传输距离小于40m。当速度小于500Kbps时,传输距离最远可达10Km。
  • 具有错误检测,错误通知和错误恢复功能
    CAN总线上的任意一个单元都可以检测错误,当任意一个单元检测出错误时,会立刻通知其他单元。正在发送消息的单元一旦检测出错误,会强制结束当前发送。强制结束的单元会不断重新发送消息,直到发送成功。
  • 故障封闭功能
    CAN可以判断出错误的类型是总线上暂时的数据错误还是持续的数据错误。当总线上持续出现数据错误时,可以将引起故障的单元从总线上隔离出去。
  • 连接节点多
    理论上连接单元没有数量限制,但是连接单元越多,速度就会越低。

1.3 CAN通信的帧类型

CAN通信有5种帧类型

帧类型帧用途
数据帧用于发送单元向接收单元传送数据的帧
遥控帧用于接收单元向具有相同ID的发送单元请求数据的帧
错误帧用于当检测出错误时向其它单元通知错误的帧
过载帧用于接收单元通知其尚未做好接收准备的帧
帧间隔用于将数据帧及遥控锁与前面的帧分离开来的帧

在上述的几种帧里,数据很和遥控帧有标准帧扩展帧两种。标准帧有11位ID,扩展帧有29位ID。

1.4 数据帧结构

CAN通信数据帧的构成如下

CAN通信数据帧结构

  • 帧起始
    表示数据帧开始的段,标准帧和扩展帧的帧起始都是由1个位的显性电平组成。
  • 仲裁段
    表示数据帧优先级的段。
    仲裁段

RTR是用来表示是否是远程帧(遥控帧)。RTR为0是数据帧,RTR为1是远程帧。扩展帧中的IDE是标识符的选择位,如果为0,使用标准标识符,如果为1,使用扩展标识符。扩展帧的SRR相当于标准帧中的RTR位。标准帧的ID禁止高七位是隐性电平

  • 控制段
    控制段由6位构成,表示数据段的字节数。
    控制段
    扩展帧的r0r1是保留位,保留位必须全部以显性电平发送。DLC是数据的长度码,数据的字节数范围是0~8。IDE是标识符的选择位,如果为0,使用标准标识符,如果为1,使用扩展标识符。
  • 数据段
    数据段可以包含0~8个字节的数据。从MSB(最高位)开始传输。标准帧和扩展帧的数据段相同。
  • CRC段
    CRC段用于校验,检查帧传输是否存在错误。CRC段包含15位CRC序列和1位CRC界定符。标准帧和扩展帧的CRC段相同。
    CRC段
  • ACK段
    ACK段用来确认是否正常接收。由ACK槽和ACK界定符2位组成。标准帧和扩展帧的ACK段相同。
    ACK段
  • 帧结束
    由7位隐形电平组成,表示帧的结束。标准帧和扩展帧的帧结束相同。

1.5 CAN的位时序

由发送单元在非同步状态下每秒钟发送的位数称为位速率。一个位可以分成4段。

  • 同步段 SS
  • 传播时间段 PTS
  • 相位缓冲段1 PBS1
  • 相位缓冲段2 PBS2

上面的这些段由称为Time Quantum(Tq)的最小时间单位组成。1个位分成4个段,一个段又分成若干个Tq,这成为位时序
位构成
采样点是读取总线电平,并将读到的电平作为位值的点。

1.6 CAN的仲裁功能

在总线空闲态,最先开始发送消息的单元获得发送权。当多个单元同时开始发送时,各发送单元从仲裁段的第一位开始进行仲裁。连续输出显性电平最多的单元可继续发送

仲裁过程

二、STM32F1的CAN

2.1 bxCAN简介

STM32F1芯片自带bxCAN 控制器 (Basic Extended CAN),即基本扩展CAN,可与 CAN 网络进行交互,它支持 2.0A 和 B 版本的CAN 协议。STM32F1的bxCAN有以下特点

  • 支持 CAN 协议 2.0A 和 20B 主动模式
  • 波特率最高达 1Mbps
  • 支持时间触发通信
  • 具有 3 个发送邮箱
  • 具有 3 级深度的 2 个接收 FIFO
  • 可变的过滤器组(STM32F103ZET6有14个)

bxCAN模块可以完全自动地接收和发送CAN报文,且完全支持标准标识符(11位)和扩展标识符(29位)。

2.2 bxCAN工作模式

bXCAN有3个主要的工作模式:初始化模式正常模式睡眠模式。除此之外,还有测试模式,静默模式,环回模式。

2.2.1 初始化模式

首先看一下CAN主控制寄存器 (CAN_MCR)的INRQ位。

寄存器介绍CAN_MCR
寄存器CAN_MSR介绍

通过介绍可以直到,想要进入初始化模式,软件先将CAN_MCR的INRQ位置1。然后等待硬件将CAN主状态寄存器(CAN_MSR)的INAK位置1。此时进入初始化模式。

当bxCAN处于初始化模式时,禁止报文的接收和发送,并且CANTX引脚输出隐性位(高电平)。

2.2.2 正常模式

在初始化完成后,软件应该让硬件进入正常模式,以便正常接收和发送报文。继续看上面对于CAN主控制寄存器INRQ位的介绍。软件将INRQ位清0,可以使CAN从初始化模式进入正常模式。此时等待硬件将CAN主状态寄存器的INAK位清0即可。

2.2.3 睡眠模式

bxCAN可工作在低功耗的睡眠模式。在该模式下,bxCAN的时钟停止了,但软件仍然可以访问邮箱寄存器。

寄存器CAN_MSR介绍

可以看出,软件将CAN主控制寄存器的SLEEP置1,即可请求进入睡眠模式。清零该位,退出睡眠模式。另外,如果CAN_MCR寄存器的AWUM位为’1’,一旦检测到CAN总线的活动,硬件就自动对SLEEP位清’0’来唤醒bxCAN。

2.2.4 静默模式

将CAN_BTR寄存器的SILM位置’1’,来选择静默模式。

寄存器CAN_BTR介绍

在静默模式下,bxCAN可以正常地接收数据帧和远程帧,但只能发出隐性位,而不能真正发送报文。如果bxCAN需要发出显性位(确认位、过载标志、主动错误标志),那么这样的显性位在内部被接回来从而可以被CAN内核检测到,同时CAN总线不会受到影响而仍然维持在隐性位状态。因此,静默模式通常用于分析CAN总线的活动,而不会对总线造成影响-显性位(确认位、错误帧)不会真正发送到总线上。

静默模式

2.2.5 环回模式

将CAN_BTR寄存器的LBKM位置’1’,来选择环回模式。在环回模式下,bxCAN把发送的报文当作接收的报文并保存(如果可以通过接收过滤)在接收邮箱里。

寄存器CAN_BTR寄存器介绍

环回模式可用于自测试。为了避免外部的影响,在环回模式下CAN内核忽略确认错误(在数据/远程帧的确认位时刻,不检测是否有显性位)。在环回模式下,bxCAN在内部把Tx输出回馈到Rx输入上,而完全忽略CANRX引脚的实际状态。发送的报文可以在CANTX引脚上检测到。

环回模式

2.3 位时序和波特率

STM32将每一位分成三段

  • 同步段 SS
  • 时间段1 BS1
  • 时间段2 BS2

位时序

其中tpclk是APB1总线的时钟频率,默认为36MHz。

三、CAN配置步骤

  • 使能CAN时钟,将对应引脚复用映射为CAN功能
    STM32F103ZET6只有一个CAN,对应引脚如下
复用功能没有重映射部分重映射完全重映射
CAN_RXPA11PB8PD0
CAN_TXPA12PB9PD1

CAN_RX配置为上拉输入模式,CAN_TX配置为复用推挽输出。

  • 设置CAN工作模式,波特率等
    库函数提供了一个结构体和一个函数来配置。初始化函数为
uint8_t CAN_Init(CAN_TypeDef* CANx, CAN_InitTypeDef* CAN_InitStruct)

结构体成员如下

结构体成员作用
CAN_Prescaler设置Tq长度,范围为0~1023,实际为配置值加1
CAN_Mode设置CAN的工作模式
CAN_SJW指定CAN硬件允许延长或缩短位以执行重新同步的最大时间量,可以配置为1~4Tq
CAN_BS1设定BS1段的长度,范围是1~16Tq
CAN_BS2设定BS2段的长度,范围是1~8Tq
CAN_TTCM是否使用时间触发功能
CAN_ABOM是否使用自动离线管理,使用的话可以在结点离线后,适时的自动恢复,不需要软件干预
CAN_AWUM是否使用自动唤醒
CAN_NART是否使用自动重传
CAN_RFLM是否使用锁存接收,接收FIFO溢出时,不使能该功能,则新的会覆盖旧的。使能该功能,会丢弃新的数据。
CAN_TXFP设置发送报文优先级判定方法,使能时以报文发送邮箱的先后顺序发送,不使能,按照ID优先级发送。

波特率 = Fpclk1 / ((CAN_BS1 + CAN_BS2 + 1)* CAN_Prescaler)

  • 设置CAN筛选器(过滤器)
    库函数也提供了筛选器的配置函数
void CAN_FilterInit(CAN_FilterInitTypeDef* CAN_FilterInitStruct)

结构体内容如下

结构体成员作用
CAN_FilterIdHigh如果筛选器工作在32位模式,该成员存储ID的高16位。如果筛选器工作在16位模式,该成员存储的是完整的16位筛选ID。
CAN_FilterIdLow存储要筛选的ID,如果筛选器工作在32位模式,该成员存储ID的低16位。如果工作在16位模式,该成员存储第二个ID。
CAN_FilterMaskIdHigh存储要筛选的掩码。当筛选器工作在标识符模式,与上面的第一个成员功能相同。当筛选器工作在掩码模式时,改为存储的是掩码的高16位,或者是一个完整的16位掩码。
CAN_FilterMaskIdLow存储要筛选的掩码。当筛选器工作在标识符模式,与上面的第二个成员功能相同。当筛选器工作在掩码模式时,改为存储的是掩码的低16位,或者是一个完整的16位掩码。
CAN_FilterFIFOAssignment报文通过删选后,该报文存储到哪个FIFO,可选择FIFO0,FIFO1
CAN_FilterNumber选择要使用的筛选器编号,0~27
CAN_FilterMode设置筛选器的工作模式,可以设置为列表模式和掩码模式
CAN_FilterScale设置筛选器的位宽,32位或16位
CAN_FilterActivation是否激活筛选器
  • 选择CAN中断类型,开启中断
    库函数提供了一个中断的配置函数
void CAN_ITConfig(CAN_TypeDef* CANx, uint32_t CAN_IT, FunctionalState NewState)

CAN的中断类型有很多,这里就不再一一介绍了。

#define IS_CAN_IT(IT)        (((IT) == CAN_IT_TME) || ((IT) == CAN_IT_FMP0)  ||\
                             ((IT) == CAN_IT_FF0)  || ((IT) == CAN_IT_FOV0)  ||\
                             ((IT) == CAN_IT_FMP1) || ((IT) == CAN_IT_FF1)   ||\
                             ((IT) == CAN_IT_FOV1) || ((IT) == CAN_IT_EWG)   ||\
                             ((IT) == CAN_IT_EPV)  || ((IT) == CAN_IT_BOF)   ||\
                             ((IT) == CAN_IT_LEC)  || ((IT) == CAN_IT_ERR)   ||\
                             ((IT) == CAN_IT_WKU)  || ((IT) == CAN_IT_SLK))
  • CAN发送和接收消息
    CAN发送消息的函数是
uint8_t CAN_Transmit(CAN_TypeDef* CANx, CanTxMsg* TxMessage)

发送之前需要配置好消息的结构体,消息结构体成员如下

结构体成员作用
StdId存储报文的11位的标准标识符,范围是0x0~0x7FF
ExtId存储报文的29位扩展标识符,范围是0x0~0x1FFFFFFF
IDE配置使用哪个标识符,配置为STD,为标准帧。配置为EXT,为扩展帧。
RTR报文类型的标志,可以配置为CAN_RTR_Data,表示报文为数据帧。配置为CAN_RTR_Remote,表示报文为遥控帧。遥控帧没有数据段。
DLC存储数据段的长度,0~8。如果报文为遥控帧,该值配置为0。
Data[8]存储数据段数据

CAN接收函数为

void CAN_Receive(CAN_TypeDef* CANx, uint8_t FIFONumber, CanRxMsg* RxMessage)

CAN接收结构体与发送结构体基本相同,多了一个

结构体成员作用
FMI存储筛选器的编号,表示接收到的报文是从哪个筛选器进入FIFO的。
  • CAN状态获取
    库函数提供了很多可以获取CAN状态标志的函数,比如
uint8_t CAN_TransmitStatus(CAN_TypeDef* CANx, uint8_t TransmitMailbox)

FlagStatus CAN_GetFlagStatus(CAN_TypeDef* CANx, uint32_t CAN_FLAG);

四、实战项目

4.1 CAN初始化

/*
 *==============================================================================
 *函数名称:Drv_Can_Init
 *函数功能:初始化CAN
 *输入参数:tsjw:重新同步跳跃宽度(Tsjw);tbs1:BS1长度;tbs2:BS2长度;
						brp:Tq大小;mode:CAN工作模式
 *返回值:无
 *备  注:无
 *==============================================================================
 */
void Drv_Can_Init (u8 tsjw,u8 tbs1,u8 tbs2,u16 brp,u8 mode)
{
	// 结构体定义
	GPIO_InitTypeDef GPIO_InitStructure;
	CAN_InitTypeDef CAN_InitStructure;
	CAN_FilterInitTypeDef CAN_FilterInitStructure;
	
	// 开启时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);   // 打开CAN1时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);   // PA端口时钟打开
	
	// 初始化GPIO
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;   // PA11 CAN_RX   
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;   // 上拉输入模式
	GPIO_Init(GPIOA, &GPIO_InitStructure);	

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;   // PA12 CAN_TX   
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;   // 复用推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   // IO口速度为50MHz
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	// 初始化CAN
	CAN_InitStructure.CAN_TTCM=DISABLE;   // 非时间触发通信模式   
	CAN_InitStructure.CAN_ABOM=DISABLE;   // 软件自动离线管理	  
	CAN_InitStructure.CAN_AWUM=DISABLE;   // 睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)
	CAN_InitStructure.CAN_NART=ENABLE;   // 使用报文自动传送 
	CAN_InitStructure.CAN_RFLM=DISABLE;   // 报文不锁定,新的覆盖旧的  
	CAN_InitStructure.CAN_TXFP=DISABLE;   // 优先级由报文标识符决定 
	CAN_InitStructure.CAN_Mode= mode;   //CAN工作模式设置 
	CAN_InitStructure.CAN_SJW=tsjw;   // 重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1tq~CAN_SJW_4tq
	CAN_InitStructure.CAN_BS1=tbs1;   // Tbs1范围CAN_BS1_1tq ~CAN_BS1_16tq
	CAN_InitStructure.CAN_BS2=tbs2;   // Tbs2范围CAN_BS2_1tq ~	CAN_BS2_8tq
	CAN_InitStructure.CAN_Prescaler=brp;   //分频系数(Fdiv)为brp+1	
	CAN_Init(CAN1, &CAN_InitStructure);   // 初始化CAN1
	
	// 初始化过滤器
	CAN_FilterInitStructure.CAN_FilterNumber=0;   // 过滤器0
	CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;   // 掩码模式
	CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;   // 32位 
	CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;   // 32位ID
	CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
	CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;   // 32位MASK
	CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
	CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;   // 过滤器0关联到FIFO0
	CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;   // 激活过滤器0
	CAN_FilterInit(&CAN_FilterInitStructure);   // 过滤器初始化
}

4.2 CAN发送

/*
 *==============================================================================
 *函数名称:Med_Can_Send_Msg
 *函数功能:发送报文
 *输入参数:msg:数据段指针;len:数据长度
 *返回值:0:发送成功;1:发送失败
 *备  注:固定ID为0x12
 *==============================================================================
 */
u8 Med_Can_Send_Msg (u8* msg,u8 len)
{	
	u8 mbox;
	u16 i = 0;
	CanTxMsg TxMessage;   // 定义发送报文结构体
	TxMessage.StdId = 0x12;   // 标准标识符
	TxMessage.ExtId = 0x12;   // 扩展标识符
	TxMessage.IDE = CAN_Id_Standard;   // 使用标准标识符
	TxMessage.RTR = 0;   // 消息类型为数据帧,一帧8位
	TxMessage.DLC = len;
	for(i = 0;i < len;i ++)
	{
		TxMessage.Data[i] = msg[i];   // 填充帧数据段
	}
	mbox = CAN_Transmit(CAN1,&TxMessage);   // 发送报文   
	i = 0;
	
	// 等待发送结束
	while((CAN_TransmitStatus(CAN1,mbox) == CAN_TxStatus_Failed) && (i < 0XFFF))
	{
		i++;
	}
	
	// 返回发送情况
	if(i >= 0XFFF)
	{
		return 1;
	}
	return 0;		
}

4.3 CAN接收

/*
 *==============================================================================
 *函数名称:Med_Can_Receive_Msg
 *函数功能:接收报文
 *输入参数:buf:数据缓存区指针
 *返回值:0:没有接收到数据;其他:接收数据长度
 *备  注:无
 *==============================================================================
 */
u8 Med_Can_Receive_Msg (u8 *buf)
{		   		   
 	u32 i;
	CanRxMsg RxMessage;   // 定义接收报文结构体
	
	// 没有接收到数据,直接退出 
	if( CAN_MessagePending(CAN1,CAN_FIFO0) == 0)
	{
		return 0;
	}
	CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);   // 读取数据	
	
	for(i = 0;i < RxMessage.DLC;i ++)
	{
		buf[i] = RxMessage.Data[i];
	}
	
	return RxMessage.DLC;	
}

4.4 CAN收发测试

利用按键WK UP控制报文的发送,按下一次发送一次报文。配置CAN波特率为500Kbps,环回模式。利用串口打印接收数据。需要注意的是,STM32只有CAN控制器,想要实现报文的收发,需要自己连接CAN收发器。首先初始化CAN

	// 初始化CAN,500Kbps波特率
	Drv_Can_Init(CAN_SJW_1tq,CAN_BS1_9tq,CAN_BS2_8tq,4,CAN_Mode_LoopBack);

然后编写主程序

u8 gKeyValue = 0;   // 获取按键值

u8 gSendData[8] = {'1','2','3','4','5','6','7','8'};   // 发送内容数组
u8 gReceData[8];   // 接收内容数组
u8 gFlag = 0;   // 接收发送标志

int main(void)
{
	Med_Mcu_Iint();   // 系统初始化
	
	while(1)
  {
		gKeyValue = Med_KeyScan();
		
		// WK UP 按下发送消息
		if (gKeyValue == 1)
		{
			gFlag = Med_Can_Send_Msg(gSendData,8);
			
			// 发送失败
			if (gFlag)
			{
				printf ("Send Defeat!\r\n");
			}
			else
			{
				printf ("Send Success!\r\n");
			}
		}
		
		// 接收报文
		gFlag = Med_Can_Receive_Msg(gReceData);
		
		// 接收成功
		if (gFlag)
		{
			printf ("Receive Data:%s\r\n",gReceData);
		}
	}
}

测试结果如下

测试结果

4.5 补充说明

上面的CAN收发测试程序,发送的内容是字符串“12345678”。如果发送的是数字12345678。在串口打印接收数据时需要先将接收到的数据转换成字符,然后再打印。转换方法很简单,只需要对接收数组的每一位加48即可。

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

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

相关文章

Spring(一):Spring 的创建和使用

目录 Spring 是什么&#xff1f; 什么是容器&#xff1f; 什么是 IoC&#xff1f; 什么是 IoC&#xff1f; IoC的优点是啥呢&#xff1f; 理解 IoC DI 概念说明 Spring 的创建 创建 Spring 项目 1. 创建⼀个普通 Maven 项⽬。 2. 添加 Spring 框架⽀持&#xff08;s…

谈一谈,Spring Boot 中的 starter 到底是什么 ?

1. 为什么要用Starter? 现在我们就来回忆一下&#xff0c;在还没有Spring-boot框架的时候&#xff0c;我们使用Spring 开发项目&#xff0c;如果需要某一个框架&#xff0c;例如mybatis&#xff0c;我们的步骤一般都是&#xff1a;到maven仓库去找需要引入的mybatis jar包&am…

【UE5 多人联机教程】01-创建主界面

目录 工程地址 步骤 参考链接 工程地址 GitHub - UE4-Maple/C_MP_Lobby: 多人大厅教程项目 步骤 1. 先新建一个工程 2. 将下载的工程中的Plugins目录拷贝到自己新建的工程下 3. 打开工程&#xff0c;新建一个游戏实例 这里命名为“GI_Main” 在项目设置中设置游戏实例类为…

排序算法之快速排序举例详解-python实现3版代码及改进过程

快速排序思想步骤&#xff1a; 1.找到一个基准值key 2.设置2个元素下标i0和jlen-1 3.从后往前找到比key小的数num[j]&#xff0c;从前往后找到比key大的数num[i]&#xff08;这里有个先后顺序&#xff09; 4.交换这两个数&#xff1a;num[i]&#xff0c;num[j] 5.继续重复…

如何在PADS Logic中查找器件

PADS Logic提供类似于Windows的查找功能&#xff0c;可以进行器件的查找。 &#xff08;1&#xff09;在Logic设计界面中&#xff0c;将菜单显示中的“选择工具栏”进行打开&#xff0c;如图1所示&#xff0c;会弹出对应的“选择工具栏”的分栏菜单选项&#xff0c;如图2所示。…

数据库信息速递 MONGODB 6.0 的新特性,更多的查询函数,加密查询,与时序数据集合 (译)...

开头还是介绍一下群&#xff0c;如果感兴趣polardb ,mongodb ,mysql ,postgresql ,redis 等有问题&#xff0c;有需求都可以加群群内有各大数据库行业大咖&#xff0c;CTO&#xff0c;可以解决你的问题。加群请联系 liuaustin3 &#xff0c;在新加的朋友会分到3群&#xff08;共…

Shell脚本函数 实验

Shell 函数 命令序列按照格式写在一起&#xff0c;用函数的方式调用并进行重复使用命令序列。这就是它的核心作用 使用函数可以避免代码重复&#xff0c;函数可以将大的工程分割成若干小的功能模块&#xff0c;提高代码的可读性。 函数的基本格式写法有两种&#xff0c;如下&…

零钱兑换 II(力扣)动态规划 JAVA

给你一个整数数组 coins 表示不同面额的硬币&#xff0c;另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额&#xff0c;返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带符号整数。 示例…

预付费电表收费系统

预付费电表收费系统是一种先进的电表管理系统&#xff0c;它能够帮助电力公司更加高效地管理电表收费&#xff0c;提高用电效率&#xff0c;降低能源浪费。本文将从以下几个方面介绍预付费电表收费系统的特点和优势。 一、预付费电表收费系统的原理 预付费电表收费系统是指用户…

5分钟给你破解这套10万赞的生产教程,访谈乔布斯的AI对话数字人视频是怎么做的

本期是赤辰第16期AI项目拆解栏目&#xff1b; 底部准备了7月粉丝福利&#xff0c;看完可以领取&#xff1b; 上周给粉丝们讲解AI动图说话月涨粉20万的案例并给出保姆式教程&#xff0c;粉丝反馈很热烈&#xff0c;都觉得AI强大&#xff0c;有些学员给自己账号做视频&#xff…

ACME申请SSL证书

1.开放443端口 firewall-cmd --permanent --add-port443/tcp # 开放443端口 firewall-cmd --reload # 重启防火墙(修改配置后要重启防火墙)2.安装ACME # 安装acme curl https://get.acme.sh | sh -s email你的邮箱地址 # 别名 alias acme.sh~/.acme.sh/acme.sh3.使用ACME申请…

rabbitMQ杂记

消息队列应用场景 消息队列中间件是分布式系统中重要的组件&#xff0c;主要解决应用耦合&#xff0c;异步消息&#xff0c;流量 削锋等问题实现高性能&#xff0c;高可用&#xff0c;可伸缩和最终一致性&#xff1a; 解耦&#xff1a; 异步&#xff1a; 削峰&#xff1a; 常…

全面深入理解MySQL自增锁

&#x1f497;推荐阅读文章&#x1f497; &#x1f338;JavaSE系列&#x1f338;&#x1f449;1️⃣《JavaSE系列教程》&#x1f33a;MySQL系列&#x1f33a;&#x1f449;2️⃣《MySQL系列教程》&#x1f340;JavaWeb系列&#x1f340;&#x1f449;3️⃣《JavaWeb系列教程》…

Gin+Gorm练手小项目bubble清单企业级结构剖析

概述 本项目来源于Qimi老师的小清单项目——基于gingorm开发的练手小项目&#xff0c;通过该项目可初识go web开发该有的姿势。笔者对代码有些许修改&#xff0c;以下是项目成功运行的截图&#xff0c;主要功能有添加&#xff0c;删除&#xff0c;确认&#xff0c;查看待办事项…

APP测试学习之Android模拟器Genymotion安装配置不上解决方法以及adb基本使用

Android模拟器Genymotion安装配置不上解决方法以及adb基本使用 Genymotion下载安装配置遇见的问题解决方法adb基本使用 Genymotion下载 1.首先进入官网 https://www.genymotion.com/ 2.在官网注册一个账号 https://www-v1.genymotion.com/account/login/ 3.下载 https://www.g…

Linux之设备树解耦架构解读-V1.0

术语和缩略语 本文档使用了以下术语和缩略语 Dts&#xff1a;DTS即Device Tree Source&#xff0c;是一个文本形式的文件&#xff0c;用于描述硬件信息。一般都是固定信息&#xff0c;无法变更&#xff0c;无法overlay。 Dtsi&#xff1a;可以理解为dts的公共部分&#xff0…

【编程技巧--函数指针回调函数】

1&#xff0e;什么是函数指针 在C语言中&#xff0c;一个函数在编译时被分配一个入口地址(第一条指令的地址),我们可以将地址赋给一个指针,这样,指针变量持有函数入口地址,它就指向了该函数,所以称这种指针为指向函数的指针,简称函数指针。 我们在编写代码的时候可以用函数名…

教你快速安装Bootstrap

目录 Bootstrap简介Bootstrap的下载Bootstrap的使用 Bootstrap简介 Bootstrap是美国Twitter公司的设计师Mark Otto和Jacob Thornton合作&#xff0c;基于HTML、CSS、JavaScript开发的简洁、直观、强悍的前端开发框架&#xff0c;它会使Web开发更加快捷Bootstrap框架的优点 开发…

【电路原理学习笔记】第4章:能量与功率:4.3 电阻的额定功率

第4章&#xff1a;能量与功率 4.3 电阻的额定功率 额定功率是一个电阻器可以消耗的最大功率&#xff0c;且保证其不会被过多的热量损坏或改变其阻值。额定功率与电阻值无关&#xff0c;主要由电阻的材料成分、物理尺寸和形状决定。在其他条件相同的情况下&#xff0c;电阻的表…

Redis分布式锁的演变历程

什么时候用分布式锁 当并发去读写一个【共享资源】的时候&#xff0c;我们为了保证数据的正确&#xff0c;需要控制同一时刻只有一个线程访问。 分布式锁就是用来控制同一时刻&#xff0c;只有一个 JVM 进程中的一个线程可以访问被保护的资源。 分布式锁入门 分布式锁应该满足…