本篇文章由 VeriMake 旧版论坛中备份出的原帖的 Markdown 源码生成
原帖标题为:以 CH549 为例的 51 教程 | 图文 2. 通用输入输出 GPIO
原帖网址为:https://verimake.com/topics/257 (旧版论坛网址,已失效)
原帖作者为:Xy(旧版论坛 id = 73,注册于 2020-10-15 13:03:26)
原帖由作者初次发表于 2021-08-19 15:37:31
📇 点此回到教程主索引
目录
GPIO 基础介绍
电路分析
具体代码解析
编译与下载
GPIO 基础介绍
GPIO(General-purpose input or output),通用型之输入输出的简称,其接脚可以供使用者由程控自由使用,PIN脚依现实考量可作为通用输入(GPI)或通用输出(GPO)或通用输入与输出(GPIO),如当clk generator, chip select等,并且可以实现与外部通讯、控制外部硬件或者采集外部硬件数据的功能。
既然一个引脚可以用于输入、输出或其他特殊功能,那么一定有寄存器用来选择这些功能。对于输入,一定可以通过读取某个寄存器来确定引脚电位的高低;对于输出,一定可以通过写入某个寄存器来让这个引脚输出高电位或者低电位;对于其他特殊功能,则有另外的寄存器来控制它们。
拓展阅读:寄存器
寄存器的功能是存储二进制代码,它是由具有存储功能的触发器组合起来构成的。一个触发器可以存储1位二进制代码,故存放n位二进制代码的寄存器,需用n个触发器来构成。
按照功能的不同,可将寄存器分为基本寄存器和移位寄存器两大类。基本寄存器只能并行送入数据,也只能并行输出。移位寄存器中的数据可以在移位脉冲作用下依次逐位右移或左移,数据既可以并行输入、并行输出,也可以串行输入、串行输出,还可以并行输入、串行输出,或串行输入、并行输出,十分灵活,用途也很广。
寄存器最起码具备以下4种功能。
①清除数码:将寄存器里的原有数码清除。
②接收数码:在接收脉冲作用下,将外输入数码存入寄存器中。
③存储数码:在没有新的写入脉冲来之前,寄存器能保存原有数码不变。
④输出数码:在输出脉冲作用下,才通过电路输出数码。
仅具有以上功能的寄存器称为数码寄存器;有的寄存器还具有移位功能,称为移位寄存器。
电路分析

Q2是一个npn型三极管,若Q2的1脚有一个很小的的基极电流则2,3脚导通,即电路导通,LED D1 亮反之则电路不导通,LED不亮。
简而言之就是P2.2为高电压则led亮 P2.2为低电压则led灭.
具体代码解析
/**
******************************************************************
* @file main.c
* @author xy
* @version V1.0
* @date 2020-9-29
* @brief LED闪烁实验
******************************************************************
* @attention
* verimake 用于ch549例程
*
******************************************************************
*/
#include <CH549_sdcc.H> //ch549的头文件,其中定义了单片机的一些特殊功能寄存器
#define led P2_2 //将单片机的P2.2端口定义为led
/********************************************************************
* 函 数 名 : delay
* 函数功能 : 延时函数
* 输 入 : 时间
* 输 出 : 无
********************************************************************/
void delay(int i)
{
while(i--);
}
/********************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*********************************************************************/
void main()
{
while(1)
{
led =!led; //P2.2输出取反
delay(50000);
}
//代码会在while(1)中无限循环
}
整篇代码分为四个部分

第一个部分:注释
几乎所有的绿色和灰色都是注释,它不参加编译的,再多的注释都不影响最后塞进单片机ROM(只读存储器)中机器码的大小。它的意义是让你代码的可读性变强。
这段注释详细的描写了这个函数的功能与输入输出。

这句注释解释了这段代码的含义。

C有两种注释方法
可以使用/* 和 */分隔符来标注一行内的注释,也可以标注多行的注释。例如,在下列的函数原型中,省略号的意思是 open() 函数有第三个参数,它是可选参数。注释解释了这个可选参数的用法:
int open( const char *name, int mode, … /* int permissions */ );
可以使用//插入整行的注释,或者将源代码写成两列分栏的格式,程序在左列,注释在右列:
const double pi = 3.1415926536; // pi是—个常量
第二个部分:两句代码

第一句的含义
这段代码包含的头文件为 CH549_sdcc.H
在编译这段代码的时候,编译器也会去CH549_sdcc.H的文件中去寻找这篇代码中有些未定义的内容 。
举个例子,对 P2.2 双击选中 右击转到定义,可以看到这句代码。
SBIT(P2_2, 0xA0, 2);
这句代码表达的含义为将地址为0XA0的寄存器的第二位定义为 P2.2
符合之前介绍GPIO时候提到的那句 :一定有寄存器用来选择这些功能。
打开数据手册验证一下:

P2端口输入输出寄存器的地址为A0h。
推出结论:我们对单片机外设进行编程的时候就是在配置单片机的各个寄存器来达到控制的目的。
第二句的含义
将 LED 定义为 P2.2,目的与注释一样是为了提高代码的可读性。
LED 即 P2.2 即 地址为 0XA0 的寄存器的第二位。
第三个部分:延时函数

这个延时函数通过无意义的循环将单片机“暂停“下来,暂停的时间可以通过改变输入的变量决定。
第四个部分:main函数

它是我们程序的主函数,可以看出我们的单片机将会一直在while(1)的循环中将 led 即 P2.2 的输出取反,并且每一次取反以后要延迟一段时间。来达到led闪烁的效果。
编译与下载
编译
- 点击上方菜单栏 终端 即 Terminal
- 点击 新终端 即 New Terminal\

- 在终端中输入
make clean//删除之前编译的程序

- 在终端中输入
make//开始编译

编译好的内容将会保存在代码文件夹的build文件夹中。

下载
- 打开第一篇教程中提供的文件中的安装包与所需文件的这个文件夹,并安装沁恒官方下载工具WCHISPTool。

- 在8位ch54x系列中选择芯片型号ch549,然后像图片中同样设置即可。

- 将ch549开发板通过usb线连接电脑,按一下靠近数据线那一端的download按键,即可在usb设备列表中找到型号ch549-1号设备。

- 在用户程序文件 中找到之前编译好的程序选中,点击下载,出现第一号设备下载完成即可。

- 可以看到 led 在闪烁 ,如果不行试着按下 RST 键。
