SPI通訊主從機(jī)程序?qū)崿F(xiàn)(軟件模擬和硬件)
??????????????????????????????????????????????前言
????寫(xiě)這篇文章算是拋磚引玉,希望有更多人來(lái)寫(xiě),雖然可能理解不到位,但是如果能多些人一起討論,形成氛圍是有好處的,工程人員是國(guó)家的剛需,哪個(gè)行業(yè)不行了理工科總有口飯吃,相應(yīng)的代價(jià)就是枯燥、煩躁,聰明人不一定坐得住,能多一個(gè)算一個(gè)吧。
? ? 關(guān)于后面的實(shí)現(xiàn),我使用的是SN8F5702--主機(jī)--模擬/軟件SPI、SN8F5909芯片--從機(jī)--硬件SPI,其他的實(shí)現(xiàn)方式可能有芯片特性的區(qū)別,不一定適用。? ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?基礎(chǔ)知識(shí)
????SPI基礎(chǔ)知識(shí):常見(jiàn)4條線,MOSI、MISO、STE、CLK這4個(gè),M是master主機(jī),S是Slave從機(jī),I是Input,O是Out,主機(jī)的輸出就是從機(jī)的輸入方向。SS是片選信號(hào),還有STE,SSN的叫法,選擇你通訊的對(duì)象,一般信號(hào)拉低時(shí)選擇器件,拉高時(shí)SPI不通訊。CLK-clock,和IIC一樣用這個(gè)信號(hào)來(lái)做到數(shù)據(jù)同步。SPI占用IO口多,速度也是最快的,它的限制是看你使用器件中最低的那一個(gè),就像CPU的頻率可以很快,但是他的外設(shè)達(dá)不到那個(gè)速度往往要分頻降頻來(lái)輸入外設(shè)。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
????????????????????????????????????????硬件部分
????關(guān)于程序?qū)崿F(xiàn)的思路和需求,我們從硬件講起,做單片機(jī)的都是先硬件后軟件,千萬(wàn)不要因?yàn)椴簧瞄L(zhǎng)怕硬件就不去想,這樣容易踩坑和走彎路,軟件設(shè)計(jì)基于硬件之上,很多時(shí)候你發(fā)現(xiàn)效果不一樣是忽略了硬件、手冊(cè)的結(jié)果,就像用家電不看廠家手冊(cè)一樣,都是壞習(xí)慣。
????硬件需求:我測(cè)試過(guò)的實(shí)現(xiàn)方式是SN8F5702是主機(jī),SN8F5909做從機(jī),主機(jī)GPIO口配置MOSI、CLK、SS推挽輸出,MISO輸入,從機(jī)就反過(guò)來(lái)MOSI、CLK、SS輸入,MISO輸出。
????我上面這個(gè)配置是因?yàn)橹鲝臋C(jī)用同系列CPU來(lái)做的,電氣特性都一致所以也可以,后來(lái)仔細(xì)想可以配的更好,如果是2個(gè)不同型號(hào)的CPU,用主機(jī)推挽輸出不變,輸入用內(nèi)置上拉;從機(jī)開(kāi)漏輸出,浮空輸入最好,這樣做的好處是統(tǒng)一讓主機(jī)提供電平,如果多個(gè)從機(jī)設(shè)備每個(gè)都推挽,那單片機(jī)可能會(huì)有各自的電平,會(huì)稍微影響穩(wěn)定性。
????用開(kāi)漏輸出加個(gè)上拉電阻應(yīng)該也可以,開(kāi)漏簡(jiǎn)單說(shuō)就是只能IO輸出低電平,高電平時(shí)本身不輸出,需要外接電源上拉電阻來(lái)供電,推挽開(kāi)漏不懂可以手冊(cè)去具體了解,看看IO口實(shí)現(xiàn)的內(nèi)部電路實(shí)現(xiàn),每款CPU手冊(cè)都有IO的硬件實(shí)現(xiàn)方式,沒(méi)有考慮過(guò)這個(gè)問(wèn)題還可以看看高電平、低電平的定義(比如0.3VDD以下為低,0.7VDD以上為高),然后在延伸了解下TTL RS232、RS485的電平特性(這是UART的),對(duì)電平的了解會(huì)進(jìn)一步增長(zhǎng)。
????????????????????????????????????????????軟件部分
? ?程序是主機(jī)軟件/模擬SPI,從機(jī)硬件SPI分別實(shí)現(xiàn)。
? ?關(guān)于硬件xx的說(shuō)法:硬件IIC、SPI是軟件實(shí)現(xiàn)的,明明是要寫(xiě)程序的卻叫硬件xx,因?yàn)閺挠布险f(shuō)這是廠家對(duì)CPU做好了集成電路,然后軟件讓用戶通過(guò)特定寄存器來(lái)操作,所以這部分歸納在軟件中,硬件xx是一種基于實(shí)現(xiàn)特性的叫法,相對(duì)的用戶自己寫(xiě)流程就是軟件/模擬xx,如軟件SPI、軟件IIC。
?? ? 硬件xx和軟件/模擬xx的優(yōu)劣,兩者性能上肯定是硬件強(qiáng),但是硬件方式你如果用了不同系列/CPU,這部分就不可移植要重做?,而軟件方式反正都是GPIO做的,只要做好了移過(guò)去改改名字就能用,移植容易,至于使用哪種就看你的需求。
????設(shè)計(jì)方式:輪詢方式實(shí)現(xiàn)主從通訊是不用中斷,讓CPU來(lái)判斷。中斷方式的做法是不占用主程,設(shè)定進(jìn)入中斷的條件來(lái)打斷原先流程。
??? 配置部分:軟件xx配置相應(yīng)GPIO的輸入輸出、上下拉、模式,前面硬件有寫(xiě)。
????硬件SPI具體要看手冊(cè),下面的一般都要有:
???1.SPI模塊和其他中斷標(biāo)志位等的使能(上面設(shè)計(jì)方式的區(qū)別,所以基本都用中斷)
? ? 2.MSB和LSB:高位先出還是低位先出
? ? 3.數(shù)據(jù)個(gè)數(shù):一次傳輸8bit還是16bit
? ? 4.CPOL(Clock?polarity)和CPHA(Clock?phase):CPOL是時(shí)鐘極性,就是空閑狀態(tài)的電平是高還是低,CPHA是時(shí)鐘相位,第1、還是第2個(gè)沿--捕獲/采樣/鎖存/有效數(shù)據(jù),附圖(松瀚SN8F系列):


