色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

如何編寫基于ARM的裸機(jī)程序和基于Linux的驅(qū)動(dòng)程序

Linux愛好者 ? 來源:一口Linux ? 作者:一口Linux ? 2020-09-13 09:25 ? 次閱讀

前言

嵌入式開發(fā)中,ADC應(yīng)用比較頻繁,本文主要講解ADC的基本原理以及如何編寫基于ARM的裸機(jī)程序和基于Linux的驅(qū)動(dòng)程序。

ARM架構(gòu):Cortex-A9 Linux內(nèi)核:3.14

在講述ADC之前,我們需要先了解什么是模擬信號(hào)數(shù)字信號(hào)

模擬信號(hào)

主要是與離散的數(shù)字信號(hào)相對(duì)的連續(xù)的信號(hào)。模擬信號(hào)分布于自然界的各個(gè)角落,如每天溫度的變化,而數(shù)字信號(hào)是人為的抽象出來的在時(shí)間上不連續(xù)的信號(hào)。電學(xué)上的模擬信號(hào)是主要是指幅度和相位都連續(xù)的電信號(hào),此信號(hào)可以被模擬電路進(jìn)行各種運(yùn)算,如放大,相加,相乘等。

模擬信號(hào)是指用連續(xù)變化的物理量表示的信息,其信號(hào)的幅度,或頻率,或相位隨時(shí)間作連續(xù)變化,如目前廣播的聲音信號(hào),或圖像信號(hào)等。

如下圖所示從上到下一次是正弦波、 調(diào)幅波、 阻尼震蕩波、 指數(shù)衰減波 。

數(shù)字信號(hào)

數(shù)字信號(hào)指幅度的取值是離散的,幅值表示被限制在有限個(gè)數(shù)值之內(nèi)。二進(jìn)制碼就是一種數(shù)字信號(hào)。二進(jìn)制碼受噪聲的影響小,易于有數(shù)字電路進(jìn)行處理,所以得到了廣泛的應(yīng)用。

數(shù)字信號(hào):高清數(shù)字電視,MP3,JPG,PNG文件等等。

優(yōu)點(diǎn):

1. 抗干擾能力強(qiáng)、無噪聲積累

在模擬通信中,為了提高信噪比,需要在信號(hào)傳輸過程中及時(shí)對(duì)衰減的傳輸信號(hào)進(jìn)行放大,信號(hào)在傳輸過程中不可避免地疊加上的噪聲也被同時(shí)放大。

隨著傳輸距離的增加,噪聲累積越來越多,以致使傳輸質(zhì)量嚴(yán)重惡化。

對(duì)于數(shù)字通信,由于數(shù)字信號(hào)的幅值為有限個(gè)離散值(通常取兩個(gè)幅值),在傳輸過程中雖然也受到噪聲的干擾,但當(dāng)信噪比惡化到一定程度時(shí),

即在適當(dāng)?shù)木嚯x采用判決再生的方法,再生成沒有噪聲干擾的和原發(fā)送端一樣的數(shù)字信號(hào),所以可實(shí)現(xiàn)長(zhǎng)距離高質(zhì)量的傳輸。

2. 便于加密處理

信息傳輸?shù)陌踩院捅C苄栽絹碓街匾瑪?shù)字通信的加密處理的比模擬通信容易得多,以話音信號(hào)為例,經(jīng)過數(shù)字變換后的信號(hào)可用簡(jiǎn)單的數(shù)字邏輯運(yùn)算進(jìn)行加密、解密處理。

3. 便于存儲(chǔ)、處理和交換

數(shù)字通信的信號(hào)形式和計(jì)算機(jī)所用信號(hào)一致,都是二進(jìn)制代碼,因此便于與計(jì)算機(jī)聯(lián)網(wǎng),也便于用計(jì)算機(jī)對(duì)數(shù)字信號(hào)進(jìn)行存儲(chǔ)、處理和交換,

可使通信網(wǎng)的管理、維護(hù)實(shí)現(xiàn)自動(dòng)化、智能化。

4. 設(shè)備便于集成化、微型

數(shù)字通信采用時(shí)分多路復(fù)用,不需要體積較大的濾波器。設(shè)備中大部分電路是數(shù)字電路,可用大規(guī)模和超大規(guī)模集成電路實(shí)現(xiàn),因此體積小、功耗低。

5. 便于構(gòu)成綜合數(shù)字網(wǎng)和綜合業(yè)務(wù)數(shù)字網(wǎng)

采用數(shù)字傳輸方式,可以通過程控?cái)?shù)字交換設(shè)備進(jìn)行數(shù)字交換,以實(shí)現(xiàn)傳輸和交換的綜合。

另外,電話業(yè)務(wù)和各種非話業(yè)務(wù)都可以實(shí)現(xiàn)數(shù)字化,構(gòu)成綜合業(yè)務(wù)數(shù)字網(wǎng)。

6. 占用信道頻帶較寬

