硬件I2C和软件I2C(模拟I2C)的区别

news2024/9/22 15:50:08

硬件I2C和软件I2C是两种不同的实现I2C(Inter-Integrated Circuit,集成电路间)通信协议的方式,它们在实现方式、性能特点以及应用场景上存在显著差异。

一、实现方式

  • 硬件I2C:通过专门的硬件电路实现,这些电路通常由微控制器或其他集成电路上的硬件模块提供支持。硬件I2C可以直接调用内部寄存器进行配置,利用芯片中的硬件I2C外设,自动执行时钟生成、起始终止条件生成、应答位收发、数据收发等功能,从而减轻CPU的负担。
  • 软件I2C:通过软件控制GPIO(通用输入输出)管脚来模拟I2C协议的时序。这通常涉及到在程序中控制SCL(串行时钟)和SDA(串行数据)线的电平状态,以模拟I2C通信的起始、停止、数据发送和接收等过程。

二、性能特点

  • 硬件I2C

    • 高速传输:由于使用专门的硬件电路,硬件I2C可以实现较高的数据传输速度,通常可以达到400kHz或更高。
    • 低占用率:传输过程由硬件电路完成,不需要CPU的直接参与,因此可以释放CPU资源,降低系统负载。
    • 稳定性高:时序控制由硬件电路完成,不易受到外部干扰的影响,具有较高的通信稳定性。
    • 占用CPU资源少:由于硬件I2C的传输过程不需要CPU的干预,因此可以显著减少CPU的占用率。
    • 可靠性高:硬件I2C的实现符合I2C标准,具有较高的可靠性。

    然而,硬件I2C也存在一些缺点,如外设数量限制和异常处理难度较大。

  • 软件I2C

    • 灵活性高:可以使用任意的GPIO管脚来实现,适应不同的硬件平台和需求。
    • 可移植性强:不依赖于特定的硬件电路,可以在不同的平台上进行移植和使用。
    • 适用范围广:在没有硬件I2C支持的情况下,软件I2C可以作为替代方案,也可以用于扩展硬件I2C的功能。
    • 软件I2C通常也被称为模拟I2C:这是因为软件I2C是通过软件编程来控制GPIO(通用输入输出)引脚来模拟I2C通信协议的时序和信号。它不使用微控制器或其他集成电路上的硬件I2C模块,而是通过编写代码来手动控制SCL(串行时钟)和SDA(串行数据)线的电平状态,从而模拟出I2C通信的起始条件、停止条件、数据发送和接收等过程。

      模拟I2C(即软件I2C)的优点在于其灵活性和可移植性,因为它不依赖于特定的硬件电路,可以在任何具有GPIO引脚的微控制器或处理器上实现。然而,与硬件I2C相比,模拟I2C的通信速度可能较慢,且由于需要CPU的参与来生成时序,因此会占用较多的CPU资源。此外,模拟I2C的实现可能不如硬件I2C稳定,因为它更容易受到外部干扰和程序错误的影响。

    然而,软件I2C的速度和稳定性可能不如硬件I2C,且需要CPU的参与,因此会占用较多的CPU资源。此外,软件I2C的实现可能不符合I2C标准,导致可靠性较低。

三、应用场景

  • 硬件I2C:适用于对传输速度和稳定性要求较高的场景,如高速数据传输、实时性要求较高的系统等。
  • /*
     * @description		: 初始化I2C,波特率100KHZ
     * @param - base 	: 要初始化的IIC设置
     * @return 			: 无
     */
    void i2c_init(I2C_Type *base)
    {
    	/* 1、配置I2C */
    	base->I2CR &= ~(1 << 7); /* 要访问I2C的寄存器,首先需要先关闭I2C */
    
        /* 设置波特率为100K
         * I2C的时钟源来源于IPG_CLK_ROOT=66Mhz
     	 * IC2 时钟 = PERCLK_ROOT/dividison(IFDR寄存器)
    	 * 设置寄存器IFDR,IFDR寄存器参考IMX6UL参考手册P1260页,表29-3,
    	 * 根据表29-3里面的值,挑选出一个还是的分频数,比如本例程我们
    	 * 设置I2C的波特率为100K, 因此当分频值=66000000/100000=660.
    	 * 在表29-3里面查找,没有660这个值,但是有640,因此就用640,
    	 * 即寄存器IFDR的IC位设置为0X15
    	 */
    	base->IFDR = 0X15 << 0;
    
    	/*
         * 设置寄存器I2CR,开启I2C
         * bit[7] : 1 使能I2C,I2CR寄存器其他位其作用之前,此位必须最先置1
    	 */
    	base->I2CR |= (1<<7);
    }
    
    /*
     * @description			: 发送重新开始信号
     * @param - base 		: 要使用的IIC
     * @param - addrss		: 设备地址
     * @param - direction	: 方向
     * @return 				: 0 正常 其他值 出错
     */
    unsigned char i2c_master_repeated_start(I2C_Type *base, unsigned char address,  enum i2c_direction direction)
    {
    	/* I2C忙并且工作在从模式,跳出 */
    	if(base->I2SR & (1 << 5) && (((base->I2CR) & (1 << 5)) == 0))		
    		return 1;
    
    	/*
         * 设置寄存器I2CR
         * bit[4]: 1 发送
         * bit[2]: 1 产生重新开始信号
    	 */
    	base->I2CR |=  (1 << 4) | (1 << 2);
    
    	/*
         * 设置寄存器I2DR
         * bit[7:0] : 要发送的数据,这里写入从设备地址
         *            参考资料:IMX6UL参考手册P1249
    	 */ 
    	base->I2DR = ((unsigned int)address << 1) | ((direction == kI2C_Read)? 1 : 0);
    	
    	return 0;
    }
    
    /*
     * @description			: 发送开始信号
     * @param - base 		: 要使用的IIC
     * @param - addrss		: 设备地址
     * @param - direction	: 方向
     * @return 				: 0 正常 其他值 出错
     */
    unsigned char i2c_master_start(I2C_Type *base, unsigned char address,  enum i2c_direction direction)
    {
    	if(base->I2SR & (1 << 5))			/* I2C忙 */
    		return 1;
    
    	/*
         * 设置寄存器I2CR
         * bit[5]: 1 主模式
         * bit[4]: 1 发送
    	 */
    	base->I2CR |=  (1 << 5) | (1 << 4);
    
    	/*
         * 设置寄存器I2DR
         * bit[7:0] : 要发送的数据,这里写入从设备地址
         *            参考资料:IMX6UL参考手册P1249
    	 */ 
    	base->I2DR = ((unsigned int)address << 1) | ((direction == kI2C_Read)? 1 : 0);
    	return 0;
    }
    
    /*
     * @description		: 检查并清除错误
     * @param - base 	: 要使用的IIC
     * @param - status	: 状态
     * @return 			: 状态结果
     */
    unsigned char i2c_check_and_clear_error(I2C_Type *base, unsigned int status)
    {
    	/* 检查是否发生仲裁丢失错误 */
    	if(status & (1<<4))
    	{
    		base->I2SR &= ~(1<<4);		/* 清除仲裁丢失错误位 			*/
    
    		base->I2CR &= ~(1 << 7);	/* 先关闭I2C 				*/
    		base->I2CR |= (1 << 7);		/* 重新打开I2C 				*/
    		return I2C_STATUS_ARBITRATIONLOST;
    	} 
    	else if(status & (1 << 0))     	/* 没有接收到从机的应答信号 */
    	{
    		return I2C_STATUS_NAK;		/* 返回NAK(No acknowledge) */
    	}
    	return I2C_STATUS_OK;
    }
    
    /*
     * @description		: 停止信号
     * @param - base	: 要使用的IIC
     * @param			: 无
     * @return 			: 状态结果
     */
    unsigned char i2c_master_stop(I2C_Type *base)
    {
    	unsigned short timeout = 0xffff;
    
    	/*
    	 * 清除I2CR的bit[5:3]这三位
    	 */
    	base->I2CR &= ~((1 << 5) | (1 << 4) | (1 << 3));
    
    	/* 等待忙结束 */
    	while((base->I2SR & (1 << 5)))
    	{
    		timeout--;
    		if(timeout == 0)	/* 超时跳出 */
    			return I2C_STATUS_TIMEOUT;
    	}
    	return I2C_STATUS_OK;
    }
    
    /*
     * @description		: 发送数据
     * @param - base 	: 要使用的IIC
     * @param - buf		: 要发送的数据
     * @param - size	: 要发送的数据大小
     * @param - flags	: 标志
     * @return 			: 无
     */
    void i2c_master_write(I2C_Type *base, const unsigned char *buf, unsigned int size)
    {
    	/* 等待传输完成 */
    	while(!(base->I2SR & (1 << 7))); 
    	/*这里判断base->I2SR的bit7,可以理解为i2c有没有被占用,手册1467中说这个位由最后一个字节传输的第9个时钟的下降沿设置,完成为一。我们要考虑当传输多个字节时,每传输完一个字节(不是最后一个字节),bit7并不会被置一,而bit1每传输完一个字节(包括最后一个字节)都会被置一,因此在要开始传输时判断bit7也就是i2c有没有被占用,在传输多个字节的过程中每传输完一个字节要判断bit1并置0。
        */
    	base->I2SR &= ~(1 << 1); 	/* 清除标志位 */
    	base->I2CR |= 1 << 4;		/* 发送数据 */
    	
    	while(size--)
    	{
    		base->I2DR = *buf++; 	/* 将buf中的数据写入到I2DR寄存器 */
    		
    		while(!(base->I2SR & (1 << 1))); 	/* 等待传输完成 */	
    		base->I2SR &= ~(1 << 1);			/* 清除标志位 */
    
    		/* 检查ACK */
    		if(i2c_check_and_clear_error(base, base->I2SR))
    			break;
    	}
    	
    	base->I2SR &= ~(1 << 1);
    	i2c_master_stop(base); 	/* 发送停止信号 */
    }
    
    /*
     * @description		: 读取数据
     * @param - base 	: 要使用的IIC
     * @param - buf		: 读取到数据
     * @param - size	: 要读取的数据大小
     * @return 			: 无
     */
    void i2c_master_read(I2C_Type *base, unsigned char *buf, unsigned int size)
    {
    	volatile uint8_t dummy = 0;
    
    	dummy++; 	/* 防止编译报错 */
    	
    	/* 等待传输完成 */
    	while(!(base->I2SR & (1 << 7))); 
    	
    	base->I2SR &= ~(1 << 1); 				/* 清除中断挂起位 */
    	base->I2CR &= ~((1 << 4) | (1 << 3));	/* 接收数据 */
    	
    	/* 如果只接收一个字节数据的话发送NACK信号 */
    	if(size == 1)
            base->I2CR |= (1 << 3);
    
    	dummy = base->I2DR; /* 假读:假读触发下一个字节的传输 */
    	
    	while(size--)
    	{
    		while(!(base->I2SR & (1 << 1))); 	/* 等待传输完成 */	
    		base->I2SR &= ~(1 << 1);			/* 清除标志位 */
    
    	 	if(size == 0)
            {
            	i2c_master_stop(base); 			/* 发送停止信号 */
            }
    
            if(size == 1)
            {
                base->I2CR |= (1 << 3);
            }
    		*buf++ = base->I2DR;
    	}
    }
    
    /*
     * @description	: I2C数据传输,包括读和写
     * @param - base: 要使用的IIC
     * @param - xfer: 传输结构体
     * @return 		: 传输结果,0 成功,其他值 失败;
     */
    unsigned char i2c_master_transfer(I2C_Type *base, struct i2c_transfer *xfer)
    {
    	unsigned char ret = 0;
    	 enum i2c_direction direction = xfer->direction;	
    
    	base->I2SR &= ~((1 << 1) | (1 << 4));			/* 清除标志位 */
    
    	/* 等待传输完成 */
    	while(!((base->I2SR >> 7) & 0X1)){}; 
    
    	/* 如果是读的话,要先发送寄存器地址,所以要先将方向改为写 */
        if ((xfer->subaddressSize > 0) && (xfer->direction == kI2C_Read))
        {
            direction = kI2C_Write;
        }
    
    	ret = i2c_master_start(base, xfer->slaveAddress, direction); /* 发送开始信号 */
        if(ret)
        {	
    		return ret;
    	}
    
    	while(!(base->I2SR & (1 << 1))){};			/* 等待传输完成 */
    
        ret = i2c_check_and_clear_error(base, base->I2SR);	/* 检查是否出现传输错误 */
        if(ret)
        {
          	i2c_master_stop(base); 						/* 发送出错,发送停止信号 */
            return ret;
        }
    	
        /* 发送寄存器地址 */
        if(xfer->subaddressSize)
        {
            do
            {
    			base->I2SR &= ~(1 << 1);			/* 清除标志位 */
                xfer->subaddressSize--;				/* 地址长度减一 */
    			
                base->I2DR =  ((xfer->subaddress) >> (8 * xfer->subaddressSize)); //向I2DR寄存器写入子地址
      
    			while(!(base->I2SR & (1 << 1)));  	/* 等待传输完成 */
    
                /* 检查是否有错误发生 */
                ret = i2c_check_and_clear_error(base, base->I2SR);
                if(ret)
                {
                 	i2c_master_stop(base); 				/* 发送停止信号 */
                 	return ret;
                }  
            } while ((xfer->subaddressSize > 0) && (ret == I2C_STATUS_OK));
    
            if(xfer->direction == kI2C_Read) 		/* 读取数据 */
            {
                base->I2SR &= ~(1 << 1);			/* 清除中断挂起位 */
                i2c_master_repeated_start(base, xfer->slaveAddress, kI2C_Read); /* 发送重复开始信号和从机地址 */
        		while(!(base->I2SR & (1 << 1))){};/* 等待传输完成 */
    
                /* 检查是否有错误发生 */
    			ret = i2c_check_and_clear_error(base, base->I2SR);
                if(ret)
                {
                 	ret = I2C_STATUS_ADDRNAK;
                    i2c_master_stop(base); 		/* 发送停止信号 */
                    return ret;  
                }
               	          
            }
        }	
    
    
        /* 发送数据 */
        if ((xfer->direction == kI2C_Write) && (xfer->dataSize > 0))
        {
        	i2c_master_write(base, xfer->data, xfer->dataSize);
    	}
    
        /* 读取数据 */
        if ((xfer->direction == kI2C_Read) && (xfer->dataSize > 0))
        {
           	i2c_master_read(base, xfer->data, xfer->dataSize);
    	}
    	return 0;	
    }
  • 软件I2C:适用于没有硬件I2C支持或需要扩展硬件I2C功能的场景,如低成本、低功耗的嵌入式系统、小型设备等。
  • //初始化IIC
    void IIC_Init(void)
    {			
      GPIO_InitTypeDef  GPIO_InitStructure;
    
      RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//使能GPIOB时钟
    
      //GPIOB8,B9初始化设置
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
      GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
      GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
      GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化
    	IIC_SCL=1;
    	IIC_SDA=1;
    }
    //产生IIC起始信号
    void IIC_Start(void)
    {
    	SDA_OUT();     //sda线输出
    	IIC_SDA=1;	  	  
    	IIC_SCL=1;
    	delay_us(4);
     	IIC_SDA=0;//START:when CLK is high,DATA change form high to low 
    	delay_us(4);
    	IIC_SCL=0;//钳住I2C总线,准备发送或接收数据 
    }	  
    //产生IIC停止信号
    void IIC_Stop(void)
    {
    	SDA_OUT();//sda线输出
    	IIC_SCL=0;
    	IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
     	delay_us(4);
    	IIC_SCL=1; 
    	IIC_SDA=1;//发送I2C总线结束信号
    	delay_us(4);							   	
    }
    //等待应答信号到来
    //返回值:1,接收应答失败
    //        0,接收应答成功
    u8 IIC_Wait_Ack(void)
    {
    	u8 ucErrTime=0;
    	SDA_IN();      //SDA设置为输入  
    	IIC_SDA=1;delay_us(1);	   
    	IIC_SCL=1;delay_us(1);	 
    	while(READ_SDA)
    	{
    		ucErrTime++;
    		if(ucErrTime>250)
    		{
    			IIC_Stop();
    			return 1;
    		}
    	}
    	IIC_SCL=0;//时钟输出0 	   
    	return 0;  
    } 
    //产生ACK应答
    void IIC_Ack(void)
    {
    	IIC_SCL=0;
    	SDA_OUT();
    	IIC_SDA=0;
    	delay_us(2);
    	IIC_SCL=1;
    	delay_us(2);
    	IIC_SCL=0;
    }
    //不产生ACK应答		    
    void IIC_NAck(void)
    {
    	IIC_SCL=0;
    	SDA_OUT();
    	IIC_SDA=1;
    	delay_us(2);
    	IIC_SCL=1;
    	delay_us(2);
    	IIC_SCL=0;
    }					 				     
    //IIC发送一个字节
    //返回从机有无应答
    //1,有应答
    //0,无应答			  
    void IIC_Send_Byte(u8 txd)
    {                        
        u8 t;   
    	SDA_OUT(); 	    
        IIC_SCL=0;//拉低时钟开始数据传输
        for(t=0;t<8;t++)
        {              
            IIC_SDA=(txd&0x80)>>7;
            txd<<=1; 	  
    		delay_us(2);   //对TEA5767这三个延时都是必须的
    		IIC_SCL=1;
    		delay_us(2); 
    		IIC_SCL=0;	
    		delay_us(2);
        }	 
    } 	    
    //读1个字节,ack=1时,发送ACK,ack=0,发送nACK   
    u8 IIC_Read_Byte(unsigned char ack)
    {
    	unsigned char i,receive=0;
    	SDA_IN();//SDA设置为输入
        for(i=0;i<8;i++ )
    	{
            IIC_SCL=0; 
            delay_us(2);
    		IIC_SCL=1;
            receive<<=1;
            if(READ_SDA)receive++;   
    		delay_us(1); 
        }					 
        if (!ack)
            IIC_NAck();//发送nACK
        else
            IIC_Ack(); //发送ACK   
        return receive;
    }
    

