打印
[STM32F1]

SPI传输数据错位

[复制链接]
2850|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
我的血含铜|  楼主 | 2014-12-24 19:01 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
硬件:Mosi-mosi miso-miso sck-sck
从机:
u8 SPI1_Buffer_Tx[BufferSize] =                        
{        0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE
};
int main(void)                          
{
          RCC_Configuration();
        GPIO_Configuration();
        USART_Configuration();
        SPI_Configuration();
        GPIO_ResetBits(GPIOC,GPIO_Pin_3);
//        GPIO_ResetBits(GPIOA, GPIO_Pin_4);
        printf("OK,I'm Slave \r\n");
       
while(Tx_Counter < BufferSize)
{               
        while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)==RESET);
        SPI_I2S_SendData(SPI1,SPI1_Buffer_Tx[Tx_Counter]);                               
        while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE) ==RESET);               
        SPI1_Buffer_Rx[Rx_Counter] = SPI_I2S_ReceiveData(SPI1);               
        Tx_Counter++;
        Rx_Counter++;
}
                printf("\r\n The SPI1 has sended data below : \r\n");
                k=0;
                while(k<BufferSize)
                {
                        printf(" %0.2d \r ",SPI1_Buffer_Tx[k]);
                        k++;
                }

                printf("\r\n The SPI1 has received data below : \r\n");       
                k=0;       
                while(k<BufferSize)
                {
                        printf(" %0.2d \r ",SPI1_Buffer_Rx[k]);
                        k++;
                }
}
void SPI_Configuration(void)
{
    SPI1_conf();
//        SPI2_conf();

}
void SPI1_conf(void)
{
  SPI_InitTypeDef  SPI_InitStructure;
  SPI_Cmd(SPI1, DISABLE);
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;       //
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_LSB;//SPI_FirstBit_MSB;
  SPI_InitStructure.SPI_CRCPolynomial = 7;
  SPI_Init(SPI1, &SPI_InitStructure);
   /*Enable SPI1.NSS as a GPIO*/
  //SPI_SSOutputCmd(SPI1, ENABLE);
//  NVIC_SPI_Config();                           //启动NVIC
//  SPI_I2S_ITConfig(SPI1,SPI_I2S_IT_RXNE,ENABLE);
  SPI_Cmd(SPI1, ENABLE);
  SPI_I2S_ClearITPendingBit(SPI1, SPI_I2S_IT_RXNE);
//  spi1_cs_low;
}

void NVIC_SPI_Config(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel = SPI1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);   
}


void GPIO_Configuration(void)
{

                GPIO_Configuration_Slave();
                GPIO_Configuration_Utra1();
                LED_GPIO_Config();
                 
}
void LED_GPIO_Config(void)
{               
        /*定义一个GPIO_InitTypeDef类型的结构体*/
        GPIO_InitTypeDef GPIO_InitStructure;

        /*开启GPIOC的外设时钟*/
        RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE);

        /*选择要控制的GPIOC引脚*/                                                                                                                          
          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5;       

        /*设置引脚模式为通用推挽输出*/
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   

        /*设置引脚速率为50MHz */   
          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

        /*调用库函数,初始化GPIOC*/
          GPIO_Init(GPIOC, &GPIO_InitStructure);                  

        /* 关闭所有led灯        */
        GPIO_SetBits(GPIOC, GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5);         
}


void GPIO_Configuration_Slave(void)
{
    GPIO_InitTypeDef        GPIO_InitStructure;
          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_7;                  //CS SCK MOSI                 从机
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
          GPIO_Init(GPIOA , &GPIO_InitStructure);

          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;                                                   //miso
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;       
          GPIO_Init(GPIOA , &GPIO_InitStructure);

}

void GPIO_Configuration_Utra1(void)
{
    GPIO_InitTypeDef        GPIO_InitStructure;
          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                       
          GPIO_Init(GPIOA , &GPIO_InitStructure);
       
          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;                       
          GPIO_Init(GPIOA , &GPIO_InitStructure);
}


void RCC_Configuration(void)
{
        /* 定义枚举类型变量 HSEStartUpStatus */
        ErrorStatus HSEStartUpStatus;

          /* 复位系统时钟设置*/
          RCC_DeInit();
          /* 开启HSE*/
          RCC_HSEConfig(RCC_HSE_ON);
          /* 等待HSE起振并稳定*/
          HSEStartUpStatus = RCC_WaitForHSEStartUp();
        /* 判断HSE起是否振成功,是则进入if()内部 */
          if(HSEStartUpStatus == SUCCESS)
          {
            /* 选择HCLK(AHB)时钟源为SYSCLK 1分频 */
            RCC_HCLKConfig(RCC_SYSCLK_Div1);
            /* 选择PCLK2时钟源为 HCLK(AHB) 1分频 */
            RCC_PCLK2Config(RCC_HCLK_Div1);
            /* 选择PCLK1时钟源为 HCLK(AHB) 2分频 */
            RCC_PCLK1Config(RCC_HCLK_Div2);
            /* 设置FLASH延时周期数为2 */
            FLASH_SetLatency(FLASH_Latency_2);
            /* 使能FLASH预取缓存 */
            FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
            /* 选择锁相环(PLL)时钟源为HSE 1分频,倍频数为9,则PLL输出频率为 8MHz * 9 = 72MHz */
            RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
            /* 使能PLL */
            RCC_PLLCmd(ENABLE);
            /* 等待PLL输出稳定 */
            while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
            /* 选择SYSCLK时钟源为PLL */
            RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
            /* 等待PLL成为SYSCLK时钟源 */
            while(RCC_GetSYSCLKSource() != 0x08);
          }
          /* 打开APB2总线上的GPIOA时钟*/
          RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_USART1|RCC_APB2Periph_SPI1|RCC_APB2Periph_GPIOE, ENABLE);

        //RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

        RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);
        //RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR|RCC_APB1Periph_BKP|RCC_APB1Periph_WWDG, ENABLE);               
}

