Skip to main content
DRicc.2
Associate III
August 1, 2024
Solved

How do I declare a UART Function in a separate C file?

I have a program that displays the current temperature of a room on the UART terminal and I want to start getting into the habit of separating my functions into their own source and header files, however, I'm running into a couple of problems. 

Here is my main header file:

 

#include "main.h" //Main header file
#include <stdio.h> //Standard header filer
#include <string.h> //String header filer
#include "uart.h"


#define SI7021_ADDRESS_READ (0x40 << 1) | 0x01
#define SI7021_ADDRESS_WRITE (0x40 << 1)
#define SI7021_MEASURE_HUM_NOHOLD 0xF5
#define SI7021_MEASURE_TEMP_NOHOLD 0xF3



char msg[50];


I2C_HandleTypeDef hi2c1;

UART_HandleTypeDef huart2;



void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_I2C1_Init(void);
static void MX_USART2_UART_Init(void);





static uint32_t si7021_measure_humidity(I2C_HandleTypeDef *hi2c)
{
 uint8_t si7021_buf[4];
 si7021_buf[0] = SI7021_MEASURE_HUM_NOHOLD;

 // Start measure
 int res = HAL_I2C_Master_Transmit(hi2c, SI7021_ADDRESS_WRITE, si7021_buf, 1, 100);

 if (res != HAL_OK)
 {
 return sprintf(msg,"ERROR - Could Not Transmit Humidity\r\n");
 uart_send_str (msg);

 }
 HAL_Delay(30);

 // Read result
 res = HAL_I2C_Master_Receive(hi2c, SI7021_ADDRESS_READ, si7021_buf, 2, 100);
 if (res != HAL_OK)
 {
	 return sprintf(msg,"ERROR - Could Not Receive Humidity\r\n");
	 uart_send_str (msg);
 }

 return (si7021_buf[0] << 8 | si7021_buf[1]) * 125 / 65536 - 6;
}

static int32_t si7021_measure_temperature(I2C_HandleTypeDef *hi2c)
{
	 uint8_t si7021_buf[4];
	 si7021_buf[0] = SI7021_MEASURE_TEMP_NOHOLD;

	 // Start measure
	 int res = HAL_I2C_Master_Transmit(hi2c, SI7021_ADDRESS_WRITE, si7021_buf, 1, 100);
	 if (res != HAL_OK)
	 {
	 return sprintf(msg,"ERROR - Could Not Transmit Humidity\r\n");
	 uart_send_str (msg);

	 }
	 HAL_Delay(30);

	 // Read result
	 res = HAL_I2C_Master_Receive(hi2c, SI7021_ADDRESS_READ, si7021_buf, 2, 100);
	 if (res != HAL_OK)
	 {
		 return sprintf(msg,"ERROR - Could Not Receive Humidity\r\n");
		 uart_send_str (msg);
	 }

	 int64_t temp_code = (si7021_buf[0] << 8 | si7021_buf[1]) * 100;
	 int64_t temp = 17572 * temp_code / 6553500 - 4685;

	 if (temp > 12500 || temp < -4000)
	 {
		 return sprintf(msg,"ERROR - Temperature could not be read properly!\r\n");
		 uart_send_str (msg);
	 }
	 return (int32_t)temp;
}

int main(void)
{

 HAL_Init();


 SystemClock_Config();


 MX_GPIO_Init();
 MX_I2C1_Init();
 MX_USART2_UART_Init();

 while (1)
 {
 uint32_t humidity = si7021_measure_humidity(&hi2c1);
 if (humidity == 0xFFFF){

 }
 uint32_t temperature = si7021_measure_temperature(&hi2c1);
 float temp_C = temperature/100;
 sprintf(msg, "%2f C %lu RH\r\n", temp_C, humidity);
 uart_send_str (msg);


 HAL_Delay(500);
 }

}

 My Uart header file:

#ifndef uart_h
#define uart_h

void uart_send_str (const char* msg);

#endif

My Uart C file:

#include <stdio.h>
#include "uart.h"
#include <stdint.h>


void uart_send_str (const char* msg)
{
	HAL_UART_Transmit(&huart2, (uint8_t*)msg, strlen(msg), HAL_MAX_DELAY);
}

 

I get the following errors:

'huart2' undeclared - first use of this function"

'HAL_MAX_DELAY' undeclared - first use of this function"

 

Along with an implicit declaration of HAL_UART_Transmit function as a warning.

