在学习89C52时,当需要编写又臭又长的代码时,会使用到代码的模块化封装,在Keil5中也可以这样进行,因为接下来是小车的项目所以代码会很长,这章作为一个简单的预备知识。

演示就在上节完成的DHT11 & LCD1602的项目中进行:

1. 想要创建新的C文件,其目录应该和main.c等一系列的所属目录一样,所以先查看main.c等c文件的目录:

按照该目录去电脑中查找:

C:\mjm_CubeMX_proj\mjm_dht11_lcd1602_proj\Core

如上图所示,在每个项目里的 Core 文件中,有 IncSrc 两个文件夹,Src 就是用来保存c文件的;Inc 就是用来保存h文件的。

2. 在 Src 文件内创建两个c文件,LCD1602.cDHT11.c

3.  在 Inc 文件内创建两个c文件,LCD1602.h DHT11.h

 

4. 在Keil中,添加这些 c文件 和 h文件 

4.1 选择刚刚添加文件的Core路径: 

 

 4.2 点击 Add Files:

上图是Core的下一级路径,所以点击上一级,然后找到Core,找到需要添加的文件:

 4.3 添加完之后:

可见,最右侧已经将两个C文件包含进来了,此时点击下方的OK,就会自动把h文件同样也包含进来。

5. 点击编译

6. 在LCD1602.c中:

6.1 include h 文件

在LCD1602.c 中必须添加“LCD1602.h”的文件,然后按需添加其他h文件

#include "LCD1602.h"
#include "DHT11.h" //要用到在DHT11.c中定义的 微秒级别延迟函数
#include "gpio.h"
#include "tim.h"
6.2 写相关代码
void write(char flag_w, char cmd) //write(1,cmd)代表写内容;write(0,cmd)代表写指令
{
	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET); //RW全程置0
	
	if(flag_w == 1){
		HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET); //RS置1写内容
		HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET); //E置0
		TIM2_Delay_us(2);
		
		GPIOA->ODR = cmd; //根据时序图,E为0时开始传内容
		
		HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET); //E置1
		HAL_Delay(5);
		HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET); //E置0
		HAL_Delay(5);
	}
	
	if(flag_w == 0){
		HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET); //RS置0写指令
		HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET); //E置0
		TIM2_Delay_us(2);
		
		GPIOA->ODR = cmd; //根据时序图,E为0时开始传内容
		
		HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET); //E置1
		HAL_Delay(5);
		HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET); //E置0
		HAL_Delay(5);
	}
	
}
 

 
void Init()
{
	HAL_Delay(15);
	write(0,0x38);
	HAL_Delay(5);
	
	//detectBusy();
	write(0,0x38);
	//detectBusy();
	write(0,0x08);
	//detectBusy();
	write(0,0x01);
	//detectBusy();
	write(0,0x06);
	//detectBusy();
	write(0,0x0C);
	
}
 
void showStr(char *msg, char hang, char lie)
{
	char pos;
	
	if(hang == 0){//如果第一行
			pos = 0x80 + 0x00 + lie; 
	}else if(hang == 1){//如果第二行
			pos = 0x80 + 0x40 + lie;
	}
	//detectBusy();
	write(0,pos); //只要定下开始的位置,之后光标会自行移动
	
	while(*msg != '\0'){
		//detectBusy();
		write(1,*msg);
		msg++;
	}
		
}
6.3 再次编译,然后就可以在左侧的LCD1602.c的目录里找到LCD1602.h了:

此时,就可以在h文件中添加可能会被外部调用的函数了:

注意,和之前不同的是,还必须写一下申明:

代码格式就是:

#ifndef __XXXX_H__ // "XXXX"就是h文件的名字
#define __XXXX_H__

/////////////////////////////
//此处就是可能被外部调用的函数名
/////////////////////////////


#endif 
//必须在程序最后加上一个新行,不然会有warning

Init函数在89C52时,如果进行封装直接写 void Init( ); 就可以,但是在32的封装中必须里面加个“void”,否则会有warning

7. 在DHT11.c 中:

遵循和LCD1602.c 相同的步骤

7.1 include h 文件
#include "DHT11.h"
#include "gpio.h"
#include "tim.h"
7.2 写相关代码
char buffer;
char datas[5];
char temp[9];
char huma[9];

void TIM2_Delay_us(uint16_t n_us) //使用TIM2来做us级延时函数
{
/* 使能定时器2计数 */
	__HAL_TIM_ENABLE(&htim2);
	__HAL_TIM_SetCounter(&htim2, 0);
	while(__HAL_TIM_GetCounter(&htim2) < ((1 * n_us)-1) );
/* 关闭定时器2计数 */
	__HAL_TIM_DISABLE(&htim2);
}

void DHT_GPIO_Init(uint32_t Mode)
{
	GPIO_InitTypeDef GPIO_InitStruct = {0};
	__HAL_RCC_GPIOB_CLK_ENABLE();
	GPIO_InitStruct.Pin = GPIO_PIN_7;
	GPIO_InitStruct.Mode = Mode;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
	HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
 7.3 再次编译,找到并修改h文件:

 8. 在main函数中 添加h文件写代码

#include "stdio.h"
#include "LCD1602.h"
#include "DHT11.h"

extern char temp[9];
extern char huma[9];

int fputc(int a, FILE *f) //一个字符一个字符发送
{
	unsigned char temp[1] = {a};
	HAL_UART_Transmit(&huart1, temp, 1, 0xffff);
	return a;
}

int main(void)
{

  Init(); //LCD1602初始化

  while (1)
  {
		HAL_Delay(1000);
		showDataFromDHT();	
		Build_Datas();
		
		printf(temp);
		printf("\r\n");
		printf(huma);
		printf("\r\n");
		
		showStr(temp,0,4);
		showStr(huma,1,4);

  }
}

 至此,封装完成!

 

 

 

 

Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