你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32F030的硬件SPI从模式,从机应答时丢失首个字节?

[复制链接]
Dylan疾风闪电 提问时间:2015-1-5 20:36 /
如题,主机发送{0,0,0,0},想要得到的从机应答{0x00,0x70,0x53,0xb0};实际获取的应答为{0x70,0x53,0xb0,0x00}。

中断程序如下:

  1. uint32_t spi_TxBuff = 0x00000000;

  2. uint32_t DataRegs[10];
  3. #define OFFSET_0                        24
  4. uint8_t offsetbits = OFFSET_0;

  5. uint8_t rw_Flag;//0x00:read,0x80:write,=data & 0x80;
  6. uint8_t reg_Address;//=data & 0x7F;

  7. void SPI2_IRQHandler(void)
  8. {
  9.         uint8_t data;
  10.        
  11.         if (SPI2->SR & 0x1)
  12.         {
  13.                 data = SPI_ReceiveData8(SPI2);
  14.                
  15.                 rw_Flag = data & 0x80;
  16.                 reg_Address = data & 0x7F;
  17.                
  18.                 if (rw_Flag != 0x00)
  19.                 {
  20.                         //write to regs
  21.                        
  22.                         //SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_TXE, DISABLE);
  23.                 }
  24.                 else
  25.                 {
  26.                         //read from regs       
  27.                         if (reg_Address < 10)
  28.                         {
  29.                                 if (offsetbits == OFFSET_0)
  30.                                 {
  31.                                         spi_TxBuff = DataRegs[reg_Address];
  32.                                 }
  33.                         }
  34.                         else
  35.                         {
  36.                                 spi_TxBuff = 0x00FFFFFF;
  37.                         }
  38.                 }
  39.         }
  40.        
  41.         if (SPI2->SR & 0x2)
  42.         {
  43.                 SPI_SendData8(SPI2, (0xFF & (spi_TxBuff >> offsetbits)));
  44.                
  45.                 if (offsetbits >= 8)
  46.                 {
  47.                         offsetbits -= 8;
  48.                 }
  49.                 else
  50.                 {
  51.                         offsetbits = OFFSET_0;
  52.                 }
  53.         }
  54. }

  55. void EXTI4_15_IRQHandler(void)
  56. {
  57.         EXTI->PR ^= (uint16_t)~EXTI_Line11;

  58.         offsetbits = OFFSET_0;
  59. }
复制代码


收藏 评论15 发布时间:2015-1-5 20:36

举报

15个回答
Dylan疾风闪电 回答时间:2015-1-5 20:42:42
本帖最后由 Dylan疾风闪电 于 2015-1-5 20:44 编辑

SPI的主/从的初始化代码:
  1. void connectSPI1ToExt(uint16_t BaudRatePCLKDiv, uint16_t CPOL, uint16_t CPHA_Edge)
  2. {
  3.         GPIO_InitTypeDef GPIO_InitStructure;
  4.         SPI_InitTypeDef  SPI_InitStructure;

  5.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);

  6.         //SPIx_SCK 主模式 推挽复用输出
  7.         //SPIx_MOSI 全双工模式/主模式 推挽复用输出
  8.         //SPIx_MISO 全双工模式/主模式 浮空输入或带上拉输入
  9.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  10.         GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  11.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  12.         GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  13.         GPIO_InitStructure.GPIO_Pin = SPLIT_DEFINE_PIN(X2_CLK);
  14.         GPIO_Init(SPLIT_DEFINE_PORT(X2_CLK), &GPIO_InitStructure);
  15.         SetAF_SPI1_SCK;
  16.        
  17.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  18.         GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  19.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  20.         GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  21.         GPIO_InitStructure.GPIO_Pin = SPLIT_DEFINE_PIN(X2_SDI);
  22.         GPIO_Init(SPLIT_DEFINE_PORT(X2_SDI), &GPIO_InitStructure);
  23.         SetAF_SPI1_MOSI;

  24.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  25.         GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  26.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  27.         GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  28.         GPIO_InitStructure.GPIO_Pin = SPLIT_DEFINE_PIN(X2_SDO);
  29.         GPIO_Init(SPLIT_DEFINE_PORT(X2_SDO), &GPIO_InitStructure);
  30.         SetAF_SPI1_MISO;

  31.         //
  32.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
  33.         RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1, ENABLE);
  34.         RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1, DISABLE);

  35.         SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  36.         SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
  37.         SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
  38.         SPI_InitStructure.SPI_CPOL = CPOL;
  39.         SPI_InitStructure.SPI_CPHA = CPHA_Edge;
  40.         SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
  41.         SPI_InitStructure.SPI_BaudRatePrescaler = BaudRatePCLKDiv;
  42.         SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
  43.         SPI_InitStructure.SPI_CRCPolynomial = 7;
  44.         SPI_Init(SPI1, &SPI_InitStructure);
  45.         SPI_CalculateCRC(SPI1,DISABLE);

  46.         SPI_RxFIFOThresholdConfig(SPI1, SPI_RxFIFOThreshold_QF);

  47.         SPI_Cmd(SPI1, ENABLE);
  48. }

  49. void connectSPI2SlaveToExt(uint16_t BaudRatePCLKDiv, uint16_t CPOL, uint16_t CPHA_Edge)
  50. {
  51.         GPIO_InitTypeDef GPIO_InitStructure;

  52.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);

  53.         //SPIx_SCK 从模式 浮空输入
  54.         //SPIx_MOSI 全双工模式/从模式 浮空输入或带上拉输入
  55.         //SPIx_MISO 全双工模式/从模式 推挽复用输出
  56.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  57.         GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  58.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  59.         GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  60.         GPIO_InitStructure.GPIO_Pin = SPLIT_DEFINE_PIN(X3_CLK_S);
  61.         GPIO_Init(SPLIT_DEFINE_PORT(X3_CLK_S), &GPIO_InitStructure);
  62.         SetAF_SPI2_SCK;

  63.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  64.         GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  65.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  66.         GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  67.         GPIO_InitStructure.GPIO_Pin = SPLIT_DEFINE_PIN(X3_SDI_S);
  68.         GPIO_Init(SPLIT_DEFINE_PORT(X3_SDI_S), &GPIO_InitStructure);
  69.         SetAF_SPI2_MOSI;

  70.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  71.         GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  72.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  73.         GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  74.         GPIO_InitStructure.GPIO_Pin = SPLIT_DEFINE_PIN(X3_SDO_S);
  75.         GPIO_Init(SPLIT_DEFINE_PORT(X3_SDO_S), &GPIO_InitStructure);
  76.         SetAF_SPI2_MISO;
  77.        
  78.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  79.         GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  80.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  81.         GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  82.         GPIO_InitStructure.GPIO_Pin = SPLIT_DEFINE_PIN(X3_CS_S);
  83.         GPIO_Init(SPLIT_DEFINE_PORT(X3_CS_S), &GPIO_InitStructure);
  84.         SetAF_SPI2_NSS;

  85.         //寄存器操作
  86.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
  87.         RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2, ENABLE);
  88.         RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2, DISABLE);

  89.         /*---------------------------- SPIx CR1 Configuration ------------------------
  90.          *
  91.          * [15]BIDIMode(双向数据模式使能) = 0 :选择2线的单向数据模式(1:选择单线双向数据模式)。
  92.          * [14]BIDIOE(双向模式输出使能) = 0 :输出禁止,只收模式(1:输出使能,只发模式)。
  93.          * *注* BIDIOE和BIDIMode决定了通讯的“双线单向模式”、“单线双向模式”和“单线单向模式”。
  94.          * [13]CRCEN(硬件CRC使能) = 0 :禁用CRC计算(1:CRC计算使能)。
  95.          * [12]CRCNEXT(下一个发送CRC) = 0 :下个发送的值来自发送缓冲器(1:下个发送的值来自CRC寄存器).
  96.          * [11]CRCL(CRC的数据长度) = x (0:8位CRC长度)(1:16位CRC长度).
  97.          * [10]RxONLY = 0 :全双工(1:只收模式)。
  98.          * [9]SSM(软件从机管理) = 0 :禁止软件从设备管理(1:启用软件从设备管理,NSS引脚的电平由SSI位决定)。
  99.          * [8]SSI(内部从设备选择) = x 决定了NSS引脚的电平。
  100.          * [7]LSBFirst(帧格式) = 0 :先发送MSB(1:先发送LSB)。
  101.          * [6]SPE(SPI使能) = 0 :禁止SPI设备(1:开启SPI设备)。
  102.          * [5:3]BR(波特率控制) = value (通信速率为{fPCLK/(2^[value+1)]})。
  103.          * [2]MSTR(主设备选择) = 0 :配置为从设备(1:配置为主设备)。
  104.          * [1]CPOL(时钟极性) = value (0:空闲状态下SCK保持低电平)(1:空闲状态SCK保持高电平)。
  105.          * [0]CPHA(时钟相位) = value (0:第一个时钟边沿开始数据采样)(1:第二个时钟边沿开始数据采样)。
  106.          *---------------------------------------------------------------------------*/

  107.         SPI2->CR1 &= 0x0000;
  108.         SPI2->CR1 |= (uint16_t)(BaudRatePCLKDiv | CPOL | CPHA_Edge);

  109.         /*---------------------------- SPIx CR2 Configuration ------------------------
  110.          *
  111.          * [11:8]DS(数据长度) = 0111b :8位(0011b~1111b:4位~16位数据长度)。
  112.          *---------------------------------------------------------------------------*/
  113.         SPI2->CR2 &= 0xF0FF;
  114.         SPI2->CR2 |= 0x0700;
  115.   
  116.         /*---------------------------- SPIx CRCPOLY Configuration --------------------
  117.          *
  118.          * [15:0]CRCPOLY(数据长度) = 0x0007 :默认的复位值是0x0007。(复位过后可忽略)
  119.          *---------------------------------------------------------------------------*/
  120.         //SPI2->CRCPR = 0x0007;

  121.         /*---------------------------- Activate the SPI mode -------------------------
  122.          *
  123.          * [11]I2SMODE(I2S模式选择) = 0 :选择SPI模式(选择I2S模式)。
  124.          *---------------------------------------------------------------------------*/
  125.         SPI2->I2SCFGR &= 0xF7FF;       

  126.         SPI_RxFIFOThresholdConfig(SPI2, SPI_RxFIFOThreshold_QF);

  127.         SPI_Cmd(SPI2, ENABLE);
  128. }
复制代码


Dylan疾风闪电 回答时间:2015-1-5 20:52:29
主循环部分代码:
  1. uint8_t temp[20];
  2. ......

  3. int main()
  4. {
  5.         NVIC_InitTypeDef NVIC_InitStructure;

  6.         ......

  7.         connectSPI1ToExt(SPI_BaudRatePrescaler_32, SPI_CPOL_Low, SPI_CPHA_1Edge);

  8.         connectSPI2SlaveToExt(SPI_BaudRatePrescaler_32, SPI_CPOL_Low, SPI_CPHA_1Edge);
  9.         SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_RXNE, ENABLE);       
  10.         SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_TXE, ENABLE);

  11.         //Interrupts
  12.         NVIC_InitStructure.NVIC_IRQChannel = SPI2_IRQn;
  13.         NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
  14.         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  15.         NVIC_Init(&NVIC_InitStructure);

  16.         NVIC_InitStructure.NVIC_IRQChannel = EXTI4_15_IRQn;
  17.         NVIC_InitStructure.NVIC_IRQChannelPriority = 1;
  18.         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  19.         NVIC_Init(&NVIC_InitStructure);

  20.         while(1)
  21.         {
  22.                 DELAY_MS(500);               
  23.                 SPI1_SS_Low;
  24.                 DELAY_MS(10);
  25.                        
  26.                 for(int i=0; i<4; i++)
  27.                 {
  28.                         temp[i] = 0;
  29.                                
  30.                         while (!(SPI1->SR & 0x2));               
  31.                         SPI_SendData8(SPI1, 0x00);
  32.                        
  33.                         while (!(SPI1->SR & 0x1));               
  34.                         temp[i] = SPI_ReceiveData8(SPI1);
  35.                 }
  36.                        
  37.                 DELAY_MS(10);
  38.                 SPI1_SS_High;;
  39.                 DELAY_MS(500);
  40.         }
  41. }
复制代码
Dylan疾风闪电 回答时间:2015-1-5 20:59:18
请各位帮忙看一下,中断处理函数是不是存在什么问题?
因为从设备启用了硬件NSS,所以在片选为高的情况下,硬件应答是0xFF;同时在片选上升沿通过EXTI中断复位偏移量(offsetbits)。
----------------------------------------------------------------------------------------------------
收到数据0x00后,依次发送spi_TxBuff的【31:24】【23:16】【15:8】【7:0】。
Dylan疾风闪电 回答时间:2015-1-12 16:43:45
自己顶一下,哪位高工来看一下,这个问题怎么解决?
6874577 回答时间:2015-1-13 12:48:25
这个问题怎么解决?
Dylan疾风闪电 回答时间:2015-1-13 16:40:21
6874577 发表于 2015-1-13 12:48
这个问题怎么解决?

我就是想知道啊!不知道程序哪边有问题,重点怀疑是中断函数中的处理机制。
回答时间:2015-1-13 17:40:47
在SPI发送中加断点,看一下发送的时候的spi_TxBuff数据是多少,另外看一下offsetbits值是多少。
Dylan疾风闪电 回答时间:2015-1-13 21:54:31
spi_TxBuff=0x007053b0;
offsetbits = 24;
mlxy123xy 回答时间:2015-1-14 00:16:39
从机应答丢失首字节,你试试从机响应的首字节加点延迟。
12下一页

所属标签

相似问题

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版