【问题标题】:SPI driver on the FRDM-K64F and continuous clockFRDM-K64F 上的 SPI 驱动程序和连续时钟
【发布时间】:2016-03-21 16:29:27
【问题描述】:

我正在尝试在 FRDM-K64F 板上创建自己的 SPI 裸机驱动程序。我暂时只写了一个初始化函数。

为了测试功能,我设置了连续时钟寄存器。我预计即使总线上没有设置数据,连续时钟也会始终生成时钟。但是我的示波器上没有看到时钟。

为什么我的示波器上看不到时钟?我是否误解了连续时钟寄存器?还是我忘记实现另一个寄存器?

int frdm_spi_init(SPI_Type *spi, struct frdm_spi_mode *mode, uint32_t hz) 
{

        if(mode->frame < FRDM_SPI_MIN_FRAME_SIZE) {
          return -1;
        }

        // Enable clock
        SIM_SCGC6 |= SIM_SCGC6_SPI0(FRDM_ENABLE);

        // For debug purpose
        SPI_MCR_REG(spi) &= ~SPI_MCR_CONT_SCKE_MASK;
        SPI_MCR_REG(spi) |= (FRDM_ENABLE<<SPI_MCR_CLR_RXF_SHIFT);

        // Master/slave
        SPI_MCR_REG(spi) &= ~SPI_MCR_MSTR_MASK;
        SPI_MCR_REG(spi) |= (mode->mode<<SPI_MCR_MSTR_SHIFT);

        if(mode->mode == FRDM_SPI_MASTER)  {

          //Frame size
          SPI_CTAR_REG(spi,0) &= ~SPI_CTAR_FMSZ_MASK;
          SPI_CTAR_REG(spi,0) |= (((mode->frame-1) & 0x0F)<<SPI_CTAR_FMSZ_SHIFT);

          // Spi mode
          SPI_CTAR_REG(spi,0) &= ~SPI_CTAR_CPOL_MASK;
          SPI_CTAR_REG(spi,0) |= (mode->CPOL)<<SPI_CTAR_CPOL_SHIFT;
          SPI_CTAR_REG(spi,0) &= ~SPI_CTAR_CPHA_MASK;
          SPI_CTAR_REG(spi,0) |= (mode->CPHA)<<SPI_CTAR_CPHA_SHIFT;

          //Always in msb mode
          SPI_CTAR_REG(spi,0) &= ~SPI_CTAR_LSBFE_MASK;

        } else if(mode->mode == FRDM_SPI_SLAVE) {

          /*TODO*/
        }

        //frequency
        SPI_CTAR_REG(spi,0) &= ~SPI_CTAR_ASC_MASK;
        SPI_CTAR_REG(spi,0) |= 1<<SPI_CTAR_ASC_SHIFT;
        SPI_CTAR_REG(spi,0) &= ~SPI_CTAR_PASC_MASK;
        SPI_CTAR_REG(spi,0) |= 0<<SPI_CTAR_PASC_SHIFT;
        SPI_CTAR_REG(spi,0) &= ~SPI_CTAR_DBR_MASK;
        SPI_CTAR_REG(spi,0) |= 0<<SPI_CTAR_DBR_SHIFT;

        // Fifo
        SPI_MCR_REG(spi) &= ~SPI_MCR_DIS_TXF_MASK;
        SPI_MCR_REG(spi) != 0<<SPI_MCR_DIS_TXF_SHIFT;

        //Enable
        SPI_MCR_REG(spi) &= ~SPI_MCR_MDIS_MASK;
        SPI_MCR_REG(spi) != 0<<SPI_MCR_MDIS_SHIFT;

        // Start hardware
        SPI_MCR_REG(spi) &= ~SPI_MCR_HALT_MASK;
        SPI_MCR_REG(spi) |= 0<<SPI_MCR_HALT_SHIFT;

        return 0;
}

【问题讨论】:

  • 除非您是芯片设计师,否则您不会“实现”特殊功能寄存器。相反,作为程序员,您可以配置它们或为它们分配值以实现功能。

标签: embedded driver spi bare-metal cortex-m


【解决方案1】:

提供的代码没有为 SPI 配置引脚控制寄存器;这可以在其他地方完成,但您应该验证引脚配置是否正确,并且您正在使用的 SPI 端口的 SCK 已复用到您期望的引脚。无论如何,在这个函数中设置引脚配置可能会更好。

这个区块看起来也很可疑:

    //frequency
    SPI_CTAR_REG(spi,0) &= ~SPI_CTAR_ASC_MASK;
    SPI_CTAR_REG(spi,0) |= 1<<SPI_CTAR_ASC_SHIFT;
    SPI_CTAR_REG(spi,0) &= ~SPI_CTAR_PASC_MASK;
    SPI_CTAR_REG(spi,0) |= 0<<SPI_CTAR_PASC_SHIFT;
    SPI_CTAR_REG(spi,0) &= ~SPI_CTAR_DBR_MASK;
    SPI_CTAR_REG(spi,0) |= 0<<SPI_CTAR_DBR_SHIFT;

它不使用hz 参数,并且Y |= 0 &lt;&lt; X 将始终等于Y。它留下 ASC = 1、PASC = 0、DBR = 0,只有最后一个影响时钟频率。您尚未设置 BR 和 PBR:

SCK 波特率 = (fP /PBR) x [(1+DBR)/BR]

假设当前值处于复位状态,则时钟为 fP/4。

此外,您还有一个错字:

    //Enable
    SPI_MCR_REG(spi) &= ~SPI_MCR_MDIS_MASK;
    SPI_MCR_REG(spi) != 0<<SPI_MCR_MDIS_SHIFT;   
                 //  ^ 
                 //  error |= not !=

但是,即使更正,第二行也不做任何事情,但第一行已经清除了该位,并且零中的 OR'ing 什么都不做(仍然),所以错误是良性的。然而,我很惊讶您的编译器没有发出“语句什么都不做”警告。

我相信有用于单独设置外设寄存器字段的宏,例如SPI_CTAR_ASC(x)SPI_CTAR_PASC(x) 等。您可能应该使用这些宏来清楚并避免屏蔽错误和维护噩梦。

【讨论】:

    猜你喜欢
    • 2017-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-08
    • 2018-04-18
    • 2015-03-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多