STM32F7 + TI ADS127L01: SPI con modo circular DMA + IC temporizador para señal de datos preparados + CRC

0

He conectado un TI ADS127L01 al SPI2 de un STM32F746 mcu a través del SPI2 y Temporizador 2 Captura de entrada del canal 4 para la señal de datos preparados. Tan pronto como se captura la señal de datos preparados, el SPI TX DMA (que se asigna al TIM2_CH4 DMA) transmite 32 bits y el SPI RX DMA recibe un punto de muestra. El ADS127L01 se está ejecutando en 500kSPS.

Mientras el SPI RX DMA se ejecute en modo normal, todo esto funciona perfectamente bien. Tan pronto configuro el RX DMA en modo circular, los datos se desordenan y la transferencia de SPI solo puede iniciarse una vez, incluso después de reinicializar.

Para crear una media móvil, con una cantidad dinámica de valores medios, se utilizan la mitad de la transferencia y la interrupción de la transferencia completa. Ambas interrupciones disparan la misma función para calcular esos valores promedios. Tan pronto como se alcanza el número total de puntos de muestra, se desactiva la captura de entrada TIM2_CH4 y se detiene SPI. Por alguna razón, esto no es confiable y quizás algunos de ustedes ya tuvieron problemas similares.

También tengo grandes problemas para calcular y verificar el CRC. He intentado calcular el CRC8 utilizando una tabla de búsqueda, el polinoma y la biblioteca STM CRC, pero no pude hacer funcionar las cosas. Tal vez alguien haya hecho esto por cualquier otro ADC de TI en combinación con el STM32 antes y pueda darme algunos consejos.

Para cualquier persona que enfrente una tarea similar, aquí están mis fragmentos de código que pueden ayudar.

El código fuente para la comunicación ADS127L01:

/* Includes ------------------------------------------------------------------*/
#include <ads127l01.h>

/* Private variables ---------------------------------------------------------*/
SPI_HandleTypeDef hAds127l01Spi;
TIM_HandleTypeDef hAds127l01Tim;
CRC_HandleTypeDef hAds127l01Crc;

ADS127L01_StatusTypeDef sAds127l01State = ADS127L01_STOP; /* ADS state flag */

int32_t uAds127l01FilterThreshold = 0; /* Threshold for peak detection, activated when > 0 */

int32_t aAds127l01Data[ADS127L01_MAX_DATA_SIZE] = { 0 }; /* Data buffer used for single ADS127L01 values */
uint16_t uAds127l01DataCount = 0; /* Sample points counter */
static uint16_t uAds127l01SamplePoints = 0; /* Total count of sample points */

uint16_t uAds127l01Fault[ADS127L01_MAX_DATA_SIZE] = { 0 }; /* Data buffer used for faulty ADS127L01 values */
static uint16_t uAds127l01FaultCount = 0; /* Faulty sample points counter */
static uint16_t uAds127l01SkipCount = 0; /* Skipped sample points because they were 0 (null) */

static uint32_t aSpiAds127l01TxBuffer = 0xFFFFFFFF; /* SPI Tx Buffer */
static uint32_t aSpiAds127l01RxBuffer[ADS127L01_BUFFERSIZE] = { 0 }; /* SPI Rx Buffer */
static uint32_t aSpiAds127l01RxDoubleBuffer[ADS127L01_BUFFERSIZE] = { 0 }; /* SPI Rx Buffer for double mode */

/* Moving average values */
int32_t uAds127l01MovingValue = 0; /* Continuous moving average value */
static uint32_t aAds127l01MovingBuffer[ADS127L01_MOVING_AVERAGE] = { 0 }; /* Continuous moving average buffer */

/* Averaging settings 1 AVG = 2us (@500 kSPS) */
uint16_t uAds127l01AvgSamplePoints[ADS127L01_AVERAGING_STEPS_MAX] = { 100, 200, 300, 400, 500 }; /* Amount of sample points for belonging averaging step */
uint16_t uAds127l01AvgMean[ADS127L01_AVERAGING_STEPS_MAX] = { 1, 2, 4, 8, 16 }; /* Mean counter, amount of values for each sample point */

uint16_t uAds127l01AvgCurrentStep = 0; /* Current averaging step */
int64_t uwAds127l01AvgCurrentSampleValue = 0; /* Current sample points within current averaging */
uint16_t uAds127l01AvgCurrentSamplePoints = 0; /* Current averaging sample points */

/* CRC8 table, not working at all */
static const uint8_t ADS127L01_CrcTable[] = { 0x00, 0x03, 0x06, 0x05, 0x0C,
        0x0F, 0x0A, 0x09, 0x18, 0x1B, 0x1E, 0x1D, 0x14, 0x17, 0x12, 0x11, 0x30,
        0x33, 0x36, 0x35, 0x3C, 0x3F, 0x3A, 0x39, 0x28, 0x2B, 0x2E, 0x2D, 0x24,
        0x27, 0x22, 0x21, 0x60, 0x63, 0x66, 0x65, 0x6C, 0x6F, 0x6A, 0x69, 0x78,
        0x7B, 0x7E, 0x7D, 0x74, 0x77, 0x72, 0x71, 0x50, 0x53, 0x56, 0x55, 0x5C,
        0x5F, 0x5A, 0x59, 0x48, 0x4B, 0x4E, 0x4D, 0x44, 0x47, 0x42, 0x41, 0xC0,
        0xC3, 0xC6, 0xC5, 0xCC, 0xCF, 0xCA, 0xC9, 0xD8, 0xDB, 0xDE, 0xDD, 0xD4,
        0xD7, 0xD2, 0xD1, 0xF0, 0xF3, 0xF6, 0xF5, 0xFC, 0xFF, 0xFA, 0xF9, 0xE8,
        0xEB, 0xEE, 0xED, 0xE4, 0xE7, 0xE2, 0xE1, 0xA0, 0xA3, 0xA6, 0xA5, 0xAC,
        0xAF, 0xAA, 0xA9, 0xB8, 0xBB, 0xBE, 0xBD, 0xB4, 0xB7, 0xB2, 0xB1, 0x90,
        0x93, 0x96, 0x95, 0x9C, 0x9F, 0x9A, 0x99, 0x88, 0x8B, 0x8E, 0x8D, 0x84,
        0x87, 0x82, 0x81, 0x83, 0x80, 0x85, 0x86, 0x8F, 0x8C, 0x89, 0x8A, 0x9B,
        0x98, 0x9D, 0x9E, 0x97, 0x94, 0x91, 0x92, 0xB3, 0xB0, 0xB5, 0xB6, 0xBF,
        0xBC, 0xB9, 0xBA, 0xAB, 0xA8, 0xAD, 0xAE, 0xA7, 0xA4, 0xA1, 0xA2, 0xE3,
        0xE0, 0xE5, 0xE6, 0xEF, 0xEC, 0xE9, 0xEA, 0xFB, 0xF8, 0xFD, 0xFE, 0xF7,
        0xF4, 0xF1, 0xF2, 0xD3, 0xD0, 0xD5, 0xD6, 0xDF, 0xDC, 0xD9, 0xDA, 0xCB,
        0xC8, 0xCD, 0xCE, 0xC7, 0xC4, 0xC1, 0xC2, 0x43, 0x40, 0x45, 0x46, 0x4F,
        0x4C, 0x49, 0x4A, 0x5B, 0x58, 0x5D, 0x5E, 0x57, 0x54, 0x51, 0x52, 0x73,
        0x70, 0x75, 0x76, 0x7F, 0x7C, 0x79, 0x7A, 0x6B, 0x68, 0x6D, 0x6E, 0x67,
        0x64, 0x61, 0x62, 0x23, 0x20, 0x25, 0x26, 0x2F, 0x2C, 0x29, 0x2A, 0x3B,
        0x38, 0x3D, 0x3E, 0x37, 0x34, 0x31, 0x32, 0x13, 0x10, 0x15, 0x16, 0x1F,
        0x1C, 0x19, 0x1A, 0x0B, 0x08, 0x0D, 0x0E, 0x07, 0x04, 0x01, 0x02 };

/* Private function prototypes -----------------------------------------------*/
static void ADS127L01_WriteConfig(void);
static void ADS127L01_ReadConfig(void);
static void ADS127L01_StartDevice(void);
static void ADS127L01_StopDevice(void);
static void ADS127L01_ResetDevice(void);
static void ADS127L01_ReadData(void);
static uint8_t ADS127L01_CalculateCrc(uint8_t *pData, uint16_t len);

static void ADS127L01_SPI_Config(void);
static void ADS127L01_TIM_Config(void);
static void ADS127L01_CRC_Config(void);

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

/**
 * @brief  Configure ADS127L01 peripheral
 *          1. TIM IC fires at Data Ready (each 2us @500kSPS)
 *          2. SPI Half Cplt will be executed for first 512 samples
 *          3. SPI Cplt will be executed for second 512 samples
 * @param  None
 * @retval None
 */
void ADS127L01_Config(void) {
    /*##-1- Configure ADS127L01 peripheral ###################################*/
    ADS127L01_SPI_Config();
    ADS127L01_TIM_Config();

    /*##-2- Configure ADS127L01 to send CRC8 #################################*/
//  ADS127L01_WriteConfig(); /* Status Word Contents: CRC-8 */
//  ADS127L01_CRC_Config();

    /*##-2- Set ADS127L01 state flag #########################################*/
    sAds127l01State = ADS127L01_OK;
}

