Autoleaders控制组——51单片机学习笔记(2)

51单片机学习(2)

1.模块化编程

1.1模块化编程的意义

在学习单片机的途中,随着我们的知识不断扩展,我们能写出的代码也越来越复杂,越来越长了,有时我们自己写出的很长的代码,出现了错误,需要调试,但奈何自己的代码实在是太长了,真的不好分析到底是哪里出错了。这是因为我们将太多的函数和代码放在一个main.c的文件里,导致代码过度堆积。如果我们能够条理清晰地去将不同作用的代码和函数放在不同的xxx.c文件里面,等我们需要用的时候直接调用它,不是会方便很多吗?
像上面说的这种方法被称为模块化编程,大致就是创建一些其他文件,将一些函数放在这个文件里面,并创建一个同名的可以被引入的头文件,在main.c里只需要引入头文件,就可以在主函数里使用,达到简化的目的。使用模块化编程可极大的提高代码的可阅读性、可维护性、可移植性等。

1.2模块化编程的操作

模块化编程的操作也很简单。我们打开keil 5后,像往常一样创建新的工程,在新的工程中创建新的main.c文件,再创建一个xxx.c,将平常要放到main.c的大把大把函数直接放进xxx.c里面,等这些都完成后,我们再点击创建一个新的文件,一个xxx.h文件,再把函数的原型声明放进来,像下面这样:

#ifndef __DELAY_H_ 
#define __DELAY_H_ 

void Delay(unsigned int h);//注意原型声明末尾有分号。
	
#endif

我们来解释以下,除了函数声明以外,还有很多其他的东西:

#ifndef  __XXX_H_  
 /*  其实这是if not define的缩写,
目的是判断之前有没有定义过__DELAY_H_,
避免重复定义,如果已经定义过了,
那就不执行以后的语句。  */

#define  __XXX_H_
/*用于定义一个头文件,定义完之后,
可以在其它文件里引入头文件,
然后可以直接使用头文件里面的函数。*/

#endif
// 一个结束语句的判断符,相当于一个  '}'

头文件格式是__XXX_H_,双下滑线+头文件名+下滑线+H+下滑线。
当定义完了头文件后,在main.c里面,我们只需要#include "XXX.H",就可以调用头文件里面的函数了。
在头文件里面,为了方便阅读,一般会给出较为详细的注释,以便于读懂函数。

2.LCD1602(液晶显示屏)

2.1液晶显示屏的介绍

LCD1602是一块两排的液晶显示屏,可以输出字母,数字或者一些符号,相比数码管,它可以显示的信息更多,但也使它更加难以解释。
这是一个原理简单,但驱动操作比较复杂的外设。
这是关于驱动液晶显示屏的代码。

#include 

//引脚配置:
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_EN=P2^7;
#define LCD_DataPort P0

//函数定义:
/**
  * @brief  LCD1602延时函数,可延时1ms    
  * @param  无
  * @retval 无
  */
void Delay1ms()		//@11.0592MHz
{
   
	unsigned char i, j;

	_nop_();
	_nop_();
	_nop_();
	i = 11;
	j = 190;
	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);

你可能感兴趣的:(51单片机,学习,笔记)