STM32之间SPI通信

来源:互联网 发布:ssh使用的端口号 编辑:程序博客网 时间:2024/06/10 03:39

    这几天实验室比较忙,所以博客这边停了一下,继续吧。

    继串口中断后,大家可以尝试单片机间串口通信,这里就不再多赘述。串口完了之后,我接着学的就是SPI通信了,作为hello moto公司推出的这种4线全双工通信,很节约PCB布局空间,但缺点就是没有指定的流控制,没有应答机制来确定信号收到与否,比I2C在硬件上要稍微复杂一点。

    话不多说,上程序最有助理解。下面是SPI通信的发送端的SPI初始化主程序。

void SPI_Configuration(void)
{
   //定义GPIO,SPI结构体
   GPIO_InitTypeDef GPIO_InitStructure;
   SPI_InitTypeDef  SPI_InitStructure;
   //开PA口复用时钟,初始化系统时钟
   SystemInit();
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO|RCC_APB2Periph_SPI1,ENABLE);
   //配置PA5,PA6,PA7即SPI1__SCK,SPI1_miso,SPI1_mosi
   GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
   GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
   GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
   GPIO_Init(GPIOA,&GPIO_InitStructure);
   //配置PC4即SPI1_NSS
   GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4;
   GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
   GPIO_Init(GPIOC,&GPIO_InitStructure);
   //配置SPI1
   SPI_InitStructure.SPI_Direction=SPI_Direction_2Lines_FullDuplex;   //全双工
   SPI_InitStructure.SPI_Mode=SPI_Mode_Master;                              //主机
   SPI_InitStructure.SPI_DataSize=SPI_DataSize_16b;                         //一次传送16位
   SPI_InitStructure.SPI_CPOL=SPI_CPOL_Low;  //无数据传输时时钟引脚保持低电平。死也没想到这里影响这么大,为什么改为High就会每复位一次,打印结果就变一次 ,若不是无奈改成手册里的例子,还不会发现是这里的问题
   SPI_InitStructure.SPI_CPHA=SPI_CPHA_2Edge;                      //第2时钟沿采样数据
   SPI_InitStructure.SPI_NSS=SPI_NSS_Soft;                                   //NSS为软件模式
   SPI_InitStructure.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_8;         //预分频值为8
   SPI_InitStructure.SPI_FirstBit=SPI_FirstBit_MSB;                           //高位先发送
   SPI_InitStructure.SPI_CRCPolynomial=7;                                     //CRC多项式计算,我也不知道是什么,官方例程以及很多开发历程都是这样写的
   SPI_Init(SPI1,&SPI_InitStructure);
   SPI_Cmd(SPI1,ENABLE);
}


//SPI读写函数

//SPI的读写在一起,百度解释是因为它的读写是同时的,我表示没看懂,求大神解释一下
u16 SPI_ReadWriteByte(u16 byte)
{
   u16 data;
   while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)!=SET); //等待发送缓冲器为空
   SPI_I2S_SendData(SPI1,byte);
   while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE)==RESET); //等待接收缓冲器有数据进来
   data= SPI_I2S_ReceiveData(SPI1);
   return data;

发送主机只要用一个循环去发送你想要发送的东西就行,就不附程序了。但要注意的是,每法送一个字符就要delay一下,让接收从机有足够时间处理发来的数据。

接下来是接收从机,用的是中断接收。

SPI初始化与上面的一样,只需添加以下一段中端配置模块就行。

 //进行SPI1的中断配置
   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
   NVIC_InitStructure.NVIC_IRQChannel = SPI1_IRQn;
   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //优先级为第0级
   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
   NVIC_Init(&NVIC_InitStructure);

至于中断的接收方法与串口中断的接收方法一样,也不再赘述。

整理一下,这次调试的两大疑问:

①为什么发送的时候将CPOL设为高就会每复位一次就在接受串口上打印出一个新值?

②为什么SPI的读写要写在一起??

    望大家多多发言,谢谢



原创粉丝点击