⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lcd.c

📁 个人移植的陈明计先生的small_rtos_MSP430版
💻 C
字号:
/*******************************************************************************************
**                             Copyright (c) 2005,上海琪普
**                                 All rights reserved.
**
------------------------文件信息------------------------------------------------------------
**  文件名  :	lcd.c
**  创建人  :	潘浩
**  创建日期:	2005-10-6
**  描述    :	通用模块, 定义LCD上显示数字,字符串,信息标识圆点, 以及LCD初始化,清空,测试等接口函数
**  移植性  :   开始为MSP430F427编写, 同时适用于有LCD控制器的MSP430系列单片机
**
--------------------------------------------------------------------------------------------
**
------------------------当前版本信息--------------------------------------------------------
**  当前版本:	v1.0
**  修改者  :	潘浩
**  修改日期:	2005-10-6
**
------------------------当前版本信息--------------------------------------------------------
**  当前版本:	v1.1
**  修改者  :	潘浩
**  修改日期:	2005-5-1
**	修改内容:	增加了编译开关, 使之能快速在Wisdom's LCD和标准LCD之间切换
**				当在 config.h 文件中声明 LCD_WISDOM 宏时, 使用Wisdom' LCD
**				当声明 LCD_STD 时, 使用标准LCD, 默认为标准LCD
**
--------------------------------------------------------------------------------------------
*******************************************************************************************/


#include "config.h"
#include "lcd_segment.h"
#include "lcd.h"

/******************************************************************************************/

// BCD字符段码表
const unsigned char TableBCD[] = {
	CHAR_0,
	CHAR_1,
	CHAR_2,
	CHAR_3,
	CHAR_4,
	CHAR_5,
	CHAR_6,
	CHAR_7,
	CHAR_8,
	CHAR_9,
	CHAR_A,
	CHAR_B,
	CHAR_C,
	CHAR_D,
	CHAR_E,
	CHAR_F,
	0,
	0
};

// 英文字母段码表
const unsigned char TableABC[] = {
	CHAR_a,
	CHAR_b,
	CHAR_c,
	CHAR_d,
	CHAR_e,
	CHAR_f,
	CHAR_g,
	CHAR_h,
	CHAR_i,
	CHAR_j,
	CHAR_k,
	CHAR_l,
	CHAR_m,
	CHAR_n,
	CHAR_o,
	CHAR_p,
	CHAR_q,
	CHAR_r,
	CHAR_s,
	CHAR_t,
	CHAR_u,
	CHAR_v,
	CHAR_w,
	CHAR_x,
	CHAR_y,
	CHAR_z,
	0,
	0
};

/******************************************************************************************/

// 声明本模块的局部函数

static void Char2LCD(unsigned char ch, unsigned int pos);		// 在指定位置显示一个字符
static void Bcd2LCD(unsigned int val, unsigned int pos);		// 在指定位置显示一个BCD码数字
static void Direct2LCD(unsigned int val, unsigned int pos);	// 在指定位置直接显示码值
static void SetPoint(unsigned int pos);						// 在指定的位置显示小数点
static void SetInfo(unsigned int pos);							// 在指定的位置显示信息标识圆点
static void Bin2Bcd16(unsigned char bcd[], unsigned int value);// 将16位二进制数字转换成BCD码数组
static void LCDDecu16(unsigned int value, int pos);			// 在LCD上显示16位无符号整型数据, 并在指定位置显示小数点

/********************************************************************************************
**	函数名称:	InitLCD
**	功能描述:	初始化LCD模块, 选择4MUX工作模式, 并清空LCD, S0-S15管脚被LCD模块选用, 不能再用于其它功能
**	输 入:		无
**	输 出:		无
**	全局变量:	无
**	调用模块:	无
********************************************************************************************/
void InitLCD(void)
{
	unsigned int i;

#ifdef __msp430xE42x

	LCDCTL = LCDON + LCD4MUX + LCDSG0_1;	// 使能LCD模块,选择4Mux驱动模式,S0-S15管脚被LCD模块选用
	BTCTL |= BT_fLCD_1K;						// 为LCD模块启用BasicTimer, 为LCD提供波形时钟

#endif

#ifdef __msp430x42x

	LCDCTL = LCDON + LCD4MUX + LCDSG0_1;	// 使能LCD模块,选择4Mux驱动模式,S0-S15管脚被LCD模块选用
	BTCTL |= BT_fLCD_1K;						// 为LCD模块启用BasicTimer, 为LCD提供波形时钟

#endif

#ifdef __msp430x42x0

    BTCTL |= BT_fLCD_DIV64;					// 为LCD模块启用BasicTimer, 为LCD提供波形时钟

    P5SEL = (BIT7 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0);	// 选择P5口相关管脚为LCD所用

    LCDACTL = LCDFREQ_128 | LCD4MUX | LCDSON | LCDON;	// 使能LCD模块,选择4Mux驱动模式
    LCDAPCTL0 = LCDS0 | LCDS4 | LCDS8 | LCDS12;
    LCDAPCTL1 = 0;
    LCDAVCTL0 = LCDCPEN;
    LCDAVCTL1 = 12 << 1;

#endif

	for ( i=0; i<20; i++ )
	{
		LCDMEM[i] = CHAR_NULL;		// LCDMEM1~LCDMEM20全部赋零
	}
}

