
具体的调用方式可以参考通过如下程序:
程序功能:利用定时器进行定时,实现每秒中led闪烁一次
#include<reg52h>sbit led = P0^0;
unsigned int num;
void main(void)
{
TMOD = 0x00; // 工作方式0
TH0 = (8192 - 5000) / 32; // 12M晶振下定时5ms
TL0 = (8192 - 5000) % 32;
EA = 1; // 开总中断
ET0 = 1; // 开定时器中断
TR0 = 1; // 启动定时器
while(1)
{
if(num == 200) // 定时1秒钟到
{
num = 0; // 计数器清零
led = ~led; // led灯取反,实现1秒闪烁一次
}
}
}
void timer() interrupt 1 // 定时器1工作与方式0
{
TH0 = (8192 - 5000) / 32; // 重装初值
TL0 = (8192 - 5000) % 32;
num++; // 计数器加1
}
问题一:为什么16ms对应的是16000??
12MHz的晶振下,CPU得到的频率是1M,因为51单片机是内部十二分频的。那么对应的一个时钟的周期就是1us,16000us就是16ms,也就是16000个周期后将产生溢出,如果你的程序里全能了定时中断和全局中断,那么将会发生定时器中断。但你程序一里面的写法是有问题的。应该是
TH0 = (-16000/256);
TL0 = (-16000%256);
或者
TH0 = (65536-16000)/256;
TL0 = (65536-16000)%256;
问题二:为什么高八位要除256,低八位求余??
51单片机是八位的单片机的,里面的寄存器都是八位的(DPTR除外),所以一个十六位的数据需要用两个八位的的寄存器来存放。在定时器0工作方式1下,51单片机是十六位的定时器,所以要用TH0来存放定时数据的高八位,用TL0来存放数据的低八位。
一个十六位数除以256得到的就是这个数的高八位,再对256求余,得到的就是这个数的低八位。
问题三:为什么要加小括号??是多余的吗?我在另一个程序(如下)中看到的初值还加上个负号是怎么回事??-5000是指50ms么??
不加也是可以的,但并不是说多余的,这是编程风格的习惯,推荐这种习惯,不会容易出错。
使用负值的写法,其实是使用补码的方法写的,-5000的十六进制数也就是0xec78,刚好是等于65536-5000,所以在这个程序里,-5000/256=(65536-5000)/256,但是呢,不推荐这种写法,因为数据类型与编译器是有关的,应该并成记好的习惯,推荐用(65536-5000)/256的写法。
那么问题一一样-5000/256=(65536-5000)/256,可以看出定时是5ms,当然这个是有前的,就是你使用的晶振是12MHz的。
希望可以帮到你,对这三个问题还有什么疑问,可以扣我236376723
#include
#define
uchar
unsigned
char
uchar
distab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff};
uchar
times,num;
void
t0isr()
interrupt
1
{
TH0=(65536-50000)/256;
//重置初值
TL0=(65536-50000)%256;
times++;
if(times>=20)
//1秒是否到
{
times=0;
num--;
//1秒到后,计数值减1
P0=distab[num];
//显示
if(num==0)num=9;
//到0后再赋值为9
}
}
main()
{
TMOD=0x01;
//定时器0为16为定时
TH0=(65536-50000)/256;
//50毫米中断一次
TL0=(65536-50000)%256;
ET0=1;
EA=1;
num=9;
times=0;
TR0=1;
while(1);
}
以下是四位数码管可调时带秒闪烁的c51单片机电子钟程序(c语言)。
/ 本程序中,晶振为12MHz, /
/ 时间控制采用定时中断控制方式。 /
/ 模式和时间调整采用查询方式。 /
#include<reg52h>
sbit P20=P2^0; //分个位控制端
sbit P21=P2^1; //分十位控制端
sbit P22=P2^2; //时个位控制端
sbit P23=P2^3; //时十位控制端
sbit led=P2^7; //second display led
sbit key0=P3^0; //模式设置
sbit key1=P3^1; //加
sbit key2=P3^2; //减
unsigned char hour,min,sec,T50ms;
unsigned char modstate; //模式状态
unsigned char code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff};//段码
void init(); //初始化子程序声明
void delay500us(unsigned char X); //延时子程序声明
void display(); //显示子程序声明
void display001(); //显示子程序声明
void display002(); //显示子程序声明
void keyscan(); //按键识别子程序声明
void main()
{
init();
while(1)
{
keyscan();
}
}
void init() //初始化子程序
{
TMOD=0x01;
TH0=(65536-49990)/256;
TL0=(65536-49990)%256;
ET0=1;
EA=1;
TR0=1;
}
void delay500us(unsigned char X)
{
unsigned char i,j;
for(i=X;i>0;i--)
for(j=248;j>0;j--);
}
void timer0() interrupt 1 //timer0中断服务子程序,定时时间为50ms,本程序加了10us的时间修正量
{
TMOD=0x01;
TH0=(65536-49990)/256;
TL0=(65536-49990)%256;
T50ms++;
if(T50ms>=20)
{
T50ms=0;
sec++;
if(sec>=60)
{
sec=0;
min++;
if(min>=60)
{
min=0;
hour++;
if(hour>=24)hour=0;
}
}
}
}
void display()
{
P20=1;
P21=1;
P22=1;
P23=1;
P0=table[hour/10];
P23=0;
delay500us(5);
P20=1;
P21=1;
P22=1;
P23=1;
P0=table[hour%10];
P22=0;
delay500us(5);
P20=1;
P21=1;
P22=1;
P23=1;
P0=table[min/10];
P21=0;
delay500us(5);
P20=1;
P21=1;
P22=1;
P23=1;
P0=table[min%10];
P20=0;
delay500us(5);
if(T50ms<=10)led=0;
if(T50ms>10)led=1;
}
void display001()
{
P20=1;
P21=1;
P22=1;
P23=1;
P0=table[hour/10];
P23=0;
delay500us(10);
P20=1;
P21=1;
P22=1;
P23=1;
P0=table[hour%10];
P22=0;
delay500us(10);
}
void display002()
{
P20=1;
P21=1;
P22=1;
P23=1;
P0=table[min/10];
P21=0;
delay500us(10);
P20=1;
P21=1;
P22=1;
P23=1;
P0=table[min%10];
P20=0;
delay500us(10);
}
void keyscan() //按键识别钟程序
{
while(modstate==0)
{
display();
if(key0==0)
{
display();
if(key0==0)modstate++; //这两句加在一起为延时10ms软件防抖设计。
while(key0==0)display001(); //等待按键释放。
}
}
////
while(modstate==1)
{
display001();
if(key0==0)
{
display001();
if(key0==0)modstate++; //这两句加在一起为延时10ms软件防抖设计。
while(key0==0)display002(); //等待按键释放。
}
if(key1==0)
{
display001();
if(key1==0)
{
hour++;
if(hour>=24)hour=0;
while(key1==0)display001();
}
}
if(key2==0)
{
display001();
if(key2==0)
{
hour--;
if(hour>=24)hour=0;
while(key2==0)display001();
}
}
}
////
while(modstate==2)
{
display002();
if(key0==0)
{
display002();
if(key0==0)modstate=0; //这两句加在一起为延时10ms软件防抖设计。
while(key0==0)display(); //等待按键释放。
}
if(key1==0)
{
display002();
if(key1==0)
{
min++;
if(min>=60)min=0;
while(key1==0)display002();
}
}
if(key2==0)
{
display002();
if(key2==0)
{
min--;
if(min>=60)min=0;
while(key2==0)display002();
}
}
}
}
图中那示波器的接法有什么用?应该是监测P20口和P23口吧。
编程如下:
#include <reg52h> //52系列头文件
#define uchar unsigned char //变量类型宏定义
#define uint unsigned int
sbit Key = P2^0; //按键位声明
sbit Bell = P2^3; //门铃位声明
uint p; //中断次数变量
void main() //主程序
{
TMOD = 0x00; //设置T0工作于方式0
TH0 = (8192-700)/32; //T0计数器装入定时700us初值
TL0 = (8192-700)%32;
IE = 0x82; //开总中断,开T0中断
if(Key==0) //如果键被按下
{
TR0 = 1; //启动T0定时器计时
}
while(Key==0); //等待按键松开
}
void Timer0() interrupt 1 //T0中断服务子程序
{
Bell = ~Bell; //每次中断发生时,门铃状态取反
p++; //中断计次值加1
if(p<=400) //如果中断<=400次,
{
TH0 = (8192-700)/32; //重装700us定时初值
TL0 = (8192-700)%32;
}
if(p>400) //如果中断次数>400
{
TH0 = (8192-1000)/32; //则重装定时 1ms 初值
TL0 = (8192-1000)%32;
if(p==1000) //如果中断次数 =800次
{
P = 0; //中断计数值归0
TR0 = 0; //关闭T0定时器
}
}
}
*** 作说明:每当按下并保持,响铃一声。松开后再按,即重复上述状态。
以上就是关于单片机C语言定时器如何调用全部的内容,包括:单片机C语言定时器如何调用、【满分求教】单片机C程序,关于定时设置初值的n多疑问、单片机怎么设计一个0-9的一位数秒表,用定时器实现 c语言程序及其注释等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)