版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
2相關(guān)知識(shí)34任務(wù)小結(jié)與練習(xí)1任務(wù)實(shí)施任務(wù)引入與目標(biāo)Arduino開(kāi)發(fā)環(huán)境搭建一、任務(wù)引入與目標(biāo)任務(wù)目標(biāo)任務(wù)1介紹Arduino語(yǔ)言的特點(diǎn)和程序結(jié)構(gòu),安裝Arduino開(kāi)發(fā)環(huán)境,用于項(xiàng)目1的ESP32物聯(lián)網(wǎng)網(wǎng)關(guān)設(shè)計(jì)。任務(wù)引入ESP32是樂(lè)鑫科技開(kāi)發(fā)的一款32位微控制器,它集成了Wi-Fi及藍(lán)牙功能,非常適合作為物聯(lián)網(wǎng)開(kāi)發(fā)中的網(wǎng)關(guān)使用,當(dāng)然也可以作為普通的單片機(jī)使用。項(xiàng)目1將ESP32作為物聯(lián)網(wǎng)網(wǎng)關(guān),首先就需要為ESP32搭建開(kāi)發(fā)環(huán)境。二、相關(guān)知識(shí)什么是Arduino語(yǔ)言Arduino使用C/C++編寫(xiě)程序,其中C語(yǔ)言是一種面向過(guò)程的編程語(yǔ)言,C++是一種面向?qū)ο蟮木幊陶Z(yǔ)言。早期的Arduino核心庫(kù)是使用C語(yǔ)言編寫(xiě),后來(lái)引進(jìn)了面向?qū)ο蟮乃枷?目前最新的Arduino核心庫(kù)采用C語(yǔ)言與C++混合編寫(xiě)而成。通常我們說(shuō)的Arduino語(yǔ)言,是指Arduino核心庫(kù)文件提供的各種應(yīng)用程序編程接口(ApplicationProgrammingInterface,API)的集合。這些API是對(duì)更底層的單片機(jī)支持庫(kù)進(jìn)行二次封裝所形成的。傳統(tǒng)開(kāi)發(fā)方式中,開(kāi)發(fā)者需要理清每個(gè)寄存器的含義及其之間的關(guān)系,然后配置多個(gè)寄存器來(lái)達(dá)到開(kāi)發(fā)的目的。而Arduino程序使用了清楚明了的API替代繁雜的寄存器配置過(guò)程,例如以下代碼:pinMode(25,OUTPUT);digitalWrite(25,HIGH);pinMode(25,OUTPUT)是設(shè)置引腳的模式,這里設(shè)定了引腳IO25為輸出模式;而digitalWrite(25,HIGH)是讓IO25引腳輸出高電平數(shù)字信號(hào)。Arduino使用戶不用再理會(huì)單片機(jī)中繁雜的寄存器配置,就能直觀地編寫(xiě)Arduino程序讓ESP32工作,在增強(qiáng)了程序可讀性的同時(shí),也提高了開(kāi)發(fā)的效率。二、相關(guān)知識(shí)Arduino程序結(jié)構(gòu)Arduino的程序結(jié)構(gòu)與傳統(tǒng)的C/C++結(jié)構(gòu)不同,在Arduino程序中沒(méi)有main函數(shù),Arduino程序的基本結(jié)構(gòu)由setup和loop兩個(gè)函數(shù)組成??刂破魍娀驈?fù)位后,即會(huì)開(kāi)始執(zhí)行setup函數(shù)中的程序,該部分只會(huì)執(zhí)行一次。通常我們會(huì)在setup函數(shù)中完成Arduino的初始化設(shè)置,如配置I/O口狀態(tài)、初始化串口等操作。在setup函數(shù)中的程序執(zhí)行完后,Arduino會(huì)接著執(zhí)行l(wèi)oop函數(shù)中的程序。loop函數(shù)是一個(gè)死循環(huán),其中的程序會(huì)不斷地重復(fù)運(yùn)行。通常我們會(huì)在loop函數(shù)中完成程序的主要功能,如驅(qū)動(dòng)各種模塊、采集數(shù)據(jù)等。除了Arduino之外,ESP32還可以使用哪些開(kāi)發(fā)環(huán)境?所使用的編程語(yǔ)言是什么?課堂討論三、任務(wù)實(shí)施實(shí)施設(shè)備安裝了Windows操作系統(tǒng)的計(jì)算機(jī)。實(shí)施過(guò)程1.軟件安裝通過(guò)官網(wǎng)https://www.arduino.cc/en/software下載,如圖1-1所示,然后點(diǎn)擊“安裝”即可;或者通過(guò)系統(tǒng)應(yīng)用安裝。圖1-1Arduino官網(wǎng)下載頁(yè)面三、任務(wù)實(shí)施2.ESP32內(nèi)核包安裝在文件→首選項(xiàng),輸入下面的開(kāi)發(fā)板管理器網(wǎng)址之一,如圖1-2所示。http://download.dfrobot.top/FireBeetle/package_esp32_index.json/dl/package_esp32_index.json圖1-2Arduino的開(kāi)發(fā)板管理器網(wǎng)址三、任務(wù)實(shí)施在打開(kāi)的開(kāi)發(fā)板管理器中,輸入“ESP32”,點(diǎn)擊“安裝”,如圖1-3所示。圖1-3在Arduino開(kāi)發(fā)板管理器中安裝內(nèi)核包3.外設(shè)庫(kù)文件安裝將4個(gè)庫(kù)文件復(fù)制到Arduino安裝目錄的libraries文件夾下,如圖1-4所示?;蛘咴陧?xiàng)目→加載庫(kù)→管理庫(kù)中,搜索外設(shè)庫(kù)名安裝,效果相同。圖1-4安裝外設(shè)庫(kù)文件圖1-3在Arduino開(kāi)發(fā)板管理器中安裝內(nèi)核包三、任務(wù)實(shí)施4.離線安裝如果ESP32內(nèi)核包下載太慢或多次失敗,可以離線下載安裝。(1)離線加載內(nèi)核包。如圖1-5所示,進(jìn)入內(nèi)核包所在目錄,以下面開(kāi)發(fā)板管理器網(wǎng)址為例介紹:http://download.dfrobot.top/FireBeetle/package_esp32_index.json打開(kāi)圖15中框2所在目錄,并找到staging—packages目錄,清空目錄。將離線壓縮包粘貼到里面,如圖1-6所示。圖1-5查找Arduino安裝目錄圖1-6在本地加載內(nèi)核包三、任務(wù)實(shí)施(2)安裝內(nèi)核包。打開(kāi)開(kāi)發(fā)板管理器,搜索esp32,選擇版本,點(diǎn)擊“安裝”即可,如圖1-7所示。內(nèi)核包因?yàn)橐呀?jīng)下載好,所以可以快速安裝。(3)espressif內(nèi)核包。另一個(gè)開(kāi)發(fā)板管理器網(wǎng)址(/dl/package_esp32_index.json)對(duì)應(yīng)的離線包如圖1-8所示。圖1-7安裝離線加載的內(nèi)核包圖1-8
espressif內(nèi)核包四、任務(wù)小結(jié)與練習(xí)任務(wù)小結(jié)任務(wù)1在計(jì)算機(jī)中搭建Arduino開(kāi)發(fā)環(huán)境,并進(jìn)行了相關(guān)配置。運(yùn)行Arduino自帶的示例程序,觀察程序的結(jié)構(gòu)和操作過(guò)程。實(shí)踐練習(xí)謝謝聆聽(tīng)2相關(guān)知識(shí)34任務(wù)小結(jié)與練習(xí)1任務(wù)實(shí)施任務(wù)引入與目標(biāo)ESP32的GPIO操作一、任務(wù)引入與目標(biāo)任務(wù)目標(biāo)任務(wù)2將學(xué)習(xí)ESP32的GPIO功能和相關(guān)函數(shù),并通過(guò)GPIO初始化和GPIO數(shù)字輸出函數(shù),完成一個(gè)LED閃爍的例子。任務(wù)引入GPIO(GeneralPurposeInputOutput)是通用輸入輸出端口的簡(jiǎn)稱(chēng),是ESP32作為微控制單元(MCU)使用時(shí)最基礎(chǔ)的功能。用戶可以利用GPIO功能,連接一些簡(jiǎn)單外設(shè),實(shí)現(xiàn)檢測(cè)和控制功能。二、相關(guān)知識(shí)ESP32資源圖1-9是一款搭載了ESP32-WROOM-32D的開(kāi)發(fā)板。ESP32的外圍設(shè)備包括:10個(gè)電容傳感GPIO、18個(gè)模數(shù)轉(zhuǎn)換器(ADC)通道、2個(gè)數(shù)模轉(zhuǎn)換器(DAC)、3個(gè)SPI接口、3個(gè)UART接口、2個(gè)I2C接口、16個(gè)脈沖寬度調(diào)制輸出通道、2個(gè)I2S接口。具體引腳的標(biāo)簽可以查看所購(gòu)置開(kāi)發(fā)板的說(shuō)明書(shū)。圖1-9搭載了ESP32-WROOM-32D的開(kāi)發(fā)板二、相關(guān)知識(shí)初始化GPIO函數(shù)語(yǔ)法:pinMode(pin,mode)作用:設(shè)置一個(gè)引腳(pin)作為GPIO時(shí)的I/O模式。參數(shù):pin,引腳編號(hào);mode,GPIO的I/O模式,取值有3種,分別是INPUT(數(shù)字輸入)、OUTPUT(數(shù)字輸出)和INPUT_PULLUP(數(shù)字輸入,且使能引腳的內(nèi)部上拉電阻)。語(yǔ)法:digitalWrite(pin,value)作用:設(shè)置一個(gè)數(shù)字輸出引腳的輸出電平值,即HIGH或LOW。參數(shù):pin,引腳編號(hào),此引腳必須在之前使用pinMode設(shè)置為OUTPUT模式;value,2個(gè)值,分別是LOW(輸出低電平)、HIGH(輸出高電平)。GPIO數(shù)字輸出二、相關(guān)知識(shí)GPIO數(shù)字輸入語(yǔ)法:intdigitalRead(pin)作用:讀取一個(gè)數(shù)字輸入引腳的電平值。返回:HIGH(高電平)或LOW(低電平)。參數(shù):pin,引腳編號(hào)。三、任務(wù)實(shí)施實(shí)施設(shè)備部署了Arduino開(kāi)發(fā)環(huán)境的計(jì)算機(jī)。實(shí)施過(guò)程1.打開(kāi)示例程序打開(kāi)示例程序Blink,如圖1-10所示,另存到其他路徑。圖1-10Arduino中的示例Blink三、任務(wù)實(shí)施//thesetupfunctionrunsoncewhenyoupressresetorpowertheboardvoidsetup(){//initializedigitalpinLED_BUILTINasanoutput.pinMode(LED_BUILTIN,OUTPUT);}//theloopfunctionrunsoverandoveragainforevervoidloop(){digitalWrite(LED_BUILTIN,HIGH);//turntheLEDon(HIGHisthevoltagelevel)delay(1000);//waitforaseconddigitalWrite(LED_BUILTIN,LOW);//turntheLEDoffbymakingthevoltageLOWdelay(1000);//waitforasecond}Blink代碼:三、任務(wù)實(shí)施//thesetupfunctionrunsoncewhenyoupressresetorpowertheboardvoidsetup(){//initializedigitalpinLED_BUILTINasanoutput.pinMode(25,OUTPUT);}//theloopfunctionrunsoverandoveragainforevervoidloop(){digitalWrite(25,HIGH);//turntheLEDon(HIGHisthevoltagelevel)delay(1000);//waitforaseconddigitalWrite(25,LOW);//turntheLEDoffbymakingthevoltageLOWdelay(1000);//waitforasecond}2.修改程序?qū)⒊绦蛑械囊_編號(hào)改為IO25,代碼如下:三、任務(wù)實(shí)施3.硬件連接將LED的數(shù)據(jù)引腳接網(wǎng)關(guān)ESP32的IO25,GND對(duì)應(yīng)連接。USB線的一頭連接電腦USB接口,另一Micro-USB頭接ESP32。4.運(yùn)行測(cè)試開(kāi)發(fā)板選擇FireBeetle-ESP32,如果能正確識(shí)別端口,比如圖1-9中的串口19(你的計(jì)算機(jī)不一定是這個(gè)號(hào)),如圖1-11所示,就可以正常上傳程序。如果識(shí)別不出來(lái)串口,則需要重新安裝CP2102驅(qū)動(dòng)。圖1-11下載程序時(shí)選擇開(kāi)發(fā)板和配置端口三、任務(wù)實(shí)施點(diǎn)擊“上傳”按鈕,按下boot鍵不松直到有上傳進(jìn)度,稍后顯示上傳成功,如圖1-12所示。圖1-12Arduino程序上傳到ESP32成功觀看實(shí)驗(yàn)結(jié)果,拍攝短視頻上傳到課程學(xué)習(xí)平臺(tái),要體現(xiàn)出:LED閃爍效果,程序中的引腳編號(hào)。四、任務(wù)小結(jié)與練習(xí)任務(wù)小結(jié)任務(wù)2通過(guò)GPIO初始化和GPIO數(shù)字輸出函數(shù),完成控制LED閃爍的功能。編寫(xiě)代碼,實(shí)現(xiàn)LED閃爍:修改引腳編號(hào);采用宏定義的方法,給引腳起別名。實(shí)踐練習(xí)謝謝聆聽(tīng)2相關(guān)知識(shí)34任務(wù)小結(jié)與練習(xí)1任務(wù)實(shí)施任務(wù)引入與目標(biāo)ESP32的串口功能一、任務(wù)引入與目標(biāo)任務(wù)目標(biāo)任務(wù)3將學(xué)習(xí)ESP32的串口功能和相關(guān)方法,并利用串口打印和讀取串口數(shù)據(jù)的方法,編寫(xiě)一個(gè)工程,測(cè)試數(shù)據(jù)接收功能。任務(wù)引入任務(wù)2為ESP32編寫(xiě)了簡(jiǎn)單的LED控制程序,容易觀察結(jié)果是否正確。如果是比較復(fù)雜的程序,當(dāng)運(yùn)行有問(wèn)題時(shí),該怎樣調(diào)試呢?這就需要用到串口的打印輸出功能,可以將程序運(yùn)行過(guò)程的一些狀態(tài)打印出來(lái)。當(dāng)然串口還有數(shù)據(jù)輸出和數(shù)據(jù)輸入的功能,都是比較常用的。二、相關(guān)知識(shí)Arduino中UART協(xié)議在Arduino中,串行通信協(xié)議是一種常見(jiàn)的通信方式,通過(guò)一個(gè)或多個(gè)串口連接兩個(gè)或多個(gè)設(shè)備。串行通信協(xié)議可以使用不同的協(xié)議和格式,最常見(jiàn)的是UART(通用異步收發(fā)器)協(xié)議。UART協(xié)議使用兩個(gè)引腳進(jìn)行通信:TX(發(fā)送)和RX(接收)。當(dāng)設(shè)備1向設(shè)備2發(fā)送數(shù)據(jù)時(shí),它將數(shù)據(jù)寫(xiě)入TX引腳,并且設(shè)備2會(huì)從其對(duì)應(yīng)的RX引腳讀取數(shù)據(jù)。這種通信通常是基于字節(jié)的,即一個(gè)字節(jié)一個(gè)字節(jié)地發(fā)送和接收。每個(gè)字節(jié)都由一個(gè)起始位、一個(gè)或多個(gè)數(shù)據(jù)位、一個(gè)可選的奇偶校驗(yàn)位和一個(gè)或多個(gè)停止位組成。在Arduino中,串口通信通常使用Serial庫(kù)來(lái)實(shí)現(xiàn)。需要注意的是,在進(jìn)行串行通信時(shí),需要確保發(fā)送和接收端的波特率(數(shù)據(jù)傳輸速率)是相同的,否則可能會(huì)導(dǎo)致通信失敗。波特率可以在初始化串口對(duì)象時(shí)設(shè)置。二、相關(guān)知識(shí)ESP32的串口ESP32共有3個(gè)UART端口,其中UART1用于Flash讀/寫(xiě),見(jiàn)表1-1。UART0在Arduino程序中的對(duì)象名是Serial,UART2在Arduino程序中的對(duì)象名是Serial2,對(duì)應(yīng)的發(fā)送和接收引腳見(jiàn)表11。比較方便的安排是:用Serial進(jìn)行打印調(diào)試,用Serial2與其他設(shè)備進(jìn)行串口通信。串口名Arduino名TXRXUART0Serialpin1pin3UART1Serial1pin10pin9UART2Serial2pin17pin16圖1-10Arduino中的示例Blink三、任務(wù)實(shí)施實(shí)施設(shè)備部署了Arduino開(kāi)發(fā)環(huán)境的計(jì)算機(jī)。實(shí)施過(guò)程1.下載示例StringToInt程序如下:StringinString="";//stringtoholdinputvoidsetup(){//Openserialcommunicationsandwaitforporttoopen:Serial.begin(9600);while(!Serial){;//waitforserialporttoconnect.NeededfornativeUSBportonly}//sendanintro:Serial.println("\n\nStringtoInt():");Serial.println();}voidloop(){//Readserialinput:while(Serial.available()>0){intinChar=Serial.read();if(isDigit(inChar)){//converttheincomingbytetoacharandaddittothestring:inString+=(char)inChar;}三、任務(wù)實(shí)施//ifyougetanewline,printthestring,thenthestrings'value:if(inChar==\'n'){Serial.print("Value:");Serial.println(inString.toInt());Serial.print("String:");Serial.println(inString);//clearthestringfornewinput:inString="";}}}在setup初始化函數(shù)中,調(diào)用Serial對(duì)象的begin方法設(shè)置波特率為9600,注意與之連接的另一個(gè)設(shè)備的波特率要求一致。在loop循環(huán)函數(shù)中,調(diào)用Serial對(duì)象的available方法判斷是否收到串口數(shù)據(jù),是的話就讀取數(shù)據(jù)。Serial對(duì)象的read方法每次只讀一個(gè)字符(字節(jié)),通過(guò)While循環(huán)將串口緩沖區(qū)的所有數(shù)據(jù)全部讀取,將其中滿足數(shù)字格式的字符(如“2”)拼接為字符串inString。如果遇到結(jié)束符(換行符),則調(diào)用Serial的print和println方法打印調(diào)試信息。三、任務(wù)實(shí)施2.運(yùn)行效果下載程序后,打開(kāi)串口監(jiān)視器,波特率設(shè)為9600,效果如圖1-13所示。圖1-13數(shù)據(jù)收發(fā)工作效果從電腦發(fā)送字符串"12"到ESP32的Serial串口,ESP32將接收的字符串轉(zhuǎn)為數(shù)字后按照格式"Value:12"發(fā)送給電腦。如果電腦發(fā)送的字符串中不包含數(shù)字部分,則功能不能實(shí)現(xiàn)。四、任務(wù)小結(jié)與練習(xí)任務(wù)小結(jié)任務(wù)3編寫(xiě)一個(gè)工程,利用串口打印和讀取串口數(shù)據(jù)的方法,測(cè)試數(shù)據(jù)接收功能。修改程序中的波特率為115200,觀察串口監(jiān)視器接收區(qū)工作情況;再設(shè)置串口監(jiān)視器的波特率為115200,觀察運(yùn)行情況。實(shí)踐練習(xí)謝謝聆聽(tīng)2相關(guān)知識(shí)34任務(wù)小結(jié)與練習(xí)1任務(wù)實(shí)施任務(wù)引入與目標(biāo)串口接收事件處理一、任務(wù)引入與目標(biāo)任務(wù)目標(biāo)任務(wù)4將串口接收部分寫(xiě)成單獨(dú)的處理函數(shù),在loop函數(shù)中調(diào)用即可。需要約定接收字符串的結(jié)束符。任務(wù)引入任務(wù)3使用了Serial,做了相關(guān)配置,可以進(jìn)行串口讀寫(xiě)操作。但是處理過(guò)程全部放在loop函數(shù)中,不清晰。如果將串口接收部分寫(xiě)成單獨(dú)的處理函數(shù),會(huì)更加方便。二、相關(guān)知識(shí)串口初始化方法(以Serial對(duì)象為例)語(yǔ)法:Serial.begin(speed,config)參數(shù):speed,波特率,一般取值9600、115200;config:設(shè)置數(shù)據(jù)位、校驗(yàn)位和停止位,默認(rèn)SERIAL_8N1表示8個(gè)數(shù)據(jù)位,無(wú)校驗(yàn)位,1個(gè)停止位。返回值:無(wú)。如果對(duì)Serial2進(jìn)行初始化,則只需要把對(duì)象名改為Serial2即可。下面介紹串口的常用方法,以Serial對(duì)象為例。如果Serial2使用這些方法,則只需要把對(duì)象名改為Serial2即可。串口打印方法(以Serial對(duì)象為例)語(yǔ)法:Serial.print(val)功能:串口輸出數(shù)據(jù),寫(xiě)入字符數(shù)據(jù)到串口。參數(shù):val,打印的值,任意數(shù)據(jù)類(lèi)型。與print方法類(lèi)似的,還有println方法,會(huì)自動(dòng)在打印的數(shù)據(jù)后面加上一個(gè)換行符。二、相關(guān)知識(shí)判斷串口緩沖區(qū)的狀態(tài)(以Serial對(duì)象為例)語(yǔ)法:Serial.available()功能:判斷串口緩沖區(qū)的狀態(tài),返回從串口緩沖區(qū)讀取的字節(jié)數(shù)。參數(shù):無(wú)。返回值:可讀取的字節(jié)數(shù)。讀取串口數(shù)據(jù)(以Serial對(duì)象為例)語(yǔ)法:Serial.read()功能:讀取串口數(shù)據(jù),一次讀一個(gè)字符,讀完后刪除已讀數(shù)據(jù)。參數(shù):無(wú)。返回值:返回串口緩存中第一個(gè)可讀字節(jié),當(dāng)沒(méi)有可讀數(shù)據(jù)時(shí)返回-1,整數(shù)類(lèi)型。三、任務(wù)實(shí)施實(shí)施設(shè)備部署了Arduino開(kāi)發(fā)環(huán)境的計(jì)算機(jī)。實(shí)施過(guò)程1.硬件連接硬件只要用USB線將ESP32和計(jì)算機(jī)連接即可,如圖1-14所示。圖1-14任務(wù)4硬件連接示意圖三、任務(wù)實(shí)施voidserialEvent(){while(Serial.available()){//getthenewbyte:charinChar=(char)Serial.read();//addittotheinputString:inputString+=inChar;//iftheincomingcharacterisanewline,setaflagsothemainloopcan//dosomethingaboutit:if(inChar==\'n'){stringComplete=true;}}}編寫(xiě)SerialEvent函數(shù),調(diào)用Serial對(duì)象的available方法判斷是否收到串口數(shù)據(jù),是的話就讀取數(shù)據(jù)。Serial對(duì)象的read方法每次只讀一個(gè)字符(字節(jié)),通過(guò)While循環(huán)將串口緩沖區(qū)的所有數(shù)據(jù)全部讀取,拼接為字符串inputString。如果遇到結(jié)束符(換行符),則將標(biāo)志stringComplete設(shè)置為真(代表接收到完整字符串inputString),供接下來(lái)的loop函數(shù)查詢(xún)判斷。2.編寫(xiě)SerialEvent函數(shù)如果緩沖器有串口數(shù)據(jù),則將其中的字符一個(gè)一個(gè)放入字符串inputString里。三、任務(wù)實(shí)施StringinputString="";//aStringtoholdincomingdataboolstringComplete=false;//whetherthestringiscompletevoidsetup(){//initializeserial:Serial.begin(9600);//reserve200bytesfortheinputString:inputString.reserve(200);}voidloop(){//printthestringwhenanewlinearrives:if(stringComplete){Serial.print(inputString);//clearthestring:inputString="";stringComplete=false;}serialEvent();}程序中定義了2個(gè)變量,inputString用于存放接收的字符串,stringComplete是接收完成的標(biāo)志,在SerialEvent函數(shù)中已經(jīng)介紹過(guò)。在setup函數(shù)中,調(diào)用Serial的begin方法,設(shè)置波特率為9600。在loop函數(shù)中,判斷stringComplete是否為真(串口數(shù)據(jù)完成)。如果為真,則對(duì)inputString做進(jìn)一步處理,最后清除inputString的值和stringComplete標(biāo)志位。3.setup和loop函數(shù)三、任務(wù)實(shí)施4.運(yùn)行效果下載程序后,打開(kāi)串口監(jiān)視器,設(shè)置波特率為9600。從串口監(jiān)視器的發(fā)送區(qū)輸入任意字符串發(fā)送,在接收區(qū)可觀察到與發(fā)送內(nèi)容相同的字符串,如圖1-15所示。圖1-15任務(wù)4運(yùn)行效果四、任務(wù)小結(jié)與練習(xí)任務(wù)小結(jié)任務(wù)4將串口接收部分寫(xiě)成單獨(dú)的處理函數(shù)serialEvent,當(dāng)接收完畢后,在loop函數(shù)中調(diào)用即可,實(shí)現(xiàn)了串口數(shù)據(jù)的收發(fā)功能,程序結(jié)構(gòu)清晰。用戶如果想使用Serial2,則只需要將程序中的Serial對(duì)象名稱(chēng)修改為Serial2即可。修改程序中的波特率為115200,觀察運(yùn)行情況。實(shí)現(xiàn)大寫(xiě)變小寫(xiě),Serial將計(jì)算機(jī)發(fā)來(lái)的字符串發(fā)回,但如果其中有大寫(xiě)字符,則將其轉(zhuǎn)換為小寫(xiě)字符。實(shí)踐練習(xí)謝謝聆聽(tīng)2相關(guān)知識(shí)34任務(wù)小結(jié)與練習(xí)1任務(wù)實(shí)施任務(wù)引入與目標(biāo)Arduino程序中的JSON解析一、任務(wù)引入與目標(biāo)任務(wù)目標(biāo)任務(wù)5通過(guò)計(jì)算機(jī)向ESP32的串口發(fā)送滿足JSON對(duì)象格式的字符串,ESP32收到后解析并控制LED燈。使用ArduinoJson庫(kù)對(duì)接收的數(shù)據(jù)進(jìn)行解析。任務(wù)引入通過(guò)serialEvent函數(shù)的設(shè)計(jì),程序很清晰。接下來(lái),我們思考怎樣把解析過(guò)程變得清晰起來(lái),可以用到JSON數(shù)據(jù)格式。這是一種跨語(yǔ)言的數(shù)據(jù)格式,C語(yǔ)言、Java、JavaScript都要使用,會(huì)貫穿于網(wǎng)關(guān)設(shè)計(jì)、APP設(shè)計(jì)和后端設(shè)計(jì)全過(guò)程。二、相關(guān)知識(shí)JSON對(duì)象數(shù)據(jù)格式JavaScript對(duì)象表示法(JavaScriptObjectNotation)是一種輕量級(jí)的文本數(shù)據(jù)交換格式。它獨(dú)立于語(yǔ)言,具有自我描述性,容易被理解和使用。比如一個(gè)JSON對(duì)象:{"motor":{"left":100,"right":20},"servo":{"servo_a":90}}。其中,有兩個(gè)成員(也是JSON對(duì)象),分別是motor、servo。JSON對(duì)象的成員是鍵值對(duì),鍵和值之間用冒號(hào)分隔,鍵值對(duì)之間用逗號(hào)分隔。ArduinoJson庫(kù)的構(gòu)造類(lèi)在Arduino中解析JSON數(shù)據(jù),可以交給ArduinoJson庫(kù)處理,但一定是從外到里一層層地獲取。JsonBuffer作為ArduinoJson庫(kù)的入口,負(fù)責(zé)處理整個(gè)JSON數(shù)據(jù)的內(nèi)存管理以及構(gòu)造解析工作,它包括兩個(gè)實(shí)現(xiàn)類(lèi):二、相關(guān)知識(shí)(1)DynamicJsonBuffer,內(nèi)存分配在heap區(qū),無(wú)固定大小,可以自動(dòng)增長(zhǎng)所需空間,方法調(diào)用完自動(dòng)回收;(2)StaticJsonBuffer,內(nèi)存分配在stack區(qū),有固定大小,大小值由開(kāi)發(fā)者定義,方法調(diào)用完自動(dòng)回收。JsonBuffer對(duì)象的方法(1)parseObject方法:功能是將字符串轉(zhuǎn)換為JSON對(duì)象。能否轉(zhuǎn)換成功,要看字符串本身是否滿足JSON對(duì)象格式。(2)Success方法:判斷JSON對(duì)象是否有效。很明顯,parseObject方法后面應(yīng)該有一個(gè)Success方法進(jìn)行判斷,然后進(jìn)行解析才有意義。三、任務(wù)實(shí)施實(shí)施設(shè)備部署了Arduino開(kāi)發(fā)環(huán)境的計(jì)算機(jī)。實(shí)施過(guò)程1.工程目標(biāo)對(duì)一個(gè)成員的JSON對(duì)象解析工程名為OneKeyValue,串口接收符合JSON對(duì)象格式的字符串,通過(guò)ArduinoJson庫(kù)進(jìn)行解析。假如串口收到字符串{"LightStatus":1},點(diǎn)亮燈;收到字符串{"LightStatus":0},熄滅燈;收到其他字符串(不滿足JSON對(duì)象格式),不處理。可見(jiàn),JSON對(duì)象里只有一個(gè)成員,鍵(字段)是“LightStatus”。三、任務(wù)實(shí)施#include<ArduinoJson.h>StringinputString="";//aStringtoholdincomingdataboolstringComplete=false;//whetherthestringiscomplete//引腳定義#defineLIGHT25//產(chǎn)品標(biāo)識(shí)符StringIdentifier="LightStatus";voidsetup(){//initializeserial:Serial.begin(9600);//reserve200bytesfortheinputString:inputString.reserve(200);pinMode(LIGHT,OUTPUT);}2.程序設(shè)計(jì)voidloop(){//printthestringwhenanewlinearrives:if(stringComplete){Serial.println(inputString);//解析,控制,約定Json格式:{"LightStatus":1},{"LightStatus":0}StaticJsonBuffer<200>jsonBuffer;JsonObject&root=jsonBuffer.parseObject(inputString);if(!root.success()){Serial.println("parseObject()failed");inputString="";stringComplete=false;return;}constchar*val=root[Identifier];三、任務(wù)實(shí)施if(val!=NULL){constuint16_tLightStatus=root[Identifier];if(LightStatus==1){digitalWrite(LIGHT,HIGH);}else{digitalWrite(LIGHT,LOW);}Serial.print("LightStatus:");Serial.println(LightStatus);}//clearthestring:inputString="";stringComplete=false;}serialEvent();}voidserialEvent(){while(Serial.available()){//getthenewbyte:charinChar=(char)Serial.read();//addittotheinputString:inputString+=inChar;//iftheincomingcharacterisanewline,setaflagsothemainloopcan//dosomethingaboutitif(inChar==\'n'){stringComplete=true;}}}三、任務(wù)實(shí)施我們下面主要分析loop函數(shù)中的解析過(guò)程:當(dāng)串口接收到字符串inputString后,調(diào)用jsonBuffer對(duì)象的parseObject,將字符串轉(zhuǎn)為JSON對(duì)象root,可能成功,也可能不成功。調(diào)用root對(duì)象的success方法,判斷root是否是JSON對(duì)象:如果不是JSON對(duì)象,則沒(méi)有必要進(jìn)行解析了,清除inputString和標(biāo)志后返回;如果是JSON對(duì)象,則執(zhí)行接下來(lái)的解析過(guò)程。解析過(guò)程中,取出JSON對(duì)象“LightStatus”字段的值,如果非空,第二次取出后,根據(jù)值控制LED的亮和滅。在以上解析過(guò)程中,需要注意兩點(diǎn):一是先轉(zhuǎn)換再解析,轉(zhuǎn)換過(guò)程可能不成功;二是解析兩次,避免未收到命令即解析值為NULL,但賦值為0,控制LED熄滅的錯(cuò)誤操作。3.硬件連接LED燈的數(shù)據(jù)引腳連接IO25。下載線連接,因?yàn)镋SP32開(kāi)發(fā)板有USB轉(zhuǎn)串口芯片CP2102,將USB口轉(zhuǎn)為串口Serial,也就是說(shuō)本任務(wù)中ESP32使用的是Serial。三、任務(wù)實(shí)施4.運(yùn)行效果下載程序后,打開(kāi)串口監(jiān)視器,波特率為9600。計(jì)算機(jī)發(fā)送字符串:{"LightStatus":1}(后面加上換行符作為結(jié)束符),紅燈點(diǎn)亮,并且串口監(jiān)視器接收區(qū)顯示:LightStatus:1,效果如圖1-16所示。圖1-16點(diǎn)亮紅燈三、任務(wù)實(shí)施計(jì)算機(jī)發(fā)送字符串{"LightStatus":0}(后面加上換行符作為結(jié)束符),紅燈熄滅,并且串口監(jiān)視器接收區(qū)顯示LightStatus:0,效果如圖117所示。圖117關(guān)閉紅燈四、任務(wù)小結(jié)與練習(xí)任務(wù)小結(jié)任務(wù)5中通過(guò)計(jì)算機(jī)往ESP32的串口發(fā)送滿足JSON對(duì)象格式的字符串,由一個(gè)成員構(gòu)成。ESP32收到后,使用ArduinoJson庫(kù)解析,并控制LED燈。計(jì)算機(jī)發(fā)送滿足JSON對(duì)象格式的字符串,如{"Light":1}和{"Light":0},修改程序解析,觀察結(jié)果。注意字符串后面加上換行符作為結(jié)束符,雙引號(hào)是在英文輸入法狀態(tài)下輸入的。實(shí)踐練習(xí)謝謝聆聽(tīng)2相關(guān)知識(shí)34任務(wù)小結(jié)與練習(xí)1任務(wù)實(shí)施任務(wù)引入與目標(biāo)多成員JSON對(duì)象的JSON解析一、任務(wù)引入與目標(biāo)任務(wù)目標(biāo)任務(wù)6對(duì)串口接收的JSON對(duì)象格式數(shù)據(jù)進(jìn)行解析,串口收到的字符串可能是:針對(duì)1個(gè)燈的:{"RedStatus":1}或{"RedStatus":0},{"BlueStatus":1}或{"BlueStatus":0}。針對(duì)2個(gè)燈的:{"RedStatus":1,"BlueStatus":0}或{"RedStatus":1,"BlueStatus":1},{"RedStatus":0,"BlueStatus":0}或{"RedStatus":0,"BlueStatus":1}。我們只有通過(guò)合理的設(shè)計(jì),才能避免類(lèi)似這個(gè)錯(cuò)誤:發(fā)送控制紅燈命令時(shí),藍(lán)燈卻熄滅了。任務(wù)引入任務(wù)5通過(guò)對(duì)由一個(gè)成員組成的JSON對(duì)象數(shù)據(jù)的解析,實(shí)現(xiàn)了對(duì)LED的控制。如果希望控制多個(gè)燈、多個(gè)設(shè)備,那就需要由多個(gè)成員組成的JSON對(duì)象數(shù)據(jù)。二、相關(guān)知識(shí)字符串對(duì)象使用字符串對(duì)象的好處是可以方便地進(jìn)行字符串的拼接和處理。例如,要定義一個(gè)字符串對(duì)象并將其初始化為“HelloWorld!”,可以使用以下代碼:StringmyString="HelloWorld!";注意,在使用字符串對(duì)象時(shí)需要注意內(nèi)存的分配,因?yàn)樽址畬?duì)象會(huì)動(dòng)態(tài)分配內(nèi)存。如果不小心使用了太多的字符串對(duì)象,則可能會(huì)導(dǎo)致內(nèi)存耗盡而程序崩潰。字符數(shù)組使用字符數(shù)組定義字符串可以避免上述問(wèn)題,但與字符串對(duì)象相比,它更難以操作和處理。例如,要定義一個(gè)字符數(shù)組并將其初始化為“HelloWorld!”,可以使用以下代碼:charmyString[]="HelloWorld!";需要注意的是,字符數(shù)組的長(zhǎng)度需要足夠容納所存儲(chǔ)的字符串,而且在定義后無(wú)法動(dòng)態(tài)調(diào)整大小。在Arduino中,可以使用字符串對(duì)象、字符數(shù)組或字符串指針來(lái)定義字符串。二、相關(guān)知識(shí)字符串指針在Arduino中,我們可以通過(guò)指針來(lái)定義字符串。這種方法與字符數(shù)組的方式類(lèi)似,但使用指針可以更好地控制和操作內(nèi)存。例如,要定義一個(gè)指向字符串常量“Hello
World!”的指針,可以使用以下代碼:constchar*myString="HelloWorld!";在這個(gè)例子中,我們使用了const關(guān)鍵字來(lái)指定myString指針?biāo)赶虻淖址且粋€(gè)常量,并且不允許修改。需要注意的是,當(dāng)使用指針定義字符串時(shí),必須確保所指向的內(nèi)存不會(huì)被意外修改,否則可能會(huì)導(dǎo)致程序出現(xiàn)未知錯(cuò)誤。因此,在使用指針定義字符串時(shí),我們應(yīng)該盡可能避免對(duì)它們進(jìn)行寫(xiě)入操作。三、任務(wù)實(shí)施實(shí)施設(shè)備部署了Arduino開(kāi)發(fā)環(huán)境的計(jì)算機(jī)。實(shí)施過(guò)程1.程序設(shè)計(jì)代碼如下:#include<ArduinoJson.h>StringinputString="";//aStringtoholdincomingdataboolstringComplete=false;//whetherthestringiscomplete//引腳定義#defineLIGHT_RED25#defineLIGHT_BLUE26//產(chǎn)品標(biāo)識(shí)符StringIdentifier1="RedStatus";StringIdentifier2="BlueStatus";voidsetup(){//initializeserial:Serial.begin(9600);//reserve200bytesfortheinputString:inputString.reserve(200);pinMode(LIGHT_RED,OUTPUT);pinMode(LIGHT_BLUE,OUTPUT);}三、任務(wù)實(shí)施voidloop(){//printthestringwhenanewlinearrives:if(stringComplete){Serial.println(inputString);//解析,控制,約定JSON格式//紅燈:{"RedStatus":1},{"RedStatus":0}//藍(lán)燈:{"BlueStatus":1},{"BlueStatus":0}//針對(duì)2個(gè)燈:{"RedStatus":1,"BlueStatus":1},{"RedStatus":0,"BlueStatus":0}StaticJsonBuffer<200>jsonBuffer;JsonObject&root=jsonBuffer.parseObject(inputString);2.程序設(shè)計(jì)if(!root.success()){Serial.println("parseObject()failed");inputString="";stringComplete=false;return;}constchar*val1=root[Identifier1];constchar*val2=root[Identifier2];if(val1!=NULL){constuint16_tRedStatus=root[Identifier1];if(RedStatus==1){digitalWrite(LIGHT_RED,HIGH);}else{digitalWrite(LIGHT_RED,LOW);}Serial.print("RedStatus:");Serial.println(RedStatus);}三、任務(wù)實(shí)施if(val2!=NULL){constuint16_tBlueStatus=root[Identifier2];if(BlueStatus==1){digitalWrite(LIGHT_BLUE,HIGH);}else{digitalWrite(LIGHT_BLUE,LOW);}Serial.print("BlueStatus:");Serial.println(BlueStatus);}//clearthestring:inputString="";stringComplete=false;}serialEvent();}voidserialEvent(){while(Serial.available()){//getthenewbyte:charinChar=(char)Serial.read();//addittotheinputString:inputString+=inChar;//iftheincomingcharacterisanewline,setaflagsothemainloopcan//dosomethingaboutitif(inChar==\'n'){stringComplete=true;}}}三、任務(wù)實(shí)施和任務(wù)5中的代碼相比,本任務(wù)初始化、解析都是針對(duì)多個(gè)燈,但基本的邏輯是一樣的。簡(jiǎn)要介紹一下:一是先轉(zhuǎn)換再解析,轉(zhuǎn)換過(guò)程可能不成功,程序中通過(guò)success方法判斷root對(duì)象是否是JSON對(duì)象;二是解析兩次,避免收到控制紅燈命令時(shí)關(guān)閉藍(lán)燈的誤操作,也避免了收到控制藍(lán)燈命令時(shí)關(guān)閉紅燈的誤操作。3.運(yùn)行效果硬件方面,ESP32接三色燈的2個(gè)數(shù)據(jù)引腳即可,其中IO25接R引腳,IO26接B引腳。下載程序后,打開(kāi)串口監(jiān)視器,波特率為9600;發(fā)送不同的JSON數(shù)據(jù),經(jīng)解析和處理后,可以看到不同的顏色,如圖1-18所示。圖1-18不同顏色燈控制效果四、任務(wù)小結(jié)與練習(xí)任務(wù)小結(jié)任務(wù)6對(duì)串口接收的JSON對(duì)象格式數(shù)據(jù)進(jìn)行解析,串口收到的字符串是由多個(gè)成員組成的,就可以用來(lái)控制多個(gè)燈。觀察不同命令時(shí)LED的顏色變化。實(shí)踐練習(xí)謝謝聆聽(tīng)2相關(guān)知識(shí)34任務(wù)小結(jié)與練習(xí)1任務(wù)實(shí)施任務(wù)引入與目標(biāo)ESP32的Serial2操作一、任務(wù)引入與目標(biāo)任務(wù)目標(biāo)任務(wù)7實(shí)現(xiàn)串口設(shè)備A的按鍵按下后,通過(guò)Serial2發(fā)送控制命令給串口設(shè)備B。其中,A設(shè)備以JSON格式發(fā)送字符串,B設(shè)備接收解析后控制LED亮滅。任務(wù)引入前面幾個(gè)任務(wù)都是針對(duì)Serial操作的,Serial比較適合用于程序打印調(diào)試信息。如果要進(jìn)行與其他串口設(shè)備的串口通信,則使用Serial2串口是比較方便的。二、相關(guān)知識(shí)Arduino中的宏定義在Arduino中,宏定義是一種預(yù)處理指令,可以用來(lái)創(chuàng)建常量或簡(jiǎn)化代碼。通過(guò)宏定義,程序員可以在程序中使用自定義的符號(hào)來(lái)代替常量或表達(dá)式。例如:#defineLED_PIN13該宏定義13為L(zhǎng)ED_PIN,這樣我們就可以在程序中使用LED_PIN來(lái)代替數(shù)字13。如果我們要改變使用的引腳,則只需要修改這個(gè)宏定義,而不需要修改整個(gè)程序。強(qiáng)制類(lèi)型轉(zhuǎn)換在Arduino中,強(qiáng)制類(lèi)型轉(zhuǎn)換是將一種數(shù)據(jù)類(lèi)型的值轉(zhuǎn)換為另一種數(shù)據(jù)類(lèi)型的值的過(guò)程。強(qiáng)制類(lèi)型轉(zhuǎn)換可以幫助我們?cè)诓煌瑪?shù)據(jù)類(lèi)型之間進(jìn)行轉(zhuǎn)換,并允許我們使用不同的算術(shù)和邏輯操作。比較常見(jiàn)的是C語(yǔ)言風(fēng)格的強(qiáng)制類(lèi)型轉(zhuǎn)換,這種轉(zhuǎn)換使用括號(hào)將要轉(zhuǎn)換的值包圍起來(lái),并指定要轉(zhuǎn)換的目標(biāo)類(lèi)型。例如:intx=10;floaty=(float)x;在這個(gè)例子中,我們將整數(shù)變量x強(qiáng)制轉(zhuǎn)換為浮點(diǎn)數(shù),并將結(jié)果存儲(chǔ)在浮點(diǎn)型變量y中。三、任務(wù)實(shí)施實(shí)施設(shè)備部署了Arduino開(kāi)發(fā)環(huán)境的計(jì)算機(jī)。實(shí)施過(guò)程1.硬件連接串口的引腳可以查看表1-2。引腳連接如下:Button_out———ESP32A_IO26
Button_GND———ESP32A_GNDButton_VCC———ESP32A_VCC
ESP32A_IO17———ESP32B_IO16ESP32A_IO16———ESP32B_IO17
ESP32A_GND———ESP32B_GNDLED_R———ESP32B_IO25
LED_GND———ESP32B_GND串口名Arduino名TXRXUART0Serialpin1(TXD0)pin3(RXD0)UART1Serial1pin10pin9UART2Serial2pin17pin16表1-2ESP32的串口引腳三、任務(wù)實(shí)施連接示意如圖1-19所示。實(shí)物連接如圖1-20所示。圖1-19任務(wù)7硬件連接示意圖圖1-20任務(wù)7硬件連接實(shí)物圖三、任務(wù)實(shí)施constintbuttonPin=26;//thenumberofthepushbuttonpinintbuttonState=0;//variableforreadingthepushbuttonstatusuint16_tLightStatus=0;voidsetup(){Serial.begin(9600);Serial2.begin(9600);pinMode(buttonPin,INPUT);}voidloop(){buttonState=digitalRead(buttonPin);}2.設(shè)備A程序(1)按鍵檢測(cè)。在02-Button的示例程序基礎(chǔ)上修改,代碼如下:if(buttonState==HIGH){if(LightStatus==0){Serial2.print("{\"LightStatus\":0}\n");Serial.print("{\"LightStatus\":0}\n");LightStatus=1;}else{Serial2.print("{\"LightStatus\":1}\n");Serial.print("{\"LightStatus\":1}\n");LightStatus=0;}}三、任務(wù)實(shí)施下載運(yùn)行,發(fā)現(xiàn)每按下一次,設(shè)備A的Serial會(huì)打印很多條內(nèi)容,說(shuō)明按下一次會(huì)檢測(cè)到多次,如圖1-21所示。這是什么原因呢?需要了解一下按鍵的知識(shí),如圖1-22所示。從按鍵按下之后輸出電平的變化可知:對(duì)按鍵的檢測(cè),需要考慮干擾情況(需要延時(shí)再檢測(cè)),再考慮按鍵長(zhǎng)按的情況(需要等待釋放)。圖1-21打印按鍵檢測(cè)結(jié)果圖1-22按鍵電路輸出電平變化情況三、任務(wù)實(shí)施constintbuttonPin=26;//thenumberofthepushbuttonpinintbuttonState=0;//variableforreadingthepushbuttonstatusuint16_tLightStatus=0;voidsetup(){Serial.begin(9600);Serial2.begin(9600);pinMode(buttonPin,INPUT);}(2)增加消抖和等待釋放處理的按鍵檢測(cè)。在上面分析的基礎(chǔ)上,修改代碼如下:voidloop(){//buttonState=digitalRead(buttonPin);if(digitalRead(buttonPin)==HIGH){delay(10);//延時(shí)消抖if(digitalRead(buttonPin)==HIGH){while(digitalRead(buttonPin));//等
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 《JBT 13920-2020 30°楔形防松螺紋絲錐》專(zhuān)題研究報(bào)告
- 唐和恩和一根小竹竿課件
- 2024年珙縣幼兒園教師招教考試備考題庫(kù)附答案解析(奪冠)
- 2024年蚌埠工商學(xué)院馬克思主義基本原理概論期末考試題帶答案解析
- 2025年淶水縣幼兒園教師招教考試備考題庫(kù)含答案解析(奪冠)
- 2025年華北科技學(xué)院馬克思主義基本原理概論期末考試模擬題含答案解析(奪冠)
- 2025年岷縣幼兒園教師招教考試備考題庫(kù)附答案解析(必刷)
- 2025年溫州理工學(xué)院?jiǎn)握新殬I(yè)傾向性考試題庫(kù)帶答案解析
- 無(wú)錫市2025-2026學(xué)年(上期)高三期末考試政治試卷(含答案)
- 2024年絳縣幼兒園教師招教考試備考題庫(kù)帶答案解析(必刷)
- 2026年工程監(jiān)理招聘面試常見(jiàn)問(wèn)題集
- 航運(yùn)電子商務(wù)行業(yè)發(fā)展前景分析及物流配送體系創(chuàng)新與商業(yè)模式研究
- 2025年陜西中考語(yǔ)文試卷副題及答案
- 腦癱兒童護(hù)理中的職業(yè)治療
- 心理治療方案在消化系統(tǒng)疾病患者中的應(yīng)用
- 篩分設(shè)備安裝施工詳細(xì)方案
- 2025年低空經(jīng)濟(jì)行業(yè)災(zāi)害應(yīng)急演練與評(píng)估報(bào)告
- 醫(yī)美院感知識(shí)培訓(xùn)課件
- 綠色交通系統(tǒng)1000輛新能源公交車(chē)推廣可行性研究報(bào)告
- 拜師儀式流程及主持稿
- 廠用電安全知識(shí)培訓(xùn)課件
評(píng)論
0/150
提交評(píng)論