🏆文章目录
❤️第一话——程序模块化基础知识
🤡1.1什么是模块化?
上图随便打开了一个工程文件,对于复杂的工程文件我们会调用很多函数,假设都写在一个.c文件下,首先代码读起来很不方便,其次对于后面有相同的函数,也不好直接复制粘贴;但是我们模块化后以后,对于看代码、后期抄代码都有好处,并且实际开发一个项目由一个团队来开发,一个功能可能对应一个模块化,也方便团队合作,简言之,程序模块化就是将程序结构划分,增加程序可读性与可移植性。
🤖1.2如何模块化?
将其对应程序用.c和.h文件表示,并且添加在工程文件下,在程序最开始的时候用#include调用一下,.c是程序文件,内含函数实现,变量定义等,.h是头文件,内含宏定义,结构体定义,函数声明,用之前的延时函数Delay()函数举个列子如下所示:
/****************延时函数主函数Delay()的.c文件*****************/
#include <intrins.h>
void Delay(unsigned char xms)
{
while(xms)
{
unsigned char i=2;
unsigned char j=199;
_nop_();
do
{
while(--j);
}while(--i);
xms--;
}
}
/****************延时函数Delay()的.h文件*****************/
#ifndef _DELAY_H__
#define _DELAY_H__
void Delay(unsigned char xms); //放函数的声明部分
#endif
最后调用的时候,一定要引用该函数的头文件!!!
👾1.3补充知识点——“” <>两种引用符号的区别
引用头文件不同
#include< >引用的是编译器的类库路径里面的头文件
#include“ ”引用的是程序目录的相对路径中的头文件调用文件顺序不同
#include< >编译程序会先到标准函数库中调用文件
#include“ ”编译程序会先从当前目录中调用文件用法不同
#include< >用来包含标准头文件
#include“ ”用来包含非标准头文件
❤️第二话——看懂时序图
😃 2.1什么是时序图?
单片机的时序图,纵轴一般表示对应的IO,横轴代表时间轴,根据芯片写程序时都要对应时序图,尤其写通信方面的程序更需要时序图,读懂时序图是基本的本领,不然程序都不知如何写。
🤣 2.2以LCD1602的时序图分析
- 在上面的直线表示高电平,下面的直线表示低电平
- 线的交叉处表示电平变化处
- valid Data表示有效数据
(这里可能有个疑问,RS和RW根据手册要么是0要么是1,时序图上为什么不是一根直线,其实是因为起始状态有高电平和低电平两种可能;E是一根线的原因是E处于高电平下,DB0~DB7的数据才有效)
== 结合LCD1602写操作时序图可以看下下面代码==
/********************LCD1602写操作***********************/
void lcd_wcmd(unsigned char cmd)
{
while(lcd_busy());
LCD_RS=0;
LCD_RW=0; //写命令
LCD_EN=0;
nops();
P0=cmd;
nops();
LCD_EN=1; //产生一个下降沿,把命令写入
nops();
LCD_EN=0;
}
void lcd_wcmd(unsigned char dat)
{
while(lcd_busy());
LCD_RS=1; //写数据
LCD_RW=0;
LCD_EN=0;
P0=dat;
nops();
LCD_EN=1; //产生一个下降沿,把数据写入
nops();
LCD_EN=0;
}
❤️第三话——LCD1602液晶显示
🏀 3.1 液晶显示原理
(1)液晶的物理特性:液晶控制光线通过的程度是由加在液晶上的电压强弱来控制的。当通电时导通,排列变的有秩序,使光线容易通过,光的路径不改变;不通电时排列混乱,阻止光线通过,改变光的路径。
(2)LCD屏幕的组成:
偏光片:上偏光片,和下偏光片,使背光源的光只能通过下偏光片,不能通过下偏光片
彩色滤光片: 不同强度的光经过红绿蓝三色滤光片之后,会形成各种各样的颜色
液晶层: 通过通电方式来控制液晶的分子排列,从而改变背光源发出的光的路径,如果通电则不改变路径,光不能通过上偏光片,如果不通电则改变光的路径,光可以通过上偏光片,从而进行显示
TFT基板:排列有序的薄膜晶体管,每一个薄膜晶体管都可以调整其电压,从而使单个晶体管范围内液晶进行不同的亮度和颜色显示,也就是我们说的像素点
背光源: 提供均匀的背景光源
(3)显示原理:显示由液晶层的分子排列决定,也就是通过加在液晶上的电压强弱来控制,我们只需要控制每个像素点的电压,就可以达到LCD屏幕显示图形图像字符的效果。
🏐 3.2 LCD1602说明
(1)命名规则:1602代表总共两行显示,每行显示有16个显示点。
第一行第一个位置显示的话,就在00这个地址给显示的内容即可
(2)引脚说明:
(3)字符关系对照表:
显示的内容对应的数据,假设显示一个A,高位0100 低位0001,输入0100 0001就代表A
(4)开发板原理图
LCD4(RS)→P2.6
LCD5(RW)→P2.5
LCD6(E)→P2.7
LCD7(DB0)→P0.0
LCD8(DB1)→P0.1
LCD9(DB2)→P0.2
LCD10(DB3)→P0.3
LCD11(DB4)→P0.4
LCD12(DB5)→P0.5
LCD13(DB6)→P0.6
LCD14(DB7)→P0.7
⚽ 3.2 LCD1602模块化代码实列
这个是网上比较全的关于LCD1602的写好代码,用的时候直接复制好,调用即可,下表是对应函数
/********************LCD1602.c文件**********************/
#include <REGX52.H>
//引脚配置:
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_EN=P2^7;
#define LCD_DataPort P0
//函数定义:
/*
LCD1602延时函数,12MHz调用可延时1ms
*/
void LCD_Delay()
{
unsigned char i, j;
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
/* LCD1602写命令
Command 要写入的命令
*/
void LCD_WriteCommand(unsigned char Command)
{
LCD_RS=0;
LCD_RW=0;
LCD_DataPort=Command;
LCD_EN=1;
LCD_Delay();
LCD_EN=0;
LCD_Delay();
}
/*
LCD1602写数据
Data 要写入的数据
*/
void LCD_WriteData(unsigned char Data)
{
LCD_RS=1;
LCD_RW=0;
LCD_DataPort=Data;
LCD_EN=1;
LCD_Delay();
LCD_EN=0;
LCD_Delay();
}
/*
LCD1602设置光标位置
Line 行位置,范围:1~2
Column 列位置,范围:1~16
*/
void LCD_SetCursor(unsigned char Line,unsigned char Column)
{
if(Line==1)
{
LCD_WriteCommand(0x80|(Column-1));
}
else if(Line==2)
{
LCD_WriteCommand(0x80|(Column-1+0x40));
}
}
/*
LCD1602初始化函数
*/
void LCD_Init()
{
LCD_WriteCommand(0x38);//八位数据接口,两行显示,5*7点阵
LCD_WriteCommand(0x0c);//显示开,光标关,闪烁关
LCD_WriteCommand(0x06);//数据读写操作后,光标自动加一,画面不动
LCD_WriteCommand(0x01);//光标复位,清屏
}
/*
在LCD1602指定位置上显示一个字符
Line 行位置,范围:1~2
Column 列位置,范围:1~16
Char 要显示的字符
*/
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)
{
LCD_SetCursor(Line,Column);
LCD_WriteData(Char);
}
/*
在LCD1602指定位置开始显示所给字符串
Line 起始行位置,范围:1~2
Column 起始列位置,范围:1~16
String 要显示的字符串
*/
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)
{
unsigned char i;
LCD_SetCursor(Line,Column);
for(i=0;String[i]!='\0';i++)
{
LCD_WriteData(String[i]);
}
}
/* 返回值=X的Y次方
*/
int LCD_Pow(int X,int Y)
{
unsigned char i;
int Result=1;
for(i=0;i<Y;i++)
{
Result*=X;
}
return Result;
}
/* 在LCD1602指定位置开始显示所给数字
Line 起始行位置,范围:1~2
Column 起始列位置,范围:1~16
Number 要显示的数字,范围:0~65535
Length 要显示数字的长度,范围:1~5
*/
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
unsigned char i;
LCD_SetCursor(Line,Column);
for(i=Length;i>0;i--)
{
LCD_WriteData(Number/LCD_Pow(10,i-1)%10+'0');
}
}
/*
在LCD1602指定位置开始以有符号十进制显示所给数字
Line 起始行位置,范围:1~2
Column 起始列位置,范围:1~16
Number 要显示的数字,范围:-32768~32767
Length 要显示数字的长度,范围:1~5
*/
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length)
{
unsigned char i;
unsigned int Number1;
LCD_SetCursor(Line,Column);
if(Number>=0)
{
LCD_WriteData('+');
Number1=Number;
}
else
{
LCD_WriteData('-');
Number1=-Number;
}
for(i=Length;i>0;i--)
{
LCD_WriteData(Number1/LCD_Pow(10,i-1)%10+'0');
}
}
/*
* @brief 在LCD1602指定位置开始以十六进制显示所给数字
Line 起始行位置,范围:1~2
Column 起始列位置,范围:1~16
Number 要显示的数字,范围:0~0xFFFF
Length 要显示数字的长度,范围:1~4
*/
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
unsigned char i,SingleNumber;
LCD_SetCursor(Line,Column);
for(i=Length;i>0;i--)
{
SingleNumber=Number/LCD_Pow(16,i-1)%16;
if(SingleNumber<10)
{
LCD_WriteData(SingleNumber+'0');
}
else
{
LCD_WriteData(SingleNumber-10+'A');
}
}
}
/*
在LCD1602指定位置开始以二进制显示所给数字
Line 起始行位置,范围:1~2
Column 起始列位置,范围:1~16
Number 要显示的数字,范围:0~1111 1111 1111 1111
Length 要显示数字的长度,范围:1~16
*/
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
unsigned char i;
LCD_SetCursor(Line,Column);
for(i=Length;i>0;i--)
{
LCD_WriteData(Number/LCD_Pow(2,i-1)%2+'0');
}
}
/*********************LCD1602.h文件**************************/
#ifndef __LCD1602_H__
#define __LCD1602_H__
//用户调用函数:
void LCD_Init();
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char);
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String);
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length);
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
#endif
🥎 3.3 LCD1602实际调用使用案列
在第二行,第二个位置显示A
要是需要LCD1602具体资料的私聊我,或者留下邮箱免费分享。