嵌 入 式 軟 件 筆 試 題
要求:閉卷考試(不能翻書、不能開電腦);作答時間50分鐘;共10道題目。
- volatile的作用有哪些
volatile: 防止編譯器對代碼進行優化,直接從內存中取最新的值 應用場景: 1、多線程使用同一資源時 2、單片機開發中
volatile 的作用:
1. 核心功能:告知編譯器變量的值可能被當前代碼塊外的因素(如中斷服務程序、硬件寄存器、其他線程)異步修改,禁止編譯器對該變量進行 “將內存值緩存到寄存器” 的優化,確保每次訪問都直接讀取內存最新值。
應用場景:
1. 多線程 / 多任務環境中,共享變量(如線程間標志位);
2. 嵌入式硬件寄存器訪問(如單片機的 GPIO 數據寄存器、定時器計數寄存器);
3. 中斷服務程序(ISR)與主程序共享的全局變量。
- 關鍵字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 文件,防止與外部文件函數重名沖突)。
- 用變量a給出下面的定義
1)?一個整型數 ????????int a
2)一個指向整型數的指針 ?int *a
3)一個指向指針的的指針,它指向的指針是指向一個整型數 :int **a; - 下面的代碼輸出是什么,為什么?(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")。
- 中斷是嵌入式系統中重要的組成部分,這導致了許多編譯開發商提供一種擴展:讓標準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,編譯會報 “未聲明標識符” 錯誤(非核心,但需修正)。 - 嵌入式系統中經常要用到無限循環,用C語言編寫死循環的代碼
?????While(1)1.?while(1){}(最常用,明確循環體為空);
2.?for(;;){}(for循環的初始化、條件、增量均可省略,條件省略視為 “永真”);
3.?do{}while(1);(先執行一次循環體,再判斷永真條件)。
- 給定一個整型變量a,寫兩段代碼,第一個設置a的bit 3,第二個清除a?的bit 3。在以上兩個操作中,要保持其它位不變。
?????設置: aI=(0x3<<偏移量) ?設置 a&= ~(0x3<<偏移量)
- 已知?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;
}
- ?簡述SPI的傳輸特點、方式并畫出工作時序
傳輸特點:
1.通信屬性:串行(數據逐位傳),同步(依賴sclk(spi)時鐘同步),全雙工(同一時鐘周期內,主機經mosi發、從機經miso發,雙向同時傳);
- 速率與數據::“高速 3.4Mbps” 是 HS-mode,需區分 “標準模式(100Kbps)、快速模式(400Kbps)、高速模式(3.4Mbps)速率達mbps級;最小單位為字節(8/16位),1時鐘周期傳1位,1字節需8時鐘周期;
- 主從模式:支持主從機,常用“單主機多從機”,主機控制sck時鐘和nss片選,從機被動響應
- 從機選擇:通過專屬的nss/ncs片選線,主機拉低目標從機nss電平建立通信,其他從機nss保持高電平不響應
傳輸方式:
- 主從邏輯:主機輸出sck和nss,經mosi發數據;從機按sck節奏收mosi數據,經miso回傳數據
- 全雙工實現:如主機發 0xFF、從機發 0x00,SCK 上升沿時二者分別經 MOSI/MISO 發 1 位,下降沿時分別讀對方數據;8 時鐘周期后,雙方均完成 “發 + 收”;
- 多從機傳輸:四線制連接(sck、mosi、miso共線,各從機獨立接主機nss),主機拉低對應從機nss實現“一對一”通信,避免沖突。
工作時序圖:
- 簡述I2C的傳輸特點、方式并畫出工作時序(從機地址、寄存器地址、數據自定義)
一、I2C 傳輸特點
- 傳輸類型:串行(逐位傳)、同步(依賴 SCL 時鐘同步)、半雙工(同一時間單向傳);
- 硬件結構:僅 2 根雙向線(SCL 時鐘、SDA 數據),均需外接上拉電阻(空閑時保高電平、穩電路);
- 速率分級:低速 100Kbps、中速 400Kbps、高速 3.4Mbps;
- 主從架構:支持單 / 多主機多從機,主機主動發起 / 結束通信,從機被動響應;
- 唯一尋址:從機均有唯一 7 位地址(如 SHT20 為 0x40),主機通過地址定位從機;
- 應答機制:每傳 1 字節(8 位),接收器第 9 時鐘周期回 ACK(0,成功)或 NACK(1,失敗 / 停止)。
二、I2C 傳輸方式
1. 主機→從機(寫傳輸)
- 主機發起始信號(S),占總線;
- 發 “7 位從機地址 + W(0)”(如 SHT20 寫地址 0x80);
- 從機回 ACK;
- 發目標寄存器地址(如 SHT20 溫度寄存器 0xE3);
- 從機回 ACK;
- 發自定義數據(如配置值 0x55);
- 從機回 ACK;
- 主機發終止信號(P),釋總線。
2. 主機←從機(讀傳輸,先寫后讀)
- 主機發起始信號(S);
- 發 “7 位從機地址 + W”(如 0x80),從機回 ACK;
- 發目標寄存器地址(如 SHT20 濕度寄存器 0xE5),從機回 ACK;
- 主機發重復起始信號(S);
- 發 “7 位從機地址 + R(1)”(如 SHT20 讀地址 0x81),從機回 ACK;
- 從機發自定義數據(如 2 字節濕度值 0x1234),每字節主機回 ACK;
- 主機收完回 NACK(停傳);
- 主機發終止信號(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. 時序步驟
- S(起始):SCL 高時,SDA 高→低(下降沿);
- 寫尋址:SCL 高時,SDA 傳 0x80(8 位),從機回 ACK;
- 寄存器地址:SCL 高時傳 0xE3,從機回 ACK;
- 重復 S:SCL 高時,SDA 高→低;
- 讀尋址:SCL 高時傳 0x81,從機回 ACK;
- 傳數據:SCL 高時從機傳 0x1A(高 8 位),主機回 ACK;再傳 0x5B(低 8 位),主機回 NACK;
- P(終止):SCL 高時,SDA 低→高(上升沿)。
答題區:
答題要求:閉卷考試(不能翻書、不能開電腦);作答時間50分鐘;共10道題目。
(請保留第原題目,答題區請備注好做題序號;只能寫在答題紙上拍照粘貼到文檔里-答題區,請保證照片清晰)
發送時:請將文檔命名更改為:本人姓名_軟件筆試題