第一次嵌入式裸机应用设计——秒表器

来源:互联网 发布:坎比数据 编辑:程序博客网 时间:2024/06/04 17:59

运用到lcd,timer,touch触摸屏,uar函数t等

第一次做的一个裸机设计花了一天半左右的时间,顺便重新温习了前面裸机程序的知识。从lcd,timer计时器,touch触摸屏,uart中断这四个方面着手,以下是第一次实现功能的程序,还需要后期的一些优化,如触摸屏校准,led亮灯,按键图片的切换等等。微笑微笑



main主函数,打印图片和字

#include"lcd.h"#include"timer.h"#include "def.h"#include"uart.h"#include"touch.h"int Main(){int a=0,b=0,c=0,d=0,f=0,g=0,h=0;//Lcd_ClearScr(0xffffff);Uart0_Init(115200) ;touch_init();   lcd_Init();    Timer0_Init();   paint_pic(gImage_test);   Draw_Text16(300,100,0xff00ff,test0);   Draw_Text16(280,100,0xff00ff,test0);   Draw_Text16(260,100,0xff00ff,test0);   Draw_Text16(240,100,0xff00ff,test0);   Draw_Text16(220,100,0xff00ff,test0);   Draw_Text16(200,100,0xff00ff,test0);while(1){//paint_line(10,100,10,250, 0xffff00);//paint_line(50,100,50,250, 0xff00ff);//paint_line(100,100,100,250, 0x00ffff);Draw_Text16(234,100,0xff00ff,testn);Draw_Text16(274,100,0xff00ff,testn);Draw_Text16(5,10,0xff00ff,han1);//Lcd_ClearScr1(15,50,16,16,0xfff00);Draw_Text16(30,10,0xff00ff,han2);} return 0;}




lcd.h

/*********************************************
  NAME: class_lcd.h
  DESC:
 *********************************************/


#ifndef __class_lcd_h__
#define __class_lcd_h__

extern void lcd_Init(void);
extern void paint_pic(const unsigned char pic[]);
extern void paint_pixel(unsigned int x,unsigned int y, unsigned short colour );
extern void paint_line(int x1,int y1,int x2,int y2,int colour);
extern void Draw_Text16(int x,int y,int colour,unsigned char ch[]);//显示16*16汉字


extern const unsigned char gImage_test[];//图片数组


static  unsigned char han1[]={ 0x20, 0x4, 0x18, 0x4, 0x9,
0x24, 0xFF, 0xA4, 0x2, 0x24, 0x42, 0x24, 0x22, 0x24, 0x14, 0x24,
 0x14, 0x24, 0x8, 0x24, 0x8, 0x24, 0x14, 0x24, 0x22,
 0x4, 0x43, 0x4, 0x81, 0x14, 0x0, 0x8,

  };//刘
static  unsigned char han2[]={0x10, 0x4, 0x13, 0xFE, 0x12, 0x4,
0x12, 0x4, 0x57, 0xFC, 0x5A, 0x4, 0x52, 0x4, 0x93, 0xFC, 0x10, 0x40,
 0x10, 0x20, 0x13, 0xFC, 0x29, 0x8, 0x24, 0x88,
 0x40, 0x90, 0x47, 0xFE, 0x80, 0x0,
};//煜

static  unsigned char test0[]={0x0 ,0x0, 0x0, 0x0 ,0x0, 0x0, 0x7, 0xF0, 0x1C ,0x38, 0x38 ,
   0x1C, 0x38, 0x1C, 0x78, 0x1E ,0x78, 0x1E, 0x38, 0x1C, 0x38 ,0x1C ,0x38, 0x1C, 0x1C ,
   0x38, 0x7, 0xE0 ,0x0 ,0x0 ,0x0,0x0,};//0
 static  unsigned char test1[]={0x0, 0x0 ,0x0, 0x0 ,0x0 ,0x0,0x1, 0xC0, 0xF ,0xC0, 0x1,
 0xC0 ,0x1, 0xC0, 0x1, 0xC0, 0x1, 0xC0, 0x1, 0xC0, 0x1, 0xC0 ,0x1 ,0xC0, 0x1 ,0xC0,
  0x1F, 0xF8, 0x0, 0x0, 0x0, 0x0,};//1