I know you have to initialize the function before you declare it as typically seen in the main with the "static void MX_USART2_UART_Init(void);" function, but I don't know how to do this in a separate header file.

    This topic has been closed for replies.
    Andrew Neil
    Andrew NeilBest answer
    Super User
    August 1, 2024

    @DRicc.2 wrote:

    Here is my main header file:

     

    #include "main.h" //Main header file
    #include <stdio.h> //Standard header filer
    #include <string.h> //String header filer
    #include "uart.h"
    
    
    #define SI7021_ADDRESS_READ (0x40 << 1) | 0x01
    #define SI7021_ADDRESS_WRITE (0x40 << 1)
    #define SI7021_MEASURE_HUM_NOHOLD 0xF5
    #define SI7021_MEASURE_TEMP_NOHOLD 0xF3
    
    
    
    char msg[50];
    
    
    I2C_HandleTypeDef hi2c1;
    
    UART_HandleTypeDef huart2;
    
    
    
    void SystemClock_Config(void);
    static void MX_GPIO_Init(void);
    static void MX_I2C1_Init(void);
    static void MX_USART2_UART_Init(void);
    
    
    
    
    
    static uint32_t si7021_measure_humidity(I2C_HandleTypeDef *hi2c)
    {
    
    :
    :
    :
    etc...

     


    No, that's not a header file - that's a .c file.

    In that .c you have some definitions that you want to share:

     

    char msg[50];
    
    I2C_HandleTypeDef hi2c1;
    
    UART_HandleTypeDef huart2;

     

    So you need to make a header with extern declaration for those - let's call it my_main_header.h:

     

    extern char msg[50];
    
    exterm I2C_HandleTypeDef hi2c1;
    
    extern UART_HandleTypeDef huart2;

     

    Then you need to include that header in your Uart C file:

     

    #include <stdio.h>
    #include "uart.h"
    #include <stdint.h>
    
    #include "my_main_header.h" // The declaration of huart2 is here
    
    void uart_send_str (const char* msg)
    {
     HAL_UART_Transmit(&huart2, (uint8_t*)msg, strlen(msg), HAL_MAX_DELAY); // You are using huart2 here
    }

     

     

     

    A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.

    5 replies

    Andrew Neil
    Super User
    August 1, 2024

    See:

    https://community.st.com/t5/stm32cubeide-mcus/adding-new-c-source-files-to-my-project-and-navigating-through/m-p/657455/highlight/true#M25847

     

    Sorry, ignore the rest of this post - I was misled by

     

    @DRicc.2 wrote:

    Here is my main header file:


    It's not a header - it's a .c file!

     

     


    @DRicc.2 wrote:

    I get the following errors:

    'huart2' undeclared - first use of this function"

    'HAL_MAX_DELAY' undeclared - first use of this function"


     

     

    That's because huart2 is declared in your "main header file", but you haven't included that in your Uart C file.

    Your Uart C file should have:

     

     

     

    #include <stdio.h>
    #include "uart.h"
    #include <stdint.h>
    
    #include "my_main_header_file.h" // You missed this.
     // This is where huart2 is declared.
    
    void uart_send_str (const char* msg)
    {
    	HAL_UART_Transmit(&huart2, (uint8_t*)msg, strlen(msg), HAL_MAX_DELAY);
    }

     

     

     

     

     

    EDIT:

    I can't see HAL_MAX_DELAY defined in anything you posted.

     

    Also note that

     

     

    char msg[50];
    
    I2C_HandleTypeDef hi2c1;
    
    UART_HandleTypeDef huart2;

     

     

    should not be in a header.

     

    They are definitions - the header should just have the extern declarations:

     

     

    extern char msg[50];
    
    extern I2C_HandleTypeDef hi2c1;
    
    extern UART_HandleTypeDef huart2;

     

     

     

     

    and the definition should be in a .c file (or files) somewhere.

     

    A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
    Tesla DeLorean
    Guru
    August 1, 2024

    need

    extern UART_HandleTypeDef huart2; // in main.h or as used in uart.c

     

    As for HAL_MAX_DELAY, probably that you need to pull in the HAL include files, is main.h doing that currently, or main.c ??

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    TDK
    August 1, 2024

    If you're using CubeMX generated code, #including main.h should pull in everything you need. Put that at the top of your header file.

    "If you feel a post has answered your question, please click ""Accept as Solution""."
    Andrew Neil
    Andrew NeilBest answer
    Super User
    August 1, 2024

    @DRicc.2 wrote:

    Here is my main header file:

     

    #include "main.h" //Main header file
    #include <stdio.h> //Standard header filer
    #include <string.h> //String header filer
    #include "uart.h"
    
    
    #define SI7021_ADDRESS_READ (0x40 << 1) | 0x01
    #define SI7021_ADDRESS_WRITE (0x40 << 1)
    #define SI7021_MEASURE_HUM_NOHOLD 0xF5
    #define SI7021_MEASURE_TEMP_NOHOLD 0xF3
    
    
    
    char msg[50];
    
    
    I2C_HandleTypeDef hi2c1;
    
    UART_HandleTypeDef huart2;
    
    
    
    void SystemClock_Config(void);
    static void MX_GPIO_Init(void);
    static void MX_I2C1_Init(void);
    static void MX_USART2_UART_Init(void);
    
    
    
    
    
    static uint32_t si7021_measure_humidity(I2C_HandleTypeDef *hi2c)
    {
    
    :
    :
    :
    etc...

     


    No, that's not a header file - that's a .c file.

    In that .c you have some definitions that you want to share:

     

    char msg[50];
    
    I2C_HandleTypeDef hi2c1;
    
    UART_HandleTypeDef huart2;

     

    So you need to make a header with extern declaration for those - let's call it my_main_header.h:

     

    extern char msg[50];
    
    exterm I2C_HandleTypeDef hi2c1;
    
    extern UART_HandleTypeDef huart2;

     

    Then you need to include that header in your Uart C file:

     

    #include <stdio.h>
    #include "uart.h"
    #include <stdint.h>
    
    #include "my_main_header.h" // The declaration of huart2 is here
    
    void uart_send_str (const char* msg)
    {
     HAL_UART_Transmit(&huart2, (uint8_t*)msg, strlen(msg), HAL_MAX_DELAY); // You are using huart2 here
    }

     

     

     

    A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
    DRicc.2
    DRicc.2Author
    Associate III
    August 1, 2024

    I read the file wrong, yes it is the main.c and not main.h silly mistake...

    Extern variables make a lot of sense, I knew there was a way to call the functions from the main in separate c files but didn't know how. Thank you very much!