/**
 * @brief  ADS127L01 start measurement
 * @param  None
 * @retval None
 */
void ADS127L01_Start(void) {
    if (sAds127l01State != ADS127L01_OK) {
        ADS127L01_Stop();
    }

    /*##-1- Reset counter and set ADS127L01 state flag #######################*/
    uAds127l01DataCount = 0;
    uAds127l01FaultCount = 0;
    uAds127l01SkipCount = 0;

    uAds127l01AvgCurrentStep = 0;
    uwAds127l01AvgCurrentSampleValue = 0;
    uAds127l01AvgCurrentSamplePoints = uAds127l01AvgMean[uAds127l01AvgCurrentStep];

    /* Get amount of total sample points */
    uAds127l01SamplePoints = 0;
    for (uint8_t i = ADS127L01_AVERAGING_STEPS_MAX; i >= 0; i--) {
        if (uAds127l01AvgSamplePoints[i] != 0) {
            uAds127l01SamplePoints = uAds127l01AvgSamplePoints[i];
            break;
        }
    }
    if (uAds127l01SamplePoints == 0 || uAds127l01SamplePoints > ADS127L01_MAX_DATA_SIZE) {
        uAds127l01SamplePoints = ADS127L01_DEFAULT_AVG_SAMPLES;
    }

    sAds127l01State = ADS127L01_BUSY;
    uStatus |= STATUS_ADS127L01_RUNNING;

    /*##-2- Set ADS127L01 data register to current value #####################*/
    ADS127L01_ReadData();

    /*##-3- Start SPI transmit/receive mode ##################################*/
    if (HAL_SPI_TransmitReceive_DMA(&hAds127l01Spi, (uint8_t *) &aSpiAds127l01TxBuffer, \
            (uint8_t *) &aSpiAds127l01RxBuffer, ADS127L01_BUFFERSIZE * ADS127L01_SAMPLE_LENGTH) != HAL_OK) {
        /* Starting Error */
        Error_Handler(__FILE__, __LINE__);
    }

    /*##-4- Start timer in input capture interrupt mode (DRDY) ###############*/
    if (HAL_TIM_IC_Start_DMA(&hAds127l01Tim, ADS127L01_TIM_IC_CHANNEL, NULL, 0) != HAL_OK) {
        /* Starting Error */
        Error_Handler(__FILE__, __LINE__);
    }
}

/**
 * @brief  ADS127L01 stop measurement
 * @param  None
 * @retval None
 */
void ADS127L01_Stop(void) {
    /*##-1- Stop timer in input capture interrupt mode (DRDY) ################*/
    if (HAL_TIM_IC_Stop_DMA(&hAds127l01Tim, ADS127L01_TIM_IC_CHANNEL) != HAL_OK) {
        /* Stopping Error */
        Error_Handler(__FILE__, __LINE__);
    }

    /*##-2- Disable SPI ######################################################*/
    __HAL_SPI_DISABLE(&hAds127l01Spi);

    /*##-3- Stop the SPI DMA Transfer ########################################*/
    if (HAL_DMA_GetState(hAds127l01Spi.hdmarx) == HAL_DMA_STATE_BUSY) {
        if (HAL_SPI_DMAStop(&hAds127l01Spi) != HAL_OK) {
            /* Stopping SPI DMA Error */
            Error_Handler(__FILE__, __LINE__);
        }
    }
    /* Clear DMA error codes */
    hAds127l01Spi.hdmarx->ErrorCode = HAL_DMA_ERROR_NONE;
    hAds127l01Spi.hdmatx->ErrorCode = HAL_DMA_ERROR_NONE;

    /*##-4- Reinitialize ADS #################################################*/
//  __SPI2_FORCE_RESET();
//  __SPI2_RELEASE_RESET();
//  ADS127L01_SPI_Config();

    /*##-5- Reset ADS state flag #############################################*/
    sAds127l01State = ADS127L01_STOP;
    uStatus &= ~(STATUS_ADS127L01_RUNNING);
}

/**
 * @brief  ADS127L01 write register (0100 rrrr 0000 nnnn)
 *          The wREG command writes the number of bytes specified by nnnn
 *          (number of registers to be written – 1) to the device configuration
 *          register, starting at register address rrrr. The command is
 *          completed after nnnn + 1 bytes are clocked in after the WREG command
 *          byte. For example, the command to write two registers (nnnn = 0001)
 *          starting at register address 01h (rrrr = 0001) is 0100 0001 0000 0001
 *          as shown in Figure 93. Two bytes follow the command to write the
 *          contents to the registers. The frame must extend by the proper
 *          number of SCLKs to write data to the registers.
 * @param  None
 * @retval None
 */
