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

📄 serial.c

📁 单相电机变频驱动原码,采用DISPIC30芯片
💻 C
字号:
/****************************************************************
*
*		Microchip 16-bit Embedded Control Design Contest
*
*		Entry # MT2268
*
*		Spa Pump Controller
*
*****************************************************************
*
*		Serial communication routines
*
*****************************************************************/

#include "PumpCtl.h"
#include "Serial.h"
#include "Periph.h"
#include "ADC.h"
#include "Inverter.h"
#include "PFC.h"


#define SW_VERSION		0x01		// Software version

#define DEV_ADDR		0			// Device address (0 or 1)

#define BAUD			9600		// Serial baud rate

#define PING_TIMEOUT	750			// Keep-alive timeout (1 - 64K msec)
#define COMM_TIMEOUT	100			// Command receive timeout (1 - 255 msec)


enum {								// Command codes
	CMD_echo		= 1,
	CMD_get_ver		= 2,
	CMD_get_stat	= 3,
	CMD_set_mode	= 4,
	CMD_get_speed	= 5,
	CMD_set_speed	= 6,
	CMD_set_ramp	= 7,
	CMD_set_parm_lo	= 16,
	CMD_get_parm_lo	= 32,
	CMD_set_parm_hi	= 16 + 64,
	CMD_get_parm_hi	= 32 + 64
};


static BYTE comm_buf[3];			// Command buffer
static BYTE comm_count;				// Byte count


#define MAX_N_PARMS		16			// Maximum size of each parm table
#define N_RO_PARMS		(sizeof (ro_parm_tbl) / sizeof (WORD *))	// Actual table size
#define N_RW_PARMS		(sizeof (rw_parm_tbl) / sizeof (WORD *))

WORD *const ro_parm_tbl[] = {		// Read-only parameters

		&sys_fault,
		&sys_state,
		&inv_state,
		&pfc_state,

		&meas.nv.vsns_ac,
		(WORD *)&meas.nv.vsns_ac_pk + 1,	// high word only
		&meas.nv.vsns_bus,
		&meas.nv.isns_pfc,
		&meas.nv.isns_aux,
		&meas.nv.isns_run,
		&meas.nv.isns_com,
		&meas.nv.temp_pfc,
		&meas.nv.temp_inv,
};

WORD *const rw_parm_tbl[] = {		// Read-write parameters

		&sys_mode.w,

		&pfcp.v_gain_p,
		&pfcp.v_gain_f,
		&pfcp.i_gain_p,
		&pfcp.i_gain_i,
		&pfcp.i_gain_lim,
		&pfcp.v_nom,
		&pfcp.v_low_thr,
		&pfcp.v_high_thr,
		&pfcp.max_duty,

		(WORD *)&invp.ramp,
		&invp.ampl_var,
		&invp.delta_nom,
		&invp.delta_thr,
		&invp.offset_nom,
		&invp.offset_thr,
};


BYTE Exec_cmd (BYTE cmd, BYTE data);


/*
	Serial comm task handler, called by the main routine

	Receive a command block from the serial port,
	execute the command, and send back a response.
*/
void Comm_run (void)
{
	WORD i;
	BYTE result;

	// Wait until the transmit FIFO is empty, so we can write out
	// the entire response block at once without additional buffering.
	if (Serial_Xempty () == 0) {

		i = Serial_Recv ();					// Check for incoming data

		if (i != SERIAL_EOF) {				// Byte received

			comm_buf[comm_count] = i;		// Save it in buffer
			comm_count ++;					// Incr buffer count

			comm_timer = 0;					// Clear comm timeout

			if (comm_count == 3) {			// Entire command received

				if (((comm_buf[0]+comm_buf[1]+comm_buf[2]) & 0xFF) == 0xFF	// Checksum OK
							&& (comm_buf[0] & 0x80) == (DEV_ADDR << 7)) {	// Our address

					result = Exec_cmd (comm_buf[0], comm_buf[1]);	// Do the command

					i = Serial_Xmit (comm_buf[0]);			// Transmit result block
					if (i == 0) {
						i = Serial_Xmit (result);
						if (i == 0)
							i = Serial_Xmit (0xFF - ((comm_buf[0] + result) & 0xFF));
					}

					if (i == 0)
						ping_timer = 0;
					else
						sys_fault |= FAULT_ser_xmit;
				}

				comm_count = 0;			// Clear buffer byte count
			}
		}
	}

	if (comm_count != 0)				// If partial command received
		if (comm_timer >= COMM_TIMEOUT)	//  but we've waited too long,
			comm_count = 0;				//  clear command buffer

	if (ping_timer >= PING_TIMEOUT)		// If nothing received for too long,
		sys_fault |= FAULT_ping_time;	//  set fault flag
}


