STM32F1之OV7725摄像头·SCCB总线代码编写附带源码详解

STM32F1之OV7725摄像头-CSDN博客

STM32F1之OV7725摄像头·像素数据输出时序、FIFO 读写时序以及摄像头的驱动原理详解-CSDN博客

目录

1.  硬件设计

1.1  SCCB 控制相关

1.2  VGA 时序相关

1.3  FIFO 相关

1.4  XCLK 信号

2.  代码设计

2.1  SCCB总线软件实现

2.1.1  宏定义

2.1.2  SCCB管脚配置

2.1.3  延时函数

2.1.4  SCCB起始信号

2.1.5  SCCB终止信号

2.1.6  SCCB应答信号

2.1.7  SCCB非应答信号

2.1.8  SCCB等待应答信号

2.1.9  发送数据

2.1.10  SCCB总线返回的数据

2.1.11  SCCB写一个字节数据

2.1.12  SCCB读一串数据


1.  硬件设计

        摄像头与 STM32 连接关系中主要分为 SCCB 控制、VGA 时序控制、FIFO 数据读取部分,介绍如下:

1.1  SCCB 控制相关

        摄像头中的 SIO_C 和 SIO_D 引脚直接连接到 STM32 普通的 GPIO,它们不具有硬件I2C 的功能,所以在后面的代码中采用模拟 I2C 时序,实际上直接使用硬件 I2C 是完全可以实现 SCCB 协议的,本设计采用模拟 I2C 是芯片资源分配妥协的结果。

1.2  VGA 时序相关

        检测 VGA 时序的 HREF、VSYNC 引脚,它们与 STM32 连接的 GPIO 均设置为输入模式,其中 HREF 在本实验中并没有使用,它已经通过摄像头内部的与非门控制了 FIFO 的写使能;VSYNC 与 STM32 连接的 GPIO 引脚会在程序中配置成中断模式,STM32 利用该中断信号获知新的图像是否采集完成,从而控制 FIFO 是否写使能。

1.3  FIFO 相关

        与 FIFO 控制相关的 RCLK、RRST、WRST、WEN 及 OE 与 STM32 连接的引脚均直接配置成推挽输出,STM32 根据图像的采集情况利用这些引脚控制 FIFO;读取 FIFO 数据内容使用的数据引脚 DO[0:7]均连接到 STM32 同一个 GPIO 端口连续的高 8 位引脚 PB[8:15],这些引脚使用时均配置成输入,程序设计中直接读取 GPIO 端口的高 8 位状态直接获取一个字节的 FIFO 内容,建议在连接这部分数据信号时,参考本设计采用同一个 GPIO 端口连续的 8 位(高 8 位或低 8 位均可),否则会导致读取数据的程序非常复杂。

1.4  XCLK 信号

        本设计中 STM32 的摄像头接口还预留了 PA8 引脚用于与摄像头的 XCLK 连接,STM32的 PA8 可以对外输出时钟信号,所以在使用不带晶振的摄像头时,可以通过该引脚给摄像头提供时钟,秉火摄像头内部已自带晶振,在程序中没有使用 PA8 引脚。

2.  代码设计

2.1  SCCB总线软件实现

2.1.1  宏定义

#ifndef __SCCB_H
#define __SCCB_H



#include "stm32f10x.h"



/************************** OV7725 连接引脚定义********************************/
#define      OV7725_SIO_C_SCK_APBxClock_FUN              RCC_APB2PeriphClockCmd
#define      OV7725_SIO_C_GPIO_CLK                       RCC_APB2Periph_GPIOC
#define      OV7725_SIO_C_GPIO_PORT                      GPIOC
#define      OV7725_SIO_C_GPIO_PIN                       GPIO_Pin_6

#define      OV7725_SIO_D_SCK_APBxClock_FUN              RCC_APB2PeriphClockCmd
#define      OV7725_SIO_D_GPIO_CLK                       RCC_APB2Periph_GPIOC
#define      OV7725_SIO_D_GPIO_PORT                      GPIOC
#define      OV7725_SIO_D_GPIO_PIN                       GPIO_Pin_7



#define SCL_H         GPIO_SetBits(OV7725_SIO_C_GPIO_PORT , OV7725_SIO_C_GPIO_PIN) 
#define SCL_L         GPIO_ResetBits(OV7725_SIO_C_GPIO_PORT , OV7725_SIO_C_GPIO_PIN) 
   
