/* Programmbeispiel für serielle Ausgabe USART3 per ISR Alle Funktionen ohne Gewähr Michael Nowak 2020-10-20 www.mino-elektronik.de */ #define _USART3 #define PRIO_USART3 10 // mittlere Priorität #include "stm32f4xx.h" #define BIT(x) (1<BRR = SystemCoreClock/APB1_TEILER/baud; return(0); } void USART3_IRQHandler(void) { uint32_t temp, sr_temp; uint32_t temp_zeiger; sr_temp = USART3->SR; if(sr_temp & USART_SR_TXE) { // Tx-Flag testen if(usart3_tx_schreib_zeiger != usart3_tx_lese_zeiger) { // noch zeichen im puffer USART3->DR = usart3_tx_puffer[usart3_tx_lese_zeiger++]; // Zeichen ausgeben usart3_tx_lese_zeiger &= TX3_BUF_MASK; } else { USART3->CR1 &= ~USART_CR1_TXEIE; // sonst weitere Interrupts sperren */ __ISB(); // Abwarten } } if(sr_temp & USART_SR_RXNE) { // Rx-Flag testen temp = USART3->DR; // Zeichen lesen temp_zeiger = (usart3_rx_schreib_zeiger + 1) & RX3_BUF_MASK; if( temp_zeiger != usart3_rx_lese_zeiger) { usart3_rx_puffer[usart3_rx_schreib_zeiger] = temp; usart3_rx_schreib_zeiger = temp_zeiger; } } } void clr_tx3_buf() { USART3->CR1 &= ~(USART_CR1_TXEIE); // TXIE abschalten __ISB(); usart3_tx_lese_zeiger = 0; usart3_tx_schreib_zeiger = 0; } void clr_rx3_buf() { USART3->CR1 &= ~(USART_CR1_RXNEIE); // RXIE abschalten __ISB(); usart3_rx_lese_zeiger = 0; usart3_rx_schreib_zeiger = 0; USART3->CR1 |= (USART_CR1_RXNEIE); // RXIE einschalten } void init_usart3(void) { RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN; RCC->APB1ENR |= RCC_APB1ENR_USART3EN; // AF für USART3 GPIOB->MODER |= (AF << (TxD3_Pin * 2) | AF << (RxD3_Pin * 2)); // USART3 Alternative-Funktions mit den IO-Pins verbinden GPIOB->AFR[1] |= (AFR_USART3 << ((TxD3_Pin-8) * 4) | AFR_USART3 << ((RxD3_Pin-8) * 4)); // alle weiteren Einstellungen default 8N1 set_baudrate3(DEF_BAUDRATE); // enable UART Interrupt-Vector NVIC_SetPriority(USART3_IRQn,PRIO_USART3); NVIC_EnableIRQ(USART3_IRQn); // USART3 aktivieren clr_rx3_buf(); clr_tx3_buf(); // RXIE und Rx + Tx einschalten USART3->CR1 |= USART_CR1_RXNEIE | USART_CR1_UE | USART_CR1_RE | USART_CR1_TE; ser_status = 1; // ist initialisiert } void write_tx3_buf(char c) { uint32_t temp_zeiger; if(!ser_status) init_usart3() ; do { temp_zeiger = (usart3_tx_schreib_zeiger + 1) & TX3_BUF_MASK; } while( temp_zeiger == usart3_tx_lese_zeiger); // warten, bis wieder platz ist usart3_tx_puffer[usart3_tx_schreib_zeiger] = c; usart3_tx_schreib_zeiger = temp_zeiger; USART3->CR1 |= USART_CR1_TXEIE; // per Interrupt ausgeben } char read_rx3_buf() { int32_t temp = 0; // default bei leerem Puffer if(!ser_status) init_usart3() ; if(usart3_rx_lese_zeiger != usart3_rx_schreib_zeiger) { temp = usart3_rx_puffer[usart3_rx_lese_zeiger++]; usart3_rx_lese_zeiger &= RX3_BUF_MASK; } return(temp); } uint32_t read_rx3_buf_count() { return((usart3_rx_schreib_zeiger - usart3_rx_lese_zeiger) & RX3_BUF_MASK); } int32_t putchar(int32_t x) { if((uint8_t)x == 10) write_tx3_buf(13); write_tx3_buf((uint8_t)x); return(x); } void sende_string(char *s) { while(*s) write_tx3_buf(*(s++)); putchar(10); }