2

嵌入式:人机交互接口设计详解

 1 year ago
source link: https://blog.51cto.com/u_15736437/5996602
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

键盘和LED的接口原理

HA7279A是一片具有串行接口并可同时驱动8位共阴式数码管或64只独立LED的智能显示驱动芯片。该芯片同时可连接多达64键的键盘矩阵,一片即可完成LED显示及键盘接口的全部功能。

HA7279A一共有28个引脚:

  • RESET:复位端。通常,该端接+5V电源;
  • DIG0~DIG7:8个LED管的位驱动输出端;
  • SA~SG:LED数码管的A段~G段的输出端;
  • DP:小数点的驱动输出端;
  • RC:外接振荡元件连接端。
  • HD7279A与微处理器仅需4条接口线:
  • CS:片选信号(低电平有效);
  • DATA:串行数据端。
  • CLK:数据串行传送的同步时钟输入端,时钟的上升沿表示数据有效。
  • KEY:按键信号输出端。该端在无键按下时为高电平;而在有键按下时变为低电平,并一直保持到按键释放为止。
嵌入式:人机交互接口设计详解_寄存器

HD7279A与S3C2410A的连接原理图

嵌入式:人机交互接口设计详解_数据_02

键盘和LED控制的编程实例

举例:通过按键来控制LED的显示。

1.键盘中断的初始化

void KeyINT_Init(void){
rGPFCON=(rGPFCON&0xF3FF)|(2<<10);
rGPECON=(rGPECON&0xF3FFFFFF)|(0x01<<26); //设置GPE13为输出位,模拟时钟输出
rEXTINT0 &= 0xff8fffff; //外部中断5低电平有效
if (rEINTPEND & 0x20) //清除外部中断5的中断挂起位
rEINTPEND |= 0x20;
if ((rINTPND & BIT_EINT4_7)){
rSRCPND |= BIT_EINT4_7;
rINTPND |= BIT_EINT4_7;
}
rINTMSK &= ~(BIT_EINT4_7); //使用外部中断4~7
rEINTMASK &= 0xffffdf; //外部中断5使能
pISR_EINT4_7 = (int)Key_ISR;
}

2.书写中断服务子程序

void __irq Key_ISR( void ){
int j;
rINTMSK |= BIT_ALLMSK; // 关中断
if (rEINTPEND & 0x20){
key_number = read7279(cmd_read);//读键盘指令程序
rINTMSK &= ~(BIT_EINT4_7);
switch(key_number){
case 0x04 : key_number = 0x08; break;
case 0x05 : key_number = 0x09; break;
case 0x06 : key_number = 0x0A; break;
case 0x07 : key_number = 0x0B; break;
case 0x08 : key_number = 0x04; break;
case 0x09 : key_number = 0x05; break;
case 0x0A : key_number = 0x06; break;
case 0x0b : key_number = 0x07; break;
default: break;
}
Uart_Printf("key is %x \n", key_number);
}
rEINTPEND |= 0x20;
rSRCPND |= BIT_EINT4_7;
rINTPND |= BIT_EINT4_7;
}

3.主程序的主要功能是根据按键键值,向HD7279A发送不同的处理命令,程序结构如下。

void Main(){
char p;
Target_Init(); //目标初始化
while(1){
switch(key_number){
case 0: send_byte(cmd_test); //测试键
break;
case 1: for(p=0;p<8;p++){ //右移8位
send_byte(0xA0);
send_byte(0xC8+7);
send_byte(p);
long_delay();
Delay(7000);
} break;
//case 2到case14
case 15://最右两个数码管上显示15
write7279(decode1+5,key_number/16*8);
write7279(decode1+4,key_number & 0x0f);
break;
default: break;
}
key_number = 0xff;
Delay(50);
}
}

LCD显示原理

所谓LCD,是Liquid Crystal Display的缩写,即液晶显示器。LCD液晶显示器主要有两类:STN(Super Twisted Nematic,超扭曲向列型)和TFT(Thin Film Transistor,薄膜晶体管型)。对于S3C2410A的LCD控制器,同时支持STN和TFT显示器。