#define SDA_H         GPIO_SetBits(OV7725_SIO_D_GPIO_PORT , OV7725_SIO_D_GPIO_PIN) 
#define SDA_L         GPIO_ResetBits(OV7725_SIO_D_GPIO_PORT , OV7725_SIO_D_GPIO_PIN) 

#define SCL_read      GPIO_ReadInputDataBit(OV7725_SIO_C_GPIO_PORT , OV7725_SIO_C_GPIO_PIN) 
#define SDA_read      GPIO_ReadInputDataBit(OV7725_SIO_D_GPIO_PORT , OV7725_SIO_D_GPIO_PIN) 

#define ADDR_OV7725   0x42



void SCCB_GPIO_Config(void);
int SCCB_WriteByte( u16 WriteAddress , u8 SendByte);
int SCCB_ReadByte(u8* pBuffer,   u16 length,   u8 ReadAddress);



#endif 

2.1.2  SCCB管脚配置

        前面我们说过,SCCB的引脚配置类似于IIC的引脚配置,这里我们对SCCB的引脚进行初始化,使用的类似软件IIC的协议,可以不用规定必须是IIC的引脚,进行配置为开漏输出模式:

void SCCB_GPIO_Config(void)
{
  GPIO_InitTypeDef  GPIO_InitStructure; 	
	
  /* SCL(PC6)、SDA(PC7)管脚配置 */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE );
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;  
  GPIO_Init(GPIOC, &GPIO_InitStructure);
	
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE );
  GPIO_InitStructure.GPIO_Pin =GPIO_Pin_7;
  GPIO_Init(GPIOC, &GPIO_InitStructure);	
}

        按照宏定义进行转换:

void SCCB_GPIO_Config(void)
{
  GPIO_InitTypeDef  GPIO_InitStructure; 
	
	
  /* SCL(PC6)、SDA(PC7)管脚配置 */
  OV7725_SIO_C_SCK_APBxClock_FUN ( OV7725_SIO_C_GPIO_CLK, ENABLE );
  GPIO_InitStructure.GPIO_Pin =  OV7725_SIO_C_GPIO_PIN ;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;  
  GPIO_Init(OV7725_SIO_C_GPIO_PORT, &GPIO_InitStructure);
	
  OV7725_SIO_D_SCK_APBxClock_FUN ( OV7725_SIO_D_GPIO_CLK, ENABLE );
  GPIO_InitStructure.GPIO_Pin =  OV7725_SIO_D_GPIO_PIN ;
  GPIO_Init(OV7725_SIO_D_GPIO_PORT, &GPIO_InitStructure);
	
}

2.1.3  延时函数

        一个简单的循环等于0时跳出循环,起到延时的作用:

static void SCCB_delay(void)
{	
   uint16_t i = 400; 
   while(i) 
   { 
     i--; 
   } 
}

2.1.4  SCCB起始信号

        类比IIC协议,起始条件下,SCL高电平期间,SDA从高电平切换到低电平。

static int SCCB_Start(void)
{
	GPIO_SetBits(GPIOC, GPIO_Pin_7);
	SCCB_delay();
	GPIO_SetBits(GPIOC, GPIO_Pin_6);
	SCCB_delay();
	GPIO_ResetBits(GPIOC, GPIO_Pin_7);
	SCCB_delay();
	GPIO_ResetBits(GPIOC, GPIO_Pin_6);
	SCCB_delay();

}

       为了提高程序的健壮性,可以加入:GPIO_ReadInputDataBit 函数,其作用是读取指定GPIO端口的指定引脚的输入状态,并返回该引脚的输入值(0 或 1) ,进行检测SDA线是否忙碌是否正常。

static int SCCB_Start(void)
{
	GPIO_SetBits(GPIOC, GPIO_Pin_7);
	GPIO_SetBits(GPIOC, GPIO_Pin_6);
	SCCB_delay();
	if(!GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_7))
	return DISABLE;	/* SDA线为低电平则总线忙,退出 */
	GPIO_ResetBits(GPIOC, GPIO_Pin_7);
	SCCB_delay();
	if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_7)) 
	return DISABLE;	/* SDA线为高电平则总线出错,退出 */
	GPIO_ResetBits(GPIOC, GPIO_Pin_7);
	SCCB_delay();
	return ENABLE;
}

        按照宏定义进行转换:

static int SCCB_Start(void)
{
	SDA_H;
	SCL_H;
	SCCB_delay();
	if(!SDA_read)
	return DISABLE;	/* SDA线为低电平则总线忙,退出 */
	SDA_L;
	SCCB_delay();
	if(SDA_read) 
	return DISABLE;	/* SDA线为高电平则总线出错,退出 */
	SDA_L;
	SCCB_delay();
	return ENABLE;
}

2.1.5  SCCB终止信号

        终止条件下,SCL高电平期间,SDA从低电平切换到高电平。

static void SCCB_Stop(void)
{
	GPIO_ResetBits(GPIOC, GPIO_Pin_6);
	SCCB_delay();
	GPIO_ResetBits(GPIOC, GPIO_Pin_7);
	SCCB_delay();
	GPIO_SetBits(GPIOC, GPIO_Pin_6);
	SCCB_delay();
	GPIO_SetBits(GPIOC, GPIO_Pin_7);
	SCCB_delay();
}

        按照宏定义进行转换:

static void SCCB_Stop(void)
{
	SCL_L;
	SCCB_delay();
	SDA_L;
	SCCB_delay();
	SCL_H;
	SCCB_delay();
	SDA_H;
	SCCB_delay();
}

2.1.6  SCCB应答信号

        与 I2C 时序类似,在 SCCB 时序也使用自由位(Don’t care bit )和非应答(NA)信号来保证正常通讯。自由位和非应答信号位于 SCCB 每个传输阶段中的第九位。

        在写数据的第一个传输阶段中,第 9 位为自由位,在一般的正常通讯中,第 9 位时,主机的 SDA 线输出高电平,而从机把 SDA 线拉低作为响应,只是传输的内容分别为目的寄存器地址和要写入的数据。

        应答信号的发送是 SCCB 协议中的一个重要步骤,用于确认数据传输的成功。

static void SCCB_Ack(void)
{
	GPIO_ResetBits(GPIOC, GPIO_Pin_6);
	SCCB_delay();
	GPIO_ResetBits(GPIOC, GPIO_Pin_7);
	SCCB_delay();
	GPIO_SetBits(GPIOC, GPIO_Pin_6);
	SCCB_delay();
	GPIO_ResetBits(GPIOC, GPIO_Pin_6);
	SCCB_delay();
}

        按照宏定义进行转换:

static void SCCB_Ack(void)
{	
	SCL_L;
	SCCB_delay();
	SDA_L;
	SCCB_delay();
	SCL_H;
	SCCB_delay();
	SCL_L;
	SCCB_delay();
}

2.1.7  SCCB非应答信号

        非应答信号的发送也是 SCCB 协议中的一部分,用于处理数据传输失败或其他错误情况。在某些情况下,如果从设备无法正确接收数据,主设备可能会发送非应答信号并采取相应的错误处理措施。

static void SCCB_NoAck(void)
{
	GPIO_ResetBits(GPIOC, GPIO_Pin_6);
	SCCB_delay();
	GPIO_SetBits(GPIOC, GPIO_Pin_7);
	SCCB_delay();
	GPIO_SetBits(GPIOC, GPIO_Pin_6);
	SCCB_delay();
	GPIO_ResetBits(GPIOC, GPIO_Pin_6);
	SCCB_delay();
}

        按照宏定义进行转换:

static void SCCB_NoAck(void)
{	
	SCL_L;
	SCCB_delay();
	SDA_H;
	SCCB_delay();
	SCL_H;
	SCCB_delay();
	SCL_L;
	SCCB_delay();
}

2.1.8  SCCB等待应答信号

        让主机把 SDA 线设为高电平,延时一段时间后再检测 SDA 线的电平,若为低则返回 ENABLE 表示接收到从机的应答,反之返回 DISABLE。(L代表低,H代表高,以下直接使用SCL和SDA的宏定义表示)

static int SCCB_WaitAck(void) 	
{
	SCL_L;
	SCCB_delay();
	SDA_H;			
	SCCB_delay();
	SCL_H;
	SCCB_delay();
	if(SDA_read)
	{
      SCL_L;
      return DISABLE;
	}
	SCL_L;
	return ENABLE;
}

