面试(五)

目录

1. 知道大顶堆小顶端吗,代码怎么区分大顶端小顶端

2. 计算机中栈地址与内存地址增长方向相反吗?

3. %p和%d输出指针地址

4. 为什么定义第二个变量时候,地址反而减了

5. 12,32,64位中数据的占字节?

6. IIC可以接入多少个设备

7. STM32的三级流水线

8. STM32F4中初始化硬件IIC代码

9. STM32启动流程:初始化确定启动方式->sp,pc指针->系统时钟初始化->初始化用户堆栈->跳到main()

10. STM32F4初始化蓝牙串口和蓝牙HC-05所有配置的代码

11. MCU/DSP

12. 学一个新板子,我们要先知道什么

13. STM32F4中函数怎么压栈到寄存器

14. STM32为什么中断会进入UART4_IRQHandler()

15. STM32收到串口数据时寄存器的状态

16. C++中链表的插入,删除


1. 知道大顶堆小顶端吗,代码怎么区分大顶端小顶端

(1)大顶端: 将数据的最高有效字节存储在起始地址,即高位字节在前。小顶端: 将数据的最低有效字节存储在起始地址,即低位字节在前。

假如现有一32位int型数0x12345678,那么其MSB(Most Significant Byte,最高有效字节)为0x12,其LSB (Least Significant Byte,最低有效字节)为0x78,在CPU内存中有两种存放方式:(假设从地址0x4000开始存放)[一个地址下存放一个字节]

(2) 代码区分大顶端和小顶端。

代码1:

#include <stdio.h>

int main() {
    unsigned int x = 0x12345678;
    unsigned char *p = (unsigned char *)&x;

    if (*p == 0x78) {
        printf("小端");
    } else if (*p == 0x12) {
        printf("大端");
    } else {
        printf("未知");
    }

    return 0;
}

指针类型为char而不是int,是因为我们只关心内存中的最低有效字节(LSB),即最低位的字节。在这个例子中,我们想要检查一个整数的字节序,所以我们需要将整数的地址转换为一个字符指针,然后通过解引用这个指针来访问最低有效字节。这样我们就可以根据这个字节的值来判断整数的字节序是大端还是小端。

代码2:

#include <stdio.h>

union {
    unsigned int i;
    unsigned char c[4];
} u;

int main() {
    u.i = 0x12345678;

    if (u.c[0] == 0x78) {
        printf("小端");
    } else if (u.c[0] == 0x12) {
        printf("大端");
    } else {
        printf("未知");
    }

    return 0;
}
在这个例子中,我们使用了一个联合体,它包含一个整数和一个字符数组。我们将整数赋值给联合体的整型成员,然后通过访问字符数组的第一个元素来判断字节序。如果第一个元素的值是0x78,那么就是小端;如果第一个元素的值是0x12,那么就是大端;否则就是未知。

2. 计算机中栈地址与内存地址增长方向相反吗?

计算机内存地址增长的方向是自小到大。栈地址增长方向与内存地址增长方向相反。

3. %p和%d输出指针地址

是把指针变量p中存储的a的地址以十六进制形式输出,%d是吧p中存储的a的地址以十进制形式输出。输出的都是p的值,不要理解成%p,是把p的地址输出。

//3和4的代码
#include <stdio.h>

int main()
{
    int a = 2;
    int b = 3;
    char c = 'a';
    int *p = &a;
    
    printf("%d\r\n",&a);
    printf("%p\r\n",&a);
    printf("%p\r\n",&b);
    printf("%p\r\n",&c);
    printf("%p\r\n",p);
    p++;
    printf("%p\r\n",p);
    return 0;
}

4. 为什么定义第二个变量时候,地址反而减了

因为栈向下增长,所以先声明的地址大,后声明的地址小。栈的这种向下增长的设计使得它在处理函数调用时非常高效。每次函数调用时,都会在栈顶创建一个新的栈帧,用来存放该函数的局部变量和返回地址。当函数执行完毕返回时,对应的栈帧会被自动清理,栈顶恢复到调用前的位置。

5. 12,32,64位中数据的占字节?

8位系统32位系统64位系统
字符型1字节1字节1字节
整型2字节4字节4字节

长整型

4字节4字节4字节

浮点型

无统一标准4字节4字节

双精度浮点型

无统一标准8字节8字节

指针类型

无统一标准4字节8字节

6. IIC可以接入多少个设备

IIC最多可以接入2的7次方-1个设备,一共是127个。
第一个字节(为slave address)由7位地址和一位R/W读写位组成的,这字节是个器件地址。
首先,你要知道:常用IIC接口通用器件的器件地址是由种类型号,及寻址码组成的,共7位。
如格式如下: 
  D7 D6 D5 D4 D3 D2 D1 D0
1-器件类型由:D7-D4 共4位决定的。这是由半导公司生产时就已固定此类型的了,也就是说这4位已是固定的。

2-用户自定义地址码:D3-D1共3位。这是由用户自己设置的,通常的作法如EEPROM这些器件是由外部IC的3个引脚所组合电平决定的(用常用的名字如A0,A1,A2)。这也就是寻址码。
所以为什么同一IIC总线上同一型号的IC只能最多共挂8片同种类芯片的原因了。

3-最低一位就是R/W位。这位不用我多说了

7. STM32的三级流水线

三个主要步骤:取值,译码和执行,取指阶段是从存储器中加载指令到指令寄存器;译码阶段是解释指令含义并准备执行所需的操作;执行阶段则实际完成指令的操作,并将结果写回寄存器。流水线允许多个指令在不同的阶段同时进行处理。例如,当第一条指令处于执行阶段时,第二条指令可能正在进行译码,而第三条指令则在取指阶段

8. STM32F4中初始化硬件IIC代码

#include "stm32f4xx.h"

void I2C1_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    I2C_InitTypeDef I2C_InitStructure;

    // 开启I2C1时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);

    // 开启GPIOB时钟
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

    // 配置PB6和PB7为复用推挽输出
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    // 连接PB6和PB7到I2C1的SCL和SDA引脚
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1);
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_I2C1);

    // 初始化I2C1
    I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
    I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
    I2C_InitStructure.I2C_OwnAddress1 = 0x00;
    I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
    I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
    I2C_InitStructure.I2C_ClockSpeed = 100000; // 设置I2C时钟速率为100kHz
    I2C_Init(I2C1, &I2C_InitStructure);

    // 使能I2C1
    I2C_Cmd(I2C1, ENABLE);
}

9. STM32启动流程:初始化确定启动方式->sp,pc指针->系统时钟初始化->初始化用户堆栈->跳到main()

10. STM32F4初始化蓝牙串口和蓝牙HC-05所有配置的代码

#include "stm32f4xx.h"
#include "usart.h"
#include "bluetooth.h"

void Bluetooth_Init(void)
{
    // 初始化USART1,用于蓝牙通信
    USART_InitTypeDef USART_InitStructure;
    USART_InitStructure.USART_BaudRate = 9600; // 设置波特率
    USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 设置数据位长度为8位
    USART_InitStructure.USART_StopBits = USART_StopBits_1; // 设置停止位为1位
    USART_InitStructure.USART_Parity = USART_Parity_No; // 不使用奇偶校验
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 不使用硬件流控制
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // 设置为收发模式
    USART_Init(USART1, &USART_InitStructure);
    USART_Cmd(USART1, ENABLE); // 使能USART1

    // 初始化蓝牙模块
    Bluetooth_Config();
}

void Bluetooth_Config(void)
{
    // 发送AT指令来配置HC-05模块
    // 设置蓝牙名称
    Bluetooth_SendCommand("AT+NAME=HC-05");
    // 设置蓝牙配对密码
    Bluetooth_SendCommand("AT+PSWD=1234");
    // 设置蓝牙工作模式为可连接模式
    Bluetooth_SendCommand("AT+MODE=0");
    // 开启蓝牙模块
    Bluetooth_SendCommand("AT+POWE=1");
}

11. MCU/DSP

MCU是将计算机的主体部分集成在一块半导体上的单片机。DSP是专门用于数字信号处理的微处理器,特别是擅长处理如离散余弦变换、快速傅里叶变换等复杂计算。

12. 学一个新板子,我们要先知道什么

  • 核心处理器:了解SOC使用的中央处理单元类型,如ARM Cortex系列,以及其基本参数,包括频率、核心数量等。
  • 存储选项:研究SOC的内存布局,包括RAM和FLASH的容量,及其对程序执行和数据存储的影响。
  • 输入输出端口:熟悉可用的GPIO数量及其配置选项,理解如何通过这些接口与外部设备进行交互

13. STM32F4中函数怎么压栈到寄存器

