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

📄 spi.cpp

📁 SBC2410 WinCE 5.0 BSP.绝大多数驱动已经调通。
💻 CPP
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

   
Module Name:	SPI.CPP

Abstract:		SPI Interface Routines for Samsung SC2410 CPU
  
Notes:			Presently, only the SPI Channel 0 is supported.

Environment:	Samsung SC2410 CPU and Windows 3.0 (or later)
    
-*/

#include <windows.h>
#include "spi.h"


//------------------------------ GLOBALS -------------------------------------------
extern volatile SSPreg		*g_pSPIregs;			// SPI control registers
extern volatile IOPreg		*g_pIOPregs;			// GPIO registers (needed to enable SPI)
extern volatile CLKPWRreg	*g_pCLKPWRreg;			// CLCKPWR (needed to enable SPI clocks)

volatile DWORD g_dwWaitCounter = 0;
//----------------------------------------------------------------------------------


// Used to wait the specified # of clock cycles
#define WAIT(x)		{ for(g_dwWaitCounter=0; g_dwWaitCounter<x; g_dwWaitCounter++); }				

#ifdef DEBUG
#define ZONE_ERROR  1
#endif


/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:		SPI_Init()

Description:	Initializes the Serial Peripheral Interface (SPI)

Notes:			This routine assumes that the control registers (see 
				the globals section above) have already been initialized.

Returns:		Boolean indicating success.
-------------------------------------------------------------------*/
BOOL SPI_Init()
{
	//----- 1. IMPORTANT: By default, the internal clock is disabled.  To configure the controller ------
	//					  we must first enable it.
    StartSPIClock();

	//----- 2. Configure the GPIO pins for SPI mode -----
	//
	//		   nSPICS0  (chip select)		= GPG2
	//		   SPICLK0  (SPI clock)			= GPE13
	//		   SPIMOSIO (SPI output data)	= GPE12
	//   
	g_pIOPregs->rGPGCON &= CLEAR_GPG2_MASK;
	g_pIOPregs->rGPGCON |= ENABLE_GPG2_OUTPUT;
	g_pIOPregs->rGPGUP  &= ENABLE_GPG2_PULLUP;

	g_pIOPregs->rGPECON |= (ENABLE_SPICLK0 | ENABLE_SPIMSIO);
	g_pIOPregs->rGPEUP  |= DISABLE_SPICLK_SPIMSIO_PULLUP;	// Disable pullup-resistor for SPICLK0 and SPIMOSIO 


	//----- 3. Configure the SPI controller with reasonable default values -----
	g_pSPIregs->rSPCON0 = (SPI_MODE_POLLING | SPI_SELECT_MASTER | SPI_CLOCK_ENABLE);

	SetSPIClockRate(CLK_RATE_SLOW);
    StopSPIClock();

	return TRUE;
}


/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:		SPI_Deinit()

Description:	Deinitializes the Serial Peripheral Interface (SPI)

Notes:			This routine DOES NOT unmap the control registers;
				the caller is responsible for freeing this memory.

Returns:		Boolean indicating success.
-------------------------------------------------------------------*/
BOOL SPI_Deinit()
{
	//----- 1. Stop the SPI clocks -----
    StopSPIClock();

	return TRUE;
}


/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:		SPI_SendByte()

Description:	Sends the specified byte out onto the SPI bus.

Returns:		Boolean indicating success.
-------------------------------------------------------------------*/
BOOL SPI_SendByte(BYTE bData)
{
    BOOL    bRet = TRUE;
	static  DWORD waitCount = 0;
    
    //----- 0. Start clock
    StartSPIClock();

	//----- 1. Chip select the slave device (active low) -----
	g_pIOPregs->rGPGDAT &= CHIP_SELECT_nSS0;

	//----- 2. Wait until the controller is ready to transfer -----
	waitCount = 100;
	while(!(g_pSPIregs->rSPSTA0 & SPI_TRANSFER_READY))
	{
		if(--waitCount == 0)
		{
			RETAILMSG(1, (TEXT("WAVEDEV.DLL: SPI_SendByte() - timeout occurred while waiting to transfer byte\r\n")));
            bRet = FALSE;
			goto SEND_ERROR;
		}
	}

	//----- 3. Put the byte out onto the SPI bus -----
	g_pSPIregs->rSPTDAT0 = bData;
	
	//----- 4. Delay a little bit so the byte finishes clocking out before the chip select line is deasserted -----
	WAIT(10000);

	//----- 5. Deselect the slave device (active low) -----
	g_pIOPregs->rGPGDAT |= CHIP_DESELECT_nSS0;

SEND_ERROR:
    
    StopSPIClock();

	return bRet;
}



/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:		SPI_SendWord()

Description:	Sends the specified word out onto the SPI bus.