2.1.9  发送数据

        首先,我们先创建一个用于接收数据的参数SendByt,它接受一个 8 位的字节数据作为输入参数,使用一个循环逐位发送这个字节的数据。循环从最高位开始,依次发送每一位,直到最低位。在每一次循环中,首先将 SCL(时钟线)拉低,然后通过 SCCB_delay 函数产生一定延迟,接着,根据 SendByte 的当前最高位,控制 SDA(数据线)为高电平或低电平,以此来发送数据的当前位,然后将 SendByte 左移一位,准备发送下一位数据。通过循环8次来完成一位数据的发送。

static void SCCB_SendByte(uint8_t SendByte) 
{
    uint8_t i=8;
    while(i--)
    {
        SCL_L;
        SCCB_delay();
      if(SendByte&0x80)
        SDA_H;  
      else 
        SDA_L;   
        SendByte<<=1;
        SCCB_delay();
		SCL_H;
        SCCB_delay();
    }
    SCL_L;
}

2.1.10  SCCB总线返回的数据

        首先声明了一个变量 i 并初始化为 8,以及再声明了一个变量 ReceiveByte 并初始化为 0,用于存储接收到的字节数据,然后,将 SDA(数据线)拉高,准备接收数据,通过一个循环逐位接收一个字节的数据。循环从最高位开始,依次接收每一位,直到最低位,读取 SDA 线上的数据,并根据其值决定是否将 ReceiveByte 的当前最低位设置为 1,将 ReceiveByte 左移一位,准备接收下一位数据。

static int SCCB_ReceiveByte(void)  
{ 
    uint8_t i=8;
    uint8_t ReceiveByte=0;

    SDA_H;				
    while(i--)
    {
      ReceiveByte<<=1;      
      SCL_L;
      SCCB_delay();
	  SCL_H;
      SCCB_delay();	
      if(SDA_read)
      {
        ReceiveByte|=0x01;
      }
    }
    SCL_L;
    return ReceiveByte;
}

2.1.11  SCCB写一个字节数据

        首先,明确两个宏,其实OV7725的设备地址:

#define ADDR_OV7725 0x42
#define DEV_ADR ADDR_OV7725

        为了确保SCCB总线通信正常启动,我们可以先进行判断SCCB是否发送起始信号,若是发送继续,若是失败则返回DISABLE。

    if(!SCCB_Start())
	{
	    return DISABLE;
	}

        然后,通过 SCCB_SendByte 函数发送设备地址 DEV_ADR,用于指定要通信的设备,此时指定要通信的设备会发送应答,通过判断本机时候接收到应答,来确定两个设备间是否能进行正常通信,若是不能则终止信号,并返回DISABLE。

    SCCB_SendByte( DEV_ADR );                   
    if( !SCCB_WaitAck() )
	{
		SCCB_Stop(); 
		return DISABLE;
	}

        若是能则将要写入的寄存器地址的低八位(WriteAddress 的低八位)发送给设备,以确定写入数据的目标寄存器,再次等待指定要通信的设备的应答,然后发送要写入的数据 SendByte 给设备,再次等待设备的应答,,停止 SCCB 通信,并返回 ENABLE 表示写入操作成功。

    SCCB_SendByte((uint8_t)(WriteAddress & 0x00FF));  
    SCCB_SendByte(SendByte);
    SCCB_WaitAck();   
    SCCB_Stop(); 
    return ENABLE;

完整代码:

#define ADDR_OV7725 0x42
#define DEV_ADR ADDR_OV7725

int SCCB_WriteByte( uint16_t WriteAddress , uint8_t SendByte )
{		
    if(!SCCB_Start())
	{
	    return DISABLE;
	}
    SCCB_SendByte( DEV_ADR );                    /* Æ÷¼þµØÖ· */
    if( !SCCB_WaitAck() )
	{
		SCCB_Stop(); 
		return DISABLE;
	}
    SCCB_SendByte((uint8_t)(WriteAddress & 0x00FF));   /* ÉèÖõÍÆðʼµØÖ· */      
    SCCB_WaitAck();	
    SCCB_SendByte(SendByte);
    SCCB_WaitAck();   
    SCCB_Stop(); 
    return ENABLE;
}

2.1.12  SCCB读一串数据

