资料详情

嵌入式linux操作系统下触摸屏的实现与分析实验报告

头像

Linux

编号:2868

 华南理工大学
XXX课程实验报告

实验题目:嵌入式linux操作系统下触摸屏的实现与分析实验报告
姓名:___________  学号:______
班级: ___________ 组别: ________
合作者: __________________         
指导教师: ______________________

一.硬件平台
    1、处理器:三星S3C2410,200MHZ
2、内存:SDRAM,64M
3、外存:NAND FLASH,64M
4、LCD&触摸屏:SHARP,640×480,TFT
5、串口:RS232,RS485
二.处理器结构
1、处理器核心
    MMU,DCACHE,ICACHE,JTAG
2、系统总线
      SDRAM,FLASH,LCD,中断,USB
3、外部总线
      串口,USB,GPIO
试验一:bootloader (ads、引导)

1、熟悉ADS 1.2开发工具
  创建、编译、下载、调试工程
2、串口通讯
  串口控制器初始化、收/发数据
3、配置主机端的nfs服务器
  配置主机端的nfs服务器,以连接linux核心
4、下载并运行linux核心
  使用自己的串口程序下载并运行linux核心
主要内容:
•编写串口接收数据函数
•编写串口发送数据函数
•打印菜单,等待用户输入
•下载并运行linux核心
•配置主机的nfs服务器,与linux核心连接
  其他部分代码从教师用机中拷贝
  linux核心从教师机中拷贝
主要步骤:
•修改bootloader:菜单、串口收发、命令行;
•使用ads1.2编译bootloader;
•使用uarmjtag下载、调试bootloader;
•使用axd查看变量、内存,单步跟踪;
•配置超级终端,与bootloader通讯;
•使用超级终端下载Linux核心映像;
•启动Linux核心运行,察看结果;(bootloader调试成功后再继续以下步骤)
•主机重起到ubuntu,配置nfs,配置cutecom;
•重新下载Linux核心映像,启动核心运行后,察看是否成功加载nfs上的root文件系统。
需要补充的代码:
接收串口数据并做相应处理
while(1)
{  
    打印菜单并等待用户输入;
    switch(ch) //根据用户输入做相应处理
    {
    case '1':
        imgsize=xmodem_receive((char *)KERNEL_BASE, MAX_KERNEL_SIZE);
        if(imgsize==0) //下载出错;
        else   //下载成功;
        break;
    case '3':
        nand_read((unsigned char *)KERNEL_BASE, 0x00030000, 4*1024*1024);
    case '2':
        BootKernel();  //这里是不会返回的,否则出错;
        break;
    default:
        break; 
    }
}
打印菜单:
Uart_puts("Menu:\n\r");
 Uart_puts("1.Load kernel via Xmodem;\n\r");
 Uart_puts("2.Boot linux; \n\r");
 Uart_puts("3.Load kernel from flash and boot; \n\r");
 Uart_puts("Make your choice.\n\r");

 do{
  ch=Uart_getc();
 }while(ch!='1' && ch!='2' && ch!='3');

串口读写:
void Uart_putc(char c)
 {
  while(!SERIAL_WRITE_READY());
  ((UTXH0) = (c));
 }

 unsigned char Uart_getc( )
 {
  while(!SERIAL_CHAR_READY());
  return URXH0;
 }

设置Linux核心启动命令行
char *linux_cmd="noinitrd init=/init root=/dev/nfs nfsroot=172.16.68.25:/rootfs,tcp ip=172.16.68.24 console=ttySAC0";
nfs服务器设置
编辑/etc/export文件:
/home/arm_os/filesystem/rootfs 目标板ip(rw,sync)
/home/arm_os/filesystem/rootfs 主机ip(rw,sync)

启动nfs服务器:
/etc/init.d/nfs-kernel-server restart

测试nfs服务器:
mount 主机ip:/home/arm_os/filesystem/rootfs /mnt
•试验二:linux kernel (gcc、make)
1、熟悉基本的linux命令
  文件操作、文件编辑
  串口工具、程序开发
2、配置linux核心
  make menuconfig
3、交叉编译linux核心
  make zImage
主要工作
•熟悉基本的linux命令
•配置linux核心
•交叉编译linux核心
•调试自己编译的核心
•挂载nfs上的root(根目录)
•编写一个小程序在目标板上运行
主要步骤:
•用root用户登录ubuntu (合理使用权限);
•解压缩源码包到/home/下;
•察看解压缩后的/home/arm_os目录:Linux核心、编译器、root等;
•配置并测试nfs;
•配置cutecom:115200,XModem,No line end;
•配置核心:make menuconfig;
•编译核心:make;
•下载并运行核心,加载root文件系统;
•重新设置cutecom为LF line end;
•熟悉基本的Linux命令;
•编写一个小程序在目标板上运行,察看结果。


•试验三:linux driver (uart)

1、Linux驱动编程
•基本接口
•常用函数
2、串口驱动
•申请中断处理
•串口数据读、写
主要工作:
•编写串口驱动初始化、释放函数;
•编写串口驱动接收数据函数;
•编写串口驱动发送数据函数;
•编写串口驱动中断处理函数;
•编写串口访问应用程序;
•使用模块方式编译驱动;
•使用模块方式调试驱动;
•实现基本的串口数据收发。
主要步骤:
•填写函数:uart_init、uart_exit、uart_open、uart_ release,实现串口设备初始化、释放、打开、关闭;
•填写函数: irq_rev_uart、uart_write、uart_read,实现串口设备中断处理、读、写;
•用模块方式编译Linux核心,生成uart.ko,启动目标板Linux核心,用insmod、rmmod等命令操作模块;
•用printk打印调试串口驱动,包括中断相应,读写等;
•编写应用程序:uart.c,实现打开串口设备、读写等,把主机端由comcute发过来的串口数据回传给主机;
•将目标板上串口线连到串口1;
•编译应用程序uart.c,实现和主机间的串口通讯。
部分代码:
串口设备初始化函数
int ret;
dev_t devno = MKDEV(uart_major, 0);
if(uart_major){
  ret = register_chrdev_region(devno, 1, "uart");
}else {
 ret = alloc_chrdev_region(&devno, 0, 1, "uart");
 uart_major = MAJOR(devno);
}
if(ret < 0){ printk("Register chrdev region failed!\n"); return ret;  }
cdev_init(&uart_cdev, &uart_fops);
ret = cdev_add(&uart_cdev, devno, 1);
if(ret){ printk("Add c device failed!\n");  return ret;  }
uart = ioremap(S3C2410_PA_UART1, 0x4000);
device_init();
ret = request_irq(IRQ_S3CUART_RX1, irq_rev_uart, IRQF_DISABLED, "uart", NULL);
if(ret){ printk("Request irq failed!\n");     return ret; }
loop_buffer_init(&readb, UART_SIZE); printk("Uart module init.\n");
return 0;
串口设备释放函数
loop_buffer_free(&readb);

free_irq(IRQ_S3CUART_RX1, NULL);

cdev_del(&uart_cdev); 

unregister_chrdev_region(MKDEV(uart_major,0),1);

printk("Uart module exit.\n");
串口设备中断处理函数
char c;

while(!(__raw_readb(uart + S3C2410_UTRSTAT) & 0x1));

c = (char)__raw_readl(uart + S3C2410_URXH);

loop_buffer_add(&readb, c);

return 0; 
串口设备读函数
int i = 0;

if(*ppos >= UART_SIZE)   return -EIO;
if(*ppos + size > UART_SIZE) size = UART_SIZE - *ppos;
do
{
 char c;
 if(!loop_buffer_del(&readb, &c))
 {
  copy_to_user(buf+i, &c, 1);
  i++;
 }
 else
  schedule_timeout(10);
} while(i < size);
return size;
串口设备写函数
int i; char wmem[UART_SIZE];

if(*ppos >= UART_SIZE) return -EIO;

if(*ppos + size > UART_SIZE)
      size = UART_SIZE - *ppos;

copy_from_user(wmem, buf, size);
    
