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

📄 ssp.c

📁 基于MDK的LPC1100处理器开发应用例程
💻 C
字号:
/******************** (C) COPYRIGHT 2010 Embest Info&Tech Co.,LTD. ************
* 文件名: ssp.c
* 作者  : Wuhan R&D Center, Embest
* 日期  : 01/18/2010
* 描述  : NXP LPC11xx 系列处理器 SSP API 文件.
*******************************************************************************
*******************************************************************************
* 历史:
* 01/18/2010		 : V1.0		   初始版本
*******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "LPC11xx.h"			/* LPC11xx 外设寄存器 */
#include "gpio.h"
#include "ssp.h"

/* 所有寄存器的数据 */
volatile uint32_t interruptRxStat0 = 0;
volatile uint32_t interruptOverRunStat0 = 0;
volatile uint32_t interruptRxTimeoutStat0 = 0;

volatile uint32_t interruptRxStat1 = 0;
volatile uint32_t interruptOverRunStat1 = 0;
volatile uint32_t interruptRxTimeoutStat1 = 0;

/**
  * 函数名:	SSP0_IRQHandler
  * 描述  :	SSP 端口用做 SPI 通信.
  *			SSP 中断处理程序
  *			算法是,如果 RXFIFO 至少半满,开始接收直到为空。 
  *			如果 TXFIFO 至少半空,开始发送知道为满。
  *			这样可以最大限度的使用 FIFOs 。
  *
  * 参数:	无
  * 返回值:	无
  */
void SSP0_IRQHandler(void) 
{
  uint32_t regValue;

  regValue = LPC_SSP0->MIS;
  /* 接收溢出中断 */
  if ( regValue & SSPMIS_RORMIS )	
  {
	interruptOverRunStat0++;
	/* 清除中断 */
	LPC_SSP0->ICR = SSPICR_RORIC;	
  }
  /* 接收超时中断 */
  if ( regValue & SSPMIS_RTMIS )	
  {
	interruptRxTimeoutStat0++;
	/* 清除中断 */
	LPC_SSP0->ICR = SSPICR_RTIC;	
  }

  /* 请注意,在 main 和 ISR, CurrentRxIndex 和 CurrentTxIndex
  作为全局变量共享。 这可能造成一些竞争条件使 main 和 ISR 同时
  操纵这些变量。 SSPSR_BSY 检查 (polling) main 和 ISR 能够防止
  这样的竞争情况出现 */
  /* Rx 至少半满 */
  if ( regValue & SSPMIS_RXMIS )	
  {
    /* 接收直到为空 */		
	interruptRxStat0++;	
  }
  return;
}


/**
  * 函数名:	SSP1_IRQHandler
  * 描述  :	SSP 端口用做 SPI 通信.
  *			SSP 中断处理程序
  *			算法是,如果 RXFIFO 至少半满,开始接收直到为空。 
  *			如果 TXFIFO 至少半空,开始发送知道为满。
  *			这样可以最大限度的使用 FIFOs 。
  *
  * 参数:	无
  * 返回值:	无
  */  
void SSP1_IRQHandler(void) 
{
  uint32_t regValue;

  regValue = LPC_SSP1->MIS;
  /* 接收溢出中断 */
  if ( regValue & SSPMIS_RORMIS )	
  {
	interruptOverRunStat1++;
	/* 清除中断 */
	LPC_SSP1->ICR = SSPICR_RORIC;	
  }
  /* 接收超时中断 */
  if ( regValue & SSPMIS_RTMIS )	
  {
	interruptRxTimeoutStat1++;
	LPC_SSP1->ICR = SSPICR_RTIC;	/* clear interrupt */
  }

  /* 请注意,在 main 和 ISR, CurrentRxIndex 和 CurrentTxIndex
  作为全局变量共享。 这可能造成一些竞争条件使 main 和 ISR 同时
  操纵这些变量。 SSPSR_BSY 检查 (polling) main 和 ISR 能够防止
  这样的竞争情况出现 */
  /* Rx 至少半满 */
  if ( regValue & SSPMIS_RXMIS )	
  {
  /* 接收直到为空 */		
	interruptRxStat1++;		
  }
  return;
}