一路模擬電話的頻帶為4kHz帶寬,一路數(shù)字電話約占64kHz,這是模擬通信目前仍有生命力的主要原因。隨著寬頻帶信道(光纜、數(shù)字微波)的大量利用(一對(duì)光纜可開通幾千路電話)以及數(shù)字信號(hào)處理技術(shù)的發(fā)展(可將一路數(shù)字電話的數(shù)碼率由64kb/s壓縮到32kb/s甚至更低的數(shù)碼率),數(shù)字電話的帶寬問題已不是主要問題了。

常用的數(shù)字信號(hào)編碼有不歸零(NRZ)編碼、 曼徹斯特(Manchester)編碼和差分曼徹斯特(Differential Manchester)編碼。

數(shù)字信號(hào)與模擬信號(hào)的轉(zhuǎn)化

模擬信號(hào)和數(shù)字信號(hào)之間可以相互轉(zhuǎn)換:模擬信號(hào)一般通過PCM脈碼調(diào)制(Pulse Code Modulation)方法量化為數(shù)字信號(hào),

即讓模擬信號(hào)的不同幅度分別對(duì)應(yīng)不同的二進(jìn)制值,例如采用8位編碼可將模擬信號(hào)量化為2^8=256個(gè)量級(jí),實(shí)用中常采取24位或30位編碼;

數(shù)字信號(hào)一般通過對(duì)載波進(jìn)行移相(Phase Shift)的方法轉(zhuǎn)換為模擬信號(hào)。計(jì)算機(jī)、計(jì)算機(jī)局域網(wǎng)與城域網(wǎng)中均使用二進(jìn)制數(shù)字信號(hào),

目前在計(jì)算機(jī)廣域網(wǎng)中實(shí)際傳送的則既有二進(jìn)制數(shù)字信號(hào),也有由數(shù)字信號(hào)轉(zhuǎn)換而得的模擬信號(hào)。但是更具應(yīng)用發(fā)展前景的是數(shù)字信號(hào)。

PCM脈沖編碼調(diào)制

脈沖編碼調(diào)制就是把一個(gè)時(shí)間連續(xù),取值連續(xù)的模擬信號(hào)變換成時(shí)間離散,取值離散的數(shù)字信號(hào)后在信道中傳輸。

脈沖編碼調(diào)制就是對(duì)模擬信號(hào)先抽樣,再對(duì)樣值幅度量化, 編碼的過程。

抽樣:

就是對(duì)模擬信號(hào)進(jìn)行周期性掃描,把時(shí)間上連續(xù)的信號(hào)變成時(shí)間上離散的信號(hào)。

該模擬信號(hào)經(jīng)過抽樣后還應(yīng)當(dāng)包含原信號(hào)中所有信息,也就是說能無失真的恢復(fù)原模擬信號(hào)。

量化:

就是把經(jīng)過抽樣得到的瞬時(shí)值將其幅度離散,即用一組規(guī)定的電平,把瞬時(shí)抽樣值用最接近的電平值來表示,通常是用二進(jìn)制表示。

編碼:

就是用一組二進(jìn)制碼組來表示每一個(gè)有固定電平的量化值。然而,實(shí)際上量化是在編碼過程中同時(shí)完成的,故編碼過程也稱為模/數(shù)變換,可記作A/D。

ADC

ADC,Analog-to-Digital Converter的縮寫,指模/數(shù)轉(zhuǎn)換器或者模數(shù)轉(zhuǎn)換器。是指將連續(xù)變化的模擬信號(hào)轉(zhuǎn)換為離散的數(shù)字信號(hào)的器件。真實(shí)世界的模擬信號(hào),例如溫度、壓力、聲音或者圖像等,需要轉(zhuǎn)換成更容易儲(chǔ)存、處理和發(fā)射的數(shù)字形式。模/數(shù)轉(zhuǎn)換器可以實(shí)現(xiàn)這個(gè)功能,在各種不同的產(chǎn)品中都可以找到它的身影。

ADC最早用于對(duì)無線信號(hào)向數(shù)字信號(hào)轉(zhuǎn)換。如電視信號(hào),長(zhǎng)短播電臺(tái)發(fā)接收等。

與之相對(duì)應(yīng)的DAC,Digital-to-Analog Converter,它是ADC模數(shù)轉(zhuǎn)換的逆向過程。

現(xiàn)在市場(chǎng)上的電子產(chǎn)品都集成了傳感器,傳感器要采集數(shù)據(jù),他的內(nèi)部結(jié)構(gòu)里就一定要用到ADC,常見的傳感器如下:

溫濕度:溫度傳感器,DHT11 聲音:音頻芯片進(jìn)行錄音,WM8906 圖像:索尼IMX386/IMX283傳感器

Exynos4412 A/D轉(zhuǎn)換器

三星的Exynos4412模塊結(jié)構(gòu)圖如下所示:

Adc控制器集成在exynos4412 soc中,控制器內(nèi)部有一根中斷線連接到中斷控制器combiner,然后路由到GIC(Generic Interrupt Controller),滑動(dòng)變阻器連接到adc控制器的通道3。

ADC控制器

參考《Exynos 4412 SCP》 的datasheet。

ADC控制器是10位或12位CMOS再循環(huán)式模擬數(shù)字轉(zhuǎn)換器,它具有10個(gè)通道輸入,并可將模擬量轉(zhuǎn)換至10位或12位二進(jìn)制數(shù)。5Mhz A/D 轉(zhuǎn)換時(shí)鐘,最大1Msps的轉(zhuǎn)換速度。A/D轉(zhuǎn)換具備片上采樣保持功能,同時(shí)也支持待機(jī)工作模式。

ADC接口包括如下特性。

10bit/12bit輸出位可選。

微分誤差 1.0LSB。

積分誤差 2.0LSB。

最大轉(zhuǎn)換速率5Msps.

功耗少,電壓輸入1.8V。

電壓輸入范圍 0~1.8V。

支持偏上樣本保持功能。

通用轉(zhuǎn)換模式。

模塊圖

4412 A/D轉(zhuǎn)換器的控制器接口框圖如下:

原理我們并不需要關(guān)注,知道即可。

通道選擇

由上圖可知,A/D控制器一共有4個(gè)通道,通用寄存器地址為0x126c0000。

A/D控制器寄存器

對(duì)ADC控制器的操作主要是通過配置寄存器來實(shí)現(xiàn)的,查看datasheet,必須掌握寄存器的使用。以下是A/D控制器寄存器匯總。

1、A/D控制寄存器ADCCON

RES : 選擇A/D轉(zhuǎn)換精度,0:劃分成1024份1:劃分成4096份

ECFLG :轉(zhuǎn)換是否結(jié)束 0:轉(zhuǎn)換中 1:轉(zhuǎn)換完畢;對(duì)于輪詢模式需要根據(jù)該位判斷數(shù)據(jù)是否轉(zhuǎn)換完畢。

PRSCEN:A/D轉(zhuǎn)換預(yù)分頻是否使能

PRSCVL:預(yù)分頻的值,轉(zhuǎn)換公式見下面

STANDBY:待機(jī)模式 0:正常工作模式 1:待機(jī)模式。處于待機(jī)模式時(shí)要將PRSCEN設(shè)置為0

READ_START: A/D轉(zhuǎn)換由讀操作觸發(fā),設(shè)置為1后,每次讀取A/D值的操作都會(huì)觸發(fā)一次A/D轉(zhuǎn)換。

ENABLE_START: 單次開啟A/D轉(zhuǎn)換,轉(zhuǎn)換完畢后該位自動(dòng)清零,當(dāng)READ_START設(shè)置為1的時(shí)候,該位無效。

通常設(shè)置值為(1 << 16 | 1 << 14 | 99 <<6 | 1 << 1)。

2、A/D轉(zhuǎn)換數(shù)據(jù)寄存器ADCDAT0

注意該寄存器的值只有低12位有效。

3、A/D清中斷寄存器CLRINTADC

黃色部分可知,中斷例程負(fù)責(zé)清中斷,中斷結(jié)束后寫入任意值就可以清中斷。

4、A/D通道選擇寄存器ADCMUX

每次操作都要先設(shè)置通道,因?yàn)?4個(gè)通道是共用同一套寄存器,如果有其他任務(wù)也在使用A/D,就會(huì)產(chǎn)生混亂。在此我們選擇通道3,置3即可。

5、ADC中斷ID

參見9.2.2GIC Interrupt Table

由此可知,ADC中斷號(hào)對(duì)應(yīng)的SPI值是10,inturrupt ID 為42。對(duì)于終端查詢方式和編寫終端的驅(qū)動(dòng)需要知道SPI id和inturrupt ID,后面講解基于Linux驅(qū)動(dòng)還會(huì)再分析設(shè)備樹節(jié)點(diǎn)如何填寫。

6、Combiner中斷控制器

combiner的配置寄存器:IMSRn、IECRn、ISERn、ISTRn,類似于GPIO 對(duì)中斷源分組。只有中斷模式才需要考慮combiner中斷控制器的操作。

7、Combiner分組

參考章節(jié):10.2.1Interrupt Combiner Table 10-1Interrupt Groups of Interrupt Combiner

可見ADC在INTG10,即第10組。

8、Combiner IESR2

參考章節(jié):10.4.2.9IESR2

如果要用中斷模式設(shè)置為1即可。

9、Combiner IECR2

參考章節(jié):10.4.2.10IECR2

此處用于關(guān)閉中斷,采用默認(rèn)值即可,注意,如果設(shè)置了1,那么中斷功能就關(guān)閉了。

10、A/D轉(zhuǎn)換的轉(zhuǎn)換時(shí)間計(jì)算

例如:PCLK為100MHz,PRESCALER = 65 ;所有10位轉(zhuǎn)換時(shí)間為

100MHz/(99+1) = 1MHz

轉(zhuǎn)化時(shí)間為1/(1MHz/5 cycles) = 5us。

完成一次A/D轉(zhuǎn)換需要5個(gè)時(shí)鐘周期。A/D轉(zhuǎn)換器的最大工作時(shí)鐘為5MHz,所以最大采樣率可以達(dá)到1Mit/s.

