大家好,我在官方提供的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的引脚是没有弄错的。