Browse Source

UART works with printf()

Thomas Chef 3 years ago
parent
commit
ca27a74e01
4 changed files with 291 additions and 3 deletions
  1. 9 3
      STM32/Core/Src/main.c
  2. 2 0
      STM32/Core/Src/stm32f1xx_it.c
  3. 241 0
      STM32/Core/Src/uart.c
  4. 39 0
      STM32/Core/Src/uart.h

+ 9 - 3
STM32/Core/Src/main.c

@@ -21,6 +21,7 @@
 
 /* Private includes ----------------------------------------------------------*/
 /* USER CODE BEGIN Includes */
+#include<stdio.h>
 
 /* USER CODE END Includes */
 
@@ -44,9 +45,6 @@ ADC_HandleTypeDef hadc1;
 UART_HandleTypeDef huart2;
 
 /* USER CODE BEGIN PV */
-#define ADC_SAMPLES 15
-uint32_t adcData[ADC_SAMPLES];
-
 uint32_t adcCounter = 0;
 
 /* USER CODE END PV */
@@ -111,6 +109,9 @@ int main(void)
   MX_NVIC_Init();
   /* USER CODE BEGIN 2 */
 
+  // Enable USART1 Interrupts
+  USART2->CR1 |= USART_CR1_RXNEIE | USART_CR1_TXEIE;
+
 
 
   // Start continous ADC-conversion
@@ -125,6 +126,11 @@ int main(void)
 
   /* Infinite loop */
   /* USER CODE BEGIN WHILE */
+
+  printf("VVB Energy Sensor\n");
+
+
+
   while (1)
   {
     /* USER CODE END WHILE */

+ 2 - 0
STM32/Core/Src/stm32f1xx_it.c

@@ -22,6 +22,7 @@
 #include "stm32f1xx_it.h"
 /* Private includes ----------------------------------------------------------*/
 /* USER CODE BEGIN Includes */
+#include "uart.h"
 /* USER CODE END Includes */
 
 /* Private typedef -----------------------------------------------------------*/
@@ -224,6 +225,7 @@ void ADC1_2_IRQHandler(void)
 void USART2_IRQHandler(void)
 {
   /* USER CODE BEGIN USART2_IRQn 0 */
+	usartInterrupt();
 
   /* USER CODE END USART2_IRQn 0 */
   /* USER CODE BEGIN USART2_IRQn 1 */

+ 241 - 0
STM32/Core/Src/uart.c

@@ -0,0 +1,241 @@
+////////////////////////////////////////////////////////////////////////////////////////
+/* enter necessary header files for proper interrupt vector and UART/USART visibility */
+////////////////////////////////////////////////////////////////////////////////////////
+ 
+#include<stdio.h>
+#include "uart.h"
+#include "stm32f1xx_hal.h"
+
+static void usartRxIntHandler();
+static void usartTxIntHandler();
+
+
+volatile uint8_t uart_rx_fifo_not_empty_flag = 0;
+volatile uint8_t uart_rx_fifo_full_flag      = 0;
+volatile uint8_t uart_rx_fifo_ovf_flag       = 0; 
+volatile uint8_t uart_tx_fifo_full_flag      = 0;
+volatile uint8_t uart_tx_fifo_ovf_flag       = 0;
+volatile uint8_t uart_tx_fifo_not_empty_flag = 0;
+
+// ********************************************** USART ************************************************
+
+extern UART_HandleTypeDef huart2;
+
+#ifdef __GNUC__
+
+#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
+
+#else
+#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
+
+#endif
+PUTCHAR_PROTOTYPE
+{
+	unsigned char c=ch;
+
+	while(uart_tx_fifo_full_flag);
+
+	uart_send_byte(c);
+	//HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, 0xFFFF);
+}
+
+
+void usartInterrupt(void) {
+
+  if( USART2->SR & USART_SR_TXE ) {
+      usartTxIntHandler();
+    }
+    if( USART2->SR & USART_SR_RXNE ) {
+      usartRxIntHandler();
+    }
+}
+
+/*int fputc(int iChar, FILE *f)
+{
+    unsigned char c=iChar;
+    
+    while(uart_tx_fifo_full_flag);
+    
+    uart_send_byte(c);
+
+    return iChar;
+}
+
+int fgetc(FILE *f)
+{
+  __IO int i=0;
+  
+  i++;
+    return 1;
+}*/
+
+
+
+// ********************************************** USART ************************************************
+
+
+
+ 
+typedef struct {
+  uint8_t  data_buf[FIFO_BUFFER_SIZE]; // FIFO buffer
+  uint16_t i_first;                    // index of oldest data byte in buffer
+  uint16_t i_last;                     // index of newest data byte in buffer
+  uint16_t num_bytes;                  // number of bytes currently in buffer
+}sw_fifo_typedef;
+ 
+sw_fifo_typedef rx_fifo = { {0}, 0, 0, 0 }; // declare a receive software buffer
+sw_fifo_typedef tx_fifo = { {0}, 0, 0, 0 }; // declare a transmit software buffer
+ 
+ 
+/***************************************************************************************************************/
+// UART receive interrupt sub-routine
+//  - interrupts when valid data exists in rx hardware buffer
+//  - checks if there's room in the rx software buffer
+//  - if there's room, it transfers the received data into the sw buffer
+//  - automatically handles "uart_rx_buffer_full_flag"
+//  - sets overflow flag upon software buffer overflow (doesn't overwrite existing data)
+//////////////////////////////////////////////
+static void usartRxIntHandler() {
+//////////////////////////////////////////////
+   
+  
+  if(rx_fifo.num_bytes == FIFO_BUFFER_SIZE) {      // if the sw buffer is full
+    uart_rx_fifo_ovf_flag = 1;                     // set the overflow flag
+  }else if(rx_fifo.num_bytes < FIFO_BUFFER_SIZE) { // if there's room in the sw buffer
+     
+     
+    rx_fifo.data_buf[rx_fifo.i_last] = USART2->DR; /* enter pointer to UART rx hardware buffer here */ // store the received data as the newest data element in the sw buffer
+     
+    rx_fifo.i_last++;                              // increment the index of the most recently added element
+    rx_fifo.num_bytes++;                           // increment the bytes counter
+  }
+  if(rx_fifo.num_bytes == FIFO_BUFFER_SIZE) {      // if sw buffer just filled up
+    uart_rx_fifo_full_flag = 1;                    // set the RX FIFO full flag
+  }
+  if(rx_fifo.i_last == FIFO_BUFFER_SIZE) {         // if the index has reached the end of the buffer,
+    rx_fifo.i_last = 0;                            // roll over the index counter
+  }
+  uart_rx_fifo_not_empty_flag = 1;                 // set received-data flag
+}
+/***************************************************************************************************************/
+ 
+ 
+/***************************************************************************************************************/
+// UART transmit interrupt sub-routine
+//  - interrupts when the tx hardware buffer is empty
+//  - checks if data exists in the tx software buffer
+//  - if data exists, it places the oldest element of the sw buffer into the tx hardware buffer
+//  - if the sw buffer is emptied, it disables the "hw buffer empty" interrupt
+//  - automatically handles "uart_tx_buffer_full_flag"
+//////////////////////////////////////////////
+static void usartTxIntHandler() {
+ 
+  if(tx_fifo.num_bytes == FIFO_BUFFER_SIZE) { // if the sw buffer is full
+    uart_tx_fifo_full_flag = 0;               // clear the buffer full flag because we are about to make room
+  }
+  if(tx_fifo.num_bytes > 0) {                 // if data exists in the sw buffer
+     
+    USART2->DR = tx_fifo.data_buf[tx_fifo.i_first]; // place oldest data element in the TX hardware buffer
+     
+    tx_fifo.i_first++;                        // increment the index of the oldest element
+    tx_fifo.num_bytes--;                      // decrement the bytes counter
+  }
+  if(tx_fifo.i_first == FIFO_BUFFER_SIZE) {   // if the index has reached the end of the buffer,
+    tx_fifo.i_first = 0;                      // roll over the index counter
+  }
+  if(tx_fifo.num_bytes == 0) {                // if no more data exists
+ 
+    uart_tx_fifo_not_empty_flag = 0;          // clear flag
+ 
+    USART2->CR1 &= ~(USART_CR1_TXEIE);        // Disable TX Empty Interrupt
+  }
+}
+/***************************************************************************************************************/
+ 
+ 
+/***************************************************************************************************************/
+// UART data transmit function
+//  - checks if there's room in the transmit sw buffer
+//  - if there's room, it transfers data byte to sw buffer
+//  - automatically handles "uart_tx_buffer_full_flag"
+//  - sets the overflow flag upon software buffer overflow (doesn't overwrite existing data)
+//  - if this is the first data byte in the buffer, it enables the "hw buffer empty" interrupt
+void uart_send_byte(uint8_t byte) {
+   
+  ///////////////////////////////////////////////////////////
+  /* disable interrupts while manipulating buffer pointers */
+  ///////////////////////////////////////////////////////////
+  unsigned int istate = USART2->CR1 & USART_CR1_TXEIE;
+  USART2->CR1 &= ~(USART_CR1_TXEIE);        // Disable TX Empty Interrupt
+  
+ 
+  if(tx_fifo.num_bytes == FIFO_BUFFER_SIZE) {      // no room in the sw buffer
+    uart_tx_fifo_ovf_flag = 1;                     // set the overflow flag
+  }else if(tx_fifo.num_bytes < FIFO_BUFFER_SIZE) { // if there's room in the sw buffer
+    tx_fifo.data_buf[tx_fifo.i_last] = byte;       // transfer data byte to sw buffer
+    tx_fifo.i_last++;                              // increment the index of the most recently added element
+    tx_fifo.num_bytes++;                           // increment the bytes counter
+  }
+  if(tx_fifo.num_bytes == FIFO_BUFFER_SIZE) {      // if sw buffer is full
+    uart_tx_fifo_full_flag = 1;                    // set the TX FIFO full flag
+  }
+  if(tx_fifo.i_last == FIFO_BUFFER_SIZE) {         // if the "new data" index has reached the end of the buffer,
+    tx_fifo.i_last = 0;                            // roll over the index counter
+  }
+
+  
+    
+  ///////////////////////
+  /* enable interrupts */
+  ///////////////////////
+  if( istate ) 
+    USART2->CR1 |=   USART_CR1_TXEIE;
+ 
+  if(tx_fifo.num_bytes > 0) {                      // if there is data in the buffer
+ 
+    uart_tx_fifo_not_empty_flag = 1;               // set flag
+     
+    USART2->CR1 |= USART_CR1_TXEIE;               // Enable TX Empty Interrupt
+     
+  }
+}
+
+int serialAvailable() {
+  return rx_fifo.num_bytes;
+}
+
+/***************************************************************************************************************/
+// UART data receive function
+//  - checks if data exists in the receive sw buffer
+//  - if data exists, it returns the oldest element contained in the buffer
+//  - automatically handles "uart_rx_buffer_full_flag"
+//  - if no data exists, it clears the uart_rx_flag
+unsigned char serialRead(void) {          
+      
+  ///////////////////////////////////////////////////////////
+  /* disable interrupts while manipulating buffer pointers */
+  ///////////////////////////////////////////////////////////
+  USART2->CR1 &= ~(USART_CR1_RXNEIE);        // Disable RX Empty Interrupt
+   
+  uint8_t byte = 0;
+  if(rx_fifo.num_bytes == FIFO_BUFFER_SIZE) { // if the sw buffer is full
+    uart_rx_fifo_full_flag = 0;               // clear the buffer full flag because we are about to make room
+  }
+  if(rx_fifo.num_bytes > 0) {                 // if data exists in the sw buffer
+    byte = rx_fifo.data_buf[rx_fifo.i_first]; // grab the oldest element in the buffer
+    rx_fifo.i_first++;                        // increment the index of the oldest element
+    rx_fifo.num_bytes--;                      // decrement the bytes counter
+  }else{                                      // RX sw buffer is empty
+    uart_rx_fifo_not_empty_flag = 0;          // clear the rx flag
+  }
+  if(rx_fifo.i_first == FIFO_BUFFER_SIZE) {   // if the index has reached the end of the buffer,
+    rx_fifo.i_first = 0;                      // roll over the index counter
+  }
+ 
+  ///////////////////////
+  /* enable interrupts */
+  ///////////////////////
+  USART2->CR1 |= USART_CR1_RXNEIE;
+ 
+  return (unsigned char)byte;                                // return the data byte
+}

+ 39 - 0
STM32/Core/Src/uart.h

@@ -0,0 +1,39 @@
+#ifndef __SW_FIFO__
+#define __SW_FIFO__
+
+
+#include <stdint.h>
+
+#define FIFO_BUFFER_SIZE 128 // software buffer size (in bytes)
+
+//typedef uint8_t unsigned char
+
+// UART data transmit function
+//  - checks if there's room in the transmit sw buffer
+//  - if there's room, it transfers data byte to sw buffer 
+//  - automatically handles "uart_tx_buffer_full_flag"
+//  - sets the overflow flag upon software buffer overflow (doesn't overwrite existing data)
+//  - if this is the first data byte in the buffer, it enables the "hw buffer empty" interrupt
+void uart_send_byte(uint8_t byte);
+
+
+// UART data receive function
+//  - checks if data exists in the receive sw buffer
+//  - if data exists, it returns the oldest element contained in the buffer 
+//  - automatically handles "uart_rx_buffer_full_flag"
+//  - if no data exists, it clears the uart_rx_flag
+uint8_t uart_get_byte(void);
+
+volatile extern uint8_t uart_rx_fifo_not_empty_flag; // this flag is automatically set and cleared by the software buffer
+volatile extern uint8_t uart_rx_fifo_full_flag;      // this flag is automatically set and cleared by the software buffer
+volatile extern uint8_t uart_rx_fifo_ovf_flag;       // this flag is not automatically cleared by the software buffer
+volatile extern uint8_t uart_tx_fifo_full_flag;      // this flag is automatically set and cleared by the software buffer
+volatile extern uint8_t uart_tx_fifo_ovf_flag;       // this flag is not automatically cleared by the software buffer
+volatile extern uint8_t uart_tx_fifo_not_empty_flag; // this flag is automatically set and cleared by the software buffer
+
+void usartInterrupt(void);
+
+int serialAvailable();
+unsigned char serialRead(void);
+
+#endif