電路連接圖

由該電路圖可知,外設(shè)是一個(gè)滑動(dòng)變阻器,根據(jù)接觸點(diǎn)的不同,會(huì)導(dǎo)致輸入電壓的模擬值不同。連接的A/D控制器通道為3。該電路利用一個(gè)電位計(jì)輸出電壓到4412的AIN3管腳。輸入的電壓范圍為0~1.8V。

ADC裸機(jī)開發(fā)程序?qū)嵗?/p>

ADC數(shù)據(jù)的讀取通常由2種方法:中斷模式、輪詢模式。

輪詢模式

輪詢模式讀取數(shù)據(jù)步驟如下:

1.要讀取數(shù)據(jù)首先向ADC寄存器ADCCON的bit:1寫1,發(fā)送轉(zhuǎn)換命令,采用讀-啟動(dòng)模式來開啟轉(zhuǎn)換。

2.當(dāng)ADC控制器轉(zhuǎn)換完畢會(huì)將ADCCON的bit:15設(shè)置為1,

3.輪詢檢測(cè)ADCCON的bit:15是否設(shè)置為1,如果設(shè)置為1,就讀走數(shù)據(jù),否則繼續(xù)等待。

這種方式比較占用CPU資源。

//注:這里使用讀-啟動(dòng)模式

/***********************ADC******************/ #defineADC_CFG__REG(0x10010118) #defineADCCON__REG(0x126C0000) #defineADCDLY__REG(0x126C0008) #defineADCDAT__REG(0x126C000C) #defineCLRINTADC__REG(0x126C0018) #defineADCMUX__REG(0x126C001C) #include"exynos_4412.h" #include"pwm.h" #include"uart.h" unsignedchartable[10]={'0','1','2','3','4','5','6','7','8','9'}; voidmydelay_ms(inttime) { inti,j; while(time--) { for(i=0;i

中斷模式

中斷模式讀取數(shù)據(jù)步驟如下:

1.要讀取數(shù)據(jù)首先向ADC寄存器ADCCON的bit:0寫1,發(fā)送轉(zhuǎn)換命令;

2.當(dāng)ADC控制器轉(zhuǎn)換完畢會(huì)通過中斷線向CPU發(fā)送中斷信號(hào);

3.在中斷處理函數(shù)中,讀走數(shù)據(jù),并清中斷.

注:中斷對(duì)應(yīng)寄存器的設(shè)置,后續(xù)會(huì)更新對(duì)應(yīng)的文檔。

voiddo_irq(void) { intirq_num; irq_num=CPU0.ICCIAR&0x3ff; switch(irq_num) { case42: adc_num=ADCDAT&0xfff; printf("adc=%d ",adc_num); CLRINTADC=0; //IECR2=IECR2|(1<

基于Linux驅(qū)動(dòng)編寫

設(shè)備樹

編寫基于Linux的ADC外設(shè)驅(qū)動(dòng),首先需要編寫設(shè)備樹節(jié)點(diǎn)信息,在裸機(jī)程序中,我們只用到了寄存器地址,而編寫基于Linux的驅(qū)動(dòng),我們需要用到中斷功能。所以編寫設(shè)備樹節(jié)點(diǎn)需要知道ADC要用到的硬件資源主要包括:寄存器資源和中斷資源。

關(guān)于中斷的使用我們?cè)诤罄m(xù)文章中會(huì)繼續(xù)分析,現(xiàn)在我們只需要知道中斷信息如何填寫即可。

ADC寄存器信息填寫

由上可知,寄存器基地址為0x126c0000,其他寄存器只需要根據(jù)基地址做偏移即可獲取,所以設(shè)備樹的reg屬性信息如下:

reg=<0x126C0000?0x20>;

ADC中斷信息填寫

描述中斷連接需要四個(gè)屬性:

父節(jié)點(diǎn)提供以下信息

interrupt-controller -一個(gè)空的屬性定義該節(jié)點(diǎn)作為一個(gè)接收中斷信號(hào)的設(shè)備。 interrupt-cells -這是一個(gè)中斷控制器節(jié)點(diǎn)的屬性。它聲明了該中斷控制器的 中斷指示符中【interrupts】 cell 的個(gè)數(shù)(類似于#address-cells 和#size-cells)。

子節(jié)點(diǎn)描述信息

interrupt-parent - 這是一個(gè)設(shè)備節(jié)點(diǎn)的屬性,包含一個(gè)指向該設(shè)備連接的中斷控制器的 phandle。那些沒有 interrupt-parent 的節(jié)點(diǎn)則從它們的父節(jié)點(diǎn)中繼承該屬性。 iterrupts - 一個(gè)設(shè)備節(jié)點(diǎn)屬性,包含一個(gè)中斷指示符的列表,對(duì)應(yīng)于該設(shè)備上的 每個(gè)中斷輸出信號(hào)。【設(shè)備的中斷信息放在該屬性中】

父節(jié)點(diǎn)

首先我們必須知道ADC控制器的中斷線的父節(jié)點(diǎn):

由上圖可知ADC控制器位于soc內(nèi),4個(gè)ADC通道公用一根中斷線,該中斷線連接在combiner上,所以我們需要查找到combiner這個(gè)父節(jié)點(diǎn)的說明:

進(jìn)入設(shè)備樹文件所在目錄:archarmootdts

grepcombiner*.*-n

經(jīng)過篩選得到以下信息:

因?yàn)槲覀兪褂玫陌遄邮莈xynos4412,而exynos系列通用的平臺(tái)設(shè)備樹文件是exynos4.dtsi,查看該文件:

上圖列舉了combiner控制器的詳細(xì)信息:

interrupt-cells; interrupt-cells=<2>;

所以ADC控制器中斷控制器的interrupts屬性應(yīng)該有兩個(gè)cell。

interrupts屬性填寫

而設(shè)備的中斷信息填寫方式由內(nèi)核的以下文檔提供:

Documentationdevicetreeindingsinterrupt-controllerinterrupts.txt69.b)twocells 70.------------ 71.The#interrupt-cellspropertyissetto2andthefirstcell72.definesthe 73.indexoftheinterruptwithinthecontroller,whilethesecondcellisused 74.tospecifyanyofthefollowingflags: 75.-bits[3:0]triggertypeandlevelflags 76.1=low-to-highedgetriggered 77.2=high-to-lowedgetriggered 78.4=activehighlevel-sensitive 79.8=activelowlevel-sensitive

