cancel
Showing results for 
Search instead for 
Did you mean: 

About STM8S103F3 UART1 interrupt issue !

jeffrey2
Associate II
Posted on January 11, 2010 at 08:36

About STM8S103F3 UART1 interrupt issue !

12 REPLIES 12
jeffrey2
Associate II
Posted on May 17, 2011 at 15:06

I tried to use STM8S103F3 UART1 with PC COM1 port (19200 baud, Non-parity

8-bit data, 1 stop bit), but there are some data lost.

void UART_Init (void)

{

// [2]310 UART1 INITIALIZATION

// Step1) [2]346 To define the word length (M bit in UART_CR1)

UART1->CR1 &= ~UART1_CR1_M; // M=0 (8 data bits)

// Step2) [2]349 To define the number of stop bits in UART_CR3

UART1->CR3 &= ~UART1_CR3_STOP; // STOP[1:0]=00 (1 stop bit)

// Step3) [2]316 To select the desired baud rate

// 1) Baud rate = 19200

// Tx/Rx baud rate = fMASTER / UART_DIV

// = (16MHz / 8) / 19200

// = 2000 / 19.2

// = 104.16

// ~= 104 = 068h

UART1->BRR2 = 0x08; // 19200 Baud

UART1->BRR1 = 0x06;

// Step4) To enable transmitter mode (TEN bit in UART_CR2)

UART1->CR2 |= UART1_CR2_TEN; // transmit enable

} /* UART_Init */

u8 bUART_TxCnt;

u8 *pbUART_Tx; // system transmit pointer

void UART_TxByte (u8 bByte)

{

pbUART_Tx = &bByte;

bUART_TxCnt = 1;

UART1->CR2 |= UART1_CR2_TIEN;

} /* UART_TxByte */

@far @interrupt void UART1_TX_IRQHandler (void)

{

if (bUART_TxCnt)

{

// Is it necessary to check the TC bit before setup new data ?

UART1->DR = *pbUART_Tx++;

bUART_TxCnt--;

}

else

UART1->CR2 &= ~UART1_CR2_TIEN;

}

void main (void)

{

u8 bData;

UART_Init();

enableInterrupts();

for (;;)

{

for (bData = '0'; bData <= '9'; bData++)

UART_TxByte(bData);

} /* for endless loop */

} /* main */

PC PComm utility lost some data as attachment.

Did I miss anything ?

Q1) What's the difference between the transmit data register empty and tramsmission complete interrupt events ?

Q2) Is it necessary to check the TC bit before writing data to the UART_DR register ?

Q3) Does every transmitted data generate TXE and TC interrupts ?

Q4) Is it possible to use TC bit interrupt ONLY for transmission ?

[ This message was edited by: jeffrey.chang168 on 18-12-2009 12:57 ]

[ This message was edited by: jeffrey.chang168 on 18-12-2009 12:58 ]

[ This message was edited by: jeffrey.chang168 on 18-12-2009 17:02 ]

[ This message was edited by: jeffrey.chang168 on 20-12-2009 03:29 ]

krzysztof239955_st
Associate II
Posted on May 17, 2011 at 15:06

Hi jeffrey.chang168,

For the baud rate 19200 (fMASTER=16MHz) should be:

UART1->BRR2 = 0x01; // 19200 Baud

UART1->BRR1 = 0x34;

Regards.

Kris

jeffrey2
Associate II
Posted on May 17, 2011 at 15:06

I used default HSI clock source (fMASTER =16MHz/8) as UART1 clock source

and refer to the UART3 57600 baud example in STM8S optimized examples.

1) Baud = 57600

Tx/Rx baud rate = fMASTER / UART_DIV

= (16MHz / 8) / 57600

= 2000 / 57.6

= 34.72

~= 35 = 0x23

UART1->BRR2 = 0x03; // 576200 Baud

UART1->BRR1 = 0x02;

So it is also lost data.

2) Baud = 19200 and I tried to use your formula as below.

Tx/Rx baud rate = fMASTER / UART_DIV

= (16MHz) / 19200

