LED灯显示
利用取字模软件来生成字模
取字模上设置相关选项取出字模,设置像素为8*8。如“上,\”等。
unsigned char code dis1[] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};//"\",阴码(1亮)、按列取字模
unsigned char code dis2[] = {0x00,0x40,0x40,0x7E,0x48,0x48,0x40,0x00};//"上",阴码(1亮)、按列取字模、低位在前
列选模版
void main() //主函数
{
unsigned char i,temp;
while(1)
{
//按列扫描
temp=0x7f;
for (i = 0; i < 8; i++)
{
P2 = temp;//列选
//P3 = dis1[i];//"\"列编码
P3 = dis2[i];//"上"列编码
temp=_cror_(temp,1);
delay(2);
}
}
}
行选模版
LED上的滚动显示心形图片
- 8行不够显示,一个字符占4列,4个字符16列,一屏(帧)显示2个字符。
- 滚动显示:将一帧数据左移一列,形成新一帧的数据,需要17帧数据,最后一帧为8列不显示的列编码,需补充8列编码0xff。
- 一帧数据显示完后不要马上显示下一帧,若一帧只显示一次就换一帧新数据,会导致旧帧数据没有被视觉捕捉到就更换了,所以一帧数据需要重复显示多次再切换为下一帧,重复的次数决定滚动显示的速度,重复的次数越多滚动速度越慢。
#include<reg51.h>
#include<intrins.h>
unsigned char ldis[16] = {0xFF,0xF3,0xE1,0xC1,0x83,0xC1,0xE1,0xF3};//图片点阵,阳码(0亮)、按列取字模、低位在前
unsigned char hdis[16] = {0x00,0x6c,0xfe,0xfe,0x7c,0x38,0x10,0x00};//图片点阵,阴码(1亮)、按行取字模、低位在前
void delay(unsigned char i) // 延时函数
{
unsigned char j,k;
for(j=i;j>0;j--)
for(k=110;k>0;k--);
}
void main() //主函数
{
unsigned char i,j,k,temp;
for (i = 8; i < 16; i++) //补8列不显示的列编码
ldis[i]=0xff;
for (i = 8; i < 16; i++) //补8行不显示的行编码
hdis[i]=0x00;
while(1)
{
//按列扫描,左右滚动
for(j=8;j<26;j++) //9帧,要循环显示就有17帧
{
for(k=0;k<50;k++)//重复显示一帧数据50次
{ temp=0x01;
for (i = 0; i < 8; i++)
{
P3 = temp;//列选
P2 = ldis[(i+j)%16];//图片点阵列编码,要循环显示ldis[(i+j)%16];
temp=temp<<1;
delay(2);
}
}
}
//按行扫描,上下滚动
/* for(j=0;j<17;j++) //9帧,要循环显示就有17帧
{
for(k=0;k<50;k++)//重复显示一帧数据50次
{ temp=0xfe;
for (i = 0; i < 8; i++)
{
P2 = temp;//行选
P3 = hdis[(i+j)%16];//图片点阵行编码,要循环显示hdis[(i+j)%16];
temp=_crol_(temp,1);
delay(2);
}
}
} */
}
}
液晶1602
读LCM状态(测试忙/闲)
unsigned char DectectBusyBit(void)//状态判断函数(忙/闲?)
{
bit result;
P0 = 0xff; //读状态前先置高电平,防止误判
RS = 0;
delay(5);
RW = 1;
LCDEN = 1;
delay(5);
result=BF; //若LCM忙,则反复测试,在此处原地踏步;当LCM闲时,才往下继续
LCDEN = 0;
return result;
}
写命令
void WrComLCD(unsigned char ComVal)//写命令函数
{
while(DectectBusyBit()==1); //先检测LCM是否空闲
RS = 0;
delay(1);
RW = 0;
LCDEN = 1;
P0 = ComVal;
delay(1);
LCDEN = 0;
}
写数据
void WrDatLCD(unsigned char DatVal)//写数据函数
{
while(DectectBusyBit()==1);
RS = 1;
delay(1);
RW = 0;
LCDEN = 1;
P0 = DatVal;
delay(1);
LCDEN = 0;
}
初始化
void LCD_Init(void)//1602初始化函数
{
WrComLCD(0x38); // 功能设定:16*2行、5*7点阵、8位数据接口
WrComLCD(0x38);
WrComLCD(0x38);
//多次重复设定功能指令,因为LCD启动后并不知道使用的是4位数据接口还是8位的,所以开始时总是默认为4位
WrComLCD(0x01); // 清屏
WrComLCD(0x06); // 光标自增、屏幕不动
delay(1); // 延时,等待上面的指令生效,下面再显示,防止出现乱码
WrComLCD(0x0f); // 开显示、关光标
}
滚动显示
unsigned char i=0;
unsigned char j=0;
unsigned char m=24;
unsigned char n=24;
LCD_Init();
delay(5);
WrComLCD(0x8f);
while(chr1[i]!='\0'){
WrDatLCD(chr1[i]);
i++;
delay(10);
}
/*
while(m--){
WrComLCD(0x1C);
delay(200);
}
WrComLCD(0x01);
WrComLCD(0x80); */
while(chr2[j]!='\0'){
WrDatLCD(chr2[j]);
j++;
delay(5);
}
while(n--){
WrComLCD(0x1C);
delay(200);
}
/*****************************显示输入文本数字等*********************************************/
void display_char(u8 *point, u8 address)
{
unsigned char i;
WrComLCD(0x80 + address);
for (i=0;i<16;i++)
{
WrDatLCD(*point);
point++;
}
}
/*****************************显示变量(三位数)*********************************************/
void display(int number, unsigned char address)
{
unsigned char b,c,d;
b = (number/100);
c = (number/10)%10;
d = (number/1)%10;
WrComLCD(0x80+address);
WrDatLCD(b+48);
WrDatLCD(c+48);
WrDatLCD(d+48);
}
例子
显示如图效果
unsigned char code chr1[]="Welcome!";
unsigned char code chr2[]="MCU-STUDY-BOARD";
//导入1206各个函数
void main()
{ unsigned char i=0;
LCD_Init();
delay(5); //延时,等待初始化完成
WrComLCD(0x80); //设置显示地址第一行第一位:0X00(0x80+0x00)
while(chr1[i]!='\0')
{
WrDatLCD(chr1[i]);
i++;
delay(5);
}
i=0;
WrComLCD(0xC0); //设置显示地址第二行第一位:0X40(0x80+0x40)
while(chr2[i]!='\0')
{
WrDatLCD(chr2[i]);
i++;
delay(5);
}
while(1);
}
液晶12864
总连接
//RST接高电平
sbit LCDEN = P3^4; //使能信号
sbit RS = P3^5; //数据/命令选择端(H/L)
sbit RW = P3^6; //数/写选择端(H/L)
sbit CS2=P3^2; //左半屏片选
sbit CS1=P3^1; //右半屏片选
sbit BF=P0^7; //检测忙
取字模取字逐列取
/*--宋体12;点阵:宽x高=16x16--;逐列取模*/
unsigned char code TAB[][32] ={
{0x40,0x80,0x40,0x80,0x42,0x40,0x42,0x20,0x42,0x10,0x42,0x0C,0x42,0x03,0xFE,0x00,
0x42,0x03,0x42,0x0C,0x42,0x10,0x42,0x20,0x42,0x40,0x40,0x80,0x40,0x80,0x00,0x00},/*"天",0*/
...
} ;
判断忙闲
unsigned char DectectBusyBit(void)//状态判断函数(1忙/0闲?)
{
bit result;
P0 = 0xff; //读状态前先置高电平,防止误判
RS = 0;
delay(5);
RW = 1;
LCDEN = 1;
delay(5);
result=BF;
LCDEN = 0;
return result;
}
写命令
void WrComLCD(unsigned char ComVal)//写命令函数
{
while(DectectBusyBit()==1); //若LCM忙,则反复测试,在此处原地踏步;当LCM闲时,才往下继续
RS = 0;
delay(1);
RW = 0;
LCDEN = 1;
P0 = ComVal;
delay(1);
LCDEN = 0;
}
写数据
void WrDatLCD(unsigned char DatVal)//写数据函数
{
while(DectectBusyBit()==1);
RS = 1;
delay(1);
RW = 0;
LCDEN = 1;
P0 = DatVal;
delay(1);
LCDEN = 0;
}
清屏
//清除整个屏幕,所以左右屏都要选
void Clear()//本模块没有清屏指令,需用户自定义
{
unsigned char i,j;
CS1=0;
CS2=0;
for(i=0;i<8;i++)
{
WrComLCD(0XB8+i); //设置页地址
WrComLCD(0X40+0); //设置列地址,总是从该页的第0列开始写
for(j=0;j<64;j++)
WrDatLCD(0); //将第i页的64列均置0清空,一次写8位(一页的一列为8位),
//由于左右半屏片选均打开,所以此命令同时送左右半屏所以左右半屏的同一页的64列均被清空,即每次清空一页的128列
}
CS1=1;
CS2=1;
}
显示开关
//显示开关,参数为1时,开为0时关
void DisON(unsigned char x)
{
CS1=0;
CS2=0; // 选中双屏
WrComLCD(0x3E+x); //关显示指令(0x3E)、开显示指令(0x3F)
CS1=1;
CS2=1;
}
//设置起始行地址,参数x为0~63
void SetLine(unsigned char x)
{
CS1=0;
CS2=0; // 选中双屏
WrComLCD(0XC0+x); //设置起始行地址(行基址0XC0)
CS1=1;
CS2=1;
}
初始化
void LCD_Init(void) //初始化
{
DisON(0); // 选中双屏关闭显示
delay(10);
DisON(1); // 选中双屏开显示
delay(10);
Clear(); // 选中双屏清屏
delay(10);
SetLine(0); // 设置显示的起始行地址为第一行
delay(10);
}
逐列取模、半列显示;
//逐列取模、半列显示;
//一次显示左半屏一行汉字的上半部分,再显示右半屏一行汉字的上半部分;
//再显示左半屏一行汉字的下半部分,再显示右半屏一行汉字的下半部分;
//依照此方法再显示下一行汉字
void LcdDraw16(unsigned char Picture[][32])
{ unsigned char i, j,k ;
for(i = 0;i < 8;i++) //i为页地址
{ /* ==== 先操作左半屏 ==== */
CS1=0;
CS2=1;
WrComLCD(0xB8 + i);//设置页地址
WrComLCD(0x40 + 0);//设置列地址
for(j =0 ;j < 4;j++) //汉字点阵数组行,左半屏四个汉字0~3⋯⋯
for(k=0;k<32;k+=2) //汉字点阵数组列,每个汉字16列
WrDatLCD(Picture[i/2*8+j][k+i%2]); //汉字点阵数组行标与页地址关系i/2*8+j;
//汉字点阵数组列标与页地址关系k+i%2;
//页地址为偶数时,对应汉字上半部分,列标为0、2、⋯⋯、30
//页地址为奇数时,对应汉字上半部分,列标为1、3、⋯⋯、31
//每写一次列地址会自加1
/* ==== 先操作右半屏 ==== */
CS1=1;
CS2=0;
WrComLCD(0xB8 + i);
WrComLCD(0x40 + 0);
for(j =4 ;j < 8;j++) //汉字点阵数组行,左半屏四个汉字4~7⋯⋯
for(k=0;k<32;k+=2)
WrDatLCD(Picture[i/2*8+j][k+i%2]);
}
}
当取模方式变换后相应的显示方式也改变
//列行式取模、半列显示;
//一次显示左半屏一行汉字的上半部分,再显示右半屏一行汉字的上半部分;
//再显示左半屏一行汉字的下半部分,再显示右半屏一行汉字的下半部分;
//依照此方法再显示下一行汉字
void LcdDraw16(unsigned char Picture[][32])
{ unsigned char i, j,k ;
for(i = 0;i < 8;i++) //页地址
{ /* ==== 先操作左半屏 ==== */
CS1=0;
CS2=1;
WrComLCD(0xB8 + i);//设置页地址
WrComLCD(0x40 + 0);//设置列地址
for(j =0 ;j < 4;j++) //汉字点阵数组行,左半屏四个汉字0~3⋯⋯
for(k=0;k<16;k++) //汉字点阵数组列,每个汉字16列
WrDatLCD(Picture[i/2*8+j][k+i%2*16]); //汉字点阵数组行标与页地址关系i/2*8+j;
//汉字点阵数组列标与页地址关系k+i%2*32;
//页地址为偶数时,对应汉字上半部分其列标0-15,下半部分列标16-31
//每写一次列地址会自加1
/* ==== 先操作右半屏 ==== */
CS1=1;
CS2=0;
WrComLCD(0xB8 + i);
WrComLCD(0x40 + 0);
for(j =4 ;j < 8;j++) //汉字点阵数组行,左半屏四个汉字4~7⋯⋯
for(k=0;k<16;k++)
WrDatLCD(Picture[i/2*8+j][k+i%2*16]);
}
}
//逐列取模、整列显示;
//一次显示完一个汉字的整个部分;
//显示完左半屏一行4个汉字,再显示右半屏一行4个汉字;
//依照此方法再显示下一行汉字
void LcdDraw16(unsigned char Picture[][32])
{ unsigned char i, j,k ;
for(i = 0;i < 4;i++) //i对应4行汉字
{ /* ==== 先操作左半屏 ==== */
CS1=0;
CS2=1;
for(j =0 ;j < 4;j++) //汉字点阵数组行,左半屏四个汉字0~3⋯⋯
for(k=0;k<16;k++) //汉字点阵数组列,每个汉字16列
{ WrComLCD(0xB8 + 2*i);//设置页地址
WrComLCD(0x40 + k+j*16);//设置列地址
WrDatLCD(Picture[i*8+j][2*k]); //写汉字的上半列
WrComLCD(0xB8 + 2*i+1);//设置页地址
WrComLCD(0x40 + k+j*16);//设置列地址
WrDatLCD(Picture[i*8+j][2*k+1]); //写汉字的下半列
}
/* ==== 先操作右半屏 ==== */
CS1=1;
CS2=0;
for(j =0 ;j < 4;j++) //汉字点阵数组行,右半屏四个汉字4~7⋯⋯
for(k=0;k<16;k++)
{ WrComLCD(0xB8 + 2*i);
WrComLCD(0x40 + k+j*16);
WrDatLCD(Picture[i*8+j+4][2*k]); //写汉字的上半列,汉字点阵数组行,右半屏四个汉字4~7⋯
WrComLCD(0xB8 + 2*i+1);
WrComLCD(0x40 + k+j*16);
WrDatLCD(Picture[i*8+j+4][2*k+1]); //写汉字的下半列
}
}
}
//列行式取模、整列显示;
//一次显示完一个汉字的整个部分;
//显示完左半屏一行4个汉字,再显示右半屏一行4个汉字;
//依照此方法再显示下一行汉字
void LcdDraw16(unsigned char Picture[][32])
{ unsigned char i, j,k ;
for(i = 0;i < 4;i++) //i对应4行汉字
{ /* ==== 先操作左半屏 ==== */
CS1=0;
CS2=1;
for(j =0 ;j < 4;j++) //汉字点阵数组行,左半屏四个汉字0~3⋯⋯
for(k=0;k<16;k++) //汉字点阵数组列,每个汉字16列
{ WrComLCD(0xB8 + 2*i);//设置页地址
WrComLCD(0x40 + k+j*16);//设置列地址
WrDatLCD(Picture[i*8+j][k]); //写汉字的上半列0-15
WrComLCD(0xB8 + 2*i+1);//设置页地址
WrComLCD(0x40 + k+j*16);//设置列地址
WrDatLCD(Picture[i*8+j][k+16]); //写汉字的下半列16-31
}
/* ==== 先操作右半屏 ==== */
CS1=1;
CS2=0;
for(j =0 ;j < 4;j++) //汉字点阵数组行,右半屏四个汉字4~7⋯⋯
for(k=0;k<16;k++)
{ WrComLCD(0xB8 + 2*i);
WrComLCD(0x40 + k+j*16);
WrDatLCD(Picture[i*8+j+4][k]); //写汉字的上半列,汉字点阵数组行,右半屏四个汉字4~7⋯
WrComLCD(0xB8 + 2*i+1);
WrComLCD(0x40 + k+j*16);
WrDatLCD(Picture[i*8+j+4][k+16]); //写汉字的下半列
}
}
}