基于ATmega128的LCD12864画图(画点,画线,画矩形等) 先上图:
程序:
文件结构:
---------------- _main.c ---------------
/*
* 基于 ATmega128 的 LCD12864 画图显示实验
* 16MHz
* 编译器: ICCAVR
* 已测试通过
* by Qin Zhengye
* 2011-08-07
*/
/*
* 硬件接口: LCD_DATA -> PE
* RS -> PB0
* RW -> PB1
* EN -> PB2
*/
#include "my_include.h"
#include "LCD12864_graphics.h"
void main()
{
Port_init(); // 端口初始化
LCD12864_init();
_delay_ms( 5 ); // 要等待液晶初始化完毕
LCD12864_string( 0, 0, "液晶" ); // 写入内容
LCD12864_string( 1, 0, "被屏蔽的号码" ); //
LCD12864_string( 0, 6, "画点");
LCD12864_clear(); // 图形模式的清屏
LCD12864_dot( 36, 0, 8, 1 ); // 在 ( 36, 8 ) 处画点 ( 0无用, 看定义函数前的说明 )
LCD12864_line( 90, 8, 39, 8, 1 ); // 箭头的形状
LCD12864_dot( 40, 0, 7, 1 );
LCD12864_dot( 40, 0, 9, 1 );
LCD12864_dot( 41, 0, 6, 1 );
LCD12864_dot( 41, 0, 10, 1 );
LCD12864_line( 30, 60, 116, 20, 1 );
LCD12864_bar( 90, 45, 110, 60, 1 );
LCD12864_rectangle( 9, 34, 40, 62, 1 );
}
------------ LCD12864_basic.h -------------
/*
* LCD12864驱动程序----basic
* 此头文件有LCD12864的基本的写指令数据
* for ATmega128
* 16MHz
* 编译器: ICCAVR
* 已测试通过
* by Qin Zhengye
*/
/* 宏定义要用到的函数( 没用到可以注释掉, 以减小目标程序的大小 )
*/
//#define __KEY_scanf
#define __LCD12864_string
/*
* define functions
*/
void LCD12864_init( void );
void LCD12864_cmd ( unsigned char cmd );
void LCD12864_dat ( unsigned char dat );
void LCD12864_string( unsigned char Y, unsigned char X, unsigned char *table );
void check_busy( void );
unsigned char KEY_scanf( void );
/*
* 定义硬件接口( 只接 8数据 + 3控制 + 2电源根线 )
* RS 0-command; 1-data
* RW 0-write ; 1-read
* EN 1-input ; 1->0 action
*/
#define LCD_IN PINE
#define LCD_DDR DDRE
#define LCD_OUT PORTE
#define KEY_IN PIND
#define KEY_OUT PORTD
#define KEY_DDR DDRD
#define BUSY ((LCD_IN & 0x80) != 0)
#define RS_COMD ( PORTB &= ~(0x01 << 0) )
#define RS_DATA ( PORTB |= (0x01 << 0) )
#define RW_WRITE ( PORTB &= ~(0x01 << 1) )
#define RW_READ ( PORTB |= (0x01 << 1) )
#define EN_SET ( PORTB |= (0x01 << 2) )
#define EN_CLR ( PORTB &= ~(0x01 << 2) )
/* 键盘扫描
* 电路无需电阻,高效行列版
*
* 键盘布局:
*
* D3 D2 D1 D0
* | | | |
* D4-- 0 1 2 3
* D5-- 4 5 6 7
* D6-- 8 9 A B
* D7-- C D E F
*
* 说明: 键盘没有按下则返回0, 按下返回对应键值 */
#ifdef __KEY_scanf
unsigned char KEY_scanf( void )
{
uchar temp;
KEY_DDR = 0x0F;
KEY_OUT = 0xF0;
_delay_ms( 4 );
if( (temp = KEY_IN) != 0xF0 )
{
KEY_DDR = 0xF0;
KEY_OUT = 0x0F;
_delay_ms( 1 );
temp = temp | KEY_IN;
switch( temp )
{
case 0xE7: return '0';
case 0xEB: return '1';
case 0xED: return '2';
case 0xEE: return '3'; // 第一行
case 0xD7: return '4';
case 0xDB: return '5';
case 0xDD: return '6';
case 0xDE: return '7'; // 第二行
case 0xB7: return '8';
case 0xBB: return '9';
case 0xBD: return 'A';
case 0xBE: return 'B'; // 第三行
case 0x77: return 'C';
case 0x7B: return 'D';
case 0x7D: return 'E';
case 0x7E: return 'F'; // 第四行
}
}
return 0;
}
#endif
/* LCD12864初始化*/
void LCD12864_init( void )
{
LCD12864_cmd( 0x30 ); // 基本指令, 字符模式LCD12864_cmd( 0x06 );
LCD12864_cmd( 0x0C ); //
LCD12864_cmd( 0x01 ); // 清屏
LCD12864_cmd( 0x80 );
}
/* 写8位的命令*/
void LCD12864_cmd( unsigned char cmd )
{
check_busy();
RW_WRITE;
LCD_OUT = cmd;
_delay_us( 1 ); // 出现乱码请加长延时时间
EN_CLR;
}
/* 写8位的数据*/
void LCD12864_dat( unsigned char dat )
{
check_busy();
RS_DATA;
RW_WRITE;
LCD_OUT = dat;
_delay_us( 1 ); // 出现乱码请加长延时时间
EN_CLR;
}
/*
* 写字符串
* Y 取值 ( 0 ~ 3 )
* X 取值 ( 0 ~ 7 )
* table: 要显示的字符串的指针
*/
#ifdef __LCD12864_string
void LCD12864_string( unsigned char Y, unsigned char X, unsigned char *table )
{
unsigned char i;
switch( Y )
{
case 0: LCD12864_cmd( 0x80 + X ); break;
case 1: LCD12864_cmd( 0x90 + X ); break;
case 2: LCD12864_cmd( 0x88 + X ); break;
case 3: LCD12864_cmd( 0x98 + X ); break;
default: return ;
}
for( i = 0; table[i] != '\0'; i++ )
LCD12864_dat( table[i] );
}
#endif
/* 检查忙*/
void check_busy( void )
{
uchar n = 200; // 控制时间, 时间过长强制退出
LCD_OUT = 0xFF;
RS_COMD;
RW_READ;
EN_SET;
//_delay_us( 10 );
while( BUSY == 1 && --n > 0 );
}
----------- LCD12864_graphics.h -------------
/*
* LCD12864驱动程序----graphics
* 此头文件有LCD12864的图形模式下的
* 清屏, 画 320 * 240 的图画,
* 读指定位置的内容, 画点, 画线, 画矩形框,
* 填充矩形
* for ATmega128
* 16MHz
* 编译器: ICCAVR
* 已测试通过
* by Qin Zhengye
*/
/* 注意: 本人用ICCAVR作编译器, 发现下面的 "LCD12864_dot" 函数的参数有问题
* 定义成 "LCD12864_dot ( unsigned char X, unsigned char Y, unsigned char color )"
* 当第一个实参 "X" 是浮点数时, 发现传给第二个参数 "Y" 的值会跟传给 "X" 的数值一样
* 所以下面在两者之间插入一个参数, 调用时多写一个数就没事了. 如果你知道解决办法麻烦QQ通知一声 :)
*/
/*
* 宏定义要用到的函数( 没用到可以注释掉, 以减小目标程序的大小 )
* 函数具体内容看下面
*/
#define __LCD12864_clear
#define __LCD12864_next
#define __LCD12864_read_8
#define __LCD12864_read_16
#define __LCD12864_dot
#define __LCD12864_line
#define __LCD12864_bar
#define __LCD12864_rectangle
#define __LCD12864_whole_line
//#define __LCD12864_BMP
/*
* 声明函数
*/
void LCD12864_clear( void );
void LCD12864_next ( void );
void LCD12864_dot ( unsigned char X, unsigned char DB_X, unsigned char Y, unsigned char color );
void LCD12864_line( unsigned char X0, unsigned char Y0, unsigned char X1, unsigned char Y1, unsigned char color );
void LCD12864_bar ( unsigned char left, unsigned char up, unsigned char right, unsigned char down, unsigned char color );
void LCD12864_rectangle ( unsigned char left, unsigned char up, unsigned char right, unsigned char down, unsigned char color );
void LCD12864_whole_line( unsigned char Y, unsigned char color ); void LCD12864_BMP( unsigned char *table );
unsigned char LCD12864_read_8( void );
unsigned int LCD12864_read_16( void );
/* 包含基本的函数*/
#include "LCD12864_basic.h"
/* 图形模式的清屏*/
#ifdef __LCD12864_clear
void LCD12864_clear( void )
{
unsigned char i,j;
LCD12864_cmd( 0x34 ); // 关图形模式的显示
for( i = 0; i < 32; i++ )
{
LCD12864_cmd( 0x80 + i );
LCD12864_cmd( 0x80 );
for( j = 0; j < 32; j++ )
LCD12864_dat( 0x00 );
}
LCD12864_cmd( 0x36 ); // 开图形模式的显示
}
#endif
/* 编辑位置移到下一个8位
* 可以移到低8位单独编辑内容
*/
#ifdef __LCD12864_next
void LCD12864_next( void )
{
uchar n = 100;
RS_COMD;
RW_READ;
EN_SET;
while( BUSY == 1 && --n > 0 );
RS_DATA;
EN_CLR;
}
#endif
/* 从LCD12864读数据
* 注意: LCD12864的读操作, 第一次读到的是地址
* 第二次读到的才是该地址对应的数据
*/
#ifdef __LCD12864_read_8
unsigned char LCD12864_read( void )
{
unsigned char temp;
check_busy();
LCD_OUT = 0xFF;
RS_DATA;
RW_READ;
EN_SET;
LCD_DDR = 0x00;
_delay_us(1);
temp = LCD_IN;
EN_CLR;
LCD_DDR = 0xFF;
return ( temp );
}
/* 读LCD12864的一个字节*/
unsigned char LCD12864_read_8( void )
{
LCD12864_read(); // 注意: 读两次才读到数据return LCD12864_read();
}
#endif
/* 读LCD12864的16位数据*/
#ifdef __LCD12864_read_16
unsigned int LCD12864_read_16( void )
{
unsigned int _16_data;
unsigned char L_dat;
_16_data = LCD12864_read_8();
L_dat = LCD12864_read();
return (_16_data << 8) | L_dat;
}
#endif
/*
* 向LCD12864在( X, Y )出写一个点
*
* 0 <= X <= 127
* 0 <= Y <= 63
* color: 0 -> 擦点, 非0 -> 画点
* ( 传来的DB_X没用看文件前面的注意 )
*/
#ifdef __LCD12864_dot
void LCD12864_dot( unsigned char X, unsigned char DB_X, unsigned char Y, unsigned char color )
{
unsigned char temp, temp2 = 0;
if( (0x01 & (X >> 3)) != 0 )
temp2 = 1;
DB_X = X >> 4;
X = X & 0x07; // X = X % 8;
if( Y >= 32 )
{
DB_X += 8;
Y -= 32;
}
LCD12864_cmd( 0x80 + Y );
LCD12864_cmd( 0x80 + DB_X );
if( temp2 )
LCD12864_next();
temp = LCD12864_read_8();
if( color != 0 )
temp |= (0x80 >> X );
else
temp &= ~(0x80 >> X );
LCD12864_cmd( 0x80 + Y );
LCD12864_cmd( 0x80 + DB_X );
if( temp2 )
LCD12864_next();
LCD12864_dat( temp );
}
#endif
/*
* 向LCD12864画一条线
* 起点( X0, Y0 ), 终点( X1, Y1 )
* 0 <= X <= 127
* 0 <= Y <= 63
*/
#ifdef __LCD12864_line
void LCD12864_line( unsigned char X0, unsigned char Y0, unsigned char X1, unsigned char Y1, uchar color ) {
LCD12864_cmd( 0x34 ); // 关闭显示
if( X0 == X1 ) // K = 1
{
if( Y0 > Y1)
{
X1 = Y0;
Y0 = Y1;
Y1 = X1;
}
while( Y0 <= Y1)
LCD12864_dot( X0, 0, Y0++, color );
LCD12864_cmd( 0x36 ); // 打开显示
return;
}
if( Y0 == Y1 ) // K = 0
{
if( X0 > X1 )
{
Y1 = X0;
X0 = X1;
X1 = Y1;
}
while( X0 <= X1 )
LCD12864_dot( X0++, 0, Y0, color );
LCD12864_cmd( 0x36 ); // 打开显示
return;
}
else // K != 0 && K != 1
{
float _K;
char temp1 = ( X1 < X0 )?( X0 - X1 ):( X1 - X0 );
char temp2 = ( Y1 < Y0 )?( Y0 - Y1 ):( Y1 - Y0 );
if( temp1 < temp2 ) // Y
{
_K = (float)temp1 / temp2;
temp2 = ( Y0 > Y1 )?( -1 ):( 1 );
if( X0 > X1 )
_K = -_K;
temp1 = 1;
LCD12864_dot( X0, 0, Y0, color );
do
{
Y0 += temp2;
LCD12864_dot( X0 + _K * temp1 ,0 , Y0, color );
temp1++;
}while( Y0 != Y1 );
}
else // X
{
_K = (float)temp2 / temp1;
temp2 = ( X0 > X1 )?( -1 ):( 1 );
if( Y0 > Y1 )
_K = -_K;
temp1 = 1;
LCD12864_dot( X0, 0,Y0, color );
do
{
X0 += temp2;
LCD12864_dot( X0, 0, Y0 + _K * temp1, color );
temp1++;
}while( X0 != X1 );
}
}
LCD12864_cmd( 0x36 ); // 打开显示
}
#endif
/*
* 向LCD12864画一个填充矩形
*
* left : 左, X 坐标
* up : 上, Y 坐标
* right: 右, X 坐标
* down : 下, Y 坐标
*
* 0 <= (left & right) <= 127
* 0 <= (up & down) <= 63
*/
#ifdef __LCD12864_bar
void LCD12864_bar( unsigned char left, unsigned char up, unsigned char right, unsigned char down, uchar color ) {
unsigned char temp;
LCD12864_cmd( 0x34 );
if( left > right )
{
temp = left;
left = right;
right = temp;
}
if( up > down )
{
temp = up;
up = down;
down = temp;
}
for( ; up <= down; up++ )
for( temp = left; temp <= right; temp++ )
LCD12864_dot( temp, 0, up, color );
LCD12864_cmd( 0x36 );
}
#endif
/*
* 向LCD12864画一个矩形框
*
* left : 左, X 坐标
* up : 上, Y 坐标
* right: 右, X 坐标
* down : 下, Y 坐标
*
* 0 <= (left & right) <= 127
* 0 <= (up & down) <= 63
*/
#ifdef __LCD12864_rectangle
void LCD12864_rectangle( unsigned char left, unsigned char up, unsigned char right, unsigned char down, uchar color ) {
LCD12864_line( left, up, right, up, color );
LCD12864_line( right, up, right, down, color );
LCD12864_line( right, down, left, down, color );
LCD12864_line( left, down, left, up, color );
}
#endif
/* 画一整行
* Y: 行数 ( 0 ~ 63 )
*/
#ifdef __LCD12864_whole_line
void LCD12864_whole_line( unsigned char Y, unsigned char color ) {
unsigned char temp = 0x80;
if( Y >= 32 )
{
temp += 8;
Y -= 32;
}
LCD12864_cmd( Y + 0x80);
LCD12864_cmd( temp );
for( temp = 0; temp < 16; temp++ )
LCD12864_dat( color );
}
#endif
/* 画一幅128*64的图画*/
#ifdef __LCD12864_BMP
void LCD12864_BMP( unsigned char *table )
{
uchar i,j;
uint n = 0;
LCD12864_cmd( 0x34 );
for( i = 0; i < 64; i++ )
{
if( i >= 32 )
{
LCD12864_cmd( 0x80 + i - 32 );
LCD12864_cmd( 0x88 );
}
else
{
LCD12864_cmd( 0x80 + i );
LCD12864_cmd( 0x80 );
}
for( j = 0; j < 16; j++ )
LCD12864_dat( table[n++] );
}
LCD12864_cmd( 0x36 );
}
#endif
--------------- my_include.h ---------------
/*
* ATmega128的头文件
* 晶振16MHz
* by Qin Zhengye
* 2011-08-07
*/
/* 宏定义要用到的函数*/
#define __Port_init
#define ___delay_ms
#define ___delay_us
/* 包含头文件;
#include
#ifdef ___delay_us
#include
#endif
#ifdef ___delay_ms
#include
#endif
/* defines */
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
/* 定义位操作*/
#define SETBIT( x, y ) ( x |= (0x01 << y) ) #define CLRBIT( x, y ) ( x &= ~(0x01 << y) ) #define CHKBIT( x, y ) ( x & (0x01 << y) )
/* I/O口初始化
* 全部配置为输出高电平
*/
#ifdef __Port_init
void Port_init( void )
{
DDRA = 0xFF;
DDRB = 0xFF;
DDRC = 0xFF;
DDRD = 0xFF;
DDRE = 0xFF;
DDRF = 0xFF;
DDRG = 0x1F;
PORTA = 0xFF;
PORTB = 0xFF;
PORTC = 0xFF;
PORTD = 0xFF;
PORTE = 0xFF;
PORTF = 0xFF;
PORTG = 0x1F;
}
#endif
/* 延时N毫秒(已仿真,稍有偏差 16MHz) */
#ifdef ___delay_ms
void _delay_ms( unsigned int _ms )
{
unsigned int _temp;
for( ; _ms > 0; _ms-- )
for( _temp = 2290; _temp > 0; _temp-- )
NOP();
}
#endif
/* 延时N微秒(已仿真 16MHz) */ #ifdef ___delay_us
void _delay_us( unsigned int _us ) {
while( -- _us )
{
NOP();
NOP();
NOP();
NOP();
NOP();
NOP();
NOP();
NOP();
}
}
#endif
;实验目的:熟悉12864LCD的使用 ;12864LCD带中文字库 ;编程让12864LCD显示公司名称“深圳乾龙盛电子”,公司电话“0975”,公司传真“6”;硬件设置: ;关断所有拨码开关。 #include<> ;__CONFIG _DEBUG_OFF&_CP_ALL&_WRT_HALF&_CPD_ON&_LVP_OFF&_BODEN_OFF&_PWRTE_ON&_WDT_OFF&_H S_OSC ;芯片配置字,看门狗关,上电延时开,掉电检测关,低压编程关,加密,4M晶体HS振荡 #define RS PORTA,5 ;命令/数据选择 #DEFINE RW PORTA,4 ;读/写选择 #DEFINE E PORTA,3 ;使能信号 #DEFINE PSB PORTA,2 ;并口/串口选择(H/L) #DEFINE RST PORTA,0 ;复位信号 ;----------------------------------------------- LCD_X EQU 30H ;页地址 LCD_Y EQU 31H ;Y地址 COUNT EQU 32H ;循环计数用 COUNT1 EQU 33H ;循环计数用 COUNT2 EQU 34H ;循环计数用 POINT EQU 35H ;查表偏移地址 POINT1 EQU 36H ;查表偏移地址 POINT2 EQU 37H ;查表偏移地址 TEMP EQU 38H ;临时寄存器 TEMP1 EQU 39H ;临时寄存器 ;----------------------------------------------- ORG 0000H ;复位地址 NOP ;ICD需要的空指令 GOTO MAIN ;跳转到主程序 ;**********************主程序************************ MAIN BANKSEL TRISA CLRF TRISA ;A口输出 CLRF TRISD ;D口输出 BANKSEL ADCON1 MOVLW 06H MOVWF ADCON1 ;A口全为数字口 CLRF STATUS
51单片机综合学习 12864液晶原理分析1 辛勤学习了好几天,终于对12864液晶有了些初步了解~没有视频教程学起来真有些累,基本上内部程序写入顺序都是根据程序自我变动,然后逆向反推出原理…… 芯片:YM12864R P-1 控制芯片:ST7920A带中文字库 初步小结: 1、控制芯片不同,寄存器定义会不同 2、显示方式有并行和串行,程序不同 3、含字库芯片显示字符时不必对字符取模了 4、对芯片的结构地址一定要理解清楚
5、显示汉字时液晶芯片写入数据的顺序(即显示的顺序)要清楚 6、显示图片时液晶芯片写入数据的顺序(即显示的顺序)要清楚 7、显示汉字时的二级单元(一级为八位数据写入单元)要清楚 8、显示图片时的二级单元(一级为八位数据写入单元)要清楚 12864点阵液晶显示模块(LCM)就是由128*64个液晶显示点组成的一个128列*64行的阵列。每个显示点对应一位二进制数,1表示亮,0表示灭。存储这些点阵信息的RAM称为显示数据存储器。要显示某个图形或汉字就是将相应的点阵信息写入
到相应的存储单元中。图形或汉字的点阵信息由自己设计,问题的关键就是显示点在液晶屏上的位置(行和列)与其在存储器中的地址之间的关系。由于多数液晶显示模块的驱动电路是由一片行驱动器和两片列驱动器构成,所以12864液晶屏实际上是由左右两块独立的64*64液晶屏拼接而成,每半屏有一个512*8 bits显示数据RAM。左右半屏驱动电路及存储器分别由片选信号CS1和CS2选择。显示点在64*64液晶屏上的位置由行号(line,0~63)与列号(column,0~63)确定。512*8 bits RAM中某个存储单元的地址由页地址(Xpage,0~7)和列地址(Yaddress,0~63)确定。每个存储单元存储8个液晶点的显示信息。
本例程为通过用A T89C52芯片操作LCD12864显示的程序,使用的晶振为12M。 /********************************************************** 程序说明:LCD12864显示主程序 程序调试员:莫剑辉 调试时间:2010-6-7 **********************************************************/ #include 在我们常用的人机交互显示界面中,除了数码管,LED,以及我们之前已经提到的LCD1602之外,还有一种液晶屏用的比较多。相信接触过单片机的朋友都知道了,那就是12864液晶。顾名思义,12864表示其横向可以显示128个点,纵向可以显示64个点。我们常用的12864液晶模块中有带字库的,也有不带字库的,其控制芯片也有很多种,如KS0108 T6963,ST7920等等。在这里我们以ST7920为主控芯片的12864液晶屏来学习如何去驱动它。(液晶屏采用金鹏的OCMJ4X8C) 关于这个液晶屏的更多信息,请参考它的DATASHEET,附件中有下载。 我们先来了解一下它的并行连接情况。 下面是电路连接图 从上面的图可以看出,液晶模块和单片机的连接除了P0口的8位并行数据线之外,还有RS,RW,E等几根线。其中R/S是指令和数据寄存器的选择控制线(串行模式下为片选),R/W 是读写控制线(串行模式下是数据线),E是使能线(串行模式下为时钟线)。 通过这几根控制线和数据线,再结合它的时序图,我们就可以编写出相应的驱动程序啦。 看看并行模式下的写时序图: 根据这个时序图,我们就可以写出写数据或者写命令到LCD12864液晶的子程序。 读时序图如下: 根据这个时序图我们就可以从LCD12864液晶模块内部RAM中读出相应的数据,我们的忙检测函数就是根据这个时序图写出来的。以及后面章节中讲的画点函数等都要用到读时序。有了这两个时序图,然后我们再看看OCMJ4X8C的相关指令集,就可以编写出驱动程序了。这里要注意的是指令集分为基本指令集和扩充指令集,其中扩充指令集主要是与绘图相关,在此后的章节中会有相应的介绍。 下面让我们根据这些编写出它的驱动程序吧。 我的硬件测试条件为:STC89C516(11.0592MHz) + OCMJ4X8C 实际显示效果图片如下: 程序部分如下,请结合液晶模块的DATASHEET看程序,这样能够更加快速的弄懂程序的流程。大致有如下几个函数:写数据,写指令,忙检测,初始化,指定地址显示字符串等等。[p][/p] #include "reg52.h" #include "intrins.h" sbit io_LCD12864_RS = P1^0 ; 本例程为通过用AT89C52芯片操作LCD12864显示的程序,使用的晶振为12M。 /********************************************************** 程序说明:LCD12864显示主程序 程序调试员:莫剑辉 调试时间:2010-6-7 **********************************************************/ #include 看到工具箱旁边那个LCD12864很久没用了(当初买回来用的时候只是简单地测试了一下),于是萌生了重新写一次接口程序的想法(而且这次要给它加个图片显示的功能),好,说做就做,就用Atmega16和ICCAVR来做吧,最近这MCU和平台用得比较熟练。 马上从书堆里把当初打印出来的中文datasheet给翻了出来,依葫芦画瓢地写了个初始化程序。好,OK。编译通过。于是又写了一个可以自定义从XY坐标值开始输出显示的函数,再次编译,也通过,OK。于是呼马上写了四行简单的字符烧到单片机上试了一下,嘿嘿,一次通过。如下图: 后来在进一步测试的时候也出了点小问题。就是我是使用USBISP烧写器把程序烧写进AVR的(此时实验板由USBISP烧写器供电),想要实现从第一行的第一个字符开始连续显示"0123456789"。刚烧写完程序后能看到LCD12864上正常显示"0123456789",但是把烧写器从实验板上断开连接,单独用USB给实验板供电的时候,LCD的第一行只是显示"123456789",第一个字符消失了……,左思右想地弄了一个多小时后,终于把问题给解决了,就是把初始化程序的延时适当增加了些,真是奇怪。刚开始一直想不通为什么在烧写器供电的情况下就正常显示,而换到USB供电后就出了问题。后来再想想,估计是跟供电有关。在使用USBISP烧写器供电的时候,LCD的背光灯明显比用USB供电的时候来得亮,而且对比度也高很多,看来是因为换到USB供电后,供电不怎么充足,以至于LCD在上电初始化的时候花上了更多的时间去初始化(因为供电低了,功率小了,跑起来有点力不从心,用的时间就久了嘛……我是觉得可以这样去理解的 接下来呢,就到了有点难度的画图了。当初刚买到12864的时候只是简单测试了字符显示功能,除了因为画图还不需要用到,另外一个原因就是那datasheet上关于画图那部分的内容不怎么看得懂…。现在重新拿起来看,依然一头雾水……。马上上网百度了一下“12864 7920 显示图片”,看到了不少的例子程序,可是……就是没看到有关于这部分功能实现的详细思路和讲解……下载下来的那些程序,基本上没注释,不是说晦涩难懂,但是至少看起来一团糟,让人家不想继续看下去……于是还是硬着头皮去啃那datasheet。上面对于画图这部分的内容是这样讲解的: 用12864显示单色图片 首先介绍本12864液晶显示器: 型号:QC12864B 因为单片机读取的是数据,而不是直接的图片。得将图片进行取模,图片应该是单色图片,像素128*64。 下面我为大家介绍个实例。 ①、在电脑附件画图,首先设置属性 开始画图 保存文件,注意格式: ②、然后进行取模。 ③、编程: #include LCD12864图形液晶并口显示 【教学引入】 液晶屏,在生活中很常见,我们常见的液晶显示器,如电脑的显示器,电视机,手机等等。 液晶屏在生活中已得到了普遍应用,它显示个各种各样的画面。 【教学目标】 1、掌握LCD12864液晶屏的用法; 2、编写LCD12864液晶屏的指令代码; 【知识目标】 1、掌握LCD12864液晶屏的用法; 2、掌握LCD12864液晶屏指令代码; 【教学准备】 电脑、Proteus、Keil 【教学方法】 教法:讲授法、讨论法 学法:练习法、探究法 【教学课时】 四课时 【教学过程】 一、12864液晶介绍 (1)12864是128*64点阵液晶模块的点阵数简称,业界约定俗成的简称。12864点阵的屏显成本相对较低,适用于各类仪器,小型设备的显示领域。12864M汉字图形点阵液晶显示模块,可显示汉字及图形,内置8192个中文汉字(16X16点阵)、128个字符(8X16点阵)及64X256点阵显示RAM(GDRAM)。 12864引脚说明 查阅“12864M.PDF”12864M液晶显示模块技术手册——四、用户指令集 1、指令表1:(RE=0:基本指令表),如下图,讲解了12864的基本指令集和扩充指令集。 当模块在接受指令前,微处理器必须先确认模块内部处于非忙碌状态,即读取BF标志时BF需为0。“RE”为基本指令集与扩充指令集的选择控制位元,往后的指令集将维持在最后的状态。 当选择G=0 :绘图显示OFF,汉字显示的时,12864屏只能显示8X4=32个汉字,下面是汉字显示的坐标 二、12864液晶屏驱动电路 原件名称所属类(Category) 所属子类(Sub-category) AT89C52 Microprocessor ICs 8051 Family POT-HG Resistors Variable RESPACK-8 Resistors Resistor Packs LCD12864A 自制- AT89C52的P0口连接12864的并行数据口,RP1为P0口的上拉排阻。 三、52代码编写 (1)打开keil uVision4,建立一个新的工程,工程名为"12864 graphic LCD parallel display",保存类型*.uvproj,单片机型号AT89C52。在工程中添加12864 graphic LCD parallel display.c文件,如下图 基于STM32--LCD12864驱动程序 STM32 LCD12864驱动程序(头文件)(2012-05-29 21:25:08)转载▼ 标签:杂谈 #ifndef LCD12864_H #define LCD12864_H #define LCD_CONTROL GPIOD //默认LCD12864的控制口在PD口 #define LCD_DATAPORT GPIOD //默认LCD12864的数据口在PD口 #define LCD_RESET_Pin GPIO_Pin_12 //默认LCD12864的复位引脚连接到PD.12 也可不用 #define LCD_RS_Pin GPIO_Pin_13 //默认LCD12864 RS -- PD.13 #define LCD_RW_Pin GPIO_Pin_14 //默认LCD12864 RW -- PD.14 #define LCD_EN_Pin GPIO_Pin_15 //默认LCD12864 E -- PD.15 #define LCD_CONTROL_CLOCK RCC_APB2Periph_GPIOD //默认LCD12864的控制口时钟 #define LCD_DATAPORT_CLOCK RCC_APB2Periph_GPIOD //默认LCD12864的数据口时钟 #define LCD_RS_1 LCD_CONTROL->BSRR &=~LCD_RS_Pin;LCD_CONTROL->BSRR |=LCD_RS_Pin //RS置高电平 #define LCD_RS_0 LCD_CONTROL->BRR &=~LCD_RS_Pin;LCD_CONTROL->BRR |=LCD_RS_Pin //RS置低电平 #define LCD_RW_1 LCD_CONTROL->BSRR &=~LCD_RW_Pin;LCD_CONTROL->BSRR |=LCD_RW_Pin //RW置高电平 #define LCD_RW_0 LCD_CONTROL->BRR &=~LCD_RW_Pin;LCD_CONTROL->BRR |=LCD_RW_Pin //RW置低电平 #define LCD_EN_1 LCD_CONTROL->BSRR &=~LCD_EN_Pin;LCD_CONTROL->BSRR |=LCD_EN_Pin //EN置高电平 #define LCD_EN_0 LCD_CONTROL->BRR &=~LCD_EN_Pin;LCD_CONTROL->BRR |=LCD_EN_Pin //EN置低电平 /******************************************************** LCD12864字符显示 ********************************************************/ #include #include 简介:第一行显示,距离系统爆炸时间 第二行显示,还剩 第三行显示,00时,00分,00秒 第四行显示,周林 按下旋钮开关,开始设定秒,秒编辑位闪动。左右旋转设定数值, 在按下开关,秒确定,设定分,分编辑位闪动左右调数值, 再按下,分确定,小时位闪动。左右转调小时,再按一下。时间确定,开始倒计时。到达定时时间后停止,并闪动。 #include signed char second=0,minute=0,hour=0,count=0,keycount=0; signed char key=0; unsigned char code DIS1[] = { "距离系统爆炸时间" }; unsigned char code DIS2[] = { "还剩:" }; unsigned char code DIS31[] = { "时" }; unsigned char code DIS32[] = { "分" }; unsigned char code DIS33[] = { "秒" }; #ifndef jh_f330 #define jh_f330 #include 12864显示一个动态图片 姓名:周潘勇班级:电子0911 程序: #include #include delay(5); } /**********写串口指令*************/ void write_com(uchar com) { CS=1; //每次传数据前把CS端拉高 send_bit(0xf8); //写指令 send_bit(com&0xf0); //0xf0为1111 0000,送高四位 send_bit((com<<4)&0xf0); //0xf0为1111 0000,送低四位delay(10); CS=0; } /**********写串口数据*************/ void write_date(uchar date) { CS=1; //每次传数据前把CS端拉高 send_bit(0xfa); //写指令 send_bit(date&0xf0); //0xf0为1111 0000,送高四位 send_bit((date<<4)&0xf0); //0xf0为1111 0000,送低四位delay(10); CS=0; } /*********初始化函数****************/ /*********初始化液晶****************/ void init() { delay(100); write_com(0x30); //基本指令模式 delay(10); write_com(0x0c); //开显示,关游标,关反白 delay(10); write_com(0x01); //清屏 delay(100); /***显示初始化***/ /////* write_com(0x80); for(num=0;num<16;num++) {玩转12864液晶(1)--显示字符
LCD显示程序
12864显示图形
在12864显示任意图片及参考程序
LCD12864图形液晶并口显示
基于STM32--LCD12864驱动程序
LCD12864字符显示
12864液晶显示程序(图案+文字)
12864LCD显示倒计时程序
LCD12864(串口)显示程序
12864动态显示图片-仿真图及程序
LCD12864串行显示程序