freetech

kinetis的SPI例程

0
阅读(5372)

kinetis有多达3个SPI接口,收发各带4个16位的FIFO,可支持自动片选。可工作于主、从模式。SPI是同步串口,发一个字节(或字)时也收一个字节(或字),其通信通过4种功能的线来完成:

  • SCK-时针线,用于主设备向从设备提供时钟。
  • SIN-串行数据输入
  • SOUT-串行数据输出
  • PCSn-片选线,工作在主模式时通过片选线的不同组合选择对应的外设;工作在从模式时,仅PCS0有意义,用于主设备选择该芯片(指kinetis)为从设备。

SPI的寄存器有很多,但常用的只有几个,它们是:

  • SPIx_MCR-DSPI模块配置寄存器
  • SPIx_CTARn(从机模式下是SPIx_CTARn_SLAVE)-DSPI 时钟与传输属性寄存器
  • SPIx_SR-DSPI状态寄存器
  • SPIx_PUSHR(从机模式是SPIx_PUSHR_SLAVE)-DSPI PUSH发送队列寄存器
  • SPIx_POPR-DSPI POP接收队列寄存器

本例程工作在主模式,未使用FIFO,外部用一根线将SIN与SOUT连接,SPI将收到自己发出的数据,下面是完整代码:

/*
* main implementation: use this 'C' sample to create your own application
*
*/

#include <stdio.h>

#include "derivative.h"

void SPI_Init(void) {
    SIM_SCGC5 |= SIM_SCGC5_PORTB_MASK;
    SIM_SCGC6 |= SIM_SCGC6_SPI1_MASK;   
    PORTB_PCR17 = PORT_PCR_MUX(2);
    PORTB_PCR16 = PORT_PCR_MUX(2);
    PORTB_PCR11 = PORT_PCR_MUX(2);
    PORTB_PCR9 = PORT_PCR_MUX(2);
    SPI1_MCR = SPI_MCR_ROOE_MASK | SPI_MCR_PCSIS(2) | SPI_MCR_HALT_MASK;//0x01020001
    // SPI1_MCR: MSTR=1,CONT_SCKE=0,DCONF=0,FRZ=0,MTFE=0,PCSSE=0,ROOE=1,??=0,??=0,PCSIS=2,DOZE=0,MDIS=0,DIS_TXF=1,DIS_RXF=1,CLR_TXF=1,CLR_RXF=1,SMPL_PT=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,HALT=1
    SPI1_MCR = SPI_MCR_MSTR_MASK | SPI_MCR_ROOE_MASK | SPI_MCR_PCSIS(2) | SPI_MCR_DIS_TXF_MASK | SPI_MCR_DIS_RXF_MASK | SPI_MCR_CLR_TXF_MASK | SPI_MCR_CLR_RXF_MASK | SPI_MCR_HALT_MASK; //Set Configuration register
    // SPI1_CTAR0: DBR=1,FMSZ=7,CPOL=0,CPHA=0,LSBFE=0,PCSSCK=1,PASC=1,PDT=1,PBR=1,CSSCK=0x0C,ASC=0x0C,DT=0x0C,BR=0x0E
    SPI1_CTAR0 = SPI_CTAR_DBR_MASK | SPI_CTAR_FMSZ(7) | SPI_CTAR_PCSSCK(1) | SPI_CTAR_PASC(1) | SPI_CTAR_PDT(1) | SPI_CTAR_PBR(1) | SPI_CTAR_CSSCK(0x0C) | SPI_CTAR_ASC(0x0C) | SPI_CTAR_DT(0x0C) | SPI_CTAR_BR(0x0E); //Set Clock and Transfer Attributes register
    // SPI1_SR: TCF=1,TXRXS=0,??=0,EOQF=1,TFUF=1,??=0,TFFF=1,??=0,??=0,??=0,??=1,??=0,RFOF=1,??=0,RFDF=1,??=0,TXCTR=0,TXNXTPTR=0,RXCTR=0,POPNXTPTR=0
    SPI1_SR = SPI_SR_TCF_MASK | SPI_SR_EOQF_MASK | SPI_SR_TFUF_MASK | SPI_SR_TFFF_MASK | SPI_SR_RFOF_MASK | SPI_SR_RFDF_MASK | SPI_SR_TXCTR(0) | SPI_SR_TXNXTPTR(0) | SPI_SR_RXCTR(0) | SPI_SR_POPNXTPTR(0); //Clear flags
    // SPI1_RSER: TCF_RE=0,??=0,??=0,EOQF_RE=0,TFUF_RE=0,??=0,TFFF_RE=0,TFFF_DIRS=0,??=0,??=0,??=0,??=0,RFOF_RE=0,??=0,RFDF_RE=0,RFDF_DIRS=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0
    SPI1_RSER = 0;  //Set DMA Interrupt Request Select and Enable register
    // SPI1_MCR: HALT=0
    SPI1_MCR &=  ~SPI_MCR_HALT_MASK;
}
unsigned char SPI_RW(unsigned char dat)
{
  unsigned char tmp;
     {
          SPI1_PUSHR = SPI_PUSHR_PCS(2) | dat;
        while((SPI1_SR&SPI_SR_TFFF_MASK) == 0);
        while((SPI1_SR&SPI_SR_RFDF_MASK) == 0);
        tmp =SPI1_POPR;
         SPI1_SR = SPI_SR_TFFF_MASK | SPI1_SR&SPI_SR_RFDF_MASK;
     }
  return(tmp);                             // return read byte
}
int main(void)
{
    int counter = 0;
    unsigned char tx_buf[10],rx_buf[10];
    for(counter=0;counter<10;counter++)
    {
        tx_buf[counter] = counter;
    }

    SPI_Init();
    printf("Hello (Kinetis) World in 'C' from MK60DX256Z derivative! \n\r");
    counter = 0;
    for(;;) {      
        rx_buf[counter] = SPI_RW(tx_buf[counter]);
        counter++;
        if( counter >= 10 )
        {
            counter = 0;
        }
    }
    return 0;
}

在发完10个数的地方设个断点,如图:

image

可以看到接收到的数据与发送的数据一致,如下图:

image