cancel
Showing results for 
Search instead for 
Did you mean: 

USART3 on STM32F4-Discovery

DNA-)
Associate III
Posted on November 30, 2012 at 16:47

Hi!

Just before starting my post, i would like to thanks the people of this very very usefull forum. A lots of topics helps me in my newly design. So, yes, i'm designing a new board, and i'm evaluating my software on the DiscoveryBoard. So my question is :: How can i send and receive several lines using interrupts but, if possible without DMA? I'm using USART3 on PD8 & PD9. I've already made this software below :

void Init_Uart3(void){ 
GPIO_InitTypeDef GPIO_InitStructure; 
USART_InitTypeDef USART_InitStructure; 
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; 
// GPIO_InitTypeDef GPIO_InitStructure; 
//configure clock for USART 
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); 
//configure clock for GPIO 
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); 
//configure AF 
GPIO_PinAFConfig(GPIOD,GPIO_PinSource8,GPIO_AF_USART3); 
GPIO_PinAFConfig(GPIOD,GPIO_PinSource9,GPIO_AF_USART3); 
//configure ports, &GPIO_InitStructure); 
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; 
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; 
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; 
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; 
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
GPIO_Init(GPIOD, &GPIO_InitStructure); 
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; 
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; 
GPIO_Init(GPIOD, &GPIO_InitStructure); 
USART_Init(USART3, &USART_InitStructure); 
// Enable USART 
USART_Cmd(USART3, ENABLE); 
}

and with this in my 'main' i can send a character :

while (USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET); 
USART_SendData(USART3, 'b');

As you can see, it is just polling for sending, but i've nothing to receive any character... I would like to use the interrupts, but i've not any hint to start.. And you? Maybe someone have already done it andd can help me? an exemple? Any help will be welcome! By the way, i should mention that i have as TTL-RS232 translator between the board and my comp. I'm using IAR EWARM. Dave. #usart-stm32
10 REPLIES 10
Posted on November 30, 2012 at 16:58

I swear I've posted this before, but here's a quick demo

// STM32 USART IRQ TX/RX Loop (USART3 Tx PD.8, Rx PD.9) STM32F4 Discovery - sourcer32@gmail.com

#include ''stm32f4_discovery.h''

volatile char StringLoop[] = ''The quick brown fox jumps over the lazy dog\r\n'';

/**************************************************************************************/

void RCC_Configuration(void)

{

/* --------------------------- System Clocks Configuration -----------------*/

/* USART3 clock enable */

RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);

/* GPIOD clock enable */

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);

}

/**************************************************************************************/

void GPIO_Configuration(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

/*-------------------------- GPIO Configuration ----------------------------*/

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOD, &GPIO_InitStructure);

/* Connect USART pins to AF */

GPIO_PinAFConfig(GPIOD, GPIO_PinSource8, GPIO_AF_USART3);

GPIO_PinAFConfig(GPIOD, GPIO_PinSource9, GPIO_AF_USART3);

}

/**************************************************************************************/

void USART3_Configuration(void)

{

USART_InitTypeDef USART_InitStructure;

/* USARTx configuration ------------------------------------------------------*/

/* USARTx configured as follow:

- BaudRate = 9600 baud

- Word Length = 8 Bits

- Two Stop Bit

- Odd parity

- Hardware flow control disabled (RTS and CTS signals)

- Receive and transmit enabled

*/

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(USART3, &USART_InitStructure);

USART_Cmd(USART3, ENABLE);   USART_ITConfig(USART3, USART_IT_RXNE |USART_IT_TXE, ENABLE);

  }

/**************************************************************************************/

void NVIC_Configuration(void)

{

NVIC_InitTypeDef NVIC_InitStructure;

/* Configure the NVIC Preemption Priority Bits */

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);

/* Enable the USART3 Interrupt */

NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

}

/**************************************************************************************/

void USART3_IRQHandler(void)

{

static int tx_index = 0;

static int rx_index = 0;

if (USART_GetITStatus(USART3, USART_IT_TXE) != RESET) // Transmit the string in a loop

{

USART_SendData(USART3, StringLoop[tx_index++]);

if (tx_index >= (sizeof(StringLoop) - 1))

tx_index = 0;

}

if (USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) // Received characters modify string

{

StringLoop[rx_index++] = USART_ReceiveData(USART3);

if (rx_index >= (sizeof(StringLoop) - 1))

rx_index = 0;

}

}

/**************************************************************************************/

int main(void)

{

RCC_Configuration();

GPIO_Configuration();

NVIC_Configuration();

USART3_Configuration();

while(1); // Don't want to exit

}

/**************************************************************************************/

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
DNA-)
Associate III
Posted on November 30, 2012 at 17:02

Great!

Thank you Clive1!

But how can i send data and how can i check if there is some data is received?
Posted on November 30, 2012 at 17:07

But how can i send data and how can i check if there is some data is received?

You'll need to build your own buffering scheme. Typically a FIFO or Ring Buffer, which is then filled/emptied in the interrupt routine. You will need to turn off the TXE interrupt if you do not have data to satiate it.

It's beyond the scope of the quick examples I'm willing to post here.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
frankmeyer9
Associate II
Posted on November 30, 2012 at 17:07

I have this added after the UART initialization:

/* parametrize USART3-Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init (&NVIC_InitStructure);
/* Interrupt at reception and receive errors */
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
USART_ITConfig(USART3, USART_IT_ERR, ENABLE);

And this is (most of the) interrupt handler:

/* handler for the USART3 interrupt (console)
*/
void USART3_IRQHandler(void)
{
uint8_t databyte;
if(USART_GetITStatus (USART3, USART_IT_RXNE) != RESET)
{
szConBuffer[ConBufCount++] = (uint8_t) USART3->DR;
if (ConBufCount >= CON_BUFSIZE)
ConBufCount = 0;
}
else if (USART_GetITStatus (USART3, USART_IT_ORE) != RESET)
{
// treat error here ...
}
}

Don't configure an interrupt on receive errors if you do not need them. But if you need/use them, don't forget to clear the pending flag ... The name of the interrupt handler routine is fixed, and must match that defined by the toolchain, as the interrupt vector needs to end up on a specific location. Not sure how IAR-WB handles this. You might need to consult IAR specific headers or the startup code, which usually puts default routines into place. EDIT: too late ...
DNA-)
Associate III
Posted on December 01, 2012 at 08:42

I'm totally agree with you!

I was meaning that my buffer is ready to send and i don't know how to launch the interrupt.

What register i should modify for that?

And by the way the interrupt doesn't seems launched when i send data to the Discovery.

dadubois
Associate
Posted on March 21, 2016 at 22:28

// BLE2 click (RN4020 bluetooth) installed on Discovery Shield MikroBus #1

// Successfully initialize click and receive ''CMD'' from RN4020,

// but never get ''data  register empty''.

// debug loops forever  while( !(USART3->SR & 0x00000040) );

void USART3_GPIOInit(void)

{

 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); //Enable clock for GPIOB

 // IMPORTANT Make sure, these lines are before pins configuration!

 GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_USART3);//Connect PB10 to USART3_Tx

 GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_USART3);//Connect PB11 to USART3_Rx

/* USART3 Tx on PB10 | Rx on PB11 */

 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;

 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //GPIO_Mode_Alternate Function

 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;

 GPIO_Init(GPIOB, &GPIO_InitStructure);

 /* MikroBus #1 PE10 RST to RN4020 SWAKE (pin 7) */

 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE); //Enable clock for GPIOE

 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;

 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; //GPIO_Mode_Output Function

 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

 GPIO_Init(GPIOE, &GPIO_InitStructure);

 /* MikroBus #1 PA1 PWM to RN4020 CMD/MLDP (pin 8) */

 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); //Enable clock for GPIOA

 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;

 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; //GPIO_Mode_Output Function

 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

 GPIO_Init(GPIOA, &GPIO_InitStructure);

 /* MikroBus #1 PC1 AN to RN4020 PI01 (pin 10) */

 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); //Enable clock for GPIOC

 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;

 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; //GPIO_Mode_Input no Pull-Up/Down Function

 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

 GPIO_Init(GPIOC, &GPIO_InitStructure);

 }

void USART3_Init(void)

{

 /* Enable peripheral clock for USART3 */

 /* USART 2, 3, 4 & 5 are on APB1 (up to 5.25Mbit/s) */

 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);

// USART3 configured as RN4020 BLE2 click on MikroBus 1

 USART_InitStructure.USART_BaudRate = 115200;

 USART_InitStructure.USART_WordLength = USART_WordLength_8b; // Word Length 8 Bits

 USART_InitStructure.USART_StopBits = USART_StopBits_1; // 1 Stop Bit

 USART_InitStructure.USART_Parity = USART_Parity_No; // No parity

 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // Hardware flow control disabled

 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // Receive and transmit enabled

 USART_Init(USART3, &USART_InitStructure); // USART configuration

 USART_Cmd(USART3, ENABLE); // Enable USART

}

void USART3_NVICInit(void)

{

 NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;

 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;

 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;

 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

 NVIC_Init(&NVIC_InitStructure);

 USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);

}

