打印
[技术问答]

hc32f460 spi作为从机用法

[复制链接]
5156|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
我现在想让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三根线接收数据

使用特权

评论回复
5
tayouxunmeng|  楼主 | 2021-7-15 16:07 | 只看该作者
asmine 发表于 2021-7-14 17:16
还真没把mcu当从机用过,楼上说的方法试试呗,有道理

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

使用特权

评论回复
6
martinhu| | 2021-7-15 16:15 | 只看该作者
tayouxunmeng 发表于 2021-7-15 16:06
我在发送中断里,写了发送寄存器,如下:
void Spi1TxEmpt_IrqHandler(void)
{   

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

使用特权

评论回复
7
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[CHANNEL_0][sum++] = 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的寄存器,如下所示:

使用特权

评论回复
8
martinhu| | 2021-7-15 18:49 | 只看该作者
本帖最后由 martinhu 于 2021-7-15 18:52 编辑
tayouxunmeng 发表于 2021-7-15 18:14
按照你说的改了,程序如下:
int32_t main(void)
{   

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

使用特权

评论回复
9
tayouxunmeng|  楼主 | 2021-7-15 19:39 | 只看该作者
martinhu 发表于 2021-7-15 18:49
你这个SPI是接收中断???明明是查询啊,你可以看看驱动库里面主机和从机是怎么操作的,虽然那个写的比较 ...

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

使用特权

评论回复
10
tayouxunmeng|  楼主 | 2021-7-16 11:24 | 只看该作者
本帖最后由 tayouxunmeng 于 2021-8-13 11:05 编辑
tayouxunmeng 发表于 2021-7-15 19:39
放接收中断里也试过,除了第一个数据,其他数据都接收不正确。而且SPI1的寄存器也出现了上面图片所示的标 ...

能加个好友吗,帮我看下程序,现在能接收到数据,但是除了第一个数据外其他都错了

使用特权

评论回复
11
zc941118| | 2021-7-17 16:18 | 只看该作者
看了你两个关于spi的问题,,有个人已经跟你讲了原因 。基本已经讲的很清楚了,应该是华大的FAE,但是你还是解决不了,听一句劝,华大的片子你把握不住!要么换片,要么换人!

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

11

主题

25

帖子

0

粉丝