= 16000 / 19.2

= 833.33

~= 833 = 0x341

UART1->BRR2 = 0x01; // 19200 Baud

UART1->BRR1 = 0x34;

PC will receive garbage data if BRR1/BRR2 register are changed to 0x341 !

[ This message was edited by: jeffrey.chang168 on 19-12-2009 01:38 ]

[ This message was edited by: jeffrey.chang168 on 19-12-2009 01:40 ]

jeffrey2
Associate II
Posted on May 17, 2011 at 15:06

I tried to implment UART1 Single byte transmission but can NOT fully understand the Figure 110 and page 311 of the RM0016 document.

Q5) Software enables tne USART:

Why does it generate an Tx Interrupt (TXE=1) automatically ?

jeffrey2
Associate II
Posted on May 17, 2011 at 15:06

I tried to modfiy my original code in Polloing approach as below:

void UART_TxByte (u8 bByte)

{

pbUART_Tx = &bByte;

bUART_TxCnt = 1;

UART1->DR = bByte;

UART1->CR2 |= UART1_CR2_TIEN;

while ((UART1->SR & UART1_SR_TXE) == 0)

;

} /* UART_TxByte */

@far @interrupt void UART1_TX_IRQHandler (void)

{

UART1->CR2 &= ~UART1_CR2_TIEN;

}

It seems to be all right. Why doesn't the UART1 interrupt approach work ?

krzysztof239955_st
Associate II
Posted on May 17, 2011 at 15:06

Hi,

The example in the enclosure.

Regards.

Kris

jeffrey2
Associate II
Posted on May 17, 2011 at 15:06

I do NOT know why the STM8S103F3 UART1 is so diffcult to use correctly.

Does Anybody have similar experience ?

The ST offical library is too complex to understand. I just wanted

to send '0' to '9 out in 19600 baud, Non-parity, 8-bit data and 1 Stop bit repeatly.

void UART_Init (void)

{

// [2]310 UART1 INITIALIZATION

// Step1) [2]346 To define the word length (M bit in UART_CR1)

UART1->CR1 &= ~UART1_CR1_M; // M=0 (8 data bits)

// Step2) [2]349 To define the number of stop bits in UART_CR3

UART1->CR3 &= ~UART1_CR3_STOP; // STOP[1:0]=00 (1 stop bit)

// Step3) [2]316 To select the desired baud rate

// 1) Baud rate = 19200

// Tx/Rx baud rate = fMASTER / UART_DIV

// = (16MHz / 8) / 19200

// = 2000 / 19.2

// = 104.16

// ~= 104 = 068h

UART1->BRR2 = 0x08; // 19200 Baud

UART1->BRR1 = 0x06;

// 2) Baud rate = 57600

// Tx/Rx baud rate = fMASTER / UART_DIV

// = (16MHz / 8) / 57600

// = 2000 / 57.6

// = 34.72

// ~= 35 = 023h

//UART1->BRR2 = 0x03; // 57600 Baud

//UART1->BRR1 = 0x02;

// Step4) To enable transmitter mode (TEN bit in UART_CR2)

UART1->CR2 |= UART1_CR2_TEN; // transmit enable

} /* UART_Init */

void UART_TxHex (u8 bHex)

{

u8 abHex[ 2 ];

u8 bNibble;

// Low Nibble

bNibble = bHex & 0x0F;

if (bNibble < 10)

abHex[ 1 ] = '0' + bNibble;

else

abHex[ 1 ] = 'A' + bNibble - 10;

// High Nibble

bNibble = bHex >> 4;

if (bNibble < 10)

abHex[ 0 ] = '0' + bNibble;

else

abHex[ 0 ] = 'A' + bNibble - 10;

pbUART_Tx = abHex; //

UART1->DR = *pbUART_Tx++; //

bUART_TxCnt = 1; //

UART1->CR2 |= UART1_CR2_TIEN; //

while ((UART1->SR & UART1_SR_TXE) == 0) //

;

} /* UART_TxHex */

@far @interrupt void UART1_TX_IRQHandler (void)

