Hello,
I'm working on a solution that attempts to implement a signal sensor as well as a switch to standby power supply. The signal is inserted into ADC and if it is below certain value, switch should be triggered to enable standby PSU.
However, there is a problem. On default, the device starts up in active mode, then goes to standby like it should, but unfortunately after that the MCU does not wake up. In fact it freezes completely and does not respond to any external triggers or anything. It appears that this freezing happens during the change of power supplies. The MCU has got plenty of decoupling on power supply and +3.3V supply is not being interrupted, so the MCU stays ON all the time. I have checked that.
I'm thinking that the problem may be with timings, please have a look at my code below, I will appreciate any advice.
Many Thanks,
#include "main.h"
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
volatile uint16_t Conversions[2];
uint8_t Mode_status = 0;
uint8_t LED_status = 0;
uint16_t temperature = 0;
uint16_t signal_sense = 0;
void ADC_restart(void)
{
DMA_Cmd(DMA1_Channel1, DISABLE); //Disable the DMA channel
DMA_Init(DMA1_Channel1, &DMA_InitStructure); //Re-initialize channel
DMA_Cmd(DMA1_Channel1, ENABLE); //Enable the DMA channel
ADC_StartOfConversion(ADC1); // Start the next conversion
}
void signal_read(void)
{
if (Mode_status == MODE_STANDBY && Mode_status != MODE_FAULT)
{
if (signal_sense > SENSE_LOW_TH)
{
Mode_status = MODE_ACTIVE;
}
}
if (Mode_status == MODE_ACTIVE && Mode_status != MODE_FAULT)
{
if (signal_sense < SENSE_LOW_TH)
{
Mode_status = MODE_STANDBY;
}
}
else{}
}
void temperature_read(void)
{
if (temperature > TEMP_WARNING)
{
LED_status = LED_RED_FLASH;
if (temperature > TEMP_FAULT)
{
Mode_status = MODE_FAULT;
}
else{}
}
else{}
}
int main (void)
{
SystemInit();
SystemCoreClockUpdate();
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB, ENABLE); // GPIOA enable
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); // enable ADC clock
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); // enable DMA clock
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_5 | GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_1;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStructure); // GPIOA outputs: PIN_STB, PIN_TDA_UNMUTE, PIN_UNMUTE
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); // ADC inputs: PIN_SENSE, PIN_TEMP
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_1;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &GPIO_InitStructure); // GPIOB_outputs: LED_HF_HIGH, LED_BYP, LED_1, LED_2
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Upward;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_GetCalibrationFactor(ADC1); // calibrate the ADC
ADC_Cmd(ADC1, ENABLE); // Activate the ADC
ADC_DMACmd(ADC1, ENABLE);
DMA_InitStructure.DMA_BufferSize = 1; //Two variables
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //ADC peripheral is the data source
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //Disable memory to memory mode
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t) &Conversions[0]; //Pointer to variables array
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //'Conversions' is 16bits large (HWord)
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //Enable memory increment
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //Circular DMA mode
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) &ADC1->DR; //Pointer to ADC data register!
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //ADC1->DR is 16bits!
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //Disable peripheral increment
DMA_InitStructure.DMA_Priority = DMA_Priority_Low; //A low priority DMA stream, not a big deal here!
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
DMA_Cmd(DMA1_Channel1, ENABLE);
DMA_ClearITPendingBit(DMA1_IT_TC1);
DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
ADC_ChannelConfig (ADC1, ADC_Channel_1, ADC_SampleTime_239_5Cycles); // 18uS sampling time
ADC_ChannelConfig (ADC1, ADC_Channel_4, ADC_SampleTime_239_5Cycles); // 18uS sampling time
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_ADRDY)); // wait for the ADC to become ready
ADC_StartOfConversion(ADC1); // Start the first conversion
Mode_status = MODE_ACTIVE;
while (1)
{
switch (Mode_status)
{
case MODE_ACTIVE:
LED_status = LED_GREEN;
GPIOA->ODR |= (1<<PIN_STB);
GPIOA->ODR |= (1<<PIN_TDA_UNMUTE);
GPIOA->ODR |= (1<<PIN_UNMUTE);
break;
case MODE_STANDBY:
LED_status = LED_ORANGE;
GPIOA->ODR &=~ (1<<PIN_UNMUTE);
GPIOA->ODR &=~ (1<<PIN_TDA_UNMUTE);
GPIOA->ODR &=~ (1<<PIN_STB);
break;
case MODE_FAULT:
LED_status = LED_RED;
GPIOA->ODR &=~ (1<<PIN_UNMUTE);
GPIOA->ODR &=~ (1<<PIN_TDA_UNMUTE);
GPIOA->ODR &=~ (1<<PIN_STB);
break;
}
switch (LED_status)
{
case LED_GREEN:
GPIOB->ODR |= (1<<LED_1);
GPIOB->ODR &=~ (1<<LED_2);
break;
case LED_RED:
GPIOB->ODR |= (1<<LED_2);
GPIOB->ODR &=~ (1<<LED_1);
break;
case LED_ORANGE:
GPIOB->ODR |= ((1<<LED_1) | (1<<LED_2));
break;
case LED_GREEN_FLASH:
GPIOB->ODR ^= (1<<LED_1);
GPIOB->ODR &=~ (1<<LED_2);
break;
case LED_RED_FLASH:
GPIOB->ODR ^= (1<<LED_2);
GPIOB->ODR &=~ (1<<LED_1);
break;
case LED_ORANGE_FLASH:
GPIOB->ODR ^= ((1<<LED_1) | (1<<LED_2));
break;
case LED_OFF:
GPIOB->ODR &=~ ((1<<LED_1) | (1<<LED_2));
break;
}
__WFI();
}
}
void DMA1_Channel1_IRQHandler(void)
{
if (DMA_GetITStatus(DMA1_IT_TC1) != RESET)
{
DMA_ClearITPendingBit(DMA1_IT_TC1);
signal_sense = (uint16_t) Conversions[0];
temperature = (uint16_t) Conversions[1];
signal_read();
temperature_read();
ADC_restart();
}
}