一用S32K144苦似海,道友,能不用,千万不去用。
本例程基以下如图所示接口操作,MCU为S32K144,开发平台S32DSworkspace
功能描述:模拟SPI,MSIO–>PTD16,MOSI–>PTB4,SCLK–>PTD15,CSB–>PTB5,FSCB–>PTE12
如有错误,麻烦帮忙指出,谢谢!
#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;
}