STM32: Problema de implementación de codificación de bits en Manchester

0

Quiero utilizar la codificación Manchester para mi proyecto DALI Master-slave. Estoy utilizando dos tarjetas para este proyecto, una es STM32E407 y la otro es STM32F3Discovery . Como paso inicial, quiero probar el envío de datos hexadecimales simples (0xFE96) [FE-Preamble data, 96 es el comando que quiero enviar] desde STM32F3Discovery a STM32E407 usando la codificación Manchester siguiendo esto App_Note , con enfoque de decodificación basada en el tiempo. He configurado ambas placas para la misma configuración de reloj.

Programación: la parte Manch_Tx (codificación) fue muy fácil y funcionó como se esperaba. El problema para mí es con la parte Manch_Rx (Decodificación). He configurado el TIMer4 (CH3) de STM32E407, por un período de 0xFFFF y modo de cuenta ascendente. De acuerdo con la configuración de mi reloj, la frecuencia del reloj del periférico del temporizador es de 64MHz. He configurado un pin de interrupción externo activado por el botón user_button en STM32F3Discovery para el control de flujo de hardware.

Varios aspectos que he considerado:

  1. Me he asegurado de que la transferencia de datos comience con una interrupción externa (botón push en STM32F3-Discovery) que activa la captura de entrada en STM32E407.
  2. Incluso he experimentado para incluir algún retraso (unos pocos ms) para que comience la transferencia de datos.
  3. Ajustar con la prioridad de NVIC para el temporizador (No se conoce exactamente ningún método estándar, solo le daba menos prioridad al Temporizador que a Systick)
  4. Uso de pulse_frequency en lugar de pulse_width (tiempo) para evitar la flotación

Estoy usando la función HAL_TIM_IC_CaptureCallback () para medir la frecuencia del pulso de la siguiente manera.

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
   {
   if(htim -> Channel == HAL_TIM_ACTIVE_CHANNEL_3)
   {

     if(uhCaptureIndex == 0)
     {
       /* Get the 1st Input Capture value */
       uwIC3Value1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_3);
       uhCaptureIndex = 1;
     }
     else if(uhCaptureIndex == 1)
     {
        /* Get the 2nd Input Capture value */
        uwIC3Value2 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_3);
       /* Capture comuputation */
       if (uwIC3Value2 > uwIC3Value1)
       {
         uwDiffCapture = (uwIC3Value2 - uwIC3Value1);
       }
       else /* (uwIC3Value2 <= uwIC3Value1) */
       {
         uwDiffCapture = ((0xFFFF - uwIC3Value1) + uwIC3Value2);
       }
       /* Calculation of 'window_T' */
       /* pulse_T = uwDiffCapture / (2*HAL_RCC_GetPCLK1Freq()); */
       /* Calcualtion of pulse_Frequency */
       pulse_Frequency = (2*HAL_RCC_GetPCLK1Freq()) / uwDiffCapture;
       uhCaptureIndex = 0;
     }
  }

}

Función principal

  int main(void)
  {
    HAL_Init();
    /* Configure the system clock */
    SystemClock_Config();
    /* Initialize all configured peripherals */
    MX_GPIO_Init();
    MX_TIM4_Init();

    while(interrupt_detected == 0)
    {
    }
   if(HAL_TIM_IC_Start_IT(&htim4, TIM_CHANNEL_3) != HAL_OK)
    {
     _Error_Handler(__FILE__, __LINE__);
    }

    /* Test in general the value of uwDiffCapture */
    /* while(!(pulse_Frequency > (2*Freq_T-Freq_Delta_T) && (pulse_Frequency < (2*Freq_T+Freq_Delta_T)))) */
    /*   { */
    /*     HAL_TIM_IC_CaptureCallback(&htim4); */
    /*     HAL_GPIO_TogglePin(LED_Red_GPIO_Port, LED_Red_Pin); */
    /*     HAL_Delay(250); */
    /*   } */
    while(!((pulse_Frequency > 4000) && (pulse_Frequency < 10000)))
    {
      HAL_TIM_IC_CaptureCallback(&htim4);
      HAL_GPIO_TogglePin(LED_Red_GPIO_Port, LED_Red_Pin);
      HAL_Delay(250);
    }
    HAL_GPIO_WritePin(LED_Red_GPIO_Port, LED_Red_Pin, GPIO_PIN_RESET);

    /* When it is in sync turn on LED_Green */
    HAL_GPIO_WritePin(LED_Green_GPIO_Port, LED_Green_Pin, GPIO_PIN_SET);
    while (1)
    {
    }
  }

Mi entendimiento:

   Min_pulse_frequency = 2*TIM4_Peripheral_Frequency/Period 

Estaba usando T (mid_bit_time) como 125usec [frecuencia de pulsos correspondiente 8kHz] para la función Manch_Tx (). Quiero asegurarme de que en el lado de recepción pulse_frequency se encuentra entre 2 * T-Delta_T y 2 * T + Delta_T como primer paso de depuración [antes de la implementación completa de Manch_Rx func ()] y aquí es donde tengo el problema. Estoy convirtiendo los datos de tiempo en frecuencia y comparando que la frecuencia de pulsos está dentro de los límites. Los valores escritos de 4000, 10000 se calculan en función de la frecuencia esperada y añadiendo un poco de gran tolerancia. No estoy obteniendo ningún resultado confiable.

Mis preguntas son:

  1. ¿Qué me falta o dónde está mal mi entendimiento?
  2. En general, mi lógica de llamar a HAL_TIM_IC_CaptureCallback [modo no bloqueante] es correcta o debería tener que usar TIM4_IRQHandler () [bloqueo de modo] ??
  3. ¿Es todo el proceso menos doloroso si uso DMA para la captura de tiempo?

PS: Estoy usando HAL_Libraries como puedes ver y la interfaz (openocd, linux, Emacs y jtag).

EDITAR: el problema radica en el uso de la función HAL_TIM_IC_CaptureCallback (). En la biblioteca HAL, HAL_TIM_IC_CaptureCallback () solo se usa para informar sobre la actualización de eventos en el modo Captura o Comparación, que es la razón por la que llamar a CaptureCallback no funciona para medir el período de la señal. En su lugar, tengo que usar IRQHandler y esto es lo que lo hace más complicado.

    
pregunta charansai

1 respuesta

0

Así es como finalmente he resuelto el problema. Esto debería concluir mi problema

void TIM4_IRQHandler(void)
{

  HAL_TIM_IRQHandler(&htim4);
  /* USER CODE BEGIN TIM4_IRQn 1 */

  if(i < 9)
   {
    /* Capture the timer value when interrupt occured */
     tmp[1] = HAL_TIM_ReadCapturedValue(&htim4, TIM_CHANNEL_3);

    if(tmp[1] > tmp[0])
     {
      uwDiffCapture = tmp[1] - tmp[0];
     }
     else /* if tmp[1] <= tmp[0]*/
       {
         uwDiffCapture = (0xFFFF - tmp[0]) + tmp[1];
       }
     /* Left shifting the vector */
     tmp[0] = tmp[1];

     if (clock_sync == 1)
     {
       if(update_variable == 0)
       {
          if ((uwDiffCapture > 6000) && (uwDiffCapture < 7000))
            {
              update_variable = 1;
              i = i-1;
            }
          else if ((uwDiffCapture > 12000) && (uwDiffCapture < 13000))
            {
             msg[i] = !Current_bit;
            }
          else 
            {
              Manch_Error();
            }

    }
  else if(update_variable == 1)
    {
      /* only execute the next block if that some variable =1; */

      /* Wait for next interupt but How ?? */
      if((uwDiffCapture > 6000) && (uwDiffCapture < 7000))
    {
      msg[i] = Current_bit;
              update_variable = 0;

    }
      else
    {

      Manch_Error();
    }

    }
  Current_bit = msg[i];
  i++;

}

  if(clock_sync == 0)
{

  if((uwDiffCapture > 12700) && (uwDiffCapture < 12900 ))
    {

      clock_sync = 1;
      if(HAL_GPIO_ReadPin(TIM_4_3_GPIO_Port, TIM_4_3_Pin) == GPIO_PIN_RESET)
    {
      Current_bit = 0;

    }
      else if(HAL_GPIO_ReadPin(TIM_4_3_GPIO_Port, TIM_4_3_Pin) == GPIO_PIN_SET)
    {
      Current_bit = 1;

    }
      else
    {

      Manch_Error();
    }

    }
  }

}
}

Mi truco consistió en escribir una decodificación completa en IRQHandler (), de esta forma podría evitar el uso de variables volátiles y las optimizaciones del compilador.

    
respondido por el charansai

Lea otras preguntas en las etiquetas