1、STM32F407的SPI1的波特率最高,但也只能到37.5Mbits/s。和SPI从设备交互时,不能只看从设备的SPI能力,得按主从设备的低限确定系统的整体波特率;
2、SPI+DMA时,发送和接收都会很快,从波形看,字节间几乎没有明显的间隔。但在读取从设备的地址空间时,从设备往往需要一定的时间准备数据,如果主设备读取太快,从设备的数据准备时间不足,会导致读取错误。此时,可不使用DMA,而是采用阻塞式或中断式SPI收发函数。经测试HAL_SPI_TransmitRecieve()会在字节间有约0.8us的空档;HAL_SPI_Transmit()会快些,间隔大约0.1us;
3、SPI+DMA的另一个问题就是:CPU调用DMA函数后并不会等待数据传输完成,而是直接运行后续程序,这就给拉高片选(NSS)以及得到的数据做后续处理带来问题,比如SPI还未传输完就拉高了NSS,或者还没完全读出数据就拿来做判断处理。于是为了解决这些问题,还得用定时器做中断拉高NSS及开始后续处理等,反而麻烦。而不使用DMA,采用阻塞式或中断式SPI收发函数则可避免这一问题;
3、SPI从设备往往需要主设备在通信的开头几个字节里写入命令和地址,如果需要往一个地址开始写入大量数据,且需要根据情况从不同的数组中取数,那就可以采用”先发字头再发数据“的方法(而且使用Transmit函数比较快):
void Write_Data(uint32_t Addr, uint8_t* pBuf, uint16_t len)
{
HAL_GPIO_WritePin(W5100S_SCS_GPIO_Port, W5100S_SCS_Pin, GPIO_PIN_RESET); //turn W5100S SCS Low
write_cmd[0]=0xF0;
write_cmd[1]=(Addr & 0xFF00) >> 8;
write_cmd[2]=(Addr & 0x00FF) >> 0;
HAL_SPI_Transmit(&hspi1,write_cmd,3,1);
HAL_SPI_Transmit(&hspi1,pBuf,len,1);
HAL_GPIO_WritePin(W5100S_SCS_GPIO_Port, W5100S_SCS_Pin, GPIO_PIN_SET);
}
4、”先发字头再发数据“的方法不适用于用TransmitReceive()函数从从设备读取大量数据,貌似是两次收发间隔太长,或者TransmitReceive()函数问题?读取数据时只能用TransmitReceive()函数,用Receive()在两线式主设备下,还时会被转为TransmitReceive()函数;
5、使用TransmitReceive()函读取数据的量比较大时,可直接在接收区头部写入”字头“,将接收和发送区地址都设为该接收区,从而避免使用其他的发送地址而导致访问越界!(调试过程中,接收256字节后总是卡住,估计有可能是用了一个10字节的数组作为发送字头的地址,导致TransmitReceive()函读访问越界)
void Read_Data(uint32_t Addr, uint8_t* pBuf, uint16_t len)
{
HAL_GPIO_WritePin(W5100S_SCS_GPIO_Port, W5100S_SCS_Pin, GPIO_PIN_RESET); //turn W5100S SCS Low
pBuf[0]=0x0F;
pBuf[1]=(Addr & 0xFF00) >> 8;
pBuf[2]=(Addr & 0x00FF) >> 0;
HAL_SPI_TransmitReceive(&hspi1,pBuf,pBuf,(len+3),2);
HAL_GPIO_WritePin(W5100S_SCS_GPIO_Port, W5100S_SCS_Pin, GPIO_PIN_SET);
}