static  unsigned char test2[]={0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xF ,0xF0 ,0x18,0x18, 0x38,
 0x1C ,0x38, 0x1C, 0x0, 0x38, 0x0, 0x70, 0x1, 0xC0 ,0x7, 0x0 ,0xC, 0x4, 0x3F ,0xFC, 0x3F,
  0xFC, 0x0, 0x0, 0x0, 0x0,};//2
static  unsigned char test3[]={0x0 ,0x0 ,0x0 ,0x0, 0x0 ,0x0 ,0xF ,0xF0, 0x38, 0x38, 0x38,
 0x18, 0x0 ,0x38, 0x3 ,0xF0 ,0x3 ,0xF0, 0x0 ,0x18, 0x0, 0x1C, 0x38, 0x1C, 0x38, 0x18,
  0x1F, 0xF0, 0x0 ,0x0, 0x0 ,0x0,};//3
  static  unsigned char test4[]={0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ,0x0, 0x30, 0x0, 0xF0 ,0x1 ,0xF0, 0x2, 0x70, 0xC ,0x70,0x18, 0x70 ,0x30 ,0x70, 0x3F, 0xFE ,0x0, 0x70, 0x0, 0x70, 0x3, 0xFE ,0x0, 0x0, 0x0, 0x0,};//4
  static  unsigned char test5[]={0x0 ,0x0, 0x0, 0x0, 0x0 ,0x0, 0x1F ,0xFC, 0x18, 0x0 ,0x18 ,0x0, 0x18, 0xC0, 0x1F, 0xF8, 0x18, 0x1C ,0x0, 0x1C, 0x10, 0x1C ,0x38, 0x1C, 0x38, 0x18 ,0xF, 0xF0, 0x0 ,0x0 ,0x0 ,0x0,};//5
  static  unsigned char test6[]={0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7 ,0xF8, 0xC, 0x38, 0x18, 0x10, 0x38, 0x0, 0x3F, 0xF8, 0x7C ,0x1C, 0x78, 0xC ,0x38 ,0xE , 0x38 , 0xC , 0x1C , 0x18 , 0xF  ,0xF0  ,0x0  ,0x0  ,0x0 ,0x0,};//6
  static  unsigned char test7[]={0x0, 0x0 ,0x0, 0x0 ,0x0 ,0x0, 0x1F, 0xFE ,0x38 ,0xC ,0x30, 0x10, 0x0 ,0x30 ,0x0, 0x60, 0x0, 0xC0 ,0x1, 0x80, 0x3, 0x80, 0x3, 0x80, 0x3, 0x80 ,0x3 ,0x80 ,0x0, 0x0, 0x0, 0x0,};//7
  static  unsigned char test8[]={0x0 ,0x0, 0x0 ,0x0, 0x0 ,0x0, 0xF ,0xF0 ,0x38, 0x1C, 0x30, 0xC ,0x3C, 0x1C,0x1F, 0xF0, 0xF ,0xF0 ,0x38 ,0x78 ,0x70, 0x1C, 0x70, 0xC, 0x38 ,0x18, 0xF ,0xF0 ,0x0, 0x0, 0x0, 0x0};//8
  static  unsigned char test9[]={0x0, 0x0, 0x0, 0x0 ,0x0, 0x0, 0xF, 0xF0, 0x38 ,0x18, 0x30, 0x1C, 0x70 ,0x1C, 0x70, 0x1C, 0x38 ,0x3C, 0x1F, 0xDC, 0x0, 0x1C, 0x18, 0x38, 0x3C, 0x70, 0x1F, 0xE0 ,0x0, 0x0 ,0x0 ,0x0};//9
