ARM裸机程序设计—触摸屏程序设计

来源:互联网 发布:新疆七五事件真相知乎 编辑:程序博客网 时间:2024/05/17 05:08

触摸屏程序设计总结:
触摸屏工作流程以及程序设计流程:
一、触摸屏初始化:
  1、设置触摸屏接口为中断等待模式(ADCTSC寄存器),等待触摸笔按下
  2、清除源挂起寄存器(SRCPND)、中断挂起寄存器(INTPND)、子源挂起寄存器

(SUBSRCPND)
  3、程序入口函数,关中断屏蔽寄存器和子中断屏蔽寄存器(INTMSK,INTSUBMSK),中断

模式和中断优先级默认即可
二、触摸屏中断服务子程序:
   一)触摸笔按下中断
     4、如果中断发生,设置x,y坐标为自动转换模式
     5、启动AD转换,然后检测AD转换是否启动
     6、检测AD转换是否结束,若结束,获取x,y坐标的值
     7、对几个寄存器写1清零,防止反复发生中断(这里的中断是笔尖按下中断)
   二)触摸笔抬起中断
     8、设置触摸屏即可为等待中断模式,等待触摸笔抬起(ADCTSC,关键是要设置触摸

笔抬起中断信号)
     9、如果发生中断,不做任何操作,只打印出一句触摸笔抬起中断信息
     10、触摸笔抬起之后,把得到的x,y坐标值发送给PC机,显示出具体数值
   三)再次设置触摸屏为等待中断模式,等待下次触摸屏被按下

源程序:

//Main.c

/*************************************************
实验环境:mini2440开发板
完成时间:2011,4,14
作者:阿龍
实现功能:对触摸屏进行设置,通过串口把触摸屏上被按下的位置,用数值显示出来
遇到的问题:这里一定要对MMU_Init()进行初始化,不然程序会出在超级终端上显示错误。
**************************************************/
#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"

void ADC_init(void);
void TC_init(void);
void delay(int times);
void Set_Clk(void);
static void cal_cpu_bus_clk(void);
static void __irq TChandler(void);
 int value_x=0;
 int value_y=0;
 int count=0;
void Main(void)

  int Scom=0;

  MMU_Init();
  Set_Clk();
  Uart_Init(0,115200);
  Uart_Select(Scom);
  ADC_init();
  TC_init();
  while(1);
}
void delay(int times)
{
 int x,y;
 for(x=times;x>0;x--)
  for(y=400;y>0;y--);
}
/*************************************************
触摸屏初始化
**************************************************/
void TC_init(void)
{
 /*设置触摸屏接口为中断等待模式,此时XP_SEN置1,PULL_UP置0*/
 rADCTSC = 0xd3; //XP_PU,XP_Dis,XM_Dis,YP_Dis,YM_En,UD设为0(检测笔尖落下中断信号)
 ClearPending(BIT_ADC);
 ClearSubPending(BIT_SUB_TC);
  
 pISR_ADC=(U32)TChandler;
 EnableIrq(BIT_ADC);
 EnableSubIrq(BIT_SUB_TC); 
}
/*************************************************
触摸屏中断服务子函数
**************************************************/
static void __irq TChandler(void)
{
//****************************************************
//1、触摸笔落下中断
//*****************************************************/ 
 if(rSUBSRCPND & (0x1<<9)) 
 {  
  if(!(rADCDAT0 & 0x80000)) //表示笔尖处于落下状态
   Uart_Printf("/nThe pen is down!/n");
  else
   Uart_Printf("/nThe pen is up!/n"); 
 }
 /*设置x,y坐标为自动转换模式*/
 rADCTSC =(1<<2)|(1<<3);  //设置为自动顺序x和y方向测量
 rADCDLY = 4000;  //加个延时
 /*启动AD转换*/
 rADCCON |=0x01;
 while(rADCCON &0x1);  //检测AD转换是否启动
 /*AD转换结束*/
 while(!(rADCCON &(1<<15))); //检测AD转换是否结束
 /*获取x,y坐标的值*/
 value_x=(rADCDAT0 &0x3ff);
 value_y=(rADCDAT1 &0x3ff);

 /*清除中断,防止反复发生中断*/
 ClearPending(BIT_ADC);
 ClearSubPending(BIT_SUB_TC);   
//*************************************************
//2、触摸笔抬起中断
//**************************************************/
 /*设置触摸屏接口为等待中断模式,等待触摸笔离开屏*/
 rADCTSC = 0xd3;
 rADCTSC =rADCTSC|(1<<8);  //检测笔尖抬起中断信号
 while(1)     //如果一直处于落下状态,那么程序一直处在这个while循环中
 {       
  if(rSUBSRCPND & BIT_SUB_TC)
  {
   count++;
   Uart_Printf("pen up interrupt!/n");
   break;    //如果是抬起,则必须进入中断之后要从中断当中出来,不然没法进行再次按下中断
  }
 }
 
 /*笔尖离开屏幕之后,在超级终端上显示x,y的坐标值*/
 Uart_Printf("count=%03d,XP=%04d,YP=%04d/n",count,value_x,value_y);
 rADCDLY=4000;
//*************************************************
//3、重新设置触摸屏为等待中断,等待下次触摸笔落下
//**************************************************/  
 /*设置触摸屏为等待中断模式,等待下次触摸屏按下*/
 rADCTSC = 0xd3;
 rADCTSC &=~(1<<8);
 ClearSubPending(BIT_SUB_TC);  //必须清除,不然会一直进入中断
 ClearPending(BIT_ADC);
 
 EnableSubIrq(BIT_SUB_TC);   
 EnableIrq(BIT_ADC);       
}

/*************************************************
ADC初始化
**************************************************/
void ADC_init(void)
{
 rADCCON = (0x3<<3)|(0x31<<6)|(0x1<<14); //转换通道选择和转换频率设置  ADC转换频率=PCLK/(转换预分频值+1)
 delay(100);   //主要作用是给一点时间去设置频率
}
/*************************************************
时钟频率设置
**************************************************/
void Set_Clk(void)
{
 int i;
 U8 key;
 U32 mpll_val = 0 ;
 i = 2 ;              //don't use 100M!
                   //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=400M, 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=100M   PCLK=50M
}
/*************************************************
Function name: cal_cpu_bus_clk
Parameter    : void
Description  : 设置PCLK/HCLK/FCLK的频率
Return   : void
Argument     : void
Autor & 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 不要超出32位数!
 FCLK = ((m+8)*(FIN/100)*2)/((p+2)*(1<<s))*100;     //FCLK=400M  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 = HCLK;
 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;
}

原创粉丝点击