是不是用这个11.0592MHz晶振的原因呢?
12/11.0592=1.085us. 最终导致了误差的产生和累积.
程序里用的是模式1. (是LCD显示的,网上下载的程序)
我以前做过一个(是LED显示的,网上下载的程序),用的是12MHz的晶振,就很准的啊!!!
不对,用11.0592M的晶体时钟一样很准,条件是必须是5的倍数,看: // 单片机执行一条指令所需要的时钟周期数 (6或12) // 在此使用的是AT89C52芯片,每个机器周期=12*时钟周期 #define OSC_PER_INST (12)
// 晶体为11.0592M或22.1184M //#define OSC_FREQ (11059200UL) #define OSC_FREQ (22118400UL)
// 创建可移植的硬件定时溢出 // 此处定时溢出(TIMEROUT必须等于5或是5的倍数) #define TIMEROUT (5) // 单位是毫秒(最小基数是5) #define PRELOAD_mS (65536 - (TIMEROUT * OSC_FREQ) / (OSC_PER_INST * 1000)) // 当晶体是11.0592M或是其倍数是,定时器低位自动装载 #define PRELOAD_mS_H (PRELOAD_mS /256)
注意: 要用定时器低位自动装载或T2的高低位自动装载.好像论坛上有一个贴就是讨论时钟误差的问题的,上面的代码我就是受到它的启发定成的.关于定时器误的问题.hotpower 和 所长都有说过,LZ存细找找看.
例: /*--------------------------------------------------------------------------------*-
MAIN.H (V1.1)
项目头文件 (Project Header)
-*---------------------------------------------------------------------------------*/
/* * Copyright (c) 2006,wsl于深圳xxxx硬件工程部 * All rights reserved * * 文件名称: main.h * 文件标识: 项目头文件(Project Header) * 摘 要: 包含控制器类型,振荡器的频率,执行一条指令 * 所需要的振荡器的周期数,公共的数据类型, * 及定义中断向量值. * * 当前版本: 1.1 * 取代版本: * 作 者: * 原作者 : Michael J.Pont * 完成日期: 2006-09-14 * 完成日期: **********************************************************************************/
#ifndef _MAIM_H //防止main.h被重复引用 #define _MAIN_H
/**********************************************************************************/
#include<intrins.h> #include <string.h>
#ifndef NULL #define NULL ((void *) 0L) /*Stdlib.h and String.h already include NULL */ #endif //--------------------------------------------------------------------------------- // 每个项目都要修改这一段 //--------------------------------------------------------------------------------- // 控制器类型 //#include "REG52.H" #include "STC12C5410AD.H" /**********************************************************************************/ // 单片机执行一条指令所需要的时钟周期数 (6或12) // 在此使用的是AT89C52芯片,每个机器周期=12*时钟周期 #define OSC_PER_INST (12)
// 晶体为11.0592M或22.1184M //#define OSC_FREQ (11059200UL) #define OSC_FREQ (22118400UL)
// 创建可移植的硬件定时溢出 // 此处定时溢出(TIMEROUT必须等于5或是5的倍数) #define TIMEROUT (5) // 单位是毫秒(最小基数是5) #define PRELOAD_mS (65536 - (TIMEROUT * OSC_FREQ) / (OSC_PER_INST * 1000)) // 当晶体是11.0592M或是其倍数是,定时器低位自动装载 #define PRELOAD_mS_H (PRELOAD_mS /256)
/***************************************************************************************/ //--------------------------------------------------------- // 以下部分不需要修改 //--------------------------------------------------------- // 杂项宏定义 #ifndef TRUE #define FALSE 0 #define TRUE (!FALSE) #endif
#define INT_EA EA #define INT_ET2 ET2 #define INT_ES ES #define INT_ET1 ET1 #define INT_EX1 EX1 #define INT_ET0 ET0 #define INT_EX0 EX0
#define INTERRUPT_ENABLE() INT_EA = TRUE /*开总中断标志位*/ #define INTERRUPT_DISABLE() INT_EA = FALSE /*禁止所有中断*/ #define INTERRUPT_GET() INT_EA /*读中断*/ #define INTERRUPT_SET(bit) INT_EA = (bit) /* 设置中断,即EA = 0或1 */
#define SETBIT(A,B) (A |= 1 << (B)) /*A=Register, B=Bitnumber (7..0)*/ #define RESETBIT(A,B) (A &= ~(1 << (B))) /*A=Register, B=Bitnumber (7..0)*/ #define GETBIT(A,B) ((A >> B) & 0x01)
#endif
/*---------------------------------------------------------*- --------------------NED OF FILE-------------------------- -*---------------------------------------------------------*/
/*--------------------------------------------------------------------*-
SysTick.C (V1.00)
这里是系统的时标. -*---------------------------------------------------------------------*/
/* * Copyright (c) 2007 * All rights reserved * * 文件名称: SysTick.C * 文件标识: * 摘 要: 系统的时标(20mS) * * 当前版本: 1.0 * 取代版本: * 作 者: * 原作者 : * 完成日期: 2007-07-31 * 完成日期: ************************************************************************/
#include "LCD_Dis.h" #include "SysTick.h"
// 串行口发送 unsigned char Txd_Buffer[MAX_TRANSMIT_LENGTH]; unsigned char data Txd_Counter; // 串行口要发送的字节数 bit Sendit; // 串口发送状态. 0 发送中, 1 发送完毕
unsigned char G_speek = 0; unsigned char dot = 8;
// 私有函数 static void serial_transmit(unsigned char *pBuffer,unsigned char number,unsigned char MaxLen);
/*---------------------------------------------------------*- * 函数名称: T0_TICK_INIT() * 入 口: xx * 出 口: xx * 函数功能: T0初始化 * * 说 明: 为了时标的准确性,系统采用T0模式1,16位加载模式. * 将T0的低位计数器设计为自动加载. * * 当前版本: 1.0 * 取代版本: * 作 者: * 原作者 : * 完成日期: 2007-07-31 * 完成日期: -*---------------------------------------------------------*/ void T0_TICK_INIT(void) { TMOD &= 0xf0; TMOD |= 0x01; TL0 = 0; TH0 = PRELOAD_mS_H; ET0 = 1; TR0 = 1; }
/*---------------------------------------------------------*- * 函数名称: SystemTick() * 函数功能: 系统时标.任何任务执行时间都不能大于系统时标. * 说 明: T0的低位计数器为自动加载. (系统时标为5mS) * 当前版本: 1.0 * 取代版本: * 作 者: * 原作者 : * 完成日期: 2007-07-31 * 完成日期: -*---------------------------------------------------------*/ void SystemTick(void) interrupt 1 using 1 { TH0 = PRELOAD_mS_H;
} 上面就是系统时标完整的代码.看看对89cpu是否有用. |