cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F4 Discovery UART works fine in debug mode but not without debug mode

arlen
Associate II
Posted on October 01, 2014 at 19:06

Hi everybody, currently I'm working on STM32F4 discovery using Keil software, I'm implementing USART transmission at 9600 of baudrate.

I've definedUSE_STDPERIPH_DRIVER andHSE_VALUE=8000000 using the toolchain and it's works well , the baudrate is 9600, but when I exit the debug mode and press the reset button the STM32F4 transmit with a higher baudrate (100kbps). the pictures below are some screenshot of the options window 0690X00000602y7QAA.jpg 0690X00000602yCQAQ.jpg also i've added a code in stm32f4xx_conf.h

#if defined (HSE_VALUE)
/* Redefine the HSE value; it's equal to 8 MHz on the STM32F4-DISCOVERY Kit */
#undef HSE_VALUE
#define HSE_VALUE ((uint32_t)8000000) 
#endif /* HSE_VALUE */

and i've removed the HSE_VALUE=8000000, and it works fine in debug mode but

this

still does not work without debug mode.

I hope someone can help me #stm32f4-discovery-usart-hse
6 REPLIES 6
Posted on October 01, 2014 at 19:23

You'll need to look at the code some more, both what your using to setup the USART, and the code via SystemInit() which is setting up the clocks/PLL.

The debug probably does a number of things to the system to achieve it's own functionality, so check that GPIO clocks are enabled, and peripheral clocks are suitably enabled. Make sure any local/auto variable using the stack are suitably cleared, and all fields correctly set.

Show your code.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
arlen
Associate II
Posted on October 01, 2014 at 21:11

Hi, thanks for your answer, below is the code, please ignore commented code and code which doesn't have relashion with the

#include ''stm32f4xx.h''
#include ''stdint.h''
#define ADC1_DR_ADDRESS ((uint32_t)0x4001204C)
#define ADC2_DR_ADDRESS ((uint32_t)0x4001214C)
#define ADC3_DR_ADDRESS ((uint32_t)0x4001224C)
#define MAX_STRLEN 12 // this is the maximum string length of our string in characters 
volatile char received_string[MAX_STRLEN+1]; // this will hold the recieved string 
// ADC common regular data register for dual and triple
#define ADC_CDR_ADDRESS ((uint32_t)0x40012308) 
/* UART handler declaration */
USART_InitTypeDef UartHandle;
/* Private variables ---------------------------------------------------------*/

__IO uint32_t ADCConvertedVoltage = 0;
__IO uint32_t ADCTripleConvertedValue[3];
RCC_ClocksTypeDef Clocks;
ADC_InitTypeDef ADC_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
DMA_InitTypeDef DMA_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
USART_ClockInitTypeDef USART_Clk_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
uint16_t ADCConvertedValue = 0;
uint16_t ADCLect=0;
uint16_t Counter=0;
uint16_t Done=0;
uint32_t PLL_M=8;
uint32_t PLL_N=336;
uint32_t PLL_P=2;
uint32_t PLL_Q=7;
volatile uint32_t msTicks; /* counts 1ms timeTicks */
FlagStatus Estado;
/*----------------------------------------------------------------------------
SysTick_Handler
*----------------------------------------------------------------------------*/
void SysTick_Handler(void) {
msTicks++;
}
/*----------------------------------------------------------------------------
delays number of tick Systicks (happens every 1 ms)
*----------------------------------------------------------------------------*/
void Delay (uint32_t dlyTicks) { 
uint32_t curTicks;
curTicks = msTicks;
while ((msTicks - curTicks) < 
dlyTicks
);
}
void USART_puts(USART_TypeDef* USARTx, volatile char *s){ 
while(*s){ 
// wait until data register is empty 
while( !(USARTx->SR & 0x00000040) ); 
USART_SendData(USARTx, *s); 
*s++; 
} 
} 
static void SystemClock_Config(void)
{
RCC_DeInit();
RCC_HSEConfig(RCC_HSE_ON);
if(RCC_WaitForHSEStartUp()){
RCC_PLLConfig(RCC_PLLSource_HSE,PLL_M,PLL_N,PLL_P,PLL_Q);
RCC_PLLCmd(ENABLE);
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
RCC_HCLKConfig(RCC_SYSCLK_Div1); //AHB clock = SYSCLK
RCC_PCLK1Config(RCC_HCLK_Div2); //APB1 clock = HCLK/2 
RCC_PCLK2Config(RCC_HCLK_Div4); //APB2 clock = HCLK/4
RCC_GetClocksFreq(&Clocks);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_DMA2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); 
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);// for USART1 
}
} 
void Init_ADC(){
/* ADC Common configuration *************************************************/
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_2,//ADC_DMAAccessMode_Disabled;//ADC_DMAAccessMode_2; 
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2; 
ADC_CommonInit(&ADC_CommonInitStructure);
/* ADC1 regular channel 12 configuration ************************************/
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;//ENABLE;//DISABLE;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfConversion = 1;
ADC_Init(ADC1, &ADC_InitStructure);
//ADC_EOCOnEachRegularChannelCmd(ADC1,ENABLE);
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_3Cycles);
}
void Init_DMA(){
/* DMA2 Stream0 channel0 configuration */
DMA_InitStructure.DMA_Channel = DMA_Channel_0; 
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR_ADDRESS;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADCConvertedValue;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = 1;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; 
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA2_Stream0, &DMA_InitStructure);
/* DMA2_Stream0 enable */
DMA_Cmd(DMA2_Stream0, ENABLE);
}
void Init_GPIO(){
/* USART1 */
/* Configure PB6(Tx) and PB7(Rx) in analog mode */
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_USART1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_USART1);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);
// GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);
// 
// GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
// GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
// GPIO_Init(GPIOA, &GPIO_InitStructure);
/* ADC1 */
/* Configure PA1 in analog mode */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOA, &GPIO_InitStructure); 
} 
void Init_USART1(){
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_Init(USART1,&USART_InitStructure);
USART_ClockStructInit(&USART_Clk_InitStructure);
USART_ClockInit(USART1,&USART_Clk_InitStructure);
} 
void USART1_IRQHandler(void)
{ 
// check if the USART1 receive interrupt flag was set 
if( USART_GetITStatus(USART1, USART_IT_RXNE) ){ 
static uint8_t cnt = 0; // this counter is used to determine the string length 
char t = USART1->DR; // the character from the USART1 data register is saved in t 
/* check if the received character is not the LF character (used to determine end of string) 
* or the if the maximum string length has been been reached 
*/ 
if( (t != '
') && (cnt < MAX_STRLEN) ){ 
received_string[cnt] = t; 
cnt++; 
} 
else{ // otherwise reset the character counter and print the received string 
cnt = 0; 
USART_puts(USART1, received_string); 
} 
} 
}
int main()
{
SystemCoreClockUpdate();
SystemClock_Config();
if (SysTick_Config(SystemCoreClock / 168000)) { /* SysTick 1 msec interrupts */
while (1); /* Capture error */
}
Init_GPIO();
Init_USART1();
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); // enable the USART1 receive interrupt 
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; 
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; 
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 
NVIC_Init(&NVIC_InitStructure); 
USART_Cmd(USART1, ENABLE); // enable USART1
Init_DMA();
Init_ADC();
ADC_DMACmd(ADC1, ENABLE);
ADC_DMARequestAfterLastTransferCmd(ADC1,ENABLE);
//ADC_ContinuousModeCmd(ADC1,ENABLE); // to make sure the CONT is set 
/* Enable ADC1 **************************************************************/
ADC_Cmd(ADC1, ENABLE);
ADC_SoftwareStartConv(ADC1);
while (1)
{ 
//USART_SendData(USART1,(uint16_t)0x0031); 
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
USART_puts(USART1,''Popoviiiii :D 
 
'');
ADCLect = ADCConvertedValue *3300/0xFFF; 
//ADC_SoftwareStartConv(ADC1);
//Estado = ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC); 
//if(Estado){
Done=1;
//ADCLect = ADC_GetConversionValue(ADC1);
//ADC_ClearFlag(ADC1,ADC_FLAG_EOC); // to clear the flags events.
//}
Delay(900); 
}
return 0;
}

