最近做了个S32K146利用SPI与xr20m1172进行通信的小demo,因为是新手,所以花费了一段时间配置寄存器,现将自己的配置流程和代码贴出,加强自己的总结能力也希望能够帮助你们。
SPI的介绍我也不多加赘述了,这里讲一下SPI配置容易出错的点或者说是我犯过的错误,希望对你们有帮助。
1. 配置引脚和引脚复用
void PORTSPI0_init (void)
{
PCC->PCCn[PCC_PORTD_INDEX ]|=PCC_PCCn_CGC_MASK; /* Enable clock for PORTD*/
PORTD->PCR[15]|=PORT_PCR_MUX(4); /* Port D15: MUX = ALT3, LPSPI0_SCK */
PORTD->PCR[16]|=PORT_PCR_MUX(4); /* Port D16: MUX = ALT3, LPSPI0_SIN */
PCC->PCCn[PCC_PORTB_INDEX ]|=PCC_PCCn_CGC_MASK; /* Enable clock for PORTB */
PORTB->PCR[4]|=PORT_PCR_MUX(3); /* Port B4: MUX = ALT3, LPSPI0_SOUT */
PORTB->PCR[5]|=PORT_PCR_MUX(3); /* Port B5: MUX = ALT3, LPSPI0_PCS1 */
//SPI0_RST/STAT------------>拉低xr20m1172得reset引脚,使其先复位
PTE->PDDR |= 1<<15;
PORTE->PCR[15] = 0x00000100;
PTE-> PCOR |= 1<<15;
delay_us(10000);
}
2. 配置时钟极性和相位极性:
因为从机CPOA=0,CPOH=0,所以S32K146按这个进行配置,SPI控制器中配置TCR寄存器的30位和31位,LPSPI_TCR_CPOL(0), LPSPI_TCR_CPHA(0) 。 配置TCR中点PCS:我用的是SPI0,配置的是LPSPI_TCR_PCS(1),其他的保持和例程上的一致。
void LPSPI0_init_master(void)
{
PCC->PCCn[PCC_LPSPI0_INDEX] = 0;
PCC->PCCn[PCC_LPSPI0_INDEX] = PCC_PCCn_PR_MASK
|PCC_PCCn_CGC_MASK
|PCC_PCCn_PCS(6);
LPSPI0->CR = 0x00000000;
LPSPI0->IER = 0x00000000;
LPSPI0->DER = 0x00000000;
LPSPI0->CFGR0 = 0x00000000;
LPSPI0->CFGR1 = LPSPI_CFGR1_MASTER_MASK;
LPSPI0->TCR = LPSPI_TCR_CPHA(0)
|LPSPI_TCR_PRESCALE(2)
|LPSPI_TCR_PCS(1)
|LPSPI_TCR_FRAMESZ(15);
LPSPI0->CCR = LPSPI_CCR_SCKPCS(4)
|LPSPI_CCR_PCSSCK(4)
|LPSPI_CCR_DBT(8)
|LPSPI_CCR_SCKDIV(8);
LPSPI0->FCR = LPSPI_FCR_TXWATER(3);
LPSPI0->CR = LPSPI_CR_MEN_MASK
|LPSPI_CR_DBGEN_MASK;
}
3. 配置xr20m1172的寄存器
配置步骤,先配置软硬件流,再配置波特率,再配置FCR,最后再配置LCR,注意,有很多寄存器存在地址共用的情况,所以配置的时候需要有一个前提,这个在用户手册那张表中会有提到,比如配置EFR就得先配置LCR。其次我在执行程序的时候总是会执行不下去,卡住在SPI发送函数那里,解决方法:根据SPI特性,发送一个数据就读一个数据,然后这个读到的数据没用直接丢弃,解决了卡死问题。以下就是我的程序代码,能实现正常的收发,数据均正确,附出.c和.h文件,主函数只是个循环发送和供电问题。
void Xr20m1172_Write_ConfigRegister(){
uint8_t i = 0;
SPI_Send_Byte(XR20M1172_LCR_REG,0xbf);
ConvinceRegister[i++] = SPI_Read_Byte(XR20M1172_LCR_REG);SPI_Send_Byte(XR20M1172_EFR_REG,0x1A);
ConvinceRegister[i++] = SPI_Read_Byte(XR20M1172_EFR_REG);SPI_Send_Byte(XR20M1172_XON1_REG,0x13);
ConvinceRegister[i++] = SPI_Read_Byte(XR20M1172_XON1_REG);SPI_Send_Byte(XR20M1172_XOFF1_REG,0x11);
ConvinceRegister[i++] = SPI_Read_Byte(XR20M1172_XOFF1_REG);SPI_Send_Byte(XR20M1172_XON2_REG,0x14);
ConvinceRegister[i++] = SPI_Read_Byte(XR20M1172_XON2_REG);SPI_Send_Byte(XR20M1172_XOFF2_REG,0x12);
ConvinceRegister[i++] = SPI_Read_Byte(XR20M1172_XOFF2_REG);SPI_Send_Byte(XR20M1172_LCR_REG,0x80);
ConvinceRegister[i++] = SPI_Read_Byte(XR20M1172_LCR_REG);SPI_Send_Byte(XR20M1172_DLD_REG,0x03);
ConvinceRegister[i++] = SPI_Read_Byte(XR20M1172_DLD_REG);SPI_Send_Byte(XR20M1172_DLM_REG,0x00);
ConvinceRegister[i++] = SPI_Read_Byte(XR20M1172_DLM_REG);SPI_Send_Byte(XR20M1172_DLL_REG,0x68);
ConvinceRegister[i++] = SPI_Read_Byte(XR20M1172_DLL_REG);SPI_Send_Byte(XR20M1172_LCR_REG,0x03);
ConvinceRegister[i++] = SPI_Read_Byte(XR20M1172_LCR_REG);SPI_Send_Byte(XR20M1172_FCR_REG,0x87);
ConvinceRegister[i++] = SPI_Read_Byte(XR20M1172_FCR_REG);
}void SPI_Send_Byte(uint8_t addr , uint8_t send){
uint16_t instruction = 0;
uint8_t ans = 0;
instruction = (addr<<11)|send;
LPSPI0_transmit_16bits(instruction);
ans = (LPSPI0_receive_16bits()&0xff);
return ;
}
uint8_t SPI_Read_Byte(uint8_t addr){
uint8_t ans = 0;
uint16_t instruction = 0;
instruction = (addr<<11)|0x8000;
LPSPI0_transmit_16bits(instruction);
ans=(LPSPI0_receive_16bits()&0xff);
return ans;
}
4. 波特率的计算问题:
一般采用16模式,divide = 时钟频率(8M)/主机频率*16*9600 ;整数高位放入DLM ,低位放入DLL,小数放入DLD。
我想把我的源码发出来,但是不知道怎么发,下次弄懂了就发出来