韋東山嵌入式Linux學習——017 ADC和觸摸屏(2)-按下鬆開檢測

ADC和觸摸屏(2)-按下鬆開檢測

/*
 *硬件平臺:韋東山嵌入式Linxu開發板(S3C2440.v3)
 *軟件平臺:運行於VMware Workstation 12 Player下UbuntuLTS16.04_x64 系統,
 *參考資料:開發版原理圖,S3C2440A datasheet
*/


一、前言

  在017 ADC和觸摸屏(1)-硬件原理介紹這一篇博文中,介紹了相關的硬件操作,接下來開始編寫程序。

二、相關寄存器

1、ADC和觸摸屏硬件設置寄存器

1.1 ADCCON

在這裏插入圖片描述

	/* [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;	

2.2 ADCTSC

在這裏插入圖片描述
這個是用來主要用來控制觸摸屏電路中的開關閉合,這裏我們先宏定義,供後面使用。

/* ADCTSC's bits */
#define PEN_UP_BIT     		(1 << 8)
#define PEN_DOWN_BIT   		(0 << 8)

#define YM_OUT_ENABLE    	(1 << 7)
#define YM_OUT_DISABLE   	(0 << 7)

#define YP_OUT_ENABLE   	(0 << 6)
#define YP_OUT_DISABLE   	(1 << 6)

#define XM_OUT_ENABLE    	(1 << 5)
#define XM_OUT_DISABLE   	(0 << 5)

#define XP_OUT_ENABLE    	(0 << 4)
#define XP_OUT_DISABLE   	(1 << 4)

#define XP_POLLUP_ENABLE    (0 << 3)
#define XP_POLLUP_DISABLE   (1 << 3)

#define NO_OPR_MODE         (0 << 0)
#define WAIT_INTER_MODE     (3 << 0)
#define AUTO_PST			(1 << 2)

3.3 ADCDAT0

在這裏插入圖片描述

int x = ADCDAT0 & 0x3ff;

3.4 ADCDAT1

在這裏插入圖片描述

int y = ADCDAT1 & 0x3ff;

2、中斷設置相關寄存器

關於ADC和觸摸屏的大致中斷流程圖如下
在這裏插入圖片描述

2.1 SRCPND

在這裏插入圖片描述

2.2 INTMSK

在這裏插入圖片描述

2.3 SUBSRCPND

在這裏插入圖片描述
中斷髮生後需要清除對應標誌位

	/* 清中斷 */
	SUBSRCPND = (1 << INT_TC) | (1 << INT_ADC_S);

2.4 INTSUBMSK

在這裏插入圖片描述

	/* 使能中斷 */
	INTSUBMSK &= ~((1 << ADC_INT_BIT) | (1 << TC_INT_BIT));

三、程序編寫

1、程序流程圖

這中,大致介紹了程序的邏輯如下:

  1. 按下觸摸屏,產生觸摸中斷
  2. 在觸摸中斷中,啓動ADC
  3. ADC初始化完成後,產生中斷
  4. 在ADC中斷中,讀取(x, y)座標
  5. 啓動定時器中斷
  6. 定時器中斷髮生時,判斷觸摸屏是否被持續按下
  7. 若是繼續執行 2 步驟,若無則判斷爲無按下,結束整個流程

具體的程序編寫過程如下圖表示:
在這裏插入圖片描述

2、touchscreen.c文件編寫

#include "../s3c2440_soc.h"

#define ADC_INT_BIT (10)
#define TC_INT_BIT 	 (9)
#define INT_ADC_S    (10)
#define INT_TC    	 (9)

#define INT_ADC_TSC  (31)

/* ADCTSC's bits */
#define PEN_UP_BIT     		(1 << 8)
#define PEN_DOWN_BIT   		(0 << 8)

#define YM_OUT_ENABLE    	(1 << 7)
#define YM_OUT_DISABLE   	(0 << 7)

