void USART2_IRQHandler(void)
{
/* USER CODE BEGIN USART2_IRQn 0 */
/* UART IDLE Interrupt */
if(__HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE) == SET)
{
__HAL_UART_CLEAR_IDLEFLAG(&huart2);
print("time %d",timeCounter");
receivedDataFlag = 1;
}
}
Wenn ich diese Funktion verwende, überprüfe den Ruhezustand der Leitung und entscheide, welche Daten empfangen oder nicht empfangen werden. Aber dieser Interrupt löst beim Senden aus. Wie kann ich Datenempfangsleitungsruhe und Empfangsruhe trennen?
Ich möchte auslösen, dass nur die Datenleitung leer ist, wie kann ich das tun? Welches andere Register sollte ich mir ansehen?
Ich bekomme ein sehr interessantes Ergebnis,
Sender sendet alle 100 ms Daten an mein Gerät;
Wenn ich nur die DMA-Funktionen empfange; Zeitrückgabe 10, 110, 220,330 (Ruhezustände arbeiten)
Aber wenn ich als nach dem Senden von Daten mit uart dieses Mal Werte 10,13,15, ... zurückbekomme, ändert eine mittlere Sendefunktion den Leitungsruhezustand, wie ist das möglich? Bezieht sich UART_FLAG_IDLE nur auf RX?
BEARBEITEN: Übrigens verwende ich rs485. Wenn ich also mit dem Senden beginne, stelle ich den Transceiver-Sendermodus ein, also den senderseitigen Empfängermodus, damit meine MCU diesen Zustand in den Leerlauf versetzt? ist das möglich? Wie kann ich diese Situation schützen?
Wenn ich nach empfangenen Daten den Übertragungsmodus starte, dann abgeschlossener Rückruf, wenn ich die HAL_UART_Receive_DMA(&huart2,(uint8_t*)dma_rx_buf,DMA_BUF_SIZE); Funktion IDLE Interrupt wird alle 5 ms ausgelöst, aber Timeout für das Senden von Daten beträgt 100 ms
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
HAL_UART_DMAStop(&huart2);
dmaTransmitCompletedFlag = 1;
RS485_Set_Receive_Mode();
HAL_UART_Receive_DMA(&huart2,(uint8_t*)dma_rx_buf,DMA_BUF_SIZE);
waitForTransmittingData = 0;
}
Dieser Interrupt wird sowohl zum Senden als auch zum Empfangen verwendet.
Das IDLE ist nur für den Empfang relevant, es bedeutet, dass mindestens ein vollständiger Rahmen des Leerlaufs erkannt wird.
Die Verwendung von print in einem Interrupt ist unklug, insbesondere wenn der Druck denselben UART verwendet, für den der Interrupt ist.
Dieser IRQ ist für USART2 bestimmt, wird aber für jeden aktivierten Interrupt aufgerufen , der USART2 zugeordnet ist. Das bedeutet, dass der Handler jedes aktivierte Interrupt-Signal prüfen und verarbeiten muss. Für STM32 USART umfasst dies Signale, die für unterbrechungsgesteuerte UART wie TXNE und RXNE von grundlegender Bedeutung sind, sowie Fehlersignale, IDLE usw.
Das IDLE-Signal dient zum Framing von Multibyte-Empfängen (ein häufiges Problem für USART, insbesondere in lauten Umgebungen). Es wird aktiviert, wenn die Empfangsleitung für eine gewisse Entprellzeit (bestimmt durch die Baudrate/Oversampling-Einstellungen) hoch (oder „idle“) aktiviert wurde, nachdem diese Leitung aktiv war (während des Empfangs einer Gruppe von einem oder mehreren Bytes). . Dies ist nützlich, da Sie damit Ihren Empfangspuffer auf den Index '0' zurücksetzen können, damit der nächste Frame richtig aufgereiht wird (auch wenn im aktuellen Frame zu wenige oder zu viele Bytes empfangen wurden). Normalerweise müssen Sie diese Art von Logik mit einem dedizierten Timer-Peripheriegerät implementieren, aber STM32 packt es bequem in seine USART-Peripheriegeräte (obwohl es vom nativen HAL-Treiber nicht unterstützt wird).
Wenn Sie wirklich möchten, dass nur das Leerlaufsignal einen Interrupt auslöst, müssen Sie jedes andere Interrupt-Signal manuell deaktivieren. Wenn Sie einen nützlichen Interrupt-gesteuerten UART-Empfänger wollen, schlage ich nicht vor, dass Sie das tun.
Aus einer Ihrer vorherigen Fragen habe ich Ihnen einige Links gegeben, wo dies implementiert ist.
USART3_IRQHandler(void) {
/* Check for IDLE line interrupt */
if (LL_USART_IsEnabledIT_IDLE(USART3) && LL_USART_IsActiveFlag_IDLE(USART3)) {
LL_USART_ClearFlag_IDLE(USART3); /* Clear IDLE line flag */
usart_rx_check(); /* Check for data to process */
}
/* Implement other events when needed */
}
Edelstahlratte
Nur ich
Edelstahlratte
Jeroen3