【转】GD32105R例程---SPI收发函数测试

[复制链接]
1554|10
手机看帖
扫描二维码
随时随地手机跟帖
Elric_QZH|  楼主 | 2015-8-30 09:14 | 显示全部楼层 |阅读模式
    SPI,是一种高速的,全双工,同步的通信总线,接口简单,利于硬件设计与实现。采用主从模式架构,支持多从设备应用。时钟速度快,目前应用中的数据速率可达几Mbps,且没有系统开销。相对抗干扰能力强,传输稳定,正是出于这种简单易用的特性,GD32 105R_STAR芯片也集成了这种通信协议。

1、SPI在一般应用中有4根信号线:

    MOSI:主器件数据输出,从器件数据输入。

    MISO:主器件数据输入,从器件数据输出。

    SCK: 时钟信号,由主设备控制发出。

    /SS: 从设备选择信号,由主设备控制。 根据此信号可以决定能连接到总线上从设备的数量。

    2、根据时钟极性(CPOL)及相位(CPHA)不同可以组合成4种工作模式:

    SPI0:CPOL=0,CPHA=0

    SPI1:CPOL=0,CPHA=1

    SPI2:CPOL=1,CPHA=0

    SPI3:CPOL=1,CPHA=1

Elric_QZH|  楼主 | 2015-8-30 09:15 | 显示全部楼层
    根据不同外设模块的需求,来对GD32 105R_STAR的SPI外设进行不同的匹配设置,楼主根据PT6315的外设需求,进行如下初始化配置:
view plaincopy to clipboardprint?
/*
****************************************************************************
*函数名称:void  Pt_SPIInit(void)
*函数功能:PT6315 SPI 总线初始化
*日期:2015 4 6
*版本:V1.0
*作者:yrj
*SPI_FirstBit_MSB;//高位在前 PT6315手册对应改为低位在前。
****************************************************************************
*/  
// PB12/SPI2NSS  PB13/SPI2CLK  PB14/SPI2MISO PTOUT  PB15/SPI2MOSI PTIN  
void Pt_SPIInit(void)  
{   
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO,ENABLE);  
  GPIO_InitTypeDef GPIO_InitStructure;  
  //PB14 (MISO)浮空输入  
  GPIO_InitStructure.GPIO_Pin=GPIO_Pin_14;  
  GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;  
  GPIO_Init(GPIOB,&GPIO_InitStructure);  
  //PB15 MOSI PB13 SCK 复用推挽输出(外设总线用)  
  GPIO_InitStructure.GPIO_Pin=GPIO_Pin_13|GPIO_Pin_15;  
  GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;  
  GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;  
  GPIO_Init(GPIOB,&GPIO_InitStructure);  
  //PB12 NSS,PB11 WP写保护普通推挽输出  本实验用软件控制NSS(主从设备的选择控制端)  
  GPIO_InitStructure.GPIO_Pin=GPIO_Pin_12;  
  GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;  
  GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;  
  GPIO_Init(GPIOB,&GPIO_InitStructure);  
  Pt_Disable(); //PB12/NSS  失能  
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);  
view plaincopy to clipboardprint?
  SPI_InitTypeDef SPI_InitStructure;  
  SPI_I2S_DeInit(SPI2);  
  SPI_Cmd(SPI2,DISABLE);//在改变CPOL/CPHA位之前必须清除SPE位将SPI禁止  
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;//全双工  
  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;//主模式  
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;//8位帧结构  
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;//时钟悬空低  
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;//数据捕获与第1个时钟沿  
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;//软件控制NSS信号  
  SPI_InitStructure.SPI_BaudRatePrescaler =SPI_BaudRatePrescaler_8;//比特率预分频值为8。最大18MHz  
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_LSB; /*SPI_FirstBit_MSB; //高位在前 7 7 与PT6315手册对应改为低位在前。*/   
  SPI_InitStructure.SPI_CRCPolynomial = 7;//定义用于CRC值计算的多项式 7  
  SPI_Init(SPI2, &SPI_InitStructure);  
  SPI_Cmd(SPI2,ENABLE);   
}  
view plaincopy to clipboardprint?
        <p>  
                此外由于SPI是一种全双工的同步通信总线,所以在进行数据通信中收发是同步进行的,为了在实际的函数调用中简单明了,针对GD32 105R_STAR SPI数据的收发,楼主在此分别设计了两个函数来进行数据的发送和接收。  
        </p>  
  
        <p>  
            SPI发送函数:  
        </p>  
  
