Compiled using RVDS4.0
We mainly look at how to configure the mode
I have been using automatic X, Y sampling before, but the readings were not accurate. Finally, the sampling was separated and it worked. It should be noted that after enabling ADC reading, the conversion result register needs to be read first, but at this time, the last conversion result is read. If it is a continuous reading, it is necessary to wait for the conversion to complete, otherwise the conversion result will be inaccurate.
adc.c
/****************************************************** *************************************************** **********
* File name: ADC.c
* Function: S3C6410 ADC bottom-level driver function
* Author: cp1300@139.com
* Created: March 12, 2012 21:05
* Last modified: March 12, 2012
* Details: Touch screen driver and related ADC driver
* Question: There has always been a misunderstanding. I always thought that after using the start read operation, I could read the converted data each time after reading the DAT register. Eventually, I found that after using this, I could only read the previous data.
* You still need to wait until the conversion is complete, otherwise the data will be very messy when converting continuously.
* Now use manual control to start the conversion
*************************************************** *************************************************** *********/
#include "system.h"
#include "ADC.h"
//ADC control register ADCCON
#define ADCCON_RESSEL_12BIT (1 << 16) //12-bit mode
#define ADCCON_ECFLG (0 << 15) //A/D conversion end flag read only;
#define ADCCON_PRSCEN (1 << 14) //A/D converter prescaler enable
#define ADCCON_PRSCVL (32 << 6) //Prescaler value, 1-255, scaler value + 1, at least 1/5 of PCLK, PCLK = 66MHZ, fastest conversion at 2.5MHZ clock
#define ADCCON_SEL_MUX (0 << 3) //Select channel 0 by default
#define ADCCON_STDBM (0 << 2) //Normal mode
#define ADCCON_READ_START (0 << 1) // Turn off the start of the read operation
#define ADCCON_ENABLE_START (0 << 0) //If READ_START is enabled, this value is invalid.
//ADCDLY
#define ADCDLY_DELAY 500 //Automatic sampling delay time,
/****************************************************** *************************************************** ************************
*Function: void SetADC_Channel(u8 ch)
*Function: Set ADC input channel
*Parameter: ch: channel number, 0-7
*Return: None
*Depends on: underlying macro definitions
*Author : cp1300@139.com
*Time : 20120513
*Last modified: 20120513
*Description: ADC input channel selection
*************************************************** *************************************************** *********************/
void SetADC_Channel(u8 ch)
{
ADC->CON &= ~(7 << 3); //Clear channel
ADC->CON |= ch & (0x07); //Set channel number
}
/****************************************************** *************************************************** ************************
*Function: void ADC_Init(void)
*Function: ADC initialization
*Parameters: None
*Return: None
*Depends on: underlying macro definitions
*Author : cp1300@139.com
*Time : 20120312
*Last modified: 20120313
*Description: ADC initialization
*************************************************** *************************************************** *********************/
void ADC_Init(void)
{
//ADC control register configuration; 12BIT mode
ADC->CON = ADCCON_RESSEL_12BIT + ADCCON_ECFLG + ADCCON_PRSCEN + ADCCON_PRSCVL + ADCCON_SEL_MUX + ADCCON_STDBM + ADCCON_READ_START + ADCCON_ENABLE_START;
ADC->DLY = ADCDLY_DELAY; //Set automatic interval sampling time
}
/****************************************************** *************************************************** ************************
*Function: void ADC_SetMode(u8 Mode)
*Function: Set ADC mode
*Parameters: None
*Return: None
*Depends on: underlying macro definitions
*Author : cp1300@139.com
*Time : 20120313
*Last modified: 20120313
*Description: Set ADC mode
*************************************************** *************************************************** *********************/
void ADC_SetMode(u8 Mode)
{
ADC->TSC &= (1 << 8); // Clear the previous settings
ADC->CON &= ~BIT2; //Exit standby mode
XP_UP_DISABLE(); //XP pull-up disabled
Normal_ADC_Mode(); //Normal ADC mode
switch(Mode)
{
case COMMON_AD_MODER: //Common ADC mode
Normal_ADC_Mode();break;
case ASUNDER_X_MODER: //Separate X scan mode
{
ADCTSC_XP_VDD();
ADCTSC_XM_GND();
ADCTSC_YP_HZ();
ADCTSC_YM_HZ();
X_PosMode();
}break; //XP=external power,XM=GND,YP=AIN5,YM=high impedance
case ASUNDER_Y_MODER: //Separate Y scan mode
{
ADCTSC_XP_HZ();
ADCTSC_XM_HZ();
ADCTSC_YP_VDD();
ADCTSC_YM_GND();
Y_PosMode();
}break; //XP=AIN7,XM=high impedance,YP=external power,YM=GND
case AUTO_XY_MODER: //Automatic XY scanning mode
{
AUTO_XYPosition();
}break;
case INT_AD_MODER: //wait for interrupt mode
{
ADCTSC_XP_HZ();
ADCTSC_XM_HZ();
ADCTSC_YP_HZ();
ADCTSC_YM_GND();
XP_UP_ENABLE(); //XP pull-up enable
INT_WaitingMode();
}break; //XP pull-up, XM = high impedance, YP = AIN5, YM = GND
case STANDBY_AD_MODER: //Power-down mode
StandbyMode();break;
default:break;
}
}
/****************************************************** *************************************************** ************************
*Function: u16 ADC_ReadX(void)
*Function: Read X coordinate
*Parameters: None
*Return: Original X coordinate value
*Depends on: underlying macro definitions
*Author : cp1300@139.com
*Time: 20121006
*Last modified: 20121006
*Description: What is read is ADC conversion register 0
* Need to set ADC mode first
*************************************************** *************************************************** *********************/
u16 ADC_ReadX(void)
{
ADC_Start(); //Start an ADC conversion
ADC_Wait(); //Wait for conversion to complete
return ADC_ReadData0();
}
/****************************************************** *************************************************** ************************
*Function: u16 ADC_ReadY(void)
*Function: Read Y coordinate
*Parameters: None
*Return: Original Y coordinate value
*Depends on: underlying macro definitions
*Author : cp1300@139.com
*Time: 20121006
*Last modified: 20121006
*Description: Read ADC conversion register 1
* Need to set ADC mode first
*************************************************** *************************************************** *********************/
u16 ADC_ReadY(void)
{
ADC_Start(); //Start an ADC conversion
ADC_Wait(); //Wait for conversion to complete
return ADC_ReadData1();
}
/****************************************************** *************************************************** ************************
*Function: u8 Get_TouchState(void)
*Function: Get touch status
*Parameters: None
*Return: 1: pen lifted; 0: pen pressed
*Depends on: underlying macro definitions
*Author : cp1300@139.com
*Time: 20120315
*Last modified: 20120315
*Description: Determine the status by reading BIT15 of ADCDAT1
*************************************************** *************************************************** *********************/
u8 Get_TouchState(void)
{
return((ADC->DAT1 & BIT15) ? TOUCH_UP : TOUCH_DOWN);
}
//Touch screen interrupt service function
void __irq Isr_Touch(void)
{
TOUCH_ClearInt(); //Clear the touch screen interrupt flag
VICInterruptEnd(); //Interrupt ends
}
adc.h
/****************************************************** *************************************************** **********
* File name: ADC.h
* Function: S3C6410 touch screen ADC bottom driver function
* Author: Chen Peng
* Created: March 12, 2012 21:05
* Last modified: March 12, 2012
* Details: Touch screen driver and related ADC driver
*************************************************** *************************************************** *********/
#ifndef _ADC_H_
#define _ADC_H_
//Button status
#define TOUCH_DOWN 0
#define TOUCH_UP 1
#define TOUCH_Posedge 0x01 //Pen lift event
#define TOUCH_Negedge 0x02 //Pen press event
//ADC sampling mode
#define COMMON_AD_MODER 0 //Common AD conversion mode
#define ASUNDER_X_MODER 1 //Separate X sampling mode
#define ASUNDER_Y_MODER 2 //Separate Y sampling mode
#define AUTO_XY_MODER 3 //Automatic X,Y sampling mode //I don't know why it is inaccurate, only separate X,Y scanning mode can be used
#define INT_AD_MODER 4 //Sampling mode for waiting interrupt
#define STANDBY_AD_MODER 5 //Power-down mode
//ADC channel selection
#define ADC_CH_AIN0 0
#define ADC_CH_AIN1 1
#define ADC_CH_AIN2 2
#define ADC_CH_AIN3 3
#define ADC_CH_YM 4
#define ADC_CH_YP 5
#define ADC_CH_XM 6
#define ADC_CH_XP 7
//Read conversion register 0
#define ADC_ReadData0() (ADC->DAT0&0xfff)
#define ADC_ReadData1() (ADC->DAT1&0xfff)
//related functions
void ADC_Init(void); //Initialize ADC
void SetADC_Channel(u8 ch); //ADC channel selection
void ADC_SetMode(u8 Mode); //ADC working mode setting
u8 Get_TouchState(void); //Get the touch pen status
u16 ADC_ReadX(void); //Read X coordinate
u16 ADC_ReadY(void); //Read Y coordinate
//Enable pen lift interrupt
__inline void ADCTSC_UD_SEN (u8 EN)
{
ADC->TSC &= ~BIT8; //pen down interrupt
if(EN == ENABLE)
ADC->TSC |= BIT8;
}
//YM connected to GMD is invalid, connect to HZ
__inline void ADCTSC_YM_HZ(void)
{
ADC->TSC &= ~BIT7;
}
//YM connected to GMD is effective, connected to GND
__inline void ADCTSC_YM_GND(void)
{
ADC->TSC |= BIT7;
}
//YP connected to VDD is invalid, connect to HZ
__inline void ADCTSC_YP_HZ(void)
{
ADC->TSC |= BIT6;
}
//YP is valid when connected to VDD, and VDDA
__inline void ADCTSC_YP_VDD(void)
{
ADC->TSC &= ~BIT6;
}
//XM is invalid when connected to GMD, connect to HZ
__inline void ADCTSC_XM_HZ(void)
{
ADC->TSC &= ~BIT5;
}
//XM connected to GMD is effective, connected to GND
__inline void ADCTSC_XM_GND(void)
{
ADC->TSC |= BIT5;
}
//Connecting XP to VDD is invalid, connect to HZ
__inline void ADCTSC_XP_HZ(void)
{
ADC->TSC |= BIT4;
}
//XP connected to VDD is effective, connected to VDDA
__inline void ADCTSC_XP_VDD(void)
{
ADC->TSC &= ~BIT4;
}
//Normal ADC conversion mode
__inline void Normal_ADC_Mode(void)
{
ADC->TSC &= ~BIT2; //Normal ADC conversion
}
//Standby mode
__inline void StandbyMode(void)
{
ADC->CON |= BIT2;
}
//Automatic X,Y conversion
__inline void AUTO_XYPosition(void)
{
ADC->TSC &= ~(BIT0+BIT1);
ADC->TSC |= BIT2; //Automatic X,Y conversion
}
//X,Y manual measurement mode, no running mode
__inline void NO_OpeMode(void)
{
ADC->TSC &= ~(BIT0+BIT1);
}
//X,Y manual measurement mode, X coordinate conversion mode
__inline void X_PosMode(void)
{
NO_OpeMode(); //Clear settings
ADC->TSC |= 1;
}
//X,Y manual measurement mode, Y coordinate conversion mode
__inline void Y_PosMode(void)
{
NO_OpeMode(); //Clear settings
ADC->TSC |= 2;
}
//X,Y manual measurement mode, waiting for interrupt mode
__inline void INT_WaitingMode(void)
{
NO_OpeMode(); //Clear settings
ADC->TSC |= 3;
}
//XP pull-up start
__inline void XP_UP_ENABLE(void)
{
ADC->TSC &= ~BIT3;
}
//XP pull-up disabled
__inline void XP_UP_DISABLE(void)
{
ADC->TSC |= BIT3;
}
// Clear ADC wake-up interrupt
__inline void ADC_ClearInt(void)
{
ADC->CLRINT = 0xffffffff; //Write any value to clear the interrupt flag
}
// Clear the touch screen interrupt
__inline void TOUCH_ClearInt(void)
{
ADC->UPDN = 0; // Clear the ADC touch screen UP-DOWN register
ADC->CLRINTPNDNUP = 0xffffffff; //Write any value to clear the interrupt flag
}
//Start an ADC conversion
__inline void ADC_Start(void)
{
ADC->CON |= BIT0; //Start ADC conversion
}
//Wait for ADC conversion to complete
__inline void ADC_Wait(void)
{
while(!(ADC->CON & BIT15));
}
#endif
touch.c
/****************************************************** *************************************************** **********
* File name: Touch.c
* Function: S3C6410 resistive touch screen driver
* Author: cp1300@139.com
* Created: October 6, 2012 17:31
* Last modified: October 6, 2012
* Details: Requires underlying ADC support
*************************************************** *************************************************** *********/
#include "system.h"
#include "adc.h"
#include "touch.h"
Pen_Holder Pen_Point; //Define pen entity
// Enable touch screen calibration, other support required
#define _TOUCH_ADJUST 1
#if _TOUCH_ADJUST
void TOUCH_Adjust(void); //touch screen calibration
#endif //_TOUCH_ADJUST
/****************************************************** *************************************************** ************************
*Function: void TOUCH_Init(FunctionalState EnableInt)
*Function: Touch screen initialization
*Parameter: EnableInt: pen interrupt enable
*Return: None
*Depends on: underlying macro definitions
*Author : cp1300@139.com
*Time : 20120313
*Last modified: 20121006
*Description: Touch screen initialization
*************************************************** *************************************************** *********************/
void TOUCH_Init(FunctionalState EnableInt)
{
ADC_Init(); //Initialize ADC
TOUCH_ClearInt(); //Clear the touch screen interrupt flag
ADC_ClearInt(); //Clear ADC interrupt
ADC_SetMode(INT_AD_MODER); //Wait for interrupt mode
ADCTSC_UD_SEN(DISABLE); //Set to press interrupt
if(EnableInt == ENABLE) // Enable pen interrupt
{
//Set_IsrAddr(INT_PENDNUP,(u32)Isr_Touch); //Set interrupt vector entry
//Set_IntEnable(INT_PENDNUP,ENABLE); //Turn on the touch screen and press
}
#if _TOUCH_ADJUST
TOUCH_Adjust(); //Touch screen calibration
#endif //_TOUCH_ADJUST
}
/****************************************************** *************************************************** ************************
* Function: u16 ADS_Read_XY(u16(*ADC_ReadXY)(void))
* Function: Use the bubble method to read the coordinates once
* Parameter: ADC_ReadXY: X or Y coordinate reading function
* Return: conversion result
* Depends on: ADC
* Author : cp1300@139.com
* Date : 20121006
* Last modified: 20121006
* Description: Read READ_TIMES times of data continuously and sort them in ascending order.
Then remove the lowest and highest LOST_VAL numbers and take the average
*************************************************** *************************************************** *********************/
#define READ_TIMES 15 //Read times
#define LOST_VAL 5 //discard value
u16 ADS_Read_XY(u16(*ADC_ReadXY)(void))
{
u16 i, j;
u16 buff[READ_TIMES];
u16 sum=0;
u16 temp;
for(i = 0;i < READ_TIMES;i ++)
{
buff[i] = ADC_ReadXY();
}
for(i = 0;i < READ_TIMES - 1;i ++)//Sort
{
for(j = i + 1;j < READ_TIMES;j++)
{
if(buff[i] > buff[j]) // sort in ascending order
{
temp = buff[i];
buff[i] = buff[j];
buff[j] = temp;
}
}
}
sum = 0;
for(i = LOST_VAL;i < READ_TIMES - LOST_VAL;i ++)
sum += buff[i];
temp = sum / (READ_TIMES - 2 * LOST_VAL);
return temp;
}
/****************************************************** *************************************************** ************************
* Function: u8 Read_ADS(u16 *x,u16 *y)
* Function: Read X,Y coordinates with filtering
* Parameter: X,Y coordinate value buffer pointer
* Return: 1: conversion result is valid; 0: conversion result is invalid
* Dependency: XPT2046 underlying function
* Author : cp1300@139.com
* Date : 20120914
* Last modified: 20120914
* Description: Coordinate reading with filtering
The minimum value cannot be less than MINI_ADC_DATA.
*************************************************** *************************************************** *********************/
#define MINI_ADC_DATA 100
u8 Read_ADS(u16 *x,u16 *y)
{
u16 xtemp, ytemp;
ADC_SetMode(ASUNDER_X_MODER); //Set ADC to separate X sampling mode
xtemp = ADS_Read_XY(ADC_ReadX); //Read X coordinate
ADC_SetMode(ASUNDER_Y_MODER); //Set ADC to separate Y sampling mode
ytemp = ADS_Read_XY(ADC_ReadY); //Read Y coordinate
ADC_SetMode(INT_AD_MODER); //Set ADC to wait interrupt mode
if(xtemp < MINI_ADC_DATA || ytemp < MINI_ADC_DATA)
return 0; // reading failed
*x = xtemp;
*y = ytemp;
return 1; //Reading successful
}
/****************************************************** *************************************************** ************************
* Function: u8 Read_ADS2(u16 *x,u16 *y)
* Function: Read 2 valid AD values continuously
* Parameter: X,Y coordinate value buffer pointer
* Return: 1: conversion result is valid; 0: conversion result is invalid
* Depends on: u8 Read_ADS(u16 *x,u16 *y)
* Author : cp1300@139.com
* Date : 20120914
* Last modified: 20120914
* Description: Read valid AD values 2 times in succession, and the deviation between the two times cannot exceed ERR_RANGE
If the conditions are met, the reading is considered correct, otherwise the reading is wrong.
This function can greatly improve the accuracy
*************************************************** *************************************************** *********************/
#define ERR_RANGE 50 //Error range
u8 Read_ADS2(u16 *x,u16 *y)
{
u16 x1,y1;
u16 x2,y2;
u8 flag;
flag = Read_ADS(&x1,&y1);
if(flag == 0)
return(0);
flag = Read_ADS(&x2,&y2);
if(flag == 0)
return(0);
if(((x2 <= x1 && x1 < x2 + ERR_RANGE) || (x1 <= x2 && x2 < x1 + ERR_RANGE))
&& ((y2 <= y1 && y1 < y2 + ERR_RANGE) || (y1 <= y2 && y2 < y1 + ERR_RANGE))) //The two samples are within +-ERR_RANGE
{
*x = (x1 + x2) / 2;
*y = (y1 + y2) / 2;
return 1;
}
else
return 0;
}
/****************************************************** *************************************************** ************************
* Function: u8 TOUCH_ReadOneTP(void)
* Function: Read the original coordinates once
* Parameters: None
* Return: 1: conversion result is valid; 0: conversion result is invalid
* Depends on: u8 Read_ADS2(u16 *x,u16 *y)
* Author : cp1300@139.com
* Date : 20120914
* Last modified: 20120914
* Description: Call Read_ADS2 function to read. If Read_ADS2 fails, repeat the reading. The maximum number of times to read is MAX_READ_ADS
If it fails, it will return 0. Note that returning 1 means the result is valid.
The result of the conversion is stored in x0, y0 of the structure Pen_Holder
*************************************************** *************************************************** *********************/
#define MAX_READ_ADS 5 //Maximum number of retries
u8 TOUCH_ReadOneTP(void)
{
u8 i;
u16 x,y;
for(i = MAX_READ_ADS;i != 0;i --)
{
if(Read_ADS2(&x,&y))
{
Pen_Point.x0 = x; //Conversion is valid, store the result
Pen_Point.y0 = y;
return 1; //Return success
}
}
return 0; //Return failure
}
/****************************************************** *************************************************** ************************
* Function: void TOUCH_ConvertPos(void)
* Function: Collect and convert touch coordinates
* Parameters: None
* Returns: None
* Depends on: LCD.C, touch screen ADC bottom layer
* Author : cp1300@139.com
* Date : 20120914
* Last modified: 20121006
* Description: The conversion result is determined according to the calibration parameters of the touch screen and saved in x, y
* Touch calibration is required first
*************************************************** *************************************************** *********************/
void TOUCH_ConvertPos(void)
{
if(TOUCH_ReadOneTP())
{
Pen_Point.x = Pen_Point.xfac * Pen_Point.x0 + Pen_Point.xoff;
Pen_Point.y = Pen_Point.yfac * Pen_Point.y0 + Pen_Point.yoff;
}
}
//Touch screen calibration related
///////////////////////////////////////////////////// ///////////////////////////////////////////////////// /////////
#if _TOUCH_ADJUST
#include "TFT_LCD.h"
#include "stdlib.h"
#include "math.h"
#include "delay.h"
/****************************************************** *************************************************** ************************
* Function: void Drow_Touch_Point(u16 x,u16 y)
* Function: Draw a touch point for calibration
* Parameters: x, y: center position of touch point
* Returns: None
* Depends on : LCD.C
* Author : cp1300@139.com
* Date : 20120914
* Last modified: 20120914
* Description: It will call the circle, line, rectangle and other functions in LCD.C
*************************************************** *************************************************** *********************/
void Drow_Touch_Point(u16 x,u16 y)
{
Draw_Circle(x,y,10,0xf0f0);//Draw a circle
Draw_Circle(x,y,3,0xf0f0);//Draw a circle
LCD_DrawLine(x - 15, y, x + 15, y,0xf0f0); //Draw line
LCD_DrawLine(x, y - 15, x, y + 15,0xf0f0); //Draw line
LCD_DrawRectangle(x - 10,y - 10,x + 10,y + 10,0xf0f0); //Draw rectangle
}
/****************************************************** *************************************************** ************************
* Function: void TOUCH_Adjust(void)
* Function: Touch screen calibration
* Parameters: None
* Returns: None
* Depends on: LCD.C, touch screen ADC bottom layer
* Author : cp1300@139.com
* Date : 20120914
* Last modified: 20120914
* Description: Get four calibration values
* (20,20) (LCD_XSIZE-20,20)
*
*
* (20,LCD_YSIZE-20) (LCD_XSIZE-20,LCD_YSIZE-20)
*************************************************** *************************************************** *********************/
void TOUCH_Adjust(void)
{
u16 pos_temp[4][2]; //coordinate cache value
u8 cnt=0;
u16 d1,d2;
u32 tem1,tem2;
float fac;
cnt=0;
LCD_ClearScreen(0xffff);//Clear screen
Drow_Touch_Point(20,20);//Draw point 1
//Pen_Point.xfac=0; //xfac is used to mark whether it has been calibrated, so it must be cleared before calibration! To avoid errors
while(1)
{
if(GetPenStartus() == TOUCH_DOWN) //The button is pressed
{
if(TOUCH_ReadOneTP()) //Get single key value
{
pos_temp[cnt][0]=Pen_Point.x0;
pos_temp[cnt][1]=Pen_Point.y0;
cnt++;
}
while(GetPenStartus() == TOUCH_DOWN); //Wait for the key to be lifted
switch(cnt)
{
case 1:
LCD_ClearScreen(0xffff);//Clear screen
Drow_Touch_Point(LCD_XSIZE-20,20);//Draw point 2
break;
case 2:
LCD_ClearScreen(0xffff);//Clear screen
Drow_Touch_Point(20,LCD_YSIZE-20);//Draw point 3
break;
case 3:
LCD_ClearScreen(0xffff);//Clear screen
Drow_Touch_Point(LCD_XSIZE-20,LCD_YSIZE-20);//Draw point 4
break;
case 4: //All four points have been obtained
// Opposite sides are equal
tem1=abs(pos_temp[0][0]-pos_temp[1][0]);//x1-x2
tem2=abs(pos_temp[0][1]-pos_temp[1][1]);//y1-y2
tem1*=tem1;
tem2*=tem2;
d1=sqrt(tem1+tem2); //get the distance between 1 and 2
tem1=abs(pos_temp[2][0]-pos_temp[3][0]);//x3-x4
tem2=abs(pos_temp[2][1]-pos_temp[3][1]);//y3-y4
tem1*=tem1;
tem2*=tem2;
d2=sqrt(tem1+tem2); //get the distance between 3 and 4
fac=(float)d1/d2;
if(fac<0.95||fac>1.05||d1==0||d2==0)//Unqualified
{
cnt=0;
LCD_ClearScreen(0xffff);//Clear screen
Drow_Touch_Point(20,20);
continue;
}
tem1=abs(pos_temp[0][0]-pos_temp[2][0]);//x1-x3
tem2=abs(pos_temp[0][1]-pos_temp[2][1]);//y1-y3
tem1*=tem1;
tem2*=tem2;
d1=sqrt(tem1+tem2); //get the distance between 1 and 3
tem1=abs(pos_temp[1][0]-pos_temp[3][0]);//x2-x4
tem2=abs(pos_temp[1][1]-pos_temp[3][1]);//y2-y4
tem1*=tem1;
tem2*=tem2;
d2=sqrt(tem1+tem2); //get the distance between 2 and 4
fac=(float)d1/d2;
if(fac<0.95||fac>1.05)//failed
{
cnt=0;
LCD_ClearScreen(0xffff);//Clear screen
Drow_Touch_Point(20,20);
continue;
}//Correct
//Diagonals are equal
tem1=abs(pos_temp[1][0]-pos_temp[2][0]);//x1-x3
tem2=abs(pos_temp[1][1]-pos_temp[2][1]);//y1-y3
tem1*=tem1;
tem2*=tem2;
d1=sqrt(tem1+tem2); //get the distance between 1 and 4
tem1=abs(pos_temp[0][0]-pos_temp[3][0]);//x2-x4
tem2=abs(pos_temp[0][1]-pos_temp[3][1]);//y2-y4
tem1*=tem1;
tem2*=tem2;
d2=sqrt(tem1+tem2); //get the distance between 2 and 3
fac=(float)d1/d2;
if(fac<0.95||fac>1.05)//failed
{
cnt=0;
LCD_ClearScreen(0xffff);//Clear screen
Drow_Touch_Point(20,20);
continue;
}//Correct
//Calculation results
Pen_Point.xfac=(float)(LCD_XSIZE-40)/(pos_temp[1][0]-pos_temp[0][0]); //Get xfac
Pen_Point.xoff=(LCD_XSIZE-Pen_Point.xfac*(pos_temp[1][0]+pos_temp[0][0]))/2; //get xoff
Pen_Point.yfac=(float)(LCD_YSIZE-40)/(pos_temp[2][1]-pos_temp[0][1]); //get yfac
Pen_Point.yoff=(LCD_YSIZE-Pen_Point.yfac*(pos_temp[2][1]+pos_temp[0][1]))/2;//Get yoff
//Wire_Touch(); //Store calibration results
LCD_ClearScreen(0xffff);//Clear screen
Show_Char(35,LCD_YSIZE/2,"Touch Screen Adjust OK!",0xf800,0xffff,0x80);
Delay_MS(1000);
LCD_ClearScreen(0xffff);//Clear screen
return; //Calibration completed
}
}
}
}
#endif //_TOUCH_ADJUST
///////////////////////////////////////////////////// ///////////////////////////////////////////////////// ///////////
touch.h
/****************************************************** *************************************************** **********
* File name: Touch.h
* Function: S3C6410 resistive touch screen driver
* Author: cp1300@139.com
* Created: October 6, 2012 17:31
* Last modified: October 6, 2012
* Details: Requires underlying ADC support
*************************************************** *************************************************** *********/
#ifndef TOUCH_H_
#define TOUCH_H_
#include "adc.h"
#ifndef TOUCH_DOWN
#define TOUCH_DOWN 0
#endif //TOUCH_DOWN
#ifndef TOUCH_UP
#define TOUCH_UP 1
#endif //TOUCH_UP
//Pen handle structure
typedef struct
{
u16 x0; //Original coordinates
u16 y0;
u16 x; //final/temporary coordinates
u16 y;
u8 Touch_Sta; //Pen status
//Touch screen calibration parameters
float xfac;
float yfac;
short xoff;
short yoff;
}Pen_Holder;
extern Pen_Holder Pen_Point; //Define a structure variable of a pen holder
void TOUCH_Init(FunctionalState EnableInt); //Touch screen initialization function
u8 TOUCH_ReadOneTP(void); //Read one coordinate
#define GetPenStartus() Get_TouchState() //Get the touch pen status
void TOUCH_ConvertPos(void); //Get the actual coordinates after conversion
#endif /*TOUCH_H_*/
Main function test program
main.c
#include "system.h"
#include "uart.h"
#include "tft_lcd.h"
#include "other.h"
#include "delay.h"
#include "timer.h"
#include "touch.h"
//LED1 flashing program, flashing in timer 0 interrupt service program, period 400MS
void LED1_flash(void)
{
LED1_FLASH();
}
int main(void)
{
LCD_Init(); //Initialize LCD
UART0_Init(DISABLE,115200); //Initialize the serial port, disable interrupt reception, baud rate 115200
LED_Init(); //Initialize LED
Timer1_Init(400000-1,ENABLE,LED1_flash); //Initialize timer 0, period 400ms
TOUCH_Init(DISABLE); //Initialize the touch screen
lcd_printf("Get_FCLK : %d Hz\n",Get_FCLK());
lcd_printf("Get_PCLK : %d Hz\n",Get_PCLK());
while(1)
{
//LED2_FLASH(); //LED2 flashes
//Delay_US(600000);
if(GetPenStartus() == TOUCH_DOWN) //Pen is pressed
{
TOUCH_ConvertPos();
//lcd_printf("X:%d; Y:%d\n",Pen_Point.x,Pen_Point.y);
Draw_Big_Point(Pen_Point.x,Pen_Point.y,0xf800);
Delay_MS(1);
}
}
}
//Supplement ADC related register structure
#define ADC_BASE 0x7E00B000
//ADC register
typedef struct
{
vu32 CON; //ADC control register
vu32 TSC; //Touch screen control register
vu32 DLY; //ADC start delay register
vu32 DAT0; //ADC data register 0
vu32 DAT1; //ADC data register 1
vu32 UPDN; //Touch screen UP-DOWN register
vu32 CLRINT; //ADC interrupt clear register
u32 Reserved;
vu32 CLRINTPNDNUP; //Touch screen pen interrupt register
}ADC_TypeDef;
#define ADC ((ADC_TypeDef*)ADC_BASE)
Previous article:OK6410 development board bare metal DS18B20 driver
Next article:OK6410 bare metal simple NAND FLASH driver
- Popular Resources
- Popular amplifiers
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications