首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >STM8作为SPI从站不能发送回数据

STM8作为SPI从站不能发送回数据
EN

Stack Overflow用户
提问于 2021-09-26 17:01:23
回答 2查看 416关注 0票数 1

我已经构建了一个带有STM8L的原型板,我希望它被使用并配置为一个SPI从属程序。我正在用树莓皮做师父来测试它。

为此,我使用ST提供的名为"STM8标准外设库“的库,但文档非常贫乏,不需要花费费用.

我可以在没有问题的情况下从Raspberry Pi发送数据,并在STM8上接收它,但我不能从MISO上的STM8上将任何数据发回给树莓。

有人知道我怎样才能把一些数据发回给Raspberry Pi大师吗?我的错误在哪里?

以下是主要代码:

代码语言:javascript
复制
void main(void)
{
  // GPIO
  GPIO_Init(GPIOA, GPIO_Pin_7, GPIO_Mode_Out_PP_Low_Fast);
  CLK_Config();
  

  // Set the MOSI and SCK at high level 
  GPIO_ExternalPullUpConfig(GPIOB, GPIO_Pin_6 | GPIO_Pin_5, ENABLE);
  
  SPI_DeInit(SPI1);

  SPI_Init(SPI1, SPI_FirstBit_LSB, SPI_BaudRatePrescaler_2, SPI_Mode_Slave,
           SPI_CPOL_Low, SPI_CPHA_2Edge, SPI_Direction_2Lines_FullDuplex,
           SPI_NSS_Hard, (uint8_t)0x07);

  SPI_BiDirectionalLineConfig(SPI1, SPI_Direction_Tx);


  // Enable SPI
  SPI_Cmd(SPI1, ENABLE);


  /* Infinite loop */
  while (1)
  {
    while(SPI_GetFlagStatus(SPI1, SPI_FLAG_BSY));

    // SPI polling
    if(SPI_GetFlagStatus(SPI1, SPI_FLAG_RXNE) == SET) {

      while(SPI_GetFlagStatus(SPI1, SPI_FLAG_BSY));
      
      GPIO_ToggleBits(GPIOA, GPIO_Pin_7);
      
      uint8_t data = SPI_ReceiveData(SPI1);

      while(SPI_GetFlagStatus(SPI1, SPI_FLAG_BSY));

      // I can't send back data here, it doesn't work
      SPI_SendData(SPI1, 0xFA);

      uint8_t test = SPI1->DR;

      GPIO_ResetBits(GPIOA, GPIO_Pin_7);
    }
  }
}


static void CLK_Config(void)
{
  /* Select HSE as system clock source */
  CLK_SYSCLKSourceSwitchCmd(ENABLE);
  CLK_SYSCLKSourceConfig(CLK_SYSCLKSource_HSI);
  
  /*High speed external clock prescaler: 1*/
  CLK_SYSCLKDivConfig(CLK_SYSCLKDiv_2);

  while (CLK_GetSYSCLKSource() != CLK_SYSCLKSource_HSI)
  {}

  /* Enable SPI clock */
  CLK_PeripheralClockConfig(CLK_Peripheral_SPI1, ENABLE);
}

和RPi简单代码:

代码语言:javascript
复制
#include <iostream>
#include <wiringPi.h>
#include <wiringPiSPI.h>

using namespace std;

int main()
{
    wiringPiSetup();
    wiringPiSPISetup(0, 50000);

    unsigned char data[] = {0x5A};

    wiringPiSPIDataRW(0, data, 2);

    std::cout<<data<<std::endl;


    return 0;

谢谢你的帮助!)

编辑:我认为错误在uC代码中,因为spi数据寄存器仍然包含主读后发送的数据。我不能改变它,即使是试图直接写在登记簿上。

另外:设备只包含一个SPI数据寄存器是正常的吗?如果它没有一个用于MOSI (Rx)和一个用于MISO(Tx),那么它怎么会是全双工呢?我觉得我对SPI有些不理解。我对这个串行协议不是很有经验。我以前主要使用I2C。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-09-27 15:38:09

我终于发现我的错误在哪里。

首先,我忘记在MISO引脚上配置拉拔电阻:

代码语言:javascript
复制
  // Set the MOSI and SCK at high level 
  GPIO_ExternalPullUpConfig(GPIOB, GPIO_Pin_6 | GPIO_Pin_5 | GPIO_Pin_7, ENABLE);

接下来,SPI配置是错误的。Rpi位于MSB中,而在LSB中为STM8,当需要位于第一个边缘时,相位处于第二边缘:

