单片机之显示设备

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上的滚动显示心形图片
  1. 8行不够显示,一个字符占4列,4个字符16列,一屏(帧)显示2个字符。
  2. 滚动显示:将一帧数据左移一列,形成新一帧的数据,需要17帧数据,最后一帧为8列不显示的列编码,需补充8列编码0xff。
  3. 一帧数据显示完后不要马上显示下一帧,若一帧只显示一次就换一帧新数据,会导致旧帧数据没有被视觉捕捉到就更换了,所以一帧数据需要重复显示多次再切换为下一帧,重复的次数决定滚动显示的速度,重复的次数越多滚动速度越慢。
 #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]); //写汉字的下半列
                 } 
    }   
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值