综上所述,硬件I2C和软件I2C各有其优势和适用场景。在选择时,需要根据具体的应用需求和系统资源来权衡利弊,选择最合适的实现方式。

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

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

相关文章

泛交通领域的可视化大屏作品欣赏,各个都相当惊艳。

各位新老朋友大家好&#xff0c;本次给大家带来泛交通领域的可视化大屏&#xff0c;供大家鉴赏。 泛交通领域是指综合利用各种交通方式和资源&#xff0c;提供全方位、多元化的出行选择和服务的交通体系。 它包括以下几个方面&#xff1a; 1. 公共交通&#xff1a;包括地铁、…

花钱买不到系列之—linux系统调用

关于系统调用是什么&#xff0c;为什么用系统调用? 也是通过生活的例子来说明白。 我们生活中有一种东西叫银行&#xff0c;银行是不是有存钱的仓库对不对&#xff1f;好银行有存钱的仓库&#xff0c;银行有桌椅板凳啊&#xff0c;银行还有电脑&#xff0c;设备啊&#xff0c;…

文华财经期货DK多空提示指标源码

N1:40; A:(COHL)/4; AA0:MA(A,N1),LINETHICK3;//中 MA1:MA(CLOSE,5), NODRAW; MA2:MA(CLOSE,10), NODRAW; MA3:MA(C,60), NODRAW,LINETHICK1; 转折线:MA3, NODRAW,COLORCYAN; 顺势线:MA(CLOSE,10), NODRAW; MA20:MA(C,20), NODRAW; MA30:MA(C,30), NODRAW; ZD:MA3>…

