2021-07-14 02:30 AM
I have a STM8AF6223A Processor connected to another processor on Pin 2, UART TX and Pin 3, UART RX.
The oscilloscope verifies that both processors send correctly, 19200 Baud, 8bit Data, no parity, 1 stop bit.
The STM8 processor receives the data in the UART4->DR register mostly correct, but not always correct. How is it possible that the RXNE Flag does not get set?
I am using the stdlib STM8S/A Standard Peripherals Library V2.3.1 26-April-2018. The IDE is ST Visual Develop with the Cosmic Compiler.
This is my example code:
The waitCounter always increases to 1000, the RXNE Flag is never set. At the same time the other processor sends 0x55 constantly, the data is available.
/* Includes ------------------------------------------------------------------*/
#include "stm8s.h"
/* Private defines -----------------------------------------------------------*/
#define F_CPU 2000000UL
#define _GPIO 1 /* enables the GPIOs */
#define _EXTI 1 /* enables the EXTI */
void SendData(uint16_t min, uint16_t current)
{
uint8_t main_state = 1;
uint8_t checksum = 0;
uint8_t dummy = 0;
// Check and clear uart error flags
// Read SR then read DR registers
dummy = UART4->SR;
if (dummy & (UART4_SR_OR + UART4_SR_FE + UART4_SR_PE))
{
dummy = UART4->DR;
}
while(main_state != 0)
{
switch (main_state)
{
case 0:
// end sending
break;
case 1:
// Send sync byte
while (!(UART4->SR & UART4_SR_TXE)) {};
UART4->DR = 0x9A;
main_state++;
break;
case 2:
// Send sync byte 2
while (!(UART4->SR & UART4_SR_TXE)) {};
UART4->DR = 0x9B;
main_state++;
break;
case 3:
// Send first long term byte
while (!(UART4->SR & UART4_SR_TXE)) {};
UART4->DR = (uint8_t)(min);
checksum = (uint8_t)(min);
main_state++;
break;
case 4:
// Send second long term byte
while (!(UART4->SR & UART4_SR_TXE)) {};
UART4->DR = (uint16_t)(min >> 8);
checksum = checksum + (uint16_t)(min >> 8);
main_state++;
break;
case 5:
// Send first current byte
while (!(UART4->SR & UART4_SR_TXE)) {};
UART4->DR = (uint8_t)(current);
checksum = checksum + (uint8_t)(current);
main_state++;
break;
case 6:
// Send second current byte
while (!(UART4->SR & UART4_SR_TXE)) {};
UART4->DR = (uint16_t)(current >> 8);
checksum = checksum + (uint16_t)(current >> 8);
main_state++;
break;
case 7:
// Send checksum byte
while (!(UART4->SR & UART4_SR_TXE)) {};
UART4->DR = checksum;
main_state++;
break;
case 8:
// Send termination byte
while (!(UART4->SR & UART4_SR_TXE)) {};
UART4->DR = 0xFF;
while (!(UART4->SR & UART4_SR_TXE)) {};
main_state = 0;
break;
default:
main_state = 0;
break;
}
}
}
void main(void)
{
uint16_t i = 0;
uint8_t receivedCommand = 0;
bool waitForData = TRUE;
FlagStatus receiveRegisterNotEmpty = RESET;
uint8_t dummy;
uint16_t waitCounter = 0;
uint8_t receive_byte = 0;
//disableInterrupts();
UART4_DeInit();
UART4_Init((u32)19200, // uint32_t BaudRate
UART4_WORDLENGTH_8D, // UART_WordLength_TypeDef WordLength
UART4_STOPBITS_1, // UART_StopBits_TypeDef StopBits
UART4_PARITY_NO, // UART_Parity_TypeDef Parity
UART4_SYNCMODE_CLOCK_DISABLE, // UART_SyncMode_TypeDef SyncMode
UART4_MODE_TXRX_ENABLE // UART_Mode_TypeDef Mode
);
//UART4_Cmd(DISABLE);
/* Enable general interrupts */
//enableInterrupts();
/* Infinite loop */
while (1)
{
// Try to communicate
UART4_Cmd(ENABLE);
// Wait
for (i = 0; i < 2000; i++) // 4000us delay
{
_asm("nop");
}
// Check and clear uart error flags
// Read SR then read DR registers
dummy = UART4->DR;
dummy = UART4->SR;
if (dummy & (UART4_SR_OR + UART4_SR_FE + UART4_SR_PE))
{
dummy = UART4->DR;
}
waitCounter = 0;
//waitForData = TRUE;
while((UART4_GetFlagStatus(UART4_FLAG_RXNE) == RESET)
&& (waitCounter < 1000))
{
// Wait
for (i = 0; i < 20; i++) // 40us delay
{
_asm("nop");
}
waitCounter++;
}
receivedCommand = UART4_ReceiveData8();
if (receivedCommand == 0x55)
{
receivedCommand = 1;
}
else
{
receivedCommand = 0;
}
if (1 == receivedCommand)
{
SendData(600, 650);
SendData(600, 650);
SendData(600, 650);
}
UART4_Cmd(DISABLE);
if (0 == receivedCommand) // TI may not have power
{
// Do not measure too often, add an additional delay
for (i = 0; i < 50000; i++) // 100ms delay
{
_asm("nop");
}
}
}
}
2021-07-28 12:05 AM
Further tests found, that the RXNE flag was not set anymore, if errors were cleared before:
dummy = UART4->SR;
if (dummy & (UART4_SR_OR + UART4_SR_FE + UART4_SR_PE))
{
dummy = UART4->DR;
}
The problem is solved by receiving interrupt-based.
2021-07-28 08:34 AM
Take a note that typically bit fields are merged with a bitwise OR ('|') operation, not addition ('+').