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

📄 periph.c

📁 单相电机变频驱动原码,采用DISPIC30芯片
💻 C
字号:
/****************************************************************
*
*		Microchip 16-bit Embedded Control Design Contest
*
*		Entry # MT2268
*
*		Spa Pump Controller
*
*****************************************************************
*
*		Miscellaneous peripheral routines:
*
*		I/O ports, Analog comparator, Timers
*
*****************************************************************/

#include "PumpCtl.h"
#include "Periph.h"
#include "Inverter.h"


#define INRUSH_THR	215		// Inrush charging threshold (0 - 252V)
							// = 240V * sqrt(2) * (1 - exp(-1))

#define INRUSH_MIN	50		// Minimum allowable charge time (msec)
#define INRUSH_MAX	200		// Maximum inrush wait time (msec)

#define VAC_THR_HI	150		// Line voltage comparator rising threshold (0 - 252V)
#define VAC_THR_LO	50		// Line voltage comparator falling threshold (0 - 252V)



#define CMP_INRUSH		((1023UL * (INRUSH_THR) * 1000 / 101) / 2500)
#define CMP_VAC_HI		((1023UL * (VAC_THR_HI) * 1000 / 101) / 2500)
#define CMP_VAC_LO		((1023UL * (VAC_THR_LO) * 1000 / 101) / 2500)
//						10 bits * Threshold (mV) / Res. divider / DAC reference (mV)


static volatile BYTE inrush_timer;		// Inrush relay delay timer
static volatile BYTE line_loss_timer;	// AC line loss detect timer
static volatile WORD freq_meas_timer;	// AC line frequency measurement timer
static volatile BYTE freq_meas_count;	// AC line frequency measurement cycle counter

static volatile WORD led_timer;			// LED blink timer


static enum {

	CMP_LOW		= 0,
	CMP_RISING	= 1,
	CMP_HIGH	= 2,
	CMP_FALLING	= 3

} cmp_state;


/*
	Initialize I/O pins
*/
void IO_init (void)
{

	ADPCFG = 0b10000000;	// Set RB7 to digital I/O, RB6:0 to ADC inputs

//	RB7 pin doesn't work (per Rev A1 Errata #8)
//	LATB  = 0b00000000;		// Set RB7 low
//	TRISB = 0b01111111;		// Set RB7 to output

	LATE  = 0b00000000;		// Set RE7 low (turn LED on)
	TRISE = 0b01111111;		// Set RE7 to output

	LATF  = 0b01000000;		// Set RF6 high (turn relay off)
	TRISF = 0b10111111;		// Set RF6 to output
}


/*
	Initialize comparators
*/
void Cmp_init (void)
{
	CMPCON1 = 0x8041;		// Enable cmp1 from input 1B (bus voltage) with 2.5V reference
	CMPDAC1 = CMP_INRUSH;

	CMPCON2 = 0x8001;		// Enable cmp2 from input 2A (AC voltage) with 2.5V reference
	CMPDAC2 = CMP_VAC_HI;
	cmp_state = CMP_LOW;
}


/*
	Initialize timers
*/
void Timer_init (void)
{
	led_timer = 0;
	inrush_timer = 0;
	line_loss_timer = 0;
	freq_meas_timer = 0;
	freq_meas_count = 0;

	TMR1 = 0;
	PR1 = FRC_CLK_FREQ * 2;		// Set period to Fcy (in kHz) for 1 msec timeout
	T1CON = 0x8000;				// Start the timer
}

/*
	The timer 1 interrupt executes every 1 msec

	It updates various timer variables, measures the
	power line frequency, and checks for power failure.
*/
void _ISR _T1Interrupt (void)
{
	_T1IF = 0;

	inv_update_timer ++;	// Incr inverter periodic update timer

	if (inv_update_timer >= INV_UPDATE_RATE) {
		inv_update_timer = 0;
		inv_update_flag = 1;
	}

	led_timer ++;			// Incr LED blink timer

	ping_timer ++;			// Incr ping received timer

	comm_timer ++;			// Incr serial comm timer

	if (inrush_timer < 255)
		inrush_timer ++;	// Incr inrush delay timer

	if (line_loss_timer > (1000 + 59) / 60)	// If no line signal for 1/60 second
		line_loss = 1;						//  set AC line loss flag
	else
		line_loss_timer ++;	// Incr time between line signal comparator transitions

	freq_meas_timer ++;		// Incr interrupt counter

/*
	The comparator tracks power line zero crossings.

	Two identical readings are needed before a transition is assumed.
	The threshold is adjusted at each transition to create hysteresis
	to help reduce the effect of noise.

	The rising transitions are counted, and after 120 of them (equal
	to 60 cycles of rectified sine wave), we check to see how many
	timer interrupts occurred, and adjust the osc tuning register
	if needed to get the correct value.
*/
	switch (cmp_state) {

		case CMP_LOW:
			if (CMPCON2bits.CMPSTAT)
				cmp_state = CMP_RISING;			// Indicate a rising transition
			break;

		case CMP_RISING:
			if (CMPCON2bits.CMPSTAT) {			// High twice in a row,
				CMPDAC2 = CMP_VAC_LO;			//  set threshold for falling detection
				cmp_state = CMP_HIGH;

				if (sys_mode.b.freq_meas) {

				  if (line_loss_timer >= 7 && line_loss_timer <= 10) {

					freq_meas_count ++;					// Incr cycle counter

					if (freq_meas_count == 60 * 2) {	// Measure time for 60 cycles

						if (freq_meas_timer >= 1000 + 5 && freq_meas_timer <= 1000 + 20)
							if (OSCTUNbits.TUN != 8)	// Timer is 0.5% to 2% too fast,
								OSCTUNbits.TUN --;		//  slow down system clock by 0.4%

						if (freq_meas_timer <= 1000 - 5 && freq_meas_timer >= 1000 - 20)
							if (OSCTUNbits.TUN != 7)	// Timer is 0.5% to 2% too slow,
								OSCTUNbits.TUN ++;		//  speed up system clock by 0.4%

						freq_meas_count = 0;
						freq_meas_timer = 0;
					}
				  }
				  else {
					freq_meas_count = 0;
					freq_meas_timer = 0;
				  }
				}

				line_loss_timer = 0;				// Reset interval timer

			}
			else
				cmp_state = CMP_LOW;
			break;

		case CMP_HIGH:
			if ( ! CMPCON2bits.CMPSTAT)
				cmp_state = CMP_FALLING;		// Indicate a falling transition
			break;

		case CMP_FALLING:
			if ( ! CMPCON2bits.CMPSTAT) {		// Low twice in a row,
				CMPDAC2 = CMP_VAC_HI;			//  set threshold for rising detection
				cmp_state = CMP_LOW;
			}
			else
				cmp_state = CMP_HIGH;
			break;
	}

}


/*
	LED blink task handler, called by the main routine

	The LED blink rate is proportional to the motor output frequency,
	or once every 2 seconds if stopped, or on solid if any fault.
*/
void LED_run (void)
{
	BYTE freq;

	if (sys_fault)
		LED_ON;				// Turn LED on if fault

	else {
		freq = Inv_get_freq ();

		if (led_timer >= (freq != 0) ? (768 - (freq * 2)) : 1000) {
			led_timer = 0;
			LED_TOGGLE;		// Blink LED
		}
	}
}


/*
	Start timing the inrush current capacitor charge time
*/
void Inrush_start (void)
{
	RELAY_OFF;			// Turn off inrush control relay

	inrush_timer = 0;
}


/*
	Inrush task handler, called by the main routine

	Wait for the bus capacitor to charge up to the inrush threshold,
	and check if the charge time is within valid limits.
*/
WORD Inrush_run (void)
{

	if (CMPCON1bits.CMPSTAT) {

		RELAY_ON;					// Turn on inrush control relay

		if (inrush_timer >= INRUSH_MIN)
			return (0);						// Charge time OK
		else
			sys_fault |= FAULT_inrush_fast;	// Charge time too short
	}

	else if (inrush_timer > INRUSH_MAX)
		sys_fault = FAULT_inrush_time;		// Charge time too long

	return (1);
}

⌨️ 快捷键说明

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