当前位置: 首页 > news >正文

UART,IIC,SPI总线(通信协议)

嵌 入 式 软 件 笔 试 题

要求:闭卷考不能翻书、不能开电脑);作答时间50分钟共10道题目。

  1. volatile的作用有哪些

volatile: 防止编译器对代码进行优化,直接从内存中取最新的值 应用场景: 1、多线程使用同一资源时 2、单片机开发中

volatile 的作用:

1. 核心功能:告知编译器变量的值可能被当前代码块外的因素(如中断服务程序、硬件寄存器、其他线程)异步修改,禁止编译器对该变量进行 “将内存值缓存到寄存器” 的优化,确保每次访问都直接读取内存最新值。

应用场景:

1. 多线程 / 多任务环境中,共享变量(如线程间标志位);

2. 嵌入式硬件寄存器访问(如单片机的 GPIO 数据寄存器、定时器计数寄存器);

3. 中断服务程序(ISR)与主程序共享的全局变量。

  1. 关键字const 和static有什么含意

Const :“只读属性”,限制变量 / 指针 / 参数的值不可被修改,编译时会检查写操作并报错,

Static:静态函数,可以延长生命周期和限定作用域

1. const 关键字含义
用于定义 “只读属性”,限制变量 / 指针 / 参数的值不可被修改,编译时会检查写操作并报错,常见场景:
- 修饰变量:const int a = 10;(a 的值不可修改);
- 修饰指针:
const int* p(指针指向的不可改);
int* const p(指针本身地址不可改);
- 修饰函数参数:void func(const int x)(函数内不可修改 x);
- 修饰函数返回值:const int func()(返回值不可被赋值修改)。

2. static 关键字含义
用于 “延长生命周期” 和 “限定作用域”,分三类场景:
- 局部静态变量:void func(){ static int a = 0; a++; }(生命周期延长至程序结束,作用域仅在函数内,初始化仅 1 次);
- 全局静态变量:static int g_a = 10;(作用域限定在当前.c 文件,避免外部文件通过extern调用);
- 静态函数:static void func(){}(作用域限定在当前.c 文件,防止与外部文件函数重名冲突)。

  1. 用变量a给出下面的定义
    1) 一个整型数         int a
    2)一个指向整型数的指针  int *a
    3)一个指向指针的的指针,它指向的指针是指向一个整型数 int **a;
  2. 下面的代码输出是什么,为什么?(printf为打印函数)

void foo(void)
{
unsigned int a = 6;
int b = -20;
(a+b > 6) ? printf("> 6") : printf("<= 6");
}

输出是>6,因为不同无符号 / 有符号整型运算时,会触发 “隐式类型转换”—— 将int(有符号)转换为unsigned int(无符号):

C 语言中,不同无符号 / 有符号整型运算时,会触发 “隐式类型转换”—— 将int(有符号)转换为unsigned int(无符号):
1. 变量值:a = 6(unsigned int,二进制为000...000110),b = -20(int,32 位补码为111...1101100);
2. 转换后:b作为 unsigned int 时,值为2^32 - 20 = 4294967276
3. 计算:a + b = 6 + 4294967276 = 4294967282(远大于 6),故执行printf("> 6")

  1. 中断是嵌入式系统中重要的组成部分,这导致了许多编译开发商提供一种扩展:让标准C支持中断,产生了一个新的关键字__interrupt。下面的代码就使用了__interrupt关键字去定义了一个中断服务子程序,请指出以下这段代码错误的地方。
    __interrupt double compute_area(double radius)
    {
    double area = PI * radius *radius;
    printf("nArea = %f", area);
    return area;
    }    该中断服务子程序(ISR)存在 5 处核心错误
    1. 返回值错误:ISR 是异步触发的 “被动执行函数”,没有调用者接收返回值,必须定义为void,不能返回double
    2. 参数错误:中断触发时无法传递参数(无调用上下文),ISR 不能带参数(如double radius);
    3. 调用非可重入函数printf是标准库函数,内部包含浮点运算、全局缓冲区操作,且可能依赖中断使能,属于 “非可重入函数”;ISR 要求 “快进快出”,禁止调用非可重入、耗时函数;
    4. 浮点运算风险:嵌入式系统中,double浮点运算需硬件 FPU 支持,且运算耗时较长,不符合 ISR “短延迟” 要求;
    5. PI 未定义:若未通过#define PI 3.14159宏定义 PI,编译会报 “未声明标识符” 错误(非核心,但需修正)。
  2. 嵌入式系统中经常要用到无限循环,用C语言编写死循环的代码

     While(1)1. while(1){}(最常用,明确循环体为空);
2. for(;;){}for循环的初始化、条件、增量均可省略,条件省略视为 “永真”);
3. do{}while(1);(先执行一次循环体,再判断永真条件)。

  1. 给定一个整型变量a,写两段代码,第一个设置a的bit 3,第二个清除a 的bit 3。在以上两个操作中,要保持其它位不变。

     设置: aI=(0x3<<偏移量)  设置 a&= ~(0x3<<偏移量)

  1. 已知 int 数组a[1000],需要将数组的后 100 个数据移动到前面,前面的数据依次后退。例如,若数组初始存入的数据是 1、2、3……1000,移动后的数据结果是 901、902……1000、1、2……900。用代码实现。

使用memcoy

#include <string.h>

void move_array(int a[], int n, int m) {

    int t[100];

    memcpy(t, a + n - m, m * sizeof(int));

    for(int i = n - 1; i >= m; i--)

        a[i] = a[i - m];

    memcpy(a, t, m * sizeof(int));

}

int main() {

    int a[1000];

    for(int i = 0; i < 1000; i++)

        a[i] = i + 1;

    move_array(a, 1000, 100);

    return 0;

}

  1.  简述SPI的传输特点、方式并画出工作时序

传输特点:

1.通信属性:串行(数据逐位传),同步(依赖sclk(spi)时钟同步),全双工(同一时钟周期内,主机经mosi发、从机经miso发,双向同时传);

  1. 速率与数据::“高速 3.4Mbps” 是 HS-mode,需区分 “标准模式(100Kbps)、快速模式(400Kbps)、高速模式(3.4Mbps)速率达mbps级;最小单位为字节(8/16位),1时钟周期传1位,1字节需8时钟周期;
  2. 主从模式:支持主从机,常用“单主机多从机”,主机控制sck时钟和nss片选,从机被动响应
  3. 从机选择:通过专属的nss/ncs片选线,主机拉低目标从机nss电平建立通信,其他从机nss保持高电平不响应

传输方式:

  1. 主从逻辑:主机输出sck和nss,经mosi发数据;从机按sck节奏收mosi数据,经miso回传数据
  2. 全双工实现:如主机发 0xFF、从机发 0x00,SCK 上升沿时二者分别经 MOSI/MISO 发 1 位,下降沿时分别读对方数据;8 时钟周期后,双方均完成 “发 + 收”;
  3. 多从机传输:四线制连接(sck、mosi、miso共线,各从机独立接主机nss),主机拉低对应从机nss实现“一对一”通信,避免冲突。

工作时序图:

  1. 简述I2C的传输特点、方式并画出工作时序(从机地址、寄存器地址、数据自定义)

一、I2C 传输特点

  1. 传输类型:串行(逐位传)、同步(依赖 SCL 时钟同步)、半双工(同一时间单向传);
  2. 硬件结构:仅 2 根双向线(SCL 时钟、SDA 数据),均需外接上拉电阻(空闲时保高电平、稳电路);
  3. 速率分级:低速 100Kbps、中速 400Kbps、高速 3.4Mbps;
  4. 主从架构:支持单 / 多主机多从机,主机主动发起 / 结束通信,从机被动响应;
  5. 唯一寻址:从机均有唯一 7 位地址(如 SHT20 为 0x40),主机通过地址定位从机;
  6. 应答机制:每传 1 字节(8 位),接收器第 9 时钟周期回 ACK(0,成功)或 NACK(1,失败 / 停止)。

二、I2C 传输方式

1. 主机→从机(写传输)

  1. 主机发起始信号(S),占总线;
  2. 发 “7 位从机地址 + W(0)”(如 SHT20 写地址 0x80);
  3. 从机回 ACK;
  4. 发目标寄存器地址(如 SHT20 温度寄存器 0xE3);
  5. 从机回 ACK;
  6. 发自定义数据(如配置值 0x55);
  7. 从机回 ACK;
  8. 主机发终止信号(P),释总线。

2. 主机←从机(读传输,先写后读)

  1. 主机发起始信号(S);
  2. 发 “7 位从机地址 + W”(如 0x80),从机回 ACK;
  3. 发目标寄存器地址(如 SHT20 湿度寄存器 0xE5),从机回 ACK;
  4. 主机发重复起始信号(S);
  5. 发 “7 位从机地址 + R(1)”(如 SHT20 读地址 0x81),从机回 ACK;
  6. 从机发自定义数据(如 2 字节湿度值 0x1234),每字节主机回 ACK;
  7. 主机收完回 NACK(停传);
  8. 主机发终止信号(P)。

三、I2C 工作时序(以 SHT20 读温度为例)

1. 时序参数

  • 从机地址:7 位 0x40;
  • 寄存器地址:0xE3(温度寄存器);
  • 自定义数据:2 字节温度值(0x1A、0x5B);
  • 时钟周期:1 个高 + 低电平,传 1 位需 1 周期。

2. 时序文字示意

信号

时序(高电平 “┌───┐”,低电平 “───”)

阶段说明

SCL

──┐ ┌───┐×8 ┌───┐ ┌───┐×8 ┌───┐×2 ┌───┐

时钟同步

SDA

──┼───┼───┼×8───┼───┼───┼×8───┼───┼───┼×2───┼───┘

数据 / 控制信号

阶段

S → 写寻址(0x80)→ ACK → 寄存器(0xE3)→ ACK → 重复 S → 读寻址(0x81)→ ACK → 数据(0x1A→ACK→0x5B→NACK)→ P

传输流程

3. 时序步骤

  1. S(起始):SCL 高时,SDA 高→低(下降沿);
  2. 写寻址:SCL 高时,SDA 传 0x80(8 位),从机回 ACK;
  3. 寄存器地址:SCL 高时传 0xE3,从机回 ACK;
  4. 重复 S:SCL 高时,SDA 高→低;
  5. 读寻址:SCL 高时传 0x81,从机回 ACK;
  6. 传数据:SCL 高时从机传 0x1A(高 8 位),主机回 ACK;再传 0x5B(低 8 位),主机回 NACK;
  7. P(终止):SCL 高时,SDA 低→高(上升沿)。

答题区:

答题要求:闭卷考试(不能翻书、不能开电脑);作答时间50分钟;共10道题目。

(请保留第原题目,答题区请备注好做题序号;只能写在答题纸上拍照粘贴到文档里-答题区,请保证照片清晰)

发送时请将文档命名更改为:本人姓名_软件笔试题


文章转载自:

http://jhFN6t4Y.bmLcy.cn
http://GZPtLqQb.bmLcy.cn
http://OMkuTDCM.bmLcy.cn
http://7Wwxnv23.bmLcy.cn
http://2WPXvNHC.bmLcy.cn
http://46gkCavd.bmLcy.cn
http://wnd08J3t.bmLcy.cn
http://ZHjM41jb.bmLcy.cn
http://9vLxbXcv.bmLcy.cn
http://OIPX90V4.bmLcy.cn
http://Lkk7tp3C.bmLcy.cn
http://CpzlMLzJ.bmLcy.cn
http://yiHZlwoj.bmLcy.cn
http://k0KZ8XkA.bmLcy.cn
http://H5S8IByP.bmLcy.cn
http://26zREQPb.bmLcy.cn
http://SREu5aoi.bmLcy.cn
http://8Uk9nnV0.bmLcy.cn
http://mlqMjsQb.bmLcy.cn
http://kiM5loHp.bmLcy.cn
http://6jGY6UgP.bmLcy.cn
http://apbycDN7.bmLcy.cn
http://E3NSaCZP.bmLcy.cn
http://O3mtLX42.bmLcy.cn
http://GDSe9qtY.bmLcy.cn
http://shIukScr.bmLcy.cn
http://VCW3byuh.bmLcy.cn
http://HKNgB0Px.bmLcy.cn
http://95KIYHS3.bmLcy.cn
http://mXJ7Qp0f.bmLcy.cn
http://www.dtcms.com/a/385877.html

相关文章:

  • 记录一次小程序请求报错:600001
  • 光谱相机的新兴领域应用
  • GO学习记录十——发包
  • OpenLayers数据源集成 -- 章节十六:XML图层详解:OpenStreetMap数据的动态加载与智能样式渲染方案
  • vector 模拟实现 4 大痛点解析:从 memcpy 到模板嵌套的实战方案
  • tuple/dict/list 这三个数据类型在取值时候的区别
  • 用Python实现自动化的Web测试(Selenium)
  • Spring Boot 2.5.0 集成 Elasticsearch 7.12.0 实现 CRUD 完整指南(Windows 环境)
  • 第九章:使用Jmeter+Ant+Jenkins实现接口自动化测试持续集成
  • 使用IP的好处
  • 育碧确定《AC影》3月20日发售并分享系列游戏首发数据
  • 容器热升级机制在云服务器零停机部署中的实施规范
  • 贪心算法应用:时间序列分段(PAA)问题详解
  • 微信小程序开发教程(十五)
  • 语音DDS系统架构与实现方案:车机与手机语音助手的差异分析
  • 手机群控平台的工作效率
  • DBAPI免费版对比apiSQL免费版
  • node.js在vscode中npm等出现的一个问题
  • node.js学习笔记:中间件
  • Debian更新安全补丁常用命令
  • LeetCode:6.三数之和
  • 号称用rust重写的sqlite数据库tursodb与sqlite及duckdb性能比较
  • cuda stream
  • 云计算在云手机中的作用
  • C++STL学习:unordered_set/unordered_map
  • RTOS 任务状态与调度机制详解
  • 基于 Java EE+MySQL+Dart 实现多平台应用的音乐共享社区
  • 解密Tomcat的I/O模型:非阻塞之上,为何要兼容阻塞?
  • 时序数据库IoTDB如何支撑万亿级设备连接?
  • 订阅式红队专家服务:下一代网络安全评估新模式