What is the cause of interruption after STM32 UART2 transmission?

SECTION 2

Let me talk about TC first. That is Transmission Complete. The interrupt is entered after sending a byte, which is called "interrupt after sending". In the same way as the original TI method of 8051, interrupts are sent after sending. You need to send a byte in the sending function to trigger the interrupt. Send function is as follows

Why did Lu Qi leave Baidu and where will Baidu go next

/ *******

Function: Send character string in interrupt mode. Use the method of judging TC. That is, determine the interrupt bit after transmission.

Input: the first address of the string

Output: None

******* /

void USART_SendDataString (u8 * pData)

{

pDataByte = pData;

USART_ClearFlag (USART1, USART_FLAG_TC); // Clear the transmission completion flag, otherwise the first byte of data may be lost. Provided by netizens.

USART_SendData (USART1, * (pDataByte ++)); // Must be ++, otherwise the first character t will be sent twice

}

The interrupt processing function is as follows

/ ********

* FuncTIon Name: USART1_IRQHandler

* DescripTIon: This function handles USART1 global interrupt request.

* Input: None

* Output: None

* Return: None

********* /

void USART1_IRQHandler (void)

{

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

{

if (* pDataByte == '\ 0') // TC needs to read SR + write DR to clear 0, when sent to the end, use 'if' to turn off when it reaches '\ 0'

USART_ClearFlag (USART1, USART_FLAG_TC); // Otherwise TC is always set, TCIE is also open, which will cause continuous interruption. Just clear it, no need to close TCIE

else

USART_SendData (USART1, * pDataByte ++);

}

}

Where u8 * pDataByte; is an external pointer variable

In the interrupt handler, after sending the character string, you do not need to turn off the TC's interrupt enable TCIE, you only need to clear the flag bit TC; in this way you can avoid TC == SET causing repeated interrupts.

The serial port initialization function is as follows

/ *********

Name: USART_Config

Function: Set serial port parameters

Input: None

Output: None

Returns: None

********** /

void USART_Config ()

{

USART_InitTypeDef USART_InitStructure; // Define a structure containing serial port parameters

USART_InitStructure.USART_BaudRate = 9600; // Baud rate 9600

USART_InitStructure.USART_WordLength = USART_WordLength_8b; /// 8 data bits

USART_InitStructure.USART_StopBits = USART_StopBits_1; // 1 stop bit

USART_InitStructure.USART_Parity = USART_Parity_No; // No verification

USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // No hardware flow control

USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // Input plus output mode

USART_InitStructure.USART_Clock = USART_Clock_Disable; // The clock is off

USART_InitStructure.USART_CPOL = USART_CPOL_Low;

USART_InitStructure.USART_CPHA = USART_CPHA_2Edge;

USART_InitStructure.USART_LastBit = USART_LastBit_Disable;

USART_Init (USART1, & USART_InitStructure); // Set to USART1

USART_ITConfig (USART1, USART_IT_TC, ENABLE); // Tramsimssion Complete, the interrupt is generated. Open TC interrupt must be placed here, otherwise the first byte will still be lost

USART_Cmd (USART1, ENABLE); // Enable USART1

}

Here is a question: if you open the TC interrupt USART_ITConfig () and put it in my USART_SendDataString (), then you will lose the first byte of the string. It must be placed in the serial port initialization function so as not to be lost. do not know why? ?

Here I can give an explanation. You can see why you look at SECTION1. The principle of doing so is similar to that explained by SECTION1, which is equivalent to delay. The main reason why you do n’t lose data behind is that there is such a sentence in your code. USART_ClearFlag (USART1, USART_FLAG_TC); // Clear the transmission completion flag, otherwise the first byte of data may be lost. Provided by netizens.

Let's talk about judging TXE. That is, Tx DR Empty, the transmit register is empty. When TXEIE is enabled, an interrupt will be generated as long as Tx DR is empty. Therefore, it must be turned off after sending the string, otherwise it will cause repeated entry interruption. This is also different from TC.

The sending function is as follows:

/ *******

Function: Send character string in interrupt mode. Use the method of judging TC. That is, determine the interrupt bit after transmission.

Input: the first address of the string

Output: none

******* /

void USART_SendDataString (u8 * pData)

{

pDataByte = pData;

USART_ITConfig (USART1, USART_IT_TXE, ENABLE); // As long as the transmit register is empty, there will always be an interrupt. Therefore, if you do not send data, turn off the transmit interrupt and only open it when you start sending.

}

The interrupt processing function is as follows:

/ ********

* Function Name: USART1_IRQHandler

* Description: This function handles USART1 global interrupt request.