<pre class="c" name="code">/*
****************************************************************************
*函数名称:uint8 Send_Byte(void)
*函数功能:通过硬件SPI发送一个字节
*日期:2015 4 6
*版本:V1.0
*作者:yrj
****************************************************************************
*/  
uint32 CsyCnt;  
void SendPt_Byte(uint8 data)   
{  
  SPI_I2S_SendData(SPI2, data);//发送数据  
  CsyCnt = 0;  
  while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE)==RESET) //等待数据发送完毕  
  {  
   CsyCnt++;  
   if(CsyCnt>10000)   break ;  
  }  
  SPI_I2S_ClearFlag(SPI2,SPI_I2S_FLAG_TXE);  //清除发送完成   
  //////////// 测试是否正常写入  
  if( CsyCnt >10000)  // 有故障  
  {  
    /*重新初始化*/  
    Pt_SPIInit();  
    /*重新发送数据*/  
    SPI_I2S_SendData(SPI2, data);/*发送数据*/  
    while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE)==RESET); /*等待数据发送完毕*/  
  }  
  while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE)==RESET); /*等待数据发接收完毕*/  
    SPI_I2S_ReceiveData(SPI2);  /*接收返回的数据,在此无实意*/         
}  
</pre>  
<pre class="c" name="code">SPI接收函数:  
</pre>  
<pre class="c" name="code"><pre class="c" name="code">/*
****************************************************************************
*函数名称:uint8 Get_Byte(void)
*函数功能:通过硬件SPI接口接收一个字节到处理器   
*日期:2015 4 6
*版本:V1.0
*作者:yrj
****************************************************************************
*/  
uint8 GetPt_Byte(void)  
{   
  while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE)==RESET); /*等待数据发送完毕*/  
  SPI_I2S_SendData(SPI2, 0);/*发送该数据易产生时钟,数据本身无意义。*/  
   
  while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE)==RESET);/*等待接收完成*/  
  return SPI_I2S_ReceiveData(SPI2);/*返回最近接收到的数据*/   
}</pre>  
        <p>  
            <br>  
        </p>  
</pre>  

使用特权

评论回复
justperky| | 2015-8-30 23:03 | 显示全部楼层
不错,纯硬件的SPI例程,不是模拟SPI的,很有用,收藏了!

使用特权

评论回复
蜕变吧| | 2015-8-31 11:20 | 显示全部楼层
主持下,软件模拟SPI用过,速度有点慢

使用特权

评论回复
eggbiscuit| | 2015-8-31 21:53 | 显示全部楼层
不错,收藏了。等有空了烧进去看看

使用特权

评论回复
Elric_QZH|  楼主 | 2017-11-25 09:47 | 显示全部楼层
蜕变吧 发表于 2015-8-31 11:20
主持下,软件模拟SPI用过,速度有点慢

一般场合,不是通讯场合,模拟也够用了。

使用特权

评论回复
chuntian2016| | 2017-11-27 23:27 | 显示全部楼层
SPI,是一种高速的,全双工,同步的通信总线,接口简单,利于硬件设计与实现。

使用特权

评论回复
vivilzb1985| | 2017-11-27 23:41 | 显示全部楼层
作为SPI总线的设计的,注意两边的通讯速率保持一致的

使用特权

评论回复
zya888| | 2017-11-29 10:21 | 显示全部楼层
硬件SPI可以更省资源

使用特权

评论回复
zb0830| | 2017-11-29 10:28 | 显示全部楼层
好东西,谢谢分享

使用特权

评论回复
1044132648| | 2017-11-30 16:05 | 显示全部楼层
想问下楼主,从机发送无关数据启动时钟后,从机会进入中断吗

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

20

主题

133

帖子

0

粉丝