• 单片机学习笔记---LCD1602功能函数代码


    目录

    LCD1602.c

    模拟写指令的时序

    模拟写数据的时序

    初始化

    显示字符

    显示字符串

    显示数字

    显示有符号的数字

    显示16进制数字

    显示二进制数

    LCD1602.h

    main.c


    上一篇讲了LCD1602的工作原理,这一节开始代码演示!

    新创建工程:LCD1602功能函数代码

    新创建main.c,LCD1602.c和LCD1602.h文件

    开始代码讲解:

    LCD1602.c

    先根据原理图声明一下这三个控制引脚和八个数据引脚

    1. #include
    2. //引脚定义
    3. sbit LCD_RS=P2^6;
    4. sbit LCD_RW=P2^5;
    5. sbit LCD_E=P2^7;
    6. #define LCD_DataPort P0

    然后根据上一篇讲的时序逐个定义函数

    模拟写指令的时序

    首先是写指令

    1. void LCD_WriteCommand(unsigned char Command)
    2. {
    3. LCD_RS=0;//写指令是低电平
    4. LCD_RW=0;//写
    5. LCD_DataPort=Command;//将指令放在数据口Data port上
    6. LCD_E=1;//使能
    7. LCD_Delay();//延时1ms
    8. LCD_E=0;//关闭使能
    9. LCD_Delay();//延时1ms
    10. }

    由于E等于高电平是时间太快了,我们看到手册上的时序参数都是纳秒级的,单片机最低是微秒级的。

    我们写指令得需要一定的执行时间,如果E的电平给高立马给低的话,如果太快的话可能读不过来

    因此我们需要在E=1之后加一段延时,E=0之后也加一段延时。

    我们在STC软件上生成一个1ms的延时函数

    放在写指令的函数上方,将函数名改成LCD_Delay()

    1. void LCD_Delay() //@12.000MHz 1ms
    2. {
    3. unsigned char i, j;
    4. i = 2;
    5. j = 239;
    6. do
    7. {
    8. while (--j);
    9. } while (--i);
    10. }

    这样我们就可以直接调用这个延时函数了

    模拟写数据的时序

    1. void LCD_WriteData(unsigned char Data)
    2. {
    3. LCD_RS=1;//写数据是高电平
    4. LCD_RW=0;
    5. LCD_DataPort=Data;
    6. LCD_E=1;
    7. LCD_Delay();
    8. LCD_E=0;
    9. LCD_Delay();
    10. }

    接下来我们把这两个函数组合起来根据LCD1602的操作流程完成我们想要的功能!

    初始化

    1. void LCD_Init(void)
    2. {
    3. LCD_WriteCommand(0x38);
    4. LCD_WriteCommand(0x0C);
    5. LCD_WriteCommand(0x06);
    6. LCD_WriteCommand(0x01);
    7. }

    显示字符

    显示字符之前我们得设置光标位置

    1. void LCD_SetCursor(unsigned char Line,unsigned char Column)//行,列
    2. {
    3. if(Line==1)//如果是第一行
    4. {
    5. LCD_WriteCommand(0x80|(Column-1));
    6. }
    7. else //如果是第二行
    8. {
    9. LCD_WriteCommand(0x80|(Column-1)+0x40);
    10. }
    11. }

    如果是第一行,用0x80或上列码-1

    如果是第二行,用0x80或上列码-1,再+0x40

    (如果不知道0x80是什么请看上一篇博客的解释)

    设置好光标位置后开始写显示字符函数 

    1. void LCD_ShowChar(unsigned char Line,unsigned char Column,unsigned char Char)
    2. // 行, 列, 显示的字符
    3. {
    4. LCD_SetCursor(Line,Column);
    5. LCD_WriteData(Char);
    6. }

    但是显示字符在实际的应用中还是远远不够的,我们可以让它显示别的东西

    比如

    显示字符串

    1. void LCD_ShowString(unsigned char Line,unsigned char Column,unsigned char *String)
    2. //传过来的unsigned char*型指针代表字符串的首地址
    3. {
    4. unsigned char i;
    5. LCD_SetCursor(Line,Column);
    6. for(i=0;String[i]!='\0';i++)//遍历字符数组
    7. {
    8. LCD_WriteData(String[i]);
    9. }
    10. }

    显示数字

    由于不能直接显示数字,得先转换成字符然后再显示,

    比如传过来的数字是789,那么我们得对789进行转换成字符7,字符8,和字符9再显示

    怎么转换呢?

    先挨个位取出来数字7,数字8,数字9

    789/100=7.89,对7.89取余7.89%10=7(取出来了高位)

    789/10%10=8(取出来第二位)

    789/1%10=9(取出来最低位)

    我们按照这个方法从高位开始取

    我们得弄个长度的变量 i,i 和取整时的除数的关系是:

    于是我们可以先定义一个次方函数,通过这个函数我们就可以得到返回值等于x的y次方

    1. int LCD_Pow(int X,int Y)
    2. {
    3. unsigned char i;
    4. int Result=1;//如果Y=0,则下面的i
    5. for(i=0;i
    6. {
    7. Result*=X;
    8. //如果Y=1,结果等于1*X就等于X的1次方
    9. //如果Y=2,结果等于1*X*X等于X的2次方
    10. }
    11. return Result;//返回值等于x的y次方
    12. }

    我们用这个规律Number/LCD_Pow(10,i-1)规律取出来的是数字,想要显示成字符的话,要将数字转换成对应的ASCII码值。怎么转换呢?

    我们看着ASCII码表找规律

    由此可见,我们想要将一个数字转换成对应的ASCII码值的话可以将它本身的二进制数值加上0x30,也就是字符'0"的ASCII码值就能得到它的ASCII码值了

    于是就写成'0'+Number/LCD_Pow(10,i-1)%10

    1. void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
    2. {
    3. unsigned char i;
    4. LCD_SetCursor(Line,Column);
    5. for(i=Length;i>0;i--)//从高位开始取
    6. {
    7. LCD_WriteData('0'+Number/LCD_Pow(10,i-1)%10);
    8. //Number/LCD_Pow(10,i-1) 10=X,i-1=Y
    9. }
    10. }

    显示有符号的数字

    1. void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length)
    2. {
    3. unsigned char i;
    4. unsigned int Number1;
    5. LCD_SetCursor(Line,Column);
    6. if(Number>=0)
    7. {
    8. LCD_WriteData('+');
    9. Number1=Number;
    10. }
    11. else
    12. {
    13. LCD_WriteData('-');
    14. Number1=-Number;//变成正数范围是32768,为了保证范围则需要赋给一个无符号的int型
    15. }
    16. for(i=Length;i>0;i--)
    17. {
    18. LCD_WriteData('0'+Number1/LCD_Pow(10,i-1)%10);
    19. }
    20. }

    显示16进制数字

    如果是16进制了话就不是除以10除以100这样子了,而是除以16再对16取余

    所以改成Number/LCD_Pow(16,i-1)%16;

    而且16进制从0~F:0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f

    而A的ASCII码值不是紧接着9的,所以当数字大于等于10的话要用 if 判断一下

    并且这时就不是加0x30了,要改成加上0x41,即 'A' 的ASCII码值

    我们将取出来的单个数字(定义成SingleNumber)+‘A’,但是当取出来的SingleNumber大于等于10的话,我们将它+‘A’就会偏移10。

    比如说SingleNumber=10,那么它的二进制数是0100 1010,加上‘A’的ASCII码0100 0001, 而我们想要SingleNumber是A的话就得减去10。

    如果说SingleNumber=11,那么它的二进制数是0100 1011,加上‘A’的ASCII码0100 0001, 而我们想要SingleNumber是B的话就得减去10。

    因此'A'+SingleNumber-10

    1. void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
    2. {
    3. unsigned char i;
    4. unsigned char SingleNumber;
    5. LCD_SetCursor(Line,Column);
    6. for(i=Length;i>0;i--)
    7. {
    8. SingleNumber=Number/LCD_Pow(16,i-1)%16;//取出单个数值
    9. if(SingleNumber<10)//如果单个数值小于10
    10. {
    11. LCD_WriteData('0'+SingleNumber);
    12. }
    13. else //如果单个数值大于等于10
    14. {
    15. LCD_WriteData('A'+SingleNumber-10);
    16. }
    17. }
    18. }

    显示二进制数

    二进制的话就改成除以2和%2,Number/LCD_Pow(2,i-1)%2

    取出来之后加上'0'的ASCII码就是对应的字符了

    1. void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
    2. {
    3. unsigned char i;
    4. LCD_SetCursor(Line,Column);
    5. for(i=Length;i>0;i--)
    6. {
    7. LCD_WriteData('0'+Number/LCD_Pow(2,i-1)%2);
    8. }
    9. }

    LCD1602.h

    然后声明一下这些函数

    1. #ifndef __LCD1602_H__
    2. #define __LCD1602_H__
    3. void LCD_Init(void);
    4. void LCD_ShowChar(unsigned char Line,unsigned char Column,unsigned char Char);
    5. void LCD_ShowString(unsigned char Line,unsigned char Column,unsigned char *String);
    6. void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
    7. void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length);
    8. void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
    9. void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
    10. #endif

    main.c

    最后在主程序中调用一下这些函数就可以显示了!

    1. #include
    2. #include "LCD1602.h"
    3. #include "Delay.h"
    4. void main()
    5. {
    6. LCD_Init(); //LCD初始化
    7. LCD_ShowChar(1,1,'A'); //在1行1列显示字符A
    8. LCD_ShowString(1,3,"Hello"); //在1行3列显示字符串Hello
    9. LCD_ShowNum(1,9,66,2); //在1行9列显示数字66,长度为2
    10. LCD_ShowSignedNum(1,12,-88,2); //在1行12列显示有符号数字-88,长度为2
    11. LCD_ShowHexNum(2,1,0xA5,2); //在2行1列显示十六进制数字0xA5,长度为2
    12. LCD_ShowBinNum(2,4,0xA5,8); //在2行4列显示二进制数字0xA5,长度为8
    13. LCD_ShowChar(2,13,0xDF); //在2行13列显示编码为0xDF的字符
    14. LCD_ShowChar(2,14,'C'); //在2行14列显示字符C
    15. while(1)
    16. {
    17. }
    18. }

    效果请看视频:

    LCD1602液晶显示屏

    补充:

    如果想要做流动字幕的效果的话,我们可以调用这个指令码0x18

    将写指令的函数声明为外部可调用函数

    然后在主程序中调用这个函数,传这一个移屏指令过去,放在while循环里面,调用一次,移一次

    但是这样太快了,我们可以把我们之前讲过的Delay的模块化程序添加进来,每移一次就Delay 500ms

    效果请看视频:

    LCD1602液晶屏显示流动字幕

    以上就是本节内容,源码会放在评论区,如有问题可评论区留言! 

  • 相关阅读:
    明远智睿IMX6Q烧写Ubuntu18系统,此方法同样适合其它系统!
    使用.NET简单实现一个Redis的高性能克隆版(一)
    大数据:Hive简介及核心概念
    CSS常用样式技巧
    javaweb笔记一
    神经网络优化图片大全,神经网络优化图片下载
    ElasticSerach7.15.2插件中文分词器(IK+pinyin)
    WebRTC点对点通讯建立连接的流程
    小程序里.vue界面中传值的两种方式
    okhttp4.11源码分析
  • 原文地址:https://blog.csdn.net/xiaobaivera/article/details/136121848