网络 基础

目录 1、协议&#xff1a; 2、OSI 七层 模型&#xff1a; 3、TCP/IP 五层 / 四层 协议 3.1、为什么要有TCP / IP 协议&#xff1f; 3.1.1、主机之间变远产生的问题&#xff1a; 3.1.2、TCP/IP协议于操作系统的关系 4、局域网 4.1、Mac 4.1.1 在Linux内使用指令 …

leetCode - - - 哈希表

目录 1.模拟行走机器人&#xff08;LeetCode 874&#xff09; 2.数组的度&#xff08;LeetCode 697&#xff09; 3.子域名访问次数&#xff08;LeetCode 811&#xff09; 4.字母异位词分组&#xff08;LeetCode 49&#xff09; 5.小结 1.常见的哈希表实现 2.遍历Map 1.模…

基于Java中的SSM框架实现医院收费系统项目【项目源码+论文说明】计算机毕业设计

基于Java中的SSM框架实现医院收费系统演示 摘要 随着医疗体制改革的不断深入&#xff0c;医院收费系统成为医院信息化建设的重点内容。医院收费系统是利用计算机、网络技术和数据库技术&#xff0c;实现病人在医疗机构的诊疗信息的电子化存储、传递和分析&#xff0c;从而提高…

[Meachines] [Medium] Mango PHP弱比较绕过+MongoDB注入+TRP00F自动化权限提升+JJS权限提升