Posted on October 01, 2014 at 21:32

If you are using the Standard Peripheral Library, the HSE/PLL stuff should be set up in SystemInit() in system_stm32f4xx.c, specifically SetSysClock(). With CMSIS SystemInit() is call in the ResetHandler in startup_stm32f4xx.s, prior to starting C and calling your main() function. I would expect this is already done, in which can reprogramming the PLL while running from it, is also ill advised.

You should review that code, as your code to set up the PLL doesn't appear to wait for it to lock properly, or wait for it to transition to the PLL clock.

You could also export internal system clocks via the MCO1 (PA8) pin, and measure those with a scope.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on October 01, 2014 at 21:37

ADCConvertedValue *3300/0xFFF;

// millivolts where VREF is 3.3V Note that the STM32F4-DISCO runs the chip at 3V, not 3.3V, so *3000/0xFFF
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
arlen
Associate II
Posted on October 01, 2014 at 22:56

yes, thanks , I've noticed it, well now I'm checking if the PLL is working with the code

static void SystemClock_Config(void)
{
RCC_DeInit();
RCC_HSEConfig(RCC_HSE_ON);
while(RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);
if(RCC_WaitForHSEStartUp()){
RCC_PLLConfig(RCC_PLLSource_HSE,PLL_M,PLL_N,PLL_P,PLL_Q);
RCC_PLLCmd(ENABLE);
while(SET != RCC_GetFlagStatus(RCC_FLAG_PLLRDY));
//Delay(900);
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

RCC_HCLKConfig(RCC_SYSCLK_Div1); //AHB clock = SYSCLK
RCC_PCLK1Config(RCC_HCLK_Div2); //APB1 clock = HCLK/2 
RCC_PCLK2Config(RCC_HCLK_Div4); //APB2 clock = HCLK/4
RCC_GetClocksFreq(&Clocks);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_DMA2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); 
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);// for USART1 
RCC_MCO1Config(RCC_MCO1Source_HSE,RCC_MCO1Div_1);
RCC_MCO2Config(RCC_MCO2Source_PLLCLK,RCC_MCO2Div_2);
}

The MCO1 with suorce clock HSE and works correctly ( 8MHz), and then I've tested the MCO2 and it work correctly , but when set MCO2 with source clock ''RCC_MCO2Source_PLLCLK'' doesn`t show anything.
arlen
Associate II
Posted on October 01, 2014 at 23:33

Hi again, now everything is working well, so the problem was that I didn't write the code to wait until the PLL is ready to work, the code that sent you (the last one) was ok :D, and also define the  symbols USE_STDPERIPH_DRIVER,  HSE_VALUE=8000000 in the toolchain is enough, thanks for your help