MCU的引脚(单片机IO口)驱动段码液晶屏详解
发布来源:www.xyhlcd.com 发布时间:2022-3-26
在我们日常生活之中最普通的显示屏就是段码液晶屏了,因为它省成本低效果好,那么液晶屏怎么驱动它显示呢?1、MCU+LCD驱动,2、MCU 的普通IO口来驱动。
第一种方法是大多说人常用的方法在此不在讲解,今天重点讲一下第二种方法来驱动段码液晶屏显示。
首先、讲那些液晶屏最适合MCU 的普通IO口来驱动液晶屏呢?1、笔段少显示简单;2、LCD液晶的引脚少占用MCU的IO口不多;3、1/2 BAIS的LCD。这里对MCU的IO有点要求,就是IO必须要是三态,低、高、高阻。
其次、电路如何来设计? 段码液晶屏主要是有两种引脚,一是COM和二是SEG,切记液晶屏不像数码管那样可以用直流驱动,液晶屏是靠一定的波形,COM和SEG的相位差来显示的 。
上图是COM引脚电路, SEG引脚和单片机的IO直接相连就可以了。
/******************************************************************
功能描述: MCU的IO直接驱动LCD测试程序
设 计 人:Zheng Qiu Sheng
版 本:1.0
函数命: 主函数main()
完成时间:2022年3月16日
*****************************************************************/
#include <STC8xxxx.h>
#include <stdio.h>
#include "gpio.h"
/************* 外部函数和变量声明 *****************/
#define uint unsigned int
#define uchar unsigned char
uchar ScanCoun,ZZ;
#define MAIN_Fosc 22118400L //定义主时钟
//COM SEG 的管脚定义
sbit COM0=P3^7; //COM0
sbit COM1=P3^6; //COM1
sbit COM2=P3^5; //COM2
sbit COM3=P3^4; //COM3
sbit SEG0=P1^0; //SEG0
sbit SEG1=P1^1; //SEG1
sbit SEG2=P1^2; //SEG2
sbit SEG3=P1^3; //SEG3
sbit SEG4=P1^4; //SEG4
sbit SEG5=P1^5; //SEG5
sbit SEG6=P1^6; //SEG6
sbit SEG7=P1^7; //SEG7
sbit SEG8=P5^4; //SEG8
sbit SEG9=P5^5; //SEG9
unsigned char ScanCoun=0; //动态扫描显示位数计数器
//0~9的段码查询表
unsigned char code seg_code[12]={0xfa,0x60,0xd6,0xf4,0x6c,0xbc,0xbe,0xe0,0xfe,0xfc,0x02,0x01};
//0 1 2 3 4 5 6 7 8 9 - Dot
//unsigned char DisplayBuf[6]={5,4,3,2,1,0}; //6位数字对应的显示暂存
////段码缓冲区
uchar SegBuf[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};//COM1、COM2、COM3、COM4对应的段码
/////////////延时 ms//////////////
void DelayMS(uint hh)
{ unsigned char i,j;
for(i=0; i<250; i++)
for(j=0; j<200;j++)
;
}
/******************************************************************
公司:深圳市兴宇合电子有限公司
功能描述: MCU的IO直接驱动LCD测试程序
设 计 人:Zheng Qiu Sheng
函数命: 主函数IO_set()
完成时间:2022年3月16日
*****************************************************************/
void IO_set()
{
P3n_open_drain(1<<4);//P3^4高阻 COM3
P3n_open_drain(1<<5);//P3^5高阻 COM2
P3n_open_drain(1<<6);//P3^6高阻 COM1
P3n_open_drain(1<<7);//P3^7高阻 COM0
P1M1=0x00; //P1口为输出
P1M0=0xFF; //SEG0--SEG07
P5n_push_pull(1<<4);//P5^4输出 SEG8
P5n_push_pull(1<<5);//P5^5输出 SEG9
}
/////////////////////////////////////////////////////////////////////
///************************ IO配置函数****************************//
/////////////////////////////////////////////////////////////////////
void GPIO_config(void) //(库函数定义)
{
GPIO_InitTypeDef GPIO_InitStructure; //结构定义
///////////////P1口seg输出/////////////
GPIO_InitStructure.Pin = GPIO_Pin_All; //指定要初始化的IO, GPIO_Pin_0 ~ GPIO_Pin_7
GPIO_InitStructure.Mode = GPIO_OUT_PP;
GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
GPIO_Inilize(GPIO_P1,&GPIO_InitStructure); //初始化
///////////////P54---P55口=seg输出/////////////
GPIO_InitStructure.Pin = GPIO_Pin_4 | GPIO_Pin_5; //指定要初始化的IO, GPIO_Pin_5 ~ GPIO_Pin_4
GPIO_InitStructure.Mode = GPIO_OUT_PP; //指定IO的推挽输出方式,GPIO_PullUp
GPIO_Inilize(GPIO_P5,&GPIO_InitStructure); //初始化
///////////////P34-P37 口=COM高阻/////////////
GPIO_InitStructure.Pin = GPIO_Pin_7 | GPIO_Pin_6|GPIO_Pin_5 | GPIO_Pin_4 | GPIO_Pin_2;;//指定要初始化的IO, GPIO_Pin_7 ~ GPIO_Pin_4
GPIO_Inilize(GPIO_P3,&GPIO_InitStructure); //初始化 /// P3M1|=0x04 P3M0&=0xFB
}
/******************************************************************
公司:深圳市兴宇合电子有限公司
功能描述: SGES数据转换成对应的com数据BUFFER
设 计 人:Zheng Qiu Sheng
函数命: 主函数Seg2Seg()
完成时间:2022年3月16日
*****************************************************************/
void Seg2Seg()
{
unsigned char SegXX;
SegBuf[0]=0x00;SegBuf[1]=0x00; //一定要设置为0
SegBuf[2]=0x00;SegBuf[3]=0x00;
SegBuf[4]=0x00;SegBuf[5]=0x00;
SegBuf[6]=0x00;SegBuf[7]=0x00;
//把4位数字的SEG放到COM1、COM2、COM3、COM4对应的SEGBUF[]里面
//LCD的管脚定义与LED不同,它不是一个COM对应一位数字,而是对应每个数字的一部分SEG
// 1 2 3 4 5 6 7 8 | 9 10 11 12 13 14 15 16
// 1f 1a 2f 2a 3f 3a 4f 4a -- segBuf【0】| 5f 5a 6f 6a -- segBuf【4】 ---- COM0
// 1g 1b 2g 2b 3g 3b 4g 4b -- segBuf【1】| 5g 5b 6g 6b -- segBuf【5】 ---- COM1
// 1e 1c 2e 2c 3e 3c 4e 4c -- segBuf【2】| 5e 5c 6e 6c -- segBuf【6】 ---- COM2
// 1h 1d 2h 2d 3h 3d 4h 4d -- segBuf【3】| 5h 5d 6h 6d -- segBuf【7】---- COM3
SegXX=seg_code[DY1]; //第1位数字
if (SegXX&0x80) SegBuf[0]|=0x02; //1a
if (SegXX&0x40) SegBuf[1]|=0x02; //1b
if (SegXX&0x20) SegBuf[2]|=0x02; //1c
if (SegXX&0x10) SegBuf[3]|=0x02; //1d
if (SegXX&0x08) SegBuf[0]|=0x01; //1f
if (SegXX&0x04) SegBuf[1]|=0x01; //1g
if (SegXX&0x02) SegBuf[2]|=0x01; //1e
//if (SegXX&0x01) SegBuf[3]|=0x01; //1h
SegXX=seg_code[DY0]; //第2位数字
if (SegXX&0x80) SegBuf[0]|=0x08; //2a
if (SegXX&0x40) SegBuf[1]|=0x08; //2b
if (SegXX&0x20) SegBuf[2]|=0x08; //2c
if (SegXX&0x10) SegBuf[3]|=0x08; //2d
if (SegXX&0x08) SegBuf[0]|=0x04; //2f
if (SegXX&0x04) SegBuf[1]|=0x04; //2g
if (SegXX&0x02) SegBuf[2]|=0x04; //2e
if (SegXX&0x01) SegBuf[3]|=0x04; //2h
SegXX=(seg_code[W2 ]|0x01); //第3位数字
if (SegXX&0x80) SegBuf[0]|=0x20;//3a
if (SegXX&0x40) SegBuf[1]|=0x20;//3b
if (SegXX&0x20) SegBuf[2]|=0x20;//3c
if (SegXX&0x10) SegBuf[3]|=0x20;//3d
if (SegXX&0x08) SegBuf[0]|=0x10;//3f
if (SegXX&0x04) SegBuf[1]|=0x10;//3g
if (SegXX&0x02) SegBuf[2]|=0x10;//3e
if (SegXX&0x01) SegBuf[3]|=0x10;//3h
SegXX=seg_code[W1]; //第4位数字
if (SegXX&0x80) SegBuf[0]|=0x80;//4a
if (SegXX&0x40) SegBuf[1]|=0x80;//4b
if (SegXX&0x20) SegBuf[2]|=0x80;//4c
if (SegXX&0x10) SegBuf[3]|=0x80;//4d
if (SegXX&0x08) SegBuf[0]|=0x40;//4f
if (SegXX&0x04) SegBuf[1]|=0x40;//4g
if (SegXX&0x02) SegBuf[2]|=0x40;//4g
if (SegXX&0x01) SegBuf[3]|=0x40;//4h
SegXX=(seg_code[W0]|0x01); //第5位数字
if (SegXX&0x80) SegBuf[4]|=0x02; //5a
if (SegXX&0x40) SegBuf[5]|=0x02; //5b
if (SegXX&0x20) SegBuf[6]|=0x02; //5c
if (SegXX&0x10) SegBuf[7]|=0x02; //5d
if (SegXX&0x08) SegBuf[4]|=0x01; //5f
if (SegXX&0x04) SegBuf[5]|=0x01; //5g
if (SegXX&0x02) SegBuf[6]|=0x01; //5e
if (SegXX&0x01) SegBuf[7]|=0x01; //5h
}
/*******************************************
/////////////定时器初始化////////////
********************************************/
InitInterResource()
{
IE=0; //关全部中断
TCON=0; //清全部中断请求
IP=0; //清中断优先级
TMOD=0x01; //T0工作方式1(16位定时器)
TH0=0xEC; //T0定时器辅初值
TL0=0x78;
TR0=1; //允许T0定时
ET0=1; //允许T0中断
EA=0; //关全局中断
}
/******************************************************************
公司:深圳市兴宇合电子有限公司
功能描述: 主函数测试程序
设 计 人:Zheng Qiu Sheng
函数命: 主函数 main()
完成时间:2022年3月16日
*****************************************************************/
void main()
{
DelayMS(20);
IO_set();
InitInterResource();
EA=1; //开全局中断
while(1) ;
}
/******************************************************************
公司:深圳市兴宇合电子有限公司
功能描述: 定时器0中断服务程序 5ms定时器,8字数码管动态显示驱动
设 计 人:Zheng Qiu Sheng
函数命: 主函数 main()
完成时间:2022年3月16日
********************************************************************/
void tmr0_p(void) interrupt 1
{
Seg2Seg();
switch(ScanCoun) //动态扫描显示
{
case 0: //COM0正向驱动
Tdat1=SegBuf[0];
SEG0 = (bit)(Tdat1&0x01);
SEG1 = (bit)(Tdat1&0x02);
SEG2 = (bit)(Tdat1&0x04);
SEG3 = (bit)(Tdat1&0x08);
SEG4 = (bit)(Tdat1&0x10);
SEG5 = (bit)(Tdat1&0x20);
SEG6 = (bit)(Tdat1&0x40);
SEG7 = (bit)(Tdat1&0x80);
Tdat2=SegBuf[4];
SEG8 = (bit)(Tdat2&0x01);
SEG9 = (bit)(Tdat2&0x02);
COM0=0;
P3n_push_pull(1<<7);//P3^7输出 COM0
P3n_open_drain(1<<4);//P3^4高阻 COM3
P3n_open_drain(1<<5);//P3^5高阻 COM2
P3n_open_drain(1<<6);//P3^6高阻 COM0
break;
case 1: //COM0反向驱动
Tdat1=~SegBuf[0];
SEG0 = (bit)(Tdat1&0x01);
SEG1 = (bit)(Tdat1&0x02);
SEG2 = (bit)(Tdat1&0x04);
SEG3 = (bit)(Tdat1&0x08);
SEG4 = (bit)(Tdat1&0x10);
SEG5 = (bit)(Tdat1&0x20);
SEG6 = (bit)(Tdat1&0x40);
SEG7 = (bit)(Tdat1&0x80);
Tdat2=~SegBuf[4];
SEG8 = (bit)(Tdat2&0x01);
SEG9 = (bit)(Tdat2&0x02);
COM0=1;
P3n_push_pull(1<<7);//P3^7输出 COM0
P3n_open_drain(1<<4);//P3^4高阻 COM3
P3n_open_drain(1<<5);//P3^5高阻 COM2
P3n_open_drain(1<<6);//P3^6高阻 COM0
break;
/////////////////////////////////////////////////////////
case 2: //COM1正向驱动
Tdat1=SegBuf[1];
SEG0 = (bit)(Tdat1&0x01);
SEG1 = (bit)(Tdat1&0x02);
SEG2 = (bit)(Tdat1&0x04);
SEG3 = (bit)(Tdat1&0x08);
SEG4 = (bit)(Tdat1&0x10);
SEG5 = (bit)(Tdat1&0x20);
SEG6 = (bit)(Tdat1&0x40);
SEG7 = (bit)(Tdat1&0x80);
Tdat2=SegBuf[5];
SEG8 = (bit)(Tdat2&0x01);
SEG9 = (bit)(Tdat2&0x02);
COM1=0;
P3n_push_pull(1<<6);//P3^6输出 COM1
P3n_open_drain(1<<4);//P3^4高阻 COM3
P3n_open_drain(1<<5);//P3^5高阻 COM2
P3n_open_drain(1<<7);//P3^7高阻 COM0
break;
case 3: //COM1反向驱动
Tdat1=~SegBuf[1];
SEG0 = (bit)(Tdat1&0x01);
SEG1 = (bit)(Tdat1&0x02);
SEG2 = (bit)(Tdat1&0x04);
SEG3 = (bit)(Tdat1&0x08);
SEG4 = (bit)(Tdat1&0x10);
SEG5 = (bit)(Tdat1&0x20);
SEG6 = (bit)(Tdat1&0x40);
SEG7 = (bit)(Tdat1&0x80);
Tdat2=~SegBuf[5];
SEG8 = (bit)(Tdat2&0x01);
SEG9 = (bit)(Tdat2&0x02);
COM1=1;
P3n_push_pull(1<<6);//P3^6输出 COM1
P3n_open_drain(1<<4);//P3^4高阻 COM3
P3n_open_drain(1<<5);//P3^5高阻 COM2
P3n_open_drain(1<<7);//P3^7高阻 COM0
break;
////////////////////////////////////////////////////////////////
case 4: //COM2正向驱动
Tdat1=SegBuf[2];
SEG0 = (bit)(Tdat1&0x01);
SEG1 = (bit)(Tdat1&0x02);
SEG2 = (bit)(Tdat1&0x04);
SEG3 = (bit)(Tdat1&0x08);
SEG4 = (bit)(Tdat1&0x10);
SEG5 = (bit)(Tdat1&0x20);
SEG6 = (bit)(Tdat1&0x40);
SEG7 = (bit)(Tdat1&0x80);
Tdat2=SegBuf[6];
SEG8 = (bit)(Tdat2&0x01);
SEG9 = (bit)(Tdat2&0x02);
COM2=0;
P3n_push_pull(1<<5);//P3^5输出 COM2
P3n_open_drain(1<<4);//P3^4高阻 COM3
P3n_open_drain(1<<6);//P3^6高阻 COM1
P3n_open_drain(1<<7);//P3^7高阻 COM0
break;
case 5: //COM2反向驱动
Tdat1=~SegBuf[2];
SEG0 = (bit)(Tdat1&0x01);
SEG1 = (bit)(Tdat1&0x02);
SEG2 = (bit)(Tdat1&0x04);
SEG3 = (bit)(Tdat1&0x08);
SEG4 = (bit)(Tdat1&0x10);
SEG5 = (bit)(Tdat1&0x20);
SEG6 = (bit)(Tdat1&0x40);
SEG7 = (bit)(Tdat1&0x80);
Tdat2=~SegBuf[6];
SEG8 = (bit)(Tdat2&0x01);
SEG9 = (bit)(Tdat2&0x02);
COM2=1;
P3n_push_pull(1<<5);//P3^5输出 COM2
P3n_open_drain(1<<4);//P3^4高阻 COM3
P3n_open_drain(1<<6);//P3^6高阻 COM1
P3n_open_drain(1<<7);//P3^7高阻 COM0
break;
////////////////////////////////////////////////////////////////
case 6: //COM3正向驱动
Tdat1=SegBuf[3];
SEG0 = (bit)(Tdat1&0x01);
SEG1 = (bit)(Tdat1&0x02);
SEG2 = (bit)(Tdat1&0x04);
SEG3 = (bit)(Tdat1&0x08);
SEG4 = (bit)(Tdat1&0x10);
SEG5 = (bit)(Tdat1&0x20);
SEG6 = (bit)(Tdat1&0x40);
SEG7 = (bit)(Tdat1&0x80);
Tdat2=SegBuf[7];
SEG8 = (bit)(Tdat2&0x01);
SEG9 = (bit)(Tdat2&0x02);
COM3=0;
P3n_push_pull(1<<4);//P3^4输出 COM3
P3n_open_drain(1<<5);//P3^5高阻 COM2
P3n_open_drain(1<<6);//P3^6高阻 COM1
P3n_open_drain(1<<7);//P3^7高阻 COM0
break;
case 7: //COM3反向驱动
Tdat1=~SegBuf[3];
SEG0 = (bit)(Tdat1&0x01);
SEG1 = (bit)(Tdat1&0x02);
SEG2 = (bit)(Tdat1&0x04);
SEG3 = (bit)(Tdat1&0x08);
SEG4 = (bit)(Tdat1&0x10);
SEG5 = (bit)(Tdat1&0x20);
SEG6 = (bit)(Tdat1&0x40);
SEG7 = (bit)(Tdat1&0x80);
Tdat2=~SegBuf[7];
SEG8 = (bit)(Tdat2&0x01);
SEG9 = (bit)(Tdat2&0x02);
COM3=1;
P3n_push_pull(1<<4);//P3^4输出 COM3
P3n_open_drain(1<<5);//P3^5高阻 COM2
P3n_open_drain(1<<6);//P3^6高阻 COM1
P3n_open_drain(1<<7);//P3^7高阻 COM0
break;
////////////////////////////////////////////////////////////////////
}
ScanCoun++; //下一位
if(ScanCoun>7)
ScanCoun=0;
TL0=0x78; //重新定时5ms
TH0=0xec;
ZZ++;
EA=1;
}
显示正常的情况下,经过测试:COM脚输出的波形如下图:
所以在用MCU直接驱动LCD时,尽量去选择1/2BAIS的LCD, 很容易通过IO口模拟出上述波形,这并不是唯一的方式,还有其它的波形也能实现,在这里就不一一解释了。在只是个人的一得之见,在此,抛砖引玉,希望更多人把自己的经验分享出来,帮助那些需要帮助的人,减少他们的不解和困惑。
“赠人玫瑰 ,手留余香”
“质量第一、精益求精、追求卓越”之理念是兴宇合电子有限公司 始终如一的郑重承诺。对于不明白或者有疑问的问题请拨打电话:
0755-83404646 / 0755-83570678 / 13923751240