2020-06-08 09:34 AM
Hello guys good day. I would like to ask for your suggestions regarding the UART interrupt between 2 STM32F103C8 MCUs. I can transmit and receive between 2 MCUs using a single input and output with the use of the IRQHandler. However when I wanted to use the 2nd pin and output I could not transmit and receive anymore. So basically the interrupt is only working for a single inputt/output but for multiple input/output it does not work anymore. I have the codes below:
// I defined this function before the main
void UARTTX(uint8_t data)
{
while(!(USART2 -> SR & USART_SR_TXE));
USART2 -> DR = data;
}
// I defined this function before the main
char UARTRX()
{
while(!(USART2 -> SR & USART_SR_RXNE));
return USART2 -> DR;
}
.
.
.
// I enabled these registers before the while loop
USART2 -> CR1 |= USART_CR1_UE;
USART2 -> CR1 |= USART_CR1_TE;
USART2 -> CR1 |= USART_CR1_RE;
USART2 -> CR1 |= USART_CR1_RXNEIE;
USART2 -> CR1 |= USART_CR1_TXEIE;
.
.
.
//main code is in the IRQHandler
void USART2_IRQHandler(void)
{
HAL_UART_IRQHandler(&huart2);
{
//this is first tx output. This code is working only if the second tx output below is not enabled
if(!HAL_GPIO_ReadPin(BUTTON1_GPIO_Port, BUTTON1_Pin))
{
USART2 -> DR = 0xFF;
}
else
{
USART2 -> DR = 0x00;
}
}
//this is 2nd tx input and not working
// {
// if(HAL_GPIO_ReadPin(BUTTON2_GPIO_Port, BUTTON2_Pin))
// {
// USART2 -> DR = 0xF0;
// }
// else
// {
// USART2 -> DR = 0x0F;
// }
// }
// this is first rx input and only working if 2nd rx input below is disabled
{
if(USART2 -> DR == 0xFF)
{
HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET);
}
else if(USART2 -> DR == 0x00)
{
HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET);
}
}
//this is 2nd rx input and is not working
// {
// if(USART2 -> DR == 0xF0)
// {
// HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_SET);
// }
// else if(USART2 -> DR == 0x0F)
// {
// HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_RESET);
// }
// }
}
2020-06-08 09:39 AM
Read the USART2->DR *ONCE* into a variable, and then inspect the variable
The IRQ will occur ONCE for each byte received, if you need to process a sequence, add a state-machine so you can step through the different states as each byte is received.
2020-06-08 06:17 PM
Good day Sir thank you for the answer. I am confused by what you mentioned ONCE. What do you mean by this and how is this written?
2020-06-08 06:30 PM
It is a register, it does not behave like RAM. Think of it like a ratcheting sprocket, every time you read the content the machine advances.
{
uint8_t dr = USART2 -> DR; // READ IT ONCE
if(dr == 0xFF) // Compare against the local copy
{
HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET);
}
else if(dr == 0x00)
{
HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET);
}
}
Also this is really inefficient in a load/store architecture, with volatile register accesses that the compiler/optimize cannot fold
// I enabled these registers before the while loop
USART2 -> CR1 |= USART_CR1_UE;
USART2 -> CR1 |= USART_CR1_TE;
USART2 -> CR1 |= USART_CR1_RE;
USART2 -> CR1 |= USART_CR1_RXNEIE;
USART2 -> CR1 |= USART_CR1_TXEIE;
2020-06-09 06:46 AM
Thank you Sir for the hint. Im not sure why still only 1 output is activated. I still need to do a lot of reading :)
2020-06-10 11:41 PM
@Community member I combined the codes this way as you advised but still not working. What is wrong here?
Also what about for the Transmit part? Do I have to define a common variable and compare them?
{
uint8_t dr = USART2 -> DR; // READ IT ONCE
if(dr == 0xFF) // Compare against the local copy
{
HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET);
}
else if(dr == 0x00)
{
HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET);
}
if(dr == 0xF0)
{
HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_SET);
}
else if(dr == 0x0F)
{
HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_RESET);
}
}
2020-06-11 12:31 AM
The way you have interrupts enabled it will probably enter continously.
You should check the TXE bit in the SR before sending. And for RXNE before reading.
Not sure I'd call the HAL handler for a register level test.
2020-06-13 04:35 AM
Thank you Sir now it's working fine. For now I can transmit multiple data from MCU1 to MCU2. MCU1 transmits and MCU2 receives. I use a single IRQHandler to do this. However I am having issues when I use the same IRQHandler to do both transmit and receive at the same time with multiple data.
2020-06-13 04:45 AM
You can't wait around in the handler for subsequent bytes.
You need to buffer, and index through an array, advancing at each entry.