定时器怎么计数 (定时计数器有几种工作方式)

(本实验中的蜂鸣声 用LED10闪烁来表示,该实验中 STC15-IV版试验箱 上运行)

建一个文件夹,里面建两个子文件夹,一个叫仿真,一个叫真机

用keil C 创建工程,创建文件,粘贴代码:

#include<reg51.h>

#define uchar unsigned char

#define uint unsigned int

uint bdata key;//声明变量,键状态

uint bdata edgk;//声明变量,键变化前沿

uchar data kcode;//声明变量,键编号

uchar data ktmr;//定义变量,消抖计时器

uchar data beeftmr;//定义变量,蜂鸣计时器

sbit BEEF=P3^0;//定义变量,蜂鸣器控制I/O

sbit K17=P3^3; //定义按键接口

sbit K0=key^8;//定义变量,开关型键位。大端方式:低字节存高地址,第8位始

sbit K1=key^9;

sbit K2=key^10;

sbit K3=key^11;

sbit K4=key^12;

sbit K5=key^13;

sbit K6=key^14;

sbit K7=key^15;

sbit K8=key^0;

sbit K9=key^1;

sbit KA=key^2;

sbit KB=key^3;

sbit KC=key^4;

sbit KD=key^5;

sbit KE=key^6;

sbit KF=key^7;

sbit EK0=edgk^8;//定义变量,触发型键位

sbit EK1=edgk^9;

sbit EK2=edgk^10;

sbit EK3=edgk^11;

sbit EK4=edgk^12;

sbit EK5=edgk^13;

sbit EK6=edgk^14;

sbit EK7=edgk^15;

sbit EK8=edgk^0;

sbit EK9=edgk^1;

sbit EKA=edgk^2;

sbit EKB=edgk^3;

sbit EKC=edgk^4;

sbit EKD=edgk^5;

sbit EKE=edgk^6;

sbit EKF=edgk^7;

/*sbit P_595_SER=P4^0; //定义 74HC595 的串行数据接口

sbit P_595_SRCLK=P4^3; //定义 74HC595 的移位脉冲接口

sbit P_595_RCLK=P5^4; //定义 74HC595 的输出寄存器锁存信号接口 */

uchar code seg7[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e}; //七段码表 0~9

uchar code scand_com[4]={0xfe,0xfd,0xfb,0xf7}; //4 种位选线信号数据

uchar data dis_buf[4]; //定义显示缓冲区

uchar data scand_num; //定义当前扫描位

/*void delay2ms5() //延时 2.5ms

{

unsigned int j;

for(j=0;j<429;j++);

} */

/*void send_595(uchar x) //从 STC 单片机移位输出 1 字节数据

{ uchar i;

for(i=0;i<8;i++) //循环移位,共 8 位

{

x=x<<1; //左移 1 位,最高位移出到 CY

P_595_SER=CY; //CY 从串行数据口输出

P_595_SRCLK=1; //输出移位脉冲

P_595_SRCLK=0;

}

}*/

void Timer0Int()//T0初始化,2.5ms定时@12MHz

{TMOD=0x01;//T0方式1,16位定时,初值不能重载

TL0=(65536-2500)%256;//T0定时器初值设置

TH0=(65536-2500)/256;

TF0=0;//清定时器溢出标志

TR0=1;//启动定时器

}

void readkey()//扫描键盘、存键状态

{uchar i;

P0=0x7f;//扫描第3列,列线输出为0

for(i=0;i<20;i++);//延时约10uS待列信号稳定,若键盘引线较长应延长

edgk=(~P0<<4)&0xf0;//读KC~KF键,有键按下读行线为0,求反转正逻辑

P0=0xbf;//扫描第2列

for(i=0;i<20;i++);

edgk|=(~P0)&0x0f;//读K8~KB键

edgk<<=8;

P0=0xdf;//扫描第1列

for(i=0;i<20;i++);

edgk|=(~P0<<4)&0xf0;//读K4~K7键

P0=0xef;//扫描第0列

for(i=0;i<20;i++);

edgk|=(~P0)&0x0f;//读K0~K3键

}

void keytrim()//消抖动,沿检出,求键号

{uint temp;//本行以下为:消抖动

if(edgk==0)ktmr=0;//无键,消抖计时器清零

else

{if(ktmr<255)ktmr++;//有键,消抖计时器+1(防溢出)

if(ktmr<8)edgk=0;//消抖20mS未到丢弃不稳定键

}

temp=edgk;//本行及以下为:键变化前沿提取。edgk保存本次键状态

edgk=(key^edgk)&edgk;//此时key还保存着上次循环键状态

key=temp;//暂存的本次循环键状态移至key

if(edgk!=0)//本行及以下为:求键号

{temp=edgk;//从低到高逐位查键,未查出kcode+1

for(kcode=0;(temp&0x1)==0;kcode++)temp>>=1;

}

else kcode=0x10;//无键,kcode=0x10

}

void keysound()//按键发出"嘀"声响

{if(edgk!=0)beeftmr=40;//有键变化沿,蜂鸣倒计时器100mS初值

if(beeftmr!=0){beeftmr--;BEEF=1;}//蜂鸣时间未到,走时、蜂鸣开

else BEEF=0;//蜂鸣时间已到,蜂鸣关

}

void display(void) //显示驱动函数

{

P2=0xff; //关闭所有位

P1=seg7[dis_buf[scand_num&3]]; //将当前扫描位七段码送 P1 口

P2=scand_com[scand_num&3]; //将当前扫描位选线信号送 P2 口

scand_num=(scand_num+1)%4; //调整扫描位的值,指向下一位

}

void main(void)

{

Timer0Int();

dis_buf[0]=0x0; dis_buf[1]=0x1; //显示"0123"

dis_buf[2]=0x2; dis_buf[3]=0x3;

while(1)

{

//delay2ms5();

//P1M1=0;

//P1M0=0;

while(!TF0);//2.5mS定时未到则等待

TF0=0;//清定时器溢出标志

TL0=(65536-2500)%256;//定时器初值恢复

TH0=(65536-2500)/256;

readkey();

display();

keytrim();//调用键状态消抖等处理函数

keysound();

K17=1; //准双向口,读之前先写 1

if(kcode<16)

{

dis_buf[0]=dis_buf[1]; dis_buf[1]=dis_buf[2];//键号从右边滚入

dis_buf[2]=dis_buf[3]; dis_buf[3]=kcode;

}

}

}

编译运行,并保存为.c的文件,添加在本工程的Group下面。

点击"project"下的"options for target1 'target1'",找到output选项,勾选"create hex file"

再次编译运行,就能在该文件夹中找到 相应的.hex文件

用Proteus画出仿真电路图

如何让定时器控制计数器,定时计数器延时怎么设置

双击电路图中单片机,添加刚刚的.hex文件,点击运行按钮,就开始模拟了。

你能看到显示的是0123(你想改成什么就是什么了)

.用keil C创建工程(保存在真机的文件夹下面),创建文件,粘贴代码

#include<stc15.h>

#include<intrins.h>

#define uchar unsigned char

#define uint unsigned int

uint bdata key;//声明变量,键状态

uint bdata edgk;//声明变量,键变化前沿

uchar data kcode;//声明变量,键编号

uchar data ktmr;//定义变量,消抖计时器

uchar data beeftmr;

//sbit BEEF=P3^0;//定义变量,蜂鸣计时器

sbit K17=P3^3; //定义按键接口

sbit P_595_SER=P4^0; //定义 74HC595 的串行数据接口

sbit P_595_SRCLK=P4^3; //定义 74HC595 的移位脉冲接口

sbit P_595_RCLK=P5^4; //定义 74HC595 的输出寄存器锁存信号接口

sbit K0=key^8;//定义变量,开关型键位。大端方式:低字节存高地址,第8位始

sbit K1=key^9;

sbit K2=key^10;

sbit K3=key^11;

sbit K4=key^12;

sbit K5=key^13;

sbit K6=key^14;

sbit K7=key^15;

sbit K8=key^0;

sbit K9=key^1;

sbit KA=key^2;

sbit KB=key^3;

sbit KC=key^4;

sbit KD=key^5;

sbit KE=key^6;

sbit KF=key^7;

sbit EK0=edgk^8;//定义变量,触发型键位

sbit EK1=edgk^9;

sbit EK2=edgk^10;

sbit EK3=edgk^11;

sbit EK4=edgk^12;

sbit EK5=edgk^13;

sbit EK6=edgk^14;

sbit EK7=edgk^15;

sbit EK8=edgk^0;

sbit EK9=edgk^1;

sbit EKA=edgk^2;

sbit EKB=edgk^3;

sbit EKC=edgk^4;

sbit EKD=edgk^5;

sbit EKE=edgk^6;