在STM32F4中,函数压栈到寄存器涉及对特定寄存器的保存与恢复,确保程序的正常运行和中断处理的正确返回。具体来说,当进行函数调用或响应中断时,处理器自动把PSR, PC, LR, R12, R3, R2, R1, R0等寄存器的内容按照一定顺序压入栈中.手动需要压栈的寄存器包括R11, R10, R9, R8, R7, R6, R5, R4.

14. STM32为什么中断会进入UART4_IRQHandler()

原因是在于STM32微控制器的中断处理机制,该机制通过硬件触发和自动执行预定义的中断服务程序来响应特定的事件。

中断初始化和配置:在STM32中,要使能串口的中断功能,首先要正确配置相关的控制寄存器和中断向量。这包括启用UART4时钟,配置UART4的工作模式(如波特率、数据位等),以及设置中断优先级和使能特定类型的中断源(例如接收中断、发送完成中断等)

中断向量表的角色:启动文件startup_stm32f4xx.s中包含了一个中断向量表,该表为每个中断源指定了一个处理函数。对于UART4,这个向量表中会包含DCD UART4_IRQHandler这样的指令,直接指向了UART4_IRQHandler()函数的内存地址。当UART4的中断条件满足时,处理器会自动跳转到这个地址执行中断服务程序。

硬件自动压栈操作:响应中断时,Cortex-M内核将自动进行压栈操作,保存被中断的程序执行状态,包括程序计数器(PC)、状态寄存器(PSR)、以及一些关键的寄存器如R0-R3、R12、LR、PC、xPSR的值。这一过程完全由硬件自动完成,确保了中断处理完成后能够恢复到原来被打断的程序继续执行。

中断服务程序的执行:一旦处理器响应了中断并进入了UART4_IRQHandler(),它就会执行该函数中的代码来处理具体的中断事件。这包括读取UART4的数据寄存器以获取接收到的数据,或者根据设置处理其他类型的UART中断事件。

从中断返回:处理完中断事件后,UART4_IRQHandler()函数执行结束,内核会自动恢复之前保存的寄存器值,并从中断发生前的指令继续执行。这个过程称为异常退出处理,确保了程序的正确流程和数据的完整性。

错误处理和调试:如果中断处理过程中遇到问题,如硬件错误或配置不当,可能会触发额外的错误处理机制。在这种情况下,开发人员应检查配置是否正确,以及硬件连接是否稳定可靠。

15. STM32收到串口数据时寄存器的状态

STM32的USART是用于处理串口通信的外设,具备发送和接收数据的能力。而串口接收时,主要是状态寄存器和数据寄存器发生变化。

状态寄存器(USART_SR):此寄存器用于检测USART的当前状态,其中包括多个状态位,如发送寄存器空位、发送完成位、读数据寄存器非空位等。其中最重要的两位是RXNE(读数据寄存器非空)和TC(发送完成)

