段码LCD屏幕的应用,常见的有使用STC8H4K32TLCD或者TM1621B驱动

解释一下为什么不能直接使用单片机管脚驱动段码LCD屏,因为需要输出四种的电平才能控制。一般单片机管脚就输出置0或者置1   也就是0V或者 5V(3.3V)

1.使用单片机直接驱动

STC8H4K32TLCD这款单片机自带驱动段码LCD屏幕的外设功能。可以参考STC8H手册

下面解释一下LCD外设寄存器的功能

P_SW2 |= 0x80;        // 使用过STC单片机的都知道需要使能才可以修改

LCDCFG  = 0x00 + 7;    // 0x00:选择CPU时钟为LCD时钟, 0x80: 选择内部27M时钟. VLCD电压选择0~7对应0.65+VLCD*0.05.

LCD 时钟源选择内部高速 IRC

段码LCD驱动直接选择使用单片机供电电压输出

死区保护寄存器只有3位bit数据 范围 0~7

段码LCD刷新的频率一共20位bit数据 L低八位 M中8位 H高四位 刷新频率为60HZ的时候效果比较好

COMLENM    = 0xDB;        // COM时间长度设置 中字节COMLEN[15:8]    LCD刷新率 = LCD时钟频率 / ((DBLEN[2:0]+COMLEN[19:0]+1) *2 * COM数)
    COMLENL    = 0xB9;        // COM时间长度设置 低字节COMLEN[7:0]    LCD刷新率 = 27000000/((52649+1)*2*4) = 60Hz
    BLINKRATE = 60;        // 闪烁率配置寄存器, LCD闪烁率 = LCD刷新率 / BLINKRATE[7:0] Hz

LCDCFG2没有使用到7以上的管脚默认为0 。

闪烁率配置寄存器BLINKRATE 在配置为闪缩模式下才能使用

void	LCD_config(void)
{


	P_SW2 |= 0x80;		// 使能 才可以修改
	LCDCFG  = 0x00 + 7;	// 0x00:选择CPU时钟为LCD时钟, 0x80: 选择内部27M时钟. VLCD电压选择0~7对应0.65+VLCD*0.05.
	DBLEN   = 2;		// 设置LCD显示时的死区时间长度, 取值0~7.
	COMLENH	= 0;		// COM时间长度设置 高字节COMLEN[19:16],  一共20bit.
	COMLENM	= 0xDB;		// COM时间长度设置 中字节COMLEN[15:8]	LCD刷新率 = LCD时钟频率 / ((DBLEN[2:0]+COMLEN[19:0]+1) *2 * COM数)
	COMLENL	= 0xB9;		// COM时间长度设置 低字节COMLEN[7:0]	LCD刷新率 = 27000000/((52649+1)*2*4) = 60Hz
	BLINKRATE = 60;		// 闪烁率配置寄存器, LCD闪烁率 = LCD刷新率 / BLINKRATE[7:0] Hz

	COMON  = 0x0F;		// COM使能寄存器
	SEGON1 = 0xF0;		// SEG线使能寄存器1, SEG7~SEG0
	SEGON2 = 0xFF;		// SEG线使能寄存器2, SEG15~SEG8
	SEGON3 = 0xFF;		// SEG线使能寄存器3, SEG23~SEG16
	SEGON4 = 0xFF;		// SEG线使能寄存器4, SEG31~SEG24
	SEGON5 = 0x00;		// SEG线使能寄存器5, SEG39~SEG32
	
	
	 P0M0&=~0xFF;P0M1|=0xFF; //高祖输入
	 P1M0&=~0x03;P1M1|=0x03; //高祖输入
	 P2M0=0x00;P2M1=0xFF;    //高祖输入
	 P3M0&=~0xE0;P3M1|=0xE0; //高祖输入
	 P4M0&=~0xFE;P4M1|=0xFE;//高祖输入
	 P5M0&=~0x0F;P5M1|=0x0F; //高祖输入
	
//	LCDCFG2 = 0x0f;			// SEG0~3切换到P7.7~7.4	
	

C0SEGV0 = 0x00 ; //清除显示内容
C0SEGV1 = 0x00 ;
C0SEGV2 = 0x00 ;
C0SEGV4 = 0x00 ; //清除显示内容
C1SEGV0 = 0x00 ; //清除显示内容
C1SEGV1 = 0x00 ;
C1SEGV2 = 0x00 ;
C1SEGV4 = 0x00 ; //清除显示内容
C2SEGV0 = 0x00 ; //清除显示内容
C2SEGV1 = 0x00 ;
C2SEGV2 = 0x00 ;
C2SEGV4 = 0x00 ; //清除显示内容
C3SEGV0 = 0x00 ; //清除显示内容
C3SEGV1 = 0x00 ;
C3SEGV2 = 0x00 ;
C3SEGV4 = 0x00 ; //清除显示内容

	LCDCR = (0<<1) + 1;	// LCD控制寄存器, 0:普通模式, 1:长暗模式, 2:长亮模式, 3:闪烁模式.  +0:禁止LCD模块,  +1:允许LCD模块.
}

    COMON  = 0x0F;        // COM使能寄存器 使用四个公共端


    SEGON1 = 0xF0;        // SEG线使能寄存器1, SEG7~SEG0
    SEGON2 = 0xFF;        // SEG线使能寄存器2, SEG15~SEG8
    SEGON3 = 0xFF;        // SEG线使能寄存器3, SEG23~SEG16
    SEGON4 = 0xFF;        // SEG线使能寄存器4, SEG31~SEG24
    SEGON5 = 0x00;        // SEG线使能寄存器5, SEG39~SEG32   使用到多少使能多少

     P0M0&=~0xFF;P0M1|=0xFF; //高祖输入
     P1M0&=~0x03;P1M1|=0x03; //高祖输入
     P2M0=0x00;P2M1=0xFF;    //高祖输入
     P3M0&=~0xE0;P3M1|=0xE0; //高祖输入
     P4M0&=~0xFE;P4M1|=0xFE;//高祖输入
     P5M0&=~0x0F;P5M1|=0x0F; //高祖输入

使用的驱动管脚都设置为高阻输入

段码LCD的管脚图片

驱动电路图管脚使用如下

code uint8_t seg7code[ ]={//显示段码 数码管字跟 
0x3f,	//0
0x06,	//1
0x5b,	//2
0x4f,	//3
0x66,	//4
0x6d,	//5
0x7d,	//6
0x07,	//7
0x7f,	//8
0x6f,	//9
0x77,	//A	10  
0x7c,	//b	11
0x39,	//c	12
0x5e,	//d	13
0x73,	//P	14
0x40,	//_NET	15
0x00,	//_TAP  16
0x79,  //E 17
0x71,  //F 18	
0xc0,  //19
0x5C,  //o 20 
0x54,  /n 21
0x01,  //22 
0x02,  //23
0x04,  //24
0x08,  //25
0x10,  //26
0x20,  //27	
0x3E,  //28 U
0x76,  //29 H
0x38,  //30 L
};

uint8_t  LCD_Show_buff[4][4] = 0;
void Led(uint8_t  a,uint8_t b,uint8_t c,uint8_t d)
{	
	
 
 if(seg7code[a] & 0x01 ) 
   LCD_Show_buff[3][1] |= 0x02;
 else  
  LCD_Show_buff[3][1] &= ~0x02;		//com4	   9

if(seg7code[a] & 0x20 )   
 LCD_Show_buff[2][1] |= 0x02;
else  
 LCD_Show_buff[2][1] &= ~0x02;		//com3	

if(seg7code[a] & 0x10 )   
  LCD_Show_buff[1][1] |= 0x02;
else  
 LCD_Show_buff[1][1] &= ~0x02;		//com2	
				
if(seg7code[a] & 0x08 )   
  LCD_Show_buff[0][1] |= 0x02;
else 
 LCD_Show_buff[0][1] &= ~0x02;		//com1	
		 
 if(seg7code[a] & 0x02 )  
 LCD_Show_buff[3][1] |= 0x01;
else  
  LCD_Show_buff[3][1] &= ~0x01;		//com4		 8

if(seg7code[a] & 0x40 ) 
  LCD_Show_buff[2][1] |= 0x01;
else  
  LCD_Show_buff[2][1] &= ~0x01;		//com3	

if(seg7code[a] & 0x04 )   
  LCD_Show_buff[1][1] |= 0x01;
else  
  LCD_Show_buff[1][1] &= ~0x01;		//com2	
				
//if(f_flag  >=5 )   
//  LCD_Show_buff[0][1] |= 0x02;
//else 
// LCD_Show_buff[3][1] &= ~0x02;			  //com1	
		

			 
	

  C0SEGV0 = LCD_Show_buff[0][0];    
  C0SEGV1 = LCD_Show_buff[0][1];    
  C0SEGV2 = LCD_Show_buff[0][2];    
  C0SEGV3 = LCD_Show_buff[0][3];    
	
  C1SEGV0 = LCD_Show_buff[1][0];    
  C1SEGV1 = LCD_Show_buff[1][1];    
  C1SEGV2 = LCD_Show_buff[1][2];    
  C1SEGV3 = LCD_Show_buff[1][3];    
	
  C2SEGV0 = LCD_Show_buff[2][0];    
  C2SEGV1 = LCD_Show_buff[2][1];    
  C2SEGV2 = LCD_Show_buff[2][2];    
  C2SEGV3 = LCD_Show_buff[2][3];    
	
  C3SEGV0 = LCD_Show_buff[3][0];    
  C3SEGV1 = LCD_Show_buff[3][1];    
  C3SEGV2 = LCD_Show_buff[3][2];    
  C3SEGV3 = LCD_Show_buff[3][3];    


}

解释一下段码LCD显示代码

就解释一个数码管,显示其他的原理一样的。

比如第一个数码显示大写A,那么数码管的八段显示值是0x77;

对应段码LCD的管脚图显示A,那么 

COM1 1D 和P1为0

CO2M 1E 和1C为1

COM3 1F 和1G为1

COM4 1A 和1B为1

对应驱动电路图驱动第一个数显的管脚是EG9和EG8

C0S9和C0S8为0   对应的 C0SEGV1 &=~0X03;

C1S9和C1S8为1  对应的 C1SEGV1 |=0X03;

C2S9和C0S8为1  对应的 C2SEGV1 |=0X03;

C3S9和C0S8为1  对应的 C3SEGV1 |=0X03;

写入LCD数据寄存器即可显示出大写A字母

2.考虑单片机成本,管脚紧凑的情况下可以选择TM1621B驱动

TM1621B的手册可以去半导小芯免费查看

TM1621B的驱动就不多讲自己看手册

#ifndef _TM1621_B_H_
#define _TM1621_B_H_

#include "main.h"

sbit HT1621_CS     = P5^4; 
sbit HT1621_DAT    = P1^6;
sbit HT1621_WR     = P1^7; 
sbit HT1621_RD     = P1^0;

#define HT1621_CS_H   HT1621_CS  = 1  
#define HT1621_CS_L   HT1621_CS  = 0
#define HT1621_DAT_H  HT1621_DAT = 1 
#define HT1621_DAT_L  HT1621_DAT = 0
#define HT1621_WR_H   HT1621_WR  = 1 
#define HT1621_WR_L   HT1621_WR  = 0
#define HT1621_RD_H   HT1621_RD  = 1
#define HT1621_RD_L   HT1621_RD  = 0

#define  	TEST_NET    12
#define  	DELAY_TEST  1	
#define  	COMMAND_CODE                0x80  //命令码---100
#define  	WRITE_DATA_CODE             0xA0  //写命令---101
#define  	READ_DATA_CODE              0xC0  //读命令---110
#define		SYSDIS 					0X800   //0B 1000 0000 000X  关振荡器和LCD偏压发生器
#define 	SYSEN 					0X802   //0B 1000 0000 001X  打开系统振荡器
#define 	LCD_OFF 				0X804   //0B 1000 0000 010X  关LCD偏压
#define 	LCD_ON 					0x806   //0B 1000 0000 011X  开LCD偏压
#define 	TIMERDIS 				0x808   //0B 1000 0000 100X  时基输出失效
#define 	WDTDIS					0X80A   //0B 1000 0000 101X  WDT溢出标志输出失效
#define 	TIMEREN 				0X80C   //0B 1000 0000 110X  时基输出使能
#define 	WDTEN 					0X80E   //0B 1000 0000 111X  WDT溢出标志输出有效
#define 	TONE_OFF				0X810   //0B 1000 0001 000X  关闭声音输出
#define 	TONE_ON 				0X812   //0B 1000 0001 001X  打开声音输出
#define 	CLRTIMER 				0X818   //0B 1000 0001 100X  时基发生器清零
#define 	CLRWDT 					0X81C   //0B 1000 0001 110X  清除WDT状态
#define 	XTAL_32K 				0X828   //0B 1000 0010 100X  系统时钟源,晶振
#define 	RC256 					0X830   //0B 1000 0011 000X  系统时钟源,片内RC
#define 	EXT256 					0X838   //0B 1000 0011 100X  系统时钟源,外部时钟源
																											 
#define 	BIAS1_2_2COM		0X840   //0B 1000 0100 000X 	LCD 1/2偏压选项,2个公共口 
#define 	BIAS1_2_3COM		0X848   //0B 1000 0100 100X 	LCD 1/2偏压选项,3个公共口
#define 	BIAS1_2_4COM		0X850   //0B 1000 0101 000X 	LCD 1/2偏压选项,4个公共口
																											 
#define 	BIAS1_3_2COM		0X842   //0B 1000 0100 001X 	LCD 1/3偏压选项,2个公共口 
#define 	BIAS1_3_3COM		0X84A   //0B 1000 0100 101X 	LCD 1/3偏压选项,3个公共口
#define 	BIAS1_3_4COM		0X852   //0B 1000 0101 001X 	LCD 1/3偏压选项,4个公共口
																											 
#define 	TONE4K 				0X880   //0B 1000 1000 000X  声音频率4K
#define 	TONE2K				0X8C0   //0B 1000 1100 000X  声音频率2K
#define 	IRQ_DIS 			0X900   //0B 1001 0000 000X  使/IRQ输出失效
#define 	IRQ_EN				0X910   //0B 1001 0001 000X  使/IRQ输出有效
#define     BIAS                0x852   //0b 1000 0101 0010  1/3duty 4com

void Write_Data(uint cmd);
void Write_Cmd(uint Data);
void LCD_Init(void);
void LCD_Clear(void);

void HT1621_WriteData(uchar addr,uchar sdat);
void HT1621_SendCmd(uchar command);
void HT1621_SendBit(uchar sdat,uchar cnt);
void HT1621_WriteData_much(uchar addr,uchar*sdat,uchar num );  //写多个数据
#endif

#include "main.h"

void HT1621_Delay(uint time_delay)	//@27.000MHz US
{
	while (time_delay--);
}

/*********************************************************
函数名:LCD_Init(void)
返回值:无
功  能:LCD初始化
*********************************************************/
void Write_Cmd(uint Cmd)
{
	uint8_t  i;	
	HT1621_CS_L;
		
	for(i=0;i<12;i++)
	{
		if(Cmd & 0x800)
		{
			HT1621_DAT_H;
		}
		else
		{
			HT1621_DAT_L;	
		}
		HT1621_Delay(DELAY_TEST);
		HT1621_WR_L;
		HT1621_Delay(DELAY_TEST);
		HT1621_WR_H;
		HT1621_Delay(DELAY_TEST);
		Cmd<<=1;	
	}
	HT1621_CS_H;	
}

void HT1621_SendBit(uint8_t sdat,uint8_t cnt)
{
		uint8_t i=0;
		for(i=0;i<cnt;i++)
		{
				HT1621_WR_L;
				HT1621_Delay(DELAY_TEST);
				if(sdat&0x80)
				{
						HT1621_DAT_H; 
				}
				else
				{
						HT1621_DAT_L;
				}
				HT1621_Delay(DELAY_TEST);
				HT1621_WR_H;
				HT1621_Delay(DELAY_TEST);
				sdat<<=1;
		}
}

void HT1621_WriteData(uint8_t addr,uint8_t sdat)  //写单个数据
{
		addr<<=2;//因为地址是6位的
		sdat<<=4;//数据是4位
		HT1621_CS_L;
		HT1621_SendBit(0xa0,3);//1010
		HT1621_SendBit(addr,6);
		HT1621_SendBit(sdat,4);		//一次只发送4位数据,一个地址发送1次,低四位
		//HT1621_SendBit(sdat,8);
		HT1621_CS_H;
}

void LCD_Clear(void)
{
	uint8_t i;
	
	for(i=13;i<29;i++)
	{
			HT1621_WriteData(i,0x00);
	}
	HT1621_WriteData(30,0x00);
	HT1621_WriteData(31,0x00);
}


void LCD_Init(void)
{
  Write_Cmd(RC256);           //系统时钟源,片内RC
  HT1621_Delay(15);
  Write_Cmd(TONE_OFF);        //关闭声音输出
  HT1621_Delay(15);
  Write_Cmd(WDTDIS);          //WDT溢出标志输出失效  
  HT1621_Delay(15);         
  Write_Cmd(LCD_ON);          //开LCD偏压 	          
  Write_Cmd(SYSEN);           //打开系统振荡器
  HT1621_Delay(15);	
  Write_Cmd(BIAS1_3_4COM);     //0B 1000 0101 001X 	LCD 1/3偏压选项,4个公共口      
}

驱动硬件电路如下  只需要使用三根管脚即可驱动段码LCD

段码LCD管脚图

段码LCD的第一个数字显示跟TM1621B对应的管脚SEG30和SEG29对应

SEG31跟SEG30写入数据即可显示第一个字母

uint8_t segbuff1(uint8_t dat) //根据段码LCD管脚图数据转化出来的对应TM1621B数码
{
   uint8_t buff=0;	
   if(dat&0x01)buff|=0x80;
   if(dat&0x02)buff|=0x08;
   if(dat&0x04)buff|=0x02;
   if(dat&0x08)buff|=0x10;
   if(dat&0x10)buff|=0x20;
   if(dat&0x20)buff|=0x40;
   if(dat&0x40)buff|=0x04;
   if(dat&0x80)buff|=0x01;		
   return buff;
}
void Led(uchar a,uchar b,uchar c,uchar d,uchar e,uchar f,uchar g,uchar h )
{	
	
	uchar show_data = 0 ; 
	

	if(f_flag == 4) //显示数码管小数点
      HT1621_WriteData(30,segbuff1(seg7code[a]|0x80)>>4);
    else HT1621_WriteData(30,segbuff1(seg7code[a])>>4);

	if(f_flag == 4)
      HT1621_WriteData(29,segbuff1(seg7code[a]|0x80));
   else 
    HT1621_WriteData(29,segbuff1(seg7code[a]));

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值