/**
  * 函数名:	SSP_IOConfig
  * 描述:	SSP 初始化 			
  * 参数:	无
  * 返回值:	无
  */
void SSP_IOConfig( uint8_t portNum )
{
  if ( portNum == 0 )
  {
	LPC_SYSCON->PRESETCTRL |= (0x1<<0);
	LPC_SYSCON->SYSAHBCLKCTRL |= (1<<11);
	/* 除以 2 */
	LPC_SYSCON->SSP0CLKDIV = 0x02;	
	/*  SSP I/O 配置 */	
	LPC_IOCON->PIO0_8           &= ~0x07;	
	LPC_IOCON->PIO0_8           |= 0x01;		/* SSP MISO */
	LPC_IOCON->PIO0_9           &= ~0x07;	
	LPC_IOCON->PIO0_9           |= 0x01;		/* SSP MOSI */
#ifdef __JTAG_DISABLED
	LPC_IOCON->SCKLOC = 0x00;
	LPC_IOCON->JTAG_TCK_PIO0_10 &= ~0x07;
	LPC_IOCON->JTAG_TCK_PIO0_10 |= 0x02;		/* SSP CLK */
#else
#if 1
	/* 在 HummingBird 1(HB1), SSP CLK 可以被重定向到不同的引脚,
	而不像 JTAG TCK, 可以是 P2.11 func. 1 或 P0.6 func. 2. */
	LPC_IOCON->SCK_LOC = 0x01;
	LPC_IOCON->PIO2_11 = 0x01;	/* P2.11 功能 1 是 SSP 时钟, 需要 
								同时设置 IOCONSCKLOC 寄存器 */
#else
	LPC_IOCON->SCK_LOC = 0x02;
	LPC_IOCON->PIO0_6 = 0x02;	/* P0.6 功能 2 是 SSP 时钟, 需要 
								同时设置 IOCONSCKLOC 寄存器 */
#endif
#endif	/* endif __JTAG_DISABLED */  

#if USE_CS
	LPC_IOCON->PIO0_2 &= ~0x07;	
	LPC_IOCON->PIO0_2 |= 0x01;		/* SSP SSEL */
#else
	/* 使能 AHB 到 GPIO 时钟  */
	LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6);

    /* SSP SSEL 是 GPIO 引脚 */
	LPC_IOCON->PIO0_2 &= ~0x07;		
	/* port0, 第 2 位设置为 GPIO 输出并为高 */
	GPIOSetDir( PORT0, 2, 1 );
	GPIOSetValue( PORT0, 2, 1 );
#endif
  }
  else		/* port 号 1 */
  {
	LPC_SYSCON->PRESETCTRL |= (0x1<<2);
	LPC_SYSCON->SYSAHBCLKCTRL |= (1<<18);
	/* 除以 2 */
	LPC_SYSCON->SSP1CLKDIV = 0x02;			
	LPC_IOCON->PIO2_2 &= ~0x07;	/*  SSP I/O 配置 */
	LPC_IOCON->PIO2_2 |= 0x02;		/* SSP MISO */
	LPC_IOCON->PIO2_3 &= ~0x07;	
	LPC_IOCON->PIO2_3 |= 0x02;		/* SSP MOSI */
	LPC_IOCON->PIO2_1 &= ~0x07;
	LPC_IOCON->PIO2_1 |= 0x02;		/* SSP CLK */
 
#if USE_CS
	LPC_IOCON->PIO2_0 &= ~0x07;	
	LPC_IOCON->PIO2_0 |= 0x02;		/* SSP SSEL */
#else
	/* Enable AHB clock to the GPIO domain. */
	LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6);

	LPC_IOCON->PIO2_0 &= ~0x07;		/* SSP SSEL 为  GPIO 引脚 */
	/* port2, 第 0 位设置为 GPIO 输出并为高 */
	GPIOSetDir( PORT2, 0, 1 );
	GPIOSetValue( PORT2, 0, 1 );
#endif
  }
  return;		
}

/**
  * 函数名:	SSP_Init
  * 描述:	SSP 端口常规初始化			
  * 参数:	无
  * 返回值:	无
  */
void SSP_Init( uint8_t portNum )
{
  uint8_t i, Dummy=Dummy;

  if ( portNum == 0 )
  {
	/* 设置 DSS 数据位 8-位, 帧格式 SPI, CPOL = 0, CPHA = 0,  SCR 为 15 */
	LPC_SSP0->CR0 = 0x0707;

	/* SSPCPSR 时钟分频器,主模式,最小分频系数 0x02 */
	LPC_SSP0->CPSR = 0x2;

	for ( i = 0; i < FIFOSIZE; i++ )
	{
	  /* 清除 RxFIFO */
	  Dummy = LPC_SSP0->DR;		
	}

	/* 使能 SSP 中断 */
	NVIC_EnableIRQ(SSP0_IRQn);
	
	/* 选中为主器件, SSP 使能 */
#if LOOPBACK_MODE
	LPC_SSP0->CR1 = SSPCR1_LBM | SSPCR1_SSE;
#else
#if SSP_SLAVE
	/* 从模式 */
	if ( LPC_SSP0->CR1 & SSPCR1_SSE )
	{
	  /* 从模式位不能被设置直到 SSE 位为 0. */
	  LPC_SSP0->CR1 &= ~SSPCR1_SSE;
	}
	/* 先使能从模式位 */
	LPC_SSP0->CR1 = SSPCR1_MS;		
	/* 使能 SSP */
	LPC_SSP0->CR1 |= SSPCR1_SSE;	
#else
	/* 主模式 */
	LPC_SSP0->CR1 = SSPCR1_SSE;
#endif
#endif
	/* 设置 SSPINMS 寄存器使能中断 */
	/* 使能相关中断的所有错误 */
	LPC_SSP0->IMSC = SSPIMSC_RORIM | SSPIMSC_RTIM;
  }
  else
  {
	/* 设置 DSS 数据位 8-位, 帧格式 SPI, CPOL = 0, CPHA = 0,  SCR 为 15 */
	LPC_SSP1->CR0 = 0x0707;

	/* SSPCPSR 时钟预分频器寄存器,主模式, 最小分频系数 0x02 */
	LPC_SSP1->CPSR = 0x2;

	for ( i = 0; i < FIFOSIZE; i++ )
	{
	/* 清除  RxFIFO */
	  Dummy = LPC_SSP1->DR;		
	}

	/* 使能 SSP 中断 */
	NVIC_EnableIRQ(SSP1_IRQn);
	
	/* 选定为主器件, SSP 使能 */
#if LOOPBACK_MODE
	LPC_SSP1->CR1 = SSPCR1_LBM | SSPCR1_SSE;
#else
#if SSP_SLAVE
	/* Slave mode */
	if ( LPC_SSP1->CR1 & SSPCR1_SSE )
	{
	  /* 从模式位不能被设置直到 SSE 位为 0. */
	  LPC_SSP1->CR1 &= ~SSPCR1_SSE;
	}
	/* 先使能从模式位 */
	LPC_SSP1->CR1 = SSPCR1_MS;		
	/* 使能 SSP */
	LPC_SSP1->CR1 |= SSPCR1_SSE;	
#else
	/* 主模式 */
	LPC_SSP1->CR1 = SSPCR1_SSE;
#endif
#endif
	/* 设置 SSPINMS 寄存器使能中断 */
	/* 使能所有中断相关的错误 */
	LPC_SSP1->IMSC = SSPIMSC_RORIM | SSPIMSC_RTIM;
  }
  return;
}

/**
  * 函数名:	SSP_Send
  * 描述:	发送一块数据到 SSP 端口。
  * 参数:	端口号 #,缓冲区指针, 块长度
  * 返回值:	无
  */
void SSP_Send( uint8_t portNum, uint8_t *buf, uint32_t Length )
{
  uint32_t i;
  uint8_t Dummy = Dummy;
    
  for ( i = 0; i < Length; i++ )
  {
	if ( portNum == 0 )
	{
	  /* 继续执行仅当总线不忙, TX FIFO 非满 */
	  while ( (LPC_SSP0->SR & (SSPSR_TNF|SSPSR_BSY)) != SSPSR_TNF );
	  LPC_SSP0->DR = *buf;
	  buf++;
#if !LOOPBACK_MODE
	  while ( (LPC_SSP0->SR & (SSPSR_BSY|SSPSR_RNE)) != SSPSR_RNE );
	  /* 每当写入一个字节, MISO FIFO 计数器加一, 清除 FIFO 
	    MISO. 否则, 当 SSP0Receive() 调用时, 先前的数据字节仍会留在
	  FIFO. */
	  Dummy = LPC_SSP0->DR;
#else
	  /* 等待直到忙位被清除。 */
	  while ( LPC_SSP0->SR & SSPSR_BSY );
#endif
	}
	else
	{
	  /* 继续执行仅当总线不忙, TX FIFO 非满 */
	  while ( (LPC_SSP1->SR & (SSPSR_TNF|SSPSR_BSY)) != SSPSR_TNF );
	  LPC_SSP1->DR = *buf;
	  buf++;
#if !LOOPBACK_MODE
	  while ( (LPC_SSP1->SR & (SSPSR_BSY|SSPSR_RNE)) != SSPSR_RNE );
	  /* 每当写入一个字节, MISO FIFO 计数器加一, 清除 FIFO 
	    MISO. 否则, 当 SSP0Receive() 调用时, 先前的数据字节仍会留在
	  FIFO. */
	  Dummy = LPC_SSP1->DR;
#else
	  /* 等待直到忙位被清除。 */
	  while ( LPC_SSP1->SR & SSPSR_BSY );
#endif
	}
  }
  return; 
}

/**
  * 函数名:	SSP_Receive
  * 描述:	该模块接收从 SSP 接收一块数据 
  * 参数:	端口 #, 缓冲区指针, 块长度
  * 返回值:	None
  */
void SSP_Receive( uint8_t portNum, uint8_t *buf, uint32_t Length )
{
  uint32_t i;
 
  for ( i = 0; i < Length; i++ )
  {
	/* 只要接收 FIFO 非空,能够一直接收. */
	/* 如果不是回环测试, TX 和 RX 共享时钟,不需要写假数据获得时钟
	得到数据	 */
	/* 如果是 点到点 通信, SPDR 在读操作之前需要被写 */
	if ( portNum == 0 )
	{
#if !LOOPBACK_MODE
#if SSP_SLAVE
	  while ( !(LPC_SSP0->SR & SSPSR_RNE) );
#else
	  LPC_SSP0->DR = 0xFF;
	  /* 等待直到 忙 位被清除 */
	  while ( (LPC_SSP0->SR & (SSPSR_BSY|SSPSR_RNE)) != SSPSR_RNE );
#endif
#else
	  while ( !(LPC_SSP0->SR & SSPSR_RNE) );
#endif
	  *buf = LPC_SSP0->DR;
	  buf++;
	}
	else
	{
#if !LOOPBACK_MODE
#if SSP_SLAVE
	  while ( !(LPC_SSP1->SR & SSPSR_RNE) );
#else
	  LPC_SSP1->DR = 0xFF;
	  /* 等待直到 忙 位被清除 */
	  while ( (LPC_SSP1->SR & (SSPSR_BSY|SSPSR_RNE)) != SSPSR_RNE );
#endif
#else
	  while ( !(LPC_SSP1->SR & SSPSR_RNE) );
#endif
	  *buf = LPC_SSP1->DR;
	  buf++;
	}
  }
  return; 
}

/**
  * @}
  */ 

/**
  * @}
  */ 
/************* (C) COPYRIGHT 2010 Wuhan R&D Center, Embest *****文件结束*******/


⌨️ 快捷键说明

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