sbit EKF=edgk^7;

uchar code seg7[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; //七段码表 0~9 a-f

uchar code scand_com[4]={0xfe,0xfd,0xfb,0xf7}; //4 种位选线信号数据

uchar data dis_buf[4]; //定义显示缓冲区

uchar data scand_num; //定义当前扫描位

void Timer0Int()//T0初始化,2.5ms定时@12MHz

{

TMOD=0x01;//T0方式1,16位定时,初值不能重载

TL0=(65536-2500)%256;//T0定时器初值设置

TH0=(65536-2500)/256;

TF0=0;//清定时器溢出标志

TR0=1;//启动定时器

}

void send_595(uchar x) //从 STC 单片机移位输出 1 字节数据

{

uchar i;

for(i=0;i<8;i++) //循环移位,共 8 位

{

x=x<<1; //左移 1 位,最高位移出到 CY

P_595_SER=CY; //CY 从串行数据口输出

P_595_SRCLK=1; //输出移位脉冲

P_595_SRCLK=0;

}

}

void readkey()//扫描键盘、存键状态

{

uchar i;

P0=0x7f;//扫描第3列,列线输出为0

for(i=0;i<20;i++);//延时约10uS待列信号稳定,若键盘引线较长应延长

edgk=(~P0<<4)&0xf0;//读KC~KF键,有键按下读行线为0,求反转正逻辑

P0=0xbf;//扫描第2列

for(i=0;i<20;i++);

edgk|=(~P0)&0x0f;//读K8~KB键

edgk<<=8;

P0=0xdf;//扫描第1列

for(i=0;i<20;i++);

edgk|=(~P0<<4)&0xf0;//读K4~K7键

P0=0xef;//扫描第0列

for(i=0;i<20;i++);

edgk|=(~P0)&0x0f;//读K0~K3键

}

void keytrim()//消抖动,沿检出,求键号

{uint temp;//本行以下为:消抖动

if(edgk==0)ktmr=0;//无键,消抖计时器清零

else

{

if(ktmr<255)ktmr++;//有键,消抖计时器+1(防溢出)

if(ktmr<8)edgk=0;//消抖20mS未到丢弃不稳定键

}

temp=edgk;//本行及以下为:键变化前沿提取。edgk保存本次键状态

edgk=(key^edgk)&edgk;//此时key还保存着上次循环键状态

key=temp;//暂存的本次循环键状态移至key

if(edgk!=0)//本行及以下为:求键号

{

temp=edgk;//从低到高逐位查键,未查出kcode+1

for(kcode=0;(temp&0x1)==0;kcode++)temp>>=1;

}

else kcode=0x10;//无键,kcode=0x10

}

void keysound()//按键发出"嘀"声响

{

if(edgk!=0)beeftmr=40;//有键变化沿,蜂鸣倒计时器100mS初值

if(beeftmr!=0){beeftmr--;P46=0;}//蜂鸣时间未到,走时、蜂鸣开 ,0表示亮

else P46=1;//蜂鸣时间已到,蜂鸣关

}

void display(void) //显示驱动函数

{

send_595(scand_com[scand_num&3]);//将当前扫描位选线信号发送

send_595(seg7[dis_buf[scand_num&3]]);//将当前扫描位七段数据发送

P_595_RCLK=1;//16位数据移位后锁入输出寄存器中

P_595_RCLK=0;

scand_num=(scand_num+1)%4; //调整扫描位的值,指向下一位

}

void main(void)

{

P0M1=0;

P0M0=0;

Timer0Int();

dis_buf[0]=0x0; dis_buf[1]=0x1; //显示"0106"

dis_buf[2]=0x0; dis_buf[3]=0x6;

while(1)

{

while(!TF0);//2.5mS定时未到则等待

TF0=0;//清定时器溢出标志

TL0=(65536-2500)%256;//定时器初值恢复

TH0=(65536-2500)/256;

readkey();

display();

keytrim();//调用键状态消抖等处理函数

keysound();

K17=1; //准双向口,读之前先写 1

if(kcode<16)

{

dis_buf[0]=dis_buf[1]; dis_buf[1]=dis_buf[2];//键号从右边滚入

dis_buf[2]=dis_buf[3]; dis_buf[3]=kcode;

}

}

}

重复步骤2的类似操作。

5.最后连接上真正的单片机实验板,载入程序即可

你可以在SW16键盘上面按键,从而LED10灯会闪烁