STN与TFT的主要区别在于:

  • 从工作原理上看,STN主要是增大液晶分子的扭曲角,而TFT为每个像素点设置一个开关电路,做到完全单独的控制每个像素点;
  • 从品质上看,STN的亮度较暗,画面的质量较差,颜色不够丰富,播放动画时有拖尾现象,耗电量小,价格便宜;而TFT亮度高,画面质量高,颜色丰富,播放动画时清晰,耗电量大,价格高。

LCD控制器概述

市面上出售的LCD有两种类型:

一种是带有驱动控制电路的LCD显示模块,这种LCD可以方便地与各种低档单片机进行接口;

另一种是LCD显示屏,没有驱动控制电路,

大部分ARM处理器中都集成了LCD控制器,所以对于采用ARM处理器的系统,一般使用不带驱动电路的LCD显示屏。

嵌入式处理器与LCD的连接

嵌入式:人机交互接口设计详解_寄存器_03

S3C2410A的LCD控制器

S3C2410A中的LCD控制器可支持STN和TFT两种液晶显示屏。 LCD控制器支持单色、4级、16级灰度LCD显示,以及8位彩色(256色)、12位彩色(4096色)LCD显示。LCD控制器由REGBANK、LCDCDMA、VIDPRCS、TIMEGEN和LPC3600组成。

(1)STN LCD

— 支持 3 种STN LCD 显示: 4-bit 双扫描, 4-bit 单扫描, 和8-bit 单扫描
— 支持二值, 4 级灰度, 16 级灰度,256色 和 4096 色的 STN LCD
— 典型屏幕尺寸为:640×480, 320×240, 160×160等。256色模式虚拟屏幕尺寸为:4096×1024, 2048×2048, 1024×4096等等

(2)TFT LCD

— 支持 1位、2位、4位和8位 调色板模式的TFT LCD 显示
— 支持16位、24位(16M)非调色板模式的TFT LCD显示
— 典型实际屏幕尺寸为 640×480, 320×240, 160×160等。64K 彩色模式下支持的最大虚拟屏幕尺寸为 2048×1024

LCD控制器的框图

嵌入式:人机交互接口设计详解_寄存器_04
  • REGBANK:寄存器组,由17个寄存器和一个256×16的调色板构成,用来设置LCD控制器。
  • LCDCDMA:专用DMA,用来自动将存储器中的视频数据传送到LCD驱动器中。无需CPU干涉。
  • VIDPRCS:视频数据产生,用来从LCDCDMA接收视频数据,并且转换成适当的格式(如:4/8比特单扫描或4比特双扫描),然后从端口VD[23:0] 发送到LCD驱动器。
  • TIMEGEN: 时序产生,用来产生视频控制信号。
  • LPC3600:定时控制生成逻辑单元。

LCD接口信号

S3C2410A中的LCD控制器一共有33个输出端口,其中24个数据信号端口,9个控制信号端口。

  • VFRAME/VSYNC/STV : LCD控制器发往驱动器的帧同步信号 ,它表示新的一帧的开始。LCD控制器在一个完整的帧显示后发出该信号,开始新的一帧的显示。
  • VLINE/HSYNC/CPV : LCD控制器发往驱动器的行同步脉冲信号 ,LCD驱动器在收到该信号后,将水平移位寄存器的内容显示到LCD屏上。LCD控制器在一整行数据全部传输到LCD驱动器后,发出一个VLINE信号。
  • VCLK/LCD_HCLK : LCD控制器发往驱动器的像素时钟信号 ,LCD控制器在VCLK的上升沿发送数据,LCD驱动器在VCLK的下降沿采样数据。
  • VD[23:0] : LCD 像素数据输出端口 ,也就是平时所说的RGB信号线,采用的是5:6:5的模式。
  • VM/VDEN/TP : LCD 驱动器所使用的的AC 偏置信号 。LCD驱动器使用该信号改变行电压和列电压的极性,进而打开或者关闭像素,使像素点显示或熄灭。VM信号可以与帧同步信号或者行同步信号进行同步。
  • LEND/STH : 行终止信号 (TFT)/SEC TFT信号 STH
  • LCD_PWREN : LCD 电源使能信号
  • LCDVF0 : SEC TFT OE信号
  • LCDVF1 : SEC TFT REV信号
  • LCDVF2 : SEC TFT REVB信号

STN LCD控制器操作

定时发生器 (TIMEGEN)

TIMEGEN产生LCD驱动器所需要的各种控制信号,如:VFRAME, VLINE, VCLK, 和VM。 这些信号是与REGBANK 里面的寄存器LCDCON1/2/3/4/5 的配置密切相关的。可以通过改变这些寄存器的配置使得这些控制信号能够满足各种LCD驱动器的要求。比如:

(1)VM的切换速率

VM 的切换速率由LCDCON1寄存器的 MMODE位和LCDCON4寄存器的MVAL 字段来决定。如果MMODE = 0,则VM信号每帧切换一次。如果MMODE =1 ,则VM 每MVAL[7:0]个VLINE切换一次,即:

VM Rate = VLINE Rate / ( 2 * MVAL) ,如下图所示:

嵌入式:人机交互接口设计详解_数据_05
(2)VFRAME 和VLINE脉冲

VFRAME 和VLINE脉冲的产生依赖于LCDCON2/3寄存器的HOZVAL字段和LINEVAL 字段。这两个字段的值由LCD的显示尺寸和显示模式决定:

HOZVAL = (水平显示尺寸 / 有效 VD 数据行数)- 1

(在彩色显示模式水平显示尺寸= 3 ×水平像素数;在4位单扫描和4位双扫描模式,有效 VD 数据行数为4,在8位单扫描模式,有效 VD 数据行数为8. )

LINEVAL = (垂直显示尺寸) -1 //单扫描模式下

LINEVAL = (垂直显示尺寸/2) -1 //双扫描模式下
(3)VCLK 信号速率

VCLK 信号的速率依赖于LCDCON1寄存器的CLKVAL 字段的设置。VCLK与 CLKVAL(最小为2)的对应关系为:
​VCLK(Hz)=HCLK/(CLKVAL x 2)​

如下表所示:

嵌入式:人机交互接口设计详解_数据_06
(4)帧速率

帧速率即是VFRAM 信号的频率. 帧速率与LCDCON1/2/3/4寄存器中的WLH​​1:0​​,WDLY[1:0] (VLINE脉冲之后的VCLK延时长度),HOZVAL,LINEBLANK和LINEVAL等字段,以及VCLK和HCLK有关。帧速率的计算公式为:
​frame_rate(Hz) = 1/{[(1/VCLK)×(HOZVAL+1)+(1/HCLK)×(A+B+(LINEBLANK×8))]×(LINEVAL+1)}​

​A = 2(4+WLH),B = 2(4+WDLY)​

(1)查找表

S3C2410 LCD控制器支持单色、2位(4级灰度)、4位(16灰度级)、8位(256级彩色)和12位(4096级彩色) LCD显示。

为了便于用户选择不同的显示模式, S3C2410 LCD控制器采用了调色板。通过这个调色板,用户可以在4灰度级模式下从16级灰度中选择4级灰度,构成查找表。在256级彩色中,8位彩色由3位红(8色)、3位绿(8色)、2位蓝(4色)构成(8×8×4= 256),这些红绿蓝色级也是分别在自己的16级中进行选择构成查找表。在16级灰度显示模式下,不需要查找表,16个灰度级都需要。在4096级彩色中不需要查表(红、绿、蓝都是16级, 16×16×16= 4096)。

(2)灰度模式操作