#define YP_OUT_ENABLE   	(0 << 6)
#define YP_OUT_DISABLE   	(1 << 6)

#define XM_OUT_ENABLE    	(1 << 5)
#define XM_OUT_DISABLE   	(0 << 5)

#define XP_OUT_ENABLE    	(0 << 4)
#define XP_OUT_DISABLE   	(1 << 4)

#define XP_POLLUP_ENABLE    (0 << 3)
#define XP_POLLUP_DISABLE   (1 << 3)

#define NO_OPR_MODE         (0 << 0)
#define WAIT_INTER_MODE     (3 << 0)
#define AUTO_PST			(1 << 2)

void enter_wait_pen_down(void)
{
	/* 設置寄存器,控制開關,處於等待中斷模式*/
	ADCTSC = PEN_DOWN_BIT | YM_OUT_ENABLE | XP_POLLUP_ENABLE | XP_OUT_DISABLE | YP_OUT_DISABLE | XM_OUT_DISABLE | WAIT_INTER_MODE;
}

void enter_wait_pen_up(void)
{
	/* 設置寄存器,控制開關,處於等待中斷模式*/
	ADCTSC = PEN_UP_BIT | YM_OUT_ENABLE | XP_POLLUP_ENABLE | XP_OUT_DISABLE | YP_OUT_DISABLE | XM_OUT_DISABLE | WAIT_INTER_MODE;
}

void enter_auto_measure_mode(void)
{
	ADCTSC = AUTO_PST | NO_OPR_MODE;
}

void Isr_Adc(void)
{
	int x, y;

	/* 電容筆處於按下 */
	if (!(ADCDAT0 & (1 << 15))) {
		x = ADCDAT0 & 0x3ff;
		y = ADCDAT1 & 0x3ff;
		printf("x =%08d,y =%08d\n\r", x, y);
	}

	enter_wait_pen_up();
}

void Isr_Tc(void)
{
	if (ADCDAT0 & (1 << 15)) {
		enter_wait_pen_down();
	}
	
	else {	
		/* 進入自動測量模式 */
		enter_auto_measure_mode();

		/* 開啓ADC */
		ADCCON |= (1<<0);
	}
}


/* 中斷服務函數 */
void AdcTsIntHandle(void)
{
	if (SUBSRCPND & (1 << INT_TC))		/* 觸摸屏中斷 */
		Isr_Tc();
	
	if (SUBSRCPND & (1 << INT_ADC_S))	/* ADC中斷 */
		Isr_Adc();

	/* 清中斷 */
	SUBSRCPND = (1 << INT_TC) | (1 << INT_ADC_S);
}

void adc_ts_int_init(int irq)
{
	/* 註冊中斷服務函數採用之前課上的函數 */
	register_irq(irq, AdcTsIntHandle); 

	/* 使能中斷 */
	INTSUBMSK &= ~((1 << ADC_INT_BIT) | (1 << TC_INT_BIT));
}

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);
	
	/*  按下觸摸屏, 延時一會再發出TC中斷
	 *  延時時間 = ADCDLY * 晶振週期 = ADCDLY * 1 / 12000000 = 5ms
	 */
	ADCDLY = 60000;	
}

/* 觸摸屏初始化 */
void touchsrceen_init(void)
{
	/* 設置中斷 */
	adc_ts_int_init(INT_ADC_TSC);

	/* 設置觸摸屏接口:寄存器 */
	adc_ts_reg_init();

	/* 讓觸摸屏控制器進入"等待中斷(等待觸摸筆按下)模式" */
	enter_wait_pen_down();
}

3、touchscreen_test.c文件編寫

void touchscreen_test(void)
{
	touchsrceen_init();
}

四、測試結果

在這裏插入圖片描述
從左往右,從上往下連續點擊觸摸屏,發現:可以檢測到按下和鬆開,但是硬件上連接問題,使得觸摸屏的xy對應LCD的顯示屏的yx,後續通過軟件解決這個問題。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章