由以上信息可知,中斷的第一個(gè)cell是該中斷源所在中斷控制器的index,第二個(gè)cell表示中斷的觸發(fā)方式

上升沿觸發(fā)

下降沿觸發(fā)

高電平觸發(fā)

低電平觸發(fā)

那么index應(yīng)該是多少呢?

詳見datasheet的9.2.2 GIC Interrupt Table 節(jié):

此處我們應(yīng)該是填寫左側(cè)的SPI ID:10 還是填寫INTERRUPT ID:42呢?

此處我們可以參考LCD節(jié)點(diǎn)的interrupts填寫方法:

通過查找父節(jié)點(diǎn)為combiner的設(shè)備信息。

繼續(xù)grep combiner.-n

由此可見lcd這個(gè)設(shè)備的interrupts屬性index值是11,所以可知ADC控制器中斷線的index是10。中斷信息如下:

interrupt-parent=<&combiner>; interrupts=<10?3>;

ADC外設(shè)設(shè)備樹信息

fs4412-adc{ compatible="fs4412,adc"; reg=<0x126C0000?0x20>; interrupt-parent=<&combiner>; interrupts=<10?3>; };

本文默認(rèn)大家會(huì)使用設(shè)備樹,不知道如何使用設(shè)備樹的朋友,后續(xù)會(huì)開一篇單獨(dú)講解設(shè)備樹。

【注意】在不支持設(shè)備樹內(nèi)核中,以Cortex-A8為例,中斷信息填寫在以下文件中

內(nèi)部中斷,Irqs.h(archarmmach-s5pc100includemach) 外部中斷在Irqs.h(archarmplat-s5pincludeplat)

ADC屬于內(nèi)部中斷,位于archarmmach-s5pc100includemachIrqs.h中。

寄存器信息填寫在以下位置:

archarmmach-s5pc100Mach-smdkc100.cstaticstructplatform_device*smdkc100_devices[]__initdata={ &s3c_device_adc, &s3c_device_cfcon, &s3c_device_i2c0, &s3c_device_i2c1, &s3c_device_fb, &s3c_device_hsmmc0, &s3c_device_hsmmc1, &s3c_device_hsmmc2, &samsung_device_pwm, &s3c_device_ts, &s3c_device_wdt, &smdkc100_lcd_powerdev, &s5pc100_device_iis0, &samsung_device_keypad, &s5pc100_device_ac97, &s3c_device_rtc, &s5p_device_fimc0, &s5p_device_fimc1, &s5p_device_fimc2, &s5pc100_device_spdif, };

結(jié)構(gòu)體s3c_device_adc定義在以下文件:

archarmplat-samsungDevs.c#ifdefCONFIG_PLAT_S3C24XX staticstructresources3c_adc_resource[]={ [0]=DEFINE_RES_MEM(S3C24XX_PA_ADC,S3C24XX_SZ_ADC), [1]=DEFINE_RES_IRQ(IRQ_TC), [2]=DEFINE_RES_IRQ(IRQ_ADC), }; structplatform_devices3c_device_adc={ .name="s3c24xx-adc", .id=-1, .num_resources=ARRAY_SIZE(s3c_adc_resource), .resource=s3c_adc_resource, }; #endif/*CONFIG_PLAT_S3C24XX*/ #ifdefined(CONFIG_SAMSUNG_DEV_ADC) staticstructresources3c_adc_resource[]={ [0]=DEFINE_RES_MEM(SAMSUNG_PA_ADC,SZ_256), [1]=DEFINE_RES_IRQ(IRQ_TC), [2]=DEFINE_RES_IRQ(IRQ_ADC), }; structplatform_devices3c_device_adc={ .name="samsung-adc", .id=-1, .num_resources=ARRAY_SIZE(s3c_adc_resource), .resource=s3c_adc_resource, }; #endif/*CONFIG_SAMSUNG_DEV_ADC*/

由代碼可知,平臺(tái)驅(qū)動(dòng)對(duì)應(yīng)的platform_device具體內(nèi)容由宏CONFIG_PLAT_S3C24XX、CONFIG_SAMSUNG_DEV_ADC來控制。

驅(qū)動(dòng)編寫架構(gòu)和流程如下

read() { 1、向adc設(shè)備發(fā)送要讀取的命令 ADCCON1<<0?|?1<<14?|?0X1<<16?|?0XFF<<6 ???????2、讀取不到數(shù)據(jù)就休眠 ????????????wait_event_interruptible(); ???????3、等待被喚醒讀數(shù)據(jù) ????????? havedata =?0; } adc_handler() { ???????1、清中斷?ADC使用中斷來通知轉(zhuǎn)換數(shù)據(jù)完畢的 ?????? 2、狀態(tài)位置位; ??????????? havedata=1; ???????3、喚醒阻塞進(jìn)程 ????????????wake_up() } probe() { ??????1、讀取中斷號(hào),注冊(cè)中斷處理函數(shù) ??????2、讀取寄存器的地址,ioremap ??????3、字符設(shè)備的操作 }

驅(qū)動(dòng)需要首先捕獲中斷信號(hào)后再去寄存器讀取相應(yīng)的數(shù)據(jù),在ADC控制器沒有準(zhǔn)備好數(shù)據(jù)之前,應(yīng)用層需要阻塞讀取數(shù)據(jù),所以在讀取數(shù)據(jù)的函數(shù)中,需要借助等待隊(duì)列來實(shí)現(xiàn)驅(qū)動(dòng)對(duì)應(yīng)用進(jìn)程的阻塞。驅(qū)動(dòng)程序

驅(qū)動(dòng)程序?qū)拇嫫鞯牟僮鲄⒖悸銠C(jī)程序,只是基地址需要通過ioremap()做映射,對(duì)寄存器的讀寫操作需要用readl、writel。

driver.c

#include #include #include #include #include #include #include #include #include staticintmajor=250; staticwait_queue_head_twq; staticinthave_data=0; staticintadc; staticstructresource*res1; staticstructresource*res2; staticvoid*adc_base; #defineADCCON0x0000 #defineADCDLY0x0008 #defineADCDAT0x000C #defineCLRINTADC0x0018 #defineADCMUX0x001C staticirqreturn_tadc_handler(intirqno,void*dev) { have_data=1; printk("11111 "); /*清中斷*/ writel(0x12,adc_base+CLRINTADC); wake_up_interruptible(&wq); returnIRQ_HANDLED; } staticintadc_open(structinode*inod,structfile*filep) { return0; } staticssize_tadc_read(structfile*filep,char__user*buf,size_tlen,loff_t*pos) { writel(0x3,adc_base+ADCMUX); writel(1<<0?|?1<<14?|?0X1<<16?|?0XFF<<6?,adc_base?+ADCCON?); ? ??wait_event_interruptible(wq,?have_data==1); ? ??/*read?data*/ ??adc?=?readl(adc_base+ADCDAT)&0xfff; ?? ??if(copy_to_user(buf,&adc,sizeof(int))) ??{ ????return?-EFAULT; ??} ??have_data?=?0; ??return?len; } static??int?adc_release(struct?inode?*inode,?struct?file?*filep) { ??return?0; } static?struct?file_operations??adc_ops?= { ??.open?=?adc_open, ??.release?=?adc_release, ??.read?=?adc_read, }; ? ? static?int?hello_probe(struct?platform_device?*pdev) { ??int?ret; ??printk("match?0k? "); ? ??res1?=?platform_get_resource(pdev,IORESOURCE_IRQ,?0); ????res2?=?platform_get_resource(pdev,IORESOURCE_MEM,?0); ????? ??ret?=?request_irq(res1->start,adc_handler,IRQF_DISABLED,"adc1",NULL); adc_base=ioremap(res2->start,res2->end-res2->start); register_chrdev(major,"adc",&adc_ops); init_waitqueue_head(&wq); return0; } staticinthello_remove(structplatform_device*pdev) { free_irq(res1->start,NULL); free_irq(res2->start,NULL); unregister_chrdev(major,"adc"); return0; } staticstructof_device_idadc_id[]= { {.compatible="fs4412,adc"}, }; staticstructplatform_driverhello_driver= { .probe=hello_probe, .remove=hello_remove, .driver={ .name="bigbang", .of_match_table=adc_id, }, }; staticinthello_init(void) { printk("hello_init"); returnplatform_driver_register(&hello_driver); } staticvoidhello_exit(void) { platform_driver_unregister(&hello_driver); printk("hello_exit "); return; } MODULE_LICENSE("GPL"); module_init(hello_init); module_exit(hello_exit);

測(cè)試程序

test.c

#include #include #include #include main() { intfd,len; intadc; fd=open("/dev/hello",O_RDWR); if(fd<0) ??{ ????perror("open?fail? "); ????return?; ??} ? ??while(1) ??{ ????read(fd,&adc,4); ????printf("adc%0.2f?V? ",(1.8*adc)/4096); ??} ? ??close(fd); }

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • ARM
    ARM
    +關(guān)注

    關(guān)注

    134

    文章

    9207

    瀏覽量

    371057
  • adc
    adc
    +關(guān)注

    關(guān)注

    99

    文章

    6567

    瀏覽量

    546717
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11373

    瀏覽量

    211293

原文標(biāo)題:一文搞懂 ADC 裸機(jī)和基于 Linux 驅(qū)動(dòng)編寫方法

文章出處:【微信號(hào):LinuxHub,微信公眾號(hào):Linux愛好者】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    Linux中基于EP7312的LCD驅(qū)動(dòng)程序設(shè)計(jì)

    介紹在Linux操作系統(tǒng)中基于EP7312的LCD設(shè)備驅(qū)動(dòng)程序設(shè)計(jì)。其中包括LCD設(shè)備顯示原理,EP7312上與LCD 相關(guān)的寄存器, Linux 操作系統(tǒng)中編寫設(shè)備
    發(fā)表于 04-15 11:46 ?28次下載

    基于Linux操作系統(tǒng)的設(shè)備驅(qū)動(dòng)程序開發(fā)

    本文介紹了Linux 系統(tǒng)的特點(diǎn),闡述了在Linux 操作系統(tǒng)下,對(duì)系統(tǒng)硬件的訪問和開發(fā)驅(qū)動(dòng)程序的方法,說明了設(shè)備驅(qū)動(dòng)程序的結(jié)構(gòu)和編寫過程。
    發(fā)表于 09-02 17:11 ?20次下載

    嵌入式Linux網(wǎng)絡(luò)驅(qū)動(dòng)程序的開發(fā)及實(shí)現(xiàn)原理

    分析Linux 網(wǎng)絡(luò)驅(qū)動(dòng)程序體系結(jié)構(gòu)的基礎(chǔ)上,結(jié)合利用Linux2.6.18 內(nèi)核在FS2410 開發(fā)板上移植編寫CS8900A 網(wǎng)卡驅(qū)動(dòng)程序
    發(fā)表于 09-03 11:46 ?24次下載

    ARM Boot分析及驅(qū)動(dòng)程序編寫舉例

    ARM Boot分析及驅(qū)動(dòng)程序編寫舉例
    發(fā)表于 07-22 17:20 ?57次下載

    基于BF533的Linux網(wǎng)絡(luò)驅(qū)動(dòng)程序

    在分析Linux網(wǎng)絡(luò)驅(qū)動(dòng)程序體系結(jié)構(gòu)的基礎(chǔ)上,結(jié)合Linux2.6.18內(nèi)核在ADSP鄄BF533開發(fā)板上移植編寫CS8900A網(wǎng)卡驅(qū)動(dòng)程序
    發(fā)表于 12-25 16:22 ?20次下載

    Linux字符設(shè)備驅(qū)動(dòng)程序編寫框架

    一、Linux device driver 的概念 系統(tǒng)調(diào)用是操作系統(tǒng)內(nèi)核和應(yīng)用程序之間的接口,設(shè)備驅(qū)動(dòng)程序是操作系統(tǒng)內(nèi)核和機(jī)器硬件之間的接口。設(shè)備驅(qū)動(dòng)程序為應(yīng)
    發(fā)表于 12-25 10:54 ?847次閱讀

    Linux設(shè)備驅(qū)動(dòng)程序編寫

    本站提供的Linux設(shè)備驅(qū)動(dòng)程序編寫資料,希望對(duì)你的學(xué)習(xí)有幫助。 世界各地都有人在鉆研Linux內(nèi)核,大多是在寫設(shè)備驅(qū)動(dòng)程序。盡管每個(gè)
    發(fā)表于 05-25 16:24 ?108次下載

    基于Linux的步進(jìn)電機(jī)驅(qū)動(dòng)程序設(shè)計(jì)

    介紹了Linux驅(qū)動(dòng)程序的實(shí)現(xiàn)機(jī)制,在分析步進(jìn)電機(jī)和驅(qū)動(dòng)程序接口的基礎(chǔ)上,給出了一個(gè)在嵌入式Linux平臺(tái)上編寫步進(jìn)電機(jī)
    發(fā)表于 06-15 14:22 ?6146次閱讀
    基于<b class='flag-5'>Linux</b>的步進(jìn)電機(jī)<b class='flag-5'>驅(qū)動(dòng)程序</b>設(shè)計(jì)

    第9章 Linux驅(qū)動(dòng)程序設(shè)計(jì)

    9.1 Linux 設(shè)備驅(qū)動(dòng)程序 9.2 Linux經(jīng)典Hello world驅(qū)動(dòng)程序 9.3 Linux字符設(shè)備
    發(fā)表于 04-11 14:56 ?3次下載

    Linux系統(tǒng)網(wǎng)絡(luò)驅(qū)動(dòng)程序編寫

    驅(qū)動(dòng)程序編寫 一.Linux系統(tǒng)設(shè)備驅(qū)動(dòng)程序概述 1.1 Linux設(shè)備驅(qū)動(dòng)程序分類 1.2
    發(fā)表于 11-07 10:40 ?0次下載

    Linux設(shè)備驅(qū)動(dòng)程序的平臺(tái)驅(qū)動(dòng)程序和字符驅(qū)動(dòng)程序介紹

    了解Linux設(shè)備驅(qū)動(dòng)程序的基礎(chǔ)知識(shí),重點(diǎn)介紹平臺(tái)驅(qū)動(dòng)程序和字符驅(qū)動(dòng)程序。 提出了簡(jiǎn)單的平臺(tái)驅(qū)動(dòng)程序實(shí)現(xiàn)和簡(jiǎn)單的字符
    的頭像 發(fā)表于 11-27 06:32 ?4437次閱讀

    如何為Linux編寫用戶空間設(shè)備驅(qū)動(dòng)程序

    了解如何為Linux編寫用戶空間設(shè)備驅(qū)動(dòng)程序。 用戶空間驅(qū)動(dòng)程序為某些設(shè)備提供內(nèi)核空間驅(qū)動(dòng)程序的替代方案
    的頭像 發(fā)表于 11-22 07:04 ?3854次閱讀

    如何編寫基于ARM裸機(jī)程序和基于Linux驅(qū)動(dòng)程序

    在嵌入式開發(fā)中,ADC應(yīng)用比較頻繁,本文主要講解ADC的基本原理以及如何編寫基于ARM裸機(jī)程序和基于Linux
    的頭像 發(fā)表于 03-12 15:26 ?1881次閱讀
    如何<b class='flag-5'>編寫</b>基于<b class='flag-5'>ARM</b>的<b class='flag-5'>裸機(jī)</b><b class='flag-5'>程序</b>和基于<b class='flag-5'>Linux</b>的<b class='flag-5'>驅(qū)動(dòng)程序</b>?

    linux驅(qū)動(dòng)程序如何加載進(jìn)內(nèi)核

    Linux系統(tǒng)中,驅(qū)動(dòng)程序是內(nèi)核與硬件設(shè)備之間的橋梁。它們?cè)试S內(nèi)核與硬件設(shè)備進(jìn)行通信,從而實(shí)現(xiàn)對(duì)硬件設(shè)備的控制和管理。 驅(qū)動(dòng)程序編寫 驅(qū)動(dòng)程序
    的頭像 發(fā)表于 08-30 15:02 ?698次閱讀

    Linux設(shè)備驅(qū)動(dòng)程序分類有哪些

    Linux設(shè)備驅(qū)動(dòng)程序是操作系統(tǒng)與硬件設(shè)備之間的橋梁,負(fù)責(zé)實(shí)現(xiàn)硬件設(shè)備與操作系統(tǒng)之間的通信和控制。Linux設(shè)備驅(qū)動(dòng)程序的分類繁多,可以根據(jù)不同的標(biāo)準(zhǔn)進(jìn)行分類。 按硬件類型分類
    的頭像 發(fā)表于 08-30 15:11 ?817次閱讀
    主站蜘蛛池模板: 国产黄大片在线视频 | 国产曰批试看免费视频播放免费 | 另类重口bdsm日本tv | 妻子的妹妹在线 | 医生含着我的奶边摸边做 | 涩涩视频www在线观看入口 | 一区二区三区高清视频 | 久久兔费黄A级毛片高清 | 国产AV99激情久久无码天堂 | 成人在免费视频手机观看网站 | 国产免费变态视频网址网站 | 久久受www免费人成_看片中文 | 纯肉宠文高h一对一 | 98久久人妻少妇激情啪啪 | 亚洲精品一二三 | 日韩hd高清xxxⅹ | 国产成人免费全部网站 | 日美欧韩一区二去三区 | 国产又粗又猛又爽又黄的免费视频 | 久久青草免费线观最新 | 亚洲精品高清在线 | 777午夜精品久久AV蜜臀 | 一本色道久久综合一区 | 最近中文字幕在线看免费完整版 | 戳女人屁股流水羞羞漫画 | 久久在精品线影院 | 久久久精品久久久久久 | 大屁股妇女流出白浆 | qvod快播在线观看 | 国产精品99re6热在线播放 | 奇米狠狠一区二区三区 | 亚洲欧美中文日韩视频 | 免费精品美女久久久久久久久 | 国语自产视频在线 | 国产精品久久人妻无码蜜 | 毛片大全网站 | 一本色道久久综合亚洲AV蜜桃 | 亚洲人成在线观看一区二区 | 欧美做真爱欧免费看 | 国产精品人妻无码久久久蜜桃臀 | 女攻男受高h全文肉肉 |