STM32F407VG UART interrupt problem

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Johan.o
EF Sponsor
Inlägg: 2387
Blev medlem: 18 juni 2003, 01:08:50
Ort: Jönköping

STM32F407VG UART interrupt problem

Inlägg av Johan.o »

Jag har problem med att interrupten för UART6, (Receive Data register not empty interrupt) inte riktigt fungerar i alla lägen.
Ibland fungerar den klockrent. Men andra gånger så reagerar den inte alls.

Det jag gör med interrupten är att lagra meddelanden som jag tar in på UARTEN, och lagra detta i en buffert.
Provade sedan att göra samma sak, fast utan interrupten, och då fungerar det..

Är det någon som kan tänka sig ha någon aning vad som kan vara fel?

CMGF_1b() är den funktion där detta sköts utan interrupt, medan CMGF_1() är den som sköts med interrupt.
Konstiga att innan detta så görs samma sak med interrupt för en annan funktion AT(), och där strular det inte..

Kod: Markera allt

/*************************************************************
 * File: main.c
 *
 * Description:
 * Main program and configuration
 *
*************************************************************/
#include "stm32f4xx.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_tim.h"
#include "stm32f4xx_pwr.h"
#include "stm32f4xx_usart.h"
#include "misc.h"
#include "stm32f4xx_syscfg.h"


/******************
 * Static function
 ******************/

static void OtherGPIO_Configuration(void);
static void TIM3_Configuration(void);

static void Wait_Time(uint32_t, uint32_t);
#define UNIT_us 1
#define UNIT_ms 1000
#define UNIT_s  1000000


static void USART6_Configuration(void);
static int AT(void);

#define RX_DATA_BUFF_SIZE 250
static int Rx_Data_Cnt =0;
static char Rx_Data_Buff[RX_DATA_BUFF_SIZE];

static void Prints_Uart6(char *Text_String, int Max_Length);
static signed int Find_String(char *a,int a_offset,int a_max,char *b,int b_offset,int b_max);
static int CMGF_1(void);
static int CMGF_1b(void);
static void CMGR(char Pos);

/*************************************************************
 * Function: main
 *
 * Description:
 * Main program
 *
 *************************************************************/
int main(void)
{



	OtherGPIO_Configuration();
	USART6_Configuration();
	TIM3_Configuration();


	//GPIO_SetBits(GPIOD, GPIO_Pin_15); // Blue LED



	while( 1 != AT() ){ Wait_Time(300,UNIT_ms); } // Test communication.

	;

	USART_ITConfig(USART6, USART_IT_RXNE, DISABLE);  // Receive Data register not empty interrupt.

	//CMGR_1();



	while( 1 != CMGF_1b() ){ Wait_Time(300,UNIT_ms); } //  Switch to SMS text-mode.  DEBUG!



	//while( 1 != AT() ){ Wait_Time(300,UNIT_ms); } // Test communication.


//	CMGR('1');



	while(1){;}

	Wait_Time(500, UNIT_ms);  // Wait for response.

	//while(RESET ==  GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)   ){;}

	USART_ITConfig(USART6, USART_IT_RXNE, DISABLE);  // Receive Data register not empty interrupt.



/*
{
	int i=0;

	for(i=0; i <= Rx_Data_Cnt; i++)
	{
	USART_SendData(USART6,Rx_Data_Buff[i]);
		Wait_Time(5, UNIT_us); //Delay to make transmission work properly! (Min 1 us)
		while(RESET == USART_GetFlagStatus(USART6, USART_FLAG_TC)){;} // Wait until TX is ready again.
	}

}
*/


while(1){}// END OF MAIN HERE!   --------------------------------------------------------------------------------------------
}




//--------------------------------------------------------------------------------------------

void Prints_Uart6(char *Text_String, int Max_Length)
{
	int i=0;

	Wait_Time(10,UNIT_ms); // To avoid UART hangs itself.

	while( 0  != *Text_String && (i < Max_Length) )
	{

	 USART_SendData(USART6,*Text_String);
	 Wait_Time(5, UNIT_us); //Delay to make transmission work properly! (Min 1 us)
	 while(RESET == USART_GetFlagStatus(USART6, USART_FLAG_TC)){;} // Wait until TX is ready again.
	 Text_String++;
	 i++;

	}


}

//--------------------------------------------------------------------------------------------

signed int Find_String(char *a,int a_offset,int a_max,char *b,int b_offset,int b_max)
{
	/* Search for string 'a' in string 'b' , if found: returns positive offset to after the found string. If not found: returns '-1'. */

 int ai =0, bi =0, match_cnt = 0; // Init state.
 ai= (ai + a_offset);	// Correct for wanted offset.
 bi= (bi + b_offset);  // 		--//--

 while(1)
 {
  if(a[ai] == b[bi])
  {
   match_cnt++;
   if(match_cnt == a_max){return match_cnt;} // Found string a in b!
   if( (bi >= b_max) || (ai >= a_max) ){return -1;} // Failed to find string a in b.
   ai++;
   bi++;
  }
  else
  {
   if(bi >= b_max){return -1;} // Failed to fin string a in b.
   match_cnt = 0;	// Reset of counter, because a not equal to b!
   bi++;
  }
 }

}

//--------------------------------------------------------------------------------------------

int AT(void)
{
	Rx_Data_Cnt =0;  // Reset Rx Data Buffer Counter.  	(Rx_Data_Buff)


	Prints_Uart6("AT\r\n\0", 10);
	Wait_Time(300, UNIT_ms);



	if( Rx_Data_Cnt > 0 && 0 < Find_String("OK",0,2,Rx_Data_Buff,0,Rx_Data_Cnt)){return 1;}
	else{return 0;}

}

//--------------------------------------------------------------------------------------------

int CMGF_1b(void)
{
	Rx_Data_Cnt =0;  // Reset Rx Data Buffer Counter.  	(Rx_Data_Buff)


	Prints_Uart6("AT+CMGF=1\r\n\0", 10);



	/* Wait number of micro-seconds that loaded into counter. */


	TIM_SetAutoreload(TIM2, (800*UNIT_ms) );

	TIM_SetCounter(TIM2,0);  // TimerX Counter setup.
	TIM_ClearFlag(TIM2,TIM_FLAG_Update); // TimerX Counter flag setup.

	while(SET != (TIM_GetFlagStatus(TIM2,TIM_FLAG_Update)) ) // Do this until flag is set.
	{
	  if (SET == USART_GetFlagStatus(USART6, USART_FLAG_RXNE) )
	   {
			 Rx_Data_Buff[Rx_Data_Cnt] = USART_ReceiveData(USART6);
			 Rx_Data_Cnt++;
	   }
	}

;
	if( Rx_Data_Cnt > 0 && 0 < Find_String("OK",0,2,Rx_Data_Buff,0,Rx_Data_Cnt)){return 1;}
	else{return 0;}

}

//--------------------------------------------------------------------------------------------


int CMGF_1(void)
{
	Rx_Data_Cnt =0;  // Reset Rx Data Buffer Counter.  	(Rx_Data_Buff)


	Prints_Uart6("AT+CMGF=1\r\n\0", 15);
	Wait_Time(1, UNIT_s);


	if( Rx_Data_Cnt > 0 && 0 < Find_String("OK",0,2,Rx_Data_Buff,0,( Rx_Data_Cnt + 1))){return 1;}
	else{return 0;}

}

//--------------------------------------------------------------------------------------------

void CMGR(char Pos)
{
	Rx_Data_Cnt =0;  // Reset Rx Data Buffer Counter.  	(Rx_Data_Buff)


	Prints_Uart6("AT+CMGR=", 15);
	Prints_Uart6(&Pos, 1);
	Prints_Uart6("\r\n\0", 5);

	Wait_Time(650, UNIT_ms);

}

//--------------------------------------------------------------------------------------------

void USART6_Configuration(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;


	/* Enable GPIO clock */
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);

	/* Enable USART clock */
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART6, ENABLE);

	/* Connect PC6 to USART1_Tx */
	GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_USART6);
	/* Connect PC7 to USART1_Rx */
	GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_USART6);

	/* Configure USART6 Tx, and Rx as alternate function push-pull */
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
	GPIO_Init(GPIOC, &GPIO_InitStructure);






	/* USART configuration */

	 USART_OverSampling8Cmd(USART6, ENABLE); // 8x UART oversampling.
	 USART_OneBitMethodCmd(USART6, DISABLE); // One-bit sampling, majority vote fron three samples.

	USART_InitStructure.USART_BaudRate = 9600;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	USART_Init(USART6, &USART_InitStructure);


	/* Enable USART */
	USART_Cmd(USART6, ENABLE);

	USART_ITConfig(USART6, USART_IT_RXNE, ENABLE);  // Receive Data register not empty interrupt.

	 /* Configure the NVIC Preemption Priority Bits */
	  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);


	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = USART6_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);




}


//--------------------------------------------------------------------------------------------

void TIM3_Configuration(void)
{
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);  // TIM3 Clock enable.


  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

   /* Time base configuration */
   TIM_TimeBaseStructure.TIM_Period = 65000;
   TIM_TimeBaseStructure.TIM_Prescaler = 12;
   TIM_TimeBaseStructure.TIM_ClockDivision = 0;
   TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
   TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); // Load TimeBase settings.

   TIM_ARRPreloadConfig(TIM2, ENABLE); 	// Auto Reload Preload.
   TIM_UpdateDisableConfig(TIM2, DISABLE);  // UDIS-bit, Update Event (UEV), when timer register overflow.

   /* Configures the TIMx Update Request Interrupt source. */
   TIM_UpdateRequestConfig(TIM2, TIM_UpdateSource_Global);  // Source of update is counter overflow/underflow.


   /* TIM3 enable counter */
   TIM_Cmd(TIM2, ENABLE);
}

//--------------------------------------------------------------------------------------------


static void Wait_Time(uint32_t reload, uint32_t suffix)
{

	/* Wait number of micro-seconds that loaded into counter. */


	TIM_SetAutoreload(TIM2, (reload*suffix) );

	TIM_SetCounter(TIM2,0);  // TimerX Counter setup.
	TIM_ClearFlag(TIM2,TIM_FLAG_Update); // TimerX Counter flag setup.

	while(SET != (TIM_GetFlagStatus(TIM2,TIM_FLAG_Update)) ){;} // Do this until flag is set.

}

//--------------------------------------------------------------------------------------------


/*************************************************************
 * Function: GPIO_Configuration
 *
 *************************************************************/
static void OtherGPIO_Configuration(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;

	/* Enable GPIO clock's used here */
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);


	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
	GPIO_InitStructure.GPIO_Pin =
			GPIO_Pin_15;										// LED.
	GPIO_Init(GPIOD, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
	GPIO_InitStructure.GPIO_Pin =
			GPIO_Pin_0;										// Push-button. (Normaly low with pulldown)
	GPIO_Init(GPIOA, &GPIO_InitStructure);

}
//--------------------------------------------------------------------------------------------


void USART6_IRQHandler(void)
{
	int tmp;

	if (SET == USART_GetFlagStatus(USART6, USART_FLAG_ORE) ) {GPIO_SetBits(GPIOD, GPIO_Pin_15); }
	if (SET == USART_GetFlagStatus(USART6, USART_FLAG_NE) ) {GPIO_SetBits(GPIOD, GPIO_Pin_15); }
	if (SET == USART_GetFlagStatus(USART6, USART_FLAG_FE) ) {GPIO_SetBits(GPIOD, GPIO_Pin_15); }
	if (SET == USART_GetFlagStatus(USART6, USART_FLAG_PE) ) {GPIO_SetBits(GPIOD, GPIO_Pin_15); }
	if (RESET == USART_GetFlagStatus(USART6, USART_FLAG_RXNE) )  // Is it a R-interrupt?
		{
			GPIO_SetBits(GPIOD, GPIO_Pin_15);
			return;												// If not..
		}


	//Rx_Data_Buff[Rx_Data_Cnt]=USART_ReceiveData(USART6);
	if(Rx_Data_Cnt < RX_DATA_BUFF_SIZE)  // Prevents Buffer overrun.
	{
		Rx_Data_Buff[Rx_Data_Cnt]=USART_ReceiveData(USART6);
		Rx_Data_Cnt++;
	}
	else { tmp=USART_ReceiveData(USART6); } // Don't trash last byte in buffer if it's full.


	USART_ClearITPendingBit(USART6, USART_IT_RXNE); // Clear interrupt flag
}
Mr Andersson
Inlägg: 1409
Blev medlem: 29 januari 2011, 21:06:30
Ort: Lapplandet

Re: STM32F407VG UART interrupt problem

Inlägg av Mr Andersson »

I CMGF_1b() skickar du "AT+CMGF=1\r" och i CMGF_1() skickar du "AT+CMGF=1\r\n"
Kan ju hända att enheten du pratar med inte alls svarar om den får felaktig data?
Johan.o
EF Sponsor
Inlägg: 2387
Blev medlem: 18 juni 2003, 01:08:50
Ort: Jönköping

Re: STM32F407VG UART interrupt problem

Inlägg av Johan.o »

Jaså gör jag? Hur drar du den slutsatsen. Jag kan inte se annat än att de skickar samma data. Jodå enheten jag kommunicerar med svarar korrekt varje gång.
Mr Andersson
Inlägg: 1409
Blev medlem: 29 januari 2011, 21:06:30
Ort: Lapplandet

Re: STM32F407VG UART interrupt problem

Inlägg av Mr Andersson »

Prints_Uart6("AT+CMGF=1\r\n\0", 10);
Vill du ha med allt måste du öka till 11 tecken.
Johan.o
EF Sponsor
Inlägg: 2387
Blev medlem: 18 juni 2003, 01:08:50
Ort: Jönköping

Re: STM32F407VG UART interrupt problem

Inlägg av Johan.o »

Det var uppmärksamt av dig, egentligen behövs inte de sista två tecknen.. men jag justerade det. Tack för tipset för även det var ju ett fel även om det inte löste mitt stora problem, det är fortfarande något som spökar..
Flera gånger i rad kan "Rx_Data_Buff" vara tom fast jag ser att det kommer data, och sedan plötsligt funkar det.

