我用的芯片是stm32f103zet6,实现两块板主从机全双工通信。
主机发送几个字节给从机,然后主机读从机,从机把刚才收到的数据返回给主机。
两块板都是用的spi1,一块板下载主机代码,一块板下载从机代码,硬件连线连好后,进行全双工读写测试。
连线方式如下:
主机 从机
CS (PA4) CS (PA4)
CLK (PA5) CLK (PA5)
MISO(PA6) MISO(PA6)
MOSI(PA7) MOSI(PA7)
GND GND
大家根据自己所用的芯片的数据手册进行连线即可。主从机的4条SPI线一一对应连线就行了,注意别忘了把两块板子共地。
我一开始没有用dma来做,也实现了主从机全双工通信,只是字节跟字节之前不是连续的,中间有间隔,这样无形之中降低了我的通信速率。我抓的波形如下图(18M通信速率,字节和字节之间间隔有2.5us的样子,后来我把代码精简了,不用库函数,直接用寄存器,也还是有一点几到两个us的间隔),所以应该不是软件问题。
STM32中文参考手册的第468页有一段对于连续和非连续的描述:
我读完也没有很理解,但是打算用DMA试一下。硬件连线方式同上边描述。
主机的片选配置成软件方式,主机发送数据之前,把片选拉低,发完数据之后,把片选拉高。从机的片选配置成硬件方式。主从机的CPOL和COHA要配置成一样。spi主从机通信时,时钟信号是由主机来提供,因此从机的通信速率可以不用管,配不配成和主机一样都可以。
SPI主从机配置代码如下:
void SPI1_master_configuration(void)
{
RCC->APB2ENR |= 1<<2 ; //PORTA时钟使能
RCC->APB2ENR |= 1<<12 ; //SPI1时钟使能
GPIOA->CRL &= 0X000FFFFF ;
GPIOA->CRL |= 0XBBB00000 ; //PA567复用
GPIOA->ODR |= 7<<5 ; //PA567上拉
RCC->APB2RSTR |= 1<<12; //SPI1 reset
RCC->APB2RSTR &= ~(1<<12); //SPI1 reset ok.
SPI1->CR1 |= 0<<10 ; //全双工模式
SPI1->CR1 |= 1<<9 ; //nss软件管理
SPI1->CR1 |= 1<<8 ; //nss高电平
SPI1->CR1 |= 1<<2 ; //SPI主机
SPI1->CR1 |= 0<<11 ; //数据格式:8bit
SPI1->CR1 |= 1<<1 ; //CPOL=1:空闲模式下SCK为高电平
SPI1->CR1 |= 1<<0 ; //CPHA=1:数据采样从第二个时钟沿开始
SPI1->CR1 |= 1<<3 ; //Fsck=Fcpu/4
SPI1->CR1 |= 0<<7 ; //MSBfirst
SPI1->CR2 |= 1<<1 ; //发送缓冲区DMA使能
SPI1->CR2 |= 1<<0 ; //接收缓冲区DMA使能
SPI1->CR1 |= 1<<6 ; //SPI设备使能
GPIOA->CRL &= 0XFFF0FF