* Input: None

* Output: None

* Return: None

******** /

void USART1_IRQHandler (void)

{

if (USART_GetITStatus (USART1, USART_IT_TXE) == SET)

{

if (* pDataByte == '\ 0') // The byte to be sent is NULL at the end

USART_ITConfig (USART1, USART_IT_TXE, DISABLE); // Because it is an interrupt that sends the register empty, it must be turned off after sending the string, otherwise it will enter the interrupt if it is empty

else

USART_SendData (USART1, * pDataByte ++);

}

}

In the serial port initialization function, there is no need to open the TXE interrupt (which is opened in the sending function) as follows:

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

Name: USART_Config

Function: Set serial port parameters

Input: None

Output: None

Returns: None

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

void USART_Config ()

{

USART_InitTypeDef USART_InitStructure; // Define a structure containing serial port parameters

USART_InitStructure.USART_BaudRate = 9600; // Baud rate 9600

USART_InitStructure.USART_WordLength = USART_WordLength_8b; /// 8 data bits

USART_InitStructure.USART_StopBits = USART_StopBits_1; // 1 stop bit

USART_InitStructure.USART_Parity = USART_Parity_No; // No verification

USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // No hardware flow control

USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // Input plus output mode

USART_InitStructure.USART_Clock = USART_Clock_Disable; // The clock is off

USART_InitStructure.USART_CPOL = USART_CPOL_Low;

USART_InitStructure.USART_CPHA = USART_CPHA_2Edge;

USART_InitStructure.USART_LastBit = USART_LastBit_Disable;

USART_Init (USART1, & USART_InitStructure); // Set to USART1

USART_Cmd (USART1, ENABLE); // Enable USART1

}

SECTION 3

There are 2 registers at the sending end of USART, one is the USART_DR register (TDR in the shaded part below) that the program can see, and the other is the shift register that the program cannot see.

There are two flags corresponding to USART data transmission, one is TXE = transmit data register is empty, and the other is TC = end of transmission; compare with the figure below, when the data in TDR is transferred to the shift register, TXE is set, and shift at this time The register starts to transfer data to the TX signal line bit by bit, but because the TDR has become empty, the program can write the next byte to be sent (operation USART_DR) into the TDR without having to wait until all the bits in the shift register are sent. At the end of the bit transmission (after sending the stop bit), the hardware will set the TC flag.

On the other hand, when the USART has just been initialized and no data has been sent, there will also be a TXE flag because the transmit data register is empty.

The meaning of TXEIE and TCIE is very simple. TXEIE allows interrupts to be generated when the TXE flag is '1', while TCIE allows interrupts to be generated when the TC flag is '1'.

As for when to use which logo, you need to decide according to your needs. But I think TXE allows programs to have more time to fill in the TDR register to ensure uninterrupted data flow. TC can let the program know the exact time when the transmission ends, which is helpful for the program to control the timing of the external data flow.

SECTION 4

In general, the serial port of the STM32 microcontroller is well understood, and programming is not too complicated. Of course, I would rather hope that the interrupt system is as simple as the 51 microcontroller.

For the receiving terminal, it is RXNE, which is only generated after the reception is completed, and will not enter the ISR when the USART_ITConfig (USART1, USART_IT_RXNE, ENABLE) code is executed. But the trouble is to send related interrupts: TXE or TC. According to the data and test results, TXE is set after reset, that is, an interrupt request will be generated immediately after executing USART_ITConfig (USART1, USART_IT_TXE, ENABLE). Therefore, this causes a troublesome problem: if there is no real transmission data, TXE interrupts will occur, and there is no pause, which will occupy a large part of CPU time and even affect the operation of other programs!

Therefore, it is recommended that the TXE interrupt is not enabled during initialization, and only enable TXE when data is to be sent (especially a series of data such as strings and arrays). Shut it off immediately after sending to avoid unnecessary trouble.

For sending, you need to pay attention to the difference between TXE and TC-here is a brief description, assuming that the serial data register is DR, the serial port shift register is SR and the TXD pin TXDpin, the relationship is DR-》 SR-》 TXDpin. When the data in DR is transferred to SR, TXE is set to 1. If there is data written to DR, TXE is set to 0; if all the data in SR is moved out through TXDpin and no data enters DR, TC is set to 1. And need to pay attention to TXE can only be set to 0 by writing DR, can not be directly cleared, and TC can be directly cleared by writing 1.

For sending a single character, it can be considered without interruption, and it can be completed directly by query.

For sending string / array data, the only thing to consider is to turn off the sending interrupt only after the last character is sent. There can be two cases: for sending a displayable string, it ends with 0x00, so In ISR, 0x00 is used as a condition to turn off the transmission interrupt (TXE or TC); the second case is to send binary data, that is, any data in the middle of 0x00 ~ 0xFF, you cannot use 0x00 to judge the end, you must know at this time The specific length of the data.

Here is a brief analysis of the execution process of the above code: The TXE interrupt is generated when the previous character is sent from DR to SR, and the execution effect is that the latter character is sent to DR. For the first case, if it is a displayable character, execute USART_SendData to write DR (that is, clear TXE). When the last displayable character is sent from DR to SR, the generated TXE interrupt is found to be sent to DR The character is 0x00-this of course does not work-at this time, the TXE interrupt is turned off, and the string transmission process is completed. Of course, an implicit result cannot be ignored at this time: the TXE is set after the last displayable character is transferred from DR to SR, but the TXE interrupt is turned off, so as long as the TXE interrupt is turned on next time, it will immediately enter the ISR. For the second case, the result is the same as the first.

For the first case, the program can be written like this: where TXS is the string that holds the data to be sent, and TxCounter1 is the index value:

extern __IO uint8_t TxCounter1;

extern uint8_t * TXS;

extern __IO uint8_t TxLen;

void USART1_IRQHandler (void)

{

if (USART_GetITStatus (USART1, USART_IT_TXE)! = RESET)

{

if (TXS [TxCounter1]) // If it is displayable characters

{USART_SendData (USART1, TXS [TxCounter1 ++]);}

else // Close TXE interrupt after sending,

{USART_ITConfig (USART1, USART_IT_TXE, DISABLE);}

}

}

For the second case, the same as above, where TXLen represents the length of the binary data to be sent:

void USART1_IRQHandler (void)

{

if (USART_GetITStatus (USART1, USART_IT_TXE)! = RESET) // Writing USART_DR, clear this bit to zero.

{

if (TxCounter1 "TxLen")

{USART_SendData (USART1, TXS [TxCounter1 ++]);}

else // Close TXE interrupt after sending

{USART_ITConfig (USART1, USART_IT_TXE, DISABLE);}

}

}

In fact, the first case is the second special form, which means that the second case can be used to send displayable characters-of course, no one has the leisure to count how many letter spaces and punctuation marks in a sentence!

In use, just point TXS to the string or array to be sent, set TxLen to the length of the data to be sent, and then execute USART_ITConfig (USART1, USART_IT_TXE, ENABLE) to start the sending process immediately. The user can check TxCounter1 to determine how many bytes were sent. Take the second case as an example:

uint32_t * TXS;

uint8_t TxBuffer1 [] = "0123456789ABCDEF";

uint8_t DST2 [] = "ASDFGHJKL";

__IO uint8_t TxLen = 0x00;

TxLen = 8; // Send 8 characters, the final send is 01234567

TXS = (uint32_t *) TxBuffer1; // Point TXS to the string TxBuffer1

TxCounter1 = 0; // Reset index value

USART_ITConfig (USART1, USART_IT_TXE, ENABLE); // Enable TXE interrupt, that is, start the sending process

while (TxCounter1! = TxLen); // Wait for sending completion

TXS = (uint32_t *) TxBuffer2; // As above, the final transmission is ASDFGHJK

TxCounter1 = 0;

USART_ITConfig (USART1, USART_IT_TXE, ENABLE);

while (TxCounter1! = TxLen);

The above is the best solution I think, but how many times the serial interrupt mode data is interrupted, I think it still takes a lot of CPU time, in contrast, the DMA mode is much better, because the DMA sends a string to interrupt up to two Times (half transmission is completed, full transmission is completed), and the serial port becomes a 16C550-like device.

Anisotropic Ferrite Magnets

Anisotropic magnets are magnets whose magnetization directions in the magnets are aligned in a certain direction.


Magnet powder for anisotropic magnets is composed of a single crystal or polycrystal with an aligned direction of magnetization in one magnet particle. When a magnetic field is applied externally during molding (this magnetic field is called an aligning magnetic field), the magnet powder moves to align with the direction of the magnetic field and is solidified in an aligned state, resulting in an anisotropic magnet. Magnet powder aligned with an aligning magnetic field is solidified with keeping magnetization. Therefore, after removing the alignment magnetic field, the molded body becomes a magnet having a magnetic force.

Anisotropic Ferrite Magnets,Pump Magnet,Cooler Pump Magnet,Submersible Pump Magnet

HU NAN YUBANG MAGNETIC MATERIAL CO.,LTD , https://www.ybmagnet.com