主机:
void SPI1_conf(void)
{
  SPI_InitTypeDef  SPI_InitStructure;
  SPI_Cmd(SPI1, DISABLE);
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;                   //SPI_CPOL_LOW
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;       //
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_LSB;//SPI_FirstBit_MSB;
  SPI_InitStructure.SPI_CRCPolynomial = 7;
  SPI_Init(SPI1, &SPI_InitStructure);
   /*Enable SPI1.NSS as a GPIO*/
  //SPI_SSOutputCmd(SPI1, ENABLE);
  SPI_Cmd(SPI1, ENABLE);
  SPI_I2S_ClearITPendingBit(SPI1, SPI_I2S_IT_RXNE);

//  spi1_cs_low;
}

main
{       
        while(1)
        {
                while(1)
                {
                    if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_5) == 0)
                        {
                                while(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_5)==0);
                                break;
                        }
                }
            Tx_Counter=0;
            Rx_Counter=0;
                while(Tx_Counter < BufferSize)
                {               
                        while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)==RESET);
                        SPI_I2S_SendData(SPI1,SPI1_Buffer_Tx[Tx_Counter]);
//                                delay();
                        while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE) ==RESET);               
                        SPI1_Buffer_Rx[Rx_Counter] = SPI_I2S_ReceiveData(SPI1);       
                        Tx_Counter++;
                        Rx_Counter++;
                }
                printf("\r\n The SPI1 has sended data below : \r\n");
                k=0;
                while(k<BufferSize)
                {
                        printf(" %0.2d \r ",SPI1_Buffer_Tx[k]);
                        k++;
                }
                printf("\r\n The SPI1 has received data below : \r\n");       
                k=0;       
                while(k<BufferSize)
                {
                        printf(" %0.2d \r ",SPI1_Buffer_Rx[k]);
                        k++;
                }
    }       
}
沙发
我的血含铜|  楼主 | 2014-12-24 19:02 | 只看该作者
测试时数据出现错位

使用特权

评论回复
板凳
airwill| | 2014-12-24 19:45 | 只看该作者
本帖最后由 airwill 于 2014-12-24 23:55 编辑

数据发生错误, 是 SPI 测试时的比较常见的问题, 表现在数据和实际的值移了一位.
原因是 SPI 的主从之间的时钟方式和脉冲方式设置错误. 也就是下面这两个 :
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;                   //SPI_CPOL_LOW
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;

你应该根据主从机之间的特性来确定, 根据特性查手册吧

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
我的血含铜 + 1 很给力!
地板
我的血含铜|  楼主 | 2014-12-24 21:24 | 只看该作者
airwill 发表于 2014-12-24 19:45
数据发生错误, 是 SPI 测试时的比较常见的问题, 表现在数据和实际的值移了一位.
原因是 SPI 的主从之间的时 ...

这个地方应该怎么改啊

使用特权

评论回复
5
elecintop| | 2014-12-28 19:46 | 只看该作者

测试时数据出现错位

使用特权

评论回复
6
小浣熊| | 2014-12-29 18:04 | 只看该作者
出现错位的原因是什么呢,找到了吗?

使用特权

评论回复
7
mikebing| | 2014-12-29 18:13 | 只看该作者
我的血含铜 发表于 2014-12-24 21:24
这个地方应该怎么改啊

等级太低不能发URL,去搜索一下SPI的四种传输模式大概你就能知道了。
改的话就找一下那两个参数在ST库中的定义,就知道该怎么改了

使用特权

评论回复
8
kekeke| | 2014-12-29 21:01 | 只看该作者
测试时数据出现错位

使用特权

评论回复
9
白丁野老| | 2014-12-30 21:00 | 只看该作者
我也来学习一下

使用特权

评论回复
10
我的血含铜|  楼主 | 2015-1-2 16:49 | 只看该作者
最后发现的问题是:分频太少,由于连线过长,频率过高,时钟波形走形,导致传送错位

使用特权

评论回复
11
小浣熊| | 2015-1-3 19:50 | 只看该作者
根据特性查手册吧

使用特权

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

本版积分规则

1

主题

4

帖子

0

粉丝