1 基礎知識
1.1 概述
對嵌入式的定義
- 國內定義:以應用為中心,以計算機技術為基礎,軟體硬體可裁剪,且適應系統對功能,可靠性,成本,體積,功耗嚴格要求的專用計算機系統。
- IEEE定義:用於控制,監視或者輔助操作機器和裝置的裝置。
分類
以下按照形態差異分類:
類名 | 板型號 |
---|---|
晶片級 | MCU,SoC |
板級 | 微控制器,模組 |
裝置級 | 工控機 |
其中,微控制器又分為:
- 不含作業系統(我們學習的arduino不包含作業系統)
- 含作業系統
組成
嵌入式系統四大組成部分:
- 微處理器
核心部件,微處理器強弱直接影響嵌入式裝置的複雜度和範圍。 - 儲存器
對速度和功耗要求高 - 輸入/輸出裝置(I/O)
①人機互動②感測器裝置③輸入裝置 - 通訊和擴充套件介面
嵌入式系統與其他系統進行資料交換和擴充套件。
1.2 常用元件
名稱 | 相關單位 | 作用 | 分類 |
---|---|---|---|
電阻器(Resistor) | 歐姆 Ω(R) /誤差/額定功率等 歐姆定律:I=U/R | 限流,分壓電路 | 可調電阻器,熱敏電阻器,光敏電阻器,壓敏電阻器 |
電容器(Capacitor) | 法拉 F(C) (電荷量和電壓比值) | 儲能元件,充放電特性和阻止直流電流,允許交流電 | 濾波電容器,積分電容器,微分電容器 |
電感器(Inductor) | 亨利 H(L)\(X_L(感抗)=2\pi f(交流電頻率)L\) | 對突變電流有阻礙作用 。濾波,震盪,延遲, | 篩選訊號,過濾噪聲,穩定電流,抑制電磁波干擾 |
二極體(Diode) | 1V 10mA 標記為D | ①正向導通,逆向截止 ②整流,穩壓,恆流,開關,發光,光電轉換等電路中 | 發光二極體(LED):長腳陰極短腳陽極。一般工作電壓在1V,導電電流在10mA,所以需要一個電阻分壓限流\(R=(E-U_E)/I_F\) |
(半導體)電晶體 | 標記為Q | 把微弱的電訊號放大成幅度值較大的電訊號(用作無觸點開關) | ①NPN型:基極B和發射極E之間施加正向電壓,發射極和集電極導通②PNP型:基級和發射極施加反向電壓,電晶體導通 |
萬用表 | V,A,Ω,β(半導體引數),F | 測量直流電流,電壓,交流電流,電壓,電阻,還可以測量電容量,電感量,半導體引數 | 數字萬用表分為四個測量插孔和紅黑表筆各一個 |
杜邦線 | null | 擴充套件實驗板引腳,增加實驗專案,無焊接進行電路實驗 | 杜邦線有兩頭,有插針插孔兩類,可以兩頭都是,也可一個一半 |
麵包板 | null | 電路的組裝,除錯和訓練 | 一般五個一組,分配在同一金屬片中 |
Arduino擴充套件板 | null | 簡化電路搭建過程,快速搭建專案 | 多種,不列舉 |
模組 | null | 無需瞭解模組原理,只需按照要求連線,即可快速製作硬體 | 對於一些簡單的模組只有三個訊號線:①V/VCC電源②G/GND地線③S訊號引腳。例如UART藍芽模組等 |
2 Arduino軟硬體開發基礎
2.1 開發板
2.1.1 Arduino UNO簡介
如圖所示為一個Arduino UNO板
擁有:
- 14個輸入輸出引腳(0~13),其中(3,5,6,9,10,11)可以作為PWM輸出
- 6個模擬輸入(A0~A5)
- 1個UART硬體串列埠
- 1個電源插孔,1個ICSP插座和1個復位按鈕
- 1個USB介面,與計算機連線,可以供電和通訊
引腳名稱和功能
電源引腳
名稱 | 作用 |
---|---|
VIN | ①外部電流供電時的輸入電壓引腳 ②電源插座供電時提供5V電壓 |
5V | 輸出5V電壓 使用該引腳和3.3V引腳可能損壞旁路線性穩壓器 |
3V | 輸出3.3V電壓 |
GND | 接地 |
AREF | 模擬輸入的參考電壓 |
RESET | 擴充套件一個按鈕實現復位功能。引腳為低電平 |
輸入輸出
名稱 | 引腳位 | 作用 |
---|---|---|
串列埠 | 0(RX),1(TX) | 接收(RX)和傳送(TX)TTL序列資料。 |
外部中斷 | 2,3 | 觸發中斷的引腳。觸發條件分為:①低電平觸發 ②上升沿觸發 ③下降沿觸發 ④發生變化觸發 |
PWM | 3,5,6,9,10,11(~線) | 6路八位PWM |
SPI | 10(SS),11(MOSI),12(MISO),13(SCK) | 支援SPI通訊 |
LED | 13 | 高電平LED亮,低電平LED滅 |
TWI | A4/SDA,A5/SCL | TWI通訊 |
3 Arduino程式設計
3.1 函式
時間函式
函式 | 引數 | 用法 | 備註 |
---|---|---|---|
delay(ms) | ms為unsigned long | 延長ms毫秒 | delay更多用於較短延時,但是有以下缺點:①延時中無法讀取感測器的值等,阻止了大部分操作 |
delayMicroseconds(μs) | μs為 unsigned int | 延長微秒 | 更長時間用delay |
micros() | time=micros() | 返回以微秒為單位的執行時間(unsigned long) | 計時週期為70min,對於UNO(晶體振盪器為16MHz),返回值為4μs的倍數 |
millis() | time=millis() | 返回毫秒執行時間(unsigned long) | 計時週期為50天 |
數學函式
函式 | 引數 | 用法 |
---|---|---|
abs(x) | x為int家族 | 絕對值 |
constrain(x,a,b) | x歸一化資料,a下限,b上限 任意資料型別 | 對於x,小於a返回a,小於b返回b ,中間返回x |
map(x,fromLow,fromHigh,toLow,toHigh) | 只能用於整數 (對映數,現在下限,現在上限,對映後下限,對映後上限) | 將整數從一個範圍對映到另外一個範圍,與上著規則基本一致 |
max(x,y) | 任意型別 | 返回兩個數較大者(可用作限制下限) |
min(x,y) | 同上 | 返回最小(控制上限) |
pow(base,exponent) | float | 冪的運算 |
sqrt(X) | 任意 | 求平方根 |
sq() | 任意實數 | 求平方 |
cos/sin/tan() | 弧度角 | 角餘弦值/正弦值/正切 |
字元函式
十三個,較簡單,看懂英語也能知其用法:
- isAlpha 是否為字母
- isAlphaNumeric 是否為字母或數字
- isAscii 是否為ASCII碼
- isControl 是否為控制符
- isDigit 是否為數字
- isGraph 一個非空字元是否可輸出/可列印
- isHexadecimalDigit 是否為16進位制數
- isLowerCase 是否為小寫字母
- isPrintable 任意字元是否可輸出列印
- isPunct 是否為標點符號
- isSpace 是否為空格符
- isUpperCase 是否大寫
- isWhitespace 是否為" ","\f","\n","\r","\t","\v"的任意一種
以上都是若條件成立返回真否則為假
隨機函式
random(min,max)
- min 下限
- max 可選 上限
返回[min,max-1]之間的隨機數(long)
每次執行程式結果相同,如需不同需要以下方法
randomSeed(seed)
- seed 種子值
這兩者都是偽隨機,可以逆向分析
位和位元組函式
函式 | 引數 | 作用 |
---|---|---|
bit(n) | n為指定位 | 返回位的權值(bit 0是1,1是2,2是4) |
bitClear(x,n) | x 數字變數,n 要讀取的位 | 返回指定位的值 |
bitSet(x,n) | x 數字變數 n 指定置1的位 | 某一位置0 |
bitRead(x,n) | x 變數 n 指定讀取位 | 讀取指定位的值 |
bitWrite(x,n,b) | x 變數 ,n 要賦值的位,b要賦的值 | 給變數指定位賦值 |
highByte/lowByte(x) | x | |
變數 | 提取一個字高位元組/低位元組 |
3.2 常量表示
進位制字首
- 十進位制:無
- 二進位制 字首B
- 八進位制 字首 0
- 十六進位制 字首0x
3.3 程式結構
一個Arduino程式分為兩個函式
-
setup()
程式開始執行時呼叫該函式,可用於變數初始化等等,只會執行一次 -
loop()
執行完setup會執行看、loop,loop語句始終按照順序迴圈執行。
3.4 位運算
- &按位與
0 0 1 1
0 1 0 1
--------&
0 0 0 1
- |按位或
0 0 1 1
0 1 0 1
---------|
0 1 1 1
-
~ 按位取反
-
^按位異或
0 0 1 1
0 1 0 1
---------^
0 1 1 0
-
<< 左移
運算子左移 -
>>右移
4 第四章
4.1 數字介面
- 數字引腳
- 模擬引腳
- 通訊引腳
- 外部中斷引腳
- 電源引腳
- 。。。
I/O介面封裝函式
基本封裝函式有三個
函式 | 引數 | 作用 |
---|---|---|
digitalRead(pin) | 讀取的引腳編號pin | 讀取引腳狀態 |
digitalWrite(pin,value) | pin同上,value:HIGH/LOW(高引腳低引腳) | HIGH為5Vor3.3V,LOW為0V 設定引腳的高低電平 |
pinMode(pin,mode) | mode有INPUT,OUTPUT,INPUT_PULLUP | 指定引腳輸出模式 |
-
設定引腳 為輸出(OUTPUT)模式,此時引腳為低阻抗狀態,可以向其他電路原件提供電流(通常為40mA以內)
-
設定引腳為輸入(INPUT)模式,,此時引腳為高阻抗狀態,此時該引腳可用於讀取訊號。
-
設定引腳為輸入上拉(INPUT_PULLUP)模式.首先Arduino內部自帶上拉電阻。當我們需要使用該內部上拉電阻,可以透過pinMode()將引腳設定為輸入上拉(INPUT_PULLUP)模式。當你將一個引腳設定為INPUT_PULLUP模式時,如果沒有輸入訊號,這個引腳的狀態將會是HIGH(高電平)。只有當這個引腳被接地(即連線到GND)時,它的狀態才會變為LOW(低電平)。這種模式通常用於接按鈕或開關。例如,你可以將一個按鈕的一端接到interruptPin,另一端接到GND。當按鈕沒有被按下時,interruptPin的狀態是HIGH。當按鈕被按下時,interruptPin會被接地,因此它的狀態變為LOW。使用內部上拉電阻的好處是,你不需要在你的電路中新增額外的上拉電阻。這可以簡化你的電路設計,並減少硬體成本。
4.2 模擬介面的應用
在Arduino中有A0~A5,6個模擬介面,可以透過A/D轉換器(10個),將0V~5V的電壓轉換為0~1023的值。
在板子上有~的介面,可以實現D/A轉換。
模擬介面三個封裝函式
函式 | 引數 | 作用 |
---|---|---|
analogRead(pin) | 0~5的介面 | 模擬讀,返回一個轉換值(0~1023) |
analogReference(type) | 選項:①DEFAULT:預設5V/3.3V電壓 ②INTERNAL:片內參考電壓,1.1V/2.56V ③INTERNAL1V1:片內1.1V參考電壓 ④INTERNAL2V56 ⑤EXTERNAL:透過AREF引腳獲取電壓 | 配置模擬引腳的參考電壓 |
analogWrite(pin,value) | value:0~255之間int型。 | 設定引腳輸出模擬量,用於改變燈亮度或者電機轉速等。 |
注意:
- 針腳懸空時,analogRead()返回值受到環境的多重影響。
- AREF引腳若電壓在0~5V範圍外,在呼叫analogRead()前必須設定EXTERNAL
- 呼叫analogWrite()之前,不需要呼叫pinMode()函式設定該引腳為輸出,analogWrite()和read()沒有關係
4.3 序列介面的應用
在Arduino上至少有一個串列埠(UART/USART),透過RX(0)和TX(1)和計算機USB進行串列埠通訊。
串列埠通訊指:將接收的來自CPU的並行資料轉換為連續的序列資料流傳送出去,或將接收的序列資料轉換為並行資料轉發給CPU。
串列埠的庫函式
列舉幾個在實驗中比較常見的函式
-
if(Serial) 串列埠是否準備好
-
available() 讀取串列埠收到的位元組數
Serial.available()
-
begin() 設定序列通訊波特率
begin(speed,config)
speed 設定波特率
config 設定資料位數.預設是,8資料位,無奇偶位,1個停止位。
Serial.begin(19200)
-
end(結束通訊) RX,TX可以作為普通引腳使用
-
find()/findUntil() 從串列埠緩衝區讀取已知長度的目標資料/讀取到結束串停止
-
print() 將資料傳送到串列埠顯示,一個數字按照一個ASCII字元顯示。
print(val,format)
format指定資料顯示幾位
相似函式還有println,加一個換行符 -
read() 讀字元
還有readBytes/readBytesUntil/readString/熱愛的StringUntil -
setTimeout() 設定串列埠超時時間,預設1000ms
-
write()寫二進位制資料到串列埠
-
serialEvent()串列埠資料準備好時觸發的事件函式
4.4 I2C匯流排介面(半雙工)(考的簡單)
內部積體電路(Inter-Integrated Circuit ,I2C),是具有多主機系統所需的包括匯流排仲裁和高低速器件同步功能的高效能匯流排。
兩根訊號線:資料線SDA,和時鐘線SCL。
I2C類庫函式
-
begin(address)
初始化wire庫,將I2C裝置作為主裝置或從裝置加入I2C匯流排,只呼叫一次。預設為主裝置 -
beginTransmission(address)
啟動一個已知地址的I2C從裝置的通訊 -
write()
寫資料到裝置 -
endTransmission()
結束一個begintransmission()。所以一次資料的傳輸,需要三個函式連續使用。 -
requestFrom()
設定從裝置向主裝置傳送的位元組數。
Wire.requestFrom(裝置地址,請求位元組數,stop[請求後傳送停止資訊,可選])
、 -
available()
呼叫requestFrom()返回接收的位元組數, -
read()
接收任意方向的一個位元組資料 -
setClock()
修改底層時脈頻率,底線是100KHZ -
onReceive()
onReceive(hander)
當從裝置接收主裝置的資料時,呼叫hander函式 -
onRequest()
當從主裝置接收裝置的資料時,呼叫一個hander函式
4.5 SPI介面(全雙工)
序列外設介面(Serial Peripheral Interface,SPI),物理上時透過微處理單元(MCU)的同步串列埠(Synchronous Serial Port,SSP)模擬實現資料通訊,允許MCU以全雙工的同步序列模式進行通訊
在晶片只佔用四個引腳
引腳名 | 作用 |
---|---|
SCLK | 序列時鐘,用來同步資料傳輸,由主機輸出 |
MOSI | 主機輸出從機輸入資料線 |
MISO | 主機輸入從機輸出資料線 |
SS | 片選線,低電平有效,由主機輸出 |
SS可以實現一條匯流排多個SPI,所以SPI匯流排可以出現多個從機,但是隻能出現一個主機 |
4.6 外部中斷介面(重要)(模組)
這裡中斷同作業系統的中斷。外部內部發生事件,CPU暫停當前工作,去完成當前發生的事件,之後CPU繼續剛剛被終止地方,繼續當前工作,這樣的過程稱為中斷。
-
中斷源:產生中斷請求的源
-
中斷服務程式(ISRs),處理中斷的程式
有一定限制,不能有引數和返回值等,執行時間儘量短,同一時刻只有一個ISRs執行,delay不能用但是delayMicroseconds可以使用。 -
中斷優先順序
-
中斷巢狀
在UNO中,用於中斷引腳為 ,2,3
外部中斷函式 四個
①attachInterrupt()
推薦語法:
attachInterrupt(digitalPinToInterrupt(pin),ISR,mode)
引數說明:
- pin:引腳號
- ISR:呼叫的ISRs函式(中斷服務程式函式名)不能有引數和返回值
- mode:觸發中斷方式
mode 定義 | 含義 |
---|---|
LOW | 引腳低電平 |
HIGH | 引腳高電平 (不適用UNO) |
CHANGE | 引腳變化 |
RISING | 引腳從低到高跳變 |
FALLING | 引腳從高到底跳變 |
我們在使用時建議使用digitalPinToInterrupt(pin)
函式進行轉換,因為不同開發版的對映不同
在UNO中,中斷號和引腳關係為:
INT.0=2
INT.1=3
② detachInterrupt()
關閉某個已啟用的中斷
detachInterrupt(interrupt)
引數:
interrupt,關閉中斷號
③ interrupts()
開啟中斷
無引數
④ noInterrupts()
停止已經設定好的中斷,使程式不受中斷影響
無引數
tips:多說一嘴,可以使用開關中斷實現原子級的函式,例如對時間敏感的函式(參考作業系統)
外部中斷例子
例一:實現開關中斷
void setup() {}
void loop()
{
noInterrupts();
///原子/時間敏感函式
interrupts();
}
例二:實現LED不斷閃爍
const byte ledPin=13;
const byte interruptPin=2;
volatile byte state=LOW; //volatile是每次讀都會從記憶體讀新值而不是暫存器
void setup()
{
pinMode(ledPin,OUTPUT);
pinMode(interruptPin,INPUT_PULLUP);//外接一個按鈕
attachInterrupt(digitalPinToInterrupt(interruptPin),blink,CHANGE);
}
void loop()
{
digitalWrite(ledPin,state);
}
void blink()
{
state=!state;
}
4.7 軟體串列埠(重要)
作用:硬體串列埠為0,1。但是為了解決日常大量使用0,1介面,增加的軟體串列埠。若使用軟體串列埠,只有一個可以同時接收資料。
函式
定義一個數字引腳
SoftwareSerial mySerial(RX,TX)
-
begin()
-
avaliable()
-
read()
-
write()
同硬體串列埠
-
isListening() 是否為檢測狀態
-
listen() 使串列埠處於檢測狀態,同時只有一個串列埠處於檢測狀態
-
overflow()測試軟體串列埠是否溢位,並清除溢位標誌
-
peek() 返回軟體串列埠RX接收字元,再次呼叫返回相同字元
-
print和println
4.8 EEPROM
斷電不丟失資料
特點:以位元組為單位進行資料讀寫
考點:
多位元組進行資料讀寫,使用①陣列 ②共用體