S32K系列S32K144学习笔记——模拟SPI

一用S32K144苦似海,道友,能不用,千万不去用。

本例程基以下如图所示接口操作,MCU为S32K144,开发平台S32DSworkspace
功能描述:模拟SPI,MSIO–>PTD16,MOSI–>PTB4,SCLK–>PTD15,CSB–>PTB5,FSCB–>PTE12
如有错误,麻烦帮忙指出,谢谢!
S32K系列S32K144学习笔记——模拟SPI_第1张图片

#include "S32K144.h" /* include peripheral declarations S32K144 */
#include "s32_core_cm4.h"
    
#define CMT_SCLK_GPIO 15 //PD15
#define CMT_CSB_GPIO  5  //PB5
#define CMT_FCSB_GPIO 12  //PE12
#define CMT_MIOS_GPIO 16 //PD16
#define CMT_MOIS_GPIO 4  //PB4

#define cmt_spi_csb_1()        (PTB-> PDOR |= 1< PDOR &= ~(1< PDOR |= 1< PDOR &= ~(1< PDOR |= 1< PDOR &= ~(1< PDOR |= 1< PDOR &= ~(1<PDIR & (1<PCCn[PCC_PORTB_INDEX ] |= PCC_PCCn_CGC_MASK;PTB->PDDR &= ~(1<<4);PORTB->PCR[4] = 0x00000100;}
#define cmt_spi_sdio_out()     {PCC->PCCn[PCC_PORTB_INDEX ] |= PCC_PCCn_CGC_MASK;PTB->PDDR |= (1<<4);PORTB->PCR[4] = 0x00000100;}

void WDOG_disable (void)
{
	WDOG->CNT=0xD928C520; 	 //解锁看门狗
	WDOG->TOVAL=0x0000FFFF;	 //把时间配置为最大
	WDOG->CS = 0x00002100;   //关闭看门狗
}

void SOSC_init_8MHz(void)
{
  	SCG->SOSCDIV=0x00000101;  //SOSCDIV1 & SOSCDIV2 =1:  分频/1
  	SCG->SOSCCFG=0x00000024;  //Range=2: 选择晶体振荡器的中频范围 (SOSC 1MHz-8MHz)
                              // HGO=0:   控制晶体振荡器的工作功率模式 --低功率模式
                              // EREFS=1: 外部参考选择OSC内部晶体振荡器
  	while(SCG->SOSCCSR & SCG_SOSCCSR_LK_MASK); //等待SOSCCSR解锁 寄存器解锁后才可写入
  	SCG->SOSCCSR=0x00000001;  // LK=0:  SOSCCSR可以写
                              // SOSCCM=0: 系统OSC时钟监视器被禁用
                              // SOSCEN=1: 启用系统OSC
  	while(!(SCG->SOSCCSR & SCG_SOSCCSR_SOSCVLD_MASK)); //等待系统OSC成功启用,输出时钟有效
}


void SPLL_init_160MHz(void)
{
  	while(SCG->SPLLCSR & SCG_SPLLCSR_LK_MASK); //等待SPLLCSR寄存器解锁  寄存器解锁后才可写入
  	SCG->SPLLCSR = 0x00000000;  // LK=0: SPLLCSR可以写入
  	  	  	  	  	  	  	    // SPLLEN=0: SPLL禁用
  	SCG->SPLLDIV = 0x00000302;  // SPLLDIV1 分频/2; SPLLDIV2 分频/4
  	SCG->SPLLCFG = 0x00180000;  // PREDIV=0: 锁相环参考时钟分频因子
                                // MULT=24:  SPLL时钟频率的乘法因子
                                // SPLL_CLK = 8MHz / 1 * 40 / 2 = 160 MHz    SPLL_CLK = (VCO_CLK)/2  VCO_CLK = SPLL_SOURCE/(PREDIV+1)*(MULT+16)
  	while(SCG->SPLLCSR & SCG_SPLLCSR_LK_MASK); //等待SPLLCSR寄存器解锁  寄存器解锁后才可写入
  	SCG->SPLLCSR = 0x00000001;  // LK=0: SPLLCSR可以写入
                                // SPLLCM=0: SPLL时钟监视器被禁用
                                // SPLLEN=1: 开启SPLL
  	while(!(SCG->SPLLCSR & SCG_SPLLCSR_SPLLVLD_MASK)); //等待SPLL成功启用,输出时钟有效
}

void NormalRUNmode_40MHz (void)
{
	SCG->RCCR=SCG_RCCR_SCS(6)   // SPLL做为系统时钟源
	|SCG_RCCR_DIVCORE(0b11)     // DIVCORE=3, 分频/4: Core clock = 160/4 MHz = 40 MHz
	|SCG_RCCR_DIVBUS(0b11)      // DIVBUS=3, 分频/4: bus clock = 160/4 MHz = 40 MHz
	|SCG_RCCR_DIVSLOW(0b111);   // DIVSLOW=7, 分频/8: SCG slow, flash clock= 160/8 MHz = 20MHZ
	while (((SCG->CSR & SCG_CSR_SCS_MASK) >> SCG_CSR_SCS_SHIFT ) != 6) {}//等待系统时钟源成功选择SPLL
}
/*********************************************************************
* 函数原型:void SPI_GPIO_Init(void)
* 功   能:SPI接口实始化
* 输入参数:无
* 返回参数:无
*
* 其他说明:
*********************************************************************/
void SPI_GPIO_Init(void)
{
	PCC->PCCn[PCC_PORTB_INDEX ] |= PCC_PCCn_CGC_MASK; /* Enable clock for PORTB */
	PTB->PDDR |= (1<<4) | (1<<5);    /* Port B4/B5: Data Direction= output */
	PORTB->PCR[4] = 0x00000100; /* Port B4: MUX = GPIO */
	PORTB->PCR[5] = 0x00000100; /* Port B5: MUX = GPIO */

	PCC->PCCn[PCC_PORTD_INDEX ] |= PCC_PCCn_CGC_MASK; /* Enable clock for PORTD */
	PTD->PDDR |= (1<<15);    /* Port D15: Data Direction= output */
	PORTD->PCR[15] = 0x00000100; /* Port D15: MUX = GPIO */
	PTD->PDDR &= ~(1<<16);    /* Port D16: Data Direction= input */
	PORTD->PCR[16] = 0x00000110; /* Port D16: MUX = GPIO, input filter enabled */

	PCC->PCCn[PCC_PORTE_INDEX ] |= PCC_PCCn_CGC_MASK; /* Enable clock for PORTE */
	PTE->PDDR |= (1<<12);    /* Port E8: Data Direction= output */
	PORTE->PCR[12] = 0x00000100; /* Port E8: MUX = GPIO */
	//FCSB拉高
}
/*********************************************************************
* 函数原型:void cmt_spi_delay(void)
* 功   能:不精准的简单延时
* 输入参数:无
* 返回参数:无
*
* 其他说明:
*********************************************************************/
void cmt_spi_delay(void)
{
	long int n = 20;
	while(n--);
}
/*********************************************************************
* 函数原型:void cmt_spi_delay_us(void)
* 功   能:不精准的简单延时
* 输入参数:无
* 返回参数:无
*
* 其他说明:
*********************************************************************/
void cmt_spi_delay_us(void)
{
	volatile int n = 8;
	while(n--);
}
/*********************************************************************
* 函数原型:void cmt_spi_init(void)
* 功   能:SPI初始化
* 输入参数:无
* 返回参数:无
*
* 其他说明:
*********************************************************************/
void cmt_spi_init(void)
{
	SPI_GPIO_Init();

	cmt_spi_csb_1();   /* CSB has an internal pull-up resistor */

	cmt_spi_sclk_0();   /* SCLK has an internal pull-down resistor */

	cmt_spi_sdio_out();
	cmt_spi_sdio_1();

	cmt_spi_fcsb_1();  /* FCSB has an internal pull-up resistor */

	cmt_spi_delay();
}
/*********************************************************************
* 函数原型:void cmt_spi_send(char data8)
* 功   能:SPI发送一个BYTE
* 输入参数:data8--需要发送的数据
* 返回参数:无
*
* 其他说明:
*********************************************************************/
void cmt_spi_send(char data8)
{
	char i;

	for(i=0; i<8; i++)
	{
 		cmt_spi_sclk_0();

    	/* Send byte on the rising edge of SCLK */
    	if(data8 & 0x80)
        	cmt_spi_sdio_1();
    	else
        	cmt_spi_sdio_0();

    	cmt_spi_delay();

    	data8 <<= 1;
    	cmt_spi_sclk_1();
    	cmt_spi_delay();
	}
}

/*********************************************************************
* 函数原型:char cmt_spi_recv(void)
* 功   能:SPI接收一个数据
* 输入参数:无
* 返回参数:接收的数据
*
* 其他说明:
*********************************************************************/
char cmt_spi_recv(void)
{
	char i;
	char data8 = 0xFF;

	for(i=0; i<8; i++)
	{
    	cmt_spi_sclk_0();
    	cmt_spi_delay();
    	data8 <<= 1;

    	cmt_spi_sclk_1();

    	/* Read byte on the rising edge of SCLK */
    	if(cmt_spi_sdio_read())
        	data8 |= 0x01;
    	else
        	data8 &= ~0x01;

    	cmt_spi_delay();
	}

	return data8;
}

/*********************************************************************
* 函数原型:void cmt_spi_write(char addr, char dat)
* 功   能:SPI写数据到指定地址
* 输入参数:addr--地址   dat--数据
* 返回参数:无
*
* 其他说明:
*********************************************************************/
void cmt_spi_write(char addr, char dat)
{

	cmt_spi_sdio_1();
	cmt_spi_sdio_out();

	cmt_spi_sclk_0();

	cmt_spi_fcsb_1();

	cmt_spi_csb_0();

	/* > 0.5 SCLK cycle */
	cmt_spi_delay();
	cmt_spi_delay();

	/* r/w = 0 */
	cmt_spi_send(addr&0x7F);

	cmt_spi_send(dat);

	cmt_spi_sclk_0();

	/* > 0.5 SCLK cycle */
	cmt_spi_delay();
	cmt_spi_delay();

	cmt_spi_csb_1();

	cmt_spi_sdio_1();
	cmt_spi_sdio_in();

	cmt_spi_fcsb_1();
}

/*********************************************************************
* 函数原型:void cmt_spi_read(char addr, char* p_dat)
* 功   能:SPI读取指定地址的数据
* 输入参数:addr--地址  p_dat--数据包
* 返回参数:无
*
* 其他说明:
*********************************************************************/
void cmt_spi_read(char addr, char* p_dat)
{
	cmt_spi_sdio_1();
	cmt_spi_sdio_out();

	cmt_spi_sclk_0();

	cmt_spi_fcsb_1();

	cmt_spi_csb_0();

	/* > 0.5 SCLK cycle */
	cmt_spi_delay();
	cmt_spi_delay();

	/* r/w = 1 */
	cmt_spi_send(addr|0x80);

	cmt_spi_sdio_in();

	*p_dat = cmt_spi_recv();

	cmt_spi_sclk_0();

	/* > 0.5 SCLK cycle */
	cmt_spi_delay();
	cmt_spi_delay();

	cmt_spi_csb_1();

	cmt_spi_sdio_1();
	cmt_spi_sdio_in();

	cmt_spi_fcsb_1();
}

/*********************************************************************
* 函数原型:void cmt_spi_write_fifo(const char* p_buf, int len)
* 功   能:SPI写FIFO数据
* 输入参数:p_buf--FIFO数据包  len--长度
* 返回参数:无
*
* 其他说明:
*********************************************************************/
void cmt_spi_write_fifo(const char* p_buf, int len)
{
	int i;

	cmt_spi_fcsb_1();

	cmt_spi_csb_1();

	cmt_spi_sclk_0();

	cmt_spi_sdio_out();

	for(i=0; i 1 SCLK cycle */
    	cmt_spi_delay();
    	cmt_spi_delay();

    	cmt_spi_send(p_buf[i]);

    	cmt_spi_sclk_0();

    	/* > 2 us */
    	cmt_spi_delay_us();
    	cmt_spi_delay_us();
    	cmt_spi_delay_us();

    	cmt_spi_fcsb_1();

    	/* > 4 us */
    	cmt_spi_delay_us();
    	cmt_spi_delay_us();
    	cmt_spi_delay_us();
    	cmt_spi_delay_us();
    	cmt_spi_delay_us();
    	cmt_spi_delay_us();
	}

	cmt_spi_sdio_in();

	cmt_spi_fcsb_1();
}

/*********************************************************************
* 函数原型:void cmt_spi_read_fifo(char* p_buf, int len)
* 功   能:SPI读取FIFO数据
* 输入参数:p_buf--数据包  len--长度
* 返回参数:无
*
* 其他说明:
*********************************************************************/
void cmt_spi_read_fifo(char* p_buf, int len)
{
	int i;

	cmt_spi_fcsb_1();

	cmt_spi_csb_1();

	cmt_spi_sclk_0();

	cmt_spi_sdio_in();

	for(i=0; i 1 SCLK cycle
    	cmt_spi_delay();
    	cmt_spi_delay();

    	p_buf[i] = cmt_spi_recv();

    	cmt_spi_sclk_0();

    	//* > 2 us
    	cmt_spi_delay_us();
    	cmt_spi_delay_us();
    	cmt_spi_delay_us();

    	cmt_spi_fcsb_1();

    	//* > 4 us
    	cmt_spi_delay_us();
    	cmt_spi_delay_us();
    	cmt_spi_delay_us();
    	cmt_spi_delay_us();
    	cmt_spi_delay_us();
    	cmt_spi_delay_us();
	}

	cmt_spi_sdio_in();

	cmt_spi_fcsb_1();
}

int main(void)
{
	char read_data = 0xff;
	
	WDOG_disable();                   //关闭看门狗
	SOSC_init_8MHz();                 //配置系统振荡器为外部8MHZ
	SPLL_init_160MHz();               //使用SOSC 8MHZ配置SPLL 为160 MHz
	NormalRUNmode_40MHz();            //配置系列时钟40MHz, 40MHz总线时钟
	
	cmt_spi_init();                   //模拟SPI初始化
	cmt_spi_write(0x01,0xaa);         //写0xaa到0X01这个地址
	cmt_spi_read(0x01, &read_data);   //读取0x01地址的值
	for(;;)
	{
	}

	return 0;
}

你可能感兴趣的:(S32K系列)