CVTE嵌软(提前批)
8.25 一面 全程1h多
一.目前实习最大的收获是,开始根据实习内容问相关问题,并根据回答中提到的进一步提问:
二.介绍iic和spi的区别,两者的最高速率是?
IIC 与 SPI 区别 + 最高速率
1.核心区别
- 总线引脚
- IIC:2 线制(SDA 数据线、SCL 时钟线),半双工
- SPI:4 线制(SCK 时钟、MOSI 主发、MISO 主收、CS 片选),全双工
- 通信方式
- IIC:同步串行、地址寻址,一主多从,靠设备地址选从机
- SPI:同步串行、片选寻址,靠 CS 引脚单独选中从机
- 拓扑结构
- IIC:总线型,所有设备挂同一两根线
- SPI:星型,每个从机单独接 CS
- 应答机制
- IIC:有ACK 应答,可靠性高
- SPI:无固定应答,纯高速收发
- 电平与容错
- IIC:开漏输出,需上拉电阻,支持多设备线与
- SPI:推挽输出,无需上拉,驱动能力强
- 使用场景
- IIC:低速外设(温湿度、EEPROM、RTC、传感器)
- SPI:高速外设(Flash、显示屏、ADC、无线模块)
2.最高通信速率
IIC标准:最高 400Kbps(高速模式 Fast-mode)超高速模式可达3.4Mbps(极少用)日常工程默认:400Kbps
SPI无标准固定上限,硬件决定普通 MCU SPI:10MHz~20MHz高速 SPI:可达几十 MHz工业常用极限:最高 100Mbps+
三.确认实习内容做的是哪个层面的工作,是偏向驱动开发还是协议解析
二者核心定义
驱动开发(底层硬件层)直接操作寄存器、配置时钟、初始化 IIC/SPI/UART/CAN 等外设,写硬件初始化、收发底层函数,对接芯片引脚与控制器,偏向硬件操控、寄存器配置、硬件时序适配,贴近 MCU 内核与硬件电路。
协议解析(应用 / 中间层)基于现成底层驱动接口,做数据帧封装、校验、解包、指令解析、业务指令交互,解析设备通信协议、数据格式、指令码,不碰底层寄存器,偏向数据逻辑、通信报文、业务交互。
四.用户态和内核态的区别是
1. 基本定义
- 内核态(Ring0):操作系统内核运行层级,权限最高
- 用户态(Ring3):普通应用程序运行层级,权限受限
2. 核心区别
权限不同
- 内核态:可访问全部物理内存、操作硬件、读写寄存器、修改系统资源
- 用户态:只能访问自己进程内存,不能直接操作硬件
资源访问
- 内核态:直接操控磁盘、网卡、串口、CPU 寄存器
- 用户态:不能直接操作硬件,必须通过系统调用
运行代码
- 内核态:驱动、操作系统内核、中断服务程序
- 用户态:APP、应用软件、业务程序
切换方式
用户态 → 内核态:系统调用、中断、异常
内核态 → 用户态:中断返回、调度返回
安全性
- 内核态:代码出错直接系统崩溃
- 用户态:程序崩溃只卡死自己,不影响系统
五.iic总线最多能挂载多少个设备(待定)
7 位地址(最常用)
- 地址范围:0x00 ~ 0x7F → 共128 个地址
- 0x00 是广播地址,不分配给从机
- 另有少量保留地址(如 0x01~0x07、0x78~0x7F)
- 一般面试直接说:理论最多 127 个
实际:受 400pF 电容限制 → 建议 ≤ 8 个
六.iic的起始信号和结束信号是怎么样的
默认空闲状态:SCL 高电平,SDA 高电平
1. 起始信号(Start)
SCL 为高电平时,SDA 由高电平跳变到低电平
- 时序:SCL=1 → SDA 下降沿
- 作用:通知所有从机,开始通信
2. 停止信号(Stop)
SCL 为高电平时,SDA 由低电平跳变到高电平
- 时序:SCL=1 → SDA 上升沿
- 作用:结束本次 IIC 通信
七.那spi的起始信号和结束信号又是怎么样的
SPI 无专用启停电平,拉低 CS 开始通信,拉高 CS 结束通信
八.有实际测过iic和spi接口的信号波形
实际使用示波器实测过 IIC、SPI 两种通信波形,熟悉两种总线真实时序。
1. IIC 实测波形
- 空闲状态:SCL、SDA 均为高电平
- 起始信号:SCL 高,SDA 由高变低,示波器能清晰看到下降沿
- 停止信号:SCL 高,SDA 由低变高,出现上升沿
- 数据位:SCL 高电平时数据稳定,SCL 低电平才允许 SDA 跳变
- 可测出:高低电平宽度、通信波特率、ACK 应答低电平脉冲
- 常见问题:上拉电阻不合适导致波形畸变、上升沿过缓
2. SPI 实测波形
- 空闲:CS 片选高电平,时钟 SCK 无波形
- 通信开始:CS 拉低后,出现连续周期性 SCK 时钟方波
- 两根数据线 MOSI、MISO跟随时钟同步跳变,全双工同时有数据波形
- 可直观看出时钟极性 CPOL、时钟相位 CPHA配置对应的不同采样边沿
- 通信结束:CS 拉高,时钟与数据波形立即消失
- 实测能区分高位在前 / 低位在前,也能测出实际传输速率
九. 多从机的情况下spi的片选如何设计
1.核心原理
SPI无地址寻址,依靠独立片选 CS区分不同从机,同一时刻只能拉低一个 CS,避免总线数据冲突。
四种常用设计方案
1. 独立 GPIO 直连(最常用)
2. 译码器扩展(GPIO 不够首选)
3. 软件模拟片选(分时复用)
4. 菊花链模式(串联)
多从机通信规则(必背)
- 任意时刻仅一个 CS 拉低,其余全部高电平
- 切换从机前,必须结束上一次 SPI 传输
- 所有从机共用同一组 SCK、MOSI、MISO三根总线
- 严禁同时拉低两个片选,会造成数据总线短路错乱
十.讲一下Linux系统的中断机制,追问底层实现逻辑
- 中断上下文不能休眠,没有进程栈,无法调度
- 中断优先级:硬件中断 > 软中断 > 进程
- 中断嵌套:Linux 默认允许中断嵌套,高优先级可打断低优先级
- 中断耗时太长会导致:键盘卡顿、网口丢包、定时器不准
1.整体流程
- 外设产生电信号,拉低 / 拉高中断引脚,向 CPU 发中断请求
- CPU 暂停当前进程,跳转到内核中断入口
- 内核判断中断号,找到对应中断服务函数
- 执行中断处理,分顶半部、底半部
- 处理完成,恢复现场,回到原先程序继续运行
十一.中断有什么注意点吗
中断上下文不许休眠、不许阻塞、执行要快;耗时业务下放底半部,优先用工作队列;共享资源用自旋锁不用互斥锁;内存分配用原子模式;合理选择触发方式,尽量缩短中断执行时间。
2. 顶半部 / 底半部完整区分
顶半部(硬中断)纯中断上下文,严禁休眠,快进快出
底半部分两种
- 轻量底半部:tasklet / 软中断还是中断上下文→ 不能睡
- 重型底半部:工作队列进程上下文→ 随便睡
3.中断里用自旋锁,不用互斥锁?二者核心区别
1. 互斥锁 mutex
- 获取不到锁:主动休眠放弃 CPU,等锁释放再唤醒
- 依赖进程调度,只能在进程上下文使用
- 中断上下文没有调度能力,休眠直接死锁崩溃
2. 自旋锁 spinlock
- 获取不到锁:原地循环空转,一直轮询等锁
- 不休眠、不切换进程,可用于中断上下文
- 缺点:拿不到锁会一直占用 CPU
3.中断分配内存为什么必须用 GFP_ATOMIC 原子模式
1. GFP_KERNEL(普通常用)
- 内存不足时,会阻塞休眠,等待系统释放空闲内存
- 休眠行为在中断上下文直接禁用,会崩系统
2. GFP_ATOMIC 原子分配
- 绝不休眠、绝不阻塞
- 不管内存够不够,立刻尝试分配,失败直接返回 NULL
- 完全适配中断上下文不能休眠的硬性规则
十二.中断和轮询哪个效率高,选择其一的考虑因素有
空闲多时:中断效率远高于轮询数据极密集、连续高速收发:轮询反而更快
1. 轮询
- 原理:CPU 死循环不断查询外设状态
- 优点:无上下文切换开销,连续高速传输吞吐极高
- 缺点:全程占用 CPU,空转极度浪费资源
- 适用:高频连续数据、无空闲等待场景
2. 中断
- 原理:外设有事主动通知 CPU,没事 CPU 正常跑业务
- 优点:CPU 利用率极高,空闲时完全不占用
- 缺点:存在中断响应、上下文切换开销,频繁中断会造成系统抖动
十三.Linux系统的驱动有哪几种分类
Linux 驱动三大主流分类
字符设备驱动字节流读写,顺序访问,无缓冲区。例:串口、LED、按键、传感器、I2C/SPI 外设。
块设备驱动整块读写,随机访问,自带缓存。例:硬盘、U 盘、SD 卡、闪存。
网络设备驱动面向数据包收发,无文件节点,走协议栈。例:以太网网卡、WiFi 模块。
十四.介绍一下字符设备驱动
定义Linux 三大驱动之一,以字节流形式逐字节读写数据,按顺序访问,不支持随机寻址。
核心特点
- 访问方式:像读写普通文件一样 open/read/write/close
- 存在形式:在
/dev下生成设备文件节点 - 无硬件缓存,数据串行收发
- 应用层与内核层通过文件操作接口交互
常用硬件LED、按键、串口、I2C/SPI 外设、传感器、激光雷达、触摸屏等。
十五.详细介绍其中一个需求开发具体如何实现的
我拿激光雷达驱动开发举例。首先完成雷达和板卡硬件接线,确定串口通信方式和私有通信协议;然后基于 Linux 字符设备框架开发驱动,申请设备号、实现文件操作接口,配置串口参数并注册接收中断;中断里逐字节接收原始数据,通过帧头帧尾匹配、校验校验,拼成完整数据帧,解析出角度距离等点云信息,放到内核环形缓存;应用层通过读取 /dev 下的设备节点获取点云数据,供给上层视觉和避障算法使用,同时做了缓存、容错和资源释放,保证驱动稳定运行。
十六. 其中激光雷达和板卡的通信方式
激光雷达和板卡常用四种通信:UART 串口、以太网、CAN 总线、USB 虚拟串口。
低端单线雷达多用UART 串口,接线简单、协议简易;
多线高端雷达用以太网,带宽大、能传输海量点云数据;
车载工业场景用CAN 总线,抗干扰能力强;还有 USB 虚拟串口,调试方便、即插即用。
十七. 还问了项目中视觉识别的细节问题
整个视觉识别流程:图像采集 → 预处理 → 目标检测推理 → 后处理 → 与激光雷达数据融合 → 输出结果给业务层。
我们项目视觉识别整体是摄像头采集图像,先做裁剪、降噪、归一化预处理;采用轻量级 YOLO 模型,导出 ONNX 在板卡端做轻量化部署和 INT8 量化推理;推理后经过 NMS 非极大值抑制、置信度过滤得到目标检测框;再和激光雷达做数据融合,通过相机标定和手眼标定,把像素坐标转换成实际物理距离坐标;整个架构采用多线程加队列解耦,保证嵌入式端实时性,同时针对光照、误检、推理速度问题做了对应的优化。
十八. 团队成员之间意见冲突时如何处理
遇到团队意见冲突,我会先冷静倾听对方思路,理性梳理双方方案的优缺点,以项目进度和落地效果为核心进行沟通讨论;技术上对比可行性与风险,若仍有分歧就交由上级定夺,自己服从团队安排,专注配合完成开发任务。
十九. 有同事指出你的问题时你会怎么办
我会虚心接受同事的意见,放平心态认真听取问题细节;先自查确认自身不足,有问题及时整改修正;有理解差异就平和沟通、同时做好复盘总结,避免后续再犯,保持团队良好协作。
二十. c语言的编译过程
C 语言编译分四步:预处理、编译、汇编、链接。预处理展开头文件和宏、删除注释;编译做语法检查转成汇编;汇编把汇编转为机器码生成目标文件;最后链接合并目标文件和库,生成可执行程序。
二十一. 引用和指针的区别
引用是变量的别名,必须初始化、不能为空、不能更改指向,不占额外内存;指针是存放地址的变量,可以为空、可以随时改指向,占用独立内存,使用需要解引用。
二十二. 介绍volitate
4. 易错点(面试常考)
volatile 不保证原子性、不保证线程安全,只防止编译器优化,不能替代互斥锁、信号量。
5. 面试精简口述版
volatile 关键字主要用来禁止编译器优化,强制变量每次都从内存读取,而不是缓存到寄存器;主要用在硬件寄存器、多线程共享变量、中断全局变量场景;
二十三.介绍c++的纯虚数
1. 定义格式
virtual void func() = 0;2. 核心作用
- 只声明接口,没有具体实现
- 包含纯虚函数的类 =抽象类
- 抽象类不能实例化,只能被继承
3. 派生类要求
子类必须重写纯虚函数,否则子类也变成抽象类,也不能创建对象。
4. 应用场景
用来做接口设计、多态规范,统一标准接口,让所有子类必须实现同一套方法,比如设备驱动、业务模块统一接口。
(因为纯虚函数只有声明、没有具体实现,如果抽象类能实例化,调用这个无实现的函数程序会崩溃;所以语法规定抽象类不能创建对象,只能作为父类被继承,强制子类重写纯虚函数、补齐实现后才能实例化使用。)
面试精简背诵版
C++ 纯虚函数用virtual 函数 = 0定义,没有函数实现;包含纯虚函数的类是抽象类,不能实例化,只能被继承;派生类必须重写纯虚函数,否则自身也是抽象类;主要用来定义统一接口,实现多态和规范子类行为。
四.进程和线程的区别
资源隔离进程有独立虚拟地址空间,互不共享;线程共享所在进程的地址空间、全局变量、文件描述符,只有私有栈和寄存器。
开销大小进程创建、销毁、切换开销大;线程轻量,创建切换开销小、速度快。
通信方式进程间通信复杂:管道、消息队列、共享内存、信号量、Socket;线程直接读写全局变量即可通信。
崩溃影响一个进程崩溃,不影响其他进程;一个线程崩溃,整个进程直接退出。
调度单位进程是资源分配的基本单位;线程是CPU 调度的基本单位。
从属关系一个进程至少有一个主线程,一个进程可以包含多个线程。
五.进程的通信方式
六.信号量和互斥锁的应用场景
互斥锁用于临界资源互斥访问,同一时刻只允许一个线程操作共享数据,保证数据安全;
信号量多用于生产者消费者、线程同步、并发限流,可以控制多个线程同时访问数量,还能协调线程执行顺序。
七.堆栈的区别
栈由系统自动分配自动释放,空间小、速度快,存放局部变量和函数参数,函数结束立即回收;
堆由程序员手动申请释放,空间大、速度慢,存放动态内存,不及时释放会造成内存泄漏。
八.在c语言中如何判断两浮点数相等
不能直接用 == 判断浮点数相等,因为浮点数存在精度误差。
正确做法是:计算两个数差值的绝对值,判断是否小于一个极小精度值(如 1e-6),如果小于就认为相等。
- 单精度 float 用1e-6
- 双精度 double 用1e-9
九.指针数组和数组指针的区别
看括号:括号跟数组是数组指针,括号跟指针是指针数组
- 指针数组:
int *arr[]—— 存放指针的数组 char *str[] = {"abc","123"}; - 数组指针:
int (*p)[]—— 指向数组的指针 int arr[3][4]; int (*p)[4] = arr;
十.什么是平衡二叉树
平衡二叉树是高度差不超 1 的二叉搜索树,通过旋转维持平衡,保证查找效率稳定。
左旋、右旋、左右旋、右左旋
十一.介绍排序算法
冒泡排序,选择排序,插入排序,希尔排序,快速排序,归并排序,堆排序,基数排序
简单排序冒泡、选择、插入,复杂度\(O(n^2)\);
高效排序快排、归并、堆排,复杂度\(O(n\log n)\);
十二.反转字符串中的单词
先把整个字符串全部反转,再遍历字符串,遇到空格就反转当前单词,最终实现单词顺序颠倒、单词内部字母顺序不变。
十三.说完思路后追问一个单词要反转几次
- 整个字符串整体反转 1 次
- 每一个独立单词各自反转 1 次
// 反转指定区间字符 void reverse(char *s, int l, int r) { while(l < r) { char t = s[l]; s[l] = s[r]; s[r] = t; l++; r--; } } // 反转单词 void reverseWords(char *s) { int len = strlen(s); // 1.整体反转 reverse(s, 0, len-1); int start = 0; // 2.逐个反转单词 for(int i = 0; i <= len; i++) { if(s[i] == ' ' || s[i] == '\0') { reverse(s, start, i-1); start = i + 1; } } }十四.问理想的工作环境
首先团队氛围轻松融洽,同事之间沟通顺畅、互帮互助,没有内耗;其次技术氛围浓厚,大家乐于交流探讨问题,能互相学习共同进步;再者公司制度规范合理,权责清晰,做事流程简洁不繁琐;同时重视员工成长,有培训、项目实战等提升机会;最后办公环境舒适,劳逸结合,工作氛围积极正向。
十五.你认为比较合理的上班时间
十六.职业规划
- 短期(1 年内):快速熟悉公司业务、项目流程与所用技术栈,尽快上手独立完成分配任务,补齐自身技术短板,融入团队站稳脚跟。
- 中期(2-3 年):深耕岗位技术,熟练掌握核心业务逻辑,能够独立负责模块开发与问题排查,提升项目实战能力,往资深开发方向发展。
- 长期:持续精进专业能力,不断学习新技术,争取能够主导项目功能开发,逐步向技术骨干方向发展,在岗位上创造更多价值,和公司共同成长。
十七.工作地倾向
反问
9.14 综合面(hr面) 就20min
一.上一轮面试体验感如何
整体体验很不错,面试官提问专业细致,沟通氛围轻松友好,不仅考察专业知识,也让我认清自身不足,收获很大,也更加坚定我求职方向。
二.秋招进展,收到offer了吗
目前正在积极参与秋招面试,处于面试推进阶段,暂时还没有确定最终 offer,希望能找到契合自身发展、平台合适的岗位。
三.在选择工作上最关注的三个维度
- 平台与发展:公司行业前景好,有完善培养体系,能学到实用技术
- 工作内容:岗位贴合自身专业,能发挥所学,积累项目实战经验
- 团队氛围:团队氛围和睦,同事好沟通,工作氛围积极轻松
四.父母对你工作上有什么建议
父母希望我找一份稳定踏实、正规靠谱的工作,不用急于求成,优先注重个人成长,脚踏实地做事,放平心态,好好积累经验,兼顾身体健康。