/********************************************************* * Name: SPI_Send_byte * Desc: Send one byte * Parameter: The byte to be sent * Return: None **********************************************************/ void SPI_Send_byte(uint_8 u8Data) { /*Body*/ /* Check the status flag */ if(SPI1_SR & SPI_SR_EOQF_MASK) { /* Clear the EOQF by writting a 1 to it */ SPI1_SR |= SPI_SR_EOQF_MASK; }/*Endif*/ /* Write the DSPI_PUSHR register */ SPI1_PUSHR = ( SPI_PUSHR_CTAS(0) | SPI_PUSHR_EOQ_MASK | SPI_PUSHR_CTCNT_MASK | SPI_PUSHR_PCS(1) | SPI_PUSHR_TXDATA(u8Data)); /* Write the clock and transfer attributes: master clock and frame size (8 bits) */ SPI1_CTAR0 = ( SPI_CTAR_SLAVE_FMSZ(7) | gSPI_BeforeTransfDelay | gSPI_AfterTransfDelay | gSPI_InterTransfDelay | gSPI_BaudRate); /* Start the transfer */ SPI1_MCR &= ~SPI_MCR_HALT_MASK; /* Wait until the transfer has been finished */ while(!(SPI1_SR & SPI_SR_EOQF_MASK)) { Watchdog_Reset(); }/*EndWhile*/ /* Clear the EOQF by writting a 1 to it */ SPI1_SR |= SPI_SR_EOQF_MASK; }/*EndBody*/
/** * @brief SPI初始化 * * @param spino SPI通道号 * @param master 是否是主机 * * @return E_ID 输入序号错误 * @return E_OK 初始化正常 */ ER spi_init(uint8_t spino, uint8_t master) { if((spino < 0) || (spino > SPI_NO_GET(SPI2))) { return (E_ID); } SPI_MemMapPtr base_addr = spi_get_base_address(spino); /* 使能SPI模块时钟,配置SPI引脚功能 */ if(SPI_MOD_SET(spino) == SPI0) { SIM_SCGC6 |= SIM_SCGC6_DSPI0_MASK; /* PORT_PCR_MUX(0x2) : SPI功能 * PORT_PCR_DSE_MASK : Drive Strength Enable */ gpio_init(PORT_NO_GET(SD_CS), PIN_NO_GET(SD_CS), OUT_PUT, HIGH_POWER); /* PCS0 */ PORTA_PCR15 = 0 | PORT_PCR_MUX(0x2) | PORT_PCR_DSE_MASK; /* SCK */ PORTA_PCR16 = 0 | PORT_PCR_MUX(0x2) | PORT_PCR_DSE_MASK; /* SOUT */ PORTA_PCR17 = 0 | PORT_PCR_MUX(0x2); /* SIN */ } else if(SPI_MOD_SET(spino) == SPI1) { SIM_SCGC6 |= SIM_SCGC6_SPI1_MASK; PORTE_PCR4 = 0 | PORT_PCR_MUX(0x2) | PORT_PCR_DSE_MASK; /* PCS0 */ PORTE_PCR2 = 0 | PORT_PCR_MUX(0x2) | PORT_PCR_DSE_MASK; /* SCK */ PORTE_PCR1 = 0 | PORT_PCR_MUX(0x2) | PORT_PCR_DSE_MASK; /* SOUT */ PORTE_PCR3 = 0 | PORT_PCR_MUX(0x2); /* SIN */ } else { SIM_SCGC3 |= SIM_SCGC3_SPI2_MASK; } SPI_MCR_REG(base_addr) = 0 | SPI_MCR_CLR_TXF_MASK /* Clear the Tx FIFO counter. */ | SPI_MCR_CLR_RXF_MASK /* Clear the Rx FIFO counter. */ | SPI_MCR_HALT_MASK; /* Starts and stops DSPI transfers */ /* 根据主从机模式设置工作模式 */ if(master == MASTER) { SPI_MCR_REG(base_addr) |= SPI_MCR_MSTR_MASK; /* Master/Slave Mode Select */ SPI_CTAR_REG(base_addr,0) = 0 | SPI_CTAR_DBR_MASK /* Double Baud Rate */ | SPI_CTAR_FMSZ(0x07) /* Frame Size: 8bit */ | SPI_CTAR_PDT_MASK /* 延时因子为7 */ | SPI_CTAR_BR(0x8); /* Selects the scaler value for the baud rate. */ //| SPI_CTAR_CPOL_MASK; /* Clock Polarity */ //| SPI_CTAR_CPHA_MASK; /* Clock Phase */ } else { SPI_CTAR_SLAVE_REG(base_addr,0) = 0 | SPI_CTAR_SLAVE_FMSZ(0x07) | SPI_CTAR_SLAVE_CPOL_MASK | SPI_CTAR_SLAVE_CPHA_MASK; } SPI_SR_REG(base_addr) = SPI_SR_EOQF_MASK /* End of Queue Flag */ | SPI_SR_TFUF_MASK /* Transmit FIFO Underflow Flag */ | SPI_SR_TFFF_MASK /* Transmit FIFO Fill Flag */ | SPI_SR_RFOF_MASK /* Receive FIFO Overflow Flag */ | SPI_SR_RFDF_MASK; /* Receive FIFO Drain Flag */ SPI_MCR_REG(base_addr) &= ~SPI_MCR_HALT_MASK; /* start */ return (E_OK); }
//========================================================================= //函数名称:spi_init //函数参数:spin:SPI通道号。 // Master:是否是主机。 //函数返回:无 //功能概要:SPI初始化。 //========================================================================= void spi_init(SPIn spin,SPI_CFG master) { //使能SPI模块时钟,配置SPI引脚功能 if(spin == 0) { SIM_SCGC6 |= SIM_SCGC6_DSPI0_MASK; //PORTA_PCR14 = 0 | PORT_PCR_MUX(0x2) | PORT_PCR_DSE_MASK;//PCS0 //DSE=1:输出时高驱动能力 PORTA_PCR15 = 0 | PORT_PCR_MUX(0x2) | PORT_PCR_DSE_MASK;//SCK PORTA_PCR16 = 0 | PORT_PCR_MUX(0x2) | PORT_PCR_DSE_MASK;//SOUT PORTA_PCR17 = 0 | PORT_PCR_MUX(0x2);//SIN } else if(spin == 1) { SIM_SCGC6 |= SIM_SCGC6_SPI1_MASK; PORTE_PCR1 = 0 | PORT_PCR_MUX(0x2) | PORT_PCR_DSE_MASK; //SOUT PORTE_PCR2 = 0 | PORT_PCR_MUX(0x2) | PORT_PCR_DSE_MASK; //SCK PORTE_PCR3 = 0 | PORT_PCR_MUX(0x2); //SIN PORTE_PCR4 = 0 | PORT_PCR_MUX(0x2) | PORT_PCR_DSE_MASK; //PCS0 } else { SIM_SCGC3 |= SIM_SCGC3_SPI2_MASK; PORTD_PCR13 = 0 | PORT_PCR_MUX(0x2) | PORT_PCR_DSE_MASK; //SOUT PORTD_PCR12 = 0 | PORT_PCR_MUX(0x2) | PORT_PCR_DSE_MASK; //SCK PORTD_PCR14 = 0 | PORT_PCR_MUX(0x2)/* | PORT_PCR_DSE_MASK*/; //SIN //PORTD_PCR15 = 0 | PORT_PCR_MUX(0x2)/* | PORT_PCR_DSE_MASK*/; //PCS1 } SPI_MCR_REG(SPIN[spin]) = 0 | SPI_MCR_CLR_TXF_MASK //Clear the Tx FIFO counter. | SPI_MCR_CLR_RXF_MASK //Clear the Rx FIFO counter. //| SPI_MCR_PCSIS_MASK | SPI_MCR_HALT_MASK; //根据主从机模式设置工作模式。MCU提供最大主机频率是1/2主频,最大从机频率是1/4主频 if(master == MASTER) { SPI_MCR_REG(SPIN[spin]) = (0 | SPI_MCR_MSTR_MASK //Master,主机模式 // | SPI_MCR_PCSIS(2) //PCS1 ); SPI_CTAR_REG(SPIN[spin],0) = (0 //| SPI_CTAR_DBR_MASK //双波特率 ,这里设 DBR=1,CPHA=1,PBR=00,得SCK Duty Cycle 为 50/50 //| SPI_CTAR_CPHA_MASK //数据在SCK上升沿改变(输出),在下降沿被捕捉(输入读取)。如果是0,则反之。 w25x16在上升沿读取数据;NRF24L01在上升沿读取数据 | SPI_CTAR_PBR(1) //波特率分频器 ,0~3 对应的分频值Prescaler为 2、3、5、7 | SPI_CTAR_PDT(0x00) //延时因子为 PDT*2+1 ,这里PDT为3,即延时因子为7。PDT为2bit | SPI_CTAR_BR(0) //波特率计数器值 ,当BR<=3,分频Scaler 为 2*(BR+1) ,当BR>=3,分频Scaler 为 2^BR 。BR为4bit //SCK 波特率 = (fSYS/Prescaler) x [(1+DBR)/Scaler ] fSYS 为 Bus clock // 100M 2 1 2 = 50M 这里以最大的来算 // 100M 5 1 2 =20M //| SPI_CTAR_CPOL_MASK //时钟极性,1表示 SCK 不活跃状态为高电平, NRF24L01 不活跃为低电平 | SPI_CTAR_FMSZ(0x07) //每帧传输 7bit+1 ,即8bit (FMSZ默认就是8) // | SPI_CTAR_LSBFE_MASK //1为低位在前。 //| SPI_CTAR_CSSCK(1) // //|SPI_CTAR_PCSSCK(2) //设置片选信号有效到时钟第一个边沿出现的延时的预分频值。tcsc延时预分频 2*x+1; ); //LSBFE 为 0 ,数据在前 } else { //默认从机模式 SPI_CTAR_SLAVE_REG(SPIN[spin],0) = 0 | SPI_CTAR_SLAVE_FMSZ(0x07) | SPI_CTAR_SLAVE_CPOL_MASK | SPI_CTAR_SLAVE_CPHA_MASK; } //DELAY_MS(100); /************* 清标志位 ***************/ SPI_SR_REG(SPIN[spin]) = (SPI_SR_EOQF_MASK //End of Queue Flag,发送队列空了,发送完毕 | SPI_SR_TFUF_MASK //Transmit FIFO Underflow Flag,传输FIFO下溢标志位,SPI为从机模式,Tx FIFO为空,而外部SPI主机模式启动传输,标志位就会置1,写1清0 | SPI_SR_TFFF_MASK //Transmit FIFO Fill Flag,传输FIFO满标志位。 写1或者DMA控制器发现传输FIFO满了就会清0。 0表示Tx FIFO满了 | SPI_SR_RFOF_MASK //Receive FIFO Overflow Flag,接收FIFO溢出标志位。 | SPI_SR_RFDF_MASK); //Receive FIFO Drain Flag,接收FIFO损耗标志位,写1或者DMA控制器发现传输FIFO空了就会清0。0表示Rx FIFO空 SPI_MCR_REG(SPIN[spin]) &= ~SPI_MCR_HALT_MASK; //启动SPI传输。1为暂停,0为启动 DELAY_MS(1); }
int spi_init_slave(spi_t dev, spi_conf_t conf, char(*cb)(char data)) { SPI_Type *spi_dev; switch (dev) { #if SPI_0_EN case SPI_0: spi_dev = SPI_0_DEV; /* enable clocks */ SPI_0_CLKEN(); SPI_0_PCS0_PORT_CLKEN(); SPI_0_SCK_PORT_CLKEN(); SPI_0_SOUT_PORT_CLKEN(); SPI_0_SIN_PORT_CLKEN(); /* Set PORT to AF mode */ SPI_0_PCS0_PORT->PCR[SPI_0_PCS0_PIN] = PORT_PCR_MUX(SPI_0_PCS0_AF); SPI_0_SCK_PORT->PCR[SPI_0_SCK_PIN] = PORT_PCR_MUX(SPI_0_SCK_AF); SPI_0_SOUT_PORT->PCR[SPI_0_SOUT_PIN] = PORT_PCR_MUX(SPI_0_SOUT_AF); SPI_0_SIN_PORT->PCR[SPI_0_SIN_PIN] = PORT_PCR_MUX(SPI_0_SIN_AF); break; #endif /* SPI_0_EN */ default: return -1; } /* set frame size, slave mode always uses CTAR0 */ spi_dev->CTAR[0] = SPI_CTAR_SLAVE_FMSZ(7); /* Set clock polarity and phase. */ switch (conf) { case SPI_CONF_FIRST_RISING: spi_dev->CTAR[0] &= ~(SPI_CTAR_CPHA_MASK | SPI_CTAR_CPOL_MASK); break; case SPI_CONF_SECOND_RISING: spi_dev->CTAR[0] &= ~(SPI_CTAR_CPOL_MASK); spi_dev->CTAR[0] |= SPI_CTAR_CPHA_MASK; break; case SPI_CONF_FIRST_FALLING: spi_dev->CTAR[0] &= ~(SPI_CTAR_CPHA_MASK); spi_dev->CTAR[0] |= SPI_CTAR_CPOL_MASK; break; case SPI_CONF_SECOND_FALLING: spi_dev->CTAR[0] |= SPI_CTAR_CPHA_MASK | SPI_CTAR_CPOL_MASK; break; default: return -2; } /* enable SPI */ spi_dev->MCR = SPI_MCR_DOZE_MASK | SPI_MCR_PCSIS(SPI_0_PCS0_ACTIVE_LOW << 0) | SPI_MCR_CLR_TXF_MASK | SPI_MCR_CLR_RXF_MASK; spi_dev->RSER = (uint32_t)0; /* set callback */ spi_config[dev].cb = cb; return 0; }