信息收集 IP AddressOpening Ports10.10.10.162TCP:22&#xff0c;80&#xff0c;443 $ nmap -p- 10.10.10.162 --min-rate 1000 -sC -sV PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0) | ssh-host…

<数据集>快递识别数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;5382张 标注数量(xml文件个数)&#xff1a;5382 标注数量(txt文件个数)&#xff1a;5382 标注类别数&#xff1a;1 标注类别名称&#xff1a;[Box-Packet] 序号类别名称图片数框数1Box-Packet53828965 使用标注工…

8.15-配置mysql5.7环境+使用python管理数据库+使用中间件mycat配置读写分离

一、配置mysql5.7的环境 1.基础配置 # 将mysql5.7的包拖入xshell [rootmysql_5 ~]# ls anaconda-ks.cfg mysql-5.7.44-linux-glibc2.12-x86_64.tar.gz ​ # 解压 [rootmysql_5 ~]# tar -xf mysql-5.7.44-linux-glibc2.12-x86_64.tar.gz ​ # 备份文件 [rootmysql_5 ~]# cp…

短说V4.2.0测试版发布|字体更换、小名片及个人中心UI更换

Hi 大家好&#xff0c; 我是给你们带来惊喜的运营小番茄。 本期更新为短说V4.2.0测试版&#xff0c;本次更新涉及平台有H5、App、微信小程序。 4.2.0版本除功能优化外&#xff0c;新增了如下功能&#xff1a; 一、新增功能 通用版&#xff1a; ①全站默认字体全部更换为…

淘宝到一个墨水屏,成功实现显示经历记录

一&#xff0c;淘一个墨水屏的原因 在一些小的PCB设计和编程中发现&#xff0c;许多程序控制运行情况如果能够显示出来&#xff0c;会很完美。大学时期使用LCD1602&#xff08;经典&#xff09;显示了一个称重传感器的课程设计&#xff0c;后来尝试OLED显示。在过程中发现墨水…

【嵌入式linux开发】智能家居入门5(QT、微信小程序、HTTP协议、ONENET云平台、旭日x3派)

智能家居入门5&#xff08;QT、微信小程序、HTTP协议、ONENET云平台、旭日x3派&#xff09; 前言一、QT界面设计二、云平台产品创建与连接三、下位机端QT代码总览&#xff1a;四、微信小程序端代码总览五、板端测试 前言 前四篇智能家居相关文章都是使用STM32作为主控&#xf…

报表的多行业应用!用工具做报表省了我不少事...

一、什么是报表&#xff1f; 说起报表&#xff0c;你不会还停留在Excel报表的层面上吧&#xff1f; 传统的报表一般都是基于Excel制作的&#xff0c;主要面向业务人员、开发人员等&#xff0c;也有一些公司会自己去开发设计&#xff0c;只不过周期较长&#xff0c;耗费人力多。…

端到端自动驾驶落地挑战与驱动力

1、端到端的发展驱动力 1.1 对标驱动&#xff1a;特斯拉FSD的标杆作用吸引行业关注 大部分行业专家表示&#xff0c;特斯拉FSD v12的优秀表现&#xff0c;是端到端自动驾驶这一技术路线快速形成大范围共识的最重要的推动力&#xff1b;而在此之前&#xff0c;从来没有一个自动…

C#模拟量线性变换小程序

1、一步步建立一个C#项目 一步步建立一个C#项目(连续读取S7-1200PLC数据)_s7协议批量读取-CSDN博客文章浏览阅读1.7k次,点赞2次,收藏4次。本文详细介绍了如何使用C#构建一个项目,通过S7net库连接并连续读取S7-1200 PLC的数据,包括创建窗体应用、配置存储位置、安装S7net库…

服务器端请求伪造漏洞

1.客户端请求 客户端请求指的是由客户端设备(如个人计算机、智能手机、平板电脑等)或软件(浏览器、各种APP)发出的请求&#xff0c;以获取指定的网页、图片、视频或其他资源。比如当用户在浏览器中输入URL或点击链接时&#xff0c;浏览器会自动发起HTTP请求&#xff0c;请求服…

Python | Leetcode Python题解之第335题路径交叉

题目&#xff1a; 题解&#xff1a; class Solution:def isSelfCrossing(self, distance: List[int]) -> bool:n len(distance)# 处理第 1 种情况i 0while i < n and (i < 2 or distance[i] > distance[i - 2]):i 1if i n:return False# 处理第 j 次移动的情况…

【语义通信】灵(Genie)——6G的第四维元素

6G 不仅包含 5G 涉及的人类社会、信息空间、 物理世界&#xff08;人、机、物&#xff09;这 3 个核心元素&#xff0c;还第四维元素—灵&#xff08;Genie&#xff09;。Genie存在于虚拟世界体系&#xff0c;虚拟世界体系包括&#xff08;VPS, VBS, VSS&#xff09;&#xff0…

BvSP_ Broad-view Soft Prompting for Few-Shot Aspect Sentiment Quad Prediction

中文题目: 英文题目: BvSP: Broad-view Soft Prompting for Few-Shot Aspect Sentiment Quad Prediction 论文地址: aclanthology.org/2024.acl-long.460.pdf 代码地址: https://github.com/byinhao/BvSP 论文级别&#xff0c; 单位: (2024 ACL long paper) 南开大学&#xff0…

写给大数据开发:如何解决拖延

你是否曾面对一个复杂的Spark任务&#xff0c;明知它对项目至关重要&#xff0c;却总是找各种理由推迟动手&#xff1f;或者&#xff0c;你有没有在面对一堆待优化的Hive查询时&#xff0c;选择先去重构那个"并不那么紧急"的Python脚本&#xff1f; 如果你点头了&am…