|
本帖最后由 xunke 于 2020-2-13 21:07 编辑
放假在家弄了一个nokia5110 LCD屏显示一行左移的程序,不过移动时显示有点抖并且移动得越快越抖,效果不如静态显示的,是不是这种LCD屏不合适动态显示?请有经验的网友指点下。
程序和效果图如下:
/*****************************************************************************
说明:
环境: IAR EW430 V6.50
硬件: 1) MSP430FR2433 + nokia5110 LCD模组.
2) MCU系统时钟为默认DCO=1MHz,工作电压为3.3V
3) 接口P1
4) LCD的x为0--83Px,y为0--5page 每page宽度为1字节
作者: 448254938@qq.com , 2020年02月12
*****************************************************************************/
#include "msp430fr2433.h"
#include "5110_font.h"
#define u8 unsigned char
#define u16 unsigned int
#define CMD 0 //命令标志
#define DAT 1 //数据标志
//LCD IO定义-----------------------------------------------------------
#define LCD_CLK_P0 0x01 //定义Pn.0引脚为LCD时钟IC
#define LCD_DIN_P1 0x02 //定义Pn.1引脚为LCD数据IO
#define LCD_DC_P2 0x04 //定义Pn.2引脚为LCD数据/命令选择IO
#define LCD_CE_P3 0x08 //定义Pn.3引脚为LCD传送使能IO
#define LCD_RES_P4 0x10 //定义Pn.4引脚为LCD复位IO
//--以上n为MCU的端口号,如P1口,n为1
#define LcdOut P1OUT //LCD输出端口
#define LCD_CLK_L LcdOut &(~LCD_CLK_P0) //时钟输出低电平
#define LCD_CLK_H LcdOut | LCD_CLK_P0 //时钟输出高电平,上升沿有效
#define LCD_DIN_L LcdOut &(~LCD_DIN_P1) //数据输出低电平
#define LCD_DIN_H LcdOut| LCD_DIN_P1 //数据输出高电平
#define LCD_DC_L LcdOut & (~LCD_DC_P2) //输出高电平,选择数据
#define LCD_DC_H LcdOut | LCD_DC_P2 //输出低电平,选择命令
#define LCD_CE_L LcdOut &(~LCD_CE_P3) //输出低电平,传送使能
#define LCD_CE_H LcdOut | LCD_CE_P3 //输出高电平,传送禁止
#define LCD_RES_L LcdOut &( ~LCD_RES_P4 ) //输出低电平,复位使能
#define LCD_RES_H LcdOut | LCD_RES_P4 //输出高电平,复位禁止
//定义内部函数-------------------------------------------------------------
#define CPU_F ((unsigned long)1000000)
#define Delay_ms(x) __delay_cycles((unsigned long)( CPU_F*x/1000 ))
/***********************************************************************
函数: LcdWriteByte( u8 DaFlg, u8 Dat)
入参:
(1) u8 DatFlg: 写数据标志,其值为1(DAT)则表写数据,为0(CMD)则表写命令
(2) u8 Dat: 一个字节数据/命令
返参: 无
功能: 写向LCD一个字节的数据或者命令,操作时序请见手册.
***********************************************************************/
void LcdWriteByte( u8 DatFlg, u8 Dat )
{
u8 i = 0; //为暂存变量
//判别数据还是命令--------
if( DatFlg )
{
LcdOut = LCD_DC_H; //bDatFlg=1则为数据,LCD_CD为高电平
}
else
{
LcdOut = LCD_DC_L; //bDatFlg=0则为命令,LCD_CD为低电平
}
//发送准备-----------------
LcdOut = LCD_CLK_L; //时钟信号准备,CLK->0
LcdOut = LCD_CE_L; //'0'芯片传送使能,CE为低电平
//数据输出-----------------
for( i=0; i<8; i++ ) //输出8位
{
LcdOut = LCD_CLK_L; //时钟信号准备,CLK->0
if( Dat&0x80 ) //先发最高位(MSB)
{
LcdOut = LCD_DIN_H; //-发"1"
}
else
{
LcdOut = LCD_DIN_L; //-发"0"
}
__no_operation(); //延时
LcdOut = LCD_CLK_H; //时钟上升沿有效,CLK->1
__no_operation();
Dat <<= 1; //准备发送下一位
}
LcdOut = LCD_CLK_L; //CLK->0
LcdOut = LCD_CE_H; //CE=1,芯片禁止传送
LcdOut = LCD_CLK_H; //CLK->1
LcdOut = LCD_DC_H; //DC=1
}
/*****************************************************************
函数: LcdSetXy( u8 x, u8 y )
入参:
(1) u8 x : LCD的x坐标(小写),单位Px
(2) u8 y : LCD的y坐标(小写),单位page
返参: 无
功能: 设置LCD显示的位置,x为0--83Px,y为0--5page 每page宽度为1字节
******************************************************************/
void LcdSetXy( u8 x, u8 y )
{
LcdWriteByte( CMD, 0x80|x );
LcdWriteByte( CMD, 0x40|y );
}
//****************************************************
#define LCD_WIDTH 84 //LCD宽度值,即x轴,单位px,1字节有8px
#define LCD_HEIGHT 6 //LCD高度值,即y轴,单位page,1page高度为1字节
void LcdShowRam( u8 x, u8 y, u8 width, u8 height, u8 *p )
{
u8 w=0; //用于存求宽度(x轴)的结果,小写,单位px
u8 h=0; //用于存求高度(y轴)的结果,单位page
u8 i=0; //为暂存变量
u8 d=0; //为暂存变量
u8 ww=0; //为暂存变量(小写)
//求宽(单位px)--------------
if( x > LCD_WIDTH ) //超过LCD的显示区吗?
{
x = LCD_WIDTH;
}
w = LCD_WIDTH - x;
//求高(单位page)------------
if( height&0x07 )
{
height = height + 0x08; //加8,即不满1个字节则凑足1个字节
}
h = y + ( height>>3 ); //等价为h=y+(height/8),px转page
if( h > LCD_HEIGHT ) //超过LCD的显示区吗?
{
h = LCD_HEIGHT;
}
//写数据,从左->右,从上->下----
for( i=0; y+i<h; i++ )
{
LcdSetXy( x, y+i );
ww = w;
while( ww-- )
{
d = *p++;
LcdWriteByte( DAT, d );
}
p += x;
}
}
//********************************************************
#define rLINE_NUB (16/8)
#define rROW_NUB 84
#define FONT_NUB 24
#define FONT_HEIGHT 16
u8 HzShowRam[ rLINE_NUB ][ rROW_NUB ];
u8 HzShowBuf[ FONT_NUB ];
void LcdShiftLineHz( u8 x, u8 y, u16 *p )
{
u8 i = 0;
u8 n = 0;
u16 TabLine = 0;
while( *p )
{
i = 0;
while( HzTab[0] )
{
if( *p == HzTab[0] )
{
TabLine = HzTab[1];
for( i=0; i<FONT_NUB; i++ )
{
HzShowBuf = HzFontTab_12[ TabLine ][ i ];
}
for( n=0; n<(FONT_NUB/2); n++ )
{
for( i=0; i<(rROW_NUB-1); i++)
{
HzShowRam[0] = HzShowRam[0][ i+1 ];
HzShowRam[1] = HzShowRam[1][ i+1 ];
}
HzShowRam[0][rROW_NUB-1] = HzShowBuf[0];
HzShowRam[1][rROW_NUB-1] = HzShowBuf[ FONT_NUB/2 + n ];
for( i=0; i<(FONT_NUB/2 - 1); i++ )
{
HzShowBuf[ i ] = HzShowBuf[ i+1 ];
HzShowBuf[ rROW_NUB/2 + i ] = HzShowBuf[ rROW_NUB/2 + i + 1 ];
};
//Delay_ms( 200 );
i = 3;
while( i-- )
{
LcdShowRam( x, y, rROW_NUB, FONT_HEIGHT , (u8 *)HzShowRam );
}
}
break;
}
i++;
}
p++;
}
}
void LcdInitial()
{
LcdOut = LCD_RES_L; //RES=0则复位
Delay_ms(1);
LcdOut = LCD_RES_H;
LcdWriteByte( CMD, 0x21 ); //准备发送扩展命令(CMD=1)
LcdWriteByte( CMD, 0xd0 ); //-设置Vop电压,0xd0为最佳值
LcdWriteByte( CMD, 0x20 ); //准备发送基本命令
LcdWriteByte( CMD, 0x0c ); //-设置显示模式为普通模式(b2=1,b0=0)
}
//***************************************************************************************
const u16 Hz[]={'这','里','远','比','混','乱','的','现','实','世',
'界','美','好', 1, '电','工','平','安','健','康',1,'\0'};
main( )
{
WDTCTL = WDTPW + WDTHOLD; //关闭看门狗
//所有IO为高电平输出------------------
P1DIR = 0xff; //P1口为输出模式
P2DIR = 0xff; //P2口为输出模式
P1OUT = 0xff; //P1输出高电平
P2OUT = 0xff; //P2输出高电平
PM5CTL0 &= ~LOCKLPM5; //PM5模式寄存器的LOCKLPM5=0则IO工作
//初始化LCD---------------------------
LcdInitial();
//显示一行左移的汉字-
LcdShiftLineHz(0, 0, (u16 *)Hz );
while(1 )
{
}
}
本来注释是整齐的,贴上来就不齐了。
这个gif图可能看不出具体效果,现在老家电脑没网络发视频,手机太麻烦了、眼睛又累。
字模(包含文件)请见附件 |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?注册
x
阿莫论坛20周年了!感谢大家的支持与爱护!!
如果天空是黑暗的,那就摸黑生存;
如果发出声音是危险的,那就保持沉默;
如果自觉无力发光,那就蜷伏于牆角。
但是,不要习惯了黑暗就为黑暗辩护;
也不要为自己的苟且而得意;
不要嘲讽那些比自己更勇敢的人。
我们可以卑微如尘土,但不可扭曲如蛆虫。
|