void USART3_puts(volatile char *s)

{

 while(*s)

 {

 // wait until data register is empty

 while( !(USART3->SR & 0x00000040) );

 USART_SendData(USART3, *s);

 *s++;

 }

}

void USART3_IRQHandler(void) {

 static uint16_t RxByte = 0x00;

 if (USART_GetITStatus(USART3, USART_IT_TC) == SET)

 {

#if(0) // not using BLE_Tx IRQ for now

if (USART_GetFlagStatus(USART3, USART_FLAG_TC))

{

USART_SendData(USART3, RxByte);

USART_ITConfig(USART3, USART_IT_TC, DISABLE);

}

#endif // end BLE_Tx IRQ

USART_ClearITPendingBit(USART3, USART_IT_TC);

 }

 if (USART_GetITStatus(USART3, USART_IT_RXNE) == SET)

 {

if (USART_GetFlagStatus(USART3, USART_FLAG_RXNE))

{

RxByte = USART_ReceiveData(USART3);

USB_BLE_Rx[USB_BLE_msg][USB_BLE_Rx_len] = RxByte;

if(USB_BLE_Rx_len > 254)

RxByte = '\n';

USB_BLE_Rx_len++;

if(RxByte== '\n')

{

USB_BLE_Rx[USB_BLE_msg][USB_BLE_Rx_len] = 0; // terminate string

USB_BLE_msg++;

if(USB_BLE_msg>7)

USB_BLE_msg = 0;

USB_BLE_Rx_len = 0;

}

USART_ITConfig(USART3, USART_IT_TC, ENABLE);

}

USART_ClearITPendingBit(USART3, USART_IT_RXNE);

 }

}

void BLE_Init(void)

{

int cmd_ok=1,cur_msg=0;

while (cmd_ok!=0)

{

cur_msg=USB_BLE_msg;

BLE_SLEEP();

BLE_MODE_CMD();

Delay_ms(100);

BLE_WAKE();//high

Delay_ms(100);

cmd_ok = strcmp(''CMD\r\n'',USB_BLE_Rx[cur_msg+1]);

}

USART3_puts(''SF,1\r''); //Factory Reset

}

#include ''stm32f4xx.h''

#include ''stm32f4_discovery.h''

#include ''string.h''

#define BLE_WAKE() GPIO_WriteBit(GPIOE, GPIO_Pin_10,Bit_SET)

#define BLE_SLEEP() GPIO_WriteBit(GPIOE, GPIO_Pin_10,Bit_RESET)

#define BLE_MODE_CMD() GPIO_WriteBit(GPIOA, GPIO_Pin_1,Bit_RESET)

#define BLE_MODE_DATA() GPIO_WriteBit(GPIOA, GPIO_Pin_1,Bit_SET)

#define BLE_CONNECTION_STATUS() GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_1)

main()

{

USART3_GPIOInit();

USART3_Init();

USART3_NVICInit();

BLE_Init(); //SW_WAKE LOW then HIGH

while(1);

}

Posted on March 22, 2016 at 01:16

May be you should be waiting on TXE (Transmit Empty), the current state of things, rather than TC (Transmit Complete), some prior state that may or may not have occurred.

If the buffer is empty you can send a new byte.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
jay1991
Associate II
Posted on March 26, 2016 at 12:15

hi i have tried the code and its working very well. now i want to know that how can i receive the data come from USART receiver? i want to say that i am sending 9 times different strings. and each time it gives reply. i have attached SIM900a with it. so i am at the stage where i am sending 9 strings and receives reply accordingly. now i want the receive part as if i want 5 th string reply only. so what to do? Help please.

I am sharing my code here.

________________

Attachments :

main.c : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006HzWn&d=%2Fa%2F0X0000000bNm%2F2hEsDJTkheRZ5gVc3DdS2IysDopVLZcoBMjrKdD7K4Y&asPdf=false

stm32f4xx_it.c : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006HzZW&d=%2Fa%2F0X0000000bNk%2FaLfx_Jdtc6Jcr6jah7FD4xnTJpG8nbxd4JM5SnOuMhQ&asPdf=false
Posted on March 26, 2016 at 18:33

You'd need to buffer and process the responses from each of the AT commands, you'd expect OK, ERROR, etc. and you need to deal with each one before sending the next. Waiting a brief amount of time is not sufficient to deal with how the modem processes things, as interactions with the network might take up to 150 seconds.

I'd use the IRQ Handler to manage a ring (fifo) buffer, and then have a foreground function send the AT command, and wait for acceptable response lines from the modem in each case. Creating such an example is a bit beyond the level of service I'm planning on providing here.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..