for(i=0; i<size; i++){  
 while(!(__raw_readl(uart + S3C2410_UTRSTAT) & 0x4));
 __raw_writel(*(wmem + i), uart + S3C2410_UTXH); 
}

return size;
串口访问应用程序
#include <stdio.h>
#include <fcntl.h>
int main()

 int uart_fd, i; char c; 
 uart_fd = open("/dev/uart", O_RDWR); 
 if(uart_fd < 0) 
 {printf("Open device error!\n"); return -1;}
 for(i=0; i<50; i++){  
  read(uart_fd, &c, 1); printf("%c", c);
  write(uart_fd, &c, 1); 
  if(c == 'q') break; 
 } 
 close(uart_fd);
 return 0;
}


•试验四:linux driver (touchscreen)
1、触摸屏驱动
•初始化
•坐标值
2、触摸屏、图形系统协调工作
•触摸屏校准
•拨号键盘

 

 

 


LCD初始化
初始化GPIO(通用输入/输出):
 rGPCUP=0xffffffff;
    rGPCCON=0xaaaaaaaa;
 rGPDUP=0xffffffff;
 rGPDCON=0xaaaaaaaa;
 
 该步骤主要配置CPU引脚的输入输出方向和工作模式  
初始化LCD控制寄存器:
        rLCDCON1=0x00000178;      //配置成为16位颜色,TFT(真彩)模式;
  rLCDCON2= 0x2077c241;     //行数为480;
  rLCDCON3=0x017A7F0F;     //行宽为640;
设置 LCD在内存中的起始地址:
  rLCDADDR1=0x1904b000;      //FrameBuffer的首地址;
  rLCDADDR2=0x00096000;    // FrameBuffer的尾地址;  
  rLCDADDR3= 0x00000300;   //虚屏行宽为640;
      rLCDCON1 += 1;                        //使能LCD,开始显示;
Linux framebuffer设备操作
fb_fd = open("/dev/fb0", O_RDWR);

if(fb_fd < 0){ 
 printf("Open fb device error!\n");  
 return -1;
 }

LCD_MEM_BASE = mmap(NULL,
  SCREEN_WIDTH*SCREEN_HEIGHT*2,    PROT_READ|PROT_WRITE,
  MAP_SHARED, fb_fd, 0);

memset(LCD_MEM_BASE, 0,
  SCREEN_WIDTH*SCREEN_HEIGHT*2);
画像素函数
void drawpixel(int x, int y, unsigned short color_mask)
{
 unsigned int bits =
  (SCREEN_WIDTH*y+x)*BITS_PER_PIXEL;
 unsigned short *tmp;

 tmp = (unsigned short *)LCD_MEM_BASE+bits/16;
    //计算像素在内存中的地址;
 *tmp = color_mask;     //给象素填充颜色;
 
 return ;
}
画线函数
void drawline(int x, int y, int length,
   int flag, unsigned short color_mask)
{
 int i;
 
 if (flag==0)//画横线;
  for (i=0;i<length;i++) 
   drawpixel(x+i,y,color_mask);
  
 if (flag==1)//画竖线;
  ??? 
}
画字符函数
void draw_char
 (int x,int y,    //字符在屏幕上的坐标
 unsigned char c,   //字符值
 unsigned short color_mask)  //字符的颜色

主要工作:
•编写触摸屏驱动初始化、释放函数;
•编写触摸屏驱动读取数据函数;
•编写触摸屏驱动中断处理函数;
•使用模块方式调试驱动;
•编写触摸屏读取应用程序;
•编写简单图形系统绘制应用程序,绘制一个数字键盘;
•实现基本的触摸键盘程序。
主要步骤:
•填写函数:ts_init、ts_exit、ts_open、ts_ release,实现触摸屏设备初始化、释放、打开、关闭;
•填写函数:ts_isr、ts_read,实现触摸屏读、中断处理
•用模块方式编译Linux核心,生成ts_ads7843.ko,启动目标板Linux核心,用insmod、rmmod等操作模块;
•用printk打印调试触摸屏驱动,包括中断相应,读等;
•编写应用程序:ts_ads7843.c,实现打开触摸屏设备、读等;
•在ts_ads7843.c 中增加简单图形系统绘制函数,绘制数字键盘,对触摸屏设备数据进行校正,实现触摸键盘的功能。
部分代码:
触摸屏设备初始化函数
int ret;
dev_t devno = MKDEV(ts_major, 0);
if(ts_major){
  ret = register_chrdev_region(devno, 1, “ts_ads7843");
}else {
 ret = alloc_chrdev_region(&devno, 0, 1, " ts_ads7843 ");
 ts_major = MAJOR(devno);
}
if(ret < 0){ printk("Register chrdev region failed!\n"); return ret;  }
cdev_init(&ts_cdev, &ts_fops);
ret = cdev_add(&ts_cdev, devno, 1);
if(ret){ printk("Add c device failed!\n");  return ret;  }
spi0_base = ioremap(S3C2410_PA_SPI,0x20);
device_init();
init_waitqueue_head(&wq);
ret = request_irq(IRQ_EINT5, ts_isr, IRQF_DISABLED, "ts_ads7843", NULL);
if(ret){ printk("Request irq failed!\n");     return ret; }
TS_OPEN_INT(); ts_time = jiffies;
printk("Ts_ads7843 module init.\n");
return 0;
触摸屏设备释放函数
free_irq(IRQ_EINT5, NULL);    

cdev_del(&ts_cdev); 

unregister_chrdev_region(MKDEV(ts_major,0),1);

printk("Ts_ads7843 module exit.\n");
触摸屏设备中断处理函数
if(jiffies < ts_time + HZ/20)  
 return 0;  

if((s3c2410_gpio_getpin(S3C2410_GPF5)
 & ADS7843_PIN_PEN) == 0) 
{  
 udelay(10);   
 get_XY();  
 ts_time = jiffies;   
 wake_up_interruptible(&wq);  
 udelay(2);  

return 0;
触摸屏设备读函数
struct ts_ret ts_ret; 

int size = 0; 
while(count >= sizeof(struct ts_ret)) 
{  
 interruptible_sleep_on(&wq);
  
 ts_ret.x = x;  
 ts_ret.y = y;  
 ts_ret.pressure = PEN_DOWN;  

 copy_to_user(buffer, (char *)&ts_ret, sizeof(struct ts_ret));     count -= sizeof(struct ts_ret);  
 size += sizeof(struct ts_ret);   
}   
return size;
触摸屏访问应用程序
#include <stdio.h>
#include <fcntl.h>
int main()

 int ts_fd, i; char c; struct ts_ret ts_ret;
 ts_fd = open("/dev/ts_ads7843", O_RDWR);
 if(ts_fd < 0) {  
  printf("Open ts device error!\n"); return -1; }
 for(i=0; i<50; i++){  
 if(read(ts_fd, &ts_ret, sizeof(struct ts_ret))) {   
  if(ts_ret.x < Xmin) ts_ret.x = Xmin;   
  if(ts_ret.x > Xmax) ts_ret.x = Xmax;  
  if(ts_ret.y < Ymin) ts_ret.y = Ymin;  
  if(ts_ret.y > Ymax) ts_ret.y = Ymax;   
    x = (ts_ret.x-Xmin) * SCREEN_WIDTH/(Xmax-Xmin);
       y = (ts_ret.y-Ymin) * SCREEN_HEIGHT/(Ymax-Ymin); }}
 close(ts_fd);
 return 0;
}


•试验五:GPRS综合试验 (framebuffer)
•试验六:GPRS综合试验
1、GPRS模块控制试验
•串口控制GPRS模块
•AT命令集
2、综合试验
•电话拨号
•短消息发送

 

 

 

 

 

 

 

 

 

 

 

 

 


串口2初始化
寄存器定义:
#define OSULCON2   (*(volatile unsigned char *)0x50008000)
#define OSUCON2     (*(volatile unsigned char *)0x50008004)
#define OSUFCON2    (*(volatile unsigned char *)0x50008008)
#define OSUMCON2    (*(volatile unsigned char *)0x5000800C)
#define OSUBRDIV2   (*(volatile unsigned short *)0x50008028) 
初始化:
OSULCON0=0x03;  //设置串口数据长度、停止位、奇偶校验
OSUCON0=0x85; //设置串口时钟频率、中断类型等
OSUFCON0=0x01; //设置串口FIFO工作模式
OSUMCON0=0x00; //设置流量控制等
OSUBRDIV0=0x149; //设置串口波特率为9600bps
AT命令集
1 、查询无线模块状态:
       发送:AT<CR>,应答:OK
   2、主叫电话:
•发送ATD+Dial电话号码<CR>;应答:如连接不成功:NO CARRIER
•举例:发送“atd13476048972\r”即主叫该号码;
3、接电话:
•发送:ATA<CR>,连接成功:OK,否则:NO CARRIER
4、挂断电话:
       发送:ATH <CR> ,应答:OK
 5、发短消息:
•发送AT+CMGF=1 <CR>,设置短信为文本模式,应答:OK.
•或发送AT+CMGF=0 <CR>,设置短信为PDU模式, 应答:OK.
•发送AT+CMGS=电话号码<CR>短信内容<CTRL+Z>
•举例:(1)发送“at+cmgf=1\r”,设为文本模式;
(2) 发送“at+cmgs=13476048972\r”.
(3) 发送短信内容:“hello…”内容以ctrl+z结束(发送字符码26,表示结束).
   上述例子表示向134….发送短消息,内容为:hello…
注意:发送AT命令给无线模块时,中间应有一定的时间延时。

主程序:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <linux/fb.h>
#include <linux/kd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <linux/vt.h>
#include <assert.h>
#include "lcd.h"

#define BITS_PER_PIXEL 16

#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480

#define CHAR_WIDTH 16
#define CHAR_HEIGHT 14

#define LINE_WIDTH 
#define LINE_HEIGHT CHAR_HEIGHT*2+4

#define WHITE_COLOR 0xffff
#define BLUE_COLOR 0x7bf
#define GREEN_COLOR 0x7e0
#define RED_COLOR 0xf800

#define OFFSET_X 120
#define OFFSET_Y 80

int Xmin = 318, Xmax = 3381, Ymin = 420, Ymax = 3600;

int start_x[] = {80,81,126,248,366,480};
int start_y[] = {80,81,92,172,252,332,344};

unsigned short *LCD_MEM_BASE;
int fb_fd, ts_fd, uart_fd;

int x,y;

static int cur_x = 0;
static int cur_y = 0;

static struct ts_ret {
  unsigned int pressure;
  unsigned int x;
  unsigned int y;
} ts_ret;

static struct phonenum {
 char buffer[100];
 unsigned int tail;
} phonenum;

static void drawpixel(int x, int y, unsigned short color_mask)
{
 unsigned int bits;
 unsigned short *tmp;
 
 if((x>=SCREEN_WIDTH)||(y>=SCREEN_HEIGHT)) return;

 bits = (SCREEN_WIDTH*y+x)*BITS_PER_PIXEL;
 tmp = LCD_MEM_BASE + bits/16; 

 *tmp = color_mask;

 return;
}

void drawline(int x, int y, int length, int flag, unsigned short color_mask)
{
 int i;
 
 if (flag)
  for (i=0;i<length;i++)
   drawpixel(x+i,y,color_mask);
 else
  for (i=0;i<length;i++)
   drawpixel(x,y+i,color_mask);
}

void draw_char(int x, int y, unsigned char c, unsigned short color_mask)
{
 int i, j, t;
 unsigned short *p = helvB12_bits + (c - 0x20)*14;
 
 for (i=0; i<CHAR_HEIGHT; i++)
 {
  unsigned short tmp = p[i];

  for (j=0; j<CHAR_WIDTH; j++)
  {
   if (tmp & 0x8000)
   {
    for (t=0; t<4; t++)
    {
     drawpixel(x+j*4+t, y+i*4, color_mask); 
     drawpixel(x+j*4+t, y+i*4+1, color_mask); 
     drawpixel(x+j*4+t, y+i*4+2, color_mask); 
     drawpixel(x+j*4+t, y+i*4+3, color_mask); 
    }
   }
   tmp = tmp << 1;
  }
 }
}

void draw_keyboard(void)
{
 int i;
 
 for (i=0;i<5;i++)
 { 
  drawline(start_x[0],start_y[0]+i*OFFSET_Y,SCREEN_HEIGHT,1,WHITE_COLOR);
  drawline(start_x[0],start_y[1]+i*OFFSET_Y,SCREEN_HEIGHT,1,WHITE_COLOR);
 }
 
 for (i=0;i<5;i++)
 { 
  drawline(start_x[0]+i*OFFSET_X,start_y[0],SCREEN_WIDTH/2,0,WHITE_COLOR);
  drawline(start_x[1]+i*OFFSET_X,start_y[0],SCREEN_WIDTH/2,0,WHITE_COLOR);
 }
 
 for (i=0;i<3;i++)
 {
  draw_char(start_x[2]+i*OFFSET_X,start_y[2],'1'+i,BLUE_COLOR);
  draw_char(start_x[2]+i*OFFSET_X,start_y[3],'4'+i,BLUE_COLOR);
  draw_char(start_x[2]+i*OFFSET_X,start_y[4],'7'+i,BLUE_COLOR);
 }
 
 draw_char(start_x[2],start_y[5],'0',BLUE_COLOR);
 draw_char(start_x[3],start_y[6],'*',BLUE_COLOR);
 draw_char(start_x[4],start_y[5],'#',BLUE_COLOR);
 
 draw_char(start_x[5],start_y[2],'%', GREEN_COLOR);
 draw_char(start_x[5],start_y[3],'&',RED_COLOR);
 draw_char(start_x[5],start_y[4],'$',WHITE_COLOR);
 draw_char(start_x[5],start_y[5],'(',RED_COLOR);
}

void draw_stringline(char *s, unsigned short color_mask)
{
 unsigned char *tmp = (unsigned char *)s;
 
 while (*tmp)
 {
  draw_charline(*tmp,color_mask);
  tmp ++; 
 }
}

void draw_charline(unsigned char c, unsigned short color_mask)
{
 int i,k,n,x,y;
 unsigned long offset,*tmpnew;
 unsigned short *p = helvB12_bits+(c-0x20)*14;
 
 offset = SCREEN_WIDTH*(LINE_HEIGHT)*BITS_PER_PIXEL/32;
 n = SCREEN_WIDTH*(SCREEN_HEIGHT-LINE_HEIGHT-6)*BITS_PER_PIXEL/32;
 tmpnew = (unsigned long *)LCD_MEM_BASE; 
 for (i=0;i<n;i++) tmpnew++;
 
 if (c == '\n' || c == '\r')
 {
  cur_x = 0;
  cur_y += LINE_HEIGHT;
  return;
 }
 else
 {
  if (cur_y>=SCREEN_HEIGHT-6)
  {
   for (i=n;i<n+offset;i++)
    *tmpnew++=0x1f001f;
   cur_x =  0;
   cur_y = SCREEN_HEIGHT-LINE_HEIGHT-6;
  }

  x=cur_x;y=cur_y;

  for (i=0;i<CHAR_HEIGHT;i++)
  {
   unsigned short tmp = p[i];

   for (k=0;k<CHAR_WIDTH;k++)
   {
    if (tmp & 0x8000)
    {
     drawpixel(x+k,y+i*2,color_mask); 
     drawpixel(x+k,y+i*2+1,color_mask);
    }
    tmp = tmp << 1;
   }
  }

  cur_x += helvB12_width[c-0x20] + 1;

  return;
 }
}

char getkey(int x, int y)
{
 char key;
 char addr[4][4] = {{'0','7','4','1'},
   {'*','8','5','2'},
   {'#','9','6','3'},
   {'S',' ','H','C'}};
 
 x = (x - 80) / 120;
 y = (y - 80) / 80;

 if(x < 0) x = 0;
 if(x > 3) x = 3;
 if(y < 0) y = 0;
 if(y > 3) y = 3;

 key = addr[x][y];

 draw_charline(key, RED_COLOR);

 return key;

}

char dialing(void)
{
 char key, ctl, cr;
 ctl = 26;
 cr = 13;
   
    key = getkey(x, y);

 printf("key = %c\n", key);

   if(key!='S' & key!='H' & key!='C' & key!=' ')
    phonenum.buffer[phonenum.tail++] = key;

 if(key == 'C')
 {
  write(uart_fd, "atd", strlen("atd"));
  usleep(1000);
  write(uart_fd, phonenum.buffer, phonenum.tail);
  usleep(1000);
  write(uart_fd, ";\r", strlen(";\r"));
 
    phonenum.tail = 0;
 }
 else if(key == 'S')
 {
  write(uart_fd, "at\r", strlen("at\r"));
  usleep(1000);
  write(uart_fd, "at\r", strlen("at\r"));
  usleep(1000);
  write(uart_fd, "at+cmgf=1\r", strlen("at+cmgf=1\r"));
  usleep(1000);
  write(uart_fd, "at+cmgs=", strlen("at+cmgs="));
  usleep(1000);
  write(uart_fd, phonenum.buffer, phonenum.tail);
  usleep(1000);
  write(uart_fd, &cr, 1);
  usleep(1000);
  write(uart_fd, "hello!", strlen("hello!"));
  usleep(1000);
  write(uart_fd, &ctl, 1);

    phonenum.tail = 0;
 }
 else if(key == 'H')
 {
  write(uart_fd,"ath\r", strlen("ath\r"));
  printf("Open fb device error!\n");

    phonenum.tail = 0;
 }
 else if(key == ' ')
 {
  if(phonenum.tail > 0)
   phonenum.tail--;
 }
}

int main()

 
 fb_fd = open("/dev/fb0", O_RDWR);
 if(fb_fd < 0)
 {
  printf("Open fb device error!\n");
  return -1;
 }

 ts_fd = open("/dev/ts_ads7843", O_RDWR);
 if(ts_fd < 0)
 {
  printf("Open ts device error!\n");
  return -1;
 }

 uart_fd = open("/dev/uart", O_RDWR);
 if(uart_fd < 0)
 {
  printf("Open uart device error!\n");
  return -1;
 }
 
 LCD_MEM_BASE = mmap(NULL, SCREEN_WIDTH*SCREEN_HEIGHT*2,
   PROT_READ|PROT_WRITE, MAP_SHARED, fb_fd, 0);
 memset(LCD_MEM_BASE, 0, SCREEN_WIDTH*SCREEN_HEIGHT*2);

 phonenum.tail = 0;
  
 draw_keyboard();

 for(;;)
 {
  if(read(ts_fd, &ts_ret, sizeof(struct ts_ret)))
  {
   if(ts_ret.x < Xmin)
    ts_ret.x = Xmin;
   if(ts_ret.x > Xmax)
    ts_ret.x = Xmax;
   if(ts_ret.y < Ymin)
    ts_ret.y = Ymin;
   if(ts_ret.y > Ymax)
    ts_ret.y = Ymax;
   
   x = (ts_ret.x-Xmin) * SCREEN_WIDTH/(Xmax-Xmin);
   y = (ts_ret.y-Ymin) * SCREEN_HEIGHT/(Ymax-Ymin);

   dialing();

  }
  
 }

 close(fb_fd);
 close(ts_fd);
 close(uart_fd);

 return 0;
}
实验体会
通过这次实验,我对嵌入式有了实质性的认识,也有了一定的实践经验。实验的课时是很多的,通过这六次实验,我感受到使用linux嵌入式系统的乐趣,对此有了一定的理解。
美中不足的是,每次实验都是按老师说的一步一步做,没有对实验原理深刻的理解,没有时间思考实验原理,每次都是按部就班的做。如果说什么建议,我希望以后这课实验的时候之前多一点时间给我们准备思考,深刻想一想实验之中的道理和问题。
通过这实验,我相信大家都会多多少少有些收获,更深刻的了解了嵌入式,了解它的实验平台,最后出成果时,看到这么一台机子就能简单模拟手机来发送短信和打电话,还是触摸屏的心里还是异常欣喜的。