STM32 SPI Esclavo enviar datos Problema

2

Estoy trabajando en un proyecto con el microcontrolador STM32F411. Se establece en el modo esclavo SPI y recibe datos sin ningún problema. Cuando quiero enviar datos a través del periférico spi, a veces funciona, pero la mayoría de las veces, los bits que trato de enviar son cambiados o se han enviado datos incorrectos. He configurado el periférico spi como se muestra en un ejemplo en los controladores periféricos estándar para este controlador y tampoco tengo una línea de selección de chip porque solo tengo un esclavo en el sistema.

¿Hay algún problema en mi configuración o relleno el búfer tx en un momento incorrecto?

Aquí está mi código:

void spi1_init(){
SPI_InitTypeDef  SPI_InitStruct;

spi1_gpio_init();

// Enable the SPI periph clock
RCC_APB2PeriphClockCmd(RCC_APB2ENR_SPI1EN, ENABLE);

// Set data size to 8b 
SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b;

SPI_I2S_DeInit(SPI1);
SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64; // 100MHz / 64 = 1.5625MHz
SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStruct.SPI_Mode = SPI_Mode_Slave;
SPI_InitStruct.SPI_NSS = SPI_NSS_Soft;
SPI_InitStruct.SPI_CRCPolynomial = 7;

// Mode 0 
SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low;
SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge;


// Init SPI 
SPI_Init(SPI1, &SPI_InitStruct);


//---------------------------------------------------------------------

spi1_interrupt_init();

//---------------------------------------------------------------------


   // Enable the SPI peripheral 
   SPI_Cmd(SPI1, ENABLE); 

 }


void spi1_gpio_init(void){
GPIO_InitTypeDef GPIO_InitStruct;

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

GPIO_PinAFConfig(GPIOB, GPIO_PinSource3, GPIO_AF_SPI1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource4, GPIO_AF_SPI1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_AF_SPI1);

GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3;
GPIO_Init(GPIOB, &GPIO_InitStruct);

GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4;
GPIO_Init(GPIOB, &GPIO_InitStruct);

GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5;
GPIO_Init(GPIOB, &GPIO_InitStruct);
}

void spi1_interrupt_init(void){
NVIC_InitTypeDef  NVIC_InitStruct;

// Configure the SPI interrupt priority 
NVIC_InitStruct.NVIC_IRQChannel = SPI1_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);

// Enable the Rx buffer not empty interrupt 
SPI_I2S_ITConfig(SPI1,SPI_I2S_IT_RXNE,ENABLE);

 // Enable the Tx empty interrupt 
SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_TXE, ENABLE);
}


void SPI1_IRQHandler(void)
{  
int8_t CmdReceived;
static uint32_t CmdCount = 0;
static int8_t RecArray[SPI_REC_BYTES];
static uint32_t dataCounter = 0;

    // SPI in Transmitter mode 
  if (SPI_I2S_GetITStatus(SPI1, SPI_I2S_IT_TXE) == SET)
 {
    SPI_I2S_SendData(SPI1, 123);

 }

 // SPI in Slave Receiver mode--------------------------------------- 
  if (SPI_I2S_GetITStatus(SPI1, SPI_I2S_IT_RXNE) == SET)
 {
 CmdReceived = SPI_ReceiveData(SPI1);

        if(CmdReceived < -100){
            CmdCount = 0;
            RecArray[CmdCount] = CmdReceived;



        } else if(++CmdCount < SPI_REC_BYTES){

            RecArray[CmdCount] = CmdReceived;

            if(CmdCount == (SPI_REC_BYTES-1)){
                callbackfunction(RecArray);
            }
        }


  }


 }
    
pregunta wouser

1 respuesta

1
  1. El envío de datos mediante interrupciones es bastante complicado, ya que si no tiene nada que enviar, debe borrar el indicador TEIE (deshabilitar la interrupción) y configurarlo cuando tenga algo que enviar. De lo contrario, la interrupción se activará todo el tiempo.
  2. No establece el número de bits de datos. Puede tener cualquier valor, ya que su estructura puede contener datos de basura.

  3. Para enviar 8 bits de datos, debe forzar al compilador a escribir byte (no la media palabra) en el registro DR. Muchas versiones SPL lo hicieron mal. Si escribe la media palabra, la mitad de la palabra se almacenará en el FIFO y enviará dos bytes (¡no uno!). No uso esas bibliotecas tontas para tales periféricos, pero le aconsejo que pase por encima de la función de envío y vea si está escrito correctamente.

    1506        *(volatile uint8_t *)&SPIx -> DR = command;
    08005a9c:   strb    r1, [r0, #12]
    
respondido por el P__J__

Lea otras preguntas en las etiquetas