????理解及自己畫(huà)時(shí)序圖:高低電平空閑很容易理解,分別畫(huà)2個(gè)clk,低-高-低和高-低-高,起始和最終狀態(tài)就是初始電平。極性是采樣的數(shù)據(jù),把前面畫(huà)好的clk*8個(gè),上升下降沿畫(huà)x代表電平變化,然后在中間劃虛線代表采樣時(shí)刻,先畫(huà)有效電平后clk也行,數(shù)據(jù)采樣的關(guān)鍵就是采樣時(shí)刻要保持穩(wěn)定,所以數(shù)據(jù)采樣前半個(gè)clk準(zhǔn)備好當(dāng)前數(shù)據(jù),后半clk準(zhǔn)備下一個(gè)數(shù)據(jù),SPI有雙線收發(fā),所以主從機(jī)可以同一時(shí)刻發(fā)收,軟件實(shí)現(xiàn)的會(huì)慢一步,而硬件上升下降的速度快很多。
????試著在不看上面的分析和時(shí)序圖自己捋出來(lái),這樣映像會(huì)深很多,還有電氣特性是硬件SPI的數(shù)據(jù)。
????數(shù)據(jù)讀寫(xiě)時(shí)機(jī):關(guān)于發(fā)送讀取時(shí)機(jī)我建議在電平前,發(fā)送的數(shù)據(jù)先準(zhǔn)備好肯定沒(méi)問(wèn)題,讀的時(shí)機(jī)要測(cè)試,有的芯片是會(huì)在發(fā)收完成后改回前面開(kāi)始的狀態(tài)的,所以也是放在之前應(yīng)該也比較好,這個(gè)放在前面中間不要插入別的部分。
? ?程序(整個(gè)工程后面鏈接發(fā),這里只關(guān)注主機(jī)的軟件模擬部分):
相關(guān)定義
/********************SPI片選信號(hào)********************/
#define SPI_SSN_HIGH P03 = 1//片選拉高
#define SPI_SSN_LOW P03 = 0//片選拉低
/********************SPI時(shí)鐘信號(hào)********************/
#define SPI_SCK_HIGH P13 = 1//時(shí)鐘拉高
#define SPI_SCK_LOW P13 = 0//時(shí)鐘拉低
/********************SPI MOSI數(shù)據(jù)********************/
#define SPI_MOSI_HIGH P14 = 1//MOSI數(shù)據(jù)拉高
#define SPI_MOSI_LOW P14 = 0//MOSI數(shù)據(jù)拉低
/********************SPI MISO數(shù)據(jù)********************/
#define SPI_MISO P15 //數(shù)據(jù)讀取
CPOL=0,CPHA=0,發(fā)送模塊
uint8_t SPISendRev(uint8_t SpiSendDate)
{
???????? uint8_t i,j;
???????? SPI_SSN_LOW;
????????
????????SPI_SCK_LOW; //初始電平,確保數(shù)據(jù)發(fā)送時(shí)時(shí)鐘是低電平
???????? for(i=0;i<8;i++)
???????? {
????????????????SPI_SCK_LOW;
???????????????? if(SpiSendDate & 0x80) //輸出數(shù)據(jù)轉(zhuǎn)bit
????????????????SPI_MOSI_HIGH; //數(shù)據(jù)發(fā)送
???????????????? else
???????????????? SPI_MOSI_LOW;
????????????????SpiSendDate <<= 1; //輸出后數(shù)據(jù)改變
????????????????
????????????????SpiRecDat <<= 1; //接收數(shù)據(jù)后改變,8位數(shù)據(jù)7次移動(dòng)
????????????????if(SPI_MISO == 1) //數(shù)據(jù)接收
????????????????SpiRecDat++;
????????????????SPI_SCK_HIGH; //拉高SCK信號(hào)觸發(fā)從機(jī)發(fā)送
???????? }
????????SPI_SCK_LOW;
????????
???????? SPI_SSN_HIGH;
???????? return SpiRecDat;
}
CPOL=0,CPHA=1,發(fā)送模塊
uint8_t SPISendRev(uint8_t SpiSendDate)
{
???????? uint8_t i,j;
???????? SPI_SSN_LOW;
????????
???????? SPI_SCK_LOW; //初始電平,確保數(shù)據(jù)發(fā)送時(shí)時(shí)鐘是低電平
???????????????? for(i=0;i<8;i++)
???????????????? {
???????????????? SPI_SCK_LOW;
???????????????? if(SpiSendDate & 0x80) //輸出數(shù)據(jù)轉(zhuǎn)bit
???????????????? SPI_MOSI_HIGH; //數(shù)據(jù)發(fā)送
???????????????? else
???????????????? SPI_MOSI_LOW;
???????????????? SpiSendDate <<= 1; //輸出后數(shù)據(jù)改變
???????????????? SPI_SCK_HIGH;
????????????????
???????????????? SpiRecDat <<= 1; //接收數(shù)據(jù)后改變,8位數(shù)據(jù)7次移動(dòng)
???????????????? if(SPI_MISO == 1) //數(shù)據(jù)接收
???????????????? SpiRecDat++;
???????????????? }
???????? SPI_SCK_LOW;
????????
???????? SPI_SSN_HIGH;
???????? return SpiRecDat;
}
CPOL=1,CPHA=0,發(fā)送模塊
uint8_t SPISendRev(uint8_t SpiSendDate)
{
???????? uint8_t i;
???????? SPI_SSN_LOW;
????????
???????? SPI_SCK_HIGH; //初始電平,確保數(shù)據(jù)發(fā)送時(shí)時(shí)鐘是低電平
???????????????? for(i=0;i<8;i++)
???????????????? {
???????????????? SPI_SCK_HIGH; //拉高SCK信號(hào)觸發(fā)從機(jī)發(fā)送
???????????????? if(SpiSendDate & 0x80) //輸出數(shù)據(jù)轉(zhuǎn)bit
???????????????? SPI_MOSI_HIGH; //數(shù)據(jù)發(fā)送
???????????????? else
???????????????? SPI_MOSI_LOW;
???????????????? SpiSendDate <<= 1; //輸出后數(shù)據(jù)改變
????????????????
???????????????? SpiRecDat <<= 1; //接收數(shù)據(jù)后改變,8位數(shù)據(jù)7次移動(dòng)
???????????????? if(SPI_MISO == 1) //數(shù)據(jù)接收
???????????????? SpiRecDat++;
???????????????? SPI_SCK_LOW;
???????? }
???????? SPI_SCK_HIGH;
????????
???????? SPI_SSN_HIGH;
???????? return SpiRecDat;
}
CPOL=1,CPHA=1,發(fā)送模塊
uint8_t SPISendRev(uint8_t SpiSendDate)
{
???????? uint8_t i;
????????SPI_SSN_LOW;
????????
???????? SPI_SCK_HIGH; //初始電平,確保數(shù)據(jù)發(fā)送時(shí)時(shí)鐘是低電平
???????????????? for(i=0;i<8;i++)
???????????????? {
???????????????? if(SpiSendDate & 0x80) //輸出數(shù)據(jù)轉(zhuǎn)bit
???????????????? SPI_MOSI_HIGH; //數(shù)據(jù)發(fā)送
???????????????? else
???????????????? SPI_MOSI_LOW;
???????????????? SpiSendDate <<= 1; //輸出后數(shù)據(jù)改變
???????????????? SPI_SCK_LOW; //拉高SCK信號(hào)觸發(fā)從機(jī)發(fā)送
????????????????
???????????????? SpiRecDat <<= 1; //接收數(shù)據(jù)后改變,8位數(shù)據(jù)7次移動(dòng)
???????????????? if(SPI_MISO == 1) //數(shù)據(jù)接收
???????????????? SpiRecDat++;
???????????????? SPI_SCK_HIGH;
???????????????? }
???????? SPI_SCK_HIGH;
????????
????????SPI_SSN_HIGH;
???????? return SpiRecDat;
}
????畫(huà)好了時(shí)序圖后就是GPIO模擬的程序?qū)懛?如上是CPOL=0和CPHA=0,需要特別關(guān)注CPHA=0--第一個(gè)沿采樣,因?yàn)榘辞懊嬲f(shuō)的發(fā)送數(shù)據(jù)是要等clk到來(lái)的,第一個(gè)沿卻要先采集數(shù)據(jù)而clk還沒(méi)來(lái),怎么整?答案是從機(jī)在SSN片選信號(hào)下降沿之后一段時(shí)間就自己發(fā)送了。
????該配置下主機(jī)第一CLK上升沿發(fā)收第1個(gè)數(shù)據(jù),在第一CLK下降沿發(fā)第2個(gè)數(shù)據(jù),后面每個(gè)CLK下降沿都發(fā)數(shù)據(jù),因此實(shí)際在第七個(gè)CLK下降沿就發(fā)完了數(shù)據(jù),第八個(gè)CLK上升沿從機(jī)接收完成。流程如下:
主機(jī)控制SSN拉低-從機(jī)MISO發(fā)數(shù)據(jù)-主機(jī)MOSI發(fā)數(shù)據(jù)-主機(jī)采樣-主機(jī)CLK上升沿-從機(jī)采樣-CLK拉低電平-進(jìn)入下一流程主機(jī)MOSI發(fā)第二個(gè)數(shù)據(jù)
????上面這個(gè)流程有人會(huì)發(fā)現(xiàn),我寫(xiě)的主機(jī)沒(méi)有等CLK上升沿到來(lái)就發(fā)收數(shù)據(jù),然后CLK上升沿從機(jī)接收,只看主機(jī)就是上升沿后立即下降沿,CLK高低電平時(shí)間長(zhǎng)短不一看著難受,這個(gè)就還要談到芯片特性(我不清楚其他芯片是否這樣),因?yàn)槲覝y(cè)試中發(fā)現(xiàn)從機(jī)的MISO配置初始電平有影響,硬件的SPI會(huì)在發(fā)MISO數(shù)據(jù)的時(shí)候改變電平,接著再完成所有數(shù)據(jù)的時(shí)候--第七上升沿接收完成時(shí),把電平改回去,我沒(méi)有發(fā)現(xiàn)這個(gè)問(wèn)題就把主機(jī)收MISO數(shù)據(jù)放在上升沿后,結(jié)果就是硬件SPI完成收發(fā)后把數(shù)據(jù)改回去,等于最后1bit沒(méi)收到,表現(xiàn)出來(lái)就是根據(jù)數(shù)據(jù)會(huì)收發(fā)不到數(shù)據(jù),假如你發(fā)的最后數(shù)據(jù)和MISO跳變開(kāi)始前電平一致,這個(gè)數(shù)據(jù)就不會(huì)錯(cuò),這個(gè)結(jié)論是示波器抓波形和程序改從機(jī)MISO初始電平測(cè)試的。
????根據(jù)下面的測(cè)試,第一個(gè)CLK1.9us前MOSI開(kāi)始發(fā)第1個(gè)數(shù)據(jù),后續(xù)每個(gè)下降沿720ns后發(fā)數(shù)據(jù),從機(jī)的MISO是第一個(gè)CLK3.4us前發(fā)第1個(gè)數(shù)據(jù),后續(xù)每個(gè)下降沿160ns后發(fā)數(shù)據(jù),SSN和MISO第一個(gè)CLK幾乎同時(shí)跳變,硬件SPI的實(shí)現(xiàn)是從機(jī)使能SPI就向SPDAT寫(xiě)數(shù)據(jù),而不是等SSN信號(hào)來(lái)了在寫(xiě),會(huì)錯(cuò)位,自己寫(xiě)軟件從機(jī)的話應(yīng)該就要等一段時(shí)間的自動(dòng)發(fā)送吧,模擬從機(jī)的程序需要測(cè)試后再說(shuō)。
????還有我試圖做只有3線版本,MOSI、MISO和SSN的,但是只有CPHA=1才能用,是因?yàn)樾枰猄SN信號(hào)來(lái)立即發(fā)送MISO吧,該配置會(huì)在第八個(gè)CLK完整發(fā)完后結(jié)束流程。
示波器測(cè)試:
黃色CLK,紫色MISO

黃色CLK,紫色MOSI

黃色CLK,紫色SSN

? ??怎么知道自己對(duì)外設(shè)的了解程度:先弄個(gè)純軟件了解流程,然后用CPU自帶的硬件再配置實(shí)現(xiàn),就可以說(shuō)完美的了解這部分,對(duì)多個(gè)CPU反復(fù)實(shí)現(xiàn)這個(gè)過(guò)程增加了解,最后上升的協(xié)議本身,當(dāng)你從手冊(cè)寫(xiě)的各種硬件、電氣特性到軟件程序你都應(yīng)對(duì)自如,你就通關(guān)了。比如IIC三種模式的速度限制是100k,400k,3.4M是已經(jīng)確定的,如果你去面試時(shí)說(shuō)出你的IIC是10M、20M人家就會(huì)一臉無(wú)語(yǔ)。
? ??軟件和硬件實(shí)現(xiàn)的坑:軟件/模擬xx因?yàn)榱鞒炭煽?,所以如果程序還有別的流程的話影響不小,要以測(cè)量為主--考慮程序框架、中斷、其他影響問(wèn)題并實(shí)測(cè)才能有具體結(jié)論,每個(gè)程序的目標(biāo)和實(shí)現(xiàn)效果不一樣,不可以想當(dāng)然泛泛而談,當(dāng)你打算用其他人現(xiàn)成程序的時(shí)候,就要做好哪里出毛病的心里準(zhǔn)備,因?yàn)槠渌俗龅某绦蚨际枪潭ê昧擞布?、軟件條件,發(fā)出來(lái)一般只會(huì)提到主要部分,中間覺(jué)得不重要的、忘記的過(guò)程就沒(méi)有說(shuō),所以最好只做參考,特別是不要忽略硬件特性。
? ? 硬件xx中每個(gè)廠家的硬件實(shí)現(xiàn)、命名方式不一樣,它的CPU手冊(cè)會(huì)自帶相關(guān)說(shuō)明,框架圖,操作方式,原理,寄存器,說(shuō)到底用人家的制作就要受制于人,聽(tīng)人安排看人手冊(cè),注意使用的細(xì)節(jié),漏細(xì)節(jié)的時(shí)候就要準(zhǔn)備頭疼好幾天了,幾幅圖一堆文字、還有細(xì)節(jié),要注意的實(shí)在太多,卡住的時(shí)候最好重新審視一下整體,細(xì)節(jié)問(wèn)題還是認(rèn)識(shí)有錯(cuò)誤,不會(huì)兩個(gè)都正確最后是流程問(wèn)題吧?這個(gè)情況最好能聯(lián)絡(luò)原廠或者懂的人溝通一下。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 其他
實(shí)現(xiàn)過(guò)程中個(gè)人遇見(jiàn)的錯(cuò)誤及原因分析:
比起SPI的問(wèn)題,我在調(diào)試過(guò)程中其他的情況反而比較多,費(fèi)了挺久的。
1.SPI的使能放在GPIO后面,影響了波形
2.GPIO沒(méi)等初始化的上拉完成就檢測(cè),限制條件沒(méi)有起作用,對(duì)于寫(xiě)的程序沒(méi)有去驗(yàn)證效果
3.SPI的數(shù)據(jù)寫(xiě)入放在SSN信號(hào)后面,導(dǎo)致數(shù)據(jù)寫(xiě)入不及時(shí)
從上面這些可以看出,我對(duì)GPIO缺少了解,GPIO就算配置了上拉也要有時(shí)間才能達(dá)到,2~7us內(nèi)還在低電平,7~15s高電平到穩(wěn)定,而我配置完就直接判斷,因此需要增加延時(shí)等電平波動(dòng),還有SPI配置在GPIO之前,那多出了CLK就會(huì)影響數(shù)據(jù)發(fā)送。
????我思考了一下一些SPI常見(jiàn)錯(cuò)誤,SPI數(shù)據(jù)不正確,最后一位錯(cuò)位移位的,找不到規(guī)律,收到了自己發(fā)送的數(shù)據(jù)的情況,整理一下也許有人需要吧。
1.數(shù)據(jù)錯(cuò)位且無(wú)規(guī)律:沒(méi)有寫(xiě)入數(shù)據(jù)或?qū)懭氲臅r(shí)間不對(duì)
2.數(shù)據(jù)錯(cuò)1位:流程寫(xiě)錯(cuò)或?qū)懭霐?shù)據(jù)的時(shí)間不對(duì),芯片特性,就像我上面也有SPI發(fā)完數(shù)據(jù)返回發(fā)送前電平的芯片特性問(wèn)題。
3.主機(jī)收到ff或00:從機(jī)沒(méi)有響應(yīng)--寫(xiě)入數(shù)據(jù)
4.收到自己發(fā)的數(shù)據(jù):我是從機(jī)SPI使能,我的除了從機(jī)外設(shè)使能其他屏蔽了就是這個(gè)效果,沒(méi)有向從機(jī)寫(xiě)入數(shù)據(jù),那就要看GPIO的電平設(shè)置或者中間的改動(dòng)了
?SPI和IIC、UART的區(qū)別:這三者都屬于串行通訊,一位一位的移數(shù)據(jù),區(qū)別就是幾條線,性質(zhì)是數(shù)據(jù)還是時(shí)鐘線?SPI是2數(shù)據(jù)線1時(shí)鐘1片選,UART是2數(shù)據(jù),這兩否認(rèn)數(shù)據(jù)都是一出一入,可以同時(shí)完成收發(fā)所以是全雙工,IIC是1時(shí)鐘1數(shù)據(jù),一時(shí)間內(nèi)不限定方向所以是半雙工。SPI和UART都是一主多從,IIC是多主多從,這是分析軟硬件的時(shí)結(jié)果。
????當(dāng)你分不清、記不住上面那些的時(shí)候,想想他們的軟硬件區(qū)別,物理層的IO口,電氣特性,軟件實(shí)現(xiàn)的協(xié)議部分,程序流程:IO信號(hào)的輸入輸出及電平->時(shí)序圖->程序,然后你能就很快的想起。
????????????????????????????????????????????結(jié)尾
? ? 個(gè)人在黑廠做了幾年工作,一直處于一個(gè)想學(xué)習(xí)但又害怕沒(méi)有結(jié)果的茫然,最后通勤路上回到家就什么都不想干了的狀態(tài),知道方向想努力卻又很模糊,掰了之后重新找工作的時(shí)候太菜被嫌棄了,就有種夢(mèng)中驚醒的感覺(jué),還好年輕可以努力,每隔一段時(shí)間應(yīng)該會(huì)發(fā)一下技術(shù)學(xué)習(xí)心得來(lái)鞭策自己,狀態(tài)允許的話盡量每天看文檔學(xué)英語(yǔ),各種模擬電子、硬件電路什么的也要補(bǔ)……
? ? 以上,理工科的切記:多去動(dòng)手,實(shí)驗(yàn)室也好,自己買(mǎi)一些元器件、開(kāi)發(fā)板、示波器也好,光看視頻是沒(méi)有長(zhǎng)進(jìn)的,這樣做會(huì)讓你在面試、工作的時(shí)候印象模糊和支支吾吾,想到了問(wèn)題就去動(dòng)手測(cè)試,然后多交流。只要肯動(dòng)手去做就會(huì)前途大好,你我共勉!
程序鏈接:https://pan.baidu.com/s/19u8EiytQOib9g-uVSg3sNw?pwd=trz5?
提取碼:trz5
注意:程序有些注釋對(duì)不上,還有CPOL=1和CPHA=1在測(cè)試中改過(guò),下面的屏蔽去掉
//SPI_SSN_LOW;
//SPI_SSN_HIGH;
return SpiRecDat;