数据寄存器(USART_DR这是一个双向寄存器,分为发送数据寄存器(TDR)和接收数据寄存器(RDR)。向USART_DR写入数据时,数据会被存储在TDR内,用于后续的发送操作;从USART_DR读取数据时,会自动从RDR提取数据。

16. C++中链表的插入,删除

#include <iostream>
using namespace std;

struct ListNode {
    int val;
    ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};

// 在链表头插入节点
void insertAtHead(ListNode* &head, int val) {
    ListNode* newNode = new ListNode(val);
    newNode->next = head;
    head = newNode;
}

// 在链表尾部插入节点
void insertAtTail(ListNode* &head, int val) {
    ListNode* newNode = new ListNode(val);
    if (head == NULL) {
        head = newNode;
        return;
    }
    ListNode* temp = head;
    while (temp->next != NULL) {
        temp = temp->next;
    }
    temp->next = newNode;
}

// 在指定位置插入节点
void insertAtPosition(ListNode* &head, int position, int val) {
    if (position == 0) {
        insertAtHead(head, val);
        return;
    }
    ListNode* newNode = new ListNode(val);
    ListNode* temp = head;
    for (int i = 1; i < position && temp != NULL; i++) {
        temp = temp->next;
    }
    if (temp == NULL) {
        cout << "Invalid position!" << endl;
        return;
    }
    newNode->next = temp->next;
    temp->next = newNode;
}

// 删除指定值的节点
void deleteNode(ListNode* &head, int val) {
    if (head == NULL) {
        return;
    }
    if (head->val == val) {
        ListNode* temp = head;
        head = head->next;
        delete temp;
        return;
    }
    ListNode* temp = head;
    while (temp->next != NULL && temp->next->val != val) {
        temp = temp->next;
    }
    if (temp->next == NULL) {
        cout << "Value not found!" << endl;
        return;
    }
    ListNode* toDelete = temp->next;
    temp->next = temp->next->next;
    delete toDelete;
}

// 删除指定位置的节点
void deleteAtPosition(ListNode* &head, int position) {
    if (head == NULL) {
        return;
    }
    if (position == 0) {
        ListNode* temp = head;
        head = head->next;
        delete temp;
        return;
    }
    ListNode* temp = head;
    for (int i = 1; i < position && temp != NULL; i++) {
        temp = temp->next;
    }
    if (temp == NULL || temp->next == NULL) {
        cout << "Invalid position!" << endl;
        return;
    }
    ListNode* toDelete = temp->next;
    temp->next = temp->next->next;
    delete toDelete;
}

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

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

相关文章

DIYP对接骆驼后台IPTV管理,退出菜单中显示用户名已经网络信息,MAC,剩余天数,套餐名称等

演示&#xff1a;https://url03.ctfile.com/f/1779803-1042599473-4dc000?p8976 (访问密码: 8976) 后台加上EPG&#xff0c;增加一些播放源的动态端口替换。 前台app上&#xff0c;退出菜单中显示用户名已经网络信息&#xff0c;MAC&#xff0c;剩余天数&#xff0c;套餐名称…

网络原理——http/https ---http(2)

http(接上一篇文章) 认识请求报头"header" header里面的键值对,都是标准规定的内容,很多,我们主要是认识一些关键的 host 表示对应的服务器主机的IP / 域名 实际上,这两个通常来说是一样的 但是有些时候不一样 当我们通过代码构造http请求,url里面写的以Ip地址的…

企业使用人工智能创建营销内容的8种实践

企业使用人工智能创建营销内容的8种实践 原文作者&#xff1a;朱丽叶约翰 编辑&#xff1a;数字化营销工兵 内容营销人员是第一批从“只玩人工智能”转变为“在日常工作中使用人工智能”的人。为了了解人工智能内容创作的哪些部分影响最大&#xff0c;我询问了其他营销人员如…

论文阅读笔记(十一)——BioInformatics Agent (BIA)

论文阅读笔记(十一)——BioInformatics Agent (BIA): Unleashing the Power of Large Language Models to Reshape Bioinformatics Workflow 目录 论文阅读笔记(十一)——BioInformatics Agent (BIA): Unleashing the Power of Large Language Models to Reshape Bioinformatic…

2023年全国职业院校技能大赛(高职组)“云计算应用”赛项赛卷7(私有云)

#需要资源&#xff08;软件包及镜像&#xff09;或有问题的&#xff0c;可私聊博主&#xff01;&#xff01;&#xff01; #需要资源&#xff08;软件包及镜像&#xff09;或有问题的&#xff0c;可私聊博主&#xff01;&#xff01;&#xff01; #需要资源&#xff08;软件包…

IP协议1.0

基本概念&#xff1a; • 主机: 配有IP地址, 但是不进⾏路由控制的设备; • 路由器: 即配有IP地址, ⼜能进⾏路由控制; • 节点: 主机和路由器的统称; IP协议的报头 • 4位版本号(version): 指定IP协议的版本, 对于IPv4来说, 就是4. • 4位头部⻓度(header length): IP头部的⻓…

微博增强-tampermonkey脚本实现网页管理悄悄关注

不是很明白微博为什么不出个x的列表功能&#xff0c;毕竟现在信息洪流&#xff0c;有些东西只是要看要了解&#xff0c;但不希望天天在首页轰炸眼睛&#xff0c;扰乱心智。 这个tampermonkey脚本适配了pc web和手机pwa版本&#xff08;weibo.com/m.weibo.cn&#xff09;,解决了…

【LeetCode算法】第104题:二叉树的最大深度

目录 一、题目描述 二、初次解答 三、官方解法 四、总结 一、题目描述 二、初次解答 1. 思路&#xff1a;二叉树的先序遍历。首先判断根节点是否是空&#xff0c;其次判断根节点是否是叶子节点&#xff0c;再者递归获取左子树的深度、右子树的深度&#xff0c;最后返回左子…

设计模式(十二)行为型模式---模板方法模式(template)

文章目录 模板方法模式结构优缺点UML图具体实现UML图代码实现 模板方法模式 模板方法模式&#xff08;Template Method&#xff09;是一种基于继承实现的设计模式&#xff0c;主要思想是&#xff1a;将定义的算法抽象成一组步骤&#xff0c;在抽象类中定义算法的骨架&#xff…

HOW - BFF 服务实践系列(一)

目录 一、BFF 介绍1.1 BFF 的概念1.2 为什么需要 BFF1.3 举例说明 二、适用于Web前端的BFF应该提供哪些能力2.1 接口聚合&#xff08;重要&#xff09;2.2 简化和优化的API2.3 安全和身份验证&#xff08;重要&#xff09;2.4 缓存机制2.5 错误处理和重试机制2.6 数据格式转换2…

(ISPRS,2023)RS-CLIP: 基于对比视觉-语言监督的zero-shot遥感场景分类

文章目录 相关资料摘要引言方法CLIP回顾伪标签生成课程学习策略 实验数据集不同文本提示失败案例分析课程学习zero-shot分类 相关资料 论文&#xff1a;RS-CLIP: Zero shot remote sensing scene classification via contrastive vision-language supervision 摘要 零样本遥…

未来已来:Spring Boot引领数据库智能化革命

深入探讨了Spring Boot如何与现代数据库技术相结合&#xff0c;预测并塑造未来的数据访问趋势。本书不仅涵盖了Spring Data JPA的使用技巧&#xff0c;还介绍了云原生数据库的概念&#xff0c;微服务架构下的数据访问策略&#xff0c;以及AI在数据访问层的创新应用。旨在帮助开…

视频搬运的素材网站有哪些?打包好的视频素材在哪找?

短视频创作的朋友们&#xff0c;欢迎进入这个充满创意的世界&#xff01;如果你曾为找不到合适的素材而苦恼&#xff0c;那么今天就让我为你介绍几个能够快速丰富你视频内容的素材平台。无论是为了搬运视频还是寻找灵感&#xff0c;下面这些网站都将是你的强力助手。特别地&…

lammps金刚石三棱锥刀具建模

大家好&#xff0c;我是小马老师。 本文介绍lammps三棱锥刀具建模方法。 lammps切削模拟的刀具形状有很多&#xff0c;如球形、锐角、钝角、三棱锥等刀具。 球形、锐角、钝角等刀具建模已经在公众号发过&#xff0c;本文介绍三棱锥的建模。 形状如下图所示&#xff1a; 主要原…

探索 Vue Devtools 4.0 的新世界!

大家好&#xff0c;我是前端宝哥。Vue Devtools 4.0 版本带来了一系列激动人心的新特性和改进&#xff0c;让我们一起来探索这些更新亮点&#xff01; 宝哥省流版&#xff1a; &#x1f6e0; 直接编辑组件数据&#xff0c;实时预览变更效果。⚙️ 快速编辑功能&#xff0c;一键…

使用python实现超市购物系统(一个小例子)

可以增加其他功能&#xff0c;这里就展示一个小的例子~

git基本使用——回退,撤销add,commit,合并分支

学习笔记 笔记中表格中的—— 表示需要回退的地方&#xff0c;也就是使用命令之后会改变的地方 网页软件分享 这是一个非常好用web端笔记画图软件&#xff0c;解决了typora画图不方便的问题

【评价类模型】Topsis

综合赋权法&#xff1a;Topsis法&#xff1a; 主要适用情况&#xff1a;题目提供了足够的评价指标和数据&#xff0c;数据已知&#xff0c;评价指标的类型差异较大 基本思想&#xff1a;将所有方案与理想解和夫理想解进行比较&#xff0c;通过激素那方案与这两个解的举例去欸的…

mysql面试之分库分表总结

文章目录 1.为什么要分库分表2.分库分表有哪些中间件&#xff0c;不同的中间件都有什么优点和缺点&#xff1f;3.分库分表的方式(水平分库,垂直分库,水平分表,垂直分表)3.1 水平分库3.2 垂直分库3.3 水平分表3.4 垂直分表 4.分库分表带来的问题4.1 事务一致性问题4.2 跨节点关联…

pandas添加行

方法1(df.append()) import pandas as pd# 创建一个空的DataFrame df pd.DataFrame(columns[Column1, Column2])# 新增一行数据 data {Column1: Value1, Column2: Value2} df df.append(data, ignore_indexTrue) print(df)raw_data {"Column1":"adafafa&quo…