发布网友 发布时间:2022-04-22 06:08
共2个回答
热心网友 时间:2023-07-20 12:38
系统时钟是11.059MHz
那么定时器每走一次是1/11.059us,那么5ms就要n=5000/(1/11.059)次,向定时器(若是16位)初值就是65536-n.
外部晶振很准的,程序写好后在用示波器观察,再做细调.
热心网友 时间:2023-07-20 12:39
你要多准确?
对应系统时间T=0.0904uS,5mS=55309.7<65536,可以用定时器0工作在16位定时模式。CKCON=0X04;
TMOD=0X01;
//------------------
void Timer0_Delay (void)interrupt 1 using 1{
TH0=(65536-55310)/256;
TL0=(65536-55310)%256;
}
55309为4999.9336(少6ns),55310为5000.0240(多240ns)。定时器时钟选系统时钟,
或者:
//-----------------------------------------------------------------------------
// Timer0_Poll1.c
//-----------------------------------------------------------------------------
// 此程序是一个使用定时器T0在查询模式的例子实现一个延时计数器精度1ms
//
// 假设在XTAL1和XTAL2之间接22.1184MHz晶体
//
// 系统时钟频率存储在全局常量SYSCLK.
//
// 目标器件: C8051F02x
// 链接工具: KEIL C51 6.03 / KEIL EVAL C51
//
//-----------------------------------------------------------------------------
// 包含文件
//-----------------------------------------------------------------------------
#include <c8051f020.h> // SFR声明
//-----------------------------------------------------------------------------
// C8051FF02x的16位SFR定义
//-----------------------------------------------------------------------------
sfr16 DP = 0x82; // 数据指针
sfr16 TMR3RL = 0x92; // 定时器T3重装值
sfr16 TMR3 = 0x94; // 定时齐器T3计数器
sfr16 ADC0 = 0xbe; // ADC0数据
sfr16 ADC0GT = 0xc4; // ADC0大于窗口
sfr16 ADC0LT = 0xc6; // ADC0小于窗口
sfr16 RCAP2 = 0xca; // 定时器T2捕捉/重装
sfr16 T2 = 0xcc; // 定时器T2
sfr16 RCAP4 = 0xe4; // 定时器T4 捕捉/重装
sfr16 T4 = 0xf4; // 定时器T4
sfr16 DAC0 = 0xd2; // DAC0数据
sfr16 DAC1 = 0xd5; // DAC1数据
//-----------------------------------------------------------------------------
// 全局常量
//-----------------------------------------------------------------------------
#define SYSCLK 11059200 // 系统时钟频率Hz
sbit LED = P1^6; // LED=’1’ 意为ON
sbit SW1 = P3^7; // SW1=’0’ 意为按下开关
//-----------------------------------------------------------------------------
// 函数原型
//-----------------------------------------------------------------------------
void SYSCLK_Init (void);
void PORT_Init (void);
void Timer0_Delay (int ms);
//-----------------------------------------------------------------------------
// 全局变量
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// 主程序
//-----------------------------------------------------------------------------
void main (void) {
WDTCN = 0xde; // 禁止看门狗定时器
WDTCN = 0xad;
SYSCLK_Init (); // 初始化振荡器
PORT_Init (); // 初始化数据交叉开关和通用IO口
while (1) {
Timer0_Delay (5); // 延时5ms
LED = ~LED; //改变LED状态
}
}
//-----------------------------------------------------------------------------
// 初始化子程序
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// 系统时钟初始化
//-----------------------------------------------------------------------------
//
// 此程序初始化系统时钟使用11.0592MHz晶体作为时钟源
//
void SYSCLK_Init (void)
{
int i; // 延时计数器
OSCXCN = 0x67; // 启动外部振荡器晶振
for (i=0; i < 256; i++) ; // 等待振荡器启动
while (!(OSCXCN & 0x80)) ; // 等待振荡器稳定
OSCICN = 0x88; // 选择内部振荡器为时钟源并使能丢失时钟检测器
}
//-----------------------------------------------------------------------------
// IO口初始化
//-----------------------------------------------------------------------------
//
// 配置数据交叉开关和通用IO口
//
void PORT_Init (void)
{
XBR0 = 0x00;
XBR1 = 0x00;
XBR2 = 0x40; // 使能数据交叉开关和弱上拉
P1MDOUT |= 0x40; // 使能P1.6(LED)为推挽输出
}
//-----------------------------------------------------------------------------
// Timer0_Delay
//-----------------------------------------------------------------------------
//
// 配置定时器T0延时.
//
void Timer0_Delay (int ms)
{
int i; // 毫秒计数器
TCON &= ~0x30; // 停止定时器T0并清除溢出标志
TMOD &= ~0x0f; // 配置定时器T0为16位模式
TMOD |= 0x01;
CKCON |= 0x08; // 定时器T0计数系统时钟
for (i = 0; i < ms; i++) { // 数毫秒
TR0 = 0; // 停定时器T0
TH0 = (-SYSCLK/1000) >> 8; // 设置定时器T0 1ms溢出
TL0 = -SYSCLK/1000;
TR0 = 1; // 启动定时器T0
while (TF0 == 0); // 等待溢出
TF0 = 0; // 清除溢出标志
}
}