Touch screen Driver Design
Working principle of touch screen:
The four-wire resistive screen structure covers two layers of uniformly conductive ITO layer on glass or acrylic acid substrates, which are respectively used as the x electrode and y electrode. They are insulated by a uniformly arranged transparent lattice. The positive and negative ends of the X and Y electrodes are drawn from the two ends by the Guide wires (black bold lines), which lead to X-, x +, Y-, Y +.
When the surface of the touch screen is exposed and the pressure is applied, the ITO conductive layer on the upper layer is in contact with the ITO conductive layer on the lower layer to form an equivalent circuit shown in the right figure above.
1. Y coordinate calculation:
The drive voltage V-drive and Y-ground are added to Y +. X + is used as the voltage at the output end to measure the contact point. Due to the uniformity of the ITO layer, the ratio of the electric shock voltage to the V-drive voltage is equal to the ratio of Y coordinate to the screen height.
2. x coordinate calculation:
Add the drive voltage V-drive voltage to X + and the X-ground. Y + is used as the voltage for measuring the contact point at the lead end. Due to the uniform conductivity of the ito layer, the ratio of the contact voltage to the V-drive voltage is equal to the ratio of X coordinate to the screen width.
Y = vx/V-driv * height x = Vy/V-driv * width
Touch screen workflow (understand these steps and the code should be at least 30%)
1. Set the touch screen interface to the pending interrupt mode and wait for the touch screen to be pressed.
2. If the interrupt (int_tc) occurs, select the x/y coordinate conversion mode (x/y coordinate conversion mode, x/y coordinate automatic conversion) to start the adconversion.
3. After the adswitch is complete, use the interrupt (int_adc) to obtain the x/y coordinates,
Adcdat0 bit []-x coordinate;
Adcdat1 bit [9:0]-y coordinate;
4. Set the touch screen interface to the waiting interrupt mode and wait for the touch pen to exit the touch screen.
5. Return to Step 1 and wait until the next touch point is pressed.
# Define global_clk 1 # include <stdlib. h> # include <string. h> # include "def. H "# include" option. H "# include" 2440addr. H "# include" 2440lib. H "# include" 2440slib. H "# include" MMU. H "# include" profile. H "# include" memtest. H "# define adc_freq 2500000 // # define adc_freq 1250000 int COUNT = 0; volatile u32 prescaler; int xdata, ydata; void test_touchpanel (void ); static void _ IRQ adctsauto (void); static void cal_cpu_ B Us_clk (void); void set_clk (void ); /*************************************** * ******** Function Name: delayparameter: timesdescription: delay function return: voidargument: voidautor & date: daniel *************************************** * **********/void delay (INT times) {int I, j; for (I = 0; I <times; I ++) for (j = 0; j <400; j ++ );} /*************************************** * ******** Function Name: mainparameter: voiddesc Ription: main function return: voidargument: voidautor & date: daniel *************************************** * **********/INT main (void) {int scom = 0; mmu_init (); set_clk (); uart_init (0, 115200); uart_select (scom); // uart_printf ("\ nhello world! \ N "); test_touchpanel (); While (1); Return 0 ;} /*************************************** * ******** Function Name: test_touchpanelparameter: voiddescription: Touch Screen initialization return: voidargument: voidautor & date: daniel *************************************** * **********/void test_touchpanel (void) {radcdly = 50000; // Normal conversion mode delay about (1/3. 6864 m) * 50000 = 13.56 ms/* Set AD conversion frequency */prescaler = adc_freq; Uart_printf ("ADC Conv, freq. = % DHZ \ n ", prescaler); prescaler = 50000000/adc_freq-1; // pclk = 50 m radccon = (1 <14) | (prescaler <6 ); // adcprs en, prscvl // radccon = (1 <14) + (prescaler <6); // adcprs en, adcprs value uart_printf ("ADC Touch Screen Test \ n");/* set the touch screen to the pending interrupt mode and wait for the touch pen to be pressed */radctsc = 0xd3; // wfait, xp_pu, xp_dis, xm_dis, yp_dis, ym_en/* clear IRQ * // clearpending (bit_adc); rsrcpnd = 0x80000000; rintpn D = 0x80000000; clearsubpending (bit_sub_tc); pisr_adc = (u32) adctsauto;/* enable int_tc IRQ * // enableirq (bit_adc); rintmsk = 0x7fffffff; // enablesubirq (bit_sub_tc) can be interrupted );} /*************************************** * ******** Function Name: adctsautoparameter: voiddescription: interrupted service program return: voidargument: voidautor & date: daniel *************************************** * **********/static void _ IRQ Adctsauto (void) {u32 saveadcdly; /*************** stylus down ********************* * ** // * detects the subinterrupt source, determine whether int_tc is interrupted, and press the touch pen */If (rsubsrcpnd & (bit_sub_tc) // generate the interrupt {If (! (Radcdat0 & 0x8000) // the interruption caused by the press uart_printf ("\ nstylus down \ n "); else // raise the interrupt uart_printf ("\ nstylus up \ n");}/* pull-up disable, automatic consecutive X, Y coordinate conversion */radctsc = (1 <3) | (1 <2); saveadcdly = radcdly; radcdly = 40000; // latency // Normal conversion mode delay about (1/50 m) * 40000 = 0.8 ms/* Start adconversion */radccon | = 0x1; // start ADC while (radccon & 0x1); // check if enable_start is low while (! (Radccon & 0x8000); // whether the conversion is complete // check if EC (end of conversion) flag is high, this line is necessary ~!! While (! (Rsrcpnd & 0x80000000); // check if ADC is finished with interrupt bit/* Get X, Y coordinate */xdata = (radcdat0 & 0x3ff ); ydata = (radcdat1 & 0x3ff); clearsubpending (bit_sub_tc); // clearpending (bit_adc); rsrcpnd = 0x80000000; rintpnd = 0x80000000; enablesubirq (bit_sub_tc ); // enableirq (bit_adc); rintmsk = 0x7fffffff; /*************** stylus down ********************* * ** // ***************** stylus up ***************** ***** * *** // Set the touch screen to the waiting interrupt mode and wait for the touch pen to lift up */radctsc = 0xd3; // waiting for interrupt radctsc = radctsc | (1 <8 ); // detect stylus up interrupt signal. while (1) // to check pen-up state {If (rsubsrcpnd & (bit_sub_tc) // check if ADC is finished with interrupt bit {uart_printf ("stylus up interrupt ~! \ N "); break; // If stylus is up (1) state }}/ **************** stylus up ****************** * ******/uart_printf ("Count = % 03d XP = % 04d, yp = % 04d \ n ", Count ++, xdata, ydata); radcdly = saveadcdly;/* set the touch screen to the pending interrupt mode and wait for the next touch pen to press */radctsc = 0xd3; // waiting for interrupt clearsubpending (bit_sub_tc); // clearpending (bit_adc); rsrcpnd = 0x80000000; rintpnd = 0x80000000; enablesubirq (bit_sub_tc ); // enableirq (bit_adc); ri Ntmsk = 0x7fffffff ;} /*************************************** * ******** Function Name: set_clk () parameter: voiddescription: sets the CPU clock frequency. Return: voidargument: voidautor & date: daniel *************************************** * **********/void set_clk (void) {int I; u8 key; u32 mpll_val = 0; I = 2; // don't use 100 m! // Boot_params.cpu_clk.val = 3; Switch (I) {Case 0: // 200 key = 12; mpll_val = (92 <12) | (4 <4) | (1); break; Case 1: // 300 key = 13; mpll_val = (67 <12) | (1 <4) | (1); break; case 2: // 400 key = 14; mpll_val = (92 <12) | (1 <4) | (1); break; Case 3: // 440 !!! Key = 14; mpll_val = (102 <12) | (1 <4) | (1); break; default: Key = 14; mpll_val = (92 <12) | (1 <4) | (1); break;} // init fclk = 400 m, so change mpll first changempllvalue (mpll_val> 12) & 0xff, (mpll_val> 4) & 0x3f, mpll_val & 3); // set the register -- rmpllcon changeclockdivider (Key, 12); // The result of rclkdivn [0: 1: 0: 1] 3-0 bit cal_cpu_bus_clk (); // hclk = 100 m pclk = 50 m }/**************************** *********** * ******** Function name: cal_cpu_bus_clkparameter: voiddescription: set the frequency of pclk \ hclk \ fclk return: voidargument: voidautor & date: daniel *************************************** * **********/static void cal_cpu_bus_clk (void) {static u32 cpu_freq; static u32 upll; u32 val; u8 M, P, S; val = rmpllcon; M = (Val> 12) & 0xff; P = (Val> 4) & 0x3f; S = Val & 3; // (m + 8) * fin * 2 cannot exceed 32 digits! Fclk = (m + 8) * (FIN/100) * 2)/(p + 2) * (1 <s) * 100; // fclk = 400 m fin = 12000000 val = rclkdivn; M = (Val> 1) & 3; P = Val & 1; val = rcamdivn; S = Val> 8; Switch (m) {Case 0: hclk = fclk; break; Case 1: hclk = fclk> 1; break; Case 2: if (S & 2) hclk = fclk> 3; else hclk = fclk> 2; break; Case 3: If (S & 1) hclk = fclk/6; else hclk = fclk/3; break;} If (p) pclk = hclk> 1; else pclk = hclk; If (S & 0x10) cpu_freq = HCl K; else cpu_freq = fclk; val = rupllcon; M = (Val> 12) & 0xff; P = (Val> 4) & 0x3f; S = Val & 3; upll = (m + 8) * fin)/(p + 2) * (1 <s); uclk = (rclkdivn & 8 )? (Upll> 1): upll ;}