代码语言:javascript
复制
  SPI_Init(SPI1, SPI_FirstBit_MSB, SPI_BaudRatePrescaler_2, SPI_Mode_Slave,
           SPI_CPOL_Low, SPI_CPHA_1Edge, SPI_Direction_2Lines_FullDuplex,
           SPI_NSS_Hard, (uint8_t)0x07);

最后,这不是一个错误,而是一种不理想的测试方法:我与主机一起发送了0x81,但它是二进制的(0b10000001)。我应该发送一些异步消息,例如0x17 (0b00010111)。

以及完整的STM8代码:

代码语言:javascript
复制
#include "stm8l15x.h"
#include "stm8l15x_it.h"    /* SDCC patch: required by SDCC for interrupts */

static void CLK_Config(void);
void Delay(__IO uint16_t nCount);

void main(void)
{
  // GPIO
  GPIO_Init(GPIOA, GPIO_Pin_7, GPIO_Mode_Out_PP_Low_Fast);
  CLK_Config();
  

  // Set the MOSI and SCK at high level (I added MOSI)
  GPIO_ExternalPullUpConfig(GPIOB, GPIO_Pin_6 | GPIO_Pin_5 | GPIO_Pin_7, ENABLE);
  
  SPI_DeInit(SPI1);

  SPI_Init(SPI1, SPI_FirstBit_MSB, SPI_BaudRatePrescaler_2, SPI_Mode_Slave,
           SPI_CPOL_Low, SPI_CPHA_1Edge, SPI_Direction_2Lines_FullDuplex,
           SPI_NSS_Hard, (uint8_t)0x07);

  SPI_BiDirectionalLineConfig(SPI1, SPI_Direction_Tx);


  // Enable SPI
  SPI_Cmd(SPI1, ENABLE);


  /* Infinite loop */
  while (1)
  {
    while(SPI_GetFlagStatus(SPI1, SPI_FLAG_BSY));

    // SPI polling
    if(SPI_GetFlagStatus(SPI1, SPI_FLAG_RXNE) == SET) {

      // maybe this line is not necessary, I didn't have the time to test without it yet 
      while(SPI_GetFlagStatus(SPI1, SPI_FLAG_BSY);
      
      uint8_t data = SPI_ReceiveData(SPI1);

      while(SPI_GetFlagStatus(SPI1, SPI_FLAG_RXNE));
      
      if(data==0x82) SPI_SendData(SPI1, 0xCD);

      GPIO_ResetBits(GPIOA, GPIO_Pin_7);
    }
  }
}

/* Private functions ---------------------------------------------------------*/

static void CLK_Config(void)
{
  /* Select HSE as system clock source */
  CLK_SYSCLKSourceSwitchCmd(ENABLE);
  CLK_SYSCLKSourceConfig(CLK_SYSCLKSource_HSI);
  
  /*High speed external clock prescaler: 1*/
  CLK_SYSCLKDivConfig(CLK_SYSCLKDiv_2);

  while (CLK_GetSYSCLKSource() != CLK_SYSCLKSource_HSI)
  {}

  /* Enable SPI clock */
  CLK_PeripheralClockConfig(CLK_Peripheral_SPI1, ENABLE);
}

void Delay(__IO uint16_t nCount)
{
  /* Decrement nCount value */
  while (nCount != 0)
  {
    nCount--;
  }
}

/*******************************************************************************/



#ifdef  USE_FULL_ASSERT

void assert_failed(uint8_t* file, uint32_t line)
{ 
  /* Infinite loop */
  while (1)
  {
  }
}
#endif

PS:

我在linux上,软件工具不适合我的操作系统,所以我使用了一些工具来进行开发。我认为它对某些人是有用的,所以我在这里补充如下:

首先,lib无法用SDCC编译,所以我使用了我在这里找到的修补程序:https://github.com/gicking/STM8-SPL_SDCC_patch

要上传到uC,我使用stm8flash和ST链接V2:https://github.com/vdudouyt/stm8flash

我也遇到了一些困难,无法找到STM8L的库。这里是:https://www.st.com/en/embedded-software/stsw-stm8016.html

PS2:

我知道要回答与硬件有关的问题并不容易。有没有人知道有哪些网站对这类问题有更详细的说明?

票数 1
EN

Stack Overflow用户

发布于 2021-09-26 17:05:01

SPI要求主程序提供时钟。如果您希望从服务器发送什么--您的主必须发送一些虚拟数据来为从服务器生成时钟。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69337091

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档