static  unsigned char testq[]={0xff ,0xff ,0xff ,0xff, 0xff ,0xff ,0xff ,0xff,0xff ,0xff ,0xff ,0xff, 0xff ,0xff ,0xff ,0xff,
 0xff ,0xff ,0xff ,0xff,0xff ,0xff ,0xff ,0xff,0xff ,0xff ,0xff ,0xff,0xff ,0xff ,0xff ,0xff,0xff ,0xff ,0xff ,0xff,};//清屏
static unsigned char testn[]={0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0};
#endif  //__class_led_h__



lcd程序中实现汉字数字还有图片的显示,这里使用的图片要求较为苛刻,图片全屏时似乎会覆盖字,这个问题还有待解决

#include "2440addr.h"
#include"lcd.h"
#include "def.h"

static void lcd_power_control(int enable);

volatile unsigned short LCDBANK[272][480]; //申请帧内存 LCDBANK是系统随机分配的
//注意这里的数据类型一定是16位的也就是unsigned short 因此该数组是按照16bpp算的,正好数组里面每个单元存储一个像素
//假如这是使用的unsigend int 类型那么rLCDSADDR2 的时候就跟unsigned short 不同,有可能出现奇怪的现象,比如满屏幕只显示
// 480/2  272/2   
//unsigned char  占据8位 一个字节
//unsigned short   占据16位 两个字节
//unsigned int      占据32位 两个字节


void lcd_Init(void)
{
    #define VBPD         (1)            //垂直同步信号的后肩
    #define VFPD         (1)            //垂直同步信号的前肩
    #define VSPW         (9)            //垂直同步信号的脉宽

    #define HBPD         (1)            //水平同步信号的后肩
    #define HFPD         (1)            //水平同步信号的前肩
    #define HSPW         (40)            //水平同步信号的脉宽
    
    
    
    
       rGPCUP   = 0xffffffff;   // 禁止内部上拉
       rGPCCON  = 0xaaaaaaaa;   // GPIO管脚用于VD[7:0],LCDVF[2:0],VM,VFRAME,VLINE,VCLK,LEND
       rGPDUP   = 0xffffffff;   // 禁止内部上拉
       rGPDCON  = 0xaaaaaaaa;   // GPIO管脚用于VD[23:8]
       rGPBCON &= ~(3<<0);  // lcd背光灯控制引脚
          rGPBCON |= (1<<0);
          rGPBDAT &= ~(1<<0);     //关闭背光灯

 // 设置像素时钟频率,屏幕模型,bpp模式
    rLCDCON1 = (5<< 8)|(3 <<5 )|(12 << 1)  ;
 //设置垂直方向各信号的时间参数
    rLCDCON2 = (VBPD << 24)|(271 << 14)|(VFPD << 6)|(VSPW);
 //设置水平方向各信号的时间参数
    rLCDCON3 = (HBPD << 19)|(479 << 8)|(HFPD);
 //HSPW值,表示脉冲宽度为(HSPW)个VCLK周期
    rLCDCON4 = (HSPW);
 //信号极性 数据存储格式等的设置  
    rLCDCON5 = (1 << 11) |(1 << 10)| (1 << 9) | (1 << 8)    | (1) ;
    //选择565格式  上升沿取视频数据  VLINE/HSYNC VFIAME/VSYNC 反转 存储格式P1 P2
    
    rLCDSADDR1 = (((unsigned int)LCDBANK >> 22) << 21) | ((((unsigned int)LCDBANK)>> 1)& 0x1fffff );
    //((unsigned int)LCDBANK >> 22) << 21)  将内存地址的22到30位存到寄存器的21到29位中
    //((((unsigned int)LCDBANK)>> 1)& 0x1fffff )内存首地址(32位的数值)的第21~1位放到寄存器的20~0
    //&0x1fffff的作用是取出低21位 这样不会影响到存入寄存器的高22-32位。
     rLCDSADDR2 = ( ((unsigned int)LCDBANK + ( (480 * 272 *2) ) >> 1 ))  & 0x1fffff;
     //((the frame end address) >>1 ) + 1  之所以有(480 * 272 *2)的乘以2是因为16BPP
     //假如8BPP乘以1表示在8BPP中一个像素使用一个字节来表示
     ///先左移1位后取低21位
    
     rLCDSADDR3 = (0 << 11) | (480 / 1);
     //offsize为0 16bpp正好一个像素占用一个半字
   

     ///禁止临时调色板寄存器
        rTPAL = 0;
     //    rTCONSEL &=~((1<<4) | 1);
        rLCDINTMSK |= (3);                                                    // MASK LCD Sub Interrupt
       
    

    
     rLCDCON1 |= 1;//使能LCD数据信号的传输
         
    lcd_power_control(1);
}


/*********************************
lcd电源使能函数
为1表示使能电源信号
为0表示禁止电源

***************************************/
static void lcd_power_control(int enable)
{
    rGPGCON = (rGPGCON & (~(3<<8))) | (3<<8);   // GPG4用作LCD_PWREN
    rGPGUP  = (rGPGUP & (~(1<<4))) | (1<<4);    // 禁止内部上拉
    rGPGDAT = rGPGDAT | (1<<4) ; //输出高电平
    rLCDCON5 = rLCDCON5 & (~(1<<3)) | (enable<<3); //LCD_PWREN信号输出使能
   
    rGPBDAT |= (enable<<0);     //打开背光灯


}


/**************************************************************
lcd颜色函数
参数1 x的坐标值
参数2 y的坐标值
参数3 该点的颜色值
功能说明:LCD控制器从内存中获得某个像素的16位颜色值后,直接通过VD[23:0]数据线
          发生给LCD,也就是让LCD屏幕显示所设置的colour值。
**************************************************************/
void paint_pixel(unsigned int x,unsigned int y, unsigned short colour )
{

    if ( (x < 480) && (y < 272) )
        LCDBANK[(y)][(x)] = colour;



}

/**************************************************************
LCD显示图片
输入要显示图片
**************************************************************/

void paint_pic(const unsigned char pic[])
{
    
    int x,y;
    unsigned int colour;
    int p = 0;
    
    for( y =0 ; y < 240 ; y++ )
    {
        for( x = 0 ; x < 480 ; x++ )
        {
            colour = pic[p] | (pic[p+1]<<8) ;//获取图片的像素值(一个点16数据表示)
        
            //colour = pic[p] ;
            if ( ( x < 480) && ( y < 240) )
                LCDBANK[y][x] = colour ;    //获取得到的图片像素值格式也是565
                                            //所以可以直接赋值给LCD显示
            p = p + 2 ;  //图片一个像素点是按照8位而本程序配置的是16位
        }
    }   
    
}


void Lcd_ClearScr1(int x0,int y0,int h,int l,U32 c)
{
    unsigned int x,y;
    for( y = y0 ; y <y0+l; y++ )
    {    
        for( x = x0 ; x <x0+h ; x++ )
        {
        LCDBANK[y][x] = c ;
        }
    }
}


/**************************************************************
TFT LCD全屏填充特定颜色单元或清屏
**************************************************************/
void Lcd_ClearScr(unsigned int colour)
{
    unsigned int x,y ;
        
    for( y = 0 ; y < 272 ; y++ )
    {
        for( x = 0 ; x < 480; x++ )
        {
            LCDBANK[y][x] = colour ;
        }
    }
}

/**************************************************************
LCD显示16*16的汉字
参数1 x轴的坐标
参数2 y轴的坐标
参数3 线条的颜色
参数4 汉字的数组
**************************************************************/