{

if (bUART_TxCnt)

{

UART1->DR = *pbUART_Tx++;

bUART_TxCnt--;

}

else

{

// Last data !

while ((UART1->SR & UART1_SR_TC) == 0)

;

UART1->CR2 &= ~UART1_CR2_TIEN;

}

}

This UART1 polling approach code still has some data lost.

Q5) Is it correct to enable TEN bit in UART_Init() ?

// Step4) To enable transmitter mode (TEN bit in UART_CR2)

UART1->CR2 |= UART1_CR2_TEN; // transmit enable

Q6) Is it correct sequence to enable TIEN bit before checking

UART1_SR_TXE bit ? Is it necessary to enable TCEN in UART_TxHex() ?

Q7) Is it correct to check TC bit in UART1 TX Interrupt Service Routine ?

Do we need to enable TCEN in UART_TxHex() ?

// Last data !

while ((UART1->SR & UART1_SR_TC) == 0)

Does anybody have a SIMPLE and WORKABLE UART1 reference code ?

If yes, please share it with me. Thanks in advance !

[ This message was edited by: jeffrey.chang168 on 21-12-2009 12:10 ]

[ This message was edited by: jeffrey.chang168 on 21-12-2009 12:12 ]

[ This message was edited by: jeffrey.chang168 on 21-12-2009 12:19 ]

[ This message was edited by: jeffrey.chang168 on 21-12-2009 12:22 ]

mozra27
Associate II
Posted on May 17, 2011 at 15:06

Hi Jeffrey,

The TXE flag is set by hardware when the content of the TDR register has been transferred into the shift register and you need to wait on the TC flag before sending the next.

A new reference manual (RM0016) version is available on internet refer to Figure 110. TC/TXE behavior when transmitting page 311.

Regards

mozra

jeffrey2
Associate II
Posted on May 17, 2011 at 15:06

I spent lots of time to understand ST STM8S103F3 Library and did try-and-error process to investigate the STM8S103 MCU. But I feel frustrated.

So far, I did NOT still know why we need to wait TXE bit in UART interrupt service routine (ISR). It results in data lost seldom if we do NOT check the TXE bit.

What's the difference between UART Polling and Interrupt approach if it is necessary ? The STM8S will waste time to wait until TXE=1 after writing data to UART->DR register. It reduces the gap between Polling and Interrupt approach. Right ?

/* ----------------

Name: UART_TxByte -

Purpose: Wait to send one byte data out.

Passed: None.

Returns: None.

Notes:

---------------- */

void UART_TxByte (u8 bByte)

{

#if (UART_TX_INTERRUPT)

bUART_TxCnt = 0;

UART1->DR = bByte; // Clear TXE bit

// [2]347 Transmitter Interrupt Enable

UART1->CR2 |= UART1_CR2_TIEN;

while ((UART1->SR & UART1_SR_TXE) == 0)

;

#else

UART1->DR = bByte; // Clear TXE bit

while ((UART1->SR & UART1_SR_TXE) == 0)

;

// [2]310 To avoid last data transmission correction !

while ((UART1->SR & UART1_SR_TC) == 0)

;

#endif

} /* UART_TxByte */

/* ----------------

Name: UART1_TX_IRQHandler - UART1 TX ISR.

Purpose:

Passed: None.

Returns: None.

Notes:

---------------- */

@far @interrupt void UART1_TX_IRQHandler (void)

{

#if (UART_TX_INTERRUPT)

if (bUART_TxCnt)

{

UART1->DR = *pbUART_Tx++; // Clear TXE bit

bUART_TxCnt--;

// [2]311 To wait until TXE = 1

while ((UART1->SR & UART1_SR_TXE) == 0)

;

}

else

{

// [2]310 To avoid last data transmission correction !

while ((UART1->SR & UART1_SR_TC) == 0)

;

// [2]347 Transmitter Interrupt disable

UART1->CR2 &= ~UART1_CR2_TIEN;

}

#endif

}

[ This message was edited by: jeffrey.chang168 on 27-12-2009 10:37 ]