int SCCB_ReadByte(uint8_t* pBuffer, uint16_t length, uint8_t ReadAddress)
{	
    if(!SCCB_Start())
	{
	    return DISABLE;
	}
    SCCB_SendByte( DEV_ADR );         /* Æ÷¼þµØÖ· */
    if( !SCCB_WaitAck() )
	{
		SCCB_Stop(); 
		return DISABLE;
	}
    SCCB_SendByte( ReadAddress );     /* ÉèÖõÍÆðʼµØÖ· */      
    SCCB_WaitAck();	
    SCCB_Stop(); 
	
    if(!SCCB_Start())
	{
		return DISABLE;
	}
    SCCB_SendByte( DEV_ADR + 1 );     /* Æ÷¼þµØÖ· */ 
    if(!SCCB_WaitAck())
	{
		SCCB_Stop(); 
		return DISABLE;
	}
    while(length)
    {
      *pBuffer = SCCB_ReceiveByte();
      if(length == 1)
	  {
		  SCCB_NoAck();
	  }
      else
	  {
		SCCB_Ack(); 
	  }
      pBuffer++;
      length--;
    }
    SCCB_Stop();
    return ENABLE;
}

OV7725摄像头_时光の尘的博客-CSDN博客

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

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

相关文章

【GUI开发基础】

GUI开发基础 &#x1f31f;项目文件组成✨浅析Pro文件配置 &#x1f31f;Qt设计师&#x1f31f;剖析UI文件运行机制&#x1f31f;UI设计方式✨可视化UI设计✨代码化UI设计 &#x1f31f;项目文件组成 创建一个QtGUI项目&#xff1a; open QtCreator —> select Creator Pr…

Nvidia 如何成为 AI 训练的超级强国

周三&#xff0c;英伟达公布了第一季度的财务业绩&#xff0c;再次超出了分析师的预期。在截至 4 月 28 日的季度中&#xff0c;该公司的利润同比飙升 262%&#xff0c;股价一度创下 1000 美元以上的新高。 目前&#xff0c;英伟达的市值超过 2.3 万亿美元&#xff0c;是全球第…

从0开始学统计-什么是相关?

1.什么是统计学相关? 在统计学中&#xff0c;“相关”&#xff08;Correlation&#xff09;是指两个变量之间的线性关系程度。相关关系可以表明两个变量在某种程度上共同变化的趋势&#xff0c;但不意味着因果关系。相关的主要衡量方法是相关系数&#xff08;Correlation Coe…

【Linux-INPUT输入的子系统】

Linux-INPUT输入的子系统 ■ input 子系统简介■ input 驱动编写流程■ ■ input 子系统简介 input 子系统就是管理输入的子系统&#xff0c; input 子系统分为 input 驱动层、 input 核心层、 input 事件处理层&#xff0c;最终给用户空间提供可访问的设备节点 ■ input 驱…

shell脚本实战--批量修改文件名

字符串截取 先来了解一下shell字符串相关操作的变量 # 从开头删除匹配最短 ## 从开头删除匹配最长 % 从结尾削除匹配最短 %% 从结尾删除匹配最长#指定字符内容截取 a*c 匹配开头为a&#xff0c;中间任意个字符&#xff0c;结尾为c的字符串 a*C 匹配…

web学习笔记(五十八)

目录 1. v-model 双向数据绑定 2. 事件修饰符 3. 路径别名 4. setup语法糖 4.1 语法糖的概念 4.2 setup语法糖 5. 配置代理服务器 1. v-model 双向数据绑定 v-model 双向数据绑定只能使用在表单标签&#xff1b; v-model双向数据绑定原理&#xff1a;采用 Object.de…

C++的哈希 哈希表 哈希桶

目录 Unordered系列关联式容器 什么是哈希 哈希表 闭散列 载荷因子α 扩容 查找 删除 字符串哈希算法 最终代码 开散列 插入 查找 删除 最终代码 完整代码 Unordered系列关联式容器 C98中&#xff0c;STL提供了底层为红黑树结构的一系列关联式容器&#xff0…

模仿高效网络进行目标检测——知识蒸馏

摘要 链接&#xff1a;https://openaccess.thecvf.com/content_cvpr_2017/papers/Li_Mimicking_Very_Efficient_CVPR_2017_paper.pdf 当前的基于卷积神经网络&#xff08;CNN&#xff09;的目标检测器需要从预训练的ImageNet分类模型中初始化&#xff0c;这通常非常耗时。在本…

高效的大型语言模型适应方法:提升基础性的解决方案

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