void Draw_Text16(int x,int y,int colour,unsigned char ch[])//显示16*16汉字
{
       unsigned short int i,j;
       unsigned char mask,buffer;
 
       for(i=0;i<16;i++)
       {
              mask=0x80;                  //掩码,用作取出每一位
              buffer=ch[i*2];             //提取一行的第一个字节
              for(j=0;j<8;j++)
              {                  
                     if(buffer&mask)//这一位为1则显示 注意:上色就是显示了-不给上色也就显示不了
                     {
                            paint_pixel(x+j,y+i,colour);        //为笔画上色
                     }
                     mask=mask>>1; //用以取出下一位                 
              }
              mask=0x80;                  //掩码   
              buffer=ch[i*2+1];         //提取一行的第二个字节
              for(j=0;j<8;j++)
              {                  
                     if(buffer&mask)
                     {
                            paint_pixel(x+j+8,y+i,colour);           //为笔画上色
                     }
                     mask=mask>>1;                  
              }
       }
}


/**************************************************************
LCD画线
参数1 x轴的起点坐标
参数2 y轴的起点坐标
参数3 x轴的终点坐标
参数4 y轴的终点坐标
参数5 线条的颜色
**************************************************************/

void paint_line(int x1,int y1,int x2,int y2,int colour)
{
    int dx,dy,e;
    dx=x2-x1;
    dy=y2-y1;
    
    if(dx>=0)
    {
        if(dy >= 0) // dy>=0
        {
            if(dx>=dy) // 1/8 octant
            {
                e=dy-dx/2;
                while(x1<=x2)
                {
                    paint_pixel(x1,y1,colour);
                    if(e>0){y1+=1;e-=dx;}   
                    x1+=1;
                    e+=dy;
                }
            }
            else        // 2/8 octant
            {
                e=dx-dy/2;
                while(y1<=y2)
                {
                    paint_pixel(x1,y1,colour);
                    if(e>0){x1+=1;e-=dy;}   
                    y1+=1;
                    e+=dx;
                }
            }
        }
        else           // dy<0
        {
            dy=-dy;   // dy=abs(dy)

            if(dx>=dy) // 8/8 octant
            {
                e=dy-dx/2;
                while(x1<=x2)
                {
                    paint_pixel(x1,y1,colour);
                    if(e>0){y1-=1;e-=dx;}   
                    x1+=1;
                    e+=dy;
                }
            }
            else        // 7/8 octant
            {
                e=dx-dy/2;
                while(y1>=y2)
                {
                    paint_pixel(x1,y1,colour);
                    if(e>0){x1+=1;e-=dy;}   
                    y1-=1;
                    e+=dx;
                }
            }
        }   
    }
    else //dx<0
    {
        dx=-dx;     //dx=abs(dx)
        if(dy >= 0) // dy>=0
        {
            if(dx>=dy) // 4/8 octant
            {
                e=dy-dx/2;
                while(x1>=x2)
                {
                    paint_pixel(x1,y1,colour);
                    if(e>0){y1+=1;e-=dx;}   
                    x1-=1;
                    e+=dy;
                }
            }
            else        // 3/8 octant
            {
                e=dx-dy/2;
                while(y1<=y2)
                {
                    paint_pixel(x1,y1,colour);
                    if(e>0){x1-=1;e-=dy;}   
                    y1+=1;
                    e+=dx;
                }
            }
        }
        else           // dy<0
        {
            dy=-dy;   // dy=abs(dy)

            if(dx>=dy) // 5/8 octant
            {
                e=dy-dx/2;
                while(x1>=x2)
                {
                    paint_pixel(x1,y1,colour);
                    if(e>0){y1-=1;e-=dx;}   
                    x1-=1;
                    e+=dy;
                }
            }
            else        // 6/8 octant
            {
                e=dx-dy/2;
                while(y1>=y2)
                {
                    paint_pixel(x1,y1,colour);
                    if(e>0){x1-=1;e-=dy;}   
                    y1-=1;
                    e+=dx;
                }
            }
        }   
    }

}



timer计数器函数

