⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 timerb.c

📁 这是一个在在Dynamic C环境下实现的设备web服务器的建立
💻 C
字号:
/*** BeginHeader */
#ifndef _TIMERB_FUNC_
#define _TIMERB_FUNC_
/*** EndHeader */

/* START LIBRARY DESCRIPTION *********************************************
timerb.lib

 Generic TIMERB.
 Support the following:
  1. periodic call to user routine every timer int
  2. supports times from about 15us to 1500 seconds with 11.0592mHz xtal (22.1 clock)
  3. Note serial port baud rates <2700 effect timer, set up serial ports first
  Interrupts faster than 20,000/sec start to become too much overhead for use
 TimerBinit() must be called to initialize the ISR
  assumes 11.0592mHz x2 crystal (CPU is 22.1mhz)
  unless XTAL_FREQ is set to freq in hz
 Calls user-supplied function root nodebug void TimerBRoutine()
  if FAST_TIMERB is defined, only, hl,de,ix,a,f are saved in ISR and TimerBRoutine
   must be asm code that saves any regs it uses
END DESCRIPTION **********************************************************/

/* START FUNCTION DESCRIPTION ********************************************
TimerBInit                       <TIMERB.LIB>

SYNTAX:  int TimerBInit(int usec)

DESCRIPTION:
 Cause a user function TimerBRoutine() to be called every usec microseconds
 Notes:
  1. periodic call to user routine every timer int
  2. supports times from about 20us to 1500 seconds with 11.0592mHz xtal (22.1 clock)
  3. Interrupts faster than 20,000/sec start to become too much overhead for use
  4. TimerBinit() must be called to initialize the ISR
  5. Uses bios freq_divider for calcs
  6. If <100us, best to modify library asm isr. (inlince code, no call to ext)
  7. Note serial port baud rates <2700 effect timer, set up serial ports first
  Calls user-supplied function root nodebug void TimerBRoutine()
  if FAST_TIMERB is defined, only regs: hl,de,ix,a,f are saved in ISR and
   TimerBRoutine MUST be asm code that saves any regs it uses
RETURN VALUE: non-0 if out of range
END DESCRIPTION **********************************************************/

/*** Beginheader */

#ifndef XTAL_FREQ
// bios has 19200*16 divisor calculated
#define XTAL_FREQ ((long)freq_divider * 307200L)
#endif

//extern unsigned      int task_ms_no,task_20ms_no,task_100ms_no,task_1s_no;
//extern unsigned      char task_inv_no;
//extern unsigned char    task_20ms_en ;


unsigned int		_timerb_scale;
unsigned long		_timerb_divisor;
int					_timerb_inc;
unsigned int		_timerb_ctr;
// used by isr
int 				_timerb_match;
/*** EndHeader */