/*
	Execute a command
*/
BYTE Exec_cmd (BYTE cmd, BYTE data)
{
	BYTE result;

	if (cmd >= CMD_get_parm_lo + MAX_N_PARMS			// Get a read-only parm (0x30-3F)
	 && cmd <  CMD_get_parm_lo + MAX_N_PARMS + N_RO_PARMS)
		return ((*ro_parm_tbl[cmd - (CMD_get_parm_lo + MAX_N_PARMS)]) & 0xFF);

	if (cmd >= CMD_get_parm_hi + MAX_N_PARMS			// Get high byte (0x70-7F)
	 && cmd <  CMD_get_parm_hi + MAX_N_PARMS + N_RO_PARMS)
		return ((*ro_parm_tbl[cmd - (CMD_get_parm_hi + MAX_N_PARMS)]) >> 8);

	if (cmd >= CMD_get_parm_lo							// Get a read/write parm (0x20-2F)
	 && cmd <  CMD_get_parm_lo + N_RW_PARMS)
		return ((*rw_parm_tbl[cmd - CMD_get_parm_lo]) & 0xFF);

	if (cmd >= CMD_get_parm_hi							// Get high byte (0x60-6F)
	 && cmd <  CMD_get_parm_hi + N_RW_PARMS)
		return ((*rw_parm_tbl[cmd - CMD_get_parm_hi]) >> 8);

	if (cmd >= CMD_set_parm_lo							// Set a read/write parm (0x10-1F)
	 && cmd <  CMD_set_parm_lo + N_RW_PARMS) {
		*(BYTE *) (*rw_parm_tbl[cmd - CMD_set_parm_lo]) = data;
		return (0);
	}

	if (cmd >= CMD_set_parm_hi							// Set high byte (0x50-5F)
	 && cmd <  CMD_set_parm_hi + N_RW_PARMS) {
		*(BYTE *) ((*rw_parm_tbl[cmd - CMD_set_parm_hi]) + 1) = data;
		return (0);
	}

	switch (cmd) {

		case CMD_echo:				// Echo received data
			return (data);
			break;

		case CMD_get_ver:			// Get software version
			return (SW_VERSION);
			break;

		case CMD_get_stat:			// Get running and fault status
			result = 0;
			if (inv_state == RUNNING || inv_state == RAMP_UP || inv_state == RAMP_DOWN)
				result |= 0x80;
			if (pfc_state == P_RUNNING)
				result |= 0x40;
			if (sys_fault & 0x8000)
				result |= 0x04;
			if (sys_fault & 0x7F00)
				result |= 0x02;
			if (sys_fault & 0x00FF)
				result |= 0x01;
			return (result);
			break;

		case CMD_set_mode:			// Set running mode & clear faults
			if (data & 0x80)
				Inv_start ();
			else
				Inv_stop ();
			if (data & 0x01)
				sys_fault = 0;
			return (0);
			break;

		case CMD_get_speed:			// Get inverter frequency
			return (Inv_get_freq ());
			break;

		case CMD_set_speed:			// Set inverter frequency
			if (data != 0)
				Inv_set_freq (data);
			else
				Inv_stop ();
			return (0);
			break;

		case CMD_set_ramp:			// Not yet supported!
			return (0);
			break;

		default:
			return (0xFF);
			break;
	}
}


/*
	Initialize serial port
*/
void Serial_init (void)
{

	U1BRG = ((((LONG) FRC_CLK_FREQ * 2000UL) + (BAUD * 16UL / 2UL)) / (BAUD * 16UL)) - 1;
	U1MODEbits.UARTEN = 1;
	U1STAbits.UTXEN = 1;
}


/*
	Receive a character, or return SERIAL_EOF if none
*/
WORD Serial_Recv (void)
{
	BYTE data;

	if (! U1STAbits.URXDA)
		return (SERIAL_EOF);

	data = U1RXREG;

	return (data);
}


/*
	Transmit a character, or return SERIAL_ERR if not ready
*/
WORD Serial_Xmit (BYTE data)
{

	if (U1STAbits.UTXBF)
		return (SERIAL_ERR);

	U1TXREG = data;

	return (0);
}


/*
	Check if serial FIFO is empty, return SERIAL_ERR if not
*/
WORD Serial_Xempty (void)
{

	if (! U1STAbits.TRMT)			// Transmit FIFO not empty
		return (SERIAL_ERR);

	return (0);
}

⌨️ 快捷键说明

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