#include "timer.h"
#include "config.h"
#include"lcd.h"



void timer0_service_Init(void);

void Timer0_Init(void)
{
//第一步:选定timer0-5定时器,设置预分频器 TCFG0和TCFG1
//        定时器的时钟频率 = PCLK / {prescaler value+1 } / {divider value}
//(2440init.s设置好了PCLK=50m)

    rTCFG0 &= ~(0xFF) ;
    rTCFG0 |= 99 ;    //预分频系数为99
    rTCFG1 &= ~(0xf) ;
    rTCFG1 |= 0x02 ;   //8分频
//定时器的时钟频率=50000000/100/8=62500
//第二步:给定时器设定定时时间,也就是给TCNTB0装入初值
//        和 装入TCMPBn寄存器比较器(默认0)
    rTCNTB0 = 62500 ;//1s中断一次
//第三步:设置定时时间载入方式及其打开定时器 使用寄存器TCON
    rTCON |=  (1 << 1)  ;//将TCNTB0和TCMPB0装入内部的TCNT0和TCMP0
    rTCON &=~(0xf);
    rTCON |= 0x09 ;  //自动重载并且打开定时器0
    rINTMSK &=~(1<<10);//打开定时器0 中断
    timer0_service_Init();//中断服务函数初始化


}


void __irq timer0_service(void)
{
    
  static int flag=0;
 if(flag>4)
 {flag=0;}
  switch(flag)
        {
            case 0:
                Lcd_ClearScr(0x000000);
                // paint_pic(gImage_test);
                break ;    
            case 1:
                Lcd_ClearScr(0x00ff00);
                // paint_pic(gImage_test1);
                break ;
            case 2:
                Lcd_ClearScr(0xff0000);
                // paint_pic(gImage_test);
                break ;
            case 3:
                Lcd_ClearScr(0xffffff);
                // paint_pic(gImage_test1);
            case 4:
                //Lcd_ClearScr(0x00<<11|0x00<<5|0x00 );
                 paint_pic(gImage_test);
                break ;    
            default:
               break ;    
        }
    flag++;
 
  rSRCPND |= (0x1<<10);
  rINTPND |= (0x1<<10);
 
}


void timer0_service_Init(void)
{
    pISR_TIMER0 = (unsigned int)timer0_service ;

}


uart中断函数
#include "config.h"
#include "uart.h"


#define TXD0READY (1 << 2)
#define RXD0READY (1 << 0)
#define PCLK 50000000//时钟源设为PCLK
               

void Uart0_Init(unsigned int bandrate)
{
    //1.设置相关的引脚为UART功能的引脚
    rGPHCON &= ~((3 << 4) | (3 << 6)) ;//GPH2-GPH3是RX/TX
    rGPHCON |= ((2 << 4) | (2 << 6)) ;//GPH2--TXD[0];GPH3--RXD[0]
    rGPHUP = 0x00 ;                   //使能上拉
    //2.设置UART的数据帧格式 可通过ULCONn来设置
    rULCON0 |= 0x03 ;  // 无校验 8位数据,1位停止位
    //3.UART时钟为PCLK,查询方式  可通过UCONn来设置             
    rUCON0 = 0x05 ; //0101
     //    设置UART的波特率  UBRDIVn        
    rUBRDIV0  = PCLK / bandrate / 16 - 1 ;
    rURXH0 = 0;
}

void putc(unsigned char c)
{
     /* 向UTXH0寄存器中写入数据,UART即自动将它发送出去 */
    rUTXH0 = c ;
    while(!(rUTRSTAT0 & TXD0READY)) ;//等待上个字符发送完毕
}
unsigned char getc(void)
{
    unsigned char c ;
    /* 等待,直到接收缓冲区中的有数据 */
    while(!(rUTRSTAT0 & RXD0READY)) ;
     /* 直接读取URXH0寄存器,即可获得接收到的数据 */
    c = rURXH0 ;
    return c ;
    
}

