橙色
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"
#include<intrins.h>
typedef 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<<i);//将 1 右移 i 位, 然后将结果赋值到 P2 口
delay(50000);
}
}
}
进入 main 函数后,首先 led=~ 0x01, 因为 LED 是低电平点亮, 所以 0X01 取反后的结果是 0XFE, 对应二进制数为 1111 1110, 即最低位为 0, 因此最开始的 D1指示灯会点亮;然后延时一段时间进入while循环, 由于要实现8个LED从D1->D8循环点亮, 因此可以使用 for 循环语句循环 8 次, 每循环一次,点亮的小灯向右移动一个,即 P2 口输出的低电平要左移一位, 因此可以使用 P2=~(0x01<<i);语句实现。 0X01<<i 表示0x01 中的 1 移动移动 i 位。因为1(高电平)不会让LED点亮,需要取反后变为低电平才能点亮,所以最后的结果需要取反后给P2口.
左移_crol_、 右移_cror_函数的使用
上面的代码是通过for 循环语句实现移位,但 KEIL C51 软件内也有对应的移位库函数,左移函数是_crol_(), 右移函数是_cror_(), 这两个函数在在 intrins.h 头文件当中。 该移位函数实现的移位功能就相当于一个队列内循环移动, 如果是左移, 那么最高位就被移到最低位了, 次高位变为最高位, 依次类推。使用左移、 右移函数实现的流水灯操作代码如下:
#include "reg52.h"
#include<intrins.h>
typedef 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);
}
}
}