lcd12864液晶显示程序

一:概述 带中文字库的128x64 是一种具有4 位/8 位并行、2 线或3 线串行多种接口方式,内部含有国标一级、二级简体 中文字库的点阵图形液晶显示模块;其显示分辨率为128×64, 内置8192 个16*16 点汉字,和128 个16*8 点ascii 字符 集。利用该模块灵活的接口方式和简单、方便的操作指令,可构成全中文人机交互图形界面。可以显示8×4 行16×16 点 阵的汉字。 也可完成图形显示。低电压低功耗是其又一显著特点。由该模块构成的液晶显示方案与同类型的图形点阵液晶 显示模块相比,不论硬件电路结构或显示程序都要简洁得多,且该模块的价格也略低于相同点阵的图形液晶模块。
二:lcd12864液晶显示程序 //12864接法:pb口为数据口(db7~db0),rs~pc0,rw~pc1,en~pc2,psb即cs1(cs2不用即不接)pc3,rst~pc5。
//pd2接外部中断,pa0,pa1分别接一路可调电位器。
/*****************************************************
this program was produced by the
codewizardavr v2.04.4a advanced
automatic program generator
?copyright 1998-2009 pavel haiduc, hp infotech s.r.l.
http://www.hpinfotech.com
chip type : atmega16
program type : application
avr core clock frequency: 4.000000 mhz
memory model : small
external ram size : 0
data stack size : 256
*****************************************************/
#include 《mega16.h》
#include 《delay.h》
//flash unsigned char dis_str2[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};//0~9的ascii码
flash unsigned char dis_str3[]={“0123456789”}; //0~9的ascii码
unsigned int counter=0;
unsigned char bita,bitb; //bita为adc通道标志,bitb为是否加小数点标志
unsigned int adc_data,adc_v,adc_data2,adc_v2;
#define uchar unsigned char
#define uint unsigned int
#define lcd_rs 0 //寄存器选择输入pc0
#define lcd_rw 1 //液晶读/写控制pc1
#define lcd_en 2 //液晶使能控制pc2
#define lcd_psb 3 //串/并方式控制pc3 即cs1(cs2不用)
#define lcd_rst 5 //液晶复位端口pc5
#define busy 7 //lcd_db7,pa7
uchar const cdis1[] = {“硕飞科技电子 00”};
uchar const cdis2[] = {“ www.willar.com ”};
uchar const cdis3[] = {“me850_开发实验仪”};
uchar const cdis4[] = {“tel:077584867757”};
uchar const cdis5[] = {“counter:”};
/**********************************************************
图形数据
**********************************************************/
/**********************************************************
* *
*检查lcd忙状态 *
*lcd_busy为1时,忙,等待。lcd-busy为0时,闲,可写指令与数据*
* *
**********************************************************/
void lcd_busy(void)
{
//ddra &=~_bv(busy); //设置busy口为输入
ddrb &=~(1《《busy); //设置busy口为输入
//ddra.7=0; //设置busy口为输入
portc &=~(1《《lcd_rs);
portc |=(1《《lcd_rw);
portc |=(1《《lcd_en);
while(pinb & (1《《busy)); //忙等待
portc &=~(1《《lcd_en);
ddrb|=(1《《busy); //设置busy口为输出
}
/**********************************************************
* *
*写指令数据到lcd *
*rs=l,rw=l,e=高脉冲,d0-d7=指令码。 *
*command为指令,wait_en指定是否要检测lcd忙信号
*
* *
**********************************************************/
void lcd_wcmd(uchar command,uchar wait_en)
{
if(wait_en) //若wait_en为1,则要检测lcd忙信号
lcd_busy();
portc &=~(1《《lcd_rs);
portc &=~(1《《lcd_rw);
portc &=~(1《《lcd_en);
portb =command; //送指令数据
portc |=(1《《lcd_en);
//_nop();
// _nop();
portc &=~(1《《lcd_en);
}
/**********************************************************
* *
*写显示数据到lcd *
*rs=h,rw=l,e=高脉冲,d0-d7=数据。 *
* *
**********************************************************/
void lcd_wdat(uchar dat)
{
lcd_busy();
portc |=(1《《lcd_rs);
portc &=~(1《《lcd_rw);
portc &=~(1《《lcd_en);
portb=dat; //送显示数据
portc |=(1《《lcd_en);
//_nop();
//_nop();
delay_us(2);
portc &=~(1《《lcd_en);
}
/**********************************************************
* *
* lcd初始化设定 *
* *
**********************************************************/
void lcd_init(void)
{
ddrb=0xff; //设置pa输出
portb=0xff; //全部加上上拉电阻
ddrc=0xff; //设置pc为输出
portc=0xff; //全部加上上拉电阻
delay_ms(30); //等待上电稳定
portc|=(1《《lcd_psb); //并口方式
portc &=~(1《《lcd_rst); //液晶复位
delay_ms(5);
portc |=(1《《lcd_rst);
delay_ms(5);
lcd_wcmd(0x30,0);
delay_ms(5);
lcd_wcmd(0x0c,1); //显示开,关光标
delay_ms(5);
lcd_wcmd(0x06,1); //移动光标
delay_ms(5);
lcd_wcmd(0x01,1); //清除lcd的显示内容
delay_ms(5);
}
/**********************************************************
设定显示位置子函数
**********************************************************/
void lcd_pos(uchar x,uchar y)
{
uchar pos;
if (x==1) //第一行
{x=0x80;}
else if (x==2) //第二行
{x=0x90;}
else if (x==3) //第三行
{x=0x88;}
else if (x==4) //第四行
{x=0x98;}
pos = x+y ; //确定具体显示地址
lcd_wcmd(pos,1); //写显示地址
}
void display(unsigned int temp,unsigned char gotoy,unsigned char gotox) //(要显示的数,行,列)
{
//unsigned int temp;
unsigned char disp_c[4],i;
if(temp==counter)bitb=0; //若是counter的值传给temp,则
标志bitb为0(显示时不加小数点)
else bitb=1; //若不是counter的值传给temp,则标志bitb为1(显示时加小数点)
//temp=counter;
for(i=0;i《4;i++)
{ //拆字程序
disp_c[i]=temp%10;
temp=temp/10;
}
//lcd_gotoxy(gotox,gotoy); ////定位要显示所在的列、行
lcd_pos(gotoy,gotox);
//lcd_putchar(dis_str3[disp_c[3]]); //显示一个字符,括号中为该字符的ascii码
lcd_wdat(dis_str3[disp_c[3]]);
//if(bitb==1)lcd_putsf(“。”); //判断要不要加小数点
if(bitb==1)lcd_wdat(0x2e);
//lcd_putchar(dis_str3[disp_c[2]]); //显示一个字符,括号中为该字符的ascii码
lcd_wdat(dis_str3[disp_c[2]]);
//lcd_putchar(dis_str3[disp_c[1]]); //显示一个字符,括号中为该字符的ascii码
lcd_wdat(dis_str3[disp_c[1]]);
//lcd_putchar(dis_str3[disp_c[0]]); //显示一个字符,括号中为该字符的ascii码
lcd_wdat(dis_str3[disp_c[0]]);
}
/**********************************************************
* *
* 图形显示子函数 *
* *
**********************************************************/
/*void photodisplay(uchar flash *bmp)
{
uchar i,j,temp;
uint num=0;
lcd_wcmd(0x34,1); //写数据时,关闭图形显示
for(i=0;i《32;i++) //32行(上半屏)
{
lcd_wcmd(0x80+i,1); //先写入y坐标值
lcd_wcmd(0x80,1); //写入x坐标值
for(j=0;j《16;j++) //16*8列
{
temp=bmp[num++];
lcd_wdat(temp);
}
delay_ms(1);
}
for(i=0;i《32;i++) //32行(下半屏)
{
lcd_wcmd(0x80+i,1); //先写入y坐标值
lcd_wcmd(0x88,1); //写入x坐标值
for(j=0;j《16;j++) //16*8列
{
temp=bmp[num++];
lcd_wdat(temp);
}
delay_ms(1);
}
lcd_wcmd(0x36,1); //写完数据,开图形显示
}*/
/**********************************************************
* *
* 清屏子函数 *
* *
**********************************************************/
void clr_screen(void)
{
lcd_wcmd(0x34,1); //扩充指令操作
delay_ms(5);
lcd_wcmd(0x30,1); //基本指令操作
delay_ms(5);
lcd_wcmd(0x01,1); //清屏
delay_ms(5);
}
/**********************************************************
闪烁函数
**********************************************************/
void lcdflag(void)
{
lcd_wcmd(0x08,1); //关闭显示
delay_ms(1000);
lcd_wcmd(0x0c,1); //开启显示
delay_ms(1000);
lcd_wcmd(0x08,1);
dela
y_ms(1000);
lcd_wcmd(0x0c,1);
delay_ms(1000);
lcd_wcmd(0x08,1);
delay_ms(1000);
lcd_wcmd(0x0c,1);
delay_ms(1000);
lcd_wcmd(0x01,1); //清屏
delay_ms(5);
}
/**********************************************************
* *
* 写字符串子函数 *
* *
**********************************************************/
void wr_string(void)
{
uchar m;
lcd_pos(1,0); //设置显示位置为第一行
for(m=0;m《16;m++)
{
lcd_wdat(cdis1[m]);
delay_ms(100);
}
lcd_pos(2,0); //设置显示位置为第二行
for(m=0;m《16;m++)
{
lcd_wdat(cdis2[m]);
delay_ms(100);
}
lcd_pos(3,0); //设置显示位置为第三行
for(m=0;m《16;m++)
{
lcd_wdat(cdis3[m]);
delay_ms(100);
}
lcd_pos(4,0); //设置显示位置为第四行
for(m=0;m《16;m++)
{
lcd_wdat(cdis4[m]);
delay_ms(100);
}
}
/*void wr_string2(unsigned char string,unsigned char x,unsigned char y,unsigned char n)
{
uchar m;
lcd_pos(x,y); //设置显示位置为第一行
for(m=0;m《n;m++)
{
lcd_wdat(cdis1[m]);
delay_ms(10);
}
}*/
//绘图
/*====================================================
函数功能:清除gdrom的内容,如果不清除会出现花屏现象
清除方法:向gdrom中写入0x00来清除内容
========================================================*/
void clear_gcrom()
{
uchar i,j,k,lcd_x,lcd_y;
lcd_x=0x80;
lcd_y=0x80;
lcd_wcmd(0x34,1);//打开扩充指令关闭绘图显示(绘图指令为扩充指令,并且在绘图期间必须关闭绘图显示功能)
for(i=0;i《2;i++)//分为上下两半屏清除显示
{
for(j=0;j《32;j++)
{
lcd_wcmd(lcd_y+j,1);
lcd_wcmd(lcd_x,1);
for(k=0;k《16;k++)
{
lcd_wdat(0x00);
}
}
lcd_x=0x88;//将x指向下半屏
}
lcd_wcmd(0x36,1);//打开绘图指令
lcd_wcmd(0x30,1);//操作恢复为常用指令
}
/**********************************************************
* *
*读st7920内部ram数据的函数 *
*rs=h,rw=h,e=高脉冲,d0-d7=数据。 *
* *
**********************************************************/
uchar readbyte(void)
{
uchar returnvalue;
lcd_busy();
ddra&=0x00; //pa口为输入
//delay_ms(1);
porta=0xff; //加上拉电阻
portc |=(1《《lcd_rw); //rw=1
//delay_us(1);
portc |=(1《《lcd_rs); //rs=1
//delay_us(1);
portc &=~(1《《lcd_en); //en=0
delay_us(1);
portc
|=(1《《lcd_en); //en=1
//delay_us(3);
delay_us(1);
//portc &=~(1《《lcd_en); //en=0
returnvalue=pina; //读pa口
delay_us(1);
portc &=~(1《《lcd_en); //en=0
//delay_us(1);
portc &=~(1《《lcd_rw); //rw=0
portc &=~(1《《lcd_rs); //rs=0
ddra=0xff; //pa口为输出
return (returnvalue);
}
/**********************************************************
* *
* 画点子函数 *
* *
**********************************************************/
void drawpoint(uchar x,uchar y,uchar color)
{
uchar row,tier,tier_bit;
uchar readold_h,readold_l;
lcd_wcmd(0x34,1);
//lcd_wcmd(0x36,1);
tier = x 》》 4 ; //用移位,速度快
tier_bit = x & 0x0f ;
if( y 《 32 )
{
row = y ;
}
else
{
row = y - 32 ;
tier += 8 ;
}
lcd_wcmd(0x34,1);
lcd_wcmd( row + 0x80,1 ) ;
lcd_wcmd( tier + 0x80,1 ) ;
lcd_busy(); //
readbyte();
readold_h = readbyte() ;
readold_l = readbyte() ;
lcd_wcmd( row + 0x80,1 ) ;
lcd_wcmd( tier + 0x80,1 ) ;
if( tier_bit 《 8 )
{
switch( color)
{
case 0 : readold_h &=( ~( 0x01 《《 ( 7 - tier_bit ))) ; break ;
case 1 : readold_h |= ( 0x01 《《 ( 7 - tier_bit )) ; break ;
case 2 : readold_h ^= ( 0x01 《《 ( 7 - tier_bit )) ; break ;
default : break ;
}
lcd_wdat( readold_h ) ;
lcd_wdat( readold_l ) ;
}
else
{
switch(color)
{
case 0 : readold_l &= (~( 0x01 《《 ( 15 - tier_bit ))) ; break ;
case 1 : readold_l |= ( 0x01 《《 ( 15 - tier_bit )) ; break ;
case 2 : readold_l ^= ( 0x01 《《 ( 15 - tier_bit )) ; break ;
default : break ;
}
lcd_wdat( readold_h ) ;
lcd_wdat( readold_l ) ;
}
lcd_wcmd(0x36,1);
lcd_wcmd( 0x30,1 );
}
/**********************************************************
函数功能:画水平直线
参数说明:x0为水平线起始点,x1为水平直线终止点,y图画在第几行
color为 0时为白线, 为1时为黑线,2时取反该直线上的点
**********************************************************/
void v_lcd12864drawlinex_f( unsigned char x0, unsigned char x1, unsigned char y, unsigned char color )
{ unsigned char temp ;
if( x0 》 x1 ) //当x0在x1后面时将x1作为起始点
{
temp = x1 ;
x1 = x0 ;
x0 = temp ;
}
for( ; x0 《= x1 ; x0++ )
drawpoint( x0, y, color ) ;
}
/**********************************************************
函数功能:画垂线
参数说明:y0 为
起始点 y1为结束点,x为所在第几列 ,color同上为颜色选择
**********************************************************/
void v_lcd12864drawliney_f( unsigned char x, unsigned char y0, unsigned char y1, unsigned char color )
{
unsigned char temp ;
if( y0 》 y1 ) //当y0在x1后面时将y1作为起始点
{
temp = y1 ;
y1 = y0 ;
y0 = temp ;
}
for(; y0 《= y1 ; y0++)
drawpoint( x, y0, color) ;
}
/**********************************************************
函数功能:在任意两点间画一条直线,采用bresenham画线算法。
参数说明:startx为起始点横坐标,starty为起始点纵坐标,endx为终点横坐标,endy为终点纵坐标,
**********************************************************/
void v_lcd12864drawline_f( unsigned char startx, unsigned char starty, unsigned char endx, unsigned char endy, unsigned char color )
{
int t, distance; /*根据屏幕大小改变变量类型(如改为int型)*/
int x = 0 , y = 0 , delta_x, delta_y ;
char incx, incy ;
delta_x = endx - startx ;
delta_y = endy - starty ;
if( delta_x 》 0 )
{
incx = 1;
}
else if( delta_x == 0 )
{
v_lcd12864drawliney_f( startx, starty, endy, color ) ;
return ;
}
else
{
incx = -1 ;
}
if( delta_y 》 0 )
{
incy = 1 ;
}
else if(delta_y == 0 )
{
v_lcd12864drawlinex_f( startx, endx, starty, color ) ;
return ;
}
else
{
incy = -1 ;
}
// delta_x = abs( delta_x ); //求绝对值(cvavr的math.h中不包含该函数)
if(delta_x《0)delta_x=-delta_x; //求绝对值
//delta_y = abs( delta_y ); //求绝对值(cvavr的math.h中不包含该函数)
if(delta_y《0)delta_y=-delta_y; //求绝对值
if( delta_x 》 delta_y )
{
distance = delta_x ;
}
else
{
distance = delta_y ;
}
drawpoint( startx, starty, color ) ;
/* draw line*/
for( t = 0 ; t 《= distance+1 ; t++ )
{
drawpoint( startx, starty, color ) ;
x += delta_x ;
y += delta_y ;
if( x 》 distance )
{
x -= distance ;
startx += incx ;
}
if( y 》 distance )
{
y -= distance ;
starty += incy ;
}
}
}
interrupt [ext_int0] void aaa(void)
{
delay_ms(15);
if(pind.2==0)
counter++;
// display(counter,8,1);
}
interrupt [adc_int] void bbb(void)
{
//unsigned int adc_data,adc_v;
if(bita==0) //轮流转换
{
adc_data=adcw; //读adc0转换值
adc_v=(unsigned long)adc_data*5000/1024;
admux=0x41; //选择通道adc1
adcsra.6=1; //重新开
始转换
portd.7=~portd.7; //测试用
bita=1; //做标志
}
else
{
adc_data2=adcw; //读adc1转换值
adc_v2=(unsigned long)adc_data2*5000/1024;
admux=0x40; //选择通道adc0
adcsra.6=1; //重新开始转换
portd.7=~portd.7; //测试用
bita=0; //做标志
}
}
/**********************************************************
* *
* 主函数 *
* *
**********************************************************/
void main(void)
{
uchar m;
//init_io(); //初始化端口
//ddra=0xff; //置pa口输出
//porta=0xff; //pa口设置内部上拉电阻
ddrb=0xff; //置pb口输出
portb=0xff; //pb口设置内部上拉电阻
ddrc=0xff; //置pc口输出
portc=0xff; //pc口设置内部上拉电阻
//ddrd=0xff; //置pd口输出
//portd=0xff; //pd口设置内部上拉电阻
lcd_init(); //初始化lcd
ddrd.2=0; //外部中断初始化
portd.2=1;
mcucr=0x02;
gicr=0x40;
sreg.7=1; //开总中断开关
bita=0; //选adc0通道
admux=0x40; //adc初始化
adcsra=0b11001101;
//lcd_gotoxy(0,0); //显示固定字符
lcd_pos(1,0); //(行,列)
//lcd_putsf(“a:”); // display the message
lcd_wdat(0x41); //显示“a”
lcd_wdat(0x3a); //显示“。“
delay_ms(10);
//lcd_gotoxy(9,0);
lcd_pos(1,4); //(行,列)
//lcd_putsf(”b:“); // display the message
lcd_wdat(0x42); //显示“b”
lcd_wdat(0x3a); //显示“。”
delay_ms(10);
//counter=0; //counter初值
// lcd_gotoxy(0,1); //第1行第0列
// lcd_putsf(“counter:”);
// display(counter,8,1); //显示初始值
lcd_pos(2,0); //(行,列)
for(m=0;m《8;m++)
{
lcd_wdat(cdis5[m]);
delay_ms(10);
}
while(1)
{
display(adc_v,1,1); //(数据,行,列)
display(adc_v2,1,5); //(数据,行,列)
display(counter,2,4);
//wr_string(); //写字符串
//lcd_pos(1,0); //显示半宽字符
//lcd_wdat(0x01);
//lcd_wdat(0x02);
//lcd_wdat(0x03);
//lcd_wdat(0x33); //“3”ascii 码
//delay_ms(100);
//delay_ms(2000);
//lcdflag();
//delay_ms(2000);
/*
clear_gcrom(); //清除gdrom的内容,否则当前图会在上一幅图上叠加
delay_ms(100);
clr_screen(); //清

delay_ms(100);
clr_screen(); //清屏
delay_ms(100);
//while(1);
v_lcd12864drawliney_f( 0, 0 , 63, 1 ) ; //画垂直线
delay_ms(100);
v_lcd12864drawlinex_f( 0, 127 , 31, 1 ) ;
drawpoint(69,10,1); //画点
drawpoint(69,20,1); //画点
while(1);
*/
}
}
/*********************************************************/

OPPO专利申请量全球第六,仅次于华为
Windows Server实现RAID技术,保证数据的读取速度和安全
iOS10.2.1beta3正式发布,iOS10.3还会远么?附升级教程!
联发科成功跻身全球半导体一哥行列
基于无线通信技术的图书馆自助服务研究
lcd12864液晶显示程序
苹果iPad的外观被披露出来了?
用心守护创新: Google Play 与特色精品游戏的年度故事
受新冠疫情和苹果下调5G手机预期 射频厂商预警5G需求放缓
二维材料于场效晶体管的应用
SIM卡座三选二合一的结构是怎样的
电容检测电路配置,如何处理低频和高频噪声?
一文详解EMI的传播过程
智能开关双控怎么接线_智能开关与传统开关有什么区别
RT-Thread下LPC55S69的LVGL移植适配
中国联通康楠:“新基建”政策下数据成关键生产要素
跑马灯实验用汇编语言和C51语言做出的不同效果
可调电容盒 可调电容 ATCDB12
2022年云计算全球市场规模将超过2700亿美元
程序创业项目未来趋势与展望!OMO入口项目有红利