S3C2410 LCD控制器支持两种灰度模块:2位(4级灰度)、4位(16灰度级)。其中,4级灰度模式使用查找表,并且该查找表和彩色中的蓝色共用BLUELUT寄存器中的BLUEVAL[15:0]。

嵌入式:人机交互接口设计详解_寄存器_07

0级灰度用BLUEVAL[3:0]来表示(如:这四位的值是3,则表示用16级灰度中的3级来表示4级灰度中的0级)、 1级灰度用BLUEVAL[7:4]来表示, 2级灰度用BLUEVAL[11:8]来表示, 3级灰度用BLUEVAL[15:12]来表示。

(3)256级彩色模式操作

S3C2410 LCD控制器支持每像素8位的256色彩色模式。每个象素的8位有3位表示红,3位表示绿,2位表示兰,分别利用自己的查找表。各个表分别用REDLUT寄存器中的REDVAL[31:0]、GREENLUT寄存器中的GREENVAL[31:0]和BLUELUT寄存器中的BLUEVAL[15:0]作为查找表的入口。

嵌入式:人机交互接口设计详解_数据_08
(4)4096级彩色模式操作

S3C2410 LCD控制器支持每像素12位的4096色彩色模式。每个象素的12位有4位表示红,4位表示绿,4位表示兰,不再使用查找表。

(5)扫描模式支持

S3C2410 LCD控制器支持3种显示:4位单扫描、4位双扫描和8位单扫描。扫描方式通过PNRMODE(LCDCON1[6:5])来设置:

PNRMODE

4位双扫描

4位单扫描

8位单扫描

TFT LCD

(A)4位单扫描

从VD[3:0]1次移动4位数据,直到一帧数据移位完毕。如下图所示:

嵌入式:人机交互接口设计详解_ARM_09
嵌入式:人机交互接口设计详解_寄存器_10
(B)4位双扫描

显示控制器分别使用两条扫描线进行数据显示,显示数据从VD[3:0]获得高扫描数据, VD[7:4]获得低扫描数据。如下图所示:

嵌入式:人机交互接口设计详解_人机交互_11
嵌入式:人机交互接口设计详解_人机交互_12
(C)8位单扫描

显示数据从VD[7:0]获得扫描数据,一次输入8位行数据。如下图所示:

嵌入式:人机交互接口设计详解_数据_13
嵌入式:人机交互接口设计详解_寄存器_14
(6)显示数据的存放
嵌入式:人机交互接口设计详解_数据_15

在4级灰度模式,2bit视频数据对应一个像素

在16级灰度模式,4bit视频数据对应一个像素

在256色彩色模式,8bit视频数据对应一个像素。8位彩色数据格式如下:

嵌入式:人机交互接口设计详解_寄存器_16

在4096色彩色模式,12bit视频数据对应一个像素,以字为单位的彩色数据格式如下(注意:这时彩色视频数据必须3字对齐,即8像素对齐):

嵌入式:人机交互接口设计详解_寄存器_17

与LCD相关的寄存器

  • LCD控制寄存器1(LCDCON1)
  • LCD控制寄存器2(LCDCON2)
  • LCD控制寄存器3(LCDCON3)
  • LCD控制寄存器4(LCDCON4)
  • LCD控制寄存器5(LCDCON5)
  • 帧缓冲起始地址寄存器1(LCDSADDR1)
  • 帧缓冲起始地址寄存器2(LCDSADDR2)
  • 帧缓冲起始地址寄存器3(LCDSADDR3)
  • RGB查找表寄存器(REDLUT、GREENLUT 、BLUELUT )
  • 抖动模式寄存器(DITHMODE)

LCD显示的编程实例

举例:在LCD上填充一个蓝色的矩形,并画一个红色的圆。

1.定义与LCD相关的寄存器

