?? f12x_spi0_slave.c
字號:
//-----------------------------------------------------------------------------
// F12x_SPI0_Slave.c
//-----------------------------------------------------------------------------
// Copyright 2006 Silicon Laboratories, Inc.
// http://www.silabs.com
//
// Program Description:
//
// This program configures a C8051F12x as a SPI Slave. The 'F12x MCU
// is configured in 4-wire Slave Mode.
//
// This example is intended to be used with the SPI0_Master example.
//
// Pinout:
//
// P0.0 - SPI SCK (digital input, open-drain)
// P0.1 - SPI MISO (digital output, push-pull)
// P0.2 - SPI MOSI (digital input, open-drain)
// P0.3 - SPI NSS (digital input, open-drain)
//
// P1.6 - LED (digital output, push-pull)
//
// all other port pins unused.
//
//
// How To Test:
//
// 1) Download the code to a F120-TB that is connected as above to
// another device running the SPI0_Master code.
// 2) Verify that the J3 jumper is populated.
// 3) Run the code.
// 4) If the communication passes, the LEDs on both the Master and Slave
// boards will blink slowly. If it fails, the LEDs will be OFF.
//
//
// Target: C8051F12x
// Tool chain: Keil C51 7.50 / Keil EVAL C51
// Command Line: None
//
// Release 1.0
// -Initial Revision (TP)
// -14 DEC 2006
//
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include <C8051F120.h> // SFR declarations
//-----------------------------------------------------------------------------
// Global Constants
//-----------------------------------------------------------------------------
#define SYSCLK 24500000 // Internal oscillator frequency in Hz
#define MAX_BUFFER_SIZE 8 // Maximum buffer Master will send
// Instruction Set
#define SLAVE_LED_ON 0x01 // Turn the Slave LED on
#define SLAVE_LED_OFF 0x02 // Turn the Slave LED off
#define SPI_WRITE 0x04 // Send a byte from the Master to the
// Slave
#define SPI_READ 0x08 // Send a byte from the Slave to the
// Master
#define SPI_WRITE_BUFFER 0x10 // Send a series of bytes from the
// Master to the Slave
#define SPI_READ_BUFFER 0x20 // Send a series of bytes from the Slave
// to the Master
#define ERROR_OCCURRED 0x40 // Indicator for the Slave to tell the
// Master an error occurred
sbit LED = P1^6; // LED='1' means ON
//-----------------------------------------------------------------------------
// Global Variables
//-----------------------------------------------------------------------------
unsigned char SPI_Data = 0xA5;
unsigned char SPI_Data_Array[MAX_BUFFER_SIZE] = {0};
//-----------------------------------------------------------------------------
// Function Prototypes
//-----------------------------------------------------------------------------
void Watchdog_Init (void);
void Oscillator_Init (void);
void Port_Init (void);
void SPI0_Init (void);
void Init_Device (void);
//-----------------------------------------------------------------------------
// main() Routine
//-----------------------------------------------------------------------------
void main (void)
{
Init_Device (); // Initializes hardware peripherals
EA = 1; // Enable global interrupts
LED = 0;
while (1); // Loop forever
}
//-----------------------------------------------------------------------------
// Initialization Subroutines
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Watchdog_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// This function disables the watchdog timer.
//
//-----------------------------------------------------------------------------
void Watchdog_Init (void)
{
unsigned char SFRPAGE_save = SFRPAGE; // Save the current SFRPAGE
SFRPAGE = CONFIG_PAGE; // Switch to the necessary SFRPAGE
WDTCN = 0xDE; // Disable the Watchdog Timer
WDTCN = 0xAD;
SFRPAGE = SFRPAGE_save; // Restore the SFRPAGE
}
//-----------------------------------------------------------------------------
// Oscillator_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// This function initializes the system clock to use the internal oscillator
// at 24.5 MHz.
//
//-----------------------------------------------------------------------------
void Oscillator_Init (void)
{
unsigned char SFRPAGE_save = SFRPAGE; // Save the current SFRPAGE
SFRPAGE = CONFIG_PAGE; // Switch to the necessary SFRPAGE
OSCICN = 0x83; // Set the internal oscillator to
// 24.5 MHz
SFRPAGE = SFRPAGE_save; // Restore the SFRPAGE
}
//-----------------------------------------------------------------------------
// Port_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// This function configures the crossbar and GPIO ports.
//
// P0.0 - SCK (SPI0), Open-Drain, Digital
// P0.1 - MISO (SPI0), Push-Pull, Digital
// P0.2 - MOSI (SPI0), Open-Drain, Digital
// P0.3 - NSS (SPI0), Open-Drain, Digital
//
// P1.6 - LED, Push-Pull, Digital (LED D3 on Target Board)
//
//-----------------------------------------------------------------------------
void PORT_Init (void)
{
unsigned char SFRPAGE_save = SFRPAGE; // Save the current SFRPAGE
SFRPAGE = CONFIG_PAGE; // Switch to the necessary SFRPAGE
P0MDOUT = 0x02; // Make MISO push-pull
P1MDOUT = 0x40; // Make the LED push-pull
XBR0 = 0x02; // Enable the SPI on the XBAR
XBR2 = 0x40; // Enable the XBAR and weak pull-ups
SFRPAGE = SFRPAGE_save; // Restore the SFRPAGE
}
//-----------------------------------------------------------------------------
// SPI0_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Configures SPI0 to use 4-wire Slave mode. The SPI timing is
// configured for Mode 0,0 (data centered on first edge of clock phase and
// SCK line low in idle state).
//
//-----------------------------------------------------------------------------
void SPI0_Init()
{
unsigned char SFRPAGE_save = SFRPAGE; // Save the current SFRPAGE
SFRPAGE = SPI0_PAGE; // Switch to the necessary SFRPAGE
SPI0CFG = 0x00; // Operate in Slave mode
// CKPHA = '0', CKPOL = '0'
SPI0CN = 0x05; // 4-wire Slave mode, SPI enabled
EIE1 |= 0x01; // Enable SPI interrupts
SFRPAGE = SFRPAGE_save; // Restore the SFRPAGE
}
//-----------------------------------------------------------------------------
// Init_Device
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Calls all device initialization functions.
//
//-----------------------------------------------------------------------------
void Init_Device (void)
{
Watchdog_Init (); // Disable the Watchdog Timer first
Oscillator_Init ();
Port_Init ();
SPI0_Init ();
}
//-----------------------------------------------------------------------------
// Interrupt Service Routines
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// SPI_ISR
//-----------------------------------------------------------------------------
//
// Handles all incoming data and interprets the commands sent from the Master.
//
// Typical Write:
//
// | 1st sent | 2nd sent | 3rd sent | ... | last sent |
// ---------------------------------------------------------
// Master NSSv | Command | Data1 | Data2 | ... | DataN | NSS^
// Slave | N/A | N/A | N/A | ... | N/A |
//
// Typical Read:
//
// | 1st sent | 2nd sent | 3rd sent | ... | last sent |
// ---------------------------------------------------------
// Master NSSv | Command | dummy | dummy | ... | dummy | NSS^
// Slave | N/A | Data1 | Data2 | ... | DataN |
//-----------------------------------------------------------------------------
void SPI_ISR (void) interrupt 6
{
static unsigned char command;
static unsigned char array_index = 0;
static unsigned char state = 0;
unsigned char dummy_byte;
if (WCOL == 1)
{
// Write collision occurred
SPI0DAT = ERROR_OCCURRED; // Indicate an error occurred
WCOL = 0; // Clear the Write collision flag
}
else if (RXOVRN == 1)
{
// Receive overrun occurred
SPI0DAT = ERROR_OCCURRED; // Indicate an error occurred
RXOVRN = 0; // Clear the Receive Overrun flag
}
else
{
// SPIF caused the interrupt
// Some commands are single-byte commands (SLAVE_LED_ON/SLAVE_LED_OFF)
// For multiple-byte commands, use the state to determine action
// <state> == 0: new transfer; a command is being received
// <state> == 1: writing/reading data
if (state == 0)
{
command = SPI0DAT; // Read the command
array_index = 0; // Reset the array index
switch (command)
{
case SLAVE_LED_ON:
LED = 1;
state = 0; // End of transfer (no bytes to send)
break;
case SLAVE_LED_OFF:
LED = 0;
state = 0; // End of transfer (no bytes to send)
break;
case SPI_WRITE:
state = 1; // Do nothing
// Move to State 1 to read data from
// Master
break;
case SPI_READ:
SPI0DAT = SPI_Data; // Immediately load SPI0DAT with the
// data requested by the Master, so the
// Master can receive it at the end of
// the second transfer.
// Because the slave sends the data
// immediately, the Master's SCK is
// limited to a clock slow enough that
// the Slave has time to respond to a
// read.
state = 0; // End of transfer (only one byte)
break;
case SPI_WRITE_BUFFER:
state = 1; // Do nothing
// Move to State 1 to read data from
// Master
break;
case SPI_READ_BUFFER:
SPI0DAT = SPI_Data_Array[array_index]; // Immediately load
// SPI0DAT with the data requested by
// the Master, so the Master can receive
// it at the end of the second transfer.
// Because the slave sends the data
// immediately, the Master's SCK is
// limited to a clock slow enough that
// the Slave has time to respond to a
// read.
array_index++;
state = 1; // Move to State 1 to continue to send
// data to the Master (multiple bytes).
break;
default:
state = 0;
}
}
else if (state == 1)
{
switch (command)
{
case SPI_WRITE:
SPI_Data = SPI0DAT;
state = 0; // End of transfer (one byte received)
break;
case SPI_WRITE_BUFFER:
SPI_Data_Array[array_index] = SPI0DAT; // Receive the next byte
array_index++;
if (array_index == MAX_BUFFER_SIZE) // Check for last data
{
state = 0; // Reset the state (end of transfer)
}
else
{
state = 1; // Continue to read in data (more
// bytes to receive)
}
break;
case SPI_READ_BUFFER:
SPI0DAT = SPI_Data_Array[array_index]; // Send the next byte
dummy_byte = SPI0DAT; // Read the dummy data the Master is
// sending from SPI0DAT to prevent a
// RXOVRN (Receive overrun) error
array_index++;
if (array_index == MAX_BUFFER_SIZE) // Check for last data
{
state = 0; // Reset the state (end of transfer)
}
else
{
state = 1; // Continue to send out data (more
// bytes to send)
}
break;
default:
state = 0;
}
}
SPIF = 0; // Clear the SPIF flag
}
}
//-----------------------------------------------------------------------------
// End Of File
//-----------------------------------------------------------------------------
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -