精华内容
下载资源
问答
  • 嵌入式实验报告

    2012-11-21 19:53:47
    嵌入式实验总结报告
  • 嵌入式系统导论 实验报告 学院 学号 姓名 上海工程技术大学 电子电气工程学院 精选文库 实验一 GPIO 按键和 LED 实验实验要求 1 掌握基于 STM32F103 微控制器的嵌入式系统 仿真器和开发用 PC 机之间的连接方法 ...
  • 嵌入式系统实验总结.ppt
  • 精选文库 目录 实验一 跑马灯实验 1 实验二 按键输入实验 3 实验三 串口实验 5 实验四 外部中断实验 8 实验五 独立看门狗实验 11 实验七 定时器中断实验 13 实验十三 ADC 实验 15 实验十五 DMA实验 17 实验十六 I2C ...
  • 嵌入式实验报告总结

    千次阅读 2018-11-21 09:56:38
    实验一:LED发光二极管实验 一、实验环境 硬件:通用节点一个、USB仿真器、PC机; 软件:IAR Embedded Workbench for MCS-51; 二、实验内容 熟悉Zigbee硬件模块相关接口; 使用IAR 开发环境设计程序,...

    实验一:LED发光二极管实验

    一、实验环境

    1. 硬件:通用节点一个、USB仿真器、PC机;
    2. 软件:IAR Embedded Workbench for MCS-51;

    二、实验内容

    1. 熟悉Zigbee硬件模块相关接口;
    2. 使用IAR 开发环境设计程序,利用CC2530 的IO口进行LED发光二极管的亮灭操作;

    三、实验原理

    1. 硬件接口原理
    2. 软件设计

    程序流程图

    四、实验步骤

    1. 使用USB 仿真器连接PC 机和通用节点模块,模块电源开关处于中间“OFF”档,使用仿真器给模块供电。
    2. 启动IAR 开发环境,打开“…\基础传感器实验\1-5基础例程\1-LED”目录下的实验工程。
    3. 在IAR 开发环境中编译程序、点击下载、调试程序。按“F5”使程序运行。
    4. 观察现象,可以看到发光二极管轮流亮起。
    5. 使用调试界面上的停止按钮使程序停止,观察现象是否停止。
    6. 使用调试界面上的go按钮(等同“F5”),观察现象。

    实验二:串口收发数据实验

    一、实验环境

    1. 硬件:通用节点或任意传感器节点一个、USB仿真器、USB电缆、PC机;
    2. 软件:IAR Embedded Workbench for MCS-51、串口调试工具;

    二、实验内容

    1. 熟悉Zigbee硬件模块相关接口;
    2. 使用IAR 开发环境设计程序,利用CC2530 的串口0 进行数据收发通讯;

    三、实验原理

    1. 硬件接口原理
    2. 软件设计
      程序流程图

    四、实验步骤

    1. 使用USB 仿真器连接PC 机和ZIGBEE模块。将系统配套USB线一端连接PC 机,一端连接ZIGBEE模块的MINI-USB接口上。
    2. 连接USB电缆时,需要安装USB转串口的驱动程序,在“…\基础传感器实验\1-5基础例程\2-串口”目录下运行程序“CH341SER.EXE”安装驱动,重新拔插USB电缆,待驱动自动加载好,在“我的电脑右键——属性——设备管理器”中可以发现如下虚拟串口条目“USB-SERIAL CH340(COMXX)”。记住这里的串口号码“COMXX”。
    3. 启动IAR 开发环境,打开“…\基础传感器实验\1-5基础例程\2-串口”目录下的实验工程。
    4. 在IAR 开发环境中编译程序、点击下载、调试程序。按“F5”使程序运行。
    5. 打开“…\基础传感器实验\1-5基础例程\2-串口”目录下的串口调试程序“串口调试程序(支持中文).EXE”。按照下图设置这几项:串口号选择刚刚在设备管理器中记下的串口号;波特率选择“115200”;数据位8位;停止位1位;校验位none;流控制none等其他均为默认。点击右下角的发送数据按钮,可以看到接受文本框中显示接受到同样的数据。
    6. 更换发送文本框“字符串输入框”中的内容,点击发送按钮。可以看到相同的字符串又被返回。

    实验三:按键控制实验

    一、实验环境

    1. 硬件:传感器节点一个、USB仿真器、PC机;
    2. 软件:IAR Embedded Workbench for MCS-51;

    二、实验内容

    1. 熟悉Zigbee硬件模块相关接口;
    2. 使用IAR 开发环境设计程序,利用CC2530 的GPIO读取按键值并相应对进行LED发光二极管的亮灭操作;

    三、实验原理

    1. 硬件接口原理
      按键部分电路原理图
      2.软件设计
      程序设计流程图

    四、实验步骤

    1. 使用USB 仿真器连接PC 机和任意一个传感器节点模块,模块电源开关处于“ON”档,使用电池给模块供电(如电池电量低插上USB电缆,可一边充电一边使用)。
    2. 启动IAR 开发环境,打开“…\基础传感器实验\1-5基础例程\3-按键控制”目录下的实验工程。
    3. 在IAR 开发环境中编译程序、点击下载、调试程序,按“F5”使程序运行
    4. 观察现象,可以看到2个发光二极管都没有亮起。
    5. 按下模块中间的“KEY”按键,观察2个发光二极管的状态。
    6. 重复按键操作,尝试长按或短按,观察发光二极管状态。修改程序中的延时数值(下图中红点行)后再重复上面操作,体会不同延时下的效果。
    展开全文
  • 嵌入式实验学习心得 及期末总结 本学期的嵌入式实验课是在老师的指导下进行的主要进行了三个阶段的实验课程 一Linux系统的基础指令的认识和操作 二嵌入式平台的搭建以及外部驱动的挂载 三vi编辑器的运用及gcc操作...
  • 嵌入式实验5 计数器

    2013-03-04 19:54:01
    嵌入式实验5 计数器
  • 嵌入式实验

    2019-12-11 13:49:16
    实验一:LED发光二极管实验 1.实验内容 1.熟悉Zigbee硬件模块相关接口; 2.使用IAR 开发环境设计程序,利用CC2530 的IO口进行LED发光二极管的亮灭操作; 2 .实验环境 1硬件:通用节点一个、USB仿真器、PC机;...

    实验一:LED发光二极管实验
    1.实验内容

    1.熟悉Zigbee硬件模块相关接口;
    2.使用IAR 开发环境设计程序,利用CC2530 的IO口进行LED发光二极管的亮灭操作;
    

    2 .实验环境

    1硬件:通用节点一个、USB仿真器、PC机;
    2软件:IAR Embedded Workbench for MCS-51;
    

    3) 实验原理
    CC2530的IO口相关寄存器。
    在CC2530中,我们总共有3个可用的GPIO接口:P0、P1和P2。其中P0和P1的全部8位都有对应的引脚,而P2只有0-4几个引脚可用。这里我们主要对P0和P1共16个引脚进行操作,每个引脚都连接到一个发光二极管的驱动端,这样通过控制P0和P1的每一位,我们可以控制所有的16个发光二极管的亮灭。
    P0和P1寄存器
    在这里插入图片描述
    POSEL和P1SEL寄存器
    在这里插入图片描述
    在这里插入图片描述
    我们查看芯片SN74LVC245的器件手册,可以看到其工作原理框图如上所示。由图中描述可知,OEn信号控制所有引脚的输出使能,DIR信号控制信号驱动方向。我们的原理图中OEn接地,所以相应引脚是输出使能的。DIR(图中的T/Rn)是接高电平的,所以根据其原理框图,信号方向是由A到B。也就是A端的信号(P0.0-P0.7)经过SN74LVC245芯片后控制着B端输出信号(用来驱动D1~D8)。

    R1和R2是330欧姆的排阻,每个LED灯串接一个,用来限制通过LED灯的电流,使LED灯工作在正常大小电流下,防止烧毁。

    4.实验步骤

    l 使用USB 仿真器连接PC 机和通用节点模块,模块电源开关处于中间“OFF”档,使用仿真器给模块供电。

    l 启动IAR 开发环境,打开“…\基础传感器实验\1-5基础例程\1-LED”目录下的实验工程。

    l 在IAR 开发环境中编译程序、点击 嵌入式实验总结(第一次到第三次) 下载、调试程序。按“F5”使程序运行。

    l 观察现象,可以看到发光二极管轮流亮起。

    l 使用调试界面上的停止按钮嵌入式实验总结(第一次到第三次) 使程序停止,观察现象是否停止。

    l 使用调试界面上的go按钮 嵌入式实验总结(第一次到第三次)(等同“F5”),观察现象。

    5.试验现象

    开始实验后初始化IO寄存器,所有的灯亮一次长灭一次,接下来一次点亮P0 各位所控灯,在一次点亮P1的各位所控灯。

    小组内实验现象总结:安装好驱动后,倒入源代码,发现等全亮并缓速的闪,按F5复位后再按F7,小灯以极快的素的开始闪,再次复位后灯不再闪动但是所有的灯都是亮的。

    实验二:串口收发数据实验

    实验知识储备(组长在课上做的私人笔记,只作为参考使用):CC2530 与笔记本用 串口转USB(包容性通电协议) RS232 硬件通讯 URAT通用异步接受和发送

    CRT(T TX RX )电平转换芯片 电平抖动3~15V

    CH430 芯片安装 串口通讯协议 滴答定时器 一秒发送11520位

    2500000HZ-0(标准定时器)

    1.试验环境

            1.硬件:通用节点或任意传感器节点一个、USB仿真器、USB电缆、PC机;
    
             2 .软件:IAR Embedded Workbench for MCS-51、串口调试工具;
    

    2.实验内容

    1熟悉Zigbee硬件模块相关接口;
    
    2使用IAR 开发环境设计程序,利用CC2530 的串口0 进行数据收发通讯;
    

    3.实验原理、

    在CC2530中,我们总共有2个可用的串行接口,这些串行接口可被配置为标准串口或者SPI接口。这个例程中我们只使用USART0,并且工作在UART标准串口模式下。由于每种设置都有2套可用的IO映射,这里根据我们的硬件设置,我们应该使用其默认设置,UART0的TX和RX对应于P0_3和P0_2。

    让我们先来了解CC2530的IO口相关寄存器:

    PO寄存器
    在这里插入图片描述POSEL寄存器
    在这里插入图片描述
    PODIR寄存器
    在这里插入图片描述

    部分外设复用IO对应图
    在这里插入图片描述

    本例程中,程序通过配置以上寄存器将系统主时钟设置为片外 32M晶振。

    然后是串行接口外设相关寄存器,通过设置这些寄存器,我们将串行接口设定为预想的模式。

    以上列举了和CC2530串口操作定相关的寄存器,其中包括CLKCONCMD控制寄存器,用来控制系统时钟源,SLEEP 寄存器用来控制各种时钟源的开关和状态。PERCFG 寄存器为外设功能控制寄存器,用来控制外设功能模式。U0CSR、U0GCR、U0BUF、U0BAUD 等位串口相关寄存器。
    在这里插入图片描述

    上图是节点的串口相关电路原理图。在这个图中我们可以看到CH430芯完成了USB转串口的工作,

    通过USB电缆连接节点和计算机后,CH430芯片会在计算机中虚拟一个串口,这个串口信号对于图中的CH430—TDX和CH430_RDX,通过J2上的跳线帽与CC2530 的P0.2 和P0.3 引脚相连。

    通过之前的IO映射复用图我们可以发现,P0.2和P0.3对应的是USART0在UART模式下的RXT和TXD引脚。

    4,。对于程序的一点小解读

    程序中主要有这几个函数:

    DelayXms(unsigned int Count):延时函数。

    InitIO():完成IO初始化功作。首先将系统切换到32Hz主晶振下工作并配置芯片内部频率,因为串口工作波特率较高,芯片对串口信息的处理要求其工作频率也较高,所以需要在32M频率下工作。然后配置相关IO寄存器,包括2个LED灯的控制IO口为输出模式,2个串口收发信号引脚为特殊功能应用模式。

    InitUart():完成串口的初始化工作。其中对串口寄存器进行设置,最重要的是串口的波特率设置。我们找到CC2530用户手册的P160页,其中有对波特率相关计算的详细描述。这里归纳其计算公式为:
    在这里插入图片描述

    其中BAUD_M和BAUD_E为相关寄存器中的设置位。下表归纳了在系统时钟为32MHz频率下的常用波特率对于设置值。

    主函数和中断函数的流程为:

    开始->初始化IO寄存器-> 初始化串口 ->点亮灯,发送初始信息->等待串口接收中断
    进入中断函数服务-> 去得接收字符-> 发送该字符 ->如果发送完成清标志位,控制灯->若未完成发送, 则再次进行发送字符操作。
    

    此为main函数和中断函数的流程图

    4.实验步骤

    使用USB 仿真器连接PC 机和ZIGBEE模块。将系统配套USB线一端连接PC 机,一端连接ZIGBEE模块的MINI-USB接口上。
    

    **注意:**如果使用通用节点运行本例程,请检查板子上的“TXD”和“RXD”位置跳线帽是否已经插上(右下图圆圈处),下方的电源开关打到“OFF”档,节点使用仿真器连接供电。

    如果使用传感器节点运行本例程,请检查板子上的“TXD”和“RXD”位置跳线帽是否已经插上(左下图圆圈处),下方的电源开关打到“OFF”档,节点使用仿真器连接供电。
    

    在这里插入图片描述在这里插入图片描述
    接USB电缆时,需要安装USB转串口的驱动程序,在“…\基础传感器实验\1-5基础例程\2-串口”目录下运行程序“CH341SER.EXE”安装驱动,重新拔插USB电缆,待驱动自动加载好,在“我的电脑右键——属性——设备管理器”中可以发现如下虚拟串口条目“USB-SERIAL CH340(COMXX)”。记住这里的串口号码“COMXX”。
    启动IAR 开发环境,打开“…\基础传感器实验\1-5基础例程\2-串口”目录下的实验工程。
    在IAR 开发环境中编译程序、点击 嵌入式实验总结(第一次到第三次) 下载、调试程序。按“F5”使程序运行。
    打开“…\基础传感器实验\1-5基础例程\2-串口”目录下的串口调试程序“串口调试程序(支持中文).EXE”。按照下图设置这几项:串口号选择刚刚在设备管理器中记下的串口号;波特率选择“115200”;数据位8位;停止位1位;校验位none;流控制none等其他均为默认。点击右下角的发送数据按钮,可以看到接受文本框中显示接受到同样的数据。
    更换发送文本框“字符串输入框”中的内容,点击发送按钮。可以看到相同的字符串又被返回。

    本小组的实验结果截图:按一次reset按键复一次,上面出现一次实验结果
    在这里插入图片描述

    实验三 按键控制实验

    1.试验环境、

    1)硬件:传感器节点一个、USB仿真器、PC机;
    
    2)软件:IAR Embedded Workbench for MCS-51;
    

    2.实验内容

    1)熟悉Zigbee硬件模块相关接口;
    2)使用IAR 开发环境设计程序,利用CC2530 的GPIO读取按键值并相应对进行LED发光二极管的亮灭操作;
    

    3.实验原理

    1)  硬件接口原理
    

    如图所示,按键部分的电路图比较简单。UserINT信号连接的是芯片的P2.0引脚,在按键没有被按下时(处于断开状态),经过电阻R9的上拉作用,UserINT信号是处于高电平的,而当按键按下时,UserINT信号直接和地相连,这样处于低电平。在芯片内通过检测P2.0口的输出状态就可以知道按键的状态。电容C4在按键松开的时候起到对输出信号的缓冲作用,这样可以过滤掉部分干扰信号,使得输出信号较为平滑。
    在这里插入图片描述
    图5-3-1 按键部分电路

    程序通过读取P2.0的信息来获得按键的状态,同时对P1上的2个发光二极管进行操作。程序中的长延时是为了使得一定时间内的按下只被识别为一次按下,短延时是为了滤掉可能的干扰信号。

    程序的流程为:

    开始->初始化IO寄存器->按判断键 若为是则改变灯的状态->长延时->再次进入到判断按键  若为否-为短延时->再次进入到判断按键
    

    4.实验步骤
    1)使用USB 仿真器连接PC 机和任意一个传感器节点模块,模块电源开关处于“ON”档,使用电池给模块供电(如电池电量低插上USB电缆,可一边充电一边使用)。
    2)启动IAR 开发环境,打开“…\基础传感器实验\1-5基础例程\3-按键控制”目录下的实验工程。
    3) 在IAR 开发环境中编译程序、点击 嵌入式实验总结(第一次到第三次) 下载、调试程序。按“F5”使程序运行。
    现象,可以看到2个发光二极管都没有亮起。
    4)按下模块中间的“KEY”按键,观察2个发光二极管的状态。
    5)重复按键操作,尝试长按或短按,观察发光二极管状态。修改程序中的延时数值(下图中红点行)后再重复上面操作,体会不同延时下的效果。

    延时语句位置
    在这里插入图片描述
    5.实验现象

    按下触发开关后可以控制最后两个的亮与灭,先按一次亮一个灯,再按一次亮两个灯。
    

    注意不是按复位键。

    实验结果截图:

    在这里插入图片描述在这里插入图片描述
    关注我的微信公众号:hello521day ,大量网络,渗透、编程资料以及ppt等模板等你来取!

    在这里插入图片描述

    展开全文
  • 嵌入式实验报告心得体会
  • 嵌入式实验报告(linux实验)

    千次阅读 2018-06-27 11:22:33
    为了实现我们嵌入式实验箱的linux 驱动程序,我们需要将这两个接口好好的“对接”一下。参考ours_led.c 文件,我们做如下分析:首先,我们定义设备的i 节点名称, 这样我们就能在我们的文件系统中找到我...
    1 LED 灯驱动程序
    1.1 “文件”的实现
    设备驱动作为操作系统的一部分,是操作系统对设备进行操作的接口。操作系统规定了设备驱动需要实现的接口,而我们在裸机实验中也用到了控制设备所用到的接口。为了实现我们嵌入式实验箱的linux 驱动程序,我们需要将这
    两个接口好好的“对接”一下。
    参考ours_led.c 文件,我们做如下分析:

    首先,我们定义设备的i 节点名称, 这样我们就能在我们的文件系统中找到我们的设备。


    其次,在驱动程序加载一个设备之前,首先要做的就是获取设备编号。设备号包括主设备号和次设备号两部分, 前者表示一个特定的驱动程序, 后者表示使用该驱动程序的各设备。类似C 语言裸机实验,我们还需要定义我们的端口号。




    之后我们就要来实现操作系统规定的对“文件”操作的方法了。首先我们先把表填上:


    这里定义了三个属性:所有者、打开方式、释放方式、控制方式。这三种方式就是我们写测试文件时需要用到的控制设备的函数。我们先看一下led_open 函数





    led_open 函数调用了init 函数和led_all_off 函数。init 函数与我们的C 语言裸机实验对LED 灯初始化的步骤相同。led_all_off 也是利用开发包为我们提供的接口将所有的灯关闭。

    再看一下led_release 函数:



    这和我们C 语言裸机实验的步骤完全一样了。再看一下led_unlocked_ioctl 函数:


    第一个参数是i 节点,第二个参数是命令,对LED 灯来说有两种命令:开和关,第三个参数指定对哪一个灯操作。当然,cmd 和arg 的值反过来写也没什么问题,不过是不太符合逻辑。至此,我们的文件系统中就有了这么一个“文件”。


    1.2 驱动引导

    我们的文件系统中终于有了这么一个“文件”,但这个文件和一般的文件不同,因为它是驱动程序,它需要在我们“打开文件”之前就要和设备建立联系,做一系列的初始化工作,当然这主要是操作系统层面的。
    linux 同样提供了这样一个接口:


    参数为两个函数指针。这两个函数将函数指针存放在一个段中,当linux 系统启动时调用do_basic_steup 函数,遍历这个段执行每一个初始化函数。(当然这是将驱动加载进内核的方法)

    我们来看一下led_init 函数:






    这是这个驱动文件里面最长的一个函数了。之前我们定义设备号为0, 意味着要动态申请设备号。之后将设备号添加到设备表中,并创建设备文件目录。而我们在关机时,会执行led_exit 函数:


    这里会在文件系统中删除这个i 节点。原因很简单,因为操作系统下次开机时不知道还有没有这个设备,就像U 盘一样,这次开机有了不代表下次开机U 盘还会插在上面。为了防止访问出错,所以销毁i 节点。


    1.3 编译驱动

    随后,我们创建Makefile 文件,将需要编译的文件添加进去,再在上层Makefile 文件中添加依赖关系。
    首先我们将编译后的文件放进去:

    再在上层目录ours/文件夹下的Makefile 中添加CONFIG_OURS_LED 的依赖:


    在编译时,drivers 文件夹下的Makefile 会检查ours 文件夹下所有的依赖,保证drivers 生成的编译结果的时间戳比ours 文件夹下所有的编译结果都更新。这样我们就将驱动加载了进去。

    为了更方便的管理加载哪些模块,我们还需要实现Kconfig,用来在menuconfig中方便选择。

    在ours_led 文件夹下,创建Kconfig 文件:



    在上层Kconfig 文件中添加上我们的源文件:

    这样,我们在顶层的终端下执行make menuconfig,就可以方便的选择哪些模块加载进内核了。


    2 测试


    在写测试文件时,我们需要打开设备所在的“文件”,利用操作系统提供的接口进行操作。在这里,操作系统的意义就体现了出来:对每一种设备的操作,都是那几种函数,方便了编程人员的开发。以下是我写的跑马灯测试程序:



    核心是在while(1) 循环中将灯开、灭。
    至此,作业三完成。
    展开全文
  • 嵌入式实验报告 四个实验 实验过程 命令用法 实验心得
  • 嵌入式面试总结

    千次阅读 多人点赞 2018-05-20 21:46:32
    最近面了很多公司,总结一下最近遇到的题目,很多高频出现,后来看了一下,这些都是很经典的题目,写一个笔记,日后复习,不定期更新

    最近面了很多公司,总结一下最近遇到的题目,很多高频出现,后来看了一下,这些都是很经典的题目,写一个笔记,日后复习,不定期更新

    宏定义问题

    1、写一个标准宏MIN,输入两个参数返回较小的一个

    个人理解:

          这个题考的事使用宏定义函数的基础,外加三目运算符的考察

    我的解答:

        #define MIN(a,b)((a)>=(b)?(b):(a))

    2、使用宏定义 定义一个常数,一年有多少秒(忽略闰年)

    个人理解:

        这个题考察宏定义基本用法,还有普通平台下数据类型长度的问题在32位的设备上int是 4个byte 8位和16位是2个byte,为了兼容各平台最好使用unsigned long,以便在使用的时候不会出问题

     

    我的解答:
        #define SECOND_YEAR   (60*60*24*360ul) 

    (ps. 有一种写法是

    #define SECOND_YEAR (60*60*24*360)ul

    ,这种我没有验证,但是再16位或者8位的系统上这个数值已经大于0xffff,可能出现超出的情况,保守起见用上面的方法 )

    3、宏定义#和##的区别

    个人理解:

        我觉得这个可能会很多人不知道后面那个,至少我是这样的,根本没有使用过##,不过在apm的源码中看到过很多次,之前没注意,现在重新温习一下

    我的解答:

     

    #define a_printf(x) printf( "token " #x" = %d\n ", token##x ) 
    所以a_printf(1);就是相当于 printf("token 1 = %d\n",token1);
    

    还有一个#的例子很经典

     

    #define MONCK(ARGTERM) /
        printf("The term " #ARGTERM " is a string/n")
    MONCK(A to B);
    输出:
    The term A to B is a string
    

    4、#error、#warning有什么用?

    个人理解:

        这个可能非常简单,但是很少人用,在apm源码中非常常用,因为apm要跨五六个平台,编译的时候要做出提示或者是报错

    我的解答:

    #define NIU_BI
    #ifdef NIU_BI
    #error "there is a niubi problem"
    #else
    #warning "ni niubi,mei mao bing"
    #endif

    预编译的时候会进行一个处理,如果定义了NIU_BI,那么编译器将会报错,输出后面的字符串,如果没有的话,编译器将会输出一个警告,但并不影响编译

    5、如何使用可变参数的宏

     

    个人理解:

    熟悉Java的同学对这个再熟悉不过了,有点类似。确实可变参数宏在嵌入式编程中是一大利器

    网络解答:

    可变参数可以用三个点(...)来表示,,可以用__VA_ARGS__来展开,如:

    #define err(...) fprintf(stderr,__VA_ARGS__)
    err("%s %d/n","The error code: ",48);

    一般,我们可以这样打印错误信息:

     

    fprintf(stderr,"%s %d/n","The error code ",48);

    但想要另外输出其它信息,我们可以这样定义一个可变参数的宏,例如:

    #define errout(a,b,...) /
        fprintf(stderr,"File %s     Line %d/n",a,b); /
        fprintf(stderr,__VA_ARGS__)

    那么我们就可以这样使用这个宏:

    errout(__FILE__,__LINE__,"Unexpected termination/n");

     

    因为__VA_ARGS__在fprintf中的内部实现使用了逗号来作分割符,所以必须要求至少有一个参数,如果想使__VA_ARGS__为空,可以这样使用:

    fprintf(stderr, ##__VA_ARGS__);

    6、为什么要使用宏定义,有哪些注意事项?

    因为 宏的效率高,不需要压栈 和出栈,而且可以节省代码
    使用宏不能使用递归,宏只是进行简单替换,
    定义的时候最好加上括号,确定优先级,反之在预编译的时候出现替换
    造成优先级变化的问题。C语言里没有模板,而c语言的宏恰恰相当于C++的模板,
    虽然宏很好用,但是还是不要过于使用宏,最好只是用于一些函数比较难实现的场景。
    
    谷歌宏定义写法标准   需要翻墙
    谷歌宏定义写法标准   需要翻墙
    

    15 Typedef 在C语言中频繁用以声明一个已经存在的数据类型的同义字。也可以用预处理器做类似的事。例如,思考一下下面的例子:

     

    #define dPS struct s *
    typedef struct s * tPS;

          以上两种情况的意图都是要定义dPS 和 tPS 作为一个指向结构s指针。哪种方法更好呢?(如果有的话)为什么?

    这是一个非常微妙的问题,任何人答对这个问题(正当的原因)是应当被恭喜的。答案是:typedef更好。思考下面的例子:

     

    dPS p1,p2;
    tPS p3,p4;

    第一个扩展为

     

    struct s * p1, p2;

     

    上面的代码定义p1为一个指向结构的指针,p2为一个实际的结构,这也许不是你想要的。第二个例子正确地定义了p3 和p4 两个指针。

    指针问题

    1、用变量a给出下面的定义(我觉得这个题是必考题,虽然我俩次都特么答错了)

    a) 一个整型数(An integer)
    b)一个指向整型数的指针( A pointer to an integer)
    c)一个指向指针的的指针,它指向的指针是指向一个整型数( A pointer to a pointer to an intege)r
    d)一个有10个整型数的数组( An array of 10 integers)
    e) 一个有10个指针的数组,该指针是指向一个整型数的。(An array of 10 pointers to integers)
    f) 一个指向有10个整型数数组的指针( A pointer to an array of 10 integers)
    g) 一个指向函数的指针,该函数有一个整型参数并返回一个整型数(A pointer to a function that takes an integer as an argument and returns an integer)
    h) 一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数( An array of ten pointers to functions that take an integer argument and return an integer )

    a) int a; // An integer
    b) int *a; // A pointer to an integer
    c) int **a; // A pointer to a pointer to an integer
    d) int a[10]; // An array of 10 integers
    e) int *a[10]; // An array of 10 pointers to integers
    f) int (*a)[10]; // A pointer to an array of 10 integers
    g) int (*a)(int a); // A pointer to a function a that takes an integer argument and returns an integer
    h) int (*a[10])(int a); // An array of 10 pointers to functions that take an integer argument and return an integer

    2、char * const p、 char const * p 、const char *p 上述三个有什么区别?

    个人理解:

        这个我觉得是个必考题,但是却基本没有问的

    我的解答:

        第一个const加在p头上,常量指针,所以内容不变,指针的地址可以变,第二个const指向指针,所以指针地址不能变,但内容可以变,第三个指向整体,所以指针和内容都不变

     

    char * const p; //常量指针,p的值不可以修改
    char const * p;//指向常量的指针,指向的常量值不可以改
    const char *p; //和char const *p一样
    const char *p; //*p是const,p可变:const 后面紧跟的是char,所以*p是一个char字符,不可变  
      
    const (char *) p;//p是const,*p可变:const 后面紧跟的是(char *)这个整体,所以p是char*类型,不可变。  
      
    char* const p; //p是const,*p可变:const 后面紧跟的是p,所以p不可变  
      
    const char* const p; //p和*p都是const:第一个const后面紧跟的是char,所以char类型的字符*p不可变;第二个const后面紧跟的是p,所以p不可变。  
      
    char const * p;// *p是const,p可变:const后面紧跟的是*,但是单独的*不能表明修饰的内容,所以将*p看成一个整体,所以const修饰的是*p,*p不可变。  
      
    (char*) const p;//p是const,*p可变:const紧跟的是p,所以p不可变。  
      
    char* const p;// p是const,*p可变:const紧跟的是p,所以p不可变。  
      
    char const* const p;// p和*p都是const:第一个const紧跟的是*,不能表明修饰的内容,将后面整体的(* const p)
    看成一个整体,那就说明*p不可变,第二个const后面紧跟的是p,所以p不可变。  

    3、下面程序的输出结果是?

    char str1[] = "abc"; 
    char str2[] = "abc"; 
    const char str3[] = "abc";
    const char str4[] = "abc"; 
    const char *str5 = "abc";
    const char *str6 = "abc"; 
    char *str7 = "abc"; 
    char *str8 = "abc"; 
    cout << ( str1 == str2 ) << endl; 
    cout << ( str3 == str4 ) << endl; 
    cout << ( str5 == str6 ) << endl; 
    cout << ( str7 == str8 ) << endl;

    结果是:0 0 1 1。 str1,str2,str3,str4是数组变量,它们有各自的内存空间;而str5,str6,str7,str8是指针,它们指向相同的常量区域。

    机器平台差异

    1、一个32位的机器,该机器的指针是多少位?

    指针是多少位只要看地址总线的位数就行了。80386以后的机子都是32的数据总线。所以指针的位数就是4个字节了。

     

    栈区、堆区、全局区、文字常量区、程序代码区

     

    1、下面程序有什么错?

    char* s="AAA"; 
    printf("%s",s); 
    s[0]='B';
    printf("%s",s);
    答案:"AAA"是字符串常量。s是指针,指向这个字符串常量,所以声明s的时候就有问题,这种声明编译器并不能发现错误。 所以定义的时候要加const,即const char*s="AAA"; 然后又因为是常量,所以对是s[0]的赋值操作是不合法的。

    2、栈、堆、队列、段的区别是什么

    五大区这篇文章有详解,单片机这篇。

    数组

    1、下面程序输出结果是?

    main() 
    { 
        int a[5]={1,2,3,4,5}; 
        int *ptr=(int*)(&a+1); 
        printf("%d,%d",*(a+1),*(ptr-1)); 
    } 
    答案:2。5 *(a+1)就是a[1],*(ptr-1)就是a[4],执行结果是2,5 &a+1不是首地址+1,系统会认为加一个a数组的偏移,是偏移了一个数组的大小(本例是5个int) int *ptr=(int*)(&a+1); 则ptr实际是&(a[5]),也就是a+5 原因如下: &a是数组指针,其类型为 int (*)[5]; 而指针加1要根据指针类型加上一定的值,不同类型的指针+1之后增加的大小不同 a是长度为5的int数组指针,所以要加 5*sizeof(int) 所以ptr实际是a[5] 但是prt与(&a+1)类型是不一样的(这点很重要) 所以prt-1只会减去sizeof(int*) a,&a的地址是一样的,但意思不一样,a是数组首地址,也就是a[0]的地址,&a是对象(数组)首地址,a+1是数组下一元素的地址,即a[1],&a+1是下一个对象的地址,即a[5].

    2、多维数组取值问题

    内存问题

     

     

    1、请问以下代码有什么问题:

    int main()
    {
        char a;
        char *str=&a;
        strcpy(str,"hello");
        printf(str);
        return 0;
    } 

    答案:没有为str分配内存空间,将会发生异常问题出在将一个字符串复制进一个字符变量指针所指地址。虽然可以正确输出结果,但因为越界进行内在读写而导致程序崩溃。

    2、嵌入式系统经常具有要求程序员去访问某特定的内存位置的特点。在某工程中,要求设置一绝对地址为0x67a9的整型变量的值为0xaa66。编译器是一个纯粹的ANSI编译器。写代码去完成这一任务。

    个人理解:

        这一问题测试你是否知道为了访问一绝对地址把一个整型数强制转换(typecast)为一指针是合法的。这一问题的实现方式随着个人风格不同而不同。典型的类似代码如下:

    int *ptr;
    ptr = (int *)0x67a9;
    *ptr = 0xaa55;

      A more obscure approach is:
    一个较晦涩的方法是:

    *(int * const)(0x67a9) = 0xaa55;

    即使你的品味更接近第二种方案,但我建议你在面试时使用第一种方案,实际上我的品位就是第二种,这就是我面试老是失败的原因,哈哈哈哈,眼高手低。

     

    3.请问以下代码有什么问题:

    #include 
    #include 
    void getmemory(char *p)
    {
    p=(char *)malloc(100);
    strcpy(p,"helloworld");
    }
    int main( )
    {
    char *str=NULL;
    getmemory(str);
    printf("%s/n",str);
    free(str);
    return 0;
    答案:程序崩溃,getmemory中的malloc 不能返回动态内存, free()对str操作很危险

    4. 尽管不像非嵌入式计算机那么常见,嵌入式系统还是有从堆(heap)中动态分配内存的过程的。那么嵌入式系统中,动态分配内存可能发生的问题是什么?

          内存碎片,碎片收集的问题,变量的持行时间等等。

    延伸:下面的代码片段的输出是什么,为什么?

    char *ptr;
    if ((ptr = (char *)malloc(0)) == NULL)
        puts("Got a null pointer");
    else
        puts("Got a valid pointer");

    该代码的输出是"Got a valid pointer"。不知道为什么

    嵌入式系统的几种无限循环方式

     

    1、while(1){}

    这种每个人都会,但是在实际生产中机会没有人用,至少我没看见过

    2、for(;;)

    这种相当常用了,嵌入式系统基本上都是这种

    3、loop:           goto loop;

    这种我最喜欢了,哈哈,刚学C语言的时候我就用这个方法不让黑框关掉,别人都用getchar(),到最后上visual studio的使用优势体现出来了。

    关键字问题

    1、关键字static的作用是什么?

    网上有个答案是:定义静态变量,我估计这个你答完基本算完蛋,这是个人就能答出来

    比较合理的答案有:

    1) 在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。
    2) 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。
    3) 在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用。
    4)一个类里面的静态函数,可以不创建对象就可以直接调用
    前三条来自网络, 据说第三条能够体现本地化数据和代码范围的好处和重要性。

    2、关键字const有什么含意?

    答案:表示常量不可以修改的变量。
    const意味着"只读"。尽管这个答案不是完全的答案。

     延伸(同上面提到的const)

    const int a;
    int const a;
    const int *a;
    int * const a;
    int const * a const;
          前两个的作用是一样,a是一个常整型数。第三个意味着a是一个指向常整型数的指针(也就是,整型数是不可修改的,但指针可以)。第四个意思a是一个指向整型数的常指针(也就是说,指针指向的整型数是可以修改的,但指针是不可修改的)。最后一个意味着a是一个指向常整型数的常指针(也就是说,指针指向的整型数是不可修改的,同时指针也是不可修改的)。如果应试者能正确回答这些问题,那么他就给我留下了一个好印象。

    const的好处

    1) 关键字const的作用是为给读你代码的人传达非常有用的信息,声明一个参数为常量是为了告诉了用户这个参数的应用目的。
    2) 通过给优化器一些附加的信息,使用关键字const也许能产生更紧凑的代码。
    3) 合理地使用关键字const可以使编译器很自然地保护那些不希望被改变的参数,防止其被无意的代码修改。简而言之,这样可以减少bug的出现。

    3、关键字volatile有什么含意?并举出三个不同的例子?

    答案:提示编译器对象的值可能在编译器未监测到的情况下改变。

        一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子(我特么当时答成防止出现意向不到的值,面试官楞了):

    1) 并行设备的硬件寄存器(如:状态寄存器)
    2) 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)(这个真的是很常用)
    3) 多线程应用中被几个任务共享的变量

    延伸

    1) 一个参数既可以是const还可以是volatile吗?解释为什么。

    1) 是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。

    2) 一个指针可以是volatile 吗?解释为什么。

    2) 是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。

    3) 下面的函数有什么错误:

    int square(volatile int *ptr)
    {
            return *ptr * *ptr;
    }

    3) 这段代码有点变态。这段代码的目的是用来返指针*ptr指向值的平方,但是,由于*ptr指向一个volatile型参数,编译器将产生类似下面的代码:

    int square(volatile int *ptr)
    {
        int a,b;
        a = *ptr;
        b = *ptr;
        return a * b;
    }

    由于*ptr的值可能被意想不到地该变,因此a和b可能是不同的。结果,这段代码可能返不是你所期望的平方值!正确的代码如下:

    long square(volatile int *ptr)
    {
        int a;
        a = *ptr;
        return a * a;
    }

    C和C++的区别

    1.c和c++中的struct有什么不同?

    答案:c和c++中struct的主要区别是c中的struct不可以含有成员函数,而c++中的struct可以。c++中struct和class的主要区别在于默认的存取权限不同,struct默认为public,而class默认为private

    操作系统

     

    1.列举几种进程的同步机制,并比较其优缺点。

    答案: 原子操作 信号量机制 自旋锁 管程,会合,分布式系统

    2,mutex 和binary semaphore有什么区别

    这篇文章

     

    数据结构

    1,如何找到一个循环链表的头指针?

        这个题还真不明白

    2、如何把链表a->b->c变成c->b->a

    3、双向链表

     

    中断(Interrupts)

    1. 中断是嵌入式系统中重要的组成部分,这导致了很多编译开发商提供一种扩展—让标准C支持中断。具代表事实是,产生了一个新的关键字 __interrupt。下面的代码就使用了__interrupt关键字去定义了一个中断服务子程序(ISR),请评论一下这段代码

    __interrupt double compute_area (double radius)
    {
        double area = PI * radius * radius;
        printf("\nArea = %f", area);
        return area;
    }

    我答这个题,只发现了不能传参这个,我还是太菜了,实际上这个函数有太多的错误了,以至让人不知从何说起了:
    1) ISR 不能返回一个值。
    2) ISR 不能传递参数。
    3) 在许多的处理器/编译器中,浮点一般都是不可重入的。有些处理器/编译器需要让额处的寄存器入栈,有些处理器/编译器就是不允许在ISR中做浮点运算。此外,ISR应该是短而有效率的,在ISR中做浮点运算是不明智的。
    4) 与第三点一脉相承,printf()经常有重入和性能上的问题。

    第三和第四是加分项。

    延伸:可重入

    可重入函数主要用于多任务环境中,一个可重入的函数简单来说就是可以被中断的函数,也就是说,可以在这个函数执行的任何时刻中断它,转入OS调度下去执行另外一段代码,而返回控制时不会出现什么错误;而不可重入的函数由于使用了一些系统资源,比如全局变量区,中断向量表等,所以它如果被中断的话,可能会出现问题,这类函数是不能运行在多任务环境下的。

    C语言开发原则

    整数自动转换原则

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

    个人理解:

        整数自动转换原则,我个人之前是完全不知道的。

        这无符号整型问题的答案是输出是 ">6"。原因是当表达式中存在有符号类型和无符号类型时所有的操作数都自动转换为无符号类型。因此-20变成了一个非常大的正整数,所以该表达式计算出的结果大于6。这一点对于应当频繁用到无符号数据类型的嵌入式系统来说是丰常重要的。

    延伸

    分为显式转换和隐式转换,强转为显式转换。

        隐式转换规则:
           1、字符必须先转换为整数(C语言规定字符类型数据和整型数据之间可以通用) 。
           2、short型转换为int型(同属于整型) 。
           3、float型数据在运算时一律转换为双精度(double)型,以提高运算精度(同属于实型) 。
        其次,有下面的规则。

        当不同类型的数据进行操作时,应当首先将其转换成相同的数据类型,然后进行操作,转换规则是由低级向高级转换。转换规则如下图所示:

     

     

     

    展开全文
  • 基于Linux系统的嵌入式实验,实现了菜单以及电子相册,文件内含有工程文件和流程图。进入相册有欢迎界面,停留3s后自动跳转;设置3个imagebutton,点击可以分别进入3个不同的相册;浏览图片时,当前浏览图片可以停留...
  • 从0学嵌入式开发,嵌入式实验个人总结、踩雷、排坑 大四学生,学校安排了嵌入式实验课,因为网络授课,基本啥也没听懂,从0开始 在自己的电脑上安装keil uvision5环境,做实验,学校机房是uvision4,老师给的项目...
  • 嵌入式系统 课后实验总结

    千次阅读 2014-06-16 15:59:55
    汇编实验: STACK_TOP EQU 0x20002000 ; SP初始值,常数 NUM EQU 20 ; Vector Table Mapped to Address 0 at Reset AREA RESET, CODE, READONLY ;(段名为RESET) DCD STACK_TOP ; Top of Stack DCD START ; ...
  • 嵌入式实验-汇编点亮LED 灯 一、实验目的 通过本次实验,使学生能够操作 S5PV210实验平台,搭建并使用交叉编译环境,具备初步的嵌入式裸机平台应用开发能力。 二、实验原理 由原理图可知,点亮 210 的 4 个 LED 需...
  • 嵌入式系统总结

    千次阅读 2012-09-22 19:31:09
    1.从计算机应用的角度定义“嵌入式系统”:以应用为中心、以计算机技术为基础,软、硬件可裁剪,适应应用系统对功能、可靠性、成本、体积、功耗等严格要求的专用计算机系统。嵌入式系统是应用于特定环境下执行面对...
  • 嵌入式开发总结

    千次阅读 2015-04-01 09:44:10
    嵌入式开发知识总结 一、基础知识   目前流行的嵌入式操作系统有:Linux、uC/OS、WindowsCE、VxWorks、PalmOS和QNX。其中VxWorks实时性很强,最稳定、可靠,但价格昂贵,而其他的都有各自的优点...
  • 此次实验可以实验的目的是进一步熟练前面学过的知识,体验嵌入式开发的过程。而且有了键盘和LED矩阵的驱动、C语言贪吃蛇程序,任务的关键就是明确各个接口: 1、嵌入式开发板的LED矩阵接口。 2、嵌入式开发板的键盘...
  • ARM嵌入式开发总结

    千次阅读 2017-08-07 12:35:59
    嵌入式开发总结 一、基础知识 目前流行的嵌入式操作系统有:linux、uC/OS、WindowsCE、VxWorks、PalmOS和QNX。其中VxWorks实时性很强,最稳定、可靠,但价格昂贵,而其他的都有各自的优点。 ...
  • 嵌入式实验(一)0 实验要求1 RTOS2 实验3 总结 0 实验要求 学习FreeRTOS原理,在STM32下完成一个基于FreeRTOS的多任务程序,执行3个周期性task,具体任务不限,但建议如下: task1,每间隔500ms闪烁(变化)一次...
  • 嵌入式系统课程实验 实验一 搭建嵌入式开发环境
  • 嵌入式实验——开发环境建立 心得

    千次阅读 2012-09-29 15:27:15
    今天上了第一次嵌入式系统设计实验,内容为配置linux交叉编译环境,平台采用Redhat 9.0和北京博创公司的开发平台,红帽是安装在虚拟机当中的,因此为实验的设置过程增加了一定的复杂度。整个实验是按照开发平台提供...
  • 实验报告目录嵌入式系统实验报告实验一、熟悉嵌入式Linux开发环境一、实验目的与要求二、实验正文1. 实验内容2. 实验原理3. 实验步骤三、...三、 实验总结或结论1. 实验总结实验四、简单的嵌入式Web服务器设计一
  • 嵌入式程序设计中,C语言编程和ARM汇编语言编程都是必需的,在某些情况下,在某些情况下,还需要C语言与汇编语言的混合编程。灵活地运用C语言和汇编语言之间的关系进行嵌入式编程有利于对嵌入式以及相关模块的编程...
  • 嵌入式操作系统实验报告是对大学课程嵌入式操作系统的课程中的实验总结报告。
  • 嵌入式】基于ARM的嵌入式Linux开发总结

    万次阅读 多人点赞 2019-06-14 20:04:39
    前言嵌入式知识点复习一嵌入式知识点复习二 --体系结构嵌入式知识点复习三 --ARM-LINUX嵌入式开发环境嵌入式知识点复习四 --arm-linux文件编程嵌入式知识点复习五 --arm-linux进程编程嵌入式知识点复习六 --arm-...
  • 实验五问题总结 问题链接:《信息安全系统设计基础》实验实验报告 虽然将07_httpd文件中全部拷贝进了bc中,文件夹中拥有Makefile文件,但是还是无法通过make得到该文件夹中copy和httpd的可执行文件。解决...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 15,815
精华内容 6,326
关键字:

嵌入式实验总结