/*** BeginHeader TimerBInit */
int TimerBInit( unsigned long usec, char intlevel );
/*** EndHeader */
nodebug int TimerBInit( unsigned long usec, char intlevel )
{
	auto unsigned long			divisor;
	auto long					timeradiv, intscale;

#GLOBAL_INIT
{
	// init timer a for 1/256 divide. Serial ports set to <2700 baud will
	// change this (BTW, bug in serial lib will screw up if more than
	// one port is set to two different rates below 2600.)
	WrPortI( TAT1R, &TAT1RShadow, 0xFF ); // the bios does not init this
}

	WrPortI( TBCSR, &TBCSRShadow, 0x00 ); // disable timer B and its interrupts
	_timerb_scale = 0; // no scale be default
	// if serial ports are using timer A1 we cant modify it.
	timeradiv	= TAT1RShadow + 1L;
	if( timeradiv < 8 )
		timeradiv = 8; // if <8 then we must use only t2
	divisor = (long)(((float)usec * (float)XTAL_FREQ) / 1.0e6 + 0.5);
	// use intlevel to calc TBCR value
	if( divisor < 165 ) // not enough instructions for accurate time between ints
		return 1;

	if( divisor > (1024L*timeradiv*65535L) ) // max for using both timer a and b
		return 1;

	if( divisor > (1024L*timeradiv) ) // max for using both timer a and b
	{
		// try to calc best value
		intscale = divisor/(1024L*timeradiv) - 1;
		if( intscale < 2L )
	  		intscale = 2L; // sanity chck

		while( (divisor/(long)intscale) > (1024L*timeradiv) )
	  		++intscale;

	 	if( intscale > 65535L )
	  		return 1;

		divisor = divisor / intscale; // nearest
		_timerb_scale = _timerb_ctr = (unsigned int) intscale; // init first
	}

	if( divisor <= 1024L ) // timer b with pclk/2 direct
	{
		intlevel &= 3;  // mask valid
	 	_timerb_divisor = divisor;
	}
	else if( divisor <= 8192L ) // timer b with pclk/16
	{
		intlevel 	= 0x8 | (intlevel & 3);  // mask valid set pclk/2
		divisor 	= (divisor + 4L) / 8L;   // round to nearest
		_timerb_divisor = divisor * 8L;
	}
	else
	{
		// we need timerA! // timera --> timerb
		intlevel 	= 0x4 | (intlevel & 3);  // mask valid set timera
		divisor		= (divisor + (timeradiv >> 1)) / timeradiv;
		_timerb_divisor	= divisor * timeradiv;
	}

	_timerb_inc = (int)((divisor & 0xff) | ((divisor << 6) & 0xc000)); // val for isr
	if( _timerb_scale )
		_timerb_divisor *= _timerb_scale; // we use scale in isr

	SetVectIntern( 0x0B, _TimerBISR );    	// set up ISR
	WrPortI( TBCR, &TBCRShadow, intlevel ); // clock timer B with Ai out and
	WrPortI( TBL1R, NULL, 0x00 );   		// set initial match, isr calcs acutal
	WrPortI( TBM1R, NULL, 0x00 );
	WrPortI( TBCSR, &TBCSRShadow, 0x03 );	// enable timer B and B1 match interrupts

	return 0; // :-)
}


/*** Beginheader _TimerBISR */
interrupt _TimerBISR(void);
/*** Endheader */
#ifdef FAST_TIMERB
#asm root nodebug fast
_TimerBISR::
	push hl
	push ix
	push de
	push af
#else
nodebug interrupt _TimerBISR(void)
{
#asm nodebug fast
#endif
	ld  hl,(_timerb_match)
	ld  de,(_timerb_inc)
	add hl,de
	ld  a,h
	bit  0,a   			; carry?
	jr  z,no_inc
	add a,03fh			; if carry, inc upper two bits
// and 0xc0  ; need this so lower does not carry into calced upper
	ld  h,a
no_inc:
	ld  (_timerb_match),hl
	; high is aready in a
	ioi ld (TBM1R), a	; NOTE:  you _need_ to reload the match
	ld  a, l			; next low in a
	ioi ld (TBL1R), a	; set up next B1 match (at timer = 0000h)
						; register after every interrupt!

	ioi ld a, (TBCSR)	; load B1, B2 interrupt flags (clears flag)
						; are we scaling int calls to user routine?
	ld  hl, (_timerb_scale)
	ld  ix,hl      		; 'cache' value for later (faster than ld hl,(..))
	bool hl
	jr  z,no_scale
	; ok so we need to count down
	ld  hl,(_timerb_ctr)
	dec hl
	ld  (_timerb_ctr),hl
	bool hl
	jr  nz,skip_user
	ld  (_timerb_ctr),ix
no_scale:
	call TimerBRoutine   ; do user func
skip_user:
#ifdef FAST_TIMERB
	pop af
	pop de
	pop ix
	pop hl
	ipres
	ret
#endasm
#else
#endasm
}
#endif

/*** BeginHeader TimerBRoutine */
void TimerBRoutine(void);
/*** EndHeader */
void TimerBRoutine(void)
{

    unsigned char i;
    
    for(i=0;i<MAX_CHANNEL;++i)
    {
	    Calcval(i);
    }
}
/*** BeginHeader */
#endif
/*** EndHeader */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -