您的位置: proteus仿真社区 >> 论坛 >> 单片机仿真 >> 查看帖子
字体: 小 中 大 | 打印 发表于: 2008-8-15 10:11 作者: yuxu9710108 来源: proteus仿真社区
最新回复
yuxu9710108 (2008-8-15 10:12:38)
#include "reg51.h"
#ifndef FREQ_OSC
#define FREQ_OSC (12)//12Mhz
#endif
#define HIGH_WAVE 1
#define LOW_WAVE 0
sbit LED=P1^0;
static unsigned char __TL0_high;
static unsigned char __TH0_high;
static unsigned char __TL0_low;
static unsigned char __TH0_low;
static int flag;
/* 1)CPU时序:
* XTAL1, XTAL2并联石英谐振器和振荡电容后产生单片机的基本时钟频率fosc
* 基本时钟:fosc --> 振荡周期:Tosc <--> 一个Tosc对应一个节拍P1/P2相 --> 2个Tosc构成一个状态周期Ts
* --> 6个状态周期Ts组成一个机器周期TM --> 机器周期是指令周期的基本单位
* fosc --> Tosc == P1/P2 -->Ts --> TM -->指令周期
* 所以一个指令周期 == 1个TM == 6Ts == 12Tosc == 6个P1+6个P2
* 单周期指令 = 1个指令周期 = 1TM = 6Ts = 12Tosc
* 双周期指令 = 2个指令周期 = 2TM = 12Ts = 24Tosc
*
* 指令运行速度:MIPS = fosc/12 (MIPS)
* fosc 6Mhz MIPS 6Mhz/12=0.5 MIPS 每秒伍十万条指令
* fosc 12Mhz MIPS 12Mhz/12=1 MIPS 每秒一百万条指令
* fosc 24Mhz MIPS 24Mhz/12=2 MIPS 每秒二百万条指令
* fosc 48Mhz MIPS 48Mhz/12=4 MIPS 每秒四百万条指令
*
* 2)反汇编代码如下:
* 16: TH0 = __TL0_HIGH;
* C:0x08CE 85088C MOV TH0(0x8C),0x08
* 17: TL0 = __TL0_LOW;
* C:0x08D1 85098A MOV TL0(0x8A),0x09
* 18: TR0 = 1;
* C:0x08D4 D28C SETB TR0(0x88.4)
* 19: LED = ~LED;
* C:0x08D6 B290 CPL LED(0x90.0)
* 注意:MOV, SETB, CPL均为1个TM,1个指令周期
* 这里每次时钟中断都要重设TH0,TL0,TR0,均要多消耗3个指令周期所以计数值__TL0_LOW再加上3个周期以校正
*/
void led_int() interrupt 1 using 0
{
if( flag == LOW_WAVE){
TH0 = __TH0_high;
TL0 = __TL0_high;
TR0 = 1;
LED = ~LED;
flag = HIGH_WAVE;
}
else if(flag == HIGH_WAVE){
TH0 = __TH0_low;
TL0 = __TL0_low;
TR0 = 1;
LED = ~LED;
flag = LOW_WAVE;
}
else{
}
}
int check_us(unsigned short x_us)
{
if(x_us < (12 / FREQ_OSC)){
return -1;
}
return 0;
}
//计数脉冲周期:
//T(us) = 1/(fosc (Mhz) / 12)将fosc进行12分频后再送入计数器,所以不同频率的CPU其计数脉冲周期不同,最小可分辨的时间精度不同。
//不同频率的CPU的/计数脉冲周期
//6Mhz: T(us) = 12 / (6 Mhz) = 2us
//12Mhz:T(us) = 12 / (12 Mhz) = 1us
//24Mhz:T(us) = 12 / (24 Mhz) = 0.5us
//48Mhz:T(us) = 12 / (48 Mhz) = 0.25us
//单次定时方式1,16位计数,最大定时长度:
//6Mhz: 2us * 2^16 /1000 131ms
//12Mhz: 1us * 2^16 /1000 65ms
//24Mhz: 0.5us * 2^16 /1000 32ms
//48Mhz: 0.25us * 2^16 /1000 16ms
//x:所定的半周期时间,以微秒为单位
//计数初值m = 2^16 - x*fosc/12
void init_rectangular_wave(unsigned short x_us_high, unsigned short x_us_low)
{
unsigned short m;//计数初值
if(-1 == check_us(x_us_high))
return ;
if(-1 == check_us(x_us_low))
return ;
TMOD = 0x01;//TMOD: GATE c/nT M1 M0 : 计数器由内部TRi位控制启停,计时功能,方式一:16位计数
m = 2^16 - (x_us_high * FREQ_OSC) / 12;
__TL0_high = m & 0x00ff;
__TH0_high = (m & 0xff00) >> 8;
__TL0_high -= 5;//校正计时常数,当定时越小时,这个校正因数当越大
m = 2^16 - (x_us_low * FREQ_OSC) / 12;
__TL0_low = m & 0x00ff;
__TH0_low = (m & 0xff00) >> 8;
__TL0_low -= 7;//校正计时常数,当定时越小时,这个校正因数当越大
LED = 1;
TL0 = __TL0_high;
TH0 = __TH0_high;
EA = 1;
ET0 = 1;
TR0 = 1;
flag = HIGH_WAVE;
}
void init_led()
{
LED = 0;
}
int main()
{
init_led();
init_rectangular_wave(30, 120);
while( 1 )
{
;
}
return 0;
}
yuxu9710108 (2008-8-15 10:15:17)
hekun559 (2008-8-17 21:23:52)
顶下楼主~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`
bj301 (2008-8-18 00:32:25)
yuxu9710108 (2008-8-18 17:40:50)
不知有没有更好更精确的方法[软件上]来统一解决之
janfen406 (2008-8-19 22:37:27)
fghjkl (2008-8-20 11:09:38)
fghjkl (2008-8-20 11:13:20)
djh2007 (2008-8-20 11:22:00)