MSP430 SPI-Master IO without interrupt
/**
* @file SPI.h
* Control's for the SPI
*/
#ifndef FILE_SPI_H
#define FILE_SPI_H
class SPI
{
public:
/**
* @brief Init for SPI
* @details
* @param void
* @return void
*/
static void _Init(void);
/**
* @brief Send data to Display
* @details
* @param unsigned char msg - Message send to Display
* @return void
*/
static void LCD_DataOut(unsigned char msg);
/**
* @brief Send data to Display
* @details Display mode must be set
* @param char* msg - Message send to Display
* @param int Length - Length of message send to Display
* @return void
*/
static void LCD_DataOut(char *msg, int Length);
/**
* @brief Send command to Display
* @details
* @param unsigned char msg - Message send to Display
* @return void
*/
static void LCD_CommOut(unsigned char msg);
private:
typedef enum {ModeIdle, ModeLCD, ModeMem} SPI_Modes;
static SPI_Modes SPI_Mode;
/**
* It configures SPI in a mode to communicate to the selected device
* @param Mode This defines the mode to configure.
*/
static void ConfigSPI(SPI_Modes Mode);
/**
* It performs data exchange via SPI for a given number of inputs and outputs
* @param TX pointer to transmit buffer or 0. if 0 then a dummy byte is sent (0x81)
* @param RX pointer to receive buffer or 0
* @param IOcount total number of receive and transmit bytes
*/
static void DoSPI_IO(char* TX, char* RX, int IOcount);
};
#############################################
/**
* @file SPI.c
* Control's for the SPI
*/
#include "SPI.h"
#include "msp430.h"
#define ArrayLength(array) (sizeof(array)/sizeof(array[0]))
/// Macro to set a bit y in variable x
#define SETB(x,y) (x |= (1 << y))
/// Macro to reset a bit y in variable x
#define CLRB(x,y) (x &= ~(1 << y))
SPI::SPI_Modes SPI::SPI_Mode;
/**
* @brief Init for SPI
* @details
* @param void
* @return void
*/
void SPI::_Init(void)
{
SPI_Mode = ModeIdle;
}
/**
* @brief Send data to Display
* @details Display mode must be set
* @param unsigned char msg - Message send to Display
* @return void
*/
void SPI::LCD_DataOut(unsigned char msg) //Data Output Serial Interface
{
ConfigSPI(ModeLCD);
CLRB(P3OUT,4); //Chip Select = Active, CS = 0
SETB(P2OUT,7); //A0 = Data, A0 = 1
/* Software delay for selection line to settle */
__delay_cycles(25);
while (UCBUSY & UCB0STAT); // Wait until SPI is no longer busy
UCB0TXBUF = msg; // Transmit Message
while (UCBUSY & UCB0STAT); // Wait until SPI is no longer busy
SETB(P3OUT,4); //after 1 byte, Chip Select = inactive, CS =1
}
/**
* @brief Send data to Display
* @details Display mode must be set
* @param char* msg - Message send to Display
* @param int Length - Length of message send to Display
* @return void
*/
void SPI::LCD_DataOut(char *msg, int Length) //Data Output Serial Interface
{
ConfigSPI(ModeLCD);
CLRB(P3OUT,4); //Chip Select = Active, CS = 0
SETB(P2OUT,7); //A0 = Data, A0 = 1
/* Software delay for selection line to settle */
__delay_cycles(25);
DoSPI_IO(msg, 0, Length);
SETB(P3OUT,4); //after 1 byte, Chip Select = inactive, CS =1
}
/**
* @brief Send command to Display
* @details Display mode must be set
* @param unsigned char msg - Message send to Display
* @return void
*/
void SPI::LCD_CommOut(unsigned char msg) //Command Output Serial Interface
{
ConfigSPI(ModeLCD);
CLRB(P3OUT,4); //Chip Select = Active, CS = 0
CLRB(P2OUT,7); //A0 = Command, A0 = 0
/* Software delay for selection line to settle */
__delay_cycles(25);
while (UCBUSY & UCB0STAT); // Wait until SPI is no longer busy
UCB0TXBUF = msg; // Transmit Message
while (UCBUSY & UCB0STAT); // Wait until SPI is no longer busy
SETB(P3OUT,4); //after 1 byte, Chip Select = inactive, CS = 1
}
/**
* It configures SPI in a mode to communicate to the selected device
* @param Mode This defines the mode to configure.
*/
void SPI::ConfigSPI(SPI_Modes Mode)
{
if(SPI_Mode == Mode)
return;
switch(Mode)
{
case ModeLCD:
/*******************************************************
* USCI - SPI configuration for LCD *
*******************************************************/
UCB0CTL1 = UCSWRST; // **Reset USCI state machine**
// UCMST = Master Mode Selected
// UCCKPH = Data is captured on the first UCLK edge and changed on the following edge.
// ~UCCKPL = The inactive state is low.
// UCMSB = MSB first
// UCSYNC = Synchronous mode
// 8 bit data, 3 pin SPI
UCB0CTL0 = UCMST+UCCKPH+UCMSB+UCSYNC;
UCB0CTL1 |= UCSSEL_2; // SMCLK clock source
UCB0BR0 |= 0x03; // SPI Clk = SMCLK / 3 = 1 MHz
UCB0BR1 = 0;
UCB0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
break;
case ModeMem:
/*******************************************************
* USCI - SPI configuration for Memory *
*******************************************************/
UCB0CTL1 = UCSWRST; // **Reset USCI state machine**
// UCMST = Master Mode Selected
// UCCKPH = Data is captured on the first UCLK edge and changed on the following edge.
// ~UCCKPL = The inactive state is low.
// UCMSB = MSB first
// UCSYNC = Synchronous mode
// 8 bit data, 3 pin SPI
UCB0CTL0 = UCMST+UCCKPH+UCMSB+UCSYNC;
UCB0CTL1 |= UCSSEL_2; // SMCLK clock source
UCB0BR0 |= 0x01; // SPI Clk = SMCLK / 1 = 3 MHz
UCB0BR1 = 0;
UCB0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
break;
case ModeIdle:
default:
Mode = ModeIdle;
break;
}
SPI_Mode = Mode;
}
/**
* It performs data exchange via SPI for a given number of inputs and outputs
* @param TX pointer to transmit buffer or 0. if 0 then a dummy byte is sent (0x81)
* @param RX pointer to receive buffer or 0
* @param IOcount total number of receive and transmit bytes
*/
void SPI::DoSPI_IO(char* TX, char* RX, int IOcount)
{
volatile int dummy = 0x81;
if((TX == 0) && (RX == 0)) return;
while(IOcount > 0)
{
if(UCB0IFG & UCTXIFG)
{
if(TX == 0)
UCB0TXBUF = dummy; // dummy write
else
{
UCB0TXBUF = *TX++;
IOcount--;
}
}
if(UCB0IFG & UCRXIFG)
{
if(RX == 0)
dummy = UCB0RXBUF; // dummy read
else
{
*RX++ = UCB0RXBUF;
IOcount--;
}
}
}
while (UCBUSY & UCB0STAT); // Wait until SPI is no longer busy
dummy = UCB0RXBUF; // dummy read to empty any remaining data in RX buffer
}
MSP430 SPI-Master IO without interrupt
/**
* @file SPI.h
* Control's for the SPI
*/
#ifndef FILE_SPI_H
#define FILE_SPI_H
class SPI
{
public:
/**
* @brief Init for SPI
* @details
* @param void
* @return void
*/
static void _Init(void);
/**
* @brief Send data to Display
* @details
* @param unsigned char msg - Message send to Display
* @return void
*/
static void LCD_DataOut(unsigned char msg);
/**
* @brief Send data to Display
* @details Display mode must be set
* @param char* msg - Message send to Display
* @param int Length - Length of message send to Display
* @return void
*/
static void LCD_DataOut(char *msg, int Length);
/**
* @brief Send command to Display
* @details
* @param unsigned char msg - Message send to Display
* @return void
*/
static void LCD_CommOut(unsigned char msg);
private:
typedef enum {ModeIdle, ModeLCD, ModeMem} SPI_Modes;
static SPI_Modes SPI_Mode;
/**
* It configures SPI in a mode to communicate to the selected device
* @param Mode This defines the mode to configure.
*/
static void ConfigSPI(SPI_Modes Mode);
/**
* It performs data exchange via SPI for a given number of inputs and outputs
* @param TX pointer to transmit buffer or 0. if 0 then a dummy byte is sent (0x81)
* @param RX pointer to receive buffer or 0
* @param IOcount total number of receive and transmit bytes
*/
static void DoSPI_IO(char* TX, char* RX, int IOcount);
};
#############################################
/**
* @file SPI.c
* Control's for the SPI
*/
#include "SPI.h"
#include "msp430.h"
#define ArrayLength(array) (sizeof(array)/sizeof(array[0]))
/// Macro to set a bit y in variable x
#define SETB(x,y) (x |= (1 << y))
/// Macro to reset a bit y in variable x
#define CLRB(x,y) (x &= ~(1 << y))
SPI::SPI_Modes SPI::SPI_Mode;
/**
* @brief Init for SPI
* @details
* @param void
* @return void
*/
void SPI::_Init(void)
{
SPI_Mode = ModeIdle;
}
/**
* @brief Send data to Display
* @details Display mode must be set
* @param unsigned char msg - Message send to Display
* @return void
*/
void SPI::LCD_DataOut(unsigned char msg) //Data Output Serial Interface
{
ConfigSPI(ModeLCD);
CLRB(P3OUT,4); //Chip Select = Active, CS = 0
SETB(P2OUT,7); //A0 = Data, A0 = 1
/* Software delay for selection line to settle */
__delay_cycles(25);
while (UCBUSY & UCB0STAT); // Wait until SPI is no longer busy
UCB0TXBUF = msg; // Transmit Message
while (UCBUSY & UCB0STAT); // Wait until SPI is no longer busy
SETB(P3OUT,4); //after 1 byte, Chip Select = inactive, CS =1
}
/**
* @brief Send data to Display
* @details Display mode must be set
* @param char* msg - Message send to Display
* @param int Length - Length of message send to Display
* @return void
*/
void SPI::LCD_DataOut(char *msg, int Length) //Data Output Serial Interface
{
ConfigSPI(ModeLCD);
CLRB(P3OUT,4); //Chip Select = Active, CS = 0
SETB(P2OUT,7); //A0 = Data, A0 = 1
/* Software delay for selection line to settle */
__delay_cycles(25);
DoSPI_IO(msg, 0, Length);
SETB(P3OUT,4); //after 1 byte, Chip Select = inactive, CS =1
}
/**
* @brief Send command to Display
* @details Display mode must be set
* @param unsigned char msg - Message send to Display
* @return void
*/
void SPI::LCD_CommOut(unsigned char msg) //Command Output Serial Interface
{
ConfigSPI(ModeLCD);
CLRB(P3OUT,4); //Chip Select = Active, CS = 0
CLRB(P2OUT,7); //A0 = Command, A0 = 0
/* Software delay for selection line to settle */
__delay_cycles(25);
while (UCBUSY & UCB0STAT); // Wait until SPI is no longer busy
UCB0TXBUF = msg; // Transmit Message
while (UCBUSY & UCB0STAT); // Wait until SPI is no longer busy
SETB(P3OUT,4); //after 1 byte, Chip Select = inactive, CS = 1
}
/**
* It configures SPI in a mode to communicate to the selected device
* @param Mode This defines the mode to configure.
*/
void SPI::ConfigSPI(SPI_Modes Mode)
{
if(SPI_Mode == Mode)
return;
switch(Mode)
{
case ModeLCD:
/*******************************************************
* USCI - SPI configuration for LCD *
*******************************************************/
UCB0CTL1 = UCSWRST; // **Reset USCI state machine**
// UCMST = Master Mode Selected
// UCCKPH = Data is captured on the first UCLK edge and changed on the following edge.
// ~UCCKPL = The inactive state is low.
// UCMSB = MSB first
// UCSYNC = Synchronous mode
// 8 bit data, 3 pin SPI
UCB0CTL0 = UCMST+UCCKPH+UCMSB+UCSYNC;
UCB0CTL1 |= UCSSEL_2; // SMCLK clock source
UCB0BR0 |= 0x03; // SPI Clk = SMCLK / 3 = 1 MHz
UCB0BR1 = 0;
UCB0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
break;
case ModeMem:
/*******************************************************
* USCI - SPI configuration for Memory *
*******************************************************/
UCB0CTL1 = UCSWRST; // **Reset USCI state machine**
// UCMST = Master Mode Selected
// UCCKPH = Data is captured on the first UCLK edge and changed on the following edge.
// ~UCCKPL = The inactive state is low.
// UCMSB = MSB first
// UCSYNC = Synchronous mode
// 8 bit data, 3 pin SPI
UCB0CTL0 = UCMST+UCCKPH+UCMSB+UCSYNC;
UCB0CTL1 |= UCSSEL_2; // SMCLK clock source
UCB0BR0 |= 0x01; // SPI Clk = SMCLK / 1 = 3 MHz
UCB0BR1 = 0;
UCB0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
break;
case ModeIdle:
default:
Mode = ModeIdle;
break;
}
SPI_Mode = Mode;
}
/**
* It performs data exchange via SPI for a given number of inputs and outputs
* @param TX pointer to transmit buffer or 0. if 0 then a dummy byte is sent (0x81)
* @param RX pointer to receive buffer or 0
* @param IOcount total number of receive and transmit bytes
*/
void SPI::DoSPI_IO(char* TX, char* RX, int IOcount)
{
volatile int dummy = 0x81;
if((TX == 0) && (RX == 0)) return;
while(IOcount > 0)
{
if(UCB0IFG & UCTXIFG)
{
if(TX == 0)
UCB0TXBUF = dummy; // dummy write
else
{
UCB0TXBUF = *TX++;
IOcount--;
}
}
if(UCB0IFG & UCRXIFG)
{
if(RX == 0)
dummy = UCB0RXBUF; // dummy read
else
{
*RX++ = UCB0RXBUF;
IOcount--;
}
}
}
while (UCBUSY & UCB0STAT); // Wait until SPI is no longer busy
dummy = UCB0RXBUF; // dummy read to empty any remaining data in RX buffer
}