static void ADS127L01_WriteConfig(void) {
    uint8_t startAddress = 1;
    uint8_t length = 1;
    uint8_t config = (ADS127L01_CRCB);

    /* Write CONFIG register */
    uint8_t writeCommand[3] = { (0b00100000 | startAddress), (length - 1), config };

    if (HAL_SPI_Transmit(&hAds127l01Spi, (uint8_t *) &writeCommand, length + 2, 1000) != HAL_OK) {
        /* Transmit Error */
        Error_Handler(__FILE__, __LINE__);
    }
}

static void ADS127L01_ReadConfig(void) {
    uint8_t startAddress = 0;
    uint8_t length = 1;

    /* Read CONFIG register */
    uint8_t readCommand[2] = { (0b00100000 | startAddress), (length - 1) };
    uint8_t response[length];

    if (HAL_SPI_TransmitReceive(&hAds127l01Spi, (uint8_t *) &readCommand, (uint8_t *) &response, 5, 1000) != HAL_OK) {
        /* Transmit Receive Error */
        Error_Handler(__FILE__, __LINE__);
    }
}

static void ADS127L01_ResetDevice(void) {
    /* Reset device */
    uint8_t writeCommand[1] = { 0b00000110 };
    if (HAL_SPI_Transmit(&hAds127l01Spi, (uint8_t *) &writeCommand, 1, 1000) != HAL_OK) {
        /* Reset Device Error */
        Error_Handler(__FILE__, __LINE__);
    }
}

static void ADS127L01_StartDevice(void) {
    /* Start device */
    uint8_t writeCommand[1] = { 0b00001000 };
    if (HAL_SPI_Transmit(&hAds127l01Spi, (uint8_t *) &writeCommand, 1, 1000) != HAL_OK) {
        /* Start Device Error */
        Error_Handler(__FILE__, __LINE__);
    }
}

static void ADS127L01_StopDevice(void) {
    /* Stop device */
    uint8_t writeCommand[1] = { 0b00001010 };
    if (HAL_SPI_Transmit(&hAds127l01Spi, (uint8_t *) &writeCommand, 1, 1000) != HAL_OK) {
        /* Stop Device Error */
        Error_Handler(__FILE__, __LINE__);
    }
}

static void ADS127L01_ReadData(void) {
    /* Stop device */
    uint8_t writeCommand[1] = { 0b00010010 };
    if (HAL_SPI_Transmit(&hAds127l01Spi, (uint8_t *) &writeCommand, 1, 1000) != HAL_OK) {
        /* Stop Device Error */
        Error_Handler(__FILE__, __LINE__);
    }
}

/**
 * @brief  Calculate CRC3
 * @param  pData: pointer to Ads127l01 Rx data buffer
 * @param  len: data command length.
 * @retval crc: Calculated CRC3 value
 */
static uint8_t ADS127L01_CalculateCrc(uint8_t *pData, uint16_t len) {
    uint8_t uCRC = 0x00; /* high byte of CRC initialized */
    uint16_t uIndex;

    /* pass through message buffer */
    while (len--) {
        uIndex = uCRC ^ *pData++; /* calculate the CRC  */
        uCRC = ADS127L01_CrcTable[uIndex];
    }
    return ((uint8_t) uCRC);
}

/******************************************************************************/
/*                      Interrupt & Callback Functions                        */
/******************************************************************************/

/**
 * @brief  ADS127L01 Transfer completed callback, will be executed when amount
 *         of sample points is reached.
 * @param  None
 * @retval None
 */
void ADS127L01_TransferCpltCallback(void) {
    /*##-1- Stop ADS127L01 DMA transfer ######################################*/
    ADS127L01_Stop();

    /*##-2- Set ADS127L01 state flag #########################################*/
    sAds127l01State = ADS127L01_OK;
}

/**
 * @brief  ADS Half Transfer completed callback, will be executed by
 *         HAL_SPI_TxRxHalfCpltCallback and HAL_SPI_TxRxCpltCallback when in
 *         normal mode.
 * @param  pAdcData: pointer to reception data buffer
 * @param  offset: offset where to start with averaging
 * @param  len: amount of data
 * @retval None
 */
