tayouxunmeng 发表于 2021-7-12 09:02

hc32f460 spi作为从机用法

我现在想让spi作为从机,只接受数据,只用clk、cs、MOSI三根线。
SPI是一个环形总线结构,全双工工作时,主机和从机在时钟的同步下交换数据,但是现在没有接MOSI,构不成环形结构,怎么进行数据交换?
网上有人说从机会把自己端口悬空以后的电平作为数据,是可以实现用这3根线只接收数据的。
然后我试了下,结果接收数据时只能收到一次,然后就出现欠载,过载等错误,好像还是没有形成环路。请各位指导下,怎么用clk、cs、MOSI三根线实现spi单向接收呢?

martinhu 发表于 2021-7-12 18:02

就算是MISO悬空,SPI内部的发送寄存器总有的吧,也可以写发送寄存器啊……
欠载的原因就是主机的时钟来的时候,你没有写发送寄存器!!!!
要求是每次接收数据之前(主机时钟到来之前),都要先写一下发送数据寄存器,写什么随你

asmine 发表于 2021-7-14 17:16

还真没把mcu当从机用过,楼上说的方法试试呗,有道理

tayouxunmeng 发表于 2021-7-15 16:06

martinhu 发表于 2021-7-12 18:02
就算是MISO悬空,SPI内部的发送寄存器总有的吧,也可以写发送寄存器啊……
欠载的原因就是主机的时钟来的时 ...

我在发送中断里,写了发送寄存器,如下:
void Spi1TxEmpt_IrqHandler(void)
{   
    if (SPI_GetFlag(SPI1_UNIT,SpiFlagSendBufferEmpty) == Set)
    {
      SPI_SendData8(SPI1_UNIT,0xff);
    }      
}

结果收到的数据出了第一个对,其他都是错的,而且也会进入错误中断。
我现在时怀疑这个芯片能不能只用clk、cs、MOSI三根线接收数据

tayouxunmeng 发表于 2021-7-15 16:07

asmine 发表于 2021-7-14 17:16
还真没把mcu当从机用过,楼上说的方法试试呗,有道理

只用clk、cs、MOSI三根线,实现从机接收数据,卡了好几天了{:sad:}

martinhu 发表于 2021-7-15 16:15

