必备基础技能训练15 项
【基础08】外部中断的基本操作
新建工程,以I/O 模式编写代码,在CT107D 单片机综合训练平台上,实现以下功能:
1、将CT107D 上J5 处跳帽接到2~3 引脚,使S4 和S5 按键一端接地,S4 按键的另一端接到单片机的P32/INT0 引脚,S5 按键的另一端接到单片机的P33/INT1 引脚。
2、系统上电后,关闭蜂鸣器,关闭继电器,关闭8 个LED 灯。
3、控制L1 指示灯循环闪烁。
4、将P32/INT0 引脚定义成外部中断,下降沿触发,使能相关中断控制位。即按下S5按键就会产生一个外部中断触发信号,进入外部中断服务函数。
5、在外部中断服务函数中,点亮L8 指示灯,延时片刻后,熄灭。
实现代码:
#include "reg51.h"
sbit HC138_A = P2^5; // 74HC138的A引脚
sbit HC138_B = P2^6; // 74HC138的B引脚
sbit HC138_C = P2^7; // 74HC138的C引脚
sbit L1 = P0^0;
sbit L2 = P0^1;
sbit L3 = P0^2;
sbit L4 = P0^3;
sbit L5 = P0^4;
sbit L6 = P0^5;
sbit L7 = P0^6;
sbit L8 = P0^7;
void Delay(unsigned int t); // 延迟函数
void HC138Init(unsigned int n); // 74HC138初始化
void InterruptInit(void); // 外部中断初始化
// 08外部中断的基本操作
void main(void)
{
HC138Init(4); // 初始化74HC138
InterruptInit(); // 初始化外部中断
while (1) {
// LED1循环闪烁
L1 = 0;
Delay(1000);
L1 = 1;
Delay(1000);
}
}
void Delay(unsigned int t) // 延迟函数
{
unsigned char i, j;
while (t > 0) {
i = 2;
do {
while (--j)
;
} while (--i);
t--;
}
}
void HC138Init(unsigned int n) // 74HC138初始化
{
P2 = 0x00; // P2口输出0
if (n == 4) {
HC138_C = 1;
HC138_B = 0; // 设置74HC138为 100 4
HC138_A = 0;
} else if (n == 5) {
HC138_C = 1; // 设置74HC138为 101 5
HC138_B = 0;
HC138_A = 1;
} else if (n == 6) {
HC138_C = 1; // 设置74HC138为 110 6
HC138_B = 1;
HC138_A = 0;
} else if (n == 7) {
HC138_C = 1; // 设置74HC138为 111 7
HC138_B = 1;
HC138_A = 1;
}
}
void InterruptInit(void) // 外部中断初始化
{
IT0 = 1; // 设置外部中断0为下降沿触发
EX0 = 1; // 开启外部中断0
EA = 1; // 开启总中断
}
void Interrupt0(void) interrupt 0 // 外部中断0服务程序
{
L8 = 0;
Delay(2000);
L8 = 1;
}
【基础09】定时器实现秒闪功能
新建工程,以I/O 模式编写代码,在CT107D 单片机综合训练平台上,实现以下功能:
1、系统上电后,关闭蜂鸣器,关闭继电器,关闭8 个LED 灯。
2、利用定时/计数器T0 的模式1 实现50ms 的间隔定时。
3、在50ms 间隔定时的基础上,每隔1 秒L1 指示灯闪烁一次,即L1 指示灯循环点亮
0.5 秒,熄灭0.5 秒。4、每隔10 秒L8 指示灯闪烁1 次,即L1 指示灯循环点亮5 秒,熄灭5 秒。
通过STC-ISP生成中断初始化函数
再在其中开启中断:ET0、EA、PT0
实现代码:
#include "REG51.H"
sbit HC138_A = P2^5; // 74HC138的A引脚
sbit HC138_B = P2^6; // 74HC138的B引脚
sbit HC138_C = P2^7; // 74HC138的C引脚
sbit L1 = P0^0;
sbit L8 = P0^7;
void HC138Init(unsigned int n); // 74HC138初始化
void Timer0_Init(void); // 定时器0初始化
void main()
{
HC138Init(4); // 初始化74HC138
Timer0_Init(); // 初始化定时器0
while (1) {
}
}
void HC138Init(unsigned int n) // 74HC138初始化
{
P2 = 0x00; // P2口输出0
if (n == 4) {
HC138_C = 1;
HC138_B = 0; // 设置74HC138为 100 4
HC138_A = 0;
} else if (n == 5) {
HC138_C = 1; // 设置74HC138为 101 5
HC138_B = 0;
HC138_A = 1;
} else if (n == 6) {
HC138_C = 1; // 设置74HC138为 110 6
HC138_B = 1;
HC138_A = 0;
} else if (n == 7) {
HC138_C = 1; // 设置74HC138为 111 7
HC138_B = 1;
HC138_A = 1;
}
}
void Timer0_Init(void) // 50毫秒@12.000MHz
{
TMOD &= 0xF0; // 设置定时器模式
TMOD |= 0x01; // 设置定时器模式
TL0 = 0xB0; // 设置定时初始值
TH0 = 0x3C; // 设置定时初始值
TF0 = 0; // 清除TF0标志
TR0 = 1; // 定时器0开始计时
ET0 = 1; // 允许定时器0中断
EA = 1; // 开总中断
PT0 = 0; // 定时器0为低优先级中断
}
void Timer0_Routine() interrupt 1// 定时器0中断服务程序
{
unsigned char i;
TL0 = 0xB0; // 设置定时初始值
TH0 = 0x3C; // 设置定时初始值
i++;
if (i % 10 == 0) // 500ms
{
L1 = ~L1;
}
if (i == 100) // 5s
{
i = 0;
L8 = ~L8;
}
}
【基础10】定时器实现秒表功能
新建工程,以I/O 模式编写代码,在CT107D 单片机综合训练平台上,利用定时器T0、数码管和2 个独立按键,设计并实现一个秒表,具有启动、暂停和清零功能。
1、秒表的显示格式:分-秒-0.05 秒(即50ms)
- 如8 分26 秒900 毫秒,显示为:08-26-18
2、独立按键S4 定义为:启动/暂停,即第1 次按下启动秒表,再次按下暂停秒表。
3、独立按键S5 定义为:清零。
4、按键均为按下有效。
注意一下临界条件判断
实现代码:
#include <REG51.H>
sbit HC138_A = P2^5; // 74HC138的A引脚
sbit HC138_B = P2^6; // 74HC138的B引脚
sbit HC138_C = P2^7; // 74HC138的C引脚
sbit Key1 = P3^0; // 按键1
sbit Key2 = P3^1; // 按键2
sbit Key3 = P3^2; // 按键3
sbit Key4 = P3^3; // 按键4
unsigned char code Duanma[18] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x88, 0x80, 0xc6, 0xc0, 0x86, 0x8e, 0xbf, 0x7f};
void Delay(unsigned int t); // 延迟函数
void HC138Init(unsigned int n); // 74HC138初始化
void LED_Shu(unsigned int location, unsigned int num); // 数码管显示函数
void Display(); // LED显示
void Timer0_Init(void); // 定时器0初始化
unsigned int min = 0, sec = 0, ssec = 0; // 分,秒,毫秒
unsigned int flag1 = 0, flag2 = 0;
// 10定时器实现秒表功能
void main()
{
Timer0_Init();
while (1) {
if (Key1 == 0) {
Delay(20);while (Key1 == 0);Delay(20);// 去抖
flag1 = !flag1;// 按下一次开始,再按一次暂停
}
if (Key2 == 0 && flag2 == 0) {
Delay(20);while (Key2 == 0);Delay(20);// 去抖
flag2 = !flag2;
}
Display();
}
}
void Delay(unsigned int t) // 延迟函数
{
unsigned char i, j;
while (t > 0) {
i = 2;
do {
while (--j)
;
} while (--i);
t--;
}
}
void HC138Init(unsigned int n) // 74HC138初始化
{
if (n == 4) {
HC138_C = 1;
HC138_B = 0; // 设置74HC138为 100 4
HC138_A = 0;
} else if (n == 5) {
HC138_C = 1; // 设置74HC138为 101 5
HC138_B = 0;
HC138_A = 1;
} else if (n == 6) {
HC138_C = 1; // 设置74HC138为 110 6
HC138_B = 1;
HC138_A = 0;
} else if (n == 7) {
HC138_C = 1; // 设置74HC138为 111 7
HC138_B = 1;
HC138_A = 1;
}
}
void LED_Shu(unsigned int location, unsigned int num) // 数码管显示函数
{
HC138Init(6); // 位选
P0 = 0x01 << location;
HC138Init(7); // 段选
P0 = Duanma[num];
// 消影
Delay(1);
P0 = 0xFF;
}
void Display() // LED显示
{
LED_Shu(0, min / 10);
Delay(1);
LED_Shu(1, min % 10);
Delay(1);
LED_Shu(2, 16);
LED_Shu(3, sec / 10);
Delay(1);
LED_Shu(4, sec % 10);
Delay(1);
LED_Shu(5, 16);
LED_Shu(6, ssec / 10);
Delay(1);
LED_Shu(7, ssec % 10);
Delay(1);
}
void Timer0_Init(void) // 50毫秒@12.000MHz
{
TMOD &= 0xF0; // 设置定时器模式
TMOD |= 0x01; // 设置定时器模式
TL0 = 0xB0; // 设置定时初始值
TH0 = 0x3C; // 设置定时初始值
TF0 = 0; // 清除TF0标志
TR0 = 1; // 定时器0开始计时
ET0 = 1; // 允许定时器0中断
EA = 1; // 开总中断
PT0 = 0; // 定时器0为低优先级中断
}
void Timer0_Routine() interrupt 1 // 定时器0中断服务程序
{
TL0 = 0xB0; // 设置定时初始值
TH0 = 0x3C; // 设置定时初始值
if (flag1 == 1 && flag2 == 0) {
ssec++;
if (ssec == 20) {
ssec = 0;
sec++;
}
if (sec >= 60) {
sec = 0;
min++;
}
if (min >= 60) {
min = 0;
}
}
if (flag2 == 1) {
min = 0, sec = 0, ssec = 0;
}
}
【基础11】利用PWM 控制灯光亮度
新建工程,以I/O 模式编写代码,在CT107D 单片机综合训练平台上,利用PWM 脉宽信号实现独立按键S7 对L1 指示灯亮度变化的控制:
1、系统上电后,关闭蜂鸣器,关闭继电器,关闭8 个LED 灯。
2、PWM 脉宽信号的频率为100Hz。
3、L1 指示灯有4 种亮度,分别是:完全熄灭、10%的亮度、50%的亮度和90%的亮度。
4、按下S7 按键,循环切换L1 指示灯的四种亮度模式,如下图所示:
实现代码:
#include "REG51.H"
sbit HC138_A = P2^5; // 74HC138的A引脚
sbit HC138_B = P2^6; // 74HC138的B引脚
sbit HC138_C = P2^7; // 74HC138的C引脚
sbit Key1 = P3^0; // 按键1
sbit L1 = P0^0; // LED1
void Timer0_Init(void); // 定时器0初始化函数
void HC138Init(); // 74HC138初始化函数
void Delay(unsigned int t); // 延迟函数
unsigned int PWM_flag = 0;
unsigned int flag = 0;
void main(void)
{
HC138Init();
Timer0_Init();
while (1) {
if (Key1 == 0) {
Delay(20);while (Key1 == 0);Delay(20);
if (flag == 0) {
EA = 1; // 开总中断
PWM_flag = 10;
flag = 1;
} else if (flag == 1) {
PWM_flag = 50;
flag = 2;
} else if (flag == 2) {
PWM_flag = 90;
flag = 3;
} else if (flag == 3) {
PWM_flag = 0;
EA = 0; // 开总中断
L1 = 1;
}
}
}
}
void Delay(unsigned int t) // 延迟函数
{
unsigned char i, j;
while (t > 0) {
i = 2;
do {
while (--j)
;
} while (--i);
t--;
}
}
void Timer0_Init(void) // 100微秒@12.000MHz
{
TMOD &= 0xF0; // 设置定时器模式
TMOD |= 0x01; // 设置定时器模式
TL0 = 0xB0; // 设置定时初始值
TH0 = 0x3C; // 设置定时初始值
TF0 = 0; // 清除TF0标志
TR0 = 1; // 定时器0开始计时
ET0 = 1; // 允许定时器0中断
PT0 = 0; // 定时器0为低优先级中断
}
void HC138Init() // 74HC138初始化函数
{
P2 = 0x00; // P2口输出0
HC138_A = 0;
HC138_B = 0;
HC138_C = 1;
}
void Timer0_Routine() interrupt 1 // 定时器0中断服务程序
{
unsigned char count;
TL0 = 0xB0; // 设置定时初始值
TH0 = 0x3C; // 设置定时初始值
count++;
if (count == PWM_flag) {
L1 = 1;
} else if (count == 100) {
L1 = 0;
count = 0;
}
}
【基础12】串行接口的基本操作
新建工程,以I/O 模式编写代码,在CT107D 单片机综合训练平台上,实现以下功能:
1、初始化串口为模式1,即8 位UART 模式,波特率9600,允许接收。
2、数据发送采用查询方式,数据接收采用中断方式。
3、系统上电初始化之后,单片机向上位机发送两个字节:0x5a 和0xa5(串口助手以十六进制HEX 发送和显示)。
4、串口每成功接收到一个字节后,在该字节基础上加1,然后通过串口发送回上位机。
5、注意89C52 单片机和IAP15F2K61S2 单片机串口应用的差别,使用9600 波特率时,晶振时钟选择11.0592MHz。
实现代码:
#include "reg51.h"
sfr AUXR = 0x8e; // IAP15F2K61S新增配置
unsigned char Date;
void UART_Init(); // 串口初始化函数
void Send_Data(unsigned char dat); // 发送数据
// 12串行接口的基本操作
void main(void)
{
UART_Init();
Send_Data(0X5A);
Send_Data(0XA5);
while (1) {
}
}
void UART_Init() // 串口初始化函数
{
// STC-ISP 波特率设置模块
// 11.0592MHz 9600bps 串口1 8位数据 定时器1(8位自动重载) 12T
TMOD &= 0x0F; // 清除定时器1模式位
TMOD |= 0x20; // 设定定时器1为8位自动重装方式
TL1 = 0xFD; // 设定定时初值
TH1 = 0xFD; // 设定定时器重装值
ET1 = 0; // 禁止定时器1中断
TR1 = 1; // 启动定时器1
EA = 1; // 开总中断
PT1 = 0; // 定时器1为低优先级中断
ES = 1; // 串口中断允许
SCON = 0x50; // 8位数据,可变波特率
AUXR = 0x00;
}
void UART_Routine(void) interrupt 4 // 串口中断函数,接受数据
{
if (RI == 1) {
Date = SBUF;
Send_Data(Date + 1);
RI = 0;
}
}
void Send_Data(unsigned char dat) // 发送数据
{
SBUF = dat;
while (TI == 0);
TI = 0;
}
【基础13】串行接口的进阶应用
新建工程,以I/O 模式编写代码,在CT107D 单片机综合训练平台上,实现以下功能:
1、初始化串口为模式1,即8 位UART 模式,波特率9600,允许接收。
2、数据发送采用查询方式,数据接收采用中断方式。
3、系统上电后,关闭蜂鸣器,关闭继电器,关闭8 个LED 灯,通过串口向上位机发送字符串:“Welcome to XMF system!”,回车换行。
4、上位机通过串口发送单字节命令,控制单片机的8 个LED 灯开关,单片机响应正确的控制命令后,完成相应的灯光操作。
5、上位机通过串口发送单字节命令,读取单片机运行信息,单片机响应正确的读取命令后,向上位机返回指定的信息。
6、上位机与单片机的通信规约如下表:
实现代码:
#include "reg51.h"
sfr AUXR = 0x8e; // IAP15F2K61S新增配置
sbit HC138_A = P2 ^ 5; // 74HC138的A引脚
sbit HC138_B = P2 ^ 6; // 74HC138的B引脚
sbit HC138_C = P2 ^ 7; // 74HC138的C引脚
void UART_Init(void); // 初始化串口
void UART_SentByte(unsigned char dat); // 串口发送一个字节
void UART_SentDate(unsigned char *str); // 串口发送字符串
void HC138_Init(void); // 初始化74HC138
unsigned char Data = 0x00; // 接收到的数据
// 13串行接口的进阶应用
void main(void)
{
UART_Init(); // 初始化串口
HC138_Init(); // 初始化74HC138
UART_SentDate("Welcome to XMF system!\r\n");
while (1) {
if (Data != 0x00) {
switch (Data & 0xf0) {
// 模式判断
case 0xa0: // 控制L1~L4灯
P0 = 0xff;
P0 = P0 & (~Data | 0xf0);
Data = 0x00;
break;
case 0xb0: // 控制L5~L8灯
P0 = 0xff;
P0 = P0 & ((~Data << 4) | 0x0f);
Data = 0x00;
break;
case 0xc0: // 返回状态
UART_SentDate("The System is Running...\r\n");
Data = 0x00;
break;
}
}
}
}
void UART_Init(void) // 初始化串口
{
PCON &= 0x7F; // 波特率不倍速
SCON = 0x50; // 8位数据,可变波特率
TMOD &= 0x0F; // 清除定时器1模式位
TMOD |= 0x20; // 设定定时器1为8位自动重装方式
TL1 = 0xFD; // 设定定时初值
TH1 = 0xFD; // 设定定时器重装值
ET1 = 0; // 禁止定时器1中断
TR1 = 1; // 启动定时器1
EA = 1; // 使能总中断
PT1 = 0; // 定时器1为低优先级中断
ES = 1; // 使能串口中断
AUXR = 0x00;
}
void UART_Routine(void) interrupt 4 // 串口中断函数,接受数据
{
if (RI == 1) {
Data = SBUF; // 读取数据
RI = 0;
}
}
void UART_SentByte(unsigned char dat) // 串口发送一个字节
{
SBUF = dat;
while (!TI);
TI = 0;
}
void UART_SentDate(unsigned char *str)
{
while (*str != '\0')
UART_SentByte(*str++);
}
void HC138_Init(void)
{
HC138_C = 1; // 设置74HC138为 100 4
HC138_B = 0;
HC138_A = 0;
}
【基础14】存储器映射扩展技术应用
新建工程,以MM 模式编写代码,在CT107D 单片机综合训练平台上,实现以下功能:
1、系统上电后,关闭蜂鸣器,关闭继电器,关闭8 个LED 灯。
2、循环实现以下功能:
- 首先,点亮指示灯低4 位,关闭高4 位,延时片刻;
- 接着,点亮指示灯的高4 位,关闭低4 位,延时片刻;
- 然后,关闭所有指示灯。
- 接着,依次逐个点亮数码管的所有段码,每次只点亮一个数码管。
3、外部扩展资源的地址映射关系:
- LED 指示灯---- 0x8000;
- 蜂鸣器与继电器----0xa000;
- 数码管位选----0xc000;
- 数码管段码----0xe000
4、关于CT107D 存储器映射扩展MM 编程模式的设计提示:CT107D 平台的J13 要将1-2 脚短接,选择MM 模式。
程序中引入头文件“absacc.h”,通过XBYTE 关键字来直接操作扩展资源。存储器映射扩展方式要占用单片机的P3.6 引脚。
IO扩展:
#include "reg51.h"
void Delay(unsigned int t); // 延迟函数
void Select_HC573(unsigned int i); // 选择HC573
// 14存储器映射扩展技术应用(IO扩展)
void main(void)
{
unsigned int i;
while (1) {
Select_HC573(4);
P0 = 0xf0;
Delay(1000);
P0 = 0x0f;
Delay(1000);
P0 = 0xff;
for (i = 0; i < 8; i++) {
Select_HC573(6);
P0 = 0x01 << i;
Select_HC573(7);
P0 = 0x00;
Delay(1000);
}
P0 = 0xff;
Delay(1000);
}
}
void Delay(unsigned int t) // 延迟函数
{
unsigned char i, j;
while (t > 0) {
i = 2;
do {
while (--j)
;
} while (--i);
t--;
}
}
void Select_HC573(unsigned int i) // 选择HC573
{
switch (i) {
case 4:
P2 = (P2 & 0X1f) | 0x80;
break;
case 5:
P2 = (P2 & 0X1f) | 0xa0;
break;
case 6:
P2 = (P2 & 0X1f) | 0xc0;
break;
case 7:
P2 = (P2 & 0X1f) | 0xe0;
break;
}
}
存储器扩展:
#include "reg51.h"
#include "absacc.h"
void Delay(unsigned int t); // 延迟函数
voidmain(void)
{
unsigned int i;
while (1) {
XBYTE[0x8000] = 0xf0;
XBYTE[0x8000] = 0xf0;
Delay(1000);
XBYTE[0x8000] = 0x0f;
Delay(1000);
XBYTE[0x8000] = 0xff;
for (i = 0; i < 8; i++) {
XBYTE[0xc000] = 0x01 << i;
XBYTE[0xe000] = 0x00;
Delay(1000);
}
XBYTE[0xe000] = 0xff;
Delay(1000);
}
}
void Delay(unsigned int t) // 延迟函数
{
unsigned char i, j;
while (t > 0) {
i = 2;
do {
while (--j)
;
} while (--i);
t--;
}
}
【基础15】工厂灯光控制系统
新建工程,分别以I/O 模式和MM 模式编写代码,在CT107D 单片机综合训练平台上,实现灯光的本地操作和远程控制,并通过串口远程读取系统的运行时间,模拟实现工厂灯光控制系统。具体功能要求如下:
1、系统上电后,关闭蜂鸣器,关闭继电器,关闭8 个LED 灯。
2、首先检测LED 指示灯,从L1 到L8 依次逐个点亮,再依次逐个熄灭;然后检测数码管,从左到右依次点亮数码管的所有段码,再依次从左到右熄灭。
3、系统从上电开始显示系统运行时间,从00 时00 分00 秒开始,显示格式:
4、8 个LED 指示灯分为2 组:L1、L2、L3 和L4 为远程控制组,L7 和L8 为本地控制组。远程控制组的指LED 示灯由上位机通过串口发送命令控制开关,本地控制组的LED 指示灯由独立按键控制开关。按键松开有效,S5 按键控制L7 指示灯,S4 按键控制L8 指示灯。
5、串口工作在模式1,即8 位UART 模式,波特率为9600(使用9600 波特率时,晶振时钟选择11.0592MHz。如果是其他频率的系统时钟,需要降低波特率,可选择用2400,否则串口通信可能出现乱码,无法正常收发数据)。
6、上位机通过串口控制下位机的L1 到L4 指示灯和读取系统运行时间。
7、上位机和单片机的串口通信规约如下表:
控制命令为一个字节,高4 位为命令类型,低4 位为执行参数。控制灯光开关命令中,低4 位每1 位控制一个LED 灯的开关,无返回值。读取运行时间命令中,低4 位保留,各位为0,返回3 个字节的时间数据,用16 进制的BCD 码表示,先发时,再发分,后发秒。如果系统运行的时间为12 时24 分16 秒,收到读取时间命令字后,返回:0x12 0x24 0x16。
#include <REGX52.H>
sfr AUXR = 0x8e; // IAP15F2K61S新增配置
unsigned char code Duanma[18] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x88, 0x80, 0xc6, 0xc0, 0x86, 0x8e, 0xbf, 0x7f};
sbit Key1 = P3^0; // 按键1
sbit Key2 = P3^1; // 按键2
sbit L7 = P0^6; // LED1
sbit L8 = P0^7; // LED1
void Delay(unsigned int t); // 延迟函数
void Select_HC138(unsigned int n); // 初始化74HC138
void LED_Shu(unsigned int location, unsigned int num); // 数码管显示函数
void Show_Time(void);//数码管显示时间
void Time0_Init(void);//定时器初始化
void UART_Init(void);//初始化串口
void check();//设备判断
void Check_Key(void);//判断按键
void UART_SendByte(unsigned char dat);//发送字节
void Check_Data(void);//判断串口数据
unsigned char hour=0,min=0,sec=0;
unsigned int flag = 0;
unsigned char Data = 0x00; // 接收到的数据
void main(){
Time0_Init();
UART_Init();
while(1){
if(flag == 0)//第一次运行,设备检验
{
check();
flag = 1;
}
Show_Time();//数码管显示时间
Check_Key();//判断按键
Check_Data();//判断串口数据
}
}
void Delay(unsigned int t) //延迟函数
{
unsigned char i, j;
while(t){
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
t--;
}
}
void Select_HC138(unsigned int n)
{
switch(n){
case 4:
P2 = (P2 & 0x1f) | 0x80; //Y4输出0,选择LED控制
break;
case 5:
P2 = (P2 & 0x1f) | 0xa0; //Y5输出0,选择蜂鸣器和继电器控制
break;
case 6:
P2 = (P2 & 0x1f) | 0xc0; //Y6输出0,选择数码管位选
break;
case 7:
P2 = (P2 & 0x1f) | 0xe0; //Y7输出0,选择数码管段码
break;
case 0:
P2 = (P2 & 0x1f) | 0x00; //所有锁存器不选择
break;
}
}
void LED_Shu(unsigned int location, unsigned int num)
{
Select_HC138(6);
P0 = 0x01 << location;
Select_HC138(7);
P0 = Duanma[num];
//消影
Delay(1);
P0 = 0xFF;
}
void Show_Time()//数码管显示时间
{
LED_Shu(0, hour / 10);
Delay(1);
LED_Shu(1, hour % 10);
Delay(1);
LED_Shu(2, 16);
LED_Shu(3, min / 10);
Delay(1);
LED_Shu(4, min % 10);
Delay(1);
LED_Shu(5, 16);
LED_Shu(6, sec / 10);
Delay(1);
LED_Shu(7, sec % 10);
Delay(1);
}
void Time0_Init(void)//50毫秒@12.000MHz
{
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0xB0; // 设置定时初始值
TH0 = 0x3C; // 设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; // 允许定时器0中断
EA = 1; // 开总中断
PT0 = 0; // 定时器0为低优先级中断
}
void check()//设备判断
{
unsigned int i;
Select_HC138(4);
for(i = 0; i < 8; i++)
{
P0 = 0xff << i;
Delay(500);
}
for(i = 0; i <= 8; i++)
{
P0 = ~(0xff << i);
Delay(500);
}
for(i = 0; i<8; i++)
{
Select_HC138(6);
P0 = 0x01 << i;
Select_HC138(7);
P0 = 0x00;
Delay(500);
}
for(i = 0; i<8; i++)
{
Select_HC138(6);
P0 = ~(0x01 << i);
Select_HC138(7);
P0 = 0xFF;
Delay(500);
}
}
void Check_Key(void)
{
if(Key1 == 0)
{
Show_Time();
while(Key1 == 0)
Show_Time();
Select_HC138(4);
L8 = ~L8;
}
if(Key2 == 0)
{
Show_Time();
while(Key2 == 0)
Show_Time();
Select_HC138(4);
L7 = ~L7;
}
}
void UART_Init(void) //9600bps@11.0592MHz
{
SCON = 0x50; //8位数据,可变波特率
TMOD &= 0x0F; //清除定时器1模式位
TMOD |= 0x20; //设定定时器1为8位自动重装方式
TL1 = 0xFD; //设定定时初值
TH1 = 0xFD; //设定定时器重装值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
ES = 1;
AUXR = 0x00;
}
void UART_SendByte(unsigned char dat)
{
SBUF = dat;
while (!TI);
TI = 0;
}
void Check_Data(void)
{
if(Data != 0x00)
{
switch(Data & 0xf0){
case 0xa0: //远程灯光控制命令
Select_HC138(4);
P0 = 0xff;
P0 = P0 & (~Data | 0xf0);
Select_HC138(0);
Data = 0x00;
break;
case 0xb0: //读取现场系统运行时间命令
UART_SendByte((hour / 10 << 4) | (hour % 10));
UART_SendByte((min / 10 << 4) | (min % 10));
UART_SendByte((sec / 10 << 4) | (sec % 10));
Data = 0x00;
break;
}
}
}
void Time0_Run(void) interrupt 1
{
unsigned char i;
TL0 = 0xB0; // 设置定时初始值
TH0 = 0x3C; // 设置定时初始值
i++;
if(i == 20)//1s
{
sec++;
i = 0;
if(sec == 60){
min++;
sec = 0;
if(min == 60){
hour++;
min = 0;
if(hour == 24)
hour = 0;
}
}
}
}
void UART_Run(void) interrupt 4
{
if (RI == 1) {
Data = SBUF;
RI = 0;
}
}