乐鑫技术交流
直播中

刘英

7年用户 1093经验值
私信 关注
[问答]

求助,关于esp8266使用hspi做从机(slave)遇到的疑问求解

大家好,我在官方提供的ESP8266_NONOS_SDK  V1.5.4中的AT工程基础上进行开发,我尝试使用esp8266的HSPI做为从机(Hspi slave)接收外部mcu发来的数据,但是在实现的过程中遇到一些问题。
我根据8J-ESP8266__SPI-WiFi_Passthrough_2-Interrupt_Mode__CN_v0.1.pdf文档中spi从机通信协议的说明,把外部mcu(spi 主机)设置成spi mode0,通信速率设置为500K,每次发送34个字节(命令0x02+地址0x00+32字节数据)。设置完成后,我通过逻辑分析仪捕获spi主机输出的波形,是我期望输出的波形。
然后,我在ESP8266程序里做了如下工作:
1.有用户程序初始化函数里初始化了spi从机。代码如下:
void ICACHE_FLASH_ATTR user_init(void)
{
    led_gpio_init();
    user_link_led_timer_init();
    at_init();
    at_port_print("rnreadyrn");
    spi_slave_init(HSPI, 32);
}

spi_slave_init函数内容是采用官方默认的,并没有做修改。
2.在spi的从机中断函数void spi_slave_isr_handler(void *para)中添加了一些打印语句,代码如下:

void spi_slave_isr_handler(void *para)
{
    uint32 regvalue,calvalue;
        static uint8 state =0;
    uint32 recv_data,send_data;
    os_printf("spi_slave_isrn");
    if(READ_PERI_REG(0x3ff00020)&BIT4)
    {
        //following 3 lines is to clear isr signal
            CLEAR_PERI_REG_MASK(SPI_SLAVE(SPI), 0x3ff);
    }
    else if(READ_PERI_REG(0x3ff00020)&BIT7)
    { //bit7 is for hspi isr,
        os_printf("hspi ISRn");
        regvalue=READ_PERI_REG(SPI_SLAVE(HSPI));
        CLEAR_PERI_REG_MASK(SPI_SLAVE(HSPI),//关闭中断使能
                            SPI_TRANS_DONE_EN|
                            SPI_SLV_WR_STA_DONE_EN|
                            SPI_SLV_RD_STA_DONE_EN|
                            SPI_SLV_WR_BUF_DONE_EN|
                            SPI_SLV_RD_BUF_DONE_EN);
        SET_PERI_REG_MASK(SPI_SLAVE(HSPI), SPI_SYNC_RESET);
        CLEAR_PERI_REG_MASK(SPI_SLAVE(HSPI),//清中断标志
                            SPI_TRANS_DONE|
                            SPI_SLV_WR_STA_DONE|
                            SPI_SLV_RD_STA_DONE|
                            SPI_SLV_WR_BUF_DONE|
                            SPI_SLV_RD_BUF_DONE);
        SET_PERI_REG_MASK(SPI_SLAVE(HSPI),  //中断使能
                                SPI_TRANS_DONE_EN|
                                SPI_SLV_WR_STA_DONE_EN|
                                SPI_SLV_RD_STA_DONE_EN|
                                SPI_SLV_WR_BUF_DONE_EN|
                                SPI_SLV_RD_BUF_DONE_EN);
        if(regvalue&SPI_TRANS_DONE)//传输完成?
        {
            os_printf("translate donen");
        }
        if(regvalue&SPI_SLV_WR_BUF_DONE)//写从机buff完成?
        {
            os_printf("write buff donen");
            GPIO_OUTPUT_SET(0, 0);
            //将寄存器接收数据搬入内存
            idx=0;
            while(idx<8)//取8次,每次取出一个32位数,共取出32*8=256位,也即32个字节
            {
                recv_data=READ_PERI_REG(SPI_W0(HSPI)+(idx<<2));
                spi_data[idx<<2] = recv_data&0xff;
                spi_data[(idx<<2)+1] = (recv_data>>8)&0xff;
                spi_data[(idx<<2)+2] = (recv_data>>16)&0xff;
                spi_data[(idx<<2)+3] = (recv_data>>24)&0xff;
                idx++;
            }
            //add system_os_post here
            GPIO_OUTPUT_SET(0, 1);//用于通知主机,数据已经读取完成
            os_printf("receive finishn");

        }
        if(regvalue&SPI_SLV_RD_BUF_DONE)
        {
            os_printf("read buff donen");
        //it is necessary to call GPIO_OUTPUT_SET(2, 1), when new data is preped in SPI_W8-15 and needs to be sended.
            GPIO_OUTPUT_SET(2, 0);
        //add system_os_post here
        //system_os_post(USER_TASK_PRIO_1,WR_RD,regvalue);

        }
    }
    else if(READ_PERI_REG(0x3ff00020)&BIT9)
    { //bit7 is for i2s isr,
        os_printf("3n");
    }
}

在进行主机从机通信测试时,用主机一次发送34字节(命令0x02+地址0x00+32字节数据),结果发现os_printf("hspi ISRn");被执行了十几次(约12次,每次打印出的字符串条数有差异),也即    else if(READ_PERI_REG(0x3ff00020)&BIT7)判断条件被触发约12次,而每次对应 if(regvalue&SPI_TRANS_DONE)条件也均会满足,os_printf("translate donen");会执行并打印字符串。但是 if(regvalue&SPI_SLV_WR_BUF_DONE)条件总是不满足。当我尝试用主机发送读数据指令(0x03,0x00)时,得到的效果也如上所述,并不会触发if(regvalue&SPI_SLV_RD_BUF_DONE)。我尝试打印出regvalue的值,得到的结果为0x66f003f0,每次得到的结果不同,但是最后的三个数字总是3f0。


我现在的疑问是
1.主机一次发送34字节时,为什么会触发进入中断函数十几次,而不是一次,不是34次?
2.为什么SPI_SLV_WR_BUF_DONE和SPI_SLV_RD_BUF_DONE条件总是不被触发?是不是我哪里没有配置好,或者测试的方法有误?

另外,我尝试过用HSPI做为master主动往外发出数据,用逻辑分析仪观察波形,可以得到相应的波形,可以确定hspi的引脚是没有弄错的。


回帖(1)

胡秋阳

2024-7-9 16:04:52
在这种情况下,我建议您按照以下步骤进行操作:

1. 确保您的ESP8266硬件连接正确。检查HSPI的MISO、MOSI、CLK和CS引脚是否正确连接到外部MCU的相应引脚。

2. 在您的ESP8266程序中,确保您已经正确配置了HSPI接口。这包括设置SPI模式(在您的情况下是Mode 0)、通信速率(500Kbps)以及初始化HSPI接口。

3. 在您的程序中实现SPI从机接收数据的逻辑。这通常包括配置GPIO为输入模式,然后在SPI从机接收到数据时读取数据。您可以使用ESP8266的SPI接口库函数来实现这一点。

4. 在接收到数据后,您可以根据需要对数据进行处理。例如,您可以将接收到的数据存储在数组中,或者根据数据内容执行特定的操作。

5. 如果您在实现过程中遇到问题,可以尝试使用调试工具(如逻辑分析仪)来检查SPI通信是否正常。这可以帮助您确定问题是否出在硬件连接或软件实现上。


举报

更多回帖

发帖
×
20
完善资料,
赚取积分