void ADS127L01_HalfTransferCpltCallback(uint32_t *pAdcData, uint16_t offset, uint16_t len) {
    uint16_t avg = uAds127l01AvgCurrentSamplePoints;
    int64_t tmp = uwAds127l01AvgCurrentSampleValue;
    uint32_t byteorder = 0;
    int32_t value = 0;

    for (uint16_t i = offset; i < len; i++) {
        /*##-1- Check CRC Checksum, CRC8 must be set! ########################*/
//      ADS127L01_CalculateCrc((uint8_t *)&pAdcData[i], 6);
//      wCRCValue = HAL_CRC_Calculate(&hAds127l01Crc, (uint32_t *)&pAdcData[i], 0x03);

        /*##-2- Rearrange byte order #########################################*/
        /* Rearrange byte order */
        byteorder = (pAdcData[i] & 0x00ff0000) >> 16; /* first byte */
        byteorder |= pAdcData[i] & 0x0000ff00; /* second byte */
        byteorder |= (pAdcData[i] & 0x000000ff) << 16; /* third byte */

        /* Invert signal because hardware input channels are swapped */
        if (byteorder & 0x00800000) {
            value = ((int32_t) ((~byteorder) & 0x007FFFFF));
        } else {
            value = (-(int32_t) (byteorder & 0x007FFFFF));
        }

        /*##-3- Detect wrong values, measuring error or overflow #############*/
        /* Check for out of range input bit (INP) */
        if ((pAdcData[i] & 0x08000000) != 0) {
            uAds127l01Fault[uAds127l01FaultCount] = uAds127l01DataCount;
            uAds127l01FaultCount++;
        }
        /* Check for 0 (null) element */
        if (value == 0) {
            uAds127l01SkipCount++;
            /* Skip this value, error during transmission or during conversion */
//          continue;
        }

        /*##-4- Calculate sum for averaging ##################################*/
        if (avg > 0) {
            tmp += value;
            avg--;
        }

        /*##-5- Create new sample point ######################################*/
        if (avg == 0) {
            /* Calculate averaging value */
            aAds127l01Data[uAds127l01DataCount] = (int32_t) (tmp / uAds127l01AvgMean[uAds127l01AvgCurrentStep]);
            uAds127l01DataCount++;

            /* End if amount of sample points reached */
            if (uAds127l01DataCount >= uAds127l01SamplePoints) {
                sAds127l01State = ADS127L01_COMPLETE;
                ADS127L01_TransferCpltCallback();
                return;
            }

            /* Check for next averaging stage */
            if (uAds127l01DataCount >= uAds127l01AvgSamplePoints[uAds127l01AvgCurrentStep]) {
                uAds127l01AvgCurrentStep++;
            }

            /* Reset averaging counter */
            avg = uAds127l01AvgMean[uAds127l01AvgCurrentStep];
            tmp = 0;
        }
    }

    /* Keep averaging values for next 512 sample points */
    uwAds127l01AvgCurrentSampleValue = tmp;
    uAds127l01AvgCurrentSamplePoints = avg;
}

/**
 * @brief  This function handles DMA Rx interrupt request. It is executed every
 *         512 samples and triggers HAL_SPI_TxRxHalfCpltCallback as well as
 *         HAL_SPI_TxRxCpltCallback.
 * @param  None
 * @retval None
 */
void ADS127L01_SPI_DMA_RX_IRQHandler(void) {
    HAL_DMA_IRQHandler(hAds127l01Spi.hdmarx);
}

/**
 * @brief  This function handles DMA Tx interrupt request. Because all DMA
 *         interrupts are handled by the DMA Rx interrupt it is not needed.
 * @param  None
 * @retval None
 */
void ADS127L01_SPI_DMA_TX_IRQHandler(void) {
//  HAL_DMA_IRQHandler(hAds127l01Spi.hdmatx);
}

/**
 * @brief  This function handles TIM input capture interrupt request. Because
 *         all DMA interrupts are handled by the DMA Rx interrupt it is not
 *         needed.
 * @param  None
 * @retval None
 */
void ADS127L01_TIM_IC_IRQHandler(void) {
//  HAL_TIM_IRQHandler(&hAds127l01Tim);
}

/******************************************************************************/
/*                          Peripheral Initialization                         */
/******************************************************************************/

/**
 * @brief  Configuration SPI
 * @param  None
 * @retval None
 */
static void ADS127L01_SPI_Config(void) {
    /*##-1- Configure the SPI peripheral #####################################*/
    /* Set the SPI parameters */
    hAds127l01Spi.Instance = ADS127L01_SPI;
    hAds127l01Spi.Init.Mode = ADS127L01_SPI_MODE;

    hAds127l01Spi.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
    hAds127l01Spi.Init.Direction = SPI_DIRECTION_2LINES;
    hAds127l01Spi.Init.CLKPolarity = SPI_POLARITY_LOW;
    hAds127l01Spi.Init.CLKPhase = SPI_PHASE_2EDGE; // SPI_PHASE_1EDGE SPI_PHASE_2EDGE

    hAds127l01Spi.Init.DataSize = SPI_DATASIZE_8BIT;
    hAds127l01Spi.Init.FirstBit = SPI_FIRSTBIT_MSB;

    hAds127l01Spi.Init.TIMode = SPI_TIMODE_DISABLE;
    hAds127l01Spi.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;

    hAds127l01Spi.Init.NSS = SPI_NSS_HARD_OUTPUT;
    hAds127l01Spi.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;

    if (HAL_SPI_Init(&hAds127l01Spi) != HAL_OK) {
        /* Initialization Error */
        Error_Handler(__FILE__, __LINE__);
    }
}

/**
 * @brief  Configuration Timer
 * @param  None
 * @retval None
 */
static void ADS127L01_TIM_Config(void) {
    TIM_IC_InitTypeDef sConfig;

    /*##-1- Configure the TIM peripheral #####################################*/
    /* Initialize timer input capture (data ready) peripheral */
    hAds127l01Tim.Instance = ADS127L01_TIM_IC;
    hAds127l01Tim.Init.Period = 0xFFFF;
    hAds127l01Tim.Init.Prescaler = 0;
    hAds127l01Tim.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    hAds127l01Tim.Init.CounterMode = TIM_COUNTERMODE_UP;
    hAds127l01Tim.Init.RepetitionCounter = 0;

    if (HAL_TIM_IC_Init(&hAds127l01Tim) != HAL_OK) {
        /* Initialization Error */
        Error_Handler(__FILE__, __LINE__);
    }

    /*##-2- Configure the Input Capture channel ##############################*/
    /* Configure the Input Capture */
    sConfig.ICPolarity = TIM_ICPOLARITY_FALLING;
    sConfig.ICSelection = TIM_ICSELECTION_DIRECTTI;
    sConfig.ICPrescaler = TIM_ICPSC_DIV1;
    sConfig.ICFilter = 0;

    if (HAL_TIM_IC_ConfigChannel(&hAds127l01Tim, &sConfig, ADS127L01_TIM_IC_CHANNEL) != HAL_OK) {
        /* Configuration Error */
        Error_Handler(__FILE__, __LINE__);
    }
}

/**
 * @brief  Configuration CRC
 * @param  None
 * @retval None
 */
static void ADS127L01_CRC_Config(void) {
    hAds127l01Crc.Instance = CRC;
    hAds127l01Crc.InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES;

    hAds127l01Crc.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_DISABLE;
    hAds127l01Crc.Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_DISABLE;
    hAds127l01Crc.Init.InputDataInversionMode = CRC_INPUTDATA_FORMAT_BYTES;
    hAds127l01Crc.Init.OutputDataInversionMode =
            CRC_OUTPUTDATA_INVERSION_ENABLE;
    hAds127l01Crc.Init.GeneratingPolynomial = ADS127L01_CRC_POLY;

    hAds127l01Crc.Init.CRCLength = CRC_POLYLENGTH_8B;
    hAds127l01Crc.Init.InitValue = 0x0000;

    if (HAL_CRC_Init(&hAds127l01Crc) != HAL_OK) {
        /* Configuration Error */
        Error_Handler(__FILE__, __LINE__);
    }
}

/******************************************************************************/
/*                          Hardware Initialization                           */
/******************************************************************************/

/**
 * @brief  SPI MSP Initialization configures the hardware resources.
 * @param  hSpi: SPI handle pointer
 * @retval None
 */
void ADS127L01_SPI_MspInit(SPI_HandleTypeDef *hSpi) {
    static DMA_HandleTypeDef hSpiTxDma;
    static DMA_HandleTypeDef hSpiRxDma;

    GPIO_InitTypeDef GPIO_InitStruct;

    /*##-1- Enable peripherals and GPIO Clocks ###############################*/
    /* Enable GPIO TX/RX clock */
    ADS127L01_SPI_SCK_GPIO_CLK_ENABLE();
    ADS127L01_SPI_MISO_GPIO_CLK_ENABLE();
    ADS127L01_SPI_MOSI_GPIO_CLK_ENABLE();
    ADS127L01_SPI_NSS_GPIO_CLK_ENABLE();

    /* Enable SPI1 clock */
    ADS127L01_SPI_CLK_ENABLE();

    /* Enable DMA clock */
    ADS127L01_SPI_DMA_TX_CLK_ENABLE();
    ADS127L01_SPI_DMA_RX_CLK_ENABLE();

    /*##-2- Configure peripheral GPIO ########################################*/
    /* SPI SCK GPIO pin configuration */
    GPIO_InitStruct.Pin = ADS127L01_SPI_SCK_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = ADS127L01_SPI_SCK_AF;
    HAL_GPIO_Init(ADS127L01_SPI_SCK_GPIO_PORT, &GPIO_InitStruct);

    /* SPI MISO GPIO pin configuration */
    GPIO_InitStruct.Pin = ADS127L01_SPI_MISO_PIN;
    GPIO_InitStruct.Alternate = ADS127L01_SPI_MISO_AF;
    HAL_GPIO_Init(ADS127L01_SPI_MISO_GPIO_PORT, &GPIO_InitStruct);

    /* SPI MOSI GPIO pin configuration */
    GPIO_InitStruct.Pin = ADS127L01_SPI_MOSI_PIN;
    GPIO_InitStruct.Alternate = ADS127L01_SPI_MOSI_AF;
    HAL_GPIO_Init(ADS127L01_SPI_MOSI_GPIO_PORT, &GPIO_InitStruct);

    /* SPI NSS GPIO pin configuration */
    GPIO_InitStruct.Pin = ADS127L01_SPI_NSS_PIN;
    GPIO_InitStruct.Alternate = ADS127L01_SPI_NSS_AF;
    HAL_GPIO_Init(ADS127L01_SPI_NSS_GPIO_PORT, &GPIO_InitStruct);

    /*##-3- Configure the DMA ################################################*/
    /* Configure the DMA handler for Reception process */
    hSpiRxDma.Instance = ADS127L01_SPI_DMA_RX_STREAM;
    hSpiRxDma.Init.Channel = ADS127L01_SPI_DMA_RX_CHANNEL;

    hSpiRxDma.Init.Mode = DMA_CIRCULAR; // DMA_NORMAL DMA_CIRCULAR
    hSpiRxDma.Init.Direction = DMA_PERIPH_TO_MEMORY;

    hSpiRxDma.Init.PeriphInc = DMA_PINC_DISABLE; /* Static Peripheral: 4 x uint8_t */
    hSpiRxDma.Init.PeriphBurst = DMA_PBURST_INC4;
    hSpiRxDma.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;

    hSpiRxDma.Init.MemInc = DMA_MINC_ENABLE; /* Dynamic Memory: 1 x uint32_t */
    hSpiRxDma.Init.MemBurst = DMA_MBURST_SINGLE;
    hSpiRxDma.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;

    hSpiRxDma.Init.Priority = DMA_PRIORITY_VERY_HIGH;

    if (HAL_DMA_Init(&hSpiRxDma) != HAL_OK) {
        /* Initialization Error */
        Error_Handler(__FILE__, __LINE__);
    }

    /* Associate the initialized DMA handle to the the SPI handle */
    __HAL_LINKDMA(hSpi, hdmarx, hSpiRxDma);

    /* Configure the DMA handler for Transmission process */
    hSpiTxDma.Instance = ADS127L01_SPI_DMA_TX_STREAM;
    hSpiTxDma.Init.Channel = ADS127L01_SPI_DMA_TX_CHANNEL;
    hSpiTxDma.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
    hSpiTxDma.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; /* Check RM0385 p.232 */
    hSpiTxDma.Init.Mode = DMA_CIRCULAR;
    hSpiTxDma.Init.Direction = DMA_MEMORY_TO_PERIPH;

    hSpiTxDma.Init.MemInc = DMA_MINC_DISABLE; /* Static Memory: 1 x uint32_t */
    hSpiTxDma.Init.MemBurst = DMA_MBURST_SINGLE;
    hSpiTxDma.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;

    hSpiTxDma.Init.PeriphInc = DMA_PINC_DISABLE; /* Static Peripheral: 4 x uint8_t */
    hSpiTxDma.Init.PeriphBurst = DMA_PBURST_INC4;
    hSpiTxDma.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;

    hSpiTxDma.Init.Priority = DMA_PRIORITY_HIGH;

    if (HAL_DMA_Init(&hSpiTxDma) != HAL_OK) {
        /* Initialization Error */
        Error_Handler(__FILE__, __LINE__);
    }

    /* Associate the initialized DMA handle to the the SPI handle */
    __HAL_LINKDMA(hSpi, hdmatx, hSpiTxDma);

    /* Associate the initialized DMA handle to the the TIM handle */
    __HAL_LINKDMA(&hAds127l01Tim, hdma[ADS127L01_TIM_IC_DMA_ID], hSpiTxDma);

    /*##-4- Configure the NVIC for DMA receive ###############################*/
    /* NVIC configuration for DMA transfer complete interrupt (SPIx_RX) */
    HAL_NVIC_SetPriority(ADS127L01_SPI_DMA_RX_IRQn, ADS127L01_IRQPriority, 2);
    HAL_NVIC_EnableIRQ(ADS127L01_SPI_DMA_RX_IRQn);
}

/**
 * @brief  SPI MSP De-Initialization frees the hardware resources.
 * @param  hSpi: SPI handle pointer
 * @retval None
 */
void ADS127L01_SPI_MspDeInit(SPI_HandleTypeDef *hSpi) {
    /*##-1- Reset peripherals ################################################*/
    ADS127L01_SPI_FORCE_RESET();
    ADS127L01_SPI_RELEASE_RESET();

    /*##-2- Disable peripherals and GPIO Clocks ##############################*/
    HAL_GPIO_DeInit(ADS127L01_SPI_SCK_GPIO_PORT, ADS127L01_SPI_SCK_PIN);
    HAL_GPIO_DeInit(ADS127L01_SPI_MISO_GPIO_PORT, ADS127L01_SPI_MISO_PIN);
    HAL_GPIO_DeInit(ADS127L01_SPI_MOSI_GPIO_PORT, ADS127L01_SPI_MOSI_PIN);
    HAL_GPIO_DeInit(ADS127L01_SPI_NSS_GPIO_PORT, ADS127L01_SPI_NSS_PIN);

    /*##-3- Disable the DMA ##################################################*/
    /* De-Initialize the DMA associated to reception process */
    if (hSpi->hdmarx != 0) {
        HAL_DMA_DeInit(hSpi->hdmarx);
    }
    /* De-Initialize the DMA associated to transmission process */
    if (hSpi->hdmatx != 0) {
        HAL_DMA_DeInit(hSpi->hdmatx);
    }

    /*##-4- Disable the NVIC for DMA #########################################*/
    HAL_NVIC_DisableIRQ(ADS127L01_SPI_DMA_RX_IRQn);

    /*##-5- Configure the NVIC for SPI #######################################*/
    HAL_NVIC_SetPriority(ADS127L01_SPI_IRQn, ADS127L01_IRQPriority, 0);
    HAL_NVIC_EnableIRQ(ADS127L01_SPI_IRQn);
}

/**
 * @brief  TIM MSP Initialization configures the hardware resources.
 * @param  hTim: TIM handle pointer
 * @retval None
 */
void ADS127L01_TIM_IC_MspInit(TIM_HandleTypeDef *hTim) {
    GPIO_InitTypeDef GPIO_InitStruct;

    /*##-1- Enable peripherals and GPIO Clocks ###############################*/
    /* Timer input capture (data ready) Peripheral clock enable */
    ADS127L01_TIM_IC_CLK_ENABLE();

    /* Enable GPIO channels Clock */
    ADS127L01_TIM_IC_GPIO_CLK_ENABLE();

    /* Configure (ADS127L01_TIM_Channel) in Alternate function, push-pull and high speed */
    GPIO_InitStruct.Pin = ADS127L01_TIM_IC_GPIO_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // GPIO_MODE_AF_OD GPIO_MODE_AF_PP
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = ADS127L01_TIM_IC_GPIO_AF;

    HAL_GPIO_Init(ADS127L01_TIM_IC_GPIO_PORT, &GPIO_InitStruct);
}

/**
 * @brief  TIM MSP De-Initialization frees the hardware resources.
 * @param  hTim: TIM handle pointer
 * @retval None
 */
void ADS127L01_TIM_IC_MspDeInit(TIM_HandleTypeDef *hTim) {
    /*##-1- Reset peripherals ################################################*/
    ADS127L01_TIM_IC_FORCE_RESET();
    ADS127L01_TIM_IC_RELEASE_RESET();

    /*##-2- Disable peripherals and GPIO Clocks ##############################*/
    HAL_GPIO_DeInit(ADS127L01_TIM_IC_GPIO_PORT, ADS127L01_TIM_IC_GPIO_PIN);

    /*##-3- Disable the NVIC for TIM #########################################*/
    HAL_NVIC_DisableIRQ(ADS127L01_TIM_IC_IRQn);
}

/********************************* END OF FILE ********************************/

Y ambas funciones de interrupción de recurso:

/**
 * @brief  TxRx Half Transfer completed callback.
 * @param  hSpi: pointer to a SPI_HandleTypeDef structure that contains
 *         the configuration information for SPI module.
 * @retval None
 */
void HAL_SPI_TxRxHalfCpltCallback(SPI_HandleTypeDef *hSpi) {
#ifdef ACTIVATE_ADS127L01
    if (hSpi->Instance == ADS127L01_SPI) {
        if (sAds127l01State == ADS127L01_BUSY) {
            /* Run half transfer complete callback for lower buffer half */
            ADS127L01_HalfTransferCpltCallback((uint32_t *)hSpi->pRxBuffPtr, \
                    0, ADS127L01_BUFFERSIZE/2);
        }
    }
#endif
}

/**
 * @brief  TxRx Transfer completed callback.
 * @param  hSpi: pointer to a SPI_HandleTypeDef structure that contains
 *         the configuration information for SPI module.
 * @retval None
 */
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hSpi) {
#ifdef ACTIVATE_ADS127L01
    if (hSpi->Instance == ADS127L01_SPI) {
        if (sAds127l01State == ADS127L01_BUSY) {
            /* Run half transfer complete callback for upper buffer half */
            ADS127L01_HalfTransferCpltCallback((uint32_t *)hSpi->pRxBuffPtr, \
                    ADS127L01_BUFFERSIZE/2, ADS127L01_BUFFERSIZE);
        }
    }
#endif
}

El cuerpo está limitado a 30000 caracteres, por eso no pude agregar el archivo de encabezado, lo siento.

    
pregunta MFH

0 respuestas

Lea otras preguntas en las etiquetas