一、题目要求
在CT107D单片机综合训练平台上,通过I/O模式编写代码,实现以下功能:
- 系统上电后,关闭蜂鸣器、继电器和全部指示灯,数码管显示初始值为28,仅显示数码管最右边两位。
- 利用定时器0实现10ms间隔定时,作为长定时的基本单位,用于记录按键按下持续时间。
- 将J5的23脚短接,将S4设置为独立按键。
- 循环扫描S7按键,按下时间小于1秒为短按,数码管数字加1,超过99后恢复为00;按下时间大于1秒为长按,数码管计数清零。
- 在按键扫描和处理过程中,确保不干扰数码管正常显示,避免按键误触发和多次处理的情况发生。
二、利用烧写工具中的定时器计数器定时
记得手打打开总中断EA
三、示例代码
#include "stc15.h"
void hc573(unsigned char channel, unsigned char value)
{
P2 = (P2 & 0x1f) | 0x00;
P0 = value;
switch(channel)
{
case 4:
P2 = (P2 & 0x1f) | 0x80; //LED
break;
case 5:
P2 = (P2 & 0x1f) | 0xa0; //蜂鸣器继电器
break;
case 6:
P2 = (P2 & 0x1f) | 0xc0; //数码管位选
break;
case 7:
P2 = (P2 & 0x1f) | 0xe0; //数码管段选
break;
}
P2 = (P2 & 0x1f) | 0x00;
}
void delay_smg(unsigned int t)
{
while(t--);
}
void delay_key(unsigned int t)
{
while(t--);
}
#define TSMG 500
unsigned char n = 28;
code unsigned char Seg_Table[] =
{
0xc0, //0
0xf9, //1
0xa4, //2
0xb0, //3
0x99, //4
0x92, //5
0x82, //6
0xf8, //7
0x80, //8
0x90, //9
0x88, //A
0x83, //b
0xc6, //C
0xa1, //d
0x86, //E
0x8e //F
};
//控制所有数码管
void smg_all(unsigned char dat)
{
hc573(6, 0xff);
hc573(7, dat);
}
//控制单个数码管
void smg_bit(unsigned char pos, unsigned char dat)
{
hc573(6, 0x01 << pos);
hc573(7, dat);
delay_smg(TSMG);
hc573(6, 0x01 << pos);
hc573(7, 0xff);
}
//数码管显示函数
void smg_display()
{
smg_bit(6, Seg_Table[(n / 10)]);
smg_bit(7, Seg_Table[(n % 10)]);
}
unsigned int count = 0;
extern unsigned char f_key;
void Timer0_Init(void) //10毫秒@12.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xF0; //设置定时初始值
TH0 = 0xD8; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1;
EA = 1;
}
void service_timer0 () interrupt 1
{
if(f_key == 1)
{
count++;
}
}
#define TKEY 200
sbit s7 = P3^0;
unsigned char f_key = 0;
void key_scan()
{
if(s7 == 0)
{
count = 0;
f_key = 1;
delay_key(TKEY);
if(s7 == 0)
{
while(s7 == 0)
{
smg_display();
}
f_key = 0;
if(count >= 100)
{
n = 0;
count = 0;
}
else
{
n++;
if(n > 99)
{
n = 0;
}
count = 0;
}
}
}
f_key = 0;
count = 0;
}
void init_sys()
{
hc573(5, 0x00); //关闭所有蜂鸣器和继电器
hc573(4, 0xff); //熄灭所以LED
smg_all(0xff); //熄灭所有数码管
Timer0_Init();
}
void main()
{
init_sys();
while(1)
{
smg_display();
key_scan();
}
}
-
void hc573(unsigned char channel, unsigned char value)
:定义了一个函数hc573
,用于控制573锁存器的输出。根据传入的通道号和数据值,设置相应的输出信号。 -
void delay_smg(unsigned int t)
:定义了一个延时函数delay_smg
,用于实现数码管显示的延时。 -
void delay_key(unsigned int t)
:定义了一个延时函数delay_key
,用于实现按键扫描的延时。 -
#define TSMG 500
:定义了一个宏TSMG
,值为500,用于设置数码管显示的延时时间。 -
unsigned char n = 28;
:定义了一个无符号字符型变量n
,初始值为28,用于存储数码管显示的数值。 -
code unsigned char Seg_Table[] = {...}
:定义了一个只读数据表Seg_Table
,存储了数码管显示的段选值。 -
void smg_all(unsigned char dat)
:定义了一个函数smg_all
,用于控制所有数码管的显示。 -
void smg_bit(unsigned char pos, unsigned char dat)
:定义了一个函数smg_bit
,用于控制单个数码管的显示。 -
void smg_display()
:定义了一个数码管显示函数smg_display
,在其中调用了smg_bit
函数实现数码管的显示。 -
unsigned int count = 0;
:定义了一个无符号整型变量count
,用于记录按键按下的持续时间。 -
extern unsigned char f_key;
:声明了一个外部的无符号字符型变量f_key
,用于按键扫描的标志。 -
void Timer0_Init(void)
:定义了一个定时器0初始化函数Timer0_Init
,用于设置定时器0的工作模式和初值,并开启定时器0。 -
void service_timer0 () interrupt 1
:定义了一个定时器0中断服务函数service_timer0
,用于处理定时器0的中断事件。 -
#define TKEY 200
:定义了一个宏TKEY
,值为200,用于设置按键扫描的延时时间。 -
sbit s7 = P3^0;
:定义了一个位变量s7
,表示P3口的第0位,用于表示S7按键的状态。 -
unsigned char f_key = 0;
:定义了一个无符号字符型变量f_key
,初始化为0,用于按键扫描的标志。 -
void key_scan()
:定义了一个按键扫描函数key_scan
,用于检测S7按键的按下情况并进行相应处理。 -
void init_sys()
:定义了一个系统初始化函数init_sys
,在其中关闭蜂鸣器、继电器、LED灯和数码管,并初始化定时器0。 -
void main()
:定义了主函数main
,在其中首先调用init_sys
进行系统初始化,然后进入一个无限循环,在循环中持续进行数码管显示和按键扫描的操作。