tayouxunmeng 发表于 2021-7-15 16:06
我在发送中断里,写了发送寄存器,如下:
void Spi1TxEmpt_IrqHandler(void)
{   


我觉得你就没好好看我说的,为什么要在发送中断里做这个
1.首先,在初始化之后就先写一个发送字节,等待主机发送,从机接收第一个字节
2.从机接收第一个字节后,产生接收中断,在接收中断里面读取后,立即再写一个发送字节
……

tayouxunmeng 发表于 2021-7-15 18:14

martinhu 发表于 2021-7-15 16:15
我觉得你就没好好看我说的,为什么要在发送中断里做这个
1.首先,在初始化之后就先写一个发送字节,等待 ...

按照你说的改了,程序如下:
int32_t main(void)
{   
    /* LED initialization */
    BSP_CLK_Init();
//    BSP_GPIO_Init();   
//    DataProc_TaskInit();
   
    Spi1_Config();   
    SPI_Cmd(SPI1_UNIT, Enable);
    SPI_SendData8(SPI1_UNIT, 0xff);
    /* Initialize I2C port*/
    PORT_SetFunc(I2C_SCL_PORT, I2C_SCL_PIN, I2C_GPIO_SCL_FUNC, Disable);
    PORT_SetFunc(I2C_SDA_PORT, I2C_SDA_PIN, I2C_GPIO_SDA_FUNC, Disable);
   
    /* Enable I2C Peripheral*/
    PWC_Fcg1PeriphClockCmd(I2C_FCG_USE, Enable);
    /* Initialize I2C peripheral and enable function*/
    E2_Initialize();
    RF_Config();   
//    osKernelStart();
    uint16_t sum = 0;

    while (1)
    {      
      if (SPI_GetFlag(SPI1_UNIT,SpiFlagReceiveBufferFull) == Set)    //注释1
      {      
             g_dataRecvBuf = SPI_ReceiveData8(SPI1_UNIT);
             SPI_SendData8(SPI1_UNIT, 0xff);
            
      }
      if(sum == 200)
      {
            sum =0;
      }
    }
}

void Spi1_Config(void)
{
    stc_spi_init_t stcSpiInit;
    stc_irq_regi_conf_t stcIrqRegiConf;
    stc_port_init_t pstcPortInit;
    /* configuration structure initialization */
    MEM_ZERO_STRUCT(stcSpiInit);
    MEM_ZERO_STRUCT(stcIrqRegiConf);
    /* Configuration peripheral clock */
    PWC_Fcg1PeriphClockCmd(SPI1_UNIT_CLOCK, Enable);

    /* Configuration SPI pin */
    MEM_ZERO_STRUCT(pstcPortInit);
    pstcPortInit.enPullUp = Enable;
    PORT_Init(SPI1_SCK_PORT,SPI1_SCK_PIN,&pstcPortInit);
    PORT_Init(SPI1_MOSI_PORT, SPI1_MOSI_PIN, &pstcPortInit);
    MEM_ZERO_STRUCT(pstcPortInit);
    pstcPortInit.enPinMode = 0;
    PORT_Init(SPI1_NSS_PORT, SPI1_NSS_PIN, &pstcPortInit);
   
    PORT_SetFunc(SPI1_SCK_PORT, SPI1_SCK_PIN, SPI1_SCK_FUNC, Disable);
    PORT_SetFunc(SPI1_NSS_PORT, SPI1_NSS_PIN, SPI1_NSS_FUNC, Disable);
    PORT_SetFunc(SPI1_MOSI_PORT, SPI1_MOSI_PIN, SPI1_MOSI_FUNC, Disable);
      
    /* Configuration SPI structure */
    stcSpiInit.enClkDiv = SpiClkDiv8;//SpiClkDiv8
    stcSpiInit.enFrameNumber = SpiFrameNumber1;
    stcSpiInit.enDataLength = SpiDataLengthBit8;
    stcSpiInit.enFirstBitPosition = SpiFirstBitPositionMSB;
    stcSpiInit.enSckPolarity = SpiSckIdleLevelLow;//Sck极性
    stcSpiInit.enSckPhase = SpiSckOddSampleEvenChange;//相位SpiSckOddSampleEvenChange
    stcSpiInit.enReadBufferObject = SpiReadReceiverBuffer;
    stcSpiInit.enWorkMode = SpiWorkMode4Line;
    stcSpiInit.enTransMode = SpiTransFullDuplex;
    stcSpiInit.enCommAutoSuspendEn = Disable;
    stcSpiInit.enModeFaultErrorDetectEn = Disable;
    stcSpiInit.enParitySelfDetectEn = Disable;
    stcSpiInit.enParityEn = Disable;//奇偶校验
    stcSpiInit.enParity = SpiParityEven;//Select even parity send and receive

    stcSpiInit.enMasterSlaveMode = SpiModeSlave;
    stcSpiInit.stcSsConfig.enSsValidBit = SpiSsValidChannel0;
    stcSpiInit.stcSsConfig.enSs0Polarity = SpiSsLowValid;//SS极性和信道结构

    SPI_Init(SPI1_UNIT, &stcSpiInit);
}

结果:只能收到主机发送的第一个数,后面就进不去注释1满足的条件了。
而且我看了下SPI1的寄存器,如下所示:

martinhu 发表于 2021-7-15 18:49

本帖最后由 martinhu 于 2021-7-15 18:52 编辑

tayouxunmeng 发表于 2021-7-15 18:14
按照你说的改了,程序如下:
int32_t main(void)
{   

你这个SPI是接收中断???明明是查询啊,你可以看看驱动库里面主机和从机是怎么操作的,虽然那个写的比较简单,因为没有其他代码打断执行,所以从机用了查询方式。

tayouxunmeng 发表于 2021-7-15 19:39

martinhu 发表于 2021-7-15 18:49
你这个SPI是接收中断???明明是查询啊,你可以看看驱动库里面主机和从机是怎么操作的,虽然那个写的比较 ...

放接收中断里也试过,除了第一个数据,其他数据都接收不正确。而且SPI1的寄存器也出现了上面图片所示的标志

tayouxunmeng 发表于 2021-7-16 11:24

本帖最后由 tayouxunmeng 于 2021-8-13 11:05 编辑

tayouxunmeng 发表于 2021-7-15 19:39
放接收中断里也试过,除了第一个数据,其他数据都接收不正确。而且SPI1的寄存器也出现了上面图片所示的标 ...
能加个好友吗,帮我看下程序,现在能接收到数据,但是除了第一个数据外其他都错了

zc941118 发表于 2021-7-17 16:18

看了你两个关于spi的问题,,有个人已经跟你讲了原因 。基本已经讲的很清楚了,应该是华大的FAE,但是你还是解决不了,听一句劝,华大的片子你把握不住!要么换片,要么换人!
页: [1]
查看完整版本: hc32f460 spi作为从机用法