SMS0658B 段式液晶显示例程

头文件:

#ifndef _SMS0658B_LCD_H_
#define _SMS0658B_LCD_H_


/*
  =========================================================================================================
	SMS0658B 段式液晶结构图:
		 ___A___
		|	    |
		F	    B
		|	    |
		 ---G---
		|	    |
		E	    C
		|___D___| . --> H
		
		例如: 如果要显示 '8', 则是 0xFE(从最高位到最低位一次是 FGEDABCH, 最低位表示小数点是 H).
		再如: 显示 '4.', 则是 0xC6 | 0x01. 所以可根据上面的段序来组合意中的数字
  =========================================================================================================
*/


//=========================================================================================================
// LCD 工作的配置信息常量
#define NOP10()	{_nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();}
#define NOP()	{NOP10(); NOP10(); NOP10(); NOP10(); NOP10(); NOP10(); NOP10(); NOP10(); NOP10(); NOP10();}


// 显示小说点的掩码, H 位
#define  DOT_MASK	0x01 
// 空白显示
#define  SPACE		table[10]
 

// 下面是针对每个 LCD 的段选地址进行常量化
#define  SEG_1	 	0
#define  SEG_2		2
#define  SEG_3 		4
#define  SEG_4 		6
#define  SEG_5 		8
#define  SEG_6		10


// LCD 序号
#define  LCD_1		1
#define  LCD_2		2
#define  LCD_3		3
#define  LCD_4		4


//=========================================================================================================
// 接口声明
// 液晶显示控制器进入睡眠模式以减少功耗
void LCD_Sleep(unsigned char n);

// LCD 初始化, 复位
void LCD_Reset(unsigned char n); 

// LCD 频率显示函数
void LCD_Display_FRQ(unsigned int  num, unsigned char n);

#endif 


 

C文件:

#include <c8051f120.h>
#include <intrins.h>
#include "SMS0658B_LCD.h"

//=========================================================================================================
// 控制命令字
#define CMDOFF 		0x00
#define CMDON 		0x01
#define CMDLCDOFF 	0x02
#define CMDLCDON 	0x03
#define CMDB3C4 	0x29


//SMS0658B 引脚说明
//PIN1: CS  	[片选信号输入]
//PIN2: CLK 	[串行移位脉冲输入]
//PIN3: DI  	[串行数据输入]
//PIN4: VSS	[电源地]	
//PIN5: VDD	[电源正极]

// 1 <= n <= 4
#define CS_SET(n)    	(P4 |= 1 << n)		// 设置某位置高
#define CS_CLR(n)    	(P4 &= ~(1 << n))	// 清零某位置低
#define CS_FALLING_EDGE(n) {CS_SET(n); NOP(); NOP();  CS_CLR(n); NOP();  NOP(); } // 第 n 位引脚下降沿产生

// 数据和串行时钟引脚
sbit DIPIN  = P0^5;
sbit CLKPIN = P0^6;	

// 			       0     1     2	 3     4     5     6	 7     8     9    空白    -
unsigned char code table[] = {0xBE, 0x06, 0x7C, 0x5E, 0xC6, 0xDA, 0xFA, 0x0E, 0xFE, 0xCE, 0xBE,  0x40};


//=========================================================================================================
// 送入 1 位数据到 LCD 显示控制器
static void Trans_Bit(bit bit_data)
{
	DIPIN = bit_data;	// 送入数据到串行输入口 DI
	NOP(); 
	CLKPIN = 1;		// 时钟端口发送一个负脉冲
	NOP(); 
	CLKPIN = 0;
	NOP(); 			// 延时一会儿
	CLKPIN = 1;
}




//=========================================================================================================
// 送控制字到液晶显示控制器
// 参数: n表示选中的 LCD 序号
static void LCD_WC(unsigned char cmd, unsigned char n)
{
	unsigned char i = 0;
	// 参数检查
	if (n > 4 || n < 1) {
		return ; // LCD 序号错误
	}
	
	CS_FALLING_EDGE(n); // CS 先产生下降沿
	Trans_Bit(1);	// 连续送入数据 100b 后再送入控制命令
	NOP(); 
	Trans_Bit(0);
	NOP();  
	Trans_Bit(0);
	NOP(); 
	
	for (i = 0; i < 8; i++) {  
		if((cmd & 0x80) == 0x80) {
			Trans_Bit(1);
		}
		else {
			Trans_Bit(0);
		}
		cmd <<= 1; 
		NOP(); 
	}

	Trans_Bit(0);
	NOP(); 
	
	DIPIN = 1;
	CS_SET(n);	// 送完后将对应的 LCD 片选端置高
}


//=========================================================================================================
void LCD_Reset(unsigned char n) 
{
	// 参数检查
	if (n > 4 || n < 1) {
		return ; // LCD 序号错误
	}
	LCD_WC(CMDOFF, n);    	    // 掉电             
	LCD_WC(CMDLCDOFF, n);       // 关闭 
	LCD_WC(CMDON, n);           // 上电
	LCD_WC(CMDLCDON, n);        // 显示
	LCD_WC(CMDB3C4, n);         // 模式设置

}



//=========================================================================================================
// 液晶显示控制器进入睡眠模式减少功耗
// 参数: n 表示将对应的 LCD 设为睡眠状态
void LCD_Sleep(unsigned char n)
{
	// 参数检查
	if (n > 4 || n < 1) {
		return ; // LCD 序号错误
	}
	LCD_WC(CMDLCDOFF, n); 	// 关闭液晶显示
	LCD_WC(CMDOFF, n);	// 进入睡眠状态, 此时 LCD 控制器电流小于 1uA
}



//=========================================================================================================
// 发送 1 字节数据到液晶显示控制器
static void Trans_data(unsigned char address, unsigned char Byte_data, unsigned char n)
{
	unsigned char i;
	
	// 参数检查
	if (n > 4 || n < 1) {
		return ; // LCD 序号错误
	}	
	
	CS_SET(n);
	NOP(); 
	CS_CLR(n);
	
	Trans_Bit(1);
	NOP();  
	Trans_Bit(0);
	NOP(); 
	Trans_Bit(1);
	NOP(); 
	
	// 地址处理
	address <<= 2;
	for (i = 0; i < 6; i++) {
		if ((address & 0x80) == 0x80) {
			Trans_Bit(1);
		}
		else {
			Trans_Bit(0);
		}
		address <<= 1;
		NOP(); 
	}
	
	// 送数据
	for (i = 0; i < 8; i++) {	
		if ((Byte_data & 0x01) == 0x01) {
			Trans_Bit(1);
		}
		else {
			Trans_Bit(0);
		}
		Byte_data >>= 1;
		NOP(); 
	}
	
	DIPIN = 1;
	CS_SET(n);
}



//=========================================================================================================
// LCD 频率显示函数, 高位为零时显示空白, 其余正常显示 0
// 参数: freq 表示将要显示的频率值, n 表示送入第几个 LCD 显示.
// 输出: 无
// 注意: 如果, 将此函数放到定时中断内进行处理, 可能需要点时间, 影响其他操作的实时性. 所以, 尽量将
// 	 定时器中断频率降低, 不影响
void LCD_Display_FRQ(unsigned int  freq, unsigned char n)
{
	// 参数检查
	if (n > 4 || n < 1) {
		return ; // LCD 序号错误
	}
	
	if (freq > 137 || freq < 118) {
		return ; // 频率超出界限, 根据设置而定
	}
	
	switch (n) {
	case 1:
		Trans_data(SEG_1,  table[0],  LCD_1);			 // 最低三位为精度根据情况, 暂时定为 0
		Trans_data(SEG_2,  table[0],  LCD_1);
		Trans_data(SEG_3,  table[0],  LCD_1);
	
		Trans_data(SEG_4,  table[freq % 10] | DOT_MASK,  LCD_1); // 取个位显示, 后缀小数点
		Trans_data(SEG_5,  table[freq / 10 % 10],  LCD_1);	 // 取十位显示
		Trans_data(SEG_6,  table[freq / 100], LCD_1);
		break;
	case 2:
		Trans_data(SEG_1,  table[0],  LCD_2);			 // 最低三位为精度根据情况, 暂时定为 0
		Trans_data(SEG_2,  table[0],  LCD_2);
		Trans_data(SEG_3,  table[0],  LCD_2);
	
		Trans_data(SEG_4,  table[freq % 10] | DOT_MASK,  LCD_2); // 取个位显示, 后缀小数点
		Trans_data(SEG_5,  table[freq / 10 % 10],  LCD_2);	 // 取十位显示
		Trans_data(SEG_6,  table[freq / 100], LCD_2);
		break;
	case 3:
		Trans_data(SEG_1,  table[0],  LCD_3);			 // 最低三位为精度根据情况, 暂时定为 0
		Trans_data(SEG_2,  table[0],  LCD_3);
		Trans_data(SEG_3,  table[0],  LCD_3);
	
		Trans_data(SEG_4,  table[freq % 10] | DOT_MASK,  LCD_3); // 取个位显示, 后缀小数点
		Trans_data(SEG_5,  table[freq / 10 % 10],  LCD_3);	 // 取十位显示
		Trans_data(SEG_6,  table[freq / 100], LCD_3);
		break;
	case 4:
		Trans_data(SEG_1,  table[0],  LCD_4);			 // 最低三位为精度根据情况, 暂时定为 0
		Trans_data(SEG_2,  table[0],  LCD_4);
		Trans_data(SEG_3,  table[0],  LCD_4);
		Trans_data(SEG_4,  table[freq % 10] | DOT_MASK,  LCD_4); // 取个位显示, 后缀小数点
		Trans_data(SEG_5,  table[freq / 10 % 10],  LCD_4);	 // 取十位显示
		Trans_data(SEG_6,  table[freq / 100], LCD_4);
		break;
	default:
		return;
	}
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值