Kör jag CMGF_1b() utan interrupt så funkar det varje gång..
Användarvisningsbild
lillahuset
Gått bort
Inlägg: 13969
Blev medlem: 3 juli 2008, 08:13:14
Ort: Norrköping

Re: STM32F407VG UART interrupt problem

Inlägg av lillahuset »

Jag har haft ett liknande problem.
Ibland, kunde det dröja ganska många timmar av kontinuerlig kommunikation innan det gick åt helvete.
Det var någon flagga i statusregistret jag hanterade fel.
Beskrivningen var, i mitt tycke, inte helt klar i dokumentationen. Läs på så löser du säkert problemet.
Efter att ha ändrat i koden fungerade det perfekt. Men felet var mycket svårt att hitta.
Johan.o
EF Sponsor
Inlägg: 2387
Blev medlem: 18 juni 2003, 01:08:50
Ort: Jönköping

Re: STM32F407VG UART interrupt problem

Inlägg av Johan.o »

Kan du kolla upp vilka flaggor det var du inte hanterade rätt? Skulle kunna vara samma problem som jag har..
Eller en kika på din kod som fungerade?
Användarvisningsbild
lillahuset
Gått bort
Inlägg: 13969
Blev medlem: 3 juli 2008, 08:13:14
Ort: Norrköping

Re: STM32F407VG UART interrupt problem

Inlägg av lillahuset »

Jag kan skicka interruptrutinen till dig imorgon.
Johan.o
EF Sponsor
Inlägg: 2387
Blev medlem: 18 juni 2003, 01:08:50
Ort: Jönköping

Re: STM32F407VG UART interrupt problem

Inlägg av Johan.o »

Tack, superhyggligt :-)
Johan.o
EF Sponsor
Inlägg: 2387
Blev medlem: 18 juni 2003, 01:08:50
Ort: Jönköping

Re: STM32F407VG UART interrupt problem

Inlägg av Johan.o »

Nu har jag upptäckt att jag får "OverRun Error flag" satt när det verkar börja skita sig.. Gäsp.. Kanske inte löser detta trött =)
Användarvisningsbild
lillahuset
Gått bort
Inlägg: 13969
Blev medlem: 3 juli 2008, 08:13:14
Ort: Norrköping

Re: STM32F407VG UART interrupt problem

Inlägg av lillahuset »

Exakt den flaggan var det. Om du läser på om flagghanteringen kommer du att notera att den flaggan clearas på ett (i mitt tycke) lite märkligt sätt.
Johan.o
EF Sponsor
Inlägg: 2387
Blev medlem: 18 juni 2003, 01:08:50
Ort: Jönköping

Re: STM32F407VG UART interrupt problem

Inlägg av Johan.o »

Jag hanterar flaggan som den bör nu, men det racket inte.. Så då lade jag till en delay i min rutin där jag skickar data på uarten mellan varje tecken på 12ms. Då fungerar det klockrent. Så fort jag skickar data ekas nämligen samma data tillbaka från det modem jag kommunicerar med.. Då blir det något knas.. ska prova att stänga av interrupt då jag skickar data och enbart lyssna efter att jag är klar..

Nåväl, problemet är löst, och kanske närmare en mer perfekt lösning under dagen :-)
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: STM32F407VG UART interrupt problem

Inlägg av sodjan »

Är det så att även skickningen är interruptstyrd? Alltså interrupt
på "tom sänd buffert" eller liknande? Kan det vara så att om du
har flera tecken i buffereten så hinner inte receive interruptet
"imellan" så att säga, för att tömma receive bufferten?

Att du får overrun tyder ju i alla fall på att *något* hindrar
processorn från att läsa mottagna tecken.

Med din nya delay så hinner kanske receive-interruptet med
mellan dina sända tecken...
Användarvisningsbild
lillahuset
Gått bort
Inlägg: 13969
Blev medlem: 3 juli 2008, 08:13:14
Ort: Norrköping

Re: STM32F407VG UART interrupt problem

Inlägg av lillahuset »

Här kommer min interrupthanterare.

Jag noterade att parametern är felaktigt beskriven. Det är inte en pekare utan ett kanalnummer.
Jag noterar också en bugg, crbuf ska vara en array.

Sedan är det ju en del lullull som du inte behöver bry dig om.
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Johan.o
EF Sponsor
Inlägg: 2387
Blev medlem: 18 juni 2003, 01:08:50
Ort: Jönköping

Re: STM32F407VG UART interrupt problem

Inlägg av Johan.o »

Sodjan: Jag har ingen interrupt för skickningen..
Lillahuset: Tack, ska kika på det ikväll :-)
Skriv svar