人工智能在鼻咽癌领域的最新应用|【医学AI·论文速递·05-27】

小罗碎碎念 2024-05-27&#xff5c;文献速递 接下来打算把人工智能在主流癌种治疗中的应用&#xff0c;每天和大家做一期推送&#xff0c;方便大家了解各自领域最新的一个进展。 因为小罗的课题是鼻咽癌相关的&#xff0c;所以这一期推文就先从人工智能在鼻咽癌中最新的应用开…

50-Qt控件详解:Input Display

#ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow> //1.Combo Box控件 #include<QComboBox> //2.QFontComboBox控件 #include<QFontComboBox> #include<QLabel>//3.Line Edit控件 #include<QLineEdit> #include <QPushButton…

面向浏览器端免费开源的三维可视化编辑器,包含BIM轻量化,CAD解析预览等特色功能。

ES 3DEditor &#x1f30d;Github地址 https://github.com/mlt131220/ES-3DEditor &#x1f30d;在线体验 https://editor.mhbdng.cn/#/ 基于vue3与ThreeJs&#xff0c;具体查看Doc 主要功能&#xff1a; 模型导入展示&#xff0c;支持OBJ、FBX、GLTF、GLB、RVT、IFC、SEA、3…

5.23 Linux中超时检测方式+模拟面试

1.IO多路复用的原理&#xff1f; IO多路复用使得一个或少量线程资源处理多个连接的IO事件的技术。对于要处理的多个阻塞的IO操作&#xff0c;建立集合并存储它们的文件描述符&#xff0c;利用单个阻塞函数去监控集合中文件描述符事件到达的情况&#xff0c;&#xff08;如果到…

k8s部署presto

&#xff08;作者&#xff1a;陈玓玏&#xff09; 一、前提条件 已部署k8s&#xff1b;已部署hadoop和hive&#xff0c;可参考以下链接&#xff1a; https://blog.csdn.net/weixin_39750084/article/details/136750613?spm1001.2014.3001.5502 https://blog.csdn.net/wei…

【Linux-时间管理和内核定时器】

Linux-时间管理和内核定时器 ■ 设置系统节拍率■ 高节拍率和低节拍率的优缺点&#xff1a;■ jiffies 系统节拍数■ get_jiffies_64 这个函数可以获取 jiffies_64 的值■ 处理绕回■ 使用 jiffies 判断超时 ■ jiffies 和 ms、 us、 ns 之间的转换函数在这里插入代码片■ 内核…

Python语言基础学习(下)

目录 一、顺序语句 二、条件语句 (1) if (2) if - else (3) if - elif - else 缩进和代码块 空语句 pass 三、循环语句 while 循环 for 循环 continue break 四、函数 创建函数 调用函数 函数返回 函数变量 函数递归 关键字参数 五、列表和元组 创建列表 …

CNCAP2024主动安全解析

一、新增场景 车辆自动紧急制动系统&#xff08;AEB C2C&#xff09;在 2021 版基础上新增了叉路口场景、高速公路追尾场景和 AEB 误作用场景&#xff1b;VRU 自动紧急制动&#xff08;AEB VRU&#xff09;试验在 2021 版基础上新增了交叉路口场景&#xff0c;同时对已有场景进…

你真的了解HTTPS协议吗

前言 在 HTTP 协议中有可能存在信息窃听或身份伪装等安全问题。使用 HTTPS 通信机制可以有效地防止这些问题。本文即将带大家来了解这些。 任何事物都有两面性&#xff0c;为了满足HTTP协议的快&#xff0c;但导致了它有如下的不足&#xff1a; 通信采用明文&#xff08;不加…

IDEA 2024.1安装与破解

一、下载 官网地址&#xff1a;https://www.jetbrains.com/idea/download/other.html 二、安装 傻瓜式安装即可 三、破解 3.1 破解程序 网站&#xff1a;https://3.jetbra.in/ 3.2 获取激活码 点击*号部分即可复制成功

深入解析RPC技术:原理、实现与应用

RPC&#xff08;Remote Procedure Call&#xff0c;远程过程调用&#xff09;是一种计算机通信协议&#xff0c;允许一个程序&#xff08;客户端&#xff09;在本地调用另一个程序&#xff08;服务器&#xff09;中的函数或方法&#xff0c;并获取返回结果&#xff0c;就像调用…