#define M5D(n) ((n) & 0x1fffff)
#define MVAL (13)
#define MVAL_USED (0)
#define MODE_CSTN_8BIT (0x2001)
#define LCD_XSIZE_CSTN (320)
#define LCD_YSIZE_CSTN (240)
#define SCR_XSIZE_CSTN (LCD_XSIZE_CSTN*2) //虚拟屏幕大小
#define SCR_YSIZE_CSTN (LCD_YSIZE_CSTN*2)
#define HOZVAL_CSTN (LCD_XSIZE_CSTN*3/8-1) //有效的VD数据行号是8
#define LINEVAL_CSTN (LCD_YSIZE_CSTN-1)
#define WLH_CSTN (0)
#define WDLY_CSTN (0)
#define LINEBLANK_CSTN (16 &0xff)
#define CLKVAL_CSTN (6)
//130hz @50Mhz,WLH=16hclk,WDLY=16hclk,LINEBLANK=16*8hclk,VD=8
#define LCDFRAMEBUFFER 0x33800000 //帧缓冲区起始地址

2.初始化LCD,即对相关寄存器进行赋初值。其中参数type用于传递显示器的类型,如STN8位彩色、STN12位彩色等。

void LCD_Init(int type){
rIISPSR=(2<<5)|(2<<0); //IIS_LRCK=44.1Khz @384fs,PCLK=50Mhz.
rGPHCON = rGPHCON & ~(0xf<<18)|(0x5<<18);
switch(type){
case MODE_CSTN_8BIT: //STN8位彩色模式
frameBuffer8Bit=(U32 (*)[SCR_XSIZE_CSTN / 4])LCDFRAMEBUFFER;
rLCDCON1=(CLKVAL_CSTN<<8)|(MVAL_USED<<7)|(2<<5)|(3<<1)|0;
// 8-bit单扫描,8bpp CSTN,ENVID=关闭
rLCDCON2=(0<<24)|(LINEVAL_CSTN<<14)|(0<<6)|0;
rLCDCON3=(WDLY_CSTN<<19)|(HOZVAL_CSTN<<8)|(LINEBLANK_CSTN<<0);
rLCDCON4=(MVAL<<8)|(WLH_CSTN<<0);
rLCDCON5= 0;
rLCDSADDR1=(((U32)frameBuffer8Bit>>22)<<21)|M5D((U32)frameBuffer8Bit>>1);
rLCDSADDR2=M5D(((U32)frameBuffer8Bit+((SCR_XSIZE_CSTN)*LCD_YSIZE_CSTN))>>1);
rLCDSADDR3=(((SCR_XSIZE_CSTN-LCD_XSIZE_CSTN)/2)<<11)|(LCD_XSIZE_CSTN / 2);
rDITHMODE=0;
rREDLUT =0xfdb96420;
rGREENLUT=0xfdb96420;
rBLUELUT =0xfb40;
break;
default: break;
}
}

3.书写常用的绘图函数。函数_PutCstn8Bit()实现了在LCD的(x,y)处打点的功能。

void _PutCstn8Bit(U32 x,U32 y,U32 c){
if(x<SCR_XSIZE_CSTN&& y<SCR_YSIZE_CSTN)
frameBuffer8Bit[(y)][(x)/4]=( frameBuffer8Bit[(y)][x/4]
& ~(0xff000000>>((x)%4)*8) ) | ( (c&0x000000ff)<<((4-1-((x)%4))*8) );
}

4.书写主函数,通过调用初始化函数及绘图API函数,实现在LCD上填充一个蓝色的矩形,并画一个红色的圆。

void Main(void){
int Count = 3000;
Target_Init(); //硬件初始化
GUI_Init(); //图形用户接口初始化,包括对LCD的初始化
Set_Color(GUI_BLUE);
Fill_Rect(0,0,319,239);
Delay(Count);
Set_Color(GUI_RED);
Draw_Circle(100,100,50);
Delay(Count);
while(1);
}

触摸屏工作原理

触摸屏按其工作原理的不同可分为电阻式触摸屏、表面声波触摸屏、红外式触摸屏和电容式触摸屏几种。

最常见的是电阻式触摸屏,其屏体部分是一块与显示器表面非常配合的多层复合薄膜。触摸屏工作时,上下导体层相当于电阻网络。当某一层电极加上电压时,会在该网络上形成电压梯度。如有外力使得上下两层在某一点接触,则在另一层未加电压的电极上可测得接触点处的电压,从而知道接触点处的坐标。

四线电阻触摸屏原理

嵌入式:人机交互接口设计详解_人机交互_18
嵌入式:人机交互接口设计详解_ARM_19

在触摸点X、Y坐标的测量过程中,测量电压与测量点的等效电路图所示,图中P为测量点

S3C2410A的触摸屏接口

S3C2410A支持触摸屏接口,它由一个触摸屏面板、四个外部晶体管、一个外部电压源、信号AIN[7]和信号AIN[5]组成。

嵌入式:人机交互接口设计详解_数据_20

CPU与触摸屏连接图

嵌入式:人机交互接口设计详解_数据_21

触摸屏编程实例

举例:在触摸屏上按下的位置画一个点 。

1.对与触摸屏相关的寄存器进行初始化

void Touch_Init(void){
rADCDLY = (0x5000); // ADC启动或间隔延时
rADCTSC = (0<<8)|(1<<7)|(1<<6)|(0<<5)|(1<<4)|(0<<3)|(0<<2)|(3);
//设置成为等待中断模式:1101
rADCCON = (1<<14)|(49<<6)|(7<<3)|(0<<2)|(1<<1)|(0);
//设置ADC控制寄存器
}

2.对触摸屏中断进行初始化

void TouchINT_Init(void){
if ((rSRCPND & BIT_ADC)) //清除中断挂起位
rSRCPND |= BIT_ADC;
if ((rINTPND & BIT_ADC))
rINTPND |= BIT_ADC;
if ((rSUBSRCPND & BIT_SUB_TC))
rSUBSRCPND |= BIT_SUB_TC;
if ((rSUBSRCPND & BIT_SUB_ADC))
rSUBSRCPND |= BIT_SUB_ADC;
rINTMSK &= ~(BIT_ADC); //相关中断屏蔽位置0,使能中断
rINTSUBMSK &= ~(BIT_SUB_TC);
pISR_ADC = (unsigned)Touch_ISR; //设置中断向量
}

3.书写触摸屏中断服务程序,当有触笔按下时,转到中断服务程序执行。

void __irq Touch_ISR(void){
int AD_XY,yPhys,xPhys;
//关中断
rINTMSK |= (BIT_ADC);
rINTSUBMSK |= (BIT_SUB_ADC | BIT_SUB_TC); // 关闭子中断(ADC和TC)
//获取位置
AD_XY = GetTouch_XY_AD(); //得到阿A/D转换后的X/Y值
yPhys = (AD_XY) & 0xffff; //获取Y的AD值
xPhys = (AD_XY >> 16) & 0xffff;//获取X的AD值
TOUCH_X = AD2X(xPhys);
TOUCH_Y = AD2Y(yPhys);
Touch_Show(TOUCH_X,TOUCH_Y);//实现在触摸点位置画点
//开中断,清空挂起位
rSUBSRCPND |= BIT_SUB_TC;
ClearPending(BIT_ADC);
rINTMSK &= ~(BIT_ADC);
rINTSUBMSK &= ~(BIT_SUB_ADC);
rINTSUBMSK &= ~(BIT_SUB_TC);
}

4.书写主程序,首先对硬件及图形用户界面进行初始化,接下来通过一个while循环语句等待触摸屏中断的发生,一旦有触摸屏中断发生,则转到触摸屏中断服务程序执行。

void Main(void){
Target_Init(); //初始化硬件
GUI_Init(); //初始化图形用户界面
//背景填充为蓝色
Set_Color(GUI_BLUE);
Fill_Rect(0,0,319,239);
//设置当有触笔按下时,在LCD上画点的颜色为黄色
Set_Color(GUI_YELLOW);
//等待触摸屏中断
while (1){}
}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK