页次: 1
COM1 - COM4 按照万利板子原来的方法接
SEG0 - SEG15 也是
IAR 工程源码下载: Segment_MyTestProject_20190329.7z
/******************************************************************
本程序只供学习使用,未经作者许可,不得用于其它任何用途
欢迎访问我的USB专区:http://group.ednchina.com/93/
欢迎访问我的blog: http://www.ednchina.com/blog/computer00
http://computer00.21ic.org
LCD.c file
作者:Computer-lov
建立日期: 2008.07.30
修改日期: 2008.07.31
版本:V1.2
版权所有,盗版必究。
Copyright(C) Computer-lov 2008-2018
All rights reserved
*******************************************************************/
#include "gpio.h"
unsigned short int LcdDispBuf[4]; //用来保存显示的段码缓冲
void LcdInit(void)
{
//4个COM口都设置为高阻输入状态
//COM4
GPIOC_MODE8=0; //输入模式
GPIOC_CNF8=1; //高阻输入模式
//COM3
GPIOC_MODE9=0; //输入模式
GPIOC_CNF9=1; //高阻输入模式
//COM2
GPIOC_MODE10=0; //输入模式
GPIOC_CNF10=1; //高阻输入模式
//COM1
GPIOC_MODE11=0; //输入模式
GPIOC_CNF11=1; //高阻输入模式
//PE口设置为50MHz推挽输出
GPIOE_CRL=0x33333333;
GPIOE_CRH=0x33333333;
//先初始化为无显示
LcdDispBuf[0]=0;
LcdDispBuf[1]=0;
LcdDispBuf[2]=0;
LcdDispBuf[3]=0;
}
//像万利的板子上使用的这种LCD,有4个COM,还有有16个SEG。
//要想某一SEG显示时,需要在对应的SEG和COM之间加上足够的电压,
//但是LCD它不像LED那样,有电压就一直亮的,它只能维持一段
//时间,然后内容就消失了。此时需要将电压反转再加到相应的
//SEG和COM之间。在万利的板子上,COM驱动使用了两个电阻分压,
//输出电压为1/2VCC,当不想让某位显示时,就将它的电压设置
//为1/2VCC(通过设置IO口为高阻态来完成),这样加在对应的
//SEG和COM之间的电压只有1/2VCC,不足以点亮对应的SEG。需要显示
//的,就将COM电压设置为0或者1,这样SEG电压跟COM电压相反的
//段就被点亮了(变黑)。通过定期扫描每个COM,即可稳定的在LCD
//上显示需要的图形了。需要显示字符或者数字时,需要自己将
//对应的图案设计好,需要显示时,发送到相应的SEG和COM上即可。
/*the varitronix LCD digit is:
A
-- ----------
X \/ |\ |I /|
F| H | J |B
| \ | / |
--G-- --K--
| /| \ |
E | L | N |C
| / |M \| _
----------- | |DP
D -
PE0 PE1 PE2 PE3 ...................................................... PE15
----------------------------------------------------------------------------------------
| | S0 | S1 | S2 | S3 | S4 | S5 | S6 | S7 | S8 | S9 | S10| S11| S12| S13| S14| S15|
----------------------------------------------------------------------------------------
| COM1 | 1X | 1I | 1A | 1DP| 2X | 2I | 2A | 2DP| 3X | 3I | 3A | 3DP| 4X | 4I | 4A | 4DP|
----------------------------------------------------------------------------------------
| COM2 | 1F | 1H | 1J | 1B | 2F | 2H | 2J | 2B | 3F | 3H | 3J | 3B | 4F | 4H | 4J | 4B |
----------------------------------------------------------------------------------------
| COM3 | 1E | 1G | 1K | 1C | 2E | 2G | 2K | 2C | 3E | 3G | 3K | 3C | 4E | 4G | 4K | 4C |
----------------------------------------------------------------------------------------
| COM4 | 1L | 1M | 1N | 1D | 2L | 2M | 2N | 2D | 3L | 3M | 3N | 3D | 4L | 4M | 4N | 4D |
----------------------------------------------------------------------------------------
A LCD character coding is based on the following matrix:
{ X , F , E , L }
{ I , H , G , M }
{ A , J , K , N }
{ DP, B , C , D }
The characher A for example is:
{ 0 , 1 , 1 , 0 }
{ 0 , 0 , 1 , 0 }
{ 1 , 0 , 1 , 0 }
{ 0 , 1 , 1 , 0 }
-------------------
= 4 9 F 0 hex
=> 'A' = 0x49F0 */
#if 0
const unsigned short int Letter[26]={0x49F0,0x01F8,0x4118,0x08F8,0x4178,0x4170,0x41D8,0x09F0,0x600A,
0x0888,0x0534,0x0118,0x0F90,0x0B94,0x4998,0x4970,0x499C,0x4974,
0x41E8,0x6002,0x0998,0x0511,0x299A,0x0605,0x0601,0x4409};
const unsigned short int Number[10]={0x4998,0x0880,0x4878,0x48E8,0x09E0,0x41E8,0x41F8,0x4880,0x49F8,0x49E8};
const unsigned short int Arrow[2]={0x0005,0x0600}; // {Upstair,Downstair}
#endif
const unsigned short int Letter[26]={0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, };
const unsigned short int Number[10]={0x00003, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, };
const unsigned short int Arrow[2]={0x0000,0x0000}; // {Upstair,Downstair}
//根据LCD需要显示的字符设置缓冲区的内容。
//入口参数c为需要显示的字符。
//入口参数p为需要显示的位置,从左往右依次为0,1,2,3。
//入口参数dot为是否需要显示小数点和单引号,1只显示小数点,
//2只显示单引号,3为小数点和单引号同时显示
void LcdSetChar(unsigned char c, unsigned char p, unsigned char dot)
{
//定义一个Temp变量来保存查表的结果
unsigned short int Temp;
unsigned int tmp_num_display_buf[4];
switch(c)
{
case '0':
tmp_num_display_buf[0] = 0x01;
tmp_num_display_buf[1] = 0x03;
tmp_num_display_buf[2] = 0x01;
tmp_num_display_buf[3] = 0x03;
break;
case '1':
tmp_num_display_buf[0] = 0x00;
tmp_num_display_buf[1] = 0x02;
tmp_num_display_buf[2] = 0x00;
tmp_num_display_buf[3] = 0x02;
break;
case '2':
tmp_num_display_buf[0] = 0x01;
tmp_num_display_buf[1] = 0x01;
tmp_num_display_buf[2] = 0x02;
tmp_num_display_buf[3] = 0x03;
break;
case '3':
tmp_num_display_buf[0] = 0x01;
tmp_num_display_buf[1] = 0x02;
tmp_num_display_buf[2] = 0x02;
tmp_num_display_buf[3] = 0x03;
break;
case '4':
tmp_num_display_buf[0] = 0x00;
tmp_num_display_buf[1] = 0x02;
tmp_num_display_buf[2] = 0x03;
tmp_num_display_buf[3] = 0x02;
break;
case '5':
tmp_num_display_buf[0] = 0x01;
tmp_num_display_buf[1] = 0x02;
tmp_num_display_buf[2] = 0x03;
tmp_num_display_buf[3] = 0x01;
break;
case '6':
tmp_num_display_buf[0] = 0x01;
tmp_num_display_buf[1] = 0x03;
tmp_num_display_buf[2] = 0x03;
tmp_num_display_buf[3] = 0x01;
break;
case '7':
tmp_num_display_buf[0] = 0x00; //点D
tmp_num_display_buf[1] = 0x02; //C E
tmp_num_display_buf[2] = 0x00; //G F
tmp_num_display_buf[3] = 0x03; //B A
break;
case '8':
tmp_num_display_buf[0] = 0x01;
tmp_num_display_buf[1] = 0x03;
tmp_num_display_buf[2] = 0x03;
tmp_num_display_buf[3] = 0x03;
break;
case '9':
tmp_num_display_buf[0] = 0x01;
tmp_num_display_buf[1] = 0x02;
tmp_num_display_buf[2] = 0x03;
tmp_num_display_buf[3] = 0x03;
break;
}
if((p >= 0) && (p <= 6))
{
LcdDispBuf[0] |= tmp_num_display_buf[0] << (p*2);
LcdDispBuf[1] |= tmp_num_display_buf[1] << (p*2);
LcdDispBuf[2] |= tmp_num_display_buf[2] << (p*2);
LcdDispBuf[3] |= tmp_num_display_buf[3] << (p*2);
}
else
{
}
}
//每隔一段时间要调用一次该函数,例如2ms
//可以在一个定时器中调用该函数来定期刷新
//这里为了演示程序,使用软件延时的方法
void LcdScan(void)
{
static unsigned int i=1;
static unsigned int Off=0;
//一个完整的驱动周期,需要在COM和SEG之间正负
//电压交替一次。我们把COM输出低时定义为前半
//个周期,COM输出为高时定义为后半个周期。
//为了能够调节显示的对比度,需要在每个半周期
//中控制显示时间的长短。这里为了程序简单,
//使用了50%的占空比,即在每个半周期的前半段
//正常显示,后半段不显示,将COM和SEG都设置为
//低电平。该过程由Off标志来决定,当Off标志
//为1时,则是后半段的关闭过程,将COM和SEG置0
//后,就返回。当Off标志为0时,则处于前半段,
//就选中某个COM显示。这样,对于一个COM,完整
//的扫描周期有4个阶段:COM负亮,关,COM正亮,关。
//由于有4个COM,因此整个扫描周期就有16个阶段。
if(Off==1)
{
Off=0;
//先将4个COM都设置为高阻状态
GPIOC_MODE8=0; //输入模式
GPIOC_CNF8=1; //高阻输入模式
GPIOC_MODE9=0; //输入模式
GPIOC_CNF9=1; //高阻输入模式
GPIOC_MODE10=0; //输入模式
GPIOC_CNF10=1; //高阻输入模式
GPIOC_MODE11=0; //输入模式
GPIOC_CNF11=1; //高阻输入模式
//然后将所有SEG设置为低电平
GPIOE_ODR=0;
//再将所有COM设置为低电平
GPIOC_CLR=(1<<8)|(1<<9)|(1<<10)|(1<<11);
GPIOC_MODE8=3; //50M输出模式
GPIOC_CNF8=0; //推挽模式
GPIOC_MODE9=3; //50M输出模式
GPIOC_CNF9=0; //推挽模式
GPIOC_MODE10=3; //50M输出模式
GPIOC_CNF10=0; //推挽模式
GPIOC_MODE11=3; //50M输出模式
GPIOC_CNF11=0; //推挽模式
return;
}
else
{
Off=1;
//先将4个COM都设置为高阻状态
GPIOC_MODE8=0; //输入模式
GPIOC_CNF8=1; //高阻输入模式
GPIOC_MODE9=0; //输入模式
GPIOC_CNF9=1; //高阻输入模式
GPIOC_MODE10=0; //输入模式
GPIOC_CNF10=1; //高阻输入模式
GPIOC_MODE11=0; //输入模式
GPIOC_CNF11=1; //高阻输入模式
}
switch(i)
{
case 1:
//COM4的前半个周期
GPIOE_ODR=LcdDispBuf[3]; //将SEG码输出
GPIOC_CLR=1<<8; //COM4输出低电平
GPIOC_CNF8=0; //推挽输出
GPIOC_MODE8=3; //50MHz输出模式
break;
case 2:
//COM4的后半个周期
GPIOE_ODR=~LcdDispBuf[3]; //将SEG码取反
GPIOC_SET=1<<8; //COM4输出高电平
GPIOC_CNF8=0; //推挽输出
GPIOC_MODE8=3; //50MHz输出模式
break;
case 3:
//COM3的前半个周期
GPIOE_ODR=LcdDispBuf[2]; //将SEG码输出
GPIOC_CLR=1<<9; //COM3输出低电平
GPIOC_CNF9=0; //推挽输出
GPIOC_MODE9=3; //50MHz输出模式
break;
case 4:
//COM3的后半个周期
GPIOE_ODR=~LcdDispBuf[2]; //将SEG码取反
GPIOC_SET=1<<9; //COM3输出高电平
GPIOC_CNF9=0; //推挽输出
GPIOC_MODE9=3; //50MHz输出模式
break;
case 5:
//COM2的前半个周期
GPIOE_ODR=LcdDispBuf[1]; //将SEG码输出
GPIOC_CLR=1<<10; //COM2输出低电平
GPIOC_CNF10=0; //推挽输出
GPIOC_MODE10=3; //50MHz输出模式
break;
case 6:
//COM2的后半个周期
GPIOE_ODR=~LcdDispBuf[1]; //将SEG码取反
GPIOC_SET=1<<10; //COM2输出高电平
GPIOC_CNF10=0; //推挽输出
GPIOC_MODE10=3; //50MHz输出模式
break;
case 7:
//COM1的前半个周期
GPIOE_ODR=LcdDispBuf[0]; //将SEG码输出
GPIOC_CLR=1<<11; //COM1输出低电平
GPIOC_CNF11=0; //推挽输出
GPIOC_MODE11=3; //50MHz输出模式
break;
case 8:
//COM1的后半个周期
GPIOE_ODR=~LcdDispBuf[0]; //将SEG码取反
GPIOC_SET=1<<11; //COM1输出高电平
GPIOC_CNF11=0; //推挽输出
GPIOC_MODE11=3; //50MHz输出模式
i=0;
break;
default :
i=0;
}
//切换到下一状态
i++;
}
Bus Hound 6.01 capture on Windows Vista Service Pack 1 (x64). Complements of www.perisoft.net
Device - Device ID (followed by the endpoint for USB devices)
(20) VMware USB Device
(27) VMware USB Device
Phase - Phase Type
CTL USB control transfer
IN Data in transfer
RESET bus reset
ok command complete
Data - Hex dump of the data transferred
Descr - Description of the phase
Cmd... - Position in the captured data
Time - Time the phase occurred in hour:minute:second.millisec form
Device Phase Data Description Cmd.Phase.Ofs(rep) Time
------ ----- -------------------------------------------------- ---------------- ------------------ ------------
20 RESET 1.1.0 15:10:49.066
20 ok 1.2.0 15:10:49.207
20.0 CTL 80 06 00 01 00 00 40 00 GET DESCRIPTOR 2.1.0 15:10:49.284
20.0 IN 12 01 10 01 ff 00 00 08 86 1a 23 75 54 02 00 02 ..........#uT... 2.2.0 15:10:49.284
00 01 .. 2.2.16
20 RESET 3.1.0 15:10:49.288
20 ok 3.2.0 15:10:49.429
20.0 CTL 80 06 00 01 00 00 12 00 GET DESCRIPTOR 4.1.0 15:10:49.521
20.0 IN 12 01 10 01 ff 00 00 08 86 1a 23 75 54 02 00 02 ..........#uT... 4.2.0 15:10:49.521
00 01 .. 4.2.16
20.0 CTL 80 06 00 02 00 00 09 00 GET DESCRIPTOR 5.1.0 15:10:49.523
20.0 IN 09 02 27 00 01 01 00 80 30 ..'.....0 5.2.0 15:10:49.523
20.0 CTL 80 06 00 02 00 00 27 00 GET DESCRIPTOR 6.1.0 15:10:49.525
20.0 IN 09 02 27 00 01 01 00 80 30 09 04 00 00 03 ff 01 ..'.....0....... 6.2.0 15:10:49.525
02 00 07 05 82 02 20 00 00 07 05 02 02 20 00 00 ...... ...... .. 6.2.16
07 05 81 03 08 00 01 ....... 6.2.32
20.0 CTL 80 06 00 03 00 00 ff 00 GET DESCRIPTOR 7.1.0 15:10:49.527
20.0 IN 04 03 09 04 .... 7.2.0 15:10:49.527
20.0 CTL 80 06 02 03 09 04 ff 00 GET DESCRIPTOR 8.1.0 15:10:49.531
20.0 IN 1c 03 55 00 53 00 42 00 32 00 2e 00 30 00 2d 00 ..U.S.B.2...0.-. 8.2.0 15:10:49.531
53 00 65 00 72 00 69 00 61 00 6c 00 S.e.r.i.a.l. 8.2.16
20.0 CTL 00 09 01 00 00 00 00 00 SET CONFIG 9.1.0 15:10:49.535
20.0 CTL c0 5f 00 00 00 00 08 00 VENDOR 10.1.0 15:10:49.538
20.0 IN 30 00 0. 10.2.0 15:10:49.538
20.0 CTL 40 a1 00 00 00 00 00 00 VENDOR 11.1.0 15:10:49.565
20.0 CTL 40 9a 12 13 02 b2 00 00 VENDOR 12.1.0 15:10:49.567
20.0 CTL 40 9a 2c 0f 0c 00 00 00 VENDOR 13.1.0 15:10:49.569
20.0 CTL c0 95 18 25 00 00 08 00 VENDOR 14.1.0 15:10:49.571
20.0 IN c3 00 .. 14.2.0 15:10:49.571
20.0 CTL 40 9a 18 25 50 00 00 00 VENDOR 15.1.0 15:10:49.575
20.0 CTL c0 95 06 07 00 00 08 00 VENDOR 16.1.0 15:10:49.577
20.0 IN ff ee .. 16.2.0 15:10:49.577
20.0 CTL 40 a1 1f 50 0a d9 00 00 VENDOR 17.1.0 15:10:49.581
20.0 CTL 40 9a 12 13 02 b2 00 00 VENDOR 18.1.0 15:10:49.583
20.0 CTL 40 9a 2c 0f 0c 00 00 00 VENDOR 19.1.0 15:10:49.584
20.0 CTL 40 a4 9f ff 00 00 00 00 VENDOR 20.1.0 15:10:49.586
20.0 CTL c0 95 06 07 00 00 08 00 VENDOR 21.1.0 15:10:49.588
20.0 IN 9f ee .. 21.2.0 15:10:49.588
CH340
Bus Hound 6.01 capture on Windows Vista Service Pack 1 (x64). Complements of www.perisoft.net
Device - Device ID (followed by the endpoint for USB devices)
(20) VMware USB Device
(27) VMware USB Device
Phase - Phase Type
CTL USB control transfer
IN Data in transfer
RESET bus reset
USTS USB status
ok command complete
Data - Hex dump of the data transferred
Descr - Description of the phase
Cmd... - Position in the captured data
Time - Time the phase occurred in hour:minute:second.millisec form
Device Phase Data Description Cmd.Phase.Ofs(rep) Time
------ ----- -------------------------------------------------- ---------------- ------------------ ------------
27.0 CTL 80 06 00 02 00 00 09 00 GET DESCRIPTOR 1.1.0 14:59:21.506
27.0 IN 09 02 20 00 01 01 00 80 32 .. .....2 1.2.0 14:59:21.506
27.0 CTL 80 06 00 02 00 00 20 00 GET DESCRIPTOR 2.1.0 14:59:21.507
27.0 IN 09 02 20 00 01 01 00 80 32 09 04 00 00 02 ff 00 .. .....2....... 2.2.0 14:59:21.507
00 02 07 05 01 02 40 00 00 07 05 82 02 40 00 00 ......@......@.. 2.2.16
27 RESET 3.1.0 14:59:22.033
27 ok 3.2.0 14:59:22.174
27.0 CTL 80 06 00 01 00 00 40 00 GET DESCRIPTOR 4.1.0 14:59:22.247
27.0 IN 12 01 00 02 00 00 00 40 c4 10 60 ea 00 01 01 02 .......@..`..... 4.2.0 14:59:22.247
03 01 .. 4.2.16
27 RESET 5.1.0 14:59:22.251
27 ok 5.2.0 14:59:22.393
27.0 CTL 80 06 00 01 00 00 12 00 GET DESCRIPTOR 6.1.0 14:59:22.486
27.0 IN 12 01 00 02 00 00 00 40 c4 10 60 ea 00 01 01 02 .......@..`..... 6.2.0 14:59:22.486
03 01 .. 6.2.16
27.0 CTL 80 06 00 06 00 00 0a 00 GET DESCRIPTOR 7.1.0(3) 14:59:22.488
27.0 USTS c0000004 stall pid 7.2.0 14:59:22.488
27.0 CTL 80 06 00 02 00 00 09 00 GET DESCRIPTOR 10.1.0 14:59:22.494
27.0 IN 09 02 20 00 01 01 00 80 32 .. .....2 10.2.0 14:59:22.494
27.0 CTL 80 06 00 02 00 00 20 00 GET DESCRIPTOR 11.1.0 14:59:22.496
27.0 IN 09 02 20 00 01 01 00 80 32 09 04 00 00 02 ff 00 .. .....2....... 11.2.0 14:59:22.496
00 02 07 05 01 02 40 00 00 07 05 82 02 40 00 00 ......@......@.. 11.2.16
27.0 CTL 80 06 00 03 00 00 ff 00 GET DESCRIPTOR 12.1.0 14:59:22.498
27.0 IN 04 03 09 04 .... 12.2.0 14:59:22.498
27.0 CTL 80 06 02 03 09 04 ff 00 GET DESCRIPTOR 13.1.0 14:59:22.502
27.0 IN 4a 03 43 00 50 00 32 00 31 00 30 00 34 00 20 00 J.C.P.2.1.0.4. . 13.2.0 14:59:22.502
55 00 53 00 42 00 20 00 74 00 6f 00 20 00 55 00 U.S.B. .t.o. .U. 13.2.16
41 00 52 00 54 00 20 00 42 00 72 00 69 00 64 00 A.R.T. .B.r.i.d. 13.2.32
67 00 65 00 20 00 43 00 6f 00 6e 00 74 00 72 00 g.e. .C.o.n.t.r. 13.2.48
6f 00 6c 00 6c 00 65 00 72 00 o.l.l.e.r. 13.2.64
27.0 CTL 80 06 01 03 09 04 ff 00 GET DESCRIPTOR 14.1.0 14:59:22.506
27.0 IN 1a 03 53 00 69 00 6c 00 69 00 63 00 6f 00 6e 00 ..S.i.l.i.c.o.n. 14.2.0 14:59:22.506
20 00 4c 00 61 00 62 00 73 00 .L.a.b.s. 14.2.16
27.0 CTL 80 06 03 03 09 04 ff 00 GET DESCRIPTOR 15.1.0 14:59:22.510
27.0 IN 12 03 30 00 31 00 36 00 31 00 41 00 45 00 34 00 ..0.1.6.1.A.E.4. 15.2.0 14:59:22.510
43 00 C. 15.2.16
27.0 CTL 00 09 01 00 00 00 00 00 SET CONFIG 16.1.0 14:59:22.514
CP2104
转载圈圈的文章: https://www.veryarm.com/138135.html (这个也是网上转来的)
LCD的驱动不像LED那样,加上电压(LED实际上是电流驱动)就可以长期显示的。LCD驱动必须使用交流电压驱动才能保持稳定的显示,如果在LCD上加上稳定的直流电压,不但不能正常显示,时间久了还会损坏LCD。一段LCD由背电极和段电极组成,需要显示时,在背电极和段电极之间加上合适的交流电压(通常使用方波)。为了调节对比度,可以调节方波中每半个周期中显示的时间(即占空比)来实现。
通常,为了节约驱动口,将多个背电极连在一起,形成公共背电极端:COM。另外,再将属于不同COM的段电极连接在一起,形成公共段电极端:SEG。当在某个COM和某个SEG之间加了足够的交流电压之后,就会将对应的段点亮(实际上是变黑)。
像万利的板子上使用的这种LCD,有4个COM,还有16个SEG。要想某一SEG显示时,需要在对应的SEG和COM之间加上足够的交流电压。在万利的板子上,COM驱动使用了两个电阻分压,输出电压为1/2Vcc,当不想让某位显示时,就将它的电压设置为1/2Vcc(通过设置IO口为高阻态来完成),这样加在对应的SEG和COM之间的电压只有1/2Vcc,不足以点亮对应的SEG。需要显示的,就将COM电压设置为0或者1,这样SEG电压跟COM电压相反的段就被点亮了(变黑),因为它们之间的电压为Vcc。通过定期扫描每个COM,即可稳定的在LCD上显示需要的图形了。需要显示字符或者数字时,自己先将对应的图案设计好,在显示时,发送到相应的SEG和COM上即可。但是如果使用100%的时间都驱动的话,会造成对比度太高,甚至出现不该显示的地方也显示了。因此在显示一段时间后,就将COM和SEG都设置为低,以关闭它的显示,降低对比度。通过调节关闭时间的长短(PWM),可以调节对比度。在下面的测试程序中,为了简化程序,使用了50%固定的占空比。
为了方便描述,我们把COM为低电平时点亮叫做正亮,COM为高电平时点亮叫做负亮。扫描每个COM分成4个阶段:正亮,关闭,负亮,关闭。因此对于本板子上的LCD驱动,总共有16个状态,每个COM都有上面所说的4个状态。我们每隔2ms就切换一次状态,这样整个扫描周期就是2*16=32ms,基本上感觉不到闪烁。
但是需要注意的是,这个LCD中的每个COM并不是刚好对应着显示图案中的一个字符的位置。每个COM都对应着每个显示字符中的相同4段!换句话说,要显示第一个字符位置的字符,每个COM都要被用到。因此,要改变某个字符位置的显示,就需要改变每次COM输出时对应的SEG中的4段。为此,建立一个缓冲区,当需要修改显示字符时,就修改缓冲区中的内容。这个缓冲区有4行,每行中有16个SEG,对应着一个COM。需要修改显示时,把每行中对应的4个SEG设置为需要的值,这样就实现了某个显示位置图案的修改。
为了显示字符,需要事先把需要显示的字符按照SEG和COM的分布,制作成数据保存起来,需要显示时,就把它复制到显示缓冲区中对应的位置去。另外,由于输入的参数是字符的ASCII码,因此还需要将ASCII码转换为对应的字符图案的索引值。使用一个专门的函数来完成这些转换和填充缓冲区,在需要修改显示数据时,就调用该函数。
为了方便大家对这个LCD的驱动方式和编程,下面简单的画一下驱动的波形图。
这里只画出2个SEG波形图,实际有16个SEG,只要你理解了2个SEG的,那么16个的也是一样的意思。如图所示,所有偶数阶段都是关闭显示阶段,这时COM和SEG都是0,将不会有段被点亮,通过调节关闭显示阶段所占的时间百分比,即可调节总体显示的对比度。SEG和COM之间电平相差1格的显示不出来或者浓度不够,而SEG和COM之间电平相差2格的则可以显示出来或者浓度较深。例如第一阶段中的SEG1和COM1之间相差2格,第三阶段中COM1和SEG1相差2格,因而SEG1和COM1之间的交叉点(即点1)被显示。又如第九阶段的SEG1和COM3之间相差2格,第十一阶段中的COM3和SEG1之间相差2格,因而SEG1和COM3之间的交叉点(即点5)被显示出来。其它点以此类推。
最后,再来看看万利板子上的LCD的COM和SEG之间的关系图,如下图所示。
图中显示,S0、S1、S2、S3属于第一个字符,在显示第一个字符时,只要在对应的COM选中时,将需要显示的SEG放在上面即可。其余几个字符类似。例如要显示一个数字3,则应该将A段、B段、C段、D段、G段、K段显示。某段显示,用1表示,不显示用0表示,得到的各段值如下:
X=0 I="0" A="1" DP="0"
F=0 H="0" J="0" B="1"
E=0 G="1" K="1" C="1"
L=0 M="0" N="0" D="1"
注意是低位在先的,把每行用十六进制来表示(高位在先),就是0x4,0x8,0xE,0x8。它们分别对应着COM1~COM3选中时S3~S0的输出值。为了方便管理,将这4个十六进制值合并为一个2字节的值0x48E8保存。其它各字符的构造方式相同。显示时,分别取出各段的值写入到对应的缓冲区去。
扫描LCD的程序流程如下:
①、COM1设置为低电平,其余COM为1/2高电平,设置PE口为需要的电平(16个段码),延时2ms;
②、4个COM、PE口均设置为低电平,关闭显示,延时2ms;
③、COM1设置为高电平,其余COM为1/2高电平,设置PE口为需要的电平(第一步16个段码的取反),延时2ms。
④、4个COM、PE口均设置为低电平,关闭显示,延时2ms;
然后对剩下的3个COM重复前面4个步骤,这样一个完整的扫描就完成了。
具体的实现代码比较长,这里就不再贴出了,在工程包中的LCD.C中可以查看。该测试工程包使用软件延时的方法来实现LCD的扫描,实际使用时,可以将扫描代码放在定时器中断中处理。该测试程序使用一个时钟功能来演示LCD的显示,显示为xx分xx秒。从这里下载整个测试的工程包:
网上找到一份手册, 含原理图: stm3210b-eval-manual.pdf
IAR 源码下载: EKSTM3210B_v5.7z
STC IO驱动 段码液晶
链接: http://www.stcisp.com/STCMCU_IO_DIRECT_DRIVER_LCD-V3.html
源码: LCD_2014_6_19.7z
页次: 1