在嵌入式系統(tǒng)中,主控MCU往往集成了多種片上外設(shè),例如,GPIO、PWM、I2C、SPI、UART、ADC等等。通過它們可以使MCU輕松的與“外部世界”相互連接、相互通信,從而與“外部世界”交互。在AWorks中,對這些外設(shè)進(jìn)行了抽象,為同一類外設(shè)提供了相同的使用接口。對于用戶來講,無論使用什么MCU,只要該MCU具有相應(yīng)的外設(shè),則均可以使用相同的外設(shè)接口進(jìn)行操作,因而使用某一外設(shè)的應(yīng)用程序可以輕松的跨平臺(移到另外一個硬件平臺)復(fù)用。同時,由于直接為用戶提供了外設(shè)的使用接口,因此,用戶不再需要了解底層的寄存器操作,由此可以將用戶從閱讀寄存器手冊、編寫底層驅(qū)動中解脫出來,使用戶更加專注于產(chǎn)品本身的“核心域”,提升產(chǎn)品的競爭力。
7.1 GPIO
在使用一個I/O口前,必須正確的配置I/O的功能和模式。同時,由于一個I/O口往往可用于多種功能,但同一時刻只能用于某一確定的功能,為了避免沖突,在將一個引腳用作某一功能前,應(yīng)該向系統(tǒng)申請,使用完畢后再釋放。
當(dāng)將I/O口用作GPIO(General Purpose Input Output)功能時,GPIO作為一種通用輸入/輸出接口,有兩種常用的使用方式:一種是用作普通的輸入/輸出接口;一種是用作中斷輸入接口,即當(dāng)指定的輸入狀態(tài)事件發(fā)生(比如:下降沿)時,觸發(fā)用戶自定義回調(diào)函數(shù)。
7.1.1 I/O配置
通常情況下,一個引腳往往可以用作多種功能,例如,在i.MX280中,PIO3_0可以用作下面4種功能:
-
應(yīng)用串口0的接收引腳;
-
I2C0的時鐘引腳;
-
調(diào)試串口的CTS引腳;
-
通用GPIO。
同時,GPIO往往還具有多種模式,比如:上拉、下拉、開漏、推挽等。為了正確使用一個IO口,必須先將其配置為正確的功能和模式。AWorks提供了I/O配置接口,其原型為:
其中,pin為引腳編號,flags為配置的功能和模式標(biāo)志,返回值為標(biāo)準(zhǔn)的錯誤號,返回AW_OK時表示配置成功,否則,表示配置失敗,配置失敗可能是由于部分功能和模式不支持造成的。
引腳編號pin用于指定需要配置的引腳,在GPIO標(biāo)準(zhǔn)接口層中,所有函數(shù)的第一個參數(shù)均為pin,用于指定具體操作的引腳,具體的引腳編號在{chip}_pin.h文件中定義(chip代表芯片名,例如,對于i.mx28x系列MCU,chip即為imx28x,對應(yīng)文件名為imx28x_pin.h),宏名的格式為PIOx_y,比如:PIO3_0。
flags為配置標(biāo)志,由“通用功能|通用模式|平臺功能|平臺模式”(‘|’就是C語言中的按位或)組成。
1. 通用功能和模式
通用功能和模式是AWorks抽象的GPIO最通用的功能和模式,它們在aw_gpio.h文件中使用宏的形式進(jìn)行了定義,宏名格式為AW_GPIO_*。通用功能相關(guān)宏定義與含義詳見表7.1,通用模式相關(guān)宏定義與含義詳見表7.2。
表7.1 引腳通用功能
表7.2 引腳通用模式
通用功能和模式相關(guān)的宏定義在標(biāo)準(zhǔn)接口層中,不會隨芯片的改變而改變,使用通用功能和模式的應(yīng)用程序是與具體芯片是無關(guān)的,可以跨平臺復(fù)用。使用通用功能和模式配置引腳的范例程序詳見程序清單7.1。
程序清單7.1 使用通用功能和模式配置引腳的范例程序
2. 平臺功能和模式
平臺功能和模式與具體芯片相關(guān),會隨著芯片的不同而不同,主要包括引腳的復(fù)用功能和一些特殊的模式,平臺功能和模式相關(guān)的宏定義在{chip}_pin.h文件中,宏名的格式為PIOx_y_*,比如:PIO3_0_AUART0_RX,即PIO3_0的串口0接收引腳。
如需查找某一引腳(比如:PIO3_0)相關(guān)的平臺功能和平臺模式,可以打開{chip}_pin.h文件,找到以PIO或引腳編號PIO3_0為前綴的所有宏定義。若一個宏定義以引腳編號為前綴,則表明該宏僅可用于引腳編號對應(yīng)的引腳,例如,PIO3_0_AUART0_RX僅可用于PIO3_0。若一個宏定義沒有以具體引腳編號為前綴,僅以PIO作為前綴,則表明該宏對應(yīng)的功能或模式可用于所有引腳。例如,PIO3_0相關(guān)的平臺功能詳見表7.4,相關(guān)的平臺模式定義詳見表7.3。
表7.3 引腳平臺模式
表7.4 PIO3_0平臺功能
在表7.3中,所有平臺模式都以PIO作為前綴,而非PIO3_0作為前綴。表明這些平臺模式不是PIO3_0引腳所特有的,而是所有引腳都可能支持的模式,即這些模式對應(yīng)的宏可以在配置任意引腳時使用。使用平臺功能和模式配置引腳的范例程序詳見程序清單7.2。
程序清單7.2 使用通用功能和模式配置引腳的范例程序
特別地,平臺功能和模式可以和通用功能和模式組合使用。例如,在配置I2C引腳時,可以開啟內(nèi)部上拉,范例程序詳見程序清單7.3。
程序清單7.3 通用模式和平臺模式混合使用
7.1.2 I/O的申請和釋放
如表7.4所示,PIO3_0可以被用作4種功能。雖然PIO3_0的功能眾多,但是,在同一時刻,其只能被用作某一確定功能,并不能同時使用多種功能。
隨著系統(tǒng)復(fù)雜度的上升,用戶往往很難保證某一引腳只被用作一種功能,稍有不慎,就可能將某一引腳同時配置為多種功能,而實際上,由于引腳同一時刻只能被用作一種功能,因此,部分使用某種功能的程序?qū)⒉荒苷9ぷ?。這種情況下,用戶往往很難發(fā)現(xiàn)工作異常的原因。
例如,PIO3_0已經(jīng)被用作I2C0的時鐘引腳,結(jié)果由于程序員的不小心,又將其配置為串口0的接收引腳,此時,若不加以保護(hù),則引腳會被配置為串口0的接收引腳,這將導(dǎo)致I2C0工作不正常。
為了保證引腳功能的互斥使用,AWorks提供了一種申請機(jī)制,在將引腳用作某一功能前,必須向系統(tǒng)申請,若該引腳處于空閑狀態(tài),還未被申請過,則本次申請成功,同時標(biāo)記該引腳已被使用。若在申請時,該引腳已被申請,則本次申請失敗。當(dāng)一個引腳使用完畢時,應(yīng)該釋放該引腳,以便系統(tǒng)將該引腳分配給下一個申請者。
在實際應(yīng)用中,往往在設(shè)計硬件電路時,一個引腳只會被用作某一確定的功能,不會將一個引腳同時用作多個外設(shè)功能引腳,因此,軟件設(shè)計正確無誤的情況下,通常不會出現(xiàn)申請失敗的情況。當(dāng)申請失敗時,往往是由于軟件開發(fā)人員的錯誤導(dǎo)致的,這就需要軟件開發(fā)人員引起足夠的重視,出現(xiàn)申請失敗的情況時,必須立即解決,找到某一引腳被非法占用的位置。
引腳申請機(jī)制包括兩個接口,相關(guān)接口的原型詳見表7.5。
表7.5 引腳申請機(jī)制相關(guān)接口(aw_gpio.h)
1. 申請引腳
當(dāng)需要使用一組引腳時,應(yīng)該向系統(tǒng)申請,申請的函數(shù)原型為:
其中,p_name為申請者的名字,p_pins指向引腳列表,num為本次申請的引腳個數(shù)。返回值為標(biāo)準(zhǔn)的錯誤號,返回AW_OK時表示申請成功,可以正常使用相關(guān)的引腳,否則,表示申請失敗,相關(guān)引腳已經(jīng)被占用,無法使用。
p_name為申請者的名字,其指向一個字符串,例如,"LED"、"UART" 、"SSP0"、"I2C0"等,名字僅作標(biāo)記,便于引腳的跟蹤,可以任意設(shè)定。
p_pins為引腳列表,例如,要申請PIO3_2和PIO3_3這兩個引腳用作串口功能,則引腳列表可以定義為:
num表示本次申請的引腳個數(shù),其值應(yīng)該與p_pins指向的列表中的引腳個數(shù)相等,比如:2。申請PIO3_2和PIO3_3這兩個引腳用作串口功能的范例程序詳見程序清單7.4。
程序清單7.4 引腳申請范例程序
只有當(dāng)引腳申請成功后,才能配置相應(yīng)的引腳用作串口功能。
特別地,即使將一個IO口用作通用的GPIO口,也需要先申請,例如,要將PIO2_6用作通用I/O口,用以控制LED0。則同樣需要在將其配置為通用I/O功能前向系統(tǒng)申請,范例程序程序清單7.4。
關(guān)于需要申請引腳的時機(jī),一個簡單的原則就是:在調(diào)用aw_gpio_pin_cfg()前,都應(yīng)該確保已經(jīng)向系統(tǒng)申請到該引腳的使用權(quán)。
2. 釋放引腳
當(dāng)引腳使用完畢,暫時不再使用時,應(yīng)該釋放引腳,清除每個引腳的使用記錄。便于其它模塊申請使用。其函數(shù)原型為:
其中, p_pins指向引腳列表,num為本次釋放的引腳個數(shù)。返回值為標(biāo)準(zhǔn)的錯誤號,返回AW_OK時表示釋放成功,否則,表示釋放失敗,可能是由于參數(shù)錯誤導(dǎo)致的。
p_pins為引腳列表,其應(yīng)該與申請引腳時的引腳列表一致,例如,要釋放之前申請的PIO3_2和PIO3_3這兩個引腳,則引腳列表定義為:
num表示本次釋放的引腳個數(shù),其值應(yīng)該與p_pins指向的列表中的引腳個數(shù)相等,比如:2。釋放PIO3_2和PIO3_3這兩個引腳的范例程序詳見程序清單7.5。
程序清單7.5 釋放引腳范例程序
在釋放引腳前,可以將I/O口配置為通用GPIO功能,以使其不再作為串口的功能引腳。特別注意,這一配置操作只能在釋放前完成,釋放后將失去引腳的控制權(quán),不可再對其進(jìn)行配置操作。
7.1.3 普通I/O接口
當(dāng)將一個引腳配置為通用I/O接口時(輸入或輸出),則可以通過相關(guān)的I/O接口控制其輸出狀態(tài)或獲取其輸入狀態(tài)。相關(guān)接口的原型詳見表7.6。
表7.6 GPIO通用接口(aw_gpio.h)
1. 獲取引腳電平
無論當(dāng)前引腳處于輸出模式還是輸入模式,都可以通過該接口獲取當(dāng)前的引腳電平狀態(tài)。其函數(shù)原型為:
其中的pin為引腳編號。返回值為標(biāo)準(zhǔn)的錯誤號,若返回值小于0,則表示獲取失敗,失敗的原因可能是用于引腳不存在。若返回值為非負(fù)數(shù),則表明獲取成功,其值為0時,表明當(dāng)前引腳的電平為低電平,其值大于0時,表明當(dāng)前引腳的電平為高電平。范例程序詳見程序清單7.6。
程序清單7.6 獲取引腳電平范例程序
2. 設(shè)置引腳電平
當(dāng)引腳處于輸出模式時,可以通過該接口設(shè)置引腳的輸出電平,其函數(shù)原型為:
其中,pin為引腳編號。value為設(shè)置的值,當(dāng)value為0時,輸出低電平,否則,輸出高電平。返回值為標(biāo)準(zhǔn)的錯誤號,返回AW_OK時表示設(shè)置成功,否則,表示設(shè)置失敗。
例如,可以控制GPIO的輸出電平,達(dá)到控制LED狀態(tài)的目的。在EPC-AW280上板載了一個運行指示燈,標(biāo)識為RUN,其對應(yīng)的原理圖詳見圖7.1。
圖7.1 板載LED電路
其中,發(fā)光二極管的陰極與MCU的PIO2_6相連,當(dāng)I/O輸出低電平時,由于LED陽極加了3.3V電壓(高電平1),因而形成了電位差,所以有電流流動,則LED發(fā)光二極管導(dǎo)通,即LED發(fā)光;當(dāng)I/O輸出高電平1時,由于無法形成電位差,則LED二極管不導(dǎo)通,即LED熄滅。
基于此,可以使PIO2_6輸出低電平,以點亮LED,范例程序詳見程序清單7.7。
程序清單7.7 設(shè)置引腳電平范例程序
程序中,首先將PIO2_6配置為了輸出模式,并將初始值設(shè)定為高電平,以便初始化完畢后,LED默認(rèn)處于熄滅狀態(tài)。
同理,點亮LED后,可以控制PIO2_6輸出高電平,以熄滅LED。如以一定的頻率交替使PIO2_6輸出高電平和低電平,則可以看到LED閃爍,范例程序程序清單7.8。
程序清單7.8 交替輸出高低電平的范例程序
這里通過GPIO的輸出控制LED,僅為介紹GPIO接口的使用方法。實際中,AWorks已經(jīng)定義了通用的LED接口,在應(yīng)用中操作LED時,均建議使用通用的LED接口。
3. 翻轉(zhuǎn)引腳電平
該接口用于翻轉(zhuǎn) GPIO 引腳的輸出電平,如果GPIO當(dāng)前輸出的是低電平,當(dāng)調(diào)用該函數(shù)后,GPIO將輸出高電平,反之則輸出變?yōu)榈碗娖?。其函?shù)原型為:
其中,pin為引腳編號。返回值為標(biāo)準(zhǔn)的錯誤號,返回AW_OK時表示翻轉(zhuǎn)成功,否則,表示翻轉(zhuǎn)失敗。在程序清單7.8中,通過交替輸出高電平和低電平實現(xiàn)了LED閃爍。而交替輸出高低電平本質(zhì)上就是不斷翻轉(zhuǎn)GPIO的輸出電平。基于此,若以一定的頻率翻轉(zhuǎn)GPIO的輸出電平,同樣可以實現(xiàn)LED閃爍,范例程序詳見程序清單7.9。
程序清單7.9 翻轉(zhuǎn)引腳電平的范例程序
7.1.4 中斷I/O接口
由對普通I/O接口的介紹可知,若需獲取某一引腳的狀態(tài),可以通過aw_gpio_get()接口得到引腳的當(dāng)前輸入狀態(tài)。若用戶需要監(jiān)控GPIO某一狀態(tài)事件(比如:GPIO由高電平變?yōu)榈碗娖剑串?dāng)出現(xiàn)某一狀態(tài)時,才執(zhí)行相應(yīng)的操作。若還是使用普通I/O接口,則必須不斷的調(diào)用aw_gpio_get()接口,直到讀取到引腳電平為0。顯然,由于使用這種方式需要不斷的輪詢,因而是非常消耗CPU的。為此,AWorks提供了中斷I/O接口,其可以使GPIO工作在中斷狀態(tài),實時監(jiān)控引腳的輸入狀態(tài),只有當(dāng)用戶期望的狀態(tài)發(fā)生時,才通知用戶,用戶進(jìn)而執(zhí)行相關(guān)的處理,當(dāng)期望的狀態(tài)沒有發(fā)生時,則用戶完全不用關(guān)心引腳的狀態(tài),無需對引腳進(jìn)行不斷的輪詢。
AWorks為I/O中斷相關(guān)的操作定義了一套觸發(fā)接口,用戶期望的狀態(tài)稱之為觸發(fā)條件,當(dāng)GPIO的輸入狀態(tài)滿足觸發(fā)條件時,將自動調(diào)用引腳觸發(fā)回調(diào)函數(shù),以通知用戶作相關(guān)的處理。相關(guān)接口原型詳見表7.7。
表7.7 GPIO觸發(fā)相關(guān)接口函數(shù)
1. 連接引腳觸發(fā)回調(diào)函數(shù)
在使用引腳的觸發(fā)功能前,應(yīng)該首先連接一個回調(diào)函數(shù)到觸發(fā)引腳,當(dāng)相應(yīng)引腳的觸發(fā)事件產(chǎn)生時,則會調(diào)用本函數(shù)連接的觸發(fā)回調(diào)函數(shù)。其函數(shù)原型為:
其中,pin為引腳編號,pfunc_callback為指向回調(diào)函數(shù)的指針,其指向的函數(shù)即為本次連接的回調(diào)函數(shù),p_arg為傳遞給回調(diào)函數(shù)的用戶參數(shù)。返回值為標(biāo)準(zhǔn)的錯誤號,返回AW_OK時表示連接成功,否則,表示連接失敗,失敗可能是由于該引腳不支持觸發(fā)模式。
pfunc_callback為指向回調(diào)函數(shù)的指針,其類型為aw_pfuncvoid_t,該類型在aw_types.h文件中定義如下:
由此可見,回調(diào)函數(shù)的類型是無返回值,具有一個void *類型參數(shù)的函數(shù)。當(dāng)觸發(fā)事件發(fā)生時,將自動調(diào)用pfunc_callback指向的函數(shù),并將連接觸發(fā)回調(diào)函數(shù)時設(shè)定的p_arg作為回調(diào)函數(shù)的參數(shù)。例如,要將引腳PIO3_6用作觸發(fā)功能,則首先需要連接觸發(fā)回調(diào)函數(shù),范例程序詳見程序清單7.10。
程序清單7.10 連接引腳觸發(fā)回調(diào)函數(shù)范例程序
2. 斷開引腳觸發(fā)回調(diào)函數(shù)
與aw_gpio_trigger_connect()函數(shù)的功能相反,當(dāng)一個引腳不再需要用作觸發(fā)功能時,可以斷開引腳與回調(diào)函數(shù)的連接?;蛘弋?dāng)需要將一個引腳的回調(diào)函數(shù)重新連接到另外一個函數(shù)時,則應(yīng)該先斷開當(dāng)前連接的回調(diào)函數(shù),再重新連接到新的回調(diào)函數(shù)。其函數(shù)原型為:
其中,pin為引腳編號,pfunc_callback 為指向回調(diào)函數(shù)的指針,其值應(yīng)該與連接回調(diào)函數(shù)時設(shè)定的回調(diào)函數(shù)一致,p_arg為回調(diào)函數(shù)的參數(shù),其值同樣應(yīng)該與連接回調(diào)函數(shù)時設(shè)定的p_arg一致。返回值為標(biāo)準(zhǔn)的錯誤號,返回AW_OK時表示斷開連接成功,否則,表示斷開連接失敗,失敗可能是由于參數(shù)錯誤造成的。使用范例詳見程序清單7.11。
程序清單7.11 斷開引腳觸發(fā)回調(diào)函數(shù)范例程序
3. 配置引腳觸發(fā)條件
連接觸發(fā)回調(diào)函數(shù)后,需要配置引腳觸發(fā)的條件,其函數(shù)原型如下:
其中,pin為引腳編號,flags用于指定觸發(fā)條件。返回值為標(biāo)準(zhǔn)的錯誤號,返回AW_OK時表示配置成功,否則,表示配置失敗,配置失敗可能是由于該引腳不支持配置的觸發(fā)條件。
觸發(fā)條件決定了引腳觸發(fā)的時機(jī),所有可選的觸發(fā)條件詳見表7.8。
表7.8 GPIO觸發(fā)條件配置宏
實際中,并不是每一個引腳都支持表中所有的觸發(fā)條件,當(dāng)配置觸發(fā)條件時,應(yīng)檢測返回值,確保相應(yīng)引腳支持所配置的觸發(fā)條件。特別地,部分引腳可能不支持觸發(fā)模式,配置任何觸發(fā)條件都會失敗。
例如,配置PIO3_6為觸發(fā)模式,觸發(fā)條件為下降沿觸發(fā),范例程序詳見程序清單7.12。
程序清單7.12 配置觸發(fā)條件的范例程序
4. 打開引腳觸發(fā)
當(dāng)正確連接回調(diào)函數(shù)并設(shè)置相應(yīng)的觸發(fā)條件后,可以打開引腳觸發(fā),使引腳觸發(fā)開始工作。其函數(shù)原型為:
其中,pin為引腳編號,返回值為標(biāo)準(zhǔn)的錯誤號,返回AW_OK時表示打開成功,否則,表示打開失敗,打開失敗可能是由于未正確連接回調(diào)函數(shù)或設(shè)置觸發(fā)條件。
綜合連接引腳觸發(fā)回調(diào)函數(shù)和配置引腳觸發(fā)條件的接口,可以實現(xiàn)一個完整的引腳觸發(fā)范例程序,詳見程序清單7.13。
程序清單7.13 打開引腳觸發(fā)范例程序
程序中,由于需要使用aw_gpio_pin_cfg()將引腳配置為輸入模式,因此,在配置引腳前,同樣先向系統(tǒng)申請了引腳的控制權(quán)。特別地,在aw_gpio_trigger_cfg()前,無需再次申請。
程序運行后,若PIO3_6引腳出現(xiàn)下降沿(可以通過導(dǎo)線將PIO3_6與GND輕觸幾次),則可以觀察到LED的狀態(tài)發(fā)生變化。實際中,若采用輕觸GND的方式產(chǎn)生下降沿,由于輕觸時會有抖動,可能輕觸時將在短時間內(nèi)產(chǎn)生多個下降沿,此時,可能觀察到LED無規(guī)律的翻轉(zhuǎn)。
注意,必須先連接回調(diào)函數(shù),再配置引腳的觸發(fā)條件,這個順序不能顛倒,即不能顛倒程序清單7.13中第18行和第19行的順序。
特別地,當(dāng)將引腳用作觸發(fā)功能時,往往需要將引腳配置為輸入模式。程序清單7.13的第14行程序?qū)⒁_配置為了輸入模式,并開啟了上拉,使得PIO3_6在外部懸空狀態(tài)時,仍能處于確定的高電平狀態(tài)。
5. 關(guān)閉引腳觸發(fā)
當(dāng)暫時不使用引腳觸發(fā)功能時,可以關(guān)閉引腳觸發(fā),引腳觸發(fā)將停止工作,此時,即使?jié)M足配置的觸發(fā)條件,也不會觸發(fā)調(diào)用引腳相應(yīng)的回調(diào)函數(shù)。其函數(shù)原型為:
其中,pin為引腳編號,返回值為標(biāo)準(zhǔn)的錯誤號,返回AW_OK時表示關(guān)閉成功,否則,表示關(guān)閉失敗。使用范例詳見程序清單7.14。
程序清單7.14 關(guān)閉引腳觸發(fā)范例程序
當(dāng)引腳觸發(fā)被關(guān)閉后,若需引腳觸發(fā)重新開始工作,可以使用aw_gpio_trigger_on()再次打開引腳觸發(fā)功能。
7.2 PWM
7.2.1 PWM簡介
大小和方向隨時間發(fā)生周期性變化的電流稱為交流,交流中最基本的波形稱為正弦波,除此之外的波形稱為非正弦波。計算機(jī)、電視機(jī)、雷達(dá)等裝置中使用的信號稱為脈沖波、鋸齒波等,其電壓和電流波形都是非正弦交流的一種。
PWM(Pulse Width Modulation)就是脈沖寬度調(diào)制的意思,一種脈沖編碼技術(shù),即可以按照信號電平改變脈沖寬度。而脈沖寬度調(diào)制波的周期也是固定的,用占空比(高電平/周期,有效電平在整個信號周期中的時間比率,范圍為0~100%)來表示編碼數(shù)值。PWM可以用于對模擬信號電平進(jìn)行數(shù)字編碼,也可以通過高電平(或低電平)在整個周期中的時間來控制輸出的能量,從而控制電機(jī)轉(zhuǎn)速或LED亮度。
PWM信號是由計數(shù)器和比較器產(chǎn)生的,比較器中設(shè)定了一個閾值,計數(shù)器以一定的頻率自加。當(dāng)計數(shù)器的值小于閾值時,則輸出一種電平狀態(tài),比如,高電平。當(dāng)計數(shù)器的值大于閾值,則輸出另一種電平狀態(tài),比如,低電平。當(dāng)計數(shù)器溢出清0時,又回到最初的電平狀態(tài),即I/O引腳發(fā)生了周期性的翻轉(zhuǎn)而形成PWM波形,詳見圖7.2。
圖7.2 PWM波形圖
當(dāng)計數(shù)器的值小于閾值時,則輸出高電平;當(dāng)計數(shù)器的值大于閾值時,則輸出低電平。閾值為45,計數(shù)器的值最大為100。PWM波形有三個關(guān)鍵點:起始點①,此時計數(shù)器的值為0;計數(shù)器值達(dá)到閾值②,I/O狀態(tài)發(fā)生翻轉(zhuǎn);計數(shù)器達(dá)到最大值③,I/O狀態(tài)發(fā)生翻轉(zhuǎn),計數(shù)器的值回到0重新開始計數(shù)。
7.2.2 PWM接口
AWorks提供了接口函數(shù),用于控制PWM輸出,接口原型詳見表7.9。
表7.9 PWM接口函數(shù)(aw_pwm.h)
1. 配置PWM通道
配置一個PWM通道的周期時間和高電平時間,其函數(shù)原型為:
其中,pid為PWM通道的id號,duty_ns為脈寬時間(單位:ns),period_ns為周期時間(單位:納秒)。返回值為標(biāo)準(zhǔn)的錯誤號,返回AW_OK時表示配置成功,否則,表示配置失敗。
在AWorks中,一個系統(tǒng)往往可以輸出多個通道的PWM,各個通道通過pid區(qū)分,一個系統(tǒng)實際可以輸出PWM的通道數(shù)與具體硬件平臺相關(guān)。例如,在i.MX28x系統(tǒng)中,可以輸出8路PWM。則PWM通道的編號為:0 ~ 7,各通道對應(yīng)的默認(rèn)I/O口詳見表7.10。
表7.10 各通道對應(yīng)的I/O口
注:實際中,各個PWM通道對應(yīng)的I/O口是可以配置的,具體配置方法詳見SDK配套資料中的《用戶手冊.pdf》。
輸出PWM的頻率由周期時間period_ns決定,例如,需要輸出1KHz的PWM,周期時間為1ms,則period_ns的值為1000000。
輸出PWM的脈寬由duty_ns決定,它和周期值決定了輸出PWM的占空比,占空比即為:duty_ns / period_ns。duty_ns的值不能超過period_ns。配置PWM通道0輸出PWM的頻率為1KHz,占空比為50%的范例程序詳見程序清單7.15。
程序清單7.15 配置PWM通道的范例程序
2. 使能PWM輸出
PWM通道配置完成后,并不會輸出PWM。只有使能通道輸出后,才能使相應(yīng)通道開始輸出PWM,其函數(shù)原型為:
其中,pid為PWM通道的id號。返回值為標(biāo)準(zhǔn)的錯誤號,返回AW_OK時表示使能成功,PWM開始輸出,否則,表示使能失敗,PWM不能正常輸出,失敗原因可能是通道號設(shè)置有誤。使能PWM通道0輸出的范例程序詳見程序清單7.16。
程序清單7.16 使能PWM輸出范例程序
3. 禁能PWM輸出
若需關(guān)閉PWM通道的輸出,則可以禁能相應(yīng)PWM通道,其函數(shù)原型為:
其中,pid為PWM通道的id號。返回值為標(biāo)準(zhǔn)的錯誤號,返回AW_OK時表示禁能成功,PWM停止輸出,否則,表示禁能失敗。禁能PWM通道0輸出的范例程序詳見程序清單7.17。
程序清單7.17 禁能PWM輸出范例程序
EPC-AW280上板載了一個無源蜂鳴器,其對應(yīng)的原理圖詳見圖7.3,蜂鳴器的控制引腳與GPIO3_29連接,當(dāng)GPIO3_29輸出高電平時,則三極管導(dǎo)通,向蜂鳴器供電;當(dāng)GPIO3_29輸出低電平時,則三極管截止,停止向蜂鳴器供電。對于無源蜂鳴器,只要以一定的頻率控制蜂鳴器的“通電”和“斷電”,即可使蜂鳴器產(chǎn)生機(jī)械振動音,聲音的頻率與控制信號的頻率相同,只要頻率在人耳的聽覺范圍內(nèi),即可聽到蜂鳴器發(fā)出的聲音。
圖7.3 板載蜂鳴器電路
基于此,可以通過GPIO3_29輸出一定頻率的PWM,使蜂鳴器發(fā)聲。由表7.10可知,GPIO3_29對應(yīng)的PWM通道為4。因此,控制PWM通道4輸出PWM即可聽到蜂鳴器發(fā)聲。范例程序詳見程序清單7.18。
程序清單7.18 使用PWM輸出驅(qū)動蜂鳴器發(fā)聲范例程序
運行程序,可以聽到蜂鳴器發(fā)出的聲音。由于程序中一直輸出PWM,因此蜂鳴器會一直鳴叫,若僅需蜂鳴器每秒“嘀”一聲,則可以在不需要發(fā)聲時禁能PWM輸出。范例程序詳見程序清單7.19。
程序清單7.19 使用PWM控制蜂鳴器每秒“嘀”一聲的范例程序
這里通過控制PWM的輸出驅(qū)動蜂鳴器發(fā)聲,僅為介紹PWM接口的使用方法。實際中,AWorks已經(jīng)定義了通用的蜂鳴器接口,在應(yīng)用中操作蜂鳴器時,均建議直接使用通用的蜂鳴器接口。
7.3 SPI總線
7.3.1 SPI總線簡介
SPI(Serial Peripheral Interface)是一種全雙工同步串行通信接口,常用于短距離高速通信,其數(shù)據(jù)傳輸速率通??蛇_(dá)到幾M甚至幾十M。SPI通信采用主/從結(jié)構(gòu),主/從雙方通信時,需要使用到4根信號線:SCLK、MOSI、MISO、CS。其典型的連接示意圖詳見圖7.4。
圖7.4 SPI連接示意圖——單從機(jī)
-
SCLK:時鐘信號,由主設(shè)備產(chǎn)生;
-
MOSI:主機(jī)數(shù)據(jù)輸出,從機(jī)數(shù)據(jù)輸入;
-
MISO:從機(jī)數(shù)據(jù)輸出,主機(jī)數(shù)據(jù)輸入;
-
CS:片選信號,由主設(shè)備控制。
數(shù)據(jù)傳輸是由主機(jī)發(fā)起的,主機(jī)在串行數(shù)據(jù)傳輸前驅(qū)動CS信號,使之變?yōu)橛行顟B(tài)(通常情況下,有效狀態(tài)為低電平),接著,在SCLK上輸出時鐘信號,在時鐘信號的同步下,每個時鐘傳輸一位數(shù)據(jù),主機(jī)數(shù)據(jù)通過MOSI傳輸至從機(jī),從機(jī)數(shù)據(jù)通過MISO傳輸至主機(jī),數(shù)據(jù)傳輸完畢后,釋放CS信號,使之變?yōu)闊o效狀態(tài),一次數(shù)據(jù)傳輸完成。
一個主機(jī)可以連接多個從機(jī),多個從機(jī)共用SCLK 、MOSI、MISO三根信號線,每個從機(jī)的片選信號CS是獨立的,因此,若主機(jī)需要連接多個從機(jī),就需要多個片選控制引腳。連接示意圖詳見圖7.5。當(dāng)一個主機(jī)連接多個從機(jī)時,同一時刻最多只能使一個片選信號有效,以選擇一個確定的從機(jī)作為數(shù)據(jù)通信的目標(biāo)對象。也就是說,在某一時刻,最多只能激活尋址一個從機(jī),以使各從機(jī)之間相互獨立的使用,互不干擾。
圖7.5 SPI連接示意圖——多從機(jī)
注意,單個通信網(wǎng)絡(luò)中,可以有多個從機(jī),但有且只能有一個主機(jī)。
除了需要了解上述SPI的基本概念外,讀者還應(yīng)該理解SPI的傳輸模式,以便在操作SPI從機(jī)器件時,可以正確的設(shè)置SPI主機(jī)的傳輸模式。
SPI數(shù)據(jù)傳輸是在片選信號有效時,數(shù)據(jù)位在時鐘信號的同步下,每個時鐘傳輸一位數(shù)據(jù)。根據(jù)時鐘極性和時鐘相位的不同,將SPI分為了4種傳輸模式,詳見表7.11。
表7.11 SPI模式
-
時鐘極性(CPOL)
時鐘極性表示了SPI空閑時的時鐘極性,可以為高電平(CPOL=1)或低電平(CPOL=0)。
-
時鐘相位
時鐘相位決定了數(shù)據(jù)采樣的時機(jī),若CPHA=0,則表示數(shù)據(jù)在時鐘的第一個邊沿采樣;若CPHA=1,則表示數(shù)據(jù)在時鐘的第二個邊沿采樣。
CPHA=0時,對應(yīng)的模式0(CPOL=0)和模式2(CPOL=1)的示意圖詳見圖7.6。
圖7.6 SPI模式0和模式2示意圖
在SPI模式0(CPOL=0,CPHA=0)中,時鐘空閑電平為低電平,在傳輸數(shù)據(jù)時,每一位數(shù)據(jù)在第一個邊沿(即上升沿)采樣。
在SPI模式2(CPOL=1,CPHA=0)中,時鐘空閑電平為高電平,在傳輸數(shù)據(jù)時,每一位數(shù)據(jù)在第一個邊沿(即下降沿)采樣。
同理,CPHA=1時,對應(yīng)的模式1(CPOL=0)和模式3(CPOL=1)的示意圖詳見圖7.7。
圖7.7 SPI模式1和模式3示意圖
在SPI模式1(CPOL=0,CPHA=1)下,時鐘空閑電平為低電平,在傳輸數(shù)據(jù)時,每一位數(shù)據(jù)在第二個邊沿(即下降沿)采樣。
在SPI模式3(CPOL=1,CPHA=1)下,時鐘空閑電平為高電平,在傳輸數(shù)據(jù)時,每一位數(shù)據(jù)在第二個邊沿(即上升沿)采樣。
7.3.2 SPI總線接口
絕大部分情況下,MCU都作為SPI主機(jī)與SPI從機(jī)器件通信,因此這里僅介紹AWorks中將MCU作為SPI主機(jī)的相關(guān)接口,接口原型詳見表7.12。
表7.12 SPI標(biāo)準(zhǔn)接口函數(shù)
1. 定義SPI從機(jī)器件實例
對于用戶來講,使用SPI總線的目的往往是用于操作一個SPI從機(jī)器件,比如,HC595、SPI FLASH等。MCU作為SPI主機(jī)與從機(jī)器件通信,需要知道從機(jī)器件的相關(guān)信息,比如: SPI模式、SPI速率、數(shù)據(jù)位寬等。在AWorks中,定義了統(tǒng)一的SPI從機(jī)器件類型:aw_spi_device_t,用于包含從機(jī)器件相關(guān)的信息,以便主機(jī)正確的與之通信。該類型的具體定義用戶無需關(guān)心,在使用SPI操作一個從機(jī)器件前,必須先使用該類型定義一個與從機(jī)器件對應(yīng)的器件實例,例如:
其中,spi_dev為用戶自定義的從機(jī)實例,其地址可作為接口函數(shù)中p_dev的實參傳遞。
2. 初始化SPI從機(jī)器件實例
當(dāng)完成SPI從機(jī)器件實例的定義后,還需要完成其初始化,指定從機(jī)器件相關(guān)的信息,初始化函數(shù)的原型為:
其中,p_dev為指向SPI從機(jī)器件實例的指針,busid為SPI總線編號,bits_per_word為數(shù)據(jù)位寬,mode為使用的SPI模式,max_speed_hz為從設(shè)備支持的最高時鐘頻率,cs_pin為從機(jī)設(shè)備的片選引腳,pfunc_cs為自定義的片選引腳控制函數(shù)。
在AWorks中,一個系統(tǒng)往往具有多條SPI總線,各總線之間通過busid區(qū)分,一個系統(tǒng)實際支持的SPI總線條數(shù)與具體硬件平臺相關(guān)。例如,在i.MX28x系統(tǒng)中,最高可以支持5條SPI總線,對應(yīng)的總線編號即為:0 ~ 4。busid參數(shù)即用于指定使用那條SPI總線與從機(jī)器件進(jìn)行通信。
表7.13 SPI模式標(biāo)志
bits_per_word指定了數(shù)據(jù)傳輸?shù)奈粚挘话銇碇v,數(shù)據(jù)均為8位,即每個數(shù)據(jù)為一個字節(jié)。
mode為從機(jī)使用的SPI模式(模式0 ~ 模式3,對應(yīng)的宏定義詳見表7.13),從機(jī)器件一般支持固定的一種或幾種SPI模式,這里的mode用于指定使用何種SPI模式與從機(jī)器件通信。
max_speed_hz為從機(jī)器件支持的最大速率(SCLK最高時鐘頻率),往往在從機(jī)器件對應(yīng)的數(shù)據(jù)手冊上有定義。通常情況下,從機(jī)器件支持的最大速率都是很高的,有時可能會超過MCU中SPI主機(jī)能夠輸出的最大時鐘頻率,此時,將直接使用MCU中SPI主機(jī)能夠輸出的最大時鐘頻率。
cs_pin和pfunc_cs均與片選引腳相關(guān)。pfunc_cs是指向自定義片選引腳控制函數(shù)的指針,若pfunc_cs的值為NULL,驅(qū)動將自動控制由cs_pin指定的引腳實現(xiàn)片選控制;若pfunc_cs的值不為NULL,指向了有效的自定義片選控制函數(shù),則cs_pin不再被使用,片選控制將完全由pfunc_cs指向的函數(shù)實現(xiàn)。當(dāng)需要片選引腳有效時(SPI數(shù)據(jù)傳輸前),系統(tǒng)將自動調(diào)用pfunc_cs指向的函數(shù),并傳遞state的值為1。當(dāng)需要片選引腳無效時(SPI數(shù)據(jù)傳輸結(jié)束后),也會調(diào)用pfunc_cs指向的函數(shù),并傳遞state的值為0。一般情況下,片選引腳自動控制即可,即設(shè)置pfunc_cs的值為NULL,cs_pin的值設(shè)置為片選引腳,比如:PIO2_19。
例如,要使用SPI0(SPI總線的busid為0)操作74HC595。則首先應(yīng)該定義并初始化一個與74HC595對應(yīng)的從機(jī)器件。這就還需要知道幾點重要的信息:數(shù)據(jù)位寬、模式、最高速率和片選引腳。
要獲取這些信息,就必須查看芯片相關(guān)的數(shù)據(jù)手冊和相應(yīng)的硬件電路。74HC595是一種常用的串行輸入/并行輸出轉(zhuǎn)換芯片,其引腳分布圖詳見圖7.8。
圖7.8 74HC595管腳圖
74HC595內(nèi)部有兩個8位寄存器:一個移位寄存器和一個數(shù)據(jù)鎖存寄存器。移位寄存器的8位數(shù)據(jù)使用Q0’ ~ Q7’表示,其中僅Q7’位對應(yīng)的電平通過Q7’引腳輸出,其余位未使用引腳輸出。數(shù)據(jù)鎖存寄存器的8位數(shù)據(jù)使用Q0 ~ Q7表示,并使用Q0 ~ Q7引腳將8位數(shù)據(jù)輸出。
移位寄存器在時鐘信號CP的作用下,每個上升沿將D引腳電平移至移位寄存器的最低位,其余位依次向高位移動,移位寄存器的值發(fā)生改變,Q7’引腳的輸出隨著值的改變而改變,但此時,數(shù)據(jù)鎖存寄存器中的值保持不變,即Q0 ~ Q7的輸出保持不變。由此可見,由于移位作用,原移位寄存器中的最高位Q7’將被完全移除,數(shù)據(jù)丟失。若希望數(shù)據(jù)不丟失,即并行輸出的數(shù)據(jù)超過8位,則可以將多個74HC595串接,將Q7’引腳連接至下一個74HC595的數(shù)據(jù)輸入端D。這樣,每次移位時,原先的Q7’將移動至下一個74HC595中,這也是為什么單獨將Q7’通過引腳引出的原因,通過多個74HC595級聯(lián),可以將并行輸出擴(kuò)展為16位、24位、32位等。
數(shù)據(jù)鎖存寄存器的值可以通過STR引腳輸入上升沿信號更新,當(dāng)STR引腳輸入上升沿信號時,數(shù)據(jù)鎖存寄存器中的值將更新為移位寄存器中的值,即Q0 ~ Q7的值更新為Q0’~Q7’的值。這樣的設(shè)計可以保證同時改變所有并行輸出,將8位數(shù)據(jù)一次性地在Q0 ~ Q7端輸出,如果不使用數(shù)據(jù)鎖存寄存器,而是直接將移位寄存器的值輸出,則輸出將受到移位過程的影響,即每次移位,數(shù)據(jù)輸出都可能發(fā)生變化。
除基本的CP時鐘信號、D數(shù)據(jù)輸入信號、STR鎖存信號、Q0 ~ Q7輸出信號、Q7’輸出信號外,還有和兩個控制信號,為鎖存寄存器的輸出使能信號,當(dāng)
74HC595傳輸數(shù)據(jù)的過程為:D端為數(shù)據(jù)輸入口,在時鐘CP的作用下每次傳輸一位數(shù)據(jù)至移位寄存器中,如需傳輸8位數(shù)據(jù),則應(yīng)在CP端輸入8個時鐘信號,傳輸結(jié)束后,需要在STR上產(chǎn)生一個上升沿信號,以便將移位寄存器中的數(shù)據(jù)輸出。由此可見,其數(shù)據(jù)傳輸?shù)姆绞胶蚐PI傳輸數(shù)據(jù)的方式極為相似,均是在時鐘信號的同步下,每個時鐘傳輸一位數(shù)據(jù),特殊的,74HC595在傳輸結(jié)束后需要在STR上輸入一個上升沿鎖存信號。實際上,在SPI傳輸中,傳輸數(shù)據(jù)前,主機(jī)會將片選信號拉低,傳輸結(jié)束后,主機(jī)會將片選信號拉高,顯然,若將STR作為從機(jī)片選信號由主機(jī)控制,則在數(shù)據(jù)傳輸結(jié)束后,主機(jī)會將片選信號拉高,同樣可以達(dá)到在STR上產(chǎn)生上升沿的效果。
基于此,可以將74HC595看作一個SPI從機(jī)器件,SPI主機(jī)的SCLK時鐘信號與CP相連,MOSI作為主出從入,與D相連,CS作為片選信號,與STR相連。此外,74HC595作為一個串/轉(zhuǎn)并芯片,只能輸出數(shù)據(jù),不能輸入數(shù)據(jù),即SPI主機(jī)只需向74HC595發(fā)送數(shù)據(jù),不需要從74HC595接收數(shù)據(jù),因此,無需使用SPI的MISO引腳。
MiniPort-595模塊采用74HC595擴(kuò)展8路I/O,可以直接驅(qū)動LED顯示模塊,其等效電路詳見圖7.9。由此可見,模塊僅有3路信號輸入,但可并行輸出8位數(shù)據(jù)。電路中,將 直接接地,固定為低電平,使能了數(shù)據(jù)鎖存寄存器的輸出。將 直接與電源連接,固定為高電平,即不使用其復(fù)位功能,使其不影響移位寄存器的值。
圖7.9 74HC595電路圖
實際中,當(dāng)MiniPort-595與i.MX28x的擴(kuò)展板連接時,MOSI、SCLK與i.MX28x的SPI0連接,片選信號CS與PIO2_19連接。
在初始化與74HC595對應(yīng)的SPI從機(jī)器件實例時,還需要獲取到數(shù)據(jù)寬度、SPI模式、最高時鐘頻率等信息。即:
-
數(shù)據(jù)寬度
74HC595只有8個并行輸出口,內(nèi)部寄存器也均為8位,因此,單次傳輸?shù)臄?shù)據(jù)為8位,SPI傳輸時的數(shù)據(jù)寬度即為8。
-
SPI模式
數(shù)據(jù)在CP時鐘信號的上升沿被采樣送入74HC595的移位寄存器,對空閑時鐘電平?jīng)]有要求,根據(jù)SPI幾種模式的定義可知(詳見圖7.6和圖7.7),模式0和模式3均是在時鐘上升沿采樣數(shù)據(jù),因此,使用模式0和模式3均可,后續(xù)的程序選擇模式3作為范例。
-
最高時鐘頻率
雖然74HC595支持的最高時鐘頻率可達(dá)100MHz,但實際中,受到MCU處理速度的限制以及MCU輸出引腳翻轉(zhuǎn)頻率的限制,往往并不能達(dá)到該值。因此,最高時鐘頻率可以先設(shè)置在一個相對合理的范圍,比如,3000000Hz(3MHz)。后續(xù)若3MHz不滿足應(yīng)用需求,可以在此基礎(chǔ)上根據(jù)需要調(diào)大調(diào)小即可。
基于以上信息,可以定義并初始化一個與74HC595對應(yīng)的SPI從機(jī)器件實例,范例詳見程序清單7.20。
程序清單7.20 初始化從機(jī)器件實例的范例程序
3. 設(shè)置SPI從機(jī)器件實例
設(shè)置SPI從機(jī)實例時,會檢查MCU的SPI主機(jī)是否支持從機(jī)實例的相關(guān)參數(shù)和模式。如果不能支持,則設(shè)置失敗,說明該從機(jī)不能使用。其函數(shù)原型為:
其中,p_dev是指向SPI從機(jī)器件實例的指針。返回值為標(biāo)準(zhǔn)的錯誤號,返回AW_OK時表示設(shè)置成功,否則,表示設(shè)置失敗,存在不支持的位寬、速率或模式等。
例如,在完成74HC595的初始化后,再通過該接口設(shè)置一次74HC595器件實例,范例程序詳見程序清單7.21。
程序清單7.21 設(shè)置SPI從機(jī)器件實例的范例程序
4. 先寫后讀
當(dāng)設(shè)定好從機(jī)實例后,即可與從機(jī)器件進(jìn)行數(shù)據(jù)交互。雖然SPI協(xié)議是可以全雙工通信的,即數(shù)據(jù)的發(fā)送和接收同時進(jìn)行,但絕大部分情況下,并不會同時發(fā)送數(shù)據(jù)或接收數(shù)據(jù),往往數(shù)據(jù)時單向進(jìn)行的,即發(fā)送的時候不接收數(shù)據(jù),或接收的時候不發(fā)送數(shù)據(jù)。
基于常見的SPI從機(jī)器件的操作方法,AWorks定義了兩種情形下的數(shù)據(jù)通信:先寫入一段數(shù)據(jù)至從機(jī),再讀取一段數(shù)據(jù);先寫入一段數(shù)據(jù)至從機(jī),再寫入一段數(shù)據(jù)。之所以均是先寫入一段數(shù)據(jù),是因為絕大多數(shù)數(shù)從機(jī)器件在操作前,首先都要發(fā)送一段命令數(shù)據(jù)至從機(jī),以指定接下來的具體操作(讀數(shù)據(jù)或?qū)憯?shù)據(jù))。
先寫后讀即是主機(jī)先發(fā)送數(shù)據(jù)至從機(jī)(寫),再自從機(jī)接收數(shù)據(jù)(讀)。注意,該函數(shù)會等待數(shù)據(jù)傳輸完成后才會返回,因此該函數(shù)是阻塞式的,不應(yīng)在中斷環(huán)境中調(diào)用。其函數(shù)原型為:
其中,p_dev指向從機(jī)器件實例,表示本次數(shù)據(jù)通信的目標(biāo)對象,p_txbuf指向需要首先寫入從機(jī)的數(shù)據(jù),n_tx為寫入數(shù)據(jù)的字節(jié)數(shù)。p_rxbuf指向數(shù)據(jù)發(fā)送完成后,接收數(shù)據(jù)的緩沖區(qū),n_rx為接收數(shù)據(jù)的個數(shù)。返回值為標(biāo)準(zhǔn)的錯誤號,返回AW_OK時表示數(shù)據(jù)傳輸成功,否則,表示數(shù)據(jù)傳輸失敗。
注意,若只需要寫入數(shù)據(jù),不需要讀取數(shù)據(jù),則可以將p_rxbuf設(shè)置為NULL,n_rx設(shè)置為0,同理,若只需要讀取數(shù)據(jù),不需要發(fā)送數(shù)據(jù),則可以將p_txbuf設(shè)置為NULL,n_tx設(shè)置為0。例如,需要發(fā)送數(shù)據(jù)至74HC595,以并行輸出8位數(shù)據(jù)0x55,則范例程序詳見程序清單7.22。
程序清單7.22 先寫后讀范例程序(1)
為了更加直觀的觀察輸出數(shù)據(jù)是否正確,可以將MiniPort-LED與MiniPort-595連接,等效電路圖詳見圖7.10,由此可見,74HC595的輸出端為低電平時,對應(yīng)LED點亮, 0x55對應(yīng)的二進(jìn)制為01010101,因此,若成功輸出,則可以觀察到LED1、LED3、LED5和LED7被點亮,LED0、LED2、LED4和LED6被熄滅。
圖7.10 MiniPort-595 + MiniPort-LED等效電路圖
由于74HC595使用簡單,只能寫入數(shù)據(jù),因此,上述范例程序并沒有用到讀取數(shù)據(jù)。實際上,對于常見的SPI從機(jī)器件,其通信協(xié)議往往都是采用“命令”+“數(shù)據(jù)”的格式。如典型的SPI FLASH從機(jī)器件:MX25L1606,在對其操作時,均需要先寫1字節(jié)的命令,后續(xù)再是具體的數(shù)據(jù),具體數(shù)據(jù)的含義隨著命令的不同而不同。例如,每個MX25L1606內(nèi)部具有一個3字節(jié)的電子ID號(RDID),如需讀取該ID,則需要先發(fā)送單字節(jié)的命令0x9f。則使用先寫后讀接口讀取ID的關(guān)鍵語句詳見程序清單7.23。
程序清單7.23 先寫后讀范例程序(2)
更多命令以及RDID的含義詳見相應(yīng)的數(shù)據(jù)手冊,這里僅用于說明對于這種常見的操作方法,如何正確的使用SPI接口。
5. 連續(xù)兩次寫
連續(xù)兩次寫,即主機(jī)先發(fā)送一段數(shù)據(jù)至從機(jī)(寫),發(fā)送結(jié)束后,再發(fā)送一段數(shù)據(jù)至從機(jī)(寫)。注意,該函數(shù)會等待數(shù)據(jù)傳輸完成后才會返回,因此該函數(shù)是阻塞式的,不應(yīng)在中斷環(huán)境中調(diào)用。其函數(shù)原型為:
其中,p_dev指向從機(jī)器件實例,表示本次數(shù)據(jù)通信的目標(biāo)對象,p_txbuf0指向需要首先寫入從機(jī)的數(shù)據(jù),n_tx0為寫入數(shù)據(jù)的字節(jié)數(shù)。p_txbuf0指向數(shù)據(jù)發(fā)送完成后,開始發(fā)送下一段數(shù)據(jù),p_txbuf1指向需要再次寫入從機(jī)的數(shù)據(jù),n_tx1為寫入數(shù)據(jù)的字節(jié)數(shù)。返回值為標(biāo)準(zhǔn)的錯誤號,返回AW_OK時表示數(shù)據(jù)傳輸成功,否則,表示數(shù)據(jù)傳輸失敗。
注意,若只需要寫入一段數(shù)據(jù),則可以將p_txbuf1設(shè)置為NULL,n_tx1設(shè)置為0。
同樣可以使用該接口發(fā)送數(shù)據(jù)至74HC595,例如,使用MiniPort-595控制MiniPort-LED,使LED0 ~ LED7依次循環(huán)點亮,實現(xiàn)簡易的流水燈效果,范例程序詳見程序清單7.24。
程序清單7.24 執(zhí)行連續(xù)兩次寫的范例程序(1)
程序中,由于LED是低電平點亮,因此,通過74HC595輸出數(shù)據(jù)時,需要將data取反,以便使數(shù)據(jù)中與需要點亮的LED相應(yīng)位的值為0。
由于74HC595只能寫入單字節(jié)數(shù)據(jù),因此,上述范例程序并沒有使用到第二次的數(shù)據(jù)寫入,第二次寫入的數(shù)據(jù)緩沖區(qū)被設(shè)定為了NULL。為了更全面的說明該接口的用法,同樣以MX25L1606為例,如果要在SPI FLASH存儲器中存入一段數(shù)據(jù),則應(yīng)先發(fā)送命令0x02和存儲數(shù)據(jù)的起始地址(3字節(jié),24位),接著再發(fā)送實際的待存儲的數(shù)據(jù)。寫入數(shù)據(jù)至指定地址的關(guān)鍵語句詳見程序清單7.25。
程序清單7.25 執(zhí)行連續(xù)兩次寫的范例程序(2)
實際中,寫入數(shù)據(jù)前,應(yīng)確保相應(yīng)區(qū)域被擦除,擦除同樣有相關(guān)的命令,更多命令以及數(shù)據(jù)存儲的注意事項詳見相應(yīng)的數(shù)據(jù)手冊,這里僅用于說明連續(xù)兩次寫接口的使用方法。
-
mcu
+關(guān)注
關(guān)注
146文章
16885瀏覽量
349918 -
嵌入式
+關(guān)注
關(guān)注
5059文章
18973瀏覽量
302033
原文標(biāo)題:AWorks軟件篇 — 通用外設(shè)接口(GPIO、PWM、SPI)
文章出處:【微信號:ZLG_zhiyuan,微信公眾號:ZLG致遠(yuǎn)電子】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論