上一篇文章讲了原理和示例程序查找。这一篇讲怎么修改例程。
定时器0 1ms中断一次 1s翻转LED1一次
思维导图
内部晶振 11.0592MHz
1T 不分频
设置定时器的工作模式 16位自动装载
计算1ms需要计时的次数
修改定时器0中断函数
使能定时器中断
开始计数
开启总中断
确定内部晶振 11.0592MHz
时钟周期的长度由计算机的硬件实现决定,通常以赫兹(Hz)为单位来给出。在这种情况下,11.0592MHz的意思是,硬件内部的时钟周期长度为1/11.0592MHz秒。如果我们要使用这个时钟周期来进行1毫秒的定时计数,我们需要将11.0592MHz除以1000,计算得出的数值是11,059.2。因此,我们需要使用一个11,059.2计数器来实现1毫秒的定时计数。
#define FOSC 11059200L
#define T1MS (65536-FOSC/1000) //1T模式
确定要不要分频
分频和倍频是数字电路中常用的两种信号处理方式。
分频
分频是将输入信号的频率降低到较低的频率,常用于产生时钟信号。常见的分频电路有二分频、四分频、八分频等。例如,将一个100MHz的时钟信号进行二分频,输出的信号频率为50MHz。
倍频
倍频是将输入信号的频率提高到较高的频率,常用于提高计算机处理速度。常见的倍频电路有二倍频、四倍频、八倍频等。例如,将一个200MHz的信号进行二倍频,输出的信号频率为400MHz。
以上是分频和倍频的基本概念和应用。在实际电路设计中,根据具体的需求和条件,可以选择不同的分频和倍频电路进行设计。
定时器的最大定时时间
65536/工作频率(单位:秒) 1T模式
65536/(工作频率/12)(单位:秒) 12T模式
分频的目的就是增大计时时间
设置定时器的工作模式 16位自动装载
TMOD = 0x00; //设置定时器为模式0(16位自动重装载)
计算1ms需要计时的次数
#define T1MS (65536-FOSC/1000) //1T模式
TL0 = T1MS; // 1111 1110 1111 1100 //初始化计时值TL0 是8位的,所以只能存前8位数据
TH0 = T1MS >> 8; //高字节数据右移8位,就可以存放到TH0了
修改定时器0中断函数
/* Timer0 interrupt routine */
void tm0_isr() interrupt 1
{
count++;
if(count>999)
{
count = 0;
LED2 = ! LED2; //进入中断函数1000次,LED2反转一次
}
//将测试口取反
}
使能定时器 中断开始计数 开启总中断
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
EA = 1;
总程序
main.c
#include "main.h"
/*主函数LED1 2S一个周期闪烁
LED2 在定时器0中断函数中 1S翻转一次
*/
void main(void)
{
system_init();
while(1)
{
LED1 = 1;
Delay1s();//在此只加了一个延时
LED1 = 0;
Delay1s();//不加延时,灭后迅速被点亮
}
}
main.h
#ifndef __MAIN_H
#define __MAIN_H
#include "STC15Wxx.h"
#include "init.h"
#include "delay.h"
#include "timer.h"
//引脚定义 LED1 LED2
sbit LED1 = P3^1;
sbit LED2 = P3^0;
#endif
delay.c
#include "delay.h"
#include "intrins.h"//包含空指令_nop
/*STC官方提供的有延时函数
STC15W104 系列 内部RC晶振
ISP编程时内部时钟从5MHz~35MHz可设(5.5296MHz / 11.0592MHz / 22.1184MHz / 33.1776MHz).
低功耗设置时,我们可以选择5.5296MHz的晶振。
*/
void Delay100ms() //@5.5296MHz
{
unsigned char i, j, k;
_nop_();
_nop_();
i = 3;
j = 26;
k = 223;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Delay1s()
{
char i ;
for(i=0;i<10;i++)
{
Delay100ms();
}
}
void Delay2s()
{
char i ;
for(i=0;i<20;i++)
{
Delay100ms();
}
}
delay.h
#ifndef __DELAY_H
#define __DELAY_H
void Delay100ms(); //@5.5296MHz
void Delay1s();
void Delay2s();
#endif
timer.c
#include "main.h"
//#define T1MS (65536-FOSC/12/1000) //12T模式
unsigned int count;
void timer0_init()
{
AUXR |= 0x80; //定时器0为1T模式
// AUXR &= 0x7f; //定时器0为12T模式
TMOD = 0x00; //设置定时器为模式0(16位自动重装载)
TL0 = T1MS; // 1111 1110 1111 1100 //初始化计时值TL0 是8位的,所以只能存前8位数据
TH0 = T1MS >> 8; //高字节数据右移8位,就可以存放到TH0了
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
EA = 1;
}
/* Timer0 interrupt routine */
void tm0_isr() interrupt 1
{
count++;
if(count>999)
{
count = 0;
LED2 = ! LED2;
}
//将测试口取反
}
timer.h
#ifndef __TIMER_H
#define __TIMER_H
#define FOSC 11059200L
#define T1MS (65536-FOSC/1000) //1T模式
void timer0_init();
#endif
init.c
#include "main.h"
void system_init(void)
{
//配置成准双向IO口,内部有弱上拉
//P0M0 和P0M1 两个寄存器可以控制P0的7个IO口
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;
P3M0 |= 0x02;// P3M1 0 P3M0 1 配置P3^1 推挽输出
//配置
AUXR |= 0x80; //定时器0为1T模式
TMOD = 0x00; //设置定时器为模式0(16位自动重装载)
TL0 = T1MS; // 1111 1110 1111 1100 //初始化计时值TL0 是8位的,所以只能存前8位数据
TH0 = T1MS >> 8; //高字节数据右移8位,就可以存放到TH0了
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
EA = 1;
LED1 = 0;//LED1 点亮
LED2 = 0;//LED2 点亮
}
init.h
#ifndef __INIT_H
#define __INIT_H
void system_init(void);
#endif