📄 lcd.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 + -