代码参考
0 数码管
c
unsigned char Number[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x40, 0x00};
// 数码管显示子函数
void Display(unsigned char Location, Num)
{
switch (Location)
{
case 1: P2_2=0; P2_1=0; P2_0=0; break;
case 2: P2_2=0; P2_1=0; P2_0=1; break;
case 3: P2_2=0; P2_1=1; P2_0=0; break;
case 4: P2_2=0; P2_1=1; P2_0=1; break;
case 5: P2_2=1; P2_1=0; P2_0=0; break;
case 6: P2_2=1; P2_1=0; P2_0=1; break;
case 7: P2_2=1; P2_1=1; P2_0=0; break;
case 8: P2_2=1; P2_1=1; P2_0=1; break;
}
P0 = Number[Num]; // 段码输出
//静态没有下面两个
Delay(1); // 显示一段时间
P0 = 0x00; // 段码清0,消影
}1、并行口与 if 语句 — 按键切换 LED
P1 口接 8 个发光二极管,P3.0 接一个按键。按下时左边 4 个亮,弹开时右边 4 个亮。
c
#include <reg52.h>
#define uchar unsigned char
sbit S1 = P3^0;
void main(void)
{
while(1)
{
if(S1 == 0)
P1 = 0xF0; // 左边 4 个亮
else
P1 = 0x0F; // 右边 4 个亮
}
}2、按键控制流水灯方向切换
P1 口接 8 只发光二极管,P3.0 接 S1。按一次 S1,流水灯方向改变一次。
c
#include <reg52.h>
#define uchar unsigned char
sbit S1 = P3^0;
bit flag = 0; // 方向标志
bit kp = 0; // 按键按下标志
void delayms(uchar ms)
{
uchar i;
while(ms--)
for(i = 1; i < 123; i++);
}
void key(void)
{
if(S1 == 0)
{
delayms(10); // 消抖
if((S1 == 0) && (kp == 0))
{
kp = 1;
flag = ~flag; // 切换方向
}
}
else
kp = 0; // 按键释放
}
void main(void)
{
P1 = 0xFE; // D1 亮(最低位)
while(1)
{
key();
if(flag == 0) // 方向 0:左移
{
delayms(100);
P1 = (P1 << 1) | (P1 >> 7);
}
else // 方向 1:右移
{
delayms(100);
P1 = (P1 >> 1) | (P1 << 7);
}
}
}3、外部中断实验 — INT0/INT1 嵌套
P1 接 8 个 LED,P3.2(S3) 触发 INT0 左移 16 次,P3.3(S4) 触发 INT1 右移 8 次。INT1 可嵌套 INT0。
c
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
void delayms(uint ms)
{
uchar i;
while(ms--)
for(i = 1; i < 123; i++);
}
// INT0:左移 16 次,间隔 100ms
void LED1(void) interrupt 0
{
uchar i;
P1 = 0xFE;
for(i = 0; i < 16; i++)
{
delayms(100);
P1 = (P1 << 1) | (P1 >> 7);
}
}
// INT1:右移 8 次,间隔 200ms
void LED2(void) interrupt 2
{
uchar i;
P1 = 0xFE;
for(i = 0; i < 8; i++)
{
delayms(200);
P1 = (P1 >> 1) | (P1 << 7);
}
}
void main(void)
{
EA = 1; // 开总中断
EX0 = 1; EX1 = 1;
IT0 = 1; IT1 = 1; // 下降沿触发
PX0 = 0; PX1 = 1; // INT1 优先级 > INT0(可嵌套)
while(1) // 无按键时全亮全灭交替 200ms
{
P1 = 0x00; delayms(200);
P1 = 0xFF; delayms(200);
}
}4、定时器 T1 方式 1 + T0 方式 2
T1 方式 1 定时 1s,P1.0 LED 亮灭交替;T0 方式 2 定时 0.5s,P1.7 LED 亮灭交替。
c
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit P10 = P1^0; // T1 控制,1s 交替
sbit P17 = P1^7; // T0 控制,0.5s 交替
uint con0 = 0; // T0 计数
uint con1 = 0; // T1 计数
// T1 中断(方式 1,50ms × 20 = 1s)
void LED1(void) interrupt 3
{
TH1 = 15536 / 256; // 50ms 初值 = 65536 − 50000
TL1 = 15536 % 256;
if(++con1 == 20)
{
con1 = 0;
P10 = ~P10;
}
}
// T0 中断(方式 2,250μs × 2000 = 0.5s,TH=TL=6)
void LED2(void) interrupt 1
{
if(++con0 == 2000)
{
con0 = 0;
P17 = ~P17;
}
}
void main(void)
{
TMOD |= 0x12; // T1 方式 1(0x10) + T0 方式 2(0x02)
TH1 = 15536 / 256; TL1 = 15536 % 256;
TH0 = 6; TL0 = 6; // 256 − 250 = 6,定时 250μs
EA = 1;
ET0 = 1; TR0 = 1;
ET1 = 1; TR1 = 1;
P10 = 0; P17 = 0; // 初始点亮
while(1);
}5、数码管动态显示 — "15-35-00"
共阴数码管,P0 段码 + P2 位选,显示 "15-35-00"(
-用 0x40)。
c
#include <reg52.h>
#define uchar unsigned char
// 段码:0~9 以及 "-" (0x40)
uchar code seg[] =
{0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x40};
uchar dis[] = {1,2,3,4,5,6,7,8};
void delayms(uchar ms)
{
uchar i;
while(ms--)
for(i = 0; i < 123; i++);
}
void display(void)
{
uchar i;
for(i = 0; i < 8; i++)
{
P0 = seg[dis[i]]; // 送段码
P2 = i; // 位选
delayms(1);
}
}
void main(void)
{
while(1)
{
dis[0]=1; dis[1]=5; dis[2]=10; dis[3]=3;
dis[4]=5; dis[5]=10; dis[6]=0; dis[7]=0;
display();
}
}6、数码管时钟 — 12:30:00
T1 方式 1 定时 50ms,共阴数码管显示 HH-MM-SS,冒号闪烁。
c
#include <reg52.h>
#define uchar unsigned char
// 段码:0~9, -, 空(0x00)
uchar code seg[] =
{0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x40,0x00};
uchar dis[8];
uchar aa = 0; // 冒号闪烁标志
uchar hour = 12, min = 30, sec = 0;
uchar t1_counter = 0;
void delayms(uchar ms)
{
uchar i;
while(ms--)
for(i = 0; i < 123; i++);
}
void display(void)
{
uchar i;
for(i = 0; i < 8; i++)
{
P0 = seg[dis[i]];
P2 = i;
delayms(1);
}
}
// T1 中断:50ms 定时
void t1_int(void) interrupt 3
{
TH1 = 15529 / 256; // 50ms 初值
TL1 = 15529 % 256;
if(t1_counter == 0) aa = 1; // 冒号亮
if(t1_counter == 10) aa = 0; // 冒号灭
if(++t1_counter == 20) // 1s 到
{
t1_counter = 0;
if(++sec == 60)
{
sec = 0;
if(++min == 60)
{
min = 0;
if(++hour == 24)
hour = 0;
}
}
}
}
void main(void)
{
TMOD |= 0x10;
TH1 = 15529 / 256;
TL1 = 15529 % 256;
TR1 = 1; EA = 1; ET1 = 1;
while(1)
{
dis[0] = hour / 10;
dis[1] = hour % 10;
if(aa == 0) // 冒号灭
{
dis[2] = 10; // "-"
dis[5] = 10;
}
else // 冒号亮
{
dis[2] = 11; // 空(灭)
dis[5] = 11;
}
dis[3] = min / 10;
dis[4] = min % 10;
dis[6] = sec / 10;
dis[7] = sec % 10;
display();
}
}7、LCD1602 数字钟
利用 LCD1602 显示时钟,P2.4/P2.5/P2.6 为 RS/RW/E,P0 为数据口。
c
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit RS = P2^4;
sbit RW = P2^5;
sbit E = P2^6;
uchar code str[] = {"welcome "};
uchar sec = 0;
uchar con = 0;
void delayms(uchar ms)
{
uchar i;
while(ms--)
for(i = 0; i < 123; i++);
}
// 写指令
void w_com(uchar com)
{
RS = 0; RW = 0;
E = 1; P0 = com; E = 0;
delayms(1);
}
// 写数据
void w_dat(uchar dat)
{
RS = 1; RW = 0;
E = 1; P0 = dat; E = 0;
delayms(1);
}
// LCD 初始化
void lcd_ini(void)
{
delayms(10);
w_com(0x38); // 8 位口,2 行,5×7 点阵
delayms(10);
w_com(0x0C); // 开显示,关光标
delayms(10);
w_com(0x06); // 右移,地址加 1
delayms(10);
w_com(0x01); // 清屏
delayms(10);
w_com(0x38);
delayms(10);
}
void main(void)
{
uchar i, num;
lcd_ini();
// 第一行显示 "welcome"
w_com(0x80);
for(i = 0; str[i] != '\0'; i++)
w_dat(str[i]);
while(1)
{
w_com(0xC7); // 第二行第7位
// …(时钟显示逻辑)
}
}8、带按键调整的 LCD1602 时钟
LCD1602 显示时钟,S1=小时+1,S2=小时−1,S3=分钟+1,S4=分钟−1。
c
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit RS = P2^4;
sbit RW = P2^5;
sbit E = P2^6;
sbit S1 = P3^0; // 小时+1
sbit S2 = P3^1; // 小时−1
sbit S3 = P3^2; // 分钟+1
sbit S4 = P3^3; // 分钟−1
uchar hour = 12, min = 30, sec = 0;
uchar t1_count = 0;
void delayms(uchar ms)
{
uchar i;
while(ms--)
for(i = 0; i < 123; i++);
}
void w_com(uchar com)
{ RS = 0; RW = 0; E = 1; P0 = com; E = 0; delayms(1); }
void w_dat(uchar dat)
{ RS = 1; RW = 0; E = 1; P0 = dat; E = 0; delayms(1); }
void lcd_ini(void)
{
delayms(10);
w_com(0x38); w_com(0x0C); w_com(0x06);
w_com(0x01); w_com(0x38);
delayms(10);
}
// 按键调整
void key_adj(void)
{
if(S1 == 0) { delayms(10); if(S1 == 0)
{ hour = (hour + 1) % 24; while(S1 == 0); } }
if(S2 == 0) { delayms(10); if(S2 == 0)
{ hour = (hour == 0) ? 23 : hour - 1; while(S2 == 0); } }
if(S3 == 0) { delayms(10); if(S3 == 0)
{ min = (min + 1) % 60; while(S3 == 0); } }
if(S4 == 0) { delayms(10); if(S4 == 0)
{ min = (min == 0) ? 59 : min - 1; while(S4 == 0); } }
}
void main(void)
{
lcd_ini();
TMOD |= 0x10; // T1 方式 1
// …(定时器 + 显示循环)
}