PIC Micro Controller C Input / Output Routine

SPI to RS232 converter

John F. Fitter says:

These routines are written in Hi-Tech C and are for use with the 'F876. Specificly, they write to a MAX3100 spi->rs232 interface chip.
/*********************************************************************************************/
/* Program : SPI.C */
/* Function : MOI Machine Controller SPI Utility Control Procedures */
/* Author : John F. Fitter B.E. */
/* */
/* Rev No. Rev date Test date Test platform Description */
/* ------- -------- --------- --------------- ---------------------------------- */
/* 00 6jun98 Original in HiTech C */
/* */
/* Copyright © 1998 Eagle Air Australia Pty. Ltd. All rights reserved */
/*********************************************************************************************/
#define _SPI_C

#include "commdefs.h"
#include "moi.h"
#include "spi.h"

// Procedure to setup the spi and the spi port pin directions
void setup_spi(unsigned char mode) {

	sdo_dir = B_OUT;  // make SDO output
	sck_dir = (mode & SPI_SLAVE) ? B_IN : B_OUT;  // make SCK input(slave) or output
	sdi_dir = B_IN;  // make SDI input
	if(mode & SPI_SLAVE & 0xf) ss_dir = B_IN;  // set SS mode bit to input if required
	spi_enable(false);  // disable ssp
	SSPCON = mode;  // set ssp mode
	spi_enable(true);  // re-enable ssp
}

// Procedure to read and return data from the spi - could call spi_write
// but will trade rom for stack levels in this case.
// The argument is the data to be transmitted (use 0 if none is required)
#pragma interrupt_level 1
unsigned char
Ispi_read(unsigned char txdata) {  // write and return received data
	unsigned char rxdata;

	rxdata = SSPBUF;  // lose any data in buffer, clear BF
	SSPBUF = txdata;  // load transmit data
	while(!spi_data_is_in());  // wait until transmit complete
	return SSPBUF;  // get received data, clear BF
}

// Procedure to read and return data from the spi - could call spi_write
// but will trade rom for stack levels in this case.
// The argument is the data to be transmitted (use 0 if none is required)
unsigned char spi_read(unsigned char txdata)
{  // write and return received data
	unsigned char rxdata;

	rxdata = SSPBUF;  // lose any data in buffer, clear BF
	SSPBUF = txdata;  // load transmit data
	while(!spi_data_is_in());  // wait until transmit complete
	return SSPBUF;  // get received data, clear BF
}
// Procedure to write data to the spi
void spi_write(unsigned char txdata) {
	unsigned char rxdata;

	rxdata = SSPBUF;  // lose any data in buffer, clear BF
	SSPBUF = txdata;  // load transmit data
	while(!spi_data_is_in()); // wait until transmit complete
}

void
InitSPI(void)
{
union regs3140 Spi_Regs;
unsigned char c1, c2;

	//set EXT interrupt for falling edge,used for RCV from MAX3140
    INTEDG = 1;

	//setup SPI to work with external max3140 USART
	//(uses a non-standard mode)

  	TRISC4 = 1;   //SPI Slave In
  	TRISC5 = 0;   //SPI Slave Out
  	TRISC3 = 0;   //SPI Slave CLK In
  	TRISC0 = 0;   //SPI SS Enabled Out as chip select

  	SSPEN = 1;   //SPI port pins enabled

  	CKP = 0;   //Clock idle is low

  	STAT_SMP = 1;   //SPI master mode Sample at END
  	STAT_CKE = 1;   //Data on rising edge

  	SSPM0 = 0;   //Slave Mode SS pin Disabled
  	SSPM1 = 0;
  	SSPM2 = 0;
  	SSPM3 = 0;

	spi_cs = 0;
	Spi_Regs.word.high = spi_read( 0b11000100  ); //Write CFG - IRQ on RCV
	Spi_Regs.word.low = spi_read( 0b00001010 );  //19200 BPS @ 3.6864MHz
	spi_cs = 1;

	spi_cs = 0;
	c1 = spi_read( RDCFG1 );
	c2 = spi_read( RDCFG2 );
	spi_cs = 1;
}

void
WriteSPIByte(int byte)
{
unsigned char t, c;
union regs3140 Spi_Regs;

	t = (unsigned char)byte;

	spi_cs = 0;
	Spi_Regs.word.high = spi_read( 0b10000000 );
	if(Spi_Regs.flag.R)
		RADEnQueue(spi_read(t));
	else
		c = spi_read(t);
	spi_cs = 1;

	DelayMs(1);
}

void
WriteSPI(int p1, ...)
{
int temp=p1, temp1=0;
unsigned char numBytes;
va_list marker;

	if(p1 == -1)
		return;

    va_start(marker, int);
    while(temp != -1)
    {
		temp1+=temp;
        WriteSPIByte(temp);

        temp = va_arg(marker, int);
    }
    va_end(marker);
}

// ***** EOF SPI.C *****

// SPIINT.C
#pragma interrupt_level 1
void interrupt
isr(void)
{
unsigned char i=0;
union regs3140 Spi_Regs;

    if(INTF && INTE)
    {
		while(!RB0)
		{
			spi_cs=0;
			Spi_Regs.word.high = Ispi_read( 0x00 );

			if(Spi_Regs.flag.R)
				IRADEnQueue(Ispi_read(0x00));
			else
				i = Ispi_read( 0x00 );

			spi_cs=1;
		}
		INTF=0; // Turn off the interrupt
    }
}
// ****** EOF SPIINT.C

//Here are some data structures if you want to easily manage the configuration bits
struct flags3140
{  		//Bits 0 .. 15
         unsigned BAUD  : 4;         //Baud Rate - 1011=9600BPS
         unsigned L     : 1;             //0=8 Bit word
         unsigned PE    : 1;            //0=No parity
         unsigned ST    : 1;            //0=1 stop bit
         unsigned IR    : 1;            //0=not use IRDA timing
         unsigned RAM   : 1;
         unsigned PM    : 1;            //0=do not assert IRQ for parity
         unsigned RM    : 1;            //1=assert IRQ for data received
         unsigned TM    : 1;            //1=assert IRQ for transmit empty
         unsigned SHDN  : 1;
         unsigned FEN   : 1;
         unsigned T     : 1;
         unsigned R     : 1;
};

struct word3140
{       //Bits 0 .. 15
         unsigned char low;
         unsigned char high;
};

union regs3140
{
         struct flags3140 flag;
         struct word3140 word;
};

Questions: