stm32 se bloquea durante ADC

1

Estoy haciendo una prueba simple de ADC con un potenciómetro en STM32F103C8, parece funcionar bien durante 5 segundos aproximadamente, pero luego la unidad solo se detiene, incluso cuando el bucle deja de hacer lo que se supone que debe hacer (así que supongo que no ni siquiera dejar la rutina de interrupción cuando falla). Probablemente tenga que ver con la inicialización de ADC, pero no puedo ver qué es exactamente lo que está mal.
A continuación se muestra mi ADC.c con inicialización de ADC y mi main.c (tenga en cuenta que imprimo "1" y "2" solo para monitorear si todavía se está ejecutando el bucle, y no, todo se congela)
Si no es la inicialización, entonces quizás sea un problema de hardware, pero con tal circuito no puedo pensar en nada que pueda salir mal, la placa tiene un capacitor para ADC e incluso intenté poner otro entre la señal y la tierra, nada ... .

UPD
OK, ahora me veo como un idiota total ... Resultó que no fue el microcontrolador el que se atascó, sino el LCD. Intenté cambiarlo a un LCD diferente (era 4x20, cambiado a 2x16) y ahora no se detiene. Me di cuenta de que es que si me movía un poco los cables, se detendría con mayor probabilidad, por lo que probablemente si la conexión no es sólida el 100% del tiempo la LCD encuentra algún tipo de error interno y se atasca, no sucede con otros LCD por alguna razón. Al parecer, la vibración de mí al tocar el tablero hizo algo para conectarme y la pantalla LCD se asustó. Entonces, quienquiera que encuentre el mismo problema: intente usar un LCD diferente, verifique el cableado (intente manipularlo para ver si afecta algo), verifique si el código del controlador es bueno, etc.

ADC.c


void ADC_init(void)
{
    GPIO_InitTypeDef adcpin; 
    ADC_InitTypeDef MyADCinit;

    ///
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

    adcpin.GPIO_Pin = GPIO_Pin_0;
    adcpin.GPIO_Mode = GPIO_Mode_AIN;

    GPIO_Init(GPIOB, &adcpin);
    ////

    ////
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); // Turn on ADC clock
    ////




  /* Initialization of ADC */
  MyADCinit.ADC_Mode = ADC_Mode_Independent;
  MyADCinit.ADC_ScanConvMode = DISABLE;
  MyADCinit.ADC_ContinuousConvMode = DISABLE;
  MyADCinit.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
  MyADCinit.ADC_DataAlign = ADC_DataAlign_Right;
  MyADCinit.ADC_NbrOfChannel = 1;

    ADC_Init(ADC1, &MyADCinit);


    // specify channel we want to use
    ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 1, ADC_SampleTime_55Cycles5); // Rank - the order number by which scanning is done

    // enable interrupts on ADC
    NVIC_EnableIRQ(ADC1_2_IRQn);

    // enable interrupts on the end of conversion
    ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE);

    // Turn on ADC
    ADC_Cmd(ADC1, ENABLE);

}

main.c


#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "HD44780.h"
#include "ADC.h"
#include 

uint16_t data_adc;
char adcResult[4];


void ADC1_2_IRQHandler(void)
{
    if (ADC_GetITStatus(ADC1, ADC_IT_EOC) == SET)
    {
        ADC_ClearITPendingBit(ADC1, ADC_IT_EOC);
        data_adc = ADC_GetConversionValue(ADC1);

        LCD_GoTo(0,0);
        sprintf(adcResult, "ADC = %d", data_adc);
        LCD_SendText(adcResult);
        LCD_SendText("   ");
    }
}

int main (void)
{
    RCC_Configuration(); // Configure the system clocks.
    LCD_Init();          // Initialize the LCD.
    LCD_Clear();         //Clear the LCD.
    delay_ms(1000);
    ADC_init();

    while(1)
    {
        delay_ms(10);
        ADC_SoftwareStartConvCmd(ADC1, ENABLE); // check functional state... wtf is that
        LCD_GoTo(0,0);
        LCD_SendText ("1");
        delay_ms(100);
        LCD_GoTo(0,0);
        LCD_SendText ("2");
        delay_ms(50);
    }

}

    
pregunta ScienceSamovar

1 respuesta

1

Intente solo obtener el valor de ADC en el controlador de IRQ y deje que el bucle principal realice el procesamiento de la LCD, que puede estar provocando una interrupción que se anticipa a la interrupción de ADC en la que ya se encuentra, lo que provoca un bloqueo.

Tal vez asegúrate de que tu reloj ADC esté configurado correctamente.

Tal vez intente sin la interrupción:

    ADC_SoftwareStartConvCmd(ADC1, ENABLE);
    while(ADC_GetSoftwareStartConvStatus(ADC1));
    while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));
    data_adc = ADC_GetConversionValue(ADC1);
    ADC_ClearFlag(ADC1, ADC_FLAG_EOC);
    
respondido por el RobC

Lea otras preguntas en las etiquetas