LCD段码式液晶屏驱动

在实际项目中,我们通常会遇到许多需要驱动LCD段码屏的情形。

  如下图:

     假如是LED灯,我们都知道只需加载在一端接高另一端接低的直流电,就可以点亮。但是对于液晶屏来说,长时间的加直流电压会损坏液晶屏的内部,并且不可逆。所以需要用模拟的交流电来驱动,正常厂商会给你一份规格书,base偏压达到多少以上对应的字段就会点亮,我的这个是2.5V,也就是说一个段的两端压差超过2.5V,对应的段就会点亮。

    有需求就会有市场,于是带LCD工作模式的芯片就问世了,它的IO口有一个专门的寄存器来控制它输出多大的电压,区别于正常的只能是高或低的芯片,确实很方便。

    很幸运,老板的预算不足以我来用这样的芯片,考验哥们的时候来了。话不多说,直接展示结果:

所有的COM口和Seg口都接IO口,直接控制。

使用这样的电路:我们只需要改变IO口的工作模式就可以达到改变COM端电压的大小,浮空输入模式下,IO口电压完全取决于外部电压,我的原理图5V和GND对半分刚好是2.5V,等于我的LCD段码屏base电压,所以我只需要让5个COM循环扫描,仅仅在对应的时间段内拉高或者拉低Seg口即可,COM口扫描波形如下

这个是四扫的示意图,简单说就是在一个时间片内只有一个COM口是工作在有效电压内,其余都不是,四个口来回换着工作,由于它换的太快了,人眼识别不了这么快的亮灭,就觉得它是一直亮的,这和呼吸灯是一个道理

驱动部分代码如下:

void LedDisplayProcess()
{
   unsigned char i;
	 GPIO_InitTypeDef  GPIO_InitStructure;
	 GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_5 |GPIO_Pin_6 |GPIO_Pin_7 |GPIO_Pin_8|GPIO_Pin_13;
	 GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN_FLOATING ;	
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	
   GPIO_Init(GPIOA, &GPIO_InitStructure);//2.5V	
   if(LedReadyFlag) 
    {
      LedReadyFlag=0; //显示数据更新标志位
      for(i=0;i<5;i++)
      {				
       S_LEDDSP1[i]=LEDDSP1[i];					
      }
    }   
  if(++SEGNumber>=10) //0~9   对应5个COM口的10个时间片(单个COM口有高和低2种,base不算是一种)
    SEGNumber=0;
	LCD_Scan_Deal();//COM、Seg扫描函数  此处只做COM的展示,Seg结合自己的应用,对应拉低或拉高即可
}
void LCD_Scan_Deal()
{
	//com----------------------------------------------------------------------------------	
	if(SEGNumber==0)
	{
	 GPIO_InitTypeDef  GPIO_InitStructure;
	 GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_5;
	 GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;	
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	
   GPIO_Init(GPIOA, &GPIO_InitStructure);
	 GPIO_SetBits( GPIOA, GPIO_Pin_5);//5V
	}
  if(SEGNumber==1)
	{
	 GPIO_InitTypeDef  GPIO_InitStructure;
   GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_5;
	 GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;	
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	
   GPIO_Init(GPIOA, &GPIO_InitStructure);
	 GPIO_ResetBits( GPIOA, GPIO_Pin_5);//0V
	}
  if(SEGNumber==2)
	{	
   GPIO_InitTypeDef  GPIO_InitStructure;		
	 GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_6;
	 GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;	
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	
   GPIO_Init(GPIOA, &GPIO_InitStructure);
	 GPIO_SetBits( GPIOA, GPIO_Pin_6);//5V	
	}
  if(SEGNumber==3)
	{
   GPIO_InitTypeDef  GPIO_InitStructure;
   GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_6;
	 GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;	
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	
   GPIO_Init(GPIOA, &GPIO_InitStructure);
	 GPIO_ResetBits( GPIOA, GPIO_Pin_6);//0V
		
	}
  if(SEGNumber==4)
	{
   GPIO_InitTypeDef  GPIO_InitStructure;		
	 GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_7;
	 GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;	
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	
   GPIO_Init(GPIOA, &GPIO_InitStructure);
	 GPIO_SetBits(GPIOA, GPIO_Pin_7);//5V
	}
  if(SEGNumber==5)
	{
	 GPIO_InitTypeDef  GPIO_InitStructure;
   GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_7;
	 GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;	
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	
   GPIO_Init(GPIOA, &GPIO_InitStructure);
	 GPIO_ResetBits(GPIOA, GPIO_Pin_7);//0V
	}
	if(SEGNumber==6)
	{
   GPIO_InitTypeDef  GPIO_InitStructure;		
	 GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_8;
	 GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;	
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	
   GPIO_Init(GPIOA, &GPIO_InitStructure);
	 GPIO_SetBits( GPIOA, GPIO_Pin_8);//5V	
	}
  if(SEGNumber==7)
	{
	 GPIO_InitTypeDef  GPIO_InitStructure;
   GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_8;
	 GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;	
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	
   GPIO_Init(GPIOA, &GPIO_InitStructure);
	 GPIO_ResetBits(GPIOA, GPIO_Pin_8);//0V
	}
		if(SEGNumber==8)
	{
   GPIO_InitTypeDef  GPIO_InitStructure;		
	 GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_13;
	 GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;	
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	
   GPIO_Init(GPIOA, &GPIO_InitStructure);
	 GPIO_SetBits( GPIOA, GPIO_Pin_13);//5V	
	}
  if(SEGNumber==9)
	{
	 GPIO_InitTypeDef  GPIO_InitStructure;
   GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_13;
	 GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;	
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	
   GPIO_Init(GPIOA, &GPIO_InitStructure);
	 GPIO_ResetBits(GPIOA, GPIO_Pin_13);//0V
	}
}

  这样就完美实现了不用专门的驱动芯片仅靠MCU的IO口来实现LCD屏的显示。

  这里再给大家补充一个小技巧,当IO口不够用时,我们是可以将输入和输出分时复用的,比如我的这个项目中Seg和按键检测就是部分复用

只需要在按键扫描前改为输入模式,扫描函数结束改为输出模式,并不会对效果产生很大的影响。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值