橙色
GPIO(general purpose intput output) 是通用输入输出端口的简称, 可以通过软件来控制其输入和输出。 51 单片机芯片的 GPIO 引脚与外部设备连接起来, 从而实现与外部通讯、 控制以及数据采集的功能。 不过 GPIO 最简单的应用还属点亮 LED 灯了, 只需通过软件控制 GPIO 输出高低电平即可。 当然GPIO 还可以作为输入控制, 比如在引脚上接入一个按键, 通过电平的高低判断按键是否按下。
我所使用的51单片机型号为STC89C52, 此芯片共有40 引脚, 芯片引脚图如下图所示:
当然,不是所有引脚都是 GPIO , 51 单片机引脚可以分为这么几大类:
51 单片机所有 IO 口都是双向的, 即可以作为输入也可以作为输出使用。由于 P0 口是漏极开路的, 所以要操作 P0 口必须外接上拉电阻, 其他P1、 P2、 P3 口都内部自带上拉电阻, 可以不加, 如果要增强 IO 口驱动能力, 可以外接上拉电阻。
LED 即发光二极管。 它具有单向导电性, 通过 5mA 左右电流即可发光, 电流越大, 其亮度越强, 但若电流过大, 会烧毁二极管, 一般我们控制在 3 mA-20mA之间, 通常我们会在 LED 管脚上串联一个电阻, 目的就是为了限制通过发光二极管的电流不要太大, 因此这些电阻又可以称为“限流电阻” 。
当发光二极管发光时, 测量它两端电压约为 1.7V, 这个电压又叫做发光二极管的“导通压降” 。下图左右分别为直插式发光二极管和贴片式发光二极管实物图。 发光二极管正极又称阳极, 负极又称阴极, 电流只能从阳极流向阴极。 直插式发光二极管长脚为阳极, 短脚为阴极。 仔细观察贴片式发光二极管正面的一端有彩色标记,通常有标记的一端为阴极。
本章所要实现的功能是: 点亮 D1 发光二极管, 即让 P0.0 管脚输出一个低电平。 完成后可再控制 D1 指示灯闪烁, 即间隔一定时间点亮和熄灭 D1 指示灯。
#include "reg52.h" sbit led=P2^0; void main() { led=0; while(1) { } }
编译一下,如下图所示:
可以看到没有错误, 也没有警告。 从编译信息可以看出, 我们的代码占用FLASH 大小为: 19 字节, 所用的 SRAM 大小为: 9 个字节(9+0) 。 这里我们解释一下, 编译结果里面的几个数据的意义:
有了这个就可以知道你当前使用的 flash 和 sram 大小了。 一定要注意的是程序的大小不是.hex 文件的大小, 而是编译后的 Code 和 data 之和。
#include "reg52.h" #includetypedef unsigned int u16; typedef unsigned char u8; #define led P2 //延时函数,i=1时,大约延时10us void delay(u16 i) { while(i--); } void main() { u8 i; led=~0x01;//0x01 取反即为 0xFE delay(5000);//大约延时450ms while(1) { for(i=0;i<8;i++) { P2=~(0x01< 进入 main 函数后,首先 led=~ 0x01, 因为 LED 是低电平点亮, 所以 0X01 取反后的结果是 0XFE, 对应二进制数为 1111 1110, 即最低位为 0, 因此最开始的 D1指示灯会点亮;然后延时一段时间进入while循环, 由于要实现8个LED从D1->D8循环点亮, 因此可以使用 for 循环语句循环 8 次, 每循环一次,点亮的小灯向右移动一个,即 P2 口输出的低电平要左移一位, 因此可以使用 P2=~(0x01<
左移_crol_、 右移_cror_函数的使用
上面的代码是通过for 循环语句实现移位,但 KEIL C51 软件内也有对应的移位库函数,左移函数是_crol_(), 右移函数是_cror_(), 这两个函数在在 intrins.h 头文件当中。 该移位函数实现的移位功能就相当于一个队列内循环移动, 如果是左移, 那么最高位就被移到最低位了, 次高位变为最高位, 依次类推。使用左移、 右移函数实现的流水灯操作代码如下:
#include "reg52.h" #includetypedef unsigned int u16; typedef unsigned char u8; #define led P2 void delay(u16 i) { while(i--); } void main() { u8 i; led=~0x01; delay(5000); while(1) { for(i=0;i<7;i++) { led=_crol_(led,1); //将led左移一位 delay(50000); } for(i=0;i<7;i++) { led=_cror_(led,1); //将led右移一位 delay(50000); } } }