51之LCD1602与模块化编程

        LCD1602,即我们开发板上附赠的那个液晶显示屏,我们通常可以使用这个液晶显示屏用来做调试工具,我们使用一下江科大提供的关于这个LCD1602的代码,用来为我们提供了类似C语言标准库里面的printf函数的用法,只是这个更加复杂一点点。

直接上代码:

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

 LCD1602.c

#include <REGX52.H>//引脚配置:
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_EN=P2^7;
#define LCD_DataPort P0//函数定义:
/*** @brief  LCD1602延时函数,12MHz调用可延时1ms* @param  无* @retval 无*/
void LCD_Delay()
{unsigned char i, j;i = 2;j = 239;do{while (--j);} while (--i);
}/*** @brief  LCD1602写命令* @param  Command 要写入的命令* @retval 无*/
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();
}/*** @brief  LCD1602写数据* @param  Data 要写入的数据* @retval 无*/
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();
}/*** @brief  LCD1602设置光标位置* @param  Line 行位置,范围:1~2* @param  Column 列位置,范围:1~16* @retval 无*/
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));}
}/*** @brief  LCD1602初始化函数* @param  无* @retval 无*/
void LCD_Init()
{LCD_WriteCommand(0x38);//八位数据接口,两行显示,5*7点阵LCD_WriteCommand(0x0c);//显示开,光标关,闪烁关LCD_WriteCommand(0x06);//数据读写操作后,光标自动加一,画面不动LCD_WriteCommand(0x01);//光标复位,清屏
}/*** @brief  在LCD1602指定位置上显示一个字符* @param  Line 行位置,范围:1~2* @param  Column 列位置,范围:1~16* @param  Char 要显示的字符* @retval 无*/
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)
{LCD_SetCursor(Line,Column);LCD_WriteData(Char);
}/*** @brief  在LCD1602指定位置开始显示所给字符串* @param  Line 起始行位置,范围:1~2* @param  Column 起始列位置,范围:1~16* @param  String 要显示的字符串* @retval 无*/
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]);}
}/*** @brief  返回值=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;
}/*** @brief  在LCD1602指定位置开始显示所给数字* @param  Line 起始行位置,范围:1~2* @param  Column 起始列位置,范围:1~16* @param  Number 要显示的数字,范围:0~65535* @param  Length 要显示数字的长度,范围:1~5* @retval 无*/
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');}
}/*** @brief  在LCD1602指定位置开始以有符号十进制显示所给数字* @param  Line 起始行位置,范围:1~2* @param  Column 起始列位置,范围:1~16* @param  Number 要显示的数字,范围:-32768~32767* @param  Length 要显示数字的长度,范围:1~5* @retval 无*/
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指定位置开始以十六进制显示所给数字* @param  Line 起始行位置,范围:1~2* @param  Column 起始列位置,范围:1~16* @param  Number 要显示的数字,范围:0~0xFFFF* @param  Length 要显示数字的长度,范围:1~4* @retval 无*/
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');}}
}/*** @brief  在LCD1602指定位置开始以二进制显示所给数字* @param  Line 起始行位置,范围:1~2* @param  Column 起始列位置,范围:1~16* @param  Number 要显示的数字,范围:0~1111 1111 1111 1111* @param  Length 要显示数字的长度,范围:1~16* @retval 无*/
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');}
}

        我们在调用标准库的库函数的时候,是使用<>的,比如:#include <REGX52.H>,但是我们在使用自己定义的头文件的时候,一般要使用”“,比如:#include "LCD1602.h"

        这里我们演示一下怎么使用这个函数:

        首先,第一步我们是需要把这个头文件+C文件都复制粘贴在这个工程目录下(或者直接新建一个头文件和C文件,然后把代码粘贴进去,总之这个过程目录下就是要有这个头文件+C文件)

        下一步,如果我们是直接把两个文件粘贴到这个工程目录下的,我们就要把它们俩添加到工程中

点击Add Existing Files

        先把选择All files点开,然后按住Ctrl键,同时把我们想要选的.h文件和.c文件选上,但后点击Add添加这两个文件。

        然后看到就说明添加成功了。

        于是就可以开始测试代码,头文件内包含的函数声明才是我们可以使用的函数,而且我们想要使用头文件里面的函数还要我们在main函数所在的c文件中包含这个头文件,比如:#include "LCD1602.h"

        然后我们就可以在这个main函数中使用些外部的函数了。但是这里还会遇到一个问题:

        这里下面显示0 Error(s), 7 Warning(s),说明我们的函数中有7个警告,一般来说我们是不需要管他们的,因为这些警告存在的原因就是因为我们定义的函数没有全部使用,它就会报警告,但是我们又看的很不舒服怎么办呢?我们可以点击消除这些警告,具体操作就是:

        我们在这里配置完成之后就可以把警告消除了

        这里主要是需要学习一下怎么自己定义一个函数,比如怎么定义一个头文件,怎么定义一个c文件。

        我们拿最经典的Delay函数来做一个外包函数,我们需要模仿这个LCD1602的头文件和C文件定义,把我们常用的一些文件都可以拷贝直接使用。

        首先,我们要频繁使用Delay函数,我们就要使用这个函数创建一个c和h文件,具体也很好实现

C代码不用变,直接把它放在一个c文件中就行了:

#include <REGX52.H>
#include <INTRINS.H>void Delay(unsigned int xms)		//@11.0592MHz
{while(xms--){unsigned char i, j;_nop_();i = 2;j = 199;do{while (--j);} while (--i);}
}

        然后我们再定义h代码,也就是这个函数的定义,这里还有一个东西需要注意,就是文件的防重复定义,就是我们可以加上类似

#ifndef __LCD1602_H__
#define __LCD1602_H__
//函数声明...
#endif

        这样的东西就是为了防止重复定义的,比如说我们有两个c文件(A和B)都引用了同一个h文件,然后这个函数声明就会在两个c文件中重复被声明,这会导致重复声明的报错,所以我们要使用这样的格式来防止重复定义

大概的代码意思就是:如果定义了xxx,就定义xxx,(函数定义),终止定义;

        这里如果我们定义过这个 __LCD1602_H__,就会进入然后定义 __LCD1602_H__,并且声明函数,再出去,下次再来到这里的时候,编译器检查到我们的__LCD1602_H__被定义过了,就不会再进去,然后这个里面的函数也就不会再被声明。这就是防止重复声明的操作。

        依葫芦画瓢,我们还可以把Delay函数放在这里面,进行防重复定义处理:

        注意这里要使用.h定义,不然编译会出错,而且这个错误很难找到,可能你找大半天都找不到,使用这里一定要注意一下。

        然后像这样就行了:

#ifndef __DELAY_H__
#define __DELAY_H__void Delay(unsigned int xms);#endif

        然后需要注意的是:这里的.h文件中包含的头文件不能被.c文件或者是任何调用这个.h文件的文件调用,也就是说.h文件里使用的任何头文件都是不能被其他的文件间接使用的,然后我们这里又写了防止重复定义的预处理,所以我们这个函数被声明了一次就不会被再次声明。但是Kel5就有一点不太一样的地方:这个声明已经声明过一次了,按理来说这个声明的函数就可以反复使用了,但是这里好像还是无法使用。

        比方说我们在main函数中已经包含了头文件A,A中有a函数的声明,我们又定义了一个源文件B.c,B中调用了a函数,按理来说我们编译的话,这个main函数中已经有了函数a的声明,我们在main函数中使用B中的函数的时候应该是可以正常使用的,虽然我们没有在B中声明函数a,但是我们的main函数中有函数a的声明,在main函数中使用带有a函数的B的任何函数都应该是可以正常使用的。但是Keil5好像是不支持这样的操作的,所以我们对B的话需要再写一个a函数的声明,然后再去使用B,而且我们只能在B中声明,如果是包含头文件A的话,因为我们做了防止重复包含的预处理,是不能再次通过包含头文件包含函数a的。所以在Keil5中我们只能通过重复声明的方式在不同的c文件中使用同一个函数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/593949.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深澜计费管理系统 任意文件读取漏洞复现

0x01 产品简介 深澜计费管理系统是是一套完善的领先的具有复杂生物型特征的弹性认证计费系统。系统主要由 AAA 认证计费平台、系统运营维护管理平台、用户及策略管理平台、用户自助服务平台、智能客户端模块、消息推送模块、数据统计模块组成。目前在全球为超过 2500 家客户提…