Returns:		Boolean indicating success.
-------------------------------------------------------------------*/
BOOL SPI_SendWord(WORD wData)
{
    BOOL    bRet = TRUE;
	DWORD   waitCount = 0;

    StartSPIClock();

	//----- 1. Chip select the slave device (active low) -----
	g_pIOPregs->rGPGDAT &= CHIP_SELECT_nSS0;

	//----- 2. Wait until the controller is ready to transfer -----
	waitCount = 1000;
	while(!(g_pSPIregs->rSPSTA0 & SPI_TRANSFER_READY))
	{
		if(--waitCount == 0)
		{
			//RETAILMSG(1, (TEXT("WAVEDEV.DLL: SPI_SendWord() - timeout occurred while waiting to transfer byte\r\n")));
            bRet = FALSE;
			goto SEND_ERROR;
		}
	}

	//----- 3. Send first half of word -----
	g_pSPIregs->rSPTDAT0 = (wData & 0xFF00) >> 8;

	//----- 4. Wait until the controller is ready to transfer -----
	waitCount = 1000;
	while(!(g_pSPIregs->rSPSTA0 & SPI_TRANSFER_READY))
	{
		if(--waitCount == 0)
		{
			//RETAILMSG(1, (TEXT("WAVEDEV.DLL: SPI_SendWord() - timeout occurred while waiting to transfer byte\r\n")));
            bRet = FALSE;
			goto SEND_ERROR;
		}
	}

	//----- 5. Send second half of word -----
	g_pSPIregs->rSPTDAT0 = (wData & 0x00FF);

	//----- 6. Delay a little bit so the byte finishes clocking out before the chip select line is deasserted -----
	WAIT(10000);

	//----- 7. Deselect the slave device (active low) -----
	g_pIOPregs->rGPGDAT |= CHIP_DESELECT_nSS0;

SEND_ERROR:

    StopSPIClock();

	return bRet;
}


//------------------------------------ Helper Routines ------------------------------------

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:		StartSPIClock()

Description:	Enables the SPI clock.

Returns:		N/A
-------------------------------------------------------------------*/
VOID StartSPIClock(VOID)
{
	g_pCLKPWRreg->rCLKCON |= SPI_INTERNAL_CLOCK_ENABLE;		// Enable the CPU clock to the SPI controller

	g_pSPIregs->rSPCON0 |= SPI_CLOCK_ENABLE;					// Enable the SPI clock
	
	return;
}


/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:		StopSPIClock()

Description:	Disables the SPI clock.

Returns:		N/A
-------------------------------------------------------------------*/
VOID StopSPIClock(VOID)
{
	g_pCLKPWRreg->rCLKCON &= ~SPI_INTERNAL_CLOCK_ENABLE;	// Disable the CPU clock to the SPI controller

	g_pSPIregs->rSPCON0 &= ~SPI_CLOCK_ENABLE;				// Disable the SPI clock
	
	return;
}


/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:		SetSPIClockRate()

Description:	Sets the SPI clock (a.k.a. baud) rate:

Params:			ClockRate       0x00 =      25Mhz
								0x01 = 1/2  25Mhz
								0x02 = 1/4  25Mhz
								0x03 = 1/8  25Mhz
								0x04 = 1/16 25Mhz
								0x05 = 1/32 25Mhz
								0x06 = 1/64 25Mhz
								0x07 = 99.121Khz

Returns:		N/A
-------------------------------------------------------------------*/
VOID SetSPIClockRate(DWORD ClockRate)
{
	UINT16 prescale;

    //----- 1. Set the clock rate  -----
	//		   NOTE: Using the prescale value, the clock's baud rate is
	//				 determined as follows: baud_rate = (PCLK / 2 / (prescale + 1))
	//
	//				 Hence, the prescale value can be computed as follows:
	//				 prescale = ((PCLK / 2) / baud_rate) - 1
	switch(ClockRate)
	{
		case CLK_RATE_FULL:						// 25 Mhz			
		prescale = (S2410PCLK / 40000000) - 1;
		break;

		case CLK_RATE_HALF:						// 1/2  25 Mhz						
		prescale = (S2410PCLK / 30000000) - 1;
		break;

		case CLK_RATE_FOUR:						// 1/4  25 Mhz						
		prescale = (S2410PCLK / 10000000) - 1;
		break;

		case CLK_RATE_EIGHT:					// 1/8  25 Mhz						
		prescale = (S2410PCLK /  500000) - 1;
		break;

		case CLK_RATE_SIXTEEN:					// 1/16 25 Mhz						
		prescale = (S2410PCLK /  2500000) - 1;
		break;

		case CLK_RATE_THIRTY2:					// 1/32 25 Mhz						
		prescale = (S2410PCLK /  1250000) - 1;
		break;

		case CLK_RATE_SIXTY4:					// 1/64 25 Mhz						
		prescale = (S2410PCLK /   625000) - 1;
		break;

		case CLK_RATE_SLOW:						// 99.121 kHz (i.e. ~1/256 25Mhz)
		prescale = 255;
		break;

		default:
		DEBUGMSG(ZONE_ERROR, (TEXT("WAVEDEV.DLL:setSPIClockRate() - Invalid clock rate specified!\r\n")));  
		return;
		break;
	}

	g_pSPIregs->rSPPRE0 = prescale;


    return;
}




⌨️ 快捷键说明

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