版權(quán)聲明:本文為小斑馬學(xué)習(xí)總結(jié)文章,技術(shù)來(lái)源于韋東山著作元旬,轉(zhuǎn)載請(qǐng)注明出處赃绊!
一既峡、ADC硬件原理
模數(shù)轉(zhuǎn)換器即A/D轉(zhuǎn)換器,或簡(jiǎn)稱(chēng)ADC碧查,通常是指一個(gè)將模擬信號(hào)轉(zhuǎn)變?yōu)閿?shù)字信號(hào)的電子元件运敢。
通常的模數(shù)轉(zhuǎn)換器是把經(jīng)過(guò)與標(biāo)準(zhǔn)量比較處理后的模擬量轉(zhuǎn)換成以二進(jìn)制數(shù)值表示的離散信號(hào)的轉(zhuǎn)換器校仑。
故任何一個(gè)模數(shù)轉(zhuǎn)換器都需要一個(gè)參考模擬量作為轉(zhuǎn)換的標(biāo)準(zhǔn),比較常見(jiàn)的參考標(biāo)準(zhǔn)為最大的可轉(zhuǎn)換信號(hào)大小传惠。而輸出的數(shù)字量則表示輸入信號(hào)相對(duì)于參考信號(hào)的大小迄沫。
如圖,是把可變電阻上的電壓值變換的模擬信號(hào)通過(guò)ADC轉(zhuǎn)換卦方,輸出數(shù)字信號(hào)羊瘩。
- 用多少位來(lái)存儲(chǔ)這個(gè)數(shù)據(jù)(假設(shè)10bit)。
- 最大值0b111111111
它對(duì)應(yīng)的電壓是多少伏(模擬信號(hào)輸入的最大值是多少)我們就可以根據(jù)模擬信號(hào)(電壓)的最大值盼砍,來(lái)計(jì)算出對(duì)應(yīng)的數(shù)值尘吗。 - 采樣/轉(zhuǎn)換速度。
對(duì)于程序浇坐,不用關(guān)心ADC的內(nèi)部機(jī)制睬捶,只關(guān)心:
- 怎么啟動(dòng)ADC
- 啟動(dòng)之后怎么得到數(shù)據(jù)
從圖1-1-1可以看出ADC有8個(gè)多路選擇器近刘,顯然擒贸,以后寫(xiě)程序的時(shí)候,我們可以8個(gè)多路選擇之一
下面是編寫(xiě)程序要做的步驟:
- 確定是哪一路信號(hào):設(shè)置8:1MUX觉渴,選擇要測(cè)量哪一個(gè)引腳酗宋,(看原理圖選擇要測(cè)量的引腳)
- 設(shè)置工作時(shí)鐘(從工作室中,可以算出轉(zhuǎn)換一次疆拘,需要多長(zhǎng)時(shí)間)
- 啟動(dòng)
- 讀狀態(tài),判斷ADC轉(zhuǎn)換是否成功寂曹。
- 讀數(shù)據(jù)
ADC寄存器介紹
1.ADC 控制寄存器(ADCCON)
ADCCON控制寄存器哎迄,用于標(biāo)志轉(zhuǎn)換是否完成,控制是否使能預(yù)分頻器隆圆,輸入通道選擇漱挚,工作模式,ADC是否啟動(dòng)渺氧。它的各位含義如下圖所示旨涝。
2.ADC 啟動(dòng)延時(shí)寄存器(ADCDLY)
ADCDLY 啟動(dòng)延時(shí)寄存器用于啟動(dòng)或初始化延時(shí)寄存器。它的各位含義如下圖所示
3.ADC 轉(zhuǎn)換數(shù)據(jù)寄存器(ADCDAT0)
ADCDAT0轉(zhuǎn)換數(shù)據(jù)寄存器侣背,本節(jié)中只用到該寄存器的前10位(用于保存轉(zhuǎn)換后的結(jié)果)白华。
二、ADC編程
編程步驟:
- 初始化ADC
- 讀數(shù)據(jù)贩耐,
- 在串口上顯示出來(lái)弧腥。
一.初始化ADC
下面的函數(shù)實(shí)現(xiàn)對(duì)ADC的初始化。
03 void adc_init(void)
04 {
05 /* [15] : ECFLG, 1 = End of A/D conversion
06 * [14] : PRSCEN, 1 = A/D converter prescaler enable
07 * [13:6]: PRSCVL, adc clk = PCLK / (PRSCVL + 1)
08 * [5:3] : SEL_MUX, 000 = AIN 0
09 * [2] : STDBM
10 * [0] : 1 = A/D conversion starts and this bit is cleared after the startup.
11 */
12 ADCCON = (1<<14) | (49<<6) | (0<<3);
13
14 ADCDLY = 0xff;
15 }
第12行:配置ADCCON寄存器潮太,使能A/D 轉(zhuǎn)換器預(yù)分頻器管搪,設(shè)置A/D 轉(zhuǎn)換器預(yù)分頻值虾攻,上拉使能。
第14行:設(shè)置ADC 轉(zhuǎn)換啟動(dòng)延時(shí)值更鲁。
二.讀數(shù)據(jù)
在這個(gè)讀函數(shù)中啟動(dòng)ADC霎箍,并且等待ADC轉(zhuǎn)換成功。然后返回?cái)?shù)據(jù)澡为,
17 int adc_read_ain0(void)
18 {
19 /* 啟動(dòng)ADC */
20 ADCCON |= (1<<0);
21
22 while (!(ADCCON & (1<<15))); /* 等待ADC結(jié)束 */
23
24 return ADCDAT0 & 0x3ff;
25 }
第20行:?jiǎn)?dòng)ADC漂坏。
第22行:等待A/D轉(zhuǎn)換結(jié)束(ADCCON第15位置1),
第24行:返回轉(zhuǎn)換的值缀壤。(ADCDAT0寄存器的前10位樊拓,是保存轉(zhuǎn)換后的值)。
三.ADC測(cè)試
函數(shù)代碼如下: 函數(shù)功能:在串口/LCD上打印ADC轉(zhuǎn)換后的結(jié)果塘慕。
04 void adc_test(void)
05 {
06 int val;
07 double vol;
08 int m; /* 整數(shù)部分 */
09 int n; /* 小數(shù)部分 */
10
11 adc_init();
12
13 while (1)
14 {
15 val = adc_read_ain0();
16 vol = (double)val/1023*3.3; /* 1023----3.3v */
17 m = (int)vol; /* 3.01, m = 3 */
18 vol = vol - m; /* 小數(shù)部分: 0.01 */
19 n = vol * 1000; /* 10 */
20
21 /* 在串口上打印 */
22 printf("vol: %d.%03dv", m, n); /* 3.010v */
23
24 /* 在LCD上打印 */
25 //fb_print_string();
26 }
27 }
第11行:初始化ADC.
第15行:把ADC轉(zhuǎn)換得到的值賦值給變量val.
第16行:把變量val的值轉(zhuǎn)化為電壓值筋夏。
第17行:取vol整數(shù)部分賦值給變量m。
第18行:取vol的小數(shù)部分賦值給vol图呢。
測(cè)試:把生成的二進(jìn)制文件燒錄到開(kāi)發(fā)板上条篷,接上SPI模塊,旋轉(zhuǎn)可變電阻就可以在串口上看到電壓值發(fā)生變化蛤织。
三赴叹、電阻觸摸屏硬件原理
電阻觸摸屏的硬件原理:假設(shè)有一個(gè)比較長(zhǎng)的電阻,電阻是R 上面接3.3V電壓,下面接地
根據(jù)歐姆定律
3.3v/R = V/R1
V=3.3 *(R1/R)
假設(shè)R1是x坐標(biāo)
R的長(zhǎng)度是l
這個(gè)電阻非常的均勻指蚜,那么這個(gè)電壓就等于 3.3V * (x / l)
這個(gè)電壓和這個(gè)觸電的x坐標(biāo)有一個(gè)線性關(guān)系
我使用ADC把這個(gè)電壓算出來(lái)乞巧,就可以間接得到這個(gè)觸電的x坐標(biāo)
電阻觸摸屏就是使用歐姆定律使用電阻原理作出來(lái)的
可以上百度圖片搜索觸摸屏,就知道了觸摸屏的樣子,它是一個(gè)透明的薄膜,注意 LCD是LCD 觸摸屏是觸摸屏它是兩個(gè)設(shè)備,
我們只不過(guò)是把觸摸屏做的和LCD大小一樣摊鸡,粘在LCD上面,
實(shí)際上觸摸屏是由兩層膜組成绽媒,他們靠的非常近。
上面這層右邊引出來(lái)免猾,代表xp 是辕,p代表正極
下面這層膜 前面這條邊引出來(lái)為yp猎提,后面這層邊為ym
假設(shè)我們手指要點(diǎn)擊觸摸屏获三,那么上下就會(huì)粘貼在一起,我怎么算出這個(gè) x y點(diǎn)的坐標(biāo)呢锨苏?
測(cè)量觸電x坐標(biāo):
xp接3.3v,xm接GND
yp,ym不接電源
2 測(cè)yp電壓
上下膜連接在一起疙教,我就可以通過(guò)yp測(cè)量這個(gè)觸電的電壓
這個(gè)yp就像探測(cè)一樣,從前面的原理我們可以知道伞租,當(dāng)這個(gè)觸電越靠近左邊這個(gè)電壓越小松逊,越靠近右邊電壓越大
這個(gè)yp的電壓就可以認(rèn)為是這個(gè)觸電的坐標(biāo)(x坐標(biāo))
類(lèi)似的我們?cè)趺礈y(cè)量觸電y坐標(biāo)
類(lèi)似的xp xm不接電源,同樣yp接3.3v肯夏, ym接GND经宏,這時(shí)候電流就從 yp這里流向ym,讓后我們就可以測(cè)量xp電壓
當(dāng)按下屏幕時(shí)犀暑,上下兩層膜鏈接在一起,這個(gè)xp就像探針一樣烁兰,這個(gè)觸電越靠近yp電壓值越大耐亏,越靠近ym電壓值越小
yp接3.3V ym接GND,xp xm不接電源
測(cè)量xp電壓,就是y坐標(biāo)
注意 x y坐標(biāo)都是電壓值沪斟,不是屏幕上480 * 272 這些值广辰,我們需要把電壓值轉(zhuǎn)換為坐標(biāo)值,這需要經(jīng)過(guò)一些轉(zhuǎn)換
我們測(cè)量xp yp可以得到觸點(diǎn)的兩個(gè)方向的電壓值主之,這些電壓值和坐標(biāo)是線性關(guān)系
現(xiàn)在總結(jié)下使用觸摸屏的流程
- <1>按下觸摸屏 按下觸摸屏?xí)r择吊,對(duì)于一個(gè)高效的系統(tǒng),產(chǎn)生中斷槽奕,這是觸摸屏中斷
- <2>在觸摸中斷程序中 啟動(dòng)ADC几睛,(獲得數(shù)據(jù),xy坐標(biāo))啟動(dòng)ADC就開(kāi)始模數(shù)轉(zhuǎn)換粤攒,不可能瞬間完成所森,
- <3>ADC完成, 產(chǎn)生中斷
- <4>ADC中斷中讀取x y坐標(biāo)夯接,我們來(lái)想想焕济,在這個(gè)流程里,啟動(dòng)觸摸屏的源頭是按下觸摸屏盔几,那如果長(zhǎng)按觸摸屏晴弃,我按下之后一直不松開(kāi) 滑動(dòng)手指呢
那么誰(shuí)來(lái)觸發(fā)后續(xù)的多次ADC轉(zhuǎn)換呢 不可能只啟動(dòng)一次吧,
為了支持 長(zhǎng)按 滑動(dòng)操作,我們需要啟用定時(shí)器. - <5> 啟動(dòng)定時(shí)器
- <6> 定時(shí)器中斷發(fā)生逊拍,判斷觸摸屏是否仍被按下肝匆,如果按下就循環(huán)上述過(guò)程
<6.1>在觸摸中斷程序中 啟動(dòng)ADC,(獲得數(shù)據(jù)顺献,xy坐標(biāo))啟動(dòng)ADC就開(kāi)始模數(shù)轉(zhuǎn)換,不可能瞬間完成
<6.2>ADC完成枯怖, 產(chǎn)生中斷
<6.3>ADC中斷中讀取x y坐標(biāo)注整,) - <7> 松開(kāi)結(jié)束一個(gè)流程
這就是整個(gè)觸摸屏的使用流程
在14章里講解了觸摸屏,他抽象了幾張圖
平時(shí)的時(shí)候上下兩層膜并不連接度硝,我們按下觸摸屏的時(shí)候就會(huì)產(chǎn)生中斷肿轨,那么你怎么知道產(chǎn)生中斷,肯定是由某個(gè)引腳的電平發(fā)生變化,平時(shí) Y_ADC/xp是高電平,按下之后Y_ADC就接地了蕊程,就是被拉低了椒袍,就產(chǎn)生了低電平
讀取Y坐標(biāo)
YP YM 通電驹暑,按下后XP通電玫恳,這不就是y點(diǎn)的坐標(biāo)么
四、S3C2440觸摸屏接口
回顧上節(jié)觸摸屏使用原理必須讓S1 S3閉合,這樣電流才可以通過(guò)叶雹,同時(shí)讓S2 S4 S5斷開(kāi),這時(shí)候YP這層膜就相當(dāng)于探針一樣去測(cè)量電壓 當(dāng)我讀取y坐標(biāo)值
必須讓S2 S4閉合财饥,這樣電流才可以流 下來(lái),同時(shí)S1 S3 S5斷開(kāi)折晦,這個(gè)時(shí)候XP這層膜就相當(dāng)于探針一樣钥星,我可以來(lái)測(cè)量這里的電壓,從而得到Y(jié)坐標(biāo)的電壓值
在測(cè)量x y坐標(biāo)時(shí)筋遭,這個(gè)S5上拉電阻都要斷開(kāi),
我們需要控制這幾個(gè)開(kāi)關(guān)打颤,實(shí)際上2440就提供了這幾個(gè)開(kāi)關(guān)的控制方法,
打開(kāi)2440的芯片手冊(cè)看觸摸屏?xí)r怎么操作的,
我們看有一個(gè)8:1 MUX的多路選擇器,以及XP YP
442頁(yè)觸摸屏接口模式
正常模式 上篇文章詳寫(xiě)過(guò)
x y分離轉(zhuǎn)換模式
看看我們的X Y坐標(biāo)原理圖编饺,可以單獨(dú)轉(zhuǎn)換X坐標(biāo) 單獨(dú)轉(zhuǎn)換Y坐標(biāo)
換句話說(shuō)就是逐個(gè)去測(cè)量X Y坐標(biāo),
他首先會(huì)啟動(dòng)X坐標(biāo)的ADC轉(zhuǎn)換,轉(zhuǎn)換成功后數(shù)據(jù)會(huì)保存在ADCDAT0里响驴,同時(shí)會(huì)產(chǎn)生一個(gè)中斷透且,在這個(gè)中斷服務(wù)程序里,就可以把X坐標(biāo)讀取出來(lái)豁鲤,讓后可以啟動(dòng)Y坐標(biāo)的轉(zhuǎn)換秽誊,轉(zhuǎn)換成功后數(shù)據(jù)會(huì)保存在ADCDAT,同時(shí)會(huì)產(chǎn)生一個(gè)中斷琳骡,進(jìn)入這個(gè)中斷把Y坐標(biāo)讀取出來(lái)锅论。測(cè)量一次會(huì)產(chǎn)生2個(gè)中斷,一個(gè)時(shí)X坐標(biāo)中斷楣号,一個(gè)是Y坐標(biāo)中斷
自動(dòng)的或連續(xù)的X/Y坐標(biāo)轉(zhuǎn)換模式
也就是說(shuō)不需要單獨(dú)控制最易,不需要單獨(dú)去讀取X坐標(biāo)Y坐標(biāo),可以設(shè)置寄存器炫狱,讓它一次性的測(cè)量X坐標(biāo)測(cè)量Y坐標(biāo)藻懒,X坐標(biāo)保存在ADCDAT0 Y坐標(biāo)保存在ADCDAT1,最后產(chǎn)生一個(gè)中斷视译,也就是讀取X/Y坐標(biāo)只需要產(chǎn)生一次中斷
等待中斷模式
所謂等待中斷模式嬉荆,就是等待按下或者等待松開(kāi)
對(duì)于下面這幅圖,我按下的時(shí)候XP從高電平變?yōu)榈碗娖娇岷砷_(kāi)時(shí)鄙早,XP從低電平變?yōu)楦唠娖酵艏耄@就是按下松開(kāi)都可以檢測(cè)到
443頁(yè)編程要點(diǎn)
AD轉(zhuǎn)換數(shù)據(jù)時(shí)可以通過(guò)中斷或者查詢(xún)模式來(lái)得到數(shù)據(jù),使用中斷模式時(shí)蝶锋,從AD轉(zhuǎn)換開(kāi)始陆爽,到得到數(shù)據(jù)可能會(huì)有些延遲,因?yàn)橹袛喾?wù)程序的進(jìn)入和退出需要一定的時(shí)間扳缕,(也就是說(shuō)慌闭,如果你對(duì)數(shù)據(jù)轉(zhuǎn)換的速度要求的非常高,就可以使用查詢(xún)方式)躯舔,可以查詢(xún)ADCCON[15]來(lái)判斷是否轉(zhuǎn)換結(jié)束
444頁(yè)
PRSCEN 使能ADC轉(zhuǎn)換
PRSCVL 設(shè)置A/D轉(zhuǎn)換預(yù)分頻值
SEL_MUX選擇輸入通道驴剔,后面我們使用自動(dòng)轉(zhuǎn)換XY坐標(biāo),所以這里不需要設(shè)置
ENABLE_START 啟動(dòng)轉(zhuǎn)換
0表明被按下粥庄,1表明被松開(kāi)
YM_SEN Bit7 YM開(kāi)關(guān)使能控制S4
0表示斷開(kāi) 1閉合
YP_SEN Bit6 YP開(kāi)關(guān)
0表示閉合 1 表示斷開(kāi)
*寄存器位的含義不同
XM_SEN Bit5 XM開(kāi)關(guān)
0 斷開(kāi) 1 閉合
XP_SEN Bit4 XP開(kāi)關(guān)
0 閉合 1 斷開(kāi)
PULL_UP Bit3 控制S5開(kāi)關(guān)
0 上拉(閉合)
1 斷開(kāi)
AUTO_PST Bit2 自動(dòng)連續(xù)轉(zhuǎn)換X坐標(biāo)Y坐標(biāo)
設(shè)置是 0 正常的ADC轉(zhuǎn)換
如果需要連續(xù)轉(zhuǎn)換ADC坐標(biāo)的話丧失,需要設(shè)置為1 ,如果需要手動(dòng)轉(zhuǎn)換ADC坐標(biāo)的話惜互,需要設(shè)置為0
XY_PST Bit[1:0]
對(duì)于手動(dòng)轉(zhuǎn)換X Y坐標(biāo)我們需要手動(dòng)設(shè)置XY_PST 里面的位布讹,是測(cè)量X坐標(biāo)還是測(cè)量Y坐標(biāo),
也可以設(shè)置這兩位等于11 讓其等于等待模式,
也就是等待觸摸屏被按下或者被松開(kāi).
如果設(shè)置自動(dòng)連續(xù)轉(zhuǎn)換的話,Bit2 AUTO_PST設(shè)置為1
XY_PST設(shè)置為00
如果使用手動(dòng)轉(zhuǎn)換的話設(shè)置AUTO_PST為0
XY_PST設(shè)置為01 手動(dòng)轉(zhuǎn)換X坐標(biāo)模式
或者設(shè)置為10 Y坐標(biāo)轉(zhuǎn)換模式
447頁(yè)ADCDATA0 ADC數(shù)據(jù)寄存器
UPDOWN Bit15 可以讀取這一位去判斷觸摸屏是按下還是松開(kāi)
AUTO_PST Bit14 自動(dòng)測(cè)量
XY_PST Bit[13:12] 和上面ADCTSC寄存器中 AUTO_PST Bit2 XY_PST
Bit[1:0]原理相同
XPDATA Bit[9:0]最低10位用來(lái)保存ADC的值
448頁(yè)'ADCDAT1寄存器 和ADCDAT0功能一樣的训堆,只不過(guò)保存的數(shù)據(jù)不同這個(gè)的低10位是用來(lái)保存 Y坐標(biāo)的值
TST_DN Bit0 觸摸屏按下中斷產(chǎn)生
手冊(cè)看完了描验,涉及到中斷,我們看下這個(gè)圖
它會(huì)涉及兩個(gè)中斷坑鱼,按下或者松開(kāi)膘流,觸摸筆的狀態(tài)中斷,另外一個(gè)啟動(dòng)ADC以后鲁沥,ADC結(jié)束時(shí)也會(huì)產(chǎn)生一個(gè)中斷呼股,但是這個(gè)手冊(cè)里沒(méi)有看到中斷的是能寄存器。
那我們猜測(cè)一下画恰,ADC模塊或者觸摸屏模塊一定會(huì)發(fā)出中斷
首先是ADC或者觸摸屏產(chǎn)生中斷彭谁,通過(guò)中斷控制器發(fā)送中斷給CPU
看看中斷控制器芯片手冊(cè)中都需要設(shè)置什么
既然合并必然還會(huì)有一個(gè)寄存器來(lái)分辨到底是ADC還是觸摸屏發(fā)生的中斷變化
SRCPND寄存器
31位為ADC中斷
設(shè)置Bit[31]
INTMOD寄存器
來(lái)決定是普通中斷還是快中斷模式
用來(lái)表示是否屏蔽這個(gè)中斷
INTPND
設(shè)置Bit[31]
SUBSOURCE PENDING寄存器
INT_ADC_S Bit[10]表示ADC中斷
INT_TC Bit[9]表示觸摸屏中斷
應(yīng)該也是同樣的位
INT_ADC_S Bit[10]表示ADC中斷激活/屏蔽
INT_TC Bit[9]表示觸摸屏中斷激活/屏蔽
當(dāng)然也可以是能某個(gè)中斷
可以通過(guò)SUBSRCPND來(lái)分辨到底產(chǎn)生那個(gè)中斷
INTSUBMSK 和SUBSOURCPND這兩個(gè)寄存器都會(huì)匯集到一起
變成一個(gè)叫做INT_ADC的中斷來(lái)發(fā)送給CPU 框圖就是這樣
程序設(shè)計(jì)缠局?
寫(xiě)出一個(gè)框架
- 1 初始化ADC/TouchScreen接口ADCCON時(shí)鐘接口
- 2 一開(kāi)始觸摸屏是沒(méi)有被按下的,設(shè)置TS處于等待中斷模式
- 3 設(shè)置中斷
INTSUBMSK使能ADC中斷和觸摸屏中斷,還有INTMSK設(shè)置這個(gè)寄存器使能ANT_ADC讓他能夠發(fā)給CPU - 4 按下觸摸屏蔼两,進(jìn)入TS中斷
4.1 進(jìn)入自動(dòng)采集模式(自動(dòng)轉(zhuǎn)換XY坐標(biāo))
4.2 啟動(dòng)ADC - 5.轉(zhuǎn)換完之后產(chǎn)生ADC中斷
5.1 讀數(shù)據(jù)
5.2 再次進(jìn)入 “'等待中斷”'模式
5.3 啟動(dòng)定時(shí)器,處理長(zhǎng)按或者滑動(dòng) - 6 定時(shí)器中斷
6.1 判斷是否松開(kāi)逞度,若松開(kāi)結(jié)束
6.2 若按下重新執(zhí)行 4.2啟動(dòng)ADC步驟
五额划、觸摸屏編程_按下松開(kāi)檢測(cè)
開(kāi)始觸摸屏編程,關(guān)于觸摸屏編程大概會(huì)分為3個(gè)小節(jié)
第006節(jié)觸摸屏編程ADC中斷
第007節(jié)觸摸屏編程定時(shí)器程序優(yōu)化
參考《嵌入式Linux應(yīng)用開(kāi)發(fā)完全手冊(cè)》第14章 ADC和觸摸屏接口
可以參考下面這張圖
里面有個(gè)中斷程序 AdcTsIntHandle
它是總的中斷档泽,這里面要分辨
if,
如果是ADC中斷 那么就調(diào)用Isr_adc來(lái)處理中段
else if,
如果是觸摸屏中斷俊戳,那么就調(diào)用Isr_tc中斷,
我們看看是怎么做的
這些都是總中斷具體的中斷. 一開(kāi)始設(shè)置中斷
初始化觸摸屏控制器揖赴,進(jìn)入等待中斷模式
這個(gè)時(shí)候如果按下觸摸屏就會(huì)進(jìn)入Pen Down中斷
就會(huì)進(jìn)入AdcTsIntHandle這個(gè)總中斷函數(shù)
這里面分辨是按下觸摸屏
進(jìn)入自動(dòng)(連續(xù)) X/Y軸坐標(biāo)轉(zhuǎn)換模式,啟動(dòng)ADC,
ADC結(jié)束之后會(huì)產(chǎn)生一個(gè)ADC中斷
又再次進(jìn)入這個(gè)AdcTsIntHandle總中斷
這里面分辨是ADC中斷抑胎,這里面調(diào)用Isr_Adc
我可以讀出這里面的數(shù)據(jù)燥滑,再次設(shè)置寄存器
進(jìn)入等待Pen UP中斷模式
松開(kāi)觸摸筆會(huì)再次產(chǎn)生一個(gè)中斷
進(jìn)入總中斷AdcTsIntHandle這里面分辨,原來(lái)是松開(kāi)了觸摸筆阿逃,再次調(diào)用Isr_tc
這里面又會(huì)設(shè)置進(jìn)入等待Pen Down中斷模式
程序設(shè)計(jì):
002_touchscreen_018_005/adc_touchscreen
我們?cè)赼dc_touchscreen目錄下添加幾個(gè)文件
touchscreen_test.c
touchscreen.c
我們打開(kāi)touchscreen.c文件
void touchscreen_init(void)
{
看看上面流程圖
/*1設(shè)置觸摸屏接口:也就是寄存器 */
/*2 設(shè)置中斷我們需要提供中斷處理函數(shù) */
/*3 讓觸摸屏控制器進(jìn)入"等待中斷模式" */
}
我們?cè)O(shè)置中斷處理函數(shù)
void AdcTsIntHandle(void)
{
}
看一下之前我們是怎么寫(xiě)中斷的,看一下interrupt.c文件
void key_eint_irq(int irq)
有個(gè)中斷號(hào)
那么我們也定義個(gè)int irq參數(shù)
void AdcTsIntHandle(int irq)
我們?cè)谶@個(gè)里面分辨一下
if (SUBSRCPND & (1<<TC_INT_BIT)) /* 如果是觸摸屏中斷 */
/*調(diào)用*/
Isr_Tc();
else if //如果是ADC中斷
//調(diào)用
Isr_Adc();
我們等會(huì)實(shí)現(xiàn)這兩個(gè)函數(shù)
我們繼續(xù)寫(xiě)代碼
void touchscreen_init(void)
{
看看上面流程圖
/*1 設(shè)置中斷我們需要提供中斷處理函數(shù) */
adc_ts_int_init();
/*2 設(shè)置觸摸屏接口:也就是寄存器 */
adc_ts_reg_init();
/*3 讓觸摸屏控制器進(jìn)入"等待中斷模式" */
enter_wait_pen_down_mode();
}
//我們先來(lái)實(shí)現(xiàn) adc_ts_int_init
void adc_ts_int_init(void)
{
/*注冊(cè)中斷處理函數(shù)*/
//怎么注冊(cè)看之前的代碼
register_irq(irq, irq_handle);
中斷號(hào)是多少铭拧?
打開(kāi)芯片手冊(cè),找到中斷控制器
register_irq(31, AdcTsIntHandle);
怎么使能中斷?
我們需要把 INTSUBMISK寄存器的Bit9 Bit10設(shè)置為0
宏定義
#define ADC_INT_BIT (10)
#define TC_INT_BIT (9)
使能中斷恃锉,清零
INTSUBMSK &= ~((1<<ADC_INT_BIT) | (1<<TC_INT_BIT));
還有INTMSK我們也需要把Bit31清零
#define INT_ADC_TC (31)
Bit31位清零操作
INTMSK &= ~(1<<INT_ADC_TC);
這句可以不用設(shè)置搀菩,因?yàn)閞egister_irq已經(jīng)設(shè)置
假設(shè)產(chǎn)生中斷就會(huì)進(jìn)入AdcTsIntHandle函數(shù)中
分辨是觸摸屏終端還是ADC中斷
void AdcTsIntHandle(int irq)
{
if /* 如果是觸摸屏中斷 */
Isr_Tc();
if /* ADC中斷 */
Isr_Adc();
}
如何進(jìn)行分辨if (SUBSRCPND & (1<<TC_INT_BIT)) /* 如果是觸摸屏中斷 */
Isr_Tc();
if (SUBSRCPND & (1<<ADC_INT_BIT)) /* ADC中斷 */
Isr_Adc();
//我們要引用寄存器地址頭文件
#include "../s3c2440_soc.h"
#define ADC_INT_BIT (10)
#define TC_INT_BIT (9)
#define INT_ADC_TC (31)
/* ADCTSC's bits */
#define WAIT_PEN_DOWN (0<<8)
#define WAIT_PEN_UP (1<<8)
#define YM_ENABLE (1<<7)
#define YM_DISABLE (0<<7)
#define YP_ENABLE (0<<6)
#define YP_DISABLE (1<<6)
#define XM_ENABLE (1<<5)
#define XM_DISABLE (0<<5)
#define XP_ENABLE (0<<4)
#define XP_DISABLE (1<<4)
#define PULLUP_ENABLE (0<<3)
#define PULLUP_DISABLE (1<<3)
#define AUTO_PST (1<<2)
#define WAIT_INT_MODE (3)
#define NO_OPR_MODE (0)
void enter_wait_pen_down_mode(void)
{
ADCTSC = WAIT_PEN_DOWN | PULLUP_ENABLE | YM_ENABLE | YP_DISABLE | XP_DISABLE | XM_DISABLE | WAIT_INT_MODE;
}
void enter_wait_pen_up_mode(void)
{
ADCTSC = WAIT_PEN_UP | PULLUP_ENABLE | YM_ENABLE | YP_DISABLE | XP_DISABLE | XM_DISABLE | WAIT_INT_MODE;
}
讀一下寄存器,找到觸摸屏的寄存器觸摸筆,按下松開(kāi)狀態(tài)寄存器我們可以讀它 Bit1表示up Bit0表示down
void Isr_Tc(void)
{
printf("ADCUPDN = 0x%x, ADCDAT0 = 0x%x, ADCDAT1 = 0x%x, ADCTSC = 0x%x\n\r", ADCUPDN, ADCDAT0, ADCDAT1, ADCTSC);
if (ADCDAT0 & (1<<15))
{
printf("pen up\n\r");
enter_wait_pen_down_mode();
}
else
{
printf("pen down\n\r");
/* 進(jìn)入"等待觸摸筆松開(kāi)的模式" */
enter_wait_pen_up_mode();
}
}
void AdcTsIntHandle(int irq)
{
if (SUBSRCPND & (1<<TC_INT_BIT)) /* 如果是觸摸屏中斷 */
Isr_Tc();
// if (SUBSRCPND & (1<<ADC_INT_BIT)) /* ADC中斷 */
// Isr_Adc();
SUBSRCPND = (1<<TC_INT_BIT) | (1<<ADC_INT_BIT);
}
void adc_ts_int_init(void)
{
SUBSRCPND = (1<<TC_INT_BIT) | (1<<ADC_INT_BIT);
/* 注冊(cè)中斷處理函數(shù) */
register_irq(31, AdcTsIntHandle);
/* 使能中斷 */
INTSUBMSK &= ~((1<<ADC_INT_BIT) | (1<<TC_INT_BIT));
//INTMSK &= ~(1<<INT_ADC_TC);
}
void adc_ts_reg_init(void)
{
/* [15] : ECFLG, 1 = End of A/D conversion
* [14] : PRSCEN, 1 = A/D converter prescaler enable
* [13:6]: PRSCVL, adc clk = PCLK / (PRSCVL + 1)
* [5:3] : SEL_MUX, 000 = AIN 0
* [2] : STDBM
* [0] : 1 = A/D conversion starts and this bit is cleared after the startup.
*/
ADCCON = (1<<14) | (49<<6) | (0<<3);
ADCDLY = 0xff;
}
void touchscreen_init(void)
{
/* 設(shè)置觸摸屏接口:寄存器 */
adc_ts_reg_init();
printf("ADCUPDN = 0x%x, SUBSRCPND = 0x%x, SRCPND = 0x%x\n\r", ADCUPDN, SUBSRCPND, SRCPND);
/* 設(shè)置中斷 */
adc_ts_int_init();
/* 讓觸摸屏控制器進(jìn)入"等待中斷模式" */
enter_wait_pen_down_mode();
}
六、觸摸屏編程_ADC中斷
加上ADC中斷把觸點(diǎn)的xy坐標(biāo)讀出來(lái)
查看touchscreen.c
寫(xiě)出這個(gè)自動(dòng)測(cè)量的函數(shù)
void enter_auto_measure_mode(void)
{
//現(xiàn)在是自動(dòng)測(cè)量破托,我們沒(méi)有機(jī)會(huì)分別設(shè)置這些開(kāi)關(guān)
設(shè)置AUTO_PST =1
XY_PST = 00
ADCTSC = AUTO_PST | NO_OPR_MODE;
}
現(xiàn)在是自動(dòng)測(cè)量肪跋,我們沒(méi)有機(jī)會(huì)分別設(shè)置這些開(kāi)關(guān)