/********************************************************************************************
**	函数名称:	ClearLCD
**	功能描述:	清空LCD
**	输 入:		无
**	输 出:		无
**	全局变量:	无
**	调用模块:	无
********************************************************************************************/
void ClearLCD(void)
{
	unsigned int i;

	for ( i=0; i<20; i++ )
	{
		LCDMEM[i] = CHAR_NULL;		// LCDMEM1~LCDMEM20全部赋零
	}
}

/********************************************************************************************
**	函数名称:	CheckLCD
**	功能描述:	检验LCD, 即点亮LCD所有段, 检验LCD是否正常, 一般开机时用
**	输 入:		无
**	输 出:		无
**	全局变量:	无
**	调用模块:	无
********************************************************************************************/
void CheckLCD(void)
{
	unsigned int i;

	for ( i=0; i<20; i++ )
	{
		LCDMEM[i] = CHAR_ALL;		// LCDMEM1~LCDMEM20全部赋满
	}
}

/********************************************************************************************
**	函数名称:	LCDIntOut
**	功能描述:	在LCD上显示有符号整形数据, 并在指定的位置显示小数点
**	输 入:		val - 需要显示的数值, 因LCD只有四位, 故其范围是-999~9999,
**					  越界显示-999(负越界)或9999(正越界)
**				pos - 小数点的位置, 因LCD只有四位, 故其范围是1~3,
**					  顺序从右向左(注意: 和信息指示圆点相反), 其它数值不显示小数点
**	输 出:		无
**	全局变量:	无
**	调用模块:	LCDDecu16, Direct2LCD(模块内局部函数)
********************************************************************************************/
void LCDIntOut(signed int val, unsigned int pos)
{
	unsigned int i;
	
#ifdef LCD_WISDOM	// 如果是Wisdom's LCD, 则按四位显示

	if ( val >= 0 )		// 如val是正数, 则正常显示
	{
		if ( ( val < 10000 ) && ( pos < 4 ) )
		{
			LCDDecu16(val, pos);
		}
		else
		{
			LCDDecu16(9999, pos);	// 如果val大于最大显示值9999, 则显示9999
		}
	}
	else	// 如val是负数, 则求相反数之后再显示
	{
		val = -val;

		if ( ( val < 1000 ) && ( pos < 3 ) )
		{
			LCDDecu16(val, pos);
		}
		else
		{
			LCDDecu16(999, 2);	// 如果val小于最小显示值-999, 则显示-999
		}

		for ( i=0; i<4; i++ )
		{
			if ( LCDMEM[ 3 - i ] == 0 )
			{
				Direct2LCD(CHAR_MINUS, 3 - i);	// 在最高位的左边显示负号
				break;
			}
		}
	}
	
#else	// 如果是标准LCD, 则按8位显示

	if ( val >= 0 )		// 如val是正数, 则正常显示
	{
		if ( ( val < 32768 ) && ( pos < 5 ) )
		{
			LCDDecu16(val, pos);
		}
		else
		{
			LCDDecu16(32767, pos);	// 如果val大于最大显示值32767, 则显示32767
		}
	}
	else	// 如val是负数, 则求相反数之后再显示
	{
		val = -val;

		if ( ( val < 32768 ) && ( pos < 5 ) )
		{
			LCDDecu16(val, pos);
		}
		else
		{
			LCDDecu16(32767, 2);	// 如果val小于最小显示值-32767, 则显示-32767
		}

		for ( i=0; i<6; i++ )
		{
			if ( LCDMEM[ i ] == CHAR_NULL )
			{
				Direct2LCD(CHAR_MINUS, i);	// 在最高位的左边显示负号
				break;
			}
		}
	}
	
#endif
}

/********************************************************************************************
**	函数名称:	LCDTextOut
**	功能描述:	在LCD上显示一串字符
**	输 入:		text - 需要显示的字符数组, 数组不指定长度而以'\0'结束,
**					   因LCD只有四位, 长度超过4的字符串尾部将被截
**	输 出:		无
**	全局变量:	无
**	调用模块:	Char2LCD, Direct2LCD(模块内局部函数)
********************************************************************************************/
void LCDTextOut(const unsigned char text[])
{
	unsigned int i, j, len;

	for ( i=0; text[i] != '\0'; i++ )
	{
	}
	len = i;	// 通过检测字符串结束符'\0', 求得字符串长度

#ifdef LCD_WISDOM	// 如果是Wisdom's LCD, 则按四位显示
	
	for ( i=0; i<4; i++ )
    {
        LCDMEM[i] = CHAR_NULL;
    }

	if ( len > 4 )	// 如果字符串长度大于4, 则只显示前四个字符, 截断尾部
	{
		for ( i=0; i<4; i++ )
		{
			Char2LCD(text[i], i);
		}
	}
	else	// 如果字符串长度小于4, 则将字符串的右边和LCD对齐显示, 左边补空格
	{
		for ( i=0; i<4-len; i++ )
		{
			Direct2LCD(CHAR_SPACE, i);
		}
		for ( i=4-len, j=0; i<4; i++, j++ )
		{
			Char2LCD(text[j], i);
		}
	}

#else

	for ( i=0; i<6; i++ )
    {
        LCDMEM[i] = CHAR_NULL;
    }
	
	if ( len > 4 )	// 如果字符串长度大于4, 则只显示前四个字符, 截断尾部
	{
		for ( i=0; i<4; i++ )
		{
			Char2LCD(text[i], 3 - i);
		}
	}
	else	// 如果字符串长度小于4, 则将字符串的右边和LCD对齐显示, 左边补空格
	{
		for ( i=0; i<4-len; i++ )
		{
			Direct2LCD(CHAR_SPACE, 3 - i);
		}
		for ( i=4-len, j=0; i<4; i++, j++ )
		{
			Char2LCD(text[j], 3 - i);
		}
	}

#endif
}

/********************************************************************************************
**	函数名称:	LCDCharOut
**	功能描述:	在LCD指定位置上显示指定字符
**	输 入:		pos: 字符的位置, 顺序从右向左
**	输 出:		无
**	全局变量:	无
**	调用模块:	Char2LCD(模块内部局部函数)
********************************************************************************************/
void LCDCharOut(unsigned char ch, unsigned int pos)
{
#ifdef LCD_WISDOM	// 如果是Wisdom's LCD, 则按四位显示

	if ( pos < 4 )
	{
		Char2LCD(ch, 3 - pos);
	}

#else

	if ( pos < 6 )
	{
		Char2LCD(ch, pos);
	}

#endif
}

/********************************************************************************************
**	函数名称:	LCDInfoOut
**	功能描述:	在LCD上显示当前数值的物理意义信息, 即LCD顶部的四个圆点, 具体意义视产品不同而定
**	输 入:		pos: 圆点的位置, 因LCD只有四位, 故其范围是0~3, 顺序从左向右(注意: 和小数点相反)
**	输 出:		无
**	全局变量:	无
**	调用模块:	SetInfo(模块内部)
********************************************************************************************/
void LCDInfoOut(unsigned int index)
{
	if ( index < 4 )
	{
		SetInfo(index);		// 如果index在0~3范围内, 则调用SetInfo函数显示信息标识圆点
	}
}

/*******************************************************************************************/

// 在指定位置显示一个字符
static void Char2LCD(unsigned char ch, unsigned int pos)
{
	if ( ch >= 'A' )
	{
		if ( ch >= 'a' )
		{
			ch = ch - 'a' + 'A';
		}
		if ( ch <= 'Z' )
		{
			LCDMEM[pos] = TableABC[ch - 'A'];
		}
	}
	else if ( ch >= '0' )
	{
		if ( ch <= '9' )
		{
			LCDMEM[pos] = TableBCD[ch - '0'];
		}
	}
	else if ( ch == '-' )
	{
		LCDMEM[pos] = CHAR_MINUS;
	}
}

// 在指定位置显示一个BCD码数字
static void Bcd2LCD(unsigned int val, unsigned int pos)
{
	LCDMEM[pos] = TableBCD[val];
}

// 在指定位置直接显示码值
static void Direct2LCD(unsigned int val, unsigned int pos)
{
	LCDMEM[pos] = val;
}

// 在指定的位置显示小数点
static void SetPoint (unsigned int pos)
{
	LCDMEM[pos] |= SEG_h;
}

// 在指定的位置显示信息标识圆点
static void SetInfo(unsigned int index)
{
#ifdef LCD_WISDOM	// 如果是Wisdom's LCD, 则按四位显示

	Direct2LCD( ( 0x01 << index ), 4 );

#else

	Bcd2LCD( index, 6 );

#endif
}

// 将二进制数字转换成BCD码数组
static void Bin2Bcd16(unsigned char bcd[], unsigned int value)
{
	unsigned char i;

	bcd[0] = bcd[1] = bcd[2] = bcd[3] = bcd[4] = bcd[5] = 0;	// bcd数组必须大于4个字节长度
	
	for ( i=0; value && i<6; i++, value /= 10 )
	{
		bcd[i] = value % 10;		// 从低位到高位在bcd数组中保存value的十进制表示
	}
}

// 在LCD上显示无符号整型数据, 并在指定位置显示小数点
static void LCDDecu16(unsigned int value, int pos)
{
	unsigned char BCD_array[6];
	int i;
	unsigned int cmpl_zero;	// 补零标志变量, 不为0时表示需要补零

#ifdef LCD_WISDOM	// 如果是Wisdom's LCD, 则按四位显示

	for ( i=0; i<4; i++ )
    {
		LCDMEM[i] = CHAR_NULL;
    }

	Bin2Bcd16(BCD_array, value);

	for ( i=3, cmpl_zero = 0; i>=0; i-- )
	{
		if ( ( !cmpl_zero ) && ( BCD_array[i] == 0 ) )	// 当不需要补零而BCD数组元素又为0的时候, 不予理会
		{
			if ( i == 0 )	// 除非直到最后一位都是0, 则在最后一位显示一个0
			{
				LCDMEM[3] = TableBCD[0];
			}
		}
		else	// 其它情况则正常显示, 并在显示第一个数字的时候, 将补零标志置位, 表示隔位数字间需要补零(如2005)
		{
			LCDMEM[ 3 - i ] = TableBCD[ BCD_array[i] ];
			cmpl_zero = 1;
		}
	}

	if ( ( pos > 0 ) && ( pos < 3 ) )
	{
		if ( LCDMEM[ 3 - pos ] == 0 )	// 如果小数点的位置在第一个有效数字左边, 则一直补零到小数点左边那一位
		{
			for ( i=pos; LCDMEM[ 3 - i ] == 0; i-- )
			{
				LCDMEM[ 3 - i ] = TableBCD[0];
			}

			SetPoint( 3 - pos );	// 显示小数点
		}
		else
		{
			SetPoint( 3 - pos );	// 显示小数点
		}
	}

#else

	for ( i=0; i<6; i++ )
    {
        LCDMEM[i] = CHAR_NULL;
    }

	Bin2Bcd16(BCD_array, value);

	for ( i=4, cmpl_zero = 0; i>=0; i-- )
	{
		if ( ( !cmpl_zero ) && ( BCD_array[i] == 0 ) )	// 当不需要补零而BCD数组元素又为0的时候, 不予理会
		{
			if ( i == 0 )	// 除非直到最后一位都是0, 则在最后一位显示一个0
			{
				LCDMEM[0] = TableBCD[0];
			}
		}
		else	// 其它情况则正常显示, 并在显示第一个数字的时候, 将补零标志置位, 表示隔位数字间需要补零(如2005)
		{
			LCDMEM[ i ] = TableBCD[ BCD_array[i] ];
			cmpl_zero = 1;
		}
	}

	if ( ( pos > 0 ) && ( pos < 4 ) )
	{
		if ( LCDMEM[ pos ] == CHAR_NULL )	// 如果小数点的位置在第一个有效数字左边, 则一直补零到小数点左边那一位
		{
			for ( i=pos; LCDMEM[ i ] == 0; i-- )
			{
				LCDMEM[ i ] = TableBCD[0];
			}

			SetPoint( pos );	// 显示小数点
		}
		else
		{
			SetPoint( pos );	// 显示小数点
		}
	}

#endif
}

/*******************************************************************************************/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -