stm32驱动LCD12864液晶屏驱动程序,亲测可行,复制直接能用!

stm32驱动LCD12864液晶屏驱动程序,亲测可行,复制直接能用!

biao2488890051 2018-11-14 20:31:17  21564  已收藏 64
分类专栏: stm32
版权
废话不多说,直接贴程序,你自己复制过去即可,免得我通过把工程上传的方式,你下载还得需要c币,这个现在很贵呀!!!

就两个文件,LCD12864.h和LCD12864.c,自己复制过去后,改一下引脚即可

(如果你连改引脚都不会,那你看来是初初学者,那你自己百度吧),单片机主频:72MHZ

LCD12864.h如下所示

#ifndef __LCD12864_H
#define __LCD12864_H     
#include "sys.h"
 
 
#define LCD1602_RS PEout(0)    // PE0        go define之后我们会发现,这个宏最后就是在这个io的地址这里赋值
                                        // #define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr)) 
#define LCD1602_RW PEout(1)    // PE1    
#define LCD1602_E PAout(3)    //  PA3    
 
 
void LCD12864IO_Init(void);
 
void LCD1602_DB_IO_outputMode(void);
void LCD1602_DB_IO_inputMode(void);
 
void write_LCD1602_DB(uint8_t data);
uint8_t read_LCD1602_DB(void);
 
 
void InitLcd1602(void);
void LcdShowStr(unsigned char row, unsigned char column, unsigned char *str);
void LcdWriteCmd(unsigned char cmd);
 
void LcdShowImage(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t *img);
void LcdClearArea(uint8_t x, uint8_t y, uint8_t w, uint8_t h);
 
//#ifndef _HE_
extern uint8_t HE[];
extern uint8_t QQ[];
extern uint8_t myVX[];
 
//#endif
 
#endif
LCD12864.c如下所示:

#include "lcd12864.h"
#include "delay.h"
//#define _HE_
 
uint8_t HE[]=
{
 
 
0x20,0x00,0x70,0x00,0x1E,0x00,0x10,0x3E,0x10,0x22,0xFF,0x22,0x10,0x22,0x18,0x22,0x38,0x22,0x54,0x22,0x54,0x22,0x12,0x22,0x11,0x3E,0x10,0x22,0x10,0x00,0x10,0x00/*"和",0*/
/* (16 X 16 , 宋体 )*/
    
};
 
uint8_t QQ[]=
{
 
 
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x0F,0xE0,0x3F,0xE0,0x7F,0xF0,0x7F,0xF8,0x7D,0xF0,0x3C,0xD0,0x2C,0x30,0x30,0x70,0x38,0xE0,0x1F,0x00,0x00,0x00,0x00/*"C:\Users\Administrator\Desktop\qqXiaoBing.bmp",0*/
/* (16 X 16 )*/
 
 
 
    
};
 
u8 myVX[]=
{
0x00,0x0D,0xFC,0xC8,0x0F,0x3F,0xB0,0x00,0x00,0x0D,0xFC,0xC8,0x0F,0x3F,0xB0,0x00,
0x3F,0xCC,0x7C,0x0F,0x93,0x26,0x33,0xFC,0x20,0xCD,0x80,0x31,0xF0,0x9F,0xB3,0x04,
0x20,0xCD,0x80,0x31,0xF0,0xDF,0xB3,0x04,0x20,0xCF,0xFF,0xC6,0x0C,0xD9,0xB3,0x04,
0x20,0xCF,0xFF,0xC6,0x0C,0x99,0xB3,0x04,0x20,0xCF,0x80,0xCE,0x1C,0xE1,0xB3,0x04,
0x20,0xCF,0xC0,0xCE,0x1C,0xE1,0x33,0x04,0x3F,0xCD,0xE0,0x30,0x00,0xC6,0x33,0xFC,
0x00,0x0D,0x9B,0x36,0x6C,0xD9,0xB0,0x00,0x00,0x0D,0x9B,0x36,0x6C,0xD9,0xB0,0x00,
0xFF,0xFD,0x9F,0xC9,0x83,0x9F,0xBF,0xFF,0xFF,0xFD,0x9F,0xC9,0x83,0x9F,0xBF,0xFF,
0xE0,0xCD,0xFC,0x07,0xF0,0x27,0xC0,0xE0,0x06,0x32,0x79,0xC6,0x33,0x39,0xBC,0x99,
0x06,0x32,0x7B,0xC6,0x13,0x39,0xBC,0x9B,0xF9,0x01,0x9E,0x0F,0x9C,0x18,0x33,0x64,
0xF9,0x01,0x9C,0x0F,0x9C,0x18,0x33,0x64,0x06,0xFC,0x63,0x08,0x73,0x18,0x33,0x1C,
0x06,0xFC,0x61,0x08,0x73,0x18,0x33,0x1C,0xD8,0x03,0x9F,0x01,0x8F,0xE7,0xF3,0xE3,
0xD8,0x03,0x9F,0x01,0x8F,0xE7,0xF3,0xE3,0xFE,0x31,0x98,0xC9,0xFC,0x87,0x8C,0x87,
0x1F,0x03,0x9F,0x35,0xEC,0x18,0x43,0x98,0x1F,0x03,0x9F,0x36,0xEC,0x18,0x43,0x98,
0xFE,0xF3,0xE0,0x7F,0xAC,0x39,0xB0,0xF8,0xFE,0xF3,0xE0,0xFF,0xDC,0x39,0xB0,0xF8,
0x3E,0xC3,0xFF,0xE6,0x5C,0xE6,0x70,0x60,0xF7,0xF3,0x6F,0xFD,0xCC,0x1F,0xBC,0x9F,
0xE7,0xF2,0x67,0xFE,0xFF,0x1F,0xBC,0x9F,0xC7,0xCE,0x7D,0xA1,0xFF,0x00,0x3C,0xE0,
0xC7,0xCE,0x7D,0x83,0xBB,0x80,0x3C,0xE0,0x3F,0x3E,0x1C,0x83,0xFF,0x99,0xFF,0xFB,
0x3F,0x3E,0x1C,0x43,0xFF,0x99,0xFF,0xFB,0x19,0x02,0x18,0x7F,0xFF,0xB8,0x40,0x07,
0x00,0xFC,0x79,0xF3,0xFF,0x39,0xFC,0x83,0x00,0xFC,0x7B,0xF1,0xFF,0x79,0xFC,0x83,
0xD9,0x00,0x04,0xF1,0xFF,0x18,0x0F,0xF8,0xD9,0x00,0x04,0xF1,0x83,0x18,0x0F,0xF8,
0x18,0xFC,0x19,0xF8,0x1F,0x39,0x80,0xFB,0x18,0xFC,0x19,0xF8,0x1F,0x39,0x80,0xFB,
0x27,0xCE,0x66,0x31,0xEC,0x07,0xC0,0x1C,0x38,0x30,0x07,0x0E,0x73,0xE0,0x3C,0x84,
0x38,0x30,0x07,0x0E,0x73,0xE0,0x3C,0x84,0x3E,0xC1,0x81,0xC1,0x83,0x00,0x7C,0xF8,
0x3E,0xC1,0x83,0xC1,0x83,0x00,0x7C,0xF8,0x21,0x31,0x99,0xF6,0x1C,0x3F,0xFC,0xF8,
0x21,0x31,0x9B,0xF6,0x1C,0x3F,0xFC,0xF8,0x39,0x0C,0x1B,0xC9,0x93,0x20,0x00,0x03,
0xFF,0xFC,0x03,0x0E,0x6F,0x61,0x1E,0x7F,0xFF,0xFC,0x03,0x0E,0x6F,0x21,0xBF,0x7F,
0x00,0x0F,0xE3,0xFF,0xFF,0x81,0xB3,0x18,0x00,0x0F,0xE3,0xFF,0xFF,0xC1,0xB3,0x18,
0x3F,0xCE,0x67,0x37,0x83,0xF8,0x3F,0x7B,0x3F,0xCE,0x67,0x37,0x83,0xF8,0x3E,0x79,
0x20,0xCC,0x1B,0x36,0x13,0x18,0x00,0x60,0x20,0xCD,0xE7,0x07,0xEF,0x86,0x30,0x07,
0x20,0xCD,0xE7,0x07,0xEF,0xC6,0x30,0x07,0x20,0xCC,0x7C,0xCE,0x63,0xC6,0x3C,0x9C,
0x20,0xCC,0x7C,0xCE,0x63,0xC6,0x3C,0x9C,0x3F,0xCE,0x67,0x39,0xEC,0xDE,0x0C,0xFC,
0x3F,0xCF,0x67,0x3D,0xE4,0x9E,0x0D,0xFC,0x00,0x0F,0xE4,0x3E,0x63,0x19,0xFF,0x80,/*"C:\Users\Administrator\Desktop\我的微信二维码.bmp",0*/
/* (64 X 64 )*/
 
}
;
 
 
void LCD12864IO_Init(void)
{
 
 GPIO_InitTypeDef  GPIO_InitStructure;
     
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG|RCC_APB2Periph_GPIOE|RCC_APB2Periph_GPIOA, ENABLE);     
                                                            //使能PG,PE,PA端口时钟
 GPIO_InitStructure.GPIO_Pin = 0XFF;                         //PG端口配置
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;              //推挽输出
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;             //IO口速度为50MHz
 GPIO_Init(GPIOG, &GPIO_InitStructure);                         //根据设定参数初始化GPIOG.0
 GPIO_SetBits(GPIOG,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);                         //PG.0 输出高
 
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;        //PE.0,PE.1,端口配置
 GPIO_Init(GPIOE, &GPIO_InitStructure);                         //根据设定参数初始化GPIOE.0.1
 GPIO_SetBits(GPIOE,GPIO_Pin_0|GPIO_Pin_1);                 //PE.0.1 输出高 
 
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;                     //PA3端口配置
 GPIO_Init(GPIOA, &GPIO_InitStructure);                         //根据设定参数初始化GPIOPA3
 GPIO_SetBits(GPIOA,GPIO_Pin_3);                              //PA3 输出高 
    
}
void LCD1602_DB_IO_outputMode(void)
{
 GPIO_InitTypeDef  GPIO_InitStructure;
 GPIO_InitStructure.GPIO_Pin = 0XFF;                         //PG端口配置
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;              //推挽输出
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;             //IO口速度为50MHz
 GPIO_Init(GPIOG, &GPIO_InitStructure);                         //根据设定参数初始化GPIOG.0
 GPIO_SetBits(GPIOG,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);                         //PG.0 输出高
    
}
 
void LCD1602_DB_IO_inputMode(void)
{
 GPIO_InitTypeDef  GPIO_InitStructure;
 GPIO_InitStructure.GPIO_Pin = 0XFF;                         //PG端口配置
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;                  //上拉输入
 GPIO_Init(GPIOG, &GPIO_InitStructure);                         //根据设定参数初始化GPIOG.0
 GPIO_SetBits(GPIOG,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);                         //PG.0 输出高
    
}
 
void write_LCD1602_DB(uint8_t data)
{
    GPIO_Write(GPIOG,(uint16_t)data);
}
 
uint8_t read_LCD1602_DB(void)
{
    uint8_t value;
    value=(uint8_t)GPIO_ReadInputData(GPIOG);
    return value;
}
 
/* 等待液晶准备好 */
void LcdWaitReady()
{
    unsigned char sta;
        delay_us(1);
 
    LCD1602_RS = 0;
        delay_us(1);
 
    LCD1602_RW = 1;
        delay_us(1);
 
    do {
        LCD1602_E = 1;
        delay_us(1);
 
        LCD1602_DB_IO_inputMode();
        sta = read_LCD1602_DB();
        LCD1602_DB_IO_outputMode();    
        delay_us(1);
 
        LCD1602_E = 0;
        delay_us(1);
 
    } while (sta & 0x80);     //bit7等于1表示液晶正忙,重复检测直到其等于0为止
}
/* 向LCD1602液晶写入一字节命令,cmd-待写入命令值 */
void LcdWriteCmd(unsigned char cmd)
{
        delay_us(1);
 
    LcdWaitReady();
        delay_us(1);
 
    LCD1602_RS = 0;
        delay_us(1);
 
    LCD1602_RW = 0;
        delay_us(1);
 
    write_LCD1602_DB(cmd);
        delay_us(1);
 
    LCD1602_E  = 1;
        delay_us(1);
 
    LCD1602_E  = 0;
        delay_us(1);
 
}
 
/* 向LCD1602液晶写入一字节数据,dat-待写入数据值 */
void LcdWriteDat(unsigned char dat)
{
        delay_us(1);
 
    LcdWaitReady();
        delay_us(1);
 
    LCD1602_RS = 1;
        delay_us(1);
 
    LCD1602_RW = 0;
        delay_us(1);
 
    write_LCD1602_DB(dat);
        delay_us(1);
 
    LCD1602_E  = 1;
        delay_us(1);
 
    LCD1602_E  = 0;
        delay_us(1);
 
}
/* 设置显示RAM起始地址,亦即光标位置,(x,y)-对应屏幕上的字符坐标 */
void LcdSetCursor(unsigned char x, unsigned char y)
{
    unsigned char addr;
    
    if (y >= 2)                               //说明我们想显示在右半屏
    {
        y -= 2;
        x += 8;                            //那么x就得往右挪动8个汉字了
    }
    addr = y*16 + x;                    //现在这个是以一个汉字为单位,这里所有所说的汉字为单位的意思是16*16
                                        //由起始DDRAM地址连续写入字符串                  
                                        //addr的值是所有的汉字后面的地址,也是汉字为单位,即ddram也是以汉字为单位的
    LcdWriteCmd(0x30);                     //启动DDRAM操作
    LcdWriteCmd(0x80|addr);                //设置ram地址
}
/* 在液晶上显示字符串,(x,y)-对应屏幕上的起始坐标,str-字符串指针 */
void LcdShowStr(unsigned char row, unsigned char column, unsigned char *str)
{
    unsigned char n=0,a;
    unsigned char *fore_str;
    LcdSetCursor(column, row);           //设置起始地址
    while (*str != '\0')                  //连续写入字符串数据,直到检测到结束符
    {
        
        if((n+1)%2==0)                    //奇数地址
        {
            fore_str=str-1;
            if(*fore_str>0x80)
            {
                LcdWriteDat(*str++);
            }
            else if(*str>0x80)
                LcdWriteDat(' ');
            else if(*str<=0x80)
                LcdWriteDat(*str++);
        }            
        else
            LcdWriteDat(*str++);          //先取str指向的数据,然后str自加1
        n++;
 
        if((n+2*column)%16==0)
        {
            a=(n+2*column)/16;
            if(row==0)
            {
            if(a==1)
                LcdWriteCmd(0x90);
            if(a==2)
                LcdWriteCmd(0x88);
            if(a==3)
                LcdWriteCmd(0x98);
            if(a==4)
                LcdWriteCmd(0x80);
            }
 
            if(row==1)
            {
            if(a==1)
                LcdWriteCmd(0x88);
            if(a==2)
                LcdWriteCmd(0x98);
            if(a==3)
                LcdWriteCmd(0x80);
            if(a==4)
                LcdWriteCmd(0x90);
            }    
 
            if(row==2)
            {
            if(a==1)
                LcdWriteCmd(0x98);
            if(a==2)
                LcdWriteCmd(0x80);
            if(a==3)
                LcdWriteCmd(0x90);
            if(a==4)
                LcdWriteCmd(0x88);
            }    
 
            if(row==3)
            {
            if(a==1)
                LcdWriteCmd(0x80);
            if(a==2)
                LcdWriteCmd(0x90);
            if(a==3)
                LcdWriteCmd(0x88);
            if(a==4)
                LcdWriteCmd(0x98);
            }    
 
 
    
        }
    }
}/* 初始化1602液晶 */
void InitLcd1602()
{
    LcdWriteCmd(0x38);  //16*2显示,5*7点阵,8位数据接口
    LcdWriteCmd(0x0C);  //显示器开,光标关闭
    LcdWriteCmd(0x06);  //文字不动,地址自动+1
    LcdWriteCmd(0x01);  //清屏
}
 
 
 
 
/*
* 函数名:LcdShowImage
* 描  述:在显示屏上显示一幅图像
* 输  入:img - 待显示图像指针
*         x - 屏幕显示横坐标(以像素为单位)
*         y - 屏幕显示纵坐标(以像素为单位)
*         w - 图像宽度(以像素为单位)
*         h - 图像高度(以像素为单位)
* 输  出:无
* 备  注:x与w必须是16的整数倍,因CGRAM最小寻址单位为2字节;y与h可为0-63的任意值。
*/
 
//经过我的不断测试,y和h的值也是可以取到64,而且显示汉字,也得取到16而不是15,那么来说,是多少像素高度,这里就填多少
void LcdShowImage(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t *img)
{
    uint16_t i;
    uint8_t xi,yi;
    uint8_t xt,yt;
 
    x >>= 4;
    w >>= 3;
    i = 0;
    LcdWriteCmd(0x36); //启动CGRAM操作
    
    for (yi=0; yi<h; yi++)
    {
        yt = y+yi;
        xt = x;
        if (yt >= 32)
        {
            yt -= 32;
            xt += 8;
        }
        LcdWriteCmd(0x80|yt);
        LcdWriteCmd(0x80|xt);
        for (xi=0; xi<w; xi++)
        {
            LcdWriteDat(img[i++]);
        }
    }
}
 
/*
* 函数名:LcdClearArea
* 描  述:清除屏幕上的一块图形显示区域
* 输  入:x - 区域起始横坐标(以像素为单位)
*         y - 区域起始纵坐标(以像素为单位)
*         w - 区域宽度(以像素为单位)
*         h - 区域高度(以像素为单位)
* 输  出:无
* 备  注:x与w必须是16的整数倍,因CGRAM最小寻址单位为2字节;y与h可为0-63的任意值。
*/
 
 
//记住,绘图模式时候屏幕默认有乱点显示的数据的,需要我们先调用这个函数后面才能正常显示
 
void LcdClearArea(uint8_t x, uint8_t y, uint8_t w, uint8_t h)
{
    uint8_t xi,yi;
    uint8_t xt,yt;
 
    x >>= 4;
    w >>= 3;
    LcdWriteCmd(0x36);             //启动CGRAM操作
    for (yi=0; yi<h; yi++)
    {
        yt = y+yi;
        xt = x;
        if (yt >= 32)
        {
            yt -= 32;
            xt += 8;
        }
        LcdWriteCmd(0x80|yt);
        LcdWriteCmd(0x80|xt);
        for (xi=0; xi<w; xi++)
        {
            LcdWriteDat(0x00);     //写入0x00以清除显示
        }
    }
}
 
 主函数main()中这样调用即可:

void main()
{
    LCD12864IO_Init(void);
    // 为什么驱动函数会出现1602的字样,因为这个LCD12864的驱动程序我是从1602液晶屏移植过来的,
    // 只是忘记改了名字而已,就这样吧
    InitLcd1602(void);
    LcdShowStr(1,1,"hello 你好");
    while(1);
}
程序完全o98k,拿去用吧!
————————————————
版权声明:本文为CSDN博主「biao2488890051」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/kangkanglhb88008/article/details/84073196

  • 6
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qq_20312079

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值