现代传感器的接口:中断驱动的ADC驱动程序
現(xiàn)代傳感器的接口:中斷驅動的ADC驅動程序
Interfacing with modern sensors: Interrupt driven ADC drivers
研究了如何編寫一個阻塞的模數(shù)轉換器(ADC)驅動程序和一個使用輪詢技術不阻塞應用程序流的驅動程序。輪詢外圍設備的驅動程序效率低下,如果系統(tǒng)處于低功耗狀態(tài),可能會浪費寶貴的時鐘周期,否則會浪費能量。開發(fā)人員實現(xiàn)ADC驅動程序的一種有效方法是使用中斷來通知應用程序轉換周期已經完成。在本文中,將研究如何做到這一點。
更新ADC驅動程序示例函數(shù)
有幾種不同的方法可以編寫ADC驅動程序來使用中斷。在本文中,將介紹如何修改上一篇文章中介紹的非阻塞ADC驅動程序。應用程序可以通過調用函數(shù)ADC_Sample來啟動ADC轉換。
這是一個很好的例子,為什么有一個好的硬件抽象層(HAL)可以派上用場。無論是阻塞,還是阻塞、輪詢或中斷,都會調用完全相同的函數(shù),其行為只是根據驅動程序的配置設置而改變,或者可能會根據應用程序的需要鏈接到不同版本的Adc_Sample函數(shù)中。
非阻塞系統(tǒng)的Adc_Sample函數(shù)如下所示:
bool Adc_Sample(void)
{
AdcPin_t AdcPin = AdcChannel0;static bool SampleInProgress = false;bool SampleComplete = false;if(SampleInProgress == false){if(Adc_SampleIndex == ADC_SAMPLE_SIZE){Adc_SampleIndex = 0;}
SampleInProgress = true;
Adc_StartConversion();}else{if(Adc_ConversionComplete == true){for(AdcPin = AdcChannel0; AdcPin
< NUM_ANALOG_PINS; AdcPin++)
{Adc_SampleBuffer[i][Adc_SampleIndex]
= *AD1BufPtr++;
}Adc_SampleIndex++;SampleComplete = true;}return SampleComplete;}
新版本中,Adc_Sample函數(shù)可能實現(xiàn)如下所示:
bool Adc_Sample(void){ Adc_StartConversion(); return true; }
非阻塞驅動程序有各種各樣的檢查和對緩沖區(qū)的訪問等。對于基于中斷的驅動程序,所要做的就是啟動基于外圍設備的ADC通道轉換,這是在初始化期間配置的。因此,例如,如果要對通道0、1和3進行采樣,這些通道將是在初始化過程中啟用的通道。這個驅動程序是一次采樣所有指定的通道,而不是只采樣一個或兩個。正如所提到的,有很多方法可以做到這一點,并幫助澄清概念,正在使用最簡單的解決方案。
此時,如果調用Adc_StartConversion,希望Adc外圍設備對通道進行采樣,但是當中斷觸發(fā)時,此時不會發(fā)生任何事情。需要填充ADC中斷處理程序,但是在驅動程序中這樣做是有問題的。相反,如果可以的話,希望嘗試抽象中斷處理程序代碼。
中斷的抽象化
開發(fā)人員在編寫驅動程序時經常遇到的一個問題是,當開發(fā)一個中斷驅動的解決方案時,常常將中斷與應用程序代碼緊密耦合。最佳情況下,中斷將駐留在驅動程序層中的驅動程序代碼中,而不是位于體系結構中最高層的應用程序代碼中。將中斷與應用程序代碼緊密耦合會使移植代碼變得困難,甚至在某些情況下甚至會對其進行縮放。
開發(fā)人員可以使用一個解決方案,將中斷保留在驅動程序層中,并仍然為應用程序自定義,這就是使用回調。回調函數(shù)是對可執(zhí)行代碼的引用,該代碼作為參數(shù)傳遞給其代碼,后者允許較低級別的軟件層調用在高級層中定義的函數(shù)[1]。回調函數(shù)最簡單的就是作為參數(shù)傳遞給另一個函數(shù)的函數(shù)指針。在大多數(shù)情況下,回調將包含三個部分:
回調函數(shù)
回調注冊
回調執(zhí)行
在典型的回調實現(xiàn)中,這三個部分是如何協(xié)同工作的,如下圖所示:
Figure: Typical callback architecture.
ADC驅動程序HAL包含以下功能:
void Adc_CallbackRegister(AdcCallback_t const Function, void (*CallbackFunction)(void));
如果仔細看一下,這個函數(shù)被設計成從應用程序代碼向ADC驅動程序注冊一個回調函數(shù)。第一個參數(shù)指定回調將分配給哪個中斷,而第二個參數(shù)通過向函數(shù)傳遞函數(shù)指針來指定要調用的函數(shù)。
此時的低級驅動程序會將函數(shù)指針分配給指定的中斷。這是非常靈活的,因為開發(fā)人員可以輕松地更新和更改中斷執(zhí)行的函數(shù),而不必返回、修改和重新編譯adc驅動程序。這有助于將應用程序代碼從驅動程序代碼中分離出來,從而創(chuàng)建一個可伸縮和靈活的解決方案。
有了這些知識,可以實現(xiàn)ADC中斷處理程序,如下所示:
void ADC_IRQHandler(void){ (*ADC_Interrupt1)(); }
中斷只不過是取消對通過Adc_CallbackRegister()函數(shù)分配的指針的引用。
編寫中斷處理程序
對于使用這種方法的開發(fā)人員來說,中斷處理程序將被寫在應用程序層中,并且可以有喜歡的幾乎任何函數(shù)名。把命名為Adc_InterruptCallback,該回調的實現(xiàn)可能因應用程序而異。例如,在一個應用程序中,回調可能如下所示:
void Adc_CallbackRegister(void){ tx_semaphore_pu(&Adc1Semaphore);}
在本例中,回調只是簡單地放置一個信號量來通知任務ADC數(shù)據可用。另一個示例可能如下所示:
void Adc_CallbackRegister(void){ AdcPin = AdcChannel0; // Loop through and store the buffer data for(AdcPin = AdcChannel0; AdcPin < NUM_ANALOG_PINS; AdcPin++) { Adc_SampleBuffer[i][Adc_SampleIndex] = *AD1BufPtr++; } Adc_SampleIndex++; if(Adc_SampleIndex == ADC_SAMPLE_SIZE) { Adc_SampleIndex = 0; }}
如所見,由開發(fā)人員決定如何在中斷處理程序中處理模擬數(shù)據,并且根據應用程序及其需要,會有很大的不同。
需要注意的是,對于這些真正是中斷處理程序的回調函數(shù),遵循中斷處理程序的最佳實踐是很重要的。這意味著最小化代碼,并使其盡可能快地減少對系統(tǒng)其余性能的影響。
結論
正如在本文中看到的,使用中斷驅動驅動程序設計模式可以顯著提高驅動程序的效率。使用回調可以將中斷實現(xiàn)保留在應用程序代碼中,并通過驅動程序的回調機制分配給中斷。這使得解決方案和代碼具有高度可重用性、靈活性和可伸縮性。
總結
以上是生活随笔為你收集整理的现代传感器的接口:中断驱动的ADC驱动程序的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 与现代传感器的接口:轮询ADC驱动程序
- 下一篇: 固件安全性—防止内存损坏和注入攻击