openEuler 22.03 SP3 安装图像桌面 UKUI

UKUI 是麒麟软件团队历经多年打造的一款 Linux 桌面&#xff0c;主要基于 GTK 和 QT 开发。与其他 UI 界面相比&#xff0c;UKUI 更加注重易用性和敏捷度&#xff0c;各元件相依性小&#xff0c;可以不依赖其他套件而独自运行&#xff0c;给用户带来亲切和高效的使用体验。 UK…

【Qt】文件

目录 一、输入输出设备类 二、文件读写类 三、文件和目录信息类 文件操作是应用程序必不可少的部分。Qt作为一个通用开发库&#xff0c;提供了跨平台的文件操作能力。Qt提供了很多关于文件的类&#xff0c;通过这些类能够对文件系统进行操作&#xff0c;如文件读写、文件信息…

基于lora技术对Gemma(2B)大模型的微调实践

一、概述 本文主要基于Lora技术&#xff0c;在Google colab上用A100对Gemma 2B大模型进行了指令微调&#xff0c;第一次指令微调是采用databricks-dolly-15k 作为数据集&#xff0c;取得了不错的微调效果&#xff0c;能准确用英文回答问题&#xff0c;但databricks-dolly-15k …

无库存,无货源,怎么做视频号小店?

大家好&#xff0c;我是电商糖果 有朋友跟糖果说&#xff0c;这视频号小店非常火&#xff0c;自己想趁着这次的风口开店赚钱。 自己无库存&#xff0c;也无货源&#xff0c;能开店卖货不&#xff1f; 糖果告诉他&#xff0c;能卖货&#xff0c;而且还可以让他不到一个月时间…

6:算法基础--6.1:线性结构 ,6.2:查找算法

转上一节&#xff1a; http://t.csdnimg.cn/ql5Cdhttp://t.csdnimg.cn/ql5Cd 课程内容提要&#xff1a; 6&#xff1a;知识点考点详解 6.1&#xff1a;线性结构 通常分析时间复杂度的方法是从算法中选取-种对于所研究的问题来说是基本运算的操作&#xff0c;以 该操作重…

用顺序表实现通讯录

前言 这次的通讯录是基于上一篇的动态顺序表的基础上实现的&#xff0c;如果对动态顺序表不熟悉&#xff0c;可以打开这个链接阅读http://t.csdnimg.cn/9zJ5g&#xff0c;这里我们会调用动态顺序表的函数。 如果想看静态顺序表实现通讯录&#xff0c;可以打开这个链接阅读http:…

Redis缓存穿透和缓存雪崩

一、缓存穿透 1 什么是缓存穿透 缓存穿透说简单点就是大量请求的 key 根本不存在于缓存中&#xff0c;导致请求直接到了数据库上&#xff0c;根本没有经过缓存这一层。举个例子&#xff1a;某个黑客故意制造我们缓存中不存在的 key 发起大量请求&#xff0c;导致大量请求落到数…

1 【机器学习】统计学习的概念

&#x1f388;个人主页&#xff1a;豌豆射手^ &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;李航统计学习笔记 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习…

如何借助Idea创建多模块的SpringBoot项目

目录 1.1、前言1.2、开发环境1.3、项目多模块结构1.4、新建父工程1.5、创建子模块1.6、编辑父工程的pom.xml文件 1.1、前言 springmvc项目&#xff0c;一般会把项目分成多个包:controler、service、dao、utl等&#xff0c;但是随着项目的复杂性提高&#xff0c;想复用其他一个模…

蓝桥-时间显示

目录 题目链接 代码 题目链接 1.时间显示 - 蓝桥云课 (lanqiao.cn) 代码 #include <bits/stdc.h> using namespace std;int main() {long long x;cin>>x;int h,m,s;x x / 1000 % (3600*24); // 毫秒化秒&#xff0c;并且保留最后一天的时间h x / 3600; //求得…

深入理解计算机系统 家庭作业 2.84

这题没有这个要求所以可以用 ? > : < 这种运算 以下代码用的是位级运算.因为我误解了题意 呜呜呜 想看用判断的代码请自行百度 ((((ux<<9>>9)<<((ux<<1>>24)-127)) - ((uy<<9>>9)<<((uy<<1>>24)-127)))>…