蓝桥杯嵌入式第二课--LCD的移植与文件放置问题
前言
这节课是对前一课的延申,重点在于我们自己编写的代码要如何放置,以及如何将例程文件中的LCD移植到我们自己的工程当中。
创建一个User文件夹
一、工程文件夹概览
![](https://img-blog.csdnimg.cn/img_convert/5ba2d357c8d3f926f01a4d0b75d9f131.png)
打开一个工程,其实里面很简单,就是三个文件夹以及两个莫名其妙的文件。不卖关子,简单来说就是:
MDK-ARM文件夹里存放与IDE有关的文件,点开后里面有一个绿色的工程文件,点击之后能够打开工程,以及一个同名文件夹,里面装着我们代码经过编译后的可执行文件,例如.hex 与.axf文件。
![](https://img-blog.csdnimg.cn/img_convert/fc5d760ddb309f9d9835cf800622a815.png)
Core文件夹里面装着我们需要提交的.c和.h文件,一个Src和一个Inc分别存放.c和.h文件。考试时我们把整个Core文件夹给提交上去。
![](https://img-blog.csdnimg.cn/img_convert/edb54bdf254251224a59d7cc4e83db30.png)
Drivers文件夹存放外设驱动,内容几乎不需要我们关注,因此不做介绍。
二、在Core-->Src中创建User文件夹
我们选择在Core的Src子文件夹中创建一个user文件夹用来放置我们自己编写以及移植的.c和.h文件,其实放在哪儿都无所谓,这只是一个规范性的问题罢了。
![](https://img-blog.csdnimg.cn/img_convert/edc63550eec1626b879e5d72ed2bfc8d.png)
例如我们随意创建两个文件,用来放置自己写的代码。
![](https://img-blog.csdnimg.cn/img_convert/94627270b15e9249ddb9047d414bae5b.png)
移植LCD代码
一、找到目标代码
根据我们上面的经验,LCD有关的代码放置在例程的Core文件夹的Src和Inc当中,一共三个文件,分别是:
lcd.c //驱动源码
lcd.h //驱动头文件
fonts.h //字体文件
![](https://img-blog.csdnimg.cn/img_convert/017ec9a2f8fb2ad9ee7de113d75cc728.png)
![](https://img-blog.csdnimg.cn/img_convert/7fb16be513261d03c97737ec0d3440e7.png)
二、复制到User中
belike:
![](https://img-blog.csdnimg.cn/img_convert/c36fef06c2453c77b34fdd5537a67246.png)
让自定义代码成功编译
一、添加工程文件
![](https://img-blog.csdnimg.cn/img_convert/26d32e1d40801635718f285aba5accd3.png)
二、设置头文件路径
在魔术棒的C/C++栏目下,如下图所示,将user文件夹的地址添加到路径当中。这一步的目的是为了帮助编译器找到自定义的头文件路径。(实际上编译器很傻的)
![](https://img-blog.csdnimg.cn/img_convert/0dfa9199b7663e5583117c1338158f5a.png)
至此文件的添加就到此结束了,试着编译一遍看看能不能成功通过。
自定义的代码要怎么写
这是一个看似简单实则深奥的问题。大部分的初学者们都习惯在main.c中编写自己的函数,但是这样造成的后果就是面对复杂问题时,容易把事情搞的一团糟,试想阅读布满各种函数实现的main.c文件是怎么样的折磨。因此,这一部分要教大家怎么编写自定义的.c和.h文件,这样,我们在main.c中只要写一句简单的#include 就可以使用自定义的函数,而不需要面对繁杂的函数实现。
模块化的编程风格
一个项目往往由多个模块组成,例如按键模块,LED模块,LCD模块等等。我们习惯将一个模块的相关功能实现放在一个.c文件当中,对数据实例或对象定义,以及函数算法具体实现。另一个为头文件*.h,对模块中的数据结构和函数原型进行描述,其中.c和.h文件的命名对应相同。
*.h文件的编写
下面是按键模块的一个例子:
#ifndef _KEY_H_
#define _KEY_H_
#include "main.h"
uint8_t keyscan(void);
#endif
从中提取出模板即是:
#ifndef _XXX_H_
#define _XXX_H_
#include "main.h"
数据结构1;
数据结构2;
.
.
函数1;
函数2;
.
.
#endif
简单来说,记住这个模板就行了,更进一步理解请自行百度搜索。值得注意的是:
由于函数实现可能要使用一些HAL库文件,因此.h文件当中应该#include “main.h”
.h文件要被对应的.c文件#include
.h文件还要被main.c文件#include
*.c文件的编写
对应的按键例子:
#include "key.h"
uint8_t keyscan(void)
{
if(~HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)|~HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)|~HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2)|~HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0))
{
HAL_Delay(1000);
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==0)
{
return 1;
}
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)==0)
{
return 2;
}
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2)==0)
{
return 3;
}
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==0)
{
return 4;
}
}
return 0;
}
模板是:
#include "xxx.h"
函数实现1
函数实现2
.
.
main.c的使用
#include "xxx.h"
main(){
函数1;
函数2;
}
关于变量
按照变量定义的位置,分为全局变量和局部变量。
全局变量定义在函数之外,可以被多个函数访问。
局部变量定义在函数内部,只可以在函数内部使用。
因此,容易出现的问题是,如果一个文件内定义的全局变量要被另一个文件使用时,需要使用extern声明。
核心理解
#include“xxx.h”的作用相当于把这句代码替换成 xxx.h中的内容。
一个文件不能被#include两次,因此需要#ifndef语句避免重定义。
总结
掌握自定义文件的技巧后,基础算是打完了,不懂的地方要及时百度搞懂,接下来便可以进行编程的训练了!
相关文章
- [转Java读取文件]各种流
- PHP上传文件
- ASP.NET Core 上传大文件无法接收的问题
- Yara VS2017出现LINK : fatal error LNK1104: 无法打开文件“msvcrt.lib”
- 【C/C++学院】0826-文件重定向/键盘输入流/屏幕输出流/字符串输入输出/文件读写简单操作/字符文件读写二进制与文本差别/get与getline挖掘数据/二进制与文本差别/随机位置/多线程初级
- linux驱动开发--字符设备:添加文件指针偏移的功能
- 如何查看windows某个目录下所有文件/文件夹的大小?(TreeSize Free)
- 解决IIS 不能下载.exe.config文件的方法
- Everything 文件搜索神器
- PHP读取大文件的几种方法介绍
- postman测试上传文件
- fis入门-单文件编译之文件优化(optimize)
- [转]解决Eclipse中编辑xml文件的智能提示问题
- 将多个文件合并为一个文件
- ch3:文件处理与异常
- 《安富莱嵌入式周报》第308期:开源带软硬件安全认证的PLC设计,开源功率计,可靠PID实现,PR2机器人设计文件全开源,智能手表设计WASP-OS
- mysql 根目录下的 初始化文件 my.ini
- Angular 项目里 angular.json 文件内容的学习笔记
- pyinstaller利用spec文件打包的使用模板
- git 如何删除已经 add 的文件 (如何撤销已放入缓存区文件的修改)
- 【Android 安全】DEX 加密 ( Java 工具开发 | apk 文件签名 )
- GCN数据集Cora、Citeseer、Pubmed文件分析
- WSL嵌入式开发系列教程 2 —— Windows 与 Linux 的文件互传
- 嵌入式linux开发,Makefile 如何判断目录或文件是否存在