定时器配合独立按键控制流水灯模式
#include <STC8H.H>
#include<INTRINS.H>
unsigned int mode = 0;
void delay(void) //@12.000MHz
{
unsigned char data i, j, k;
_nop_();
_nop_();
i = 10;
j = 31;
k = 147;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
int getnum()
{
unsigned int b = 0;
if(P34 == 0)
{
delay();
while(P34 == 0)
{
;
}
delay();
b = 1;
return b;
}
if(P35 == 0)
{
delay();
while(P35 == 0)
{
;
}
delay();
b = 2;
return b;
}
return b;
}
void Timer0_Init(void) //1毫秒@12.000MHz
{
//可以具体操作某定时器的四位而不影响另外一个定时器的配置
TMOD &= 0xF0;
TMOD |= 0x01;
TL0 = 0x18; //设置定时初始值
TH0 = 0xFC; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1;
EA = 1;
PT0 = 0;
}
void main()
{
unsigned n = 0;
unsigned int num = 0;
P0M0 = 0x00; P0M1 = 0x00;
P1M0 = 0x00; P1M1 = 0x00;
P2M0 = 0x00; P2M1 = 0x00;
P3M0 = 0x00; P3M1 = 0x00;
P4M0 = 0x00; P4M1 = 0x00;
P5M0 = 0x00; P5M1 = 0x00;
P6M0 = 0x00; P6M1 = 0x00;
P7M0 = 0x00; P7M1 = 0x00;
P40 = 0;
P6 = 0xfe;
Timer0_Init();
while(1)
{
n = getnum();
switch(n)
{
case 1:
mode = 1;
break;
case 2:
mode = 2;
break;
default:
break;
}
}
}
void Timer0_Isr(void) interrupt 1
{
static unsigned int count = 0;
TL0 = 0x18; //设置定时初始值
TH0 = 0xFC;
count++;
if(count >= 500)
{
count = 0;
if(mode == 1)
{
P6 = _crol_(P6,1);
}
if(mode == 2)
{
P6 = _cror_(P6,1);
}
}
}
-
定时器的配置
void Timer0_Init(void) //1毫秒@12.000MHz
{
//可以具体操作某定时器的四位而不影响另外一个定时器的配置
TMOD &= 0xF0;
TMOD |= 0x01;
TL0 = 0x18; //设置定时初始值
TH0 = 0xFC; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1;
EA = 1;
PT0 = 0;
}
stc8h8k64u 单片机共有五个定时器(详情参考使用手册),首先我们先配置定时器模式寄存器(TMOD),在这里我们这使用定时器T0,所以给TMOD赋0000 0001,TL0,TH0两个八位寄存器在16位模式合在一起使用,定时器1us自增一次,16位的最高值位65535,我们这里将这两个寄存器的初始值设置为64535,也就是1ms中断一次,TF0位溢出进位标志,先将其请0,TR0为定时器开始计时标志,1为开始计时,ET0则为允许中断,1表示允许中断,EA和PT0则是打开中断里的两个通路(也可以不配置)
-
相关寄存器
-
逻辑实现
void Timer0_Isr(void) interrupt 1
{
static unsigned int count = 0;
TL0 = 0x18; //设置定时初始值
TH0 = 0xFC;
count++;
if(count >= 500)
{
count = 0;
if(mode == 1)
{
P6 = _crol_(P6,1);
}
if(mode == 2)
{
P6 = _cror_(P6,1);
}
}
}
在这个中断函数里,由于我们上面设置了定时器为1ms,所以我们使用一个静态变量(调用完函数不会销毁),来控制你想打要实现的定时,比如我这里的count >= 500就是0.5s,然后通过主函数获取独立按键按下,获取流水灯的模式(正向和反向),这里的_crol_(左移)_cror_(右移),为库函数,包含头文件#include<INTRINS.H>即可使用,这两个函数的优点在于使得P6口在1111 1110 - 1111 1110之间循环。
数码管显示0-9循环
#include <STC8H.H>
#include<INTRINS.H>
unsigned int num = 0;
unsigned int arr[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xBF};
void delay(void) //@12.000MHz
{
unsigned char data i, j, k;
_nop_();
_nop_();
i = 10;
j = 31;
k = 147;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Timer0_Init(void) //1毫秒@12.000MHz
{
//可以具体操作某定时器的四位而不影响另外一个定时器的配置
TMOD &= 0xF0;
TMOD |= 0x01;
TL0 = 0x18; //设置定时初始值
TH0 = 0xFC; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1;
EA = 1;
PT0 = 0;
}
void main()
{
P0M0 = 0x00; P0M1 = 0x00;
P1M0 = 0x00; P1M1 = 0x00;
P2M0 = 0x00; P2M1 = 0x00;
P3M0 = 0x00; P3M1 = 0x00;
P4M0 = 0x00; P4M1 = 0x00;
P5M0 = 0x00; P5M1 = 0x00;
P6M0 = 0x00; P6M1 = 0x00;
P7M0 = 0x00; P7M1 = 0x00;
P40 = 0;
P7 = ~0x01;
Timer0_Init();
while(1)
{
P6 = arr[num];
}
}
void Timer0_Isr(void) interrupt 1
{
static unsigned int count = 0;
TL0 = 0x18; //设置定时初始值
TH0 = 0xFC;
count++;
if(count >= 600)
{
count = 0;
if(num < 9)
{
num++;
}
else
{
num = 0;
}
}
}
这里我是使用了一个数组存储了数码管显示0-9的十六进制数,显示的位置固定为第一个数码管,在中断函数中当0.6s到了,对全局变量num++(num来作为数组的下标),控制num在0-9以内,因为在主函数里p6 = arr[num],且在while死循环里,当num改变时p6口也随之改变。