#include "2440addr.h"
#include "config.h"
#include "uart.h"
#include "touch.h"
#include"timer.h"
#include"lcd.h"
extern int a,b,c,d,e,f,g,h;
int xdata=0;
int ydata=0;
void __irq touch_isr()
{   
    

//1、    进入中断服务函数 判断是触笔按下引起的中断还是触笔抬起引起的中断
    /*检测子中断源,判断是否是触摸屏(INT_TC)中断,且触摸笔按下*/
    //正常情况下这里是因为触笔按下触发的中断
    if(rSUBSRCPND &(1<<9))   //检查是否完成了中断位ADC
    {
        if( !(rADCDAT0&0x8000))  //当触笔落下时,rADCDAT0【15?=0;
           {
    
               putc(' ');
           }
        else                         //当触笔抬起时,rADCDAT0【15?=1;        
           {
              
               putc(' ');
              
           }
    }
    
   // 2、    设置XP的上拉电阻无效,切换到自动(顺序)得到X、Y坐标中断接口模式
    rADCTSC |= (1<<3)|(1<<2); //XP上拉无效,自动(顺序)得到X、Y坐标

   //3、    在自动测量XY坐标模式下,重新设置延时间隔ADCDLY,注意初始频率为PCLK
     rADCDLY=40000;     //正常转换模式延时 (1/50M)*40000=0.8ms
   //4、    设置寄存器ADCCON[0](此时保证ADCCON[0]=0) 使之开始转换ADC。
     rADCCON |= 0x1;          //   设置AD开始转换  当硬件启动ADC转换时,该位被清0
    
    //5、    通过判断ADCCON【0】 ADCCON【15】 SRCPND【31】 是否已经转化结束。
    while(rADCCON & 0x1);   //检查AD转换是否已经开始        
    while(!(rADCCON & (1<<15)));  //等待AD转换结束

    while(!(rSRCPND &(1<<31)));  //检查AD中断标志位是否产生中断请求
 
//6、    读取ADCDAT0 和ADCDAT1的低10位获取坐标值
    xdata=(rADCDAT0&0x3ff);//取出低10位//11 1111 1111 xxxx xxxx
 /*获取X,Y坐标*/
    ydata=(rADCDAT1&0x3ff);//取出低10位5、    通过判断ADCCON【0】 ADCCON【15】 SRCPND【31】 是否已经转化结束。
    
    
     if(xdata<250&& xdata>200&&ydata<870&&ydata>740)rINTMSK&=~(1<<10);//开始
    else if(xdata<350&& xdata>280&&ydata<870&&ydata>740)rINTMSK|=(1<<10);//暂停
    else if(xdata<495&& xdata>415&&ydata<870&&ydata>740){     rINTMSK&=~(1<<10);
                                                            a=0,b=0,c=0,d=0,e=0,f=0;
                                                            rINTMSK|=(1<<10);
                                                            Draw_Text16(300,100,0x000000,testq);
                                                               Draw_Text16(280,100,0x000000,testq);
                                                               Draw_Text16(260,100,0x000000,testq);
                                                              Draw_Text16(240,100,0x000000,testq);
                                                              Draw_Text16(220,100,0x000000,testq);
                                                              Draw_Text16(200,100,0x000000,testq);        
                                                            Draw_Text16(300,100,0xff00ff,test0);
                                                               Draw_Text16(280,100,0xff00ff,test0);
                                                               Draw_Text16(260,100,0xff00ff,test0);
                                                              Draw_Text16(240,100,0xff00ff,test0);
                                                              Draw_Text16(220,100,0xff00ff,test0);
                                                              Draw_Text16(200,100,0xff00ff,test0);                                                            
                                                        }//重置
    
    
    
    //7、    清除中断挂起标志位 涉及到的寄存器有SUBSRCPND SRCPND  INTPND
    rSUBSRCPND |=(1<<9);   //清中断
    rSRCPND    |=(1<<31);
    rINTPND    |=(1<<31);  

//串口发送读取的数据
   putc('x'); putc(':');
   putc(xdata/1000%10+48);//千位 例如0200如果千位为0 则ASCII值为48则才能显示出0,所以要加上48
   putc(xdata/100%10+48);//百位,
   putc(xdata/10%10+48); //十位
   putc(xdata%10+48);  //个位
 
   putc('y'); putc(':');
   putc(ydata/1000%10+48);
   putc(ydata/100%10+48);
   putc(ydata/10%10+48);
   putc(ydata%10+48);
   
//8、    转换模式为等待中断模式(ADCTSC=0xd3),并设置设置触笔抬起触发中断ADCTSC[8]=1

/*设置触摸屏为等待中断模式,等待触摸笔抬起*/
    rADCTSC =0xd3;     //设置为等待中断模式  Wfait,XP_PU,XP_Dis,XM_Dis,YP_Dis,YM_En
    rADCTSC=rADCTSC|(1<<8); //设置触笔抬起触发中断
//检查光标提起中断信号
//9、    检测是否触笔是否抬起,并等待触笔抬起(rSUBSRCPND【9】=?1)
while(1)  //检查抬笔状态
{
  if(rSUBSRCPND & (1<<9))
   //抬笔时再次触发中断
  {
    
     putc(' ');
     putc(0x0d);//发送换行符
     putc(0x0a);
      break;  
  }
}
 
  // 10、    重新设置延时间隔ADCDLY,在等待中断模式,注意初始频率为3.6864M
   
  rADCDLY=36864;  //等待中断模式延迟 (1/3.6864M)*36864=0.01s=10ms
 
//  11、    设置触摸屏为等待中断模式,并设置下次触摸笔按下产生中断

   rADCTSC =0xd3;   //设置触摸屏为等待中断模式,等待下次触摸笔按下
   
  // 12、    为了确保可以再次清除中断挂起标志位 涉及到的寄存器有SUBSRCPND SRCPND  INTPND
    
   rSUBSRCPND  |=(1<<9);   //清中断
    rSRCPND    |=(1<<31);
    rINTPND    |=(1<<31);


}

void touch_init()   /*触摸屏初始化*/
{   
   
  // AD转换频率=PCLK/(分频值+1),且AD的最高频率为2.5M,这里PCLK=50M,所以AD的转换频率为2M
   unsigned int preScaler = 24;
   
   //1、设置等待模式下的延时时间(此时频率为3.6864M) 给ADCDLY寄存器赋值
    rADCDLY=36864;        //等待中断模式延迟 (1/3.6864M)*36864=0.01s=10ms
    
   //2、设置ADC转换的时钟频率 通过寄存器ADCCON来赋值
    rADCCON = (1<<14)|(preScaler<<6); //设置分频系数,并且设定分频有效
                                      //设置A/D转换的时钟 = PCLK/(24+1)=2Mhz,小于2.5M。
   // 3、    设置中断接口模式为等待中断模式 ADCCON= 0xd3
    rADCTSC=0xd3;   //设置触摸屏为等待中断模式,等待触摸笔被按下(触笔按下触发中断)
   
   // 4、    清除中断挂起标志位 涉及到的寄存器有SUBSRCPND SRCPND  INTPND
    rSUBSRCPND |= (1<<9); //清除子中断INT_TC标志位
    rSRCPND    |= (1<<31);   //清除adc中断INT_ADC标志位
    rINTPND    |= (1<<31);   //清除adc中断INT_ADC标志位
        
   // 5、    使能ADC及其触摸屏有关的中断 涉及到底寄存器有INTSUBMSK  INTMSK
    rINTSUBMSK &= ~(1<<9); //使能INT_TC中断
    rINTMSK    &= ~(1<<31);//使能INT_ADC中断


    pISR_ADC = (unsigned int )touch_isr;  //将中断执行函数如入地址赋给INT_TC中断
}

0 0