STM32驱动程序开发中的C编译错误

2cmtqfgy  于 2023-05-06  发布在  其他
关注(0)|答案(1)|浏览(224)

我正在为STM32 MCU开发自己的驱动程序,但当我试图编译代码时,总是出现相同的错误。下面是我开发的所有文件的完整代码。

main.c

#include "stm32f103xx.h"

void delay(void);

int main(void){
    GPIO_Handle_t GPIOLed;
    GPIOLed.pGPIOx = GPIOA;
    GPIOLed.GPIO_PinConfig.GPIO_PinNumber = GPIO_PIN_5;
    GPIOLed.GPIO_PinConfig.GPIO_PinMode = GPIO_MODE_OUTPUT_10MHZ;
    GPIO_PeriClockControl(GPIOA, ENABLE);
    GPIO_Init(&GPIOLed);

    while(1){
        GPIO_ToggleOutputPin(GPIOA, GPIO_PIN_5);
        delay();
    }
    return 0;
}

void delay(void){
    for(uint32_t i=0;i<500000;i++){
        ;
    }
}

stm32f103xx.h**

#ifndef INC_STM32F103XX_H_
#define INC_STM32F103XX_H_

#include <stdint.h> /* Native library to use unsigned integers of 8, 16 and 32 bits */

#define FLASH_BASEADDR              0x08000000U /* Start address of the embedded Flash memory */
#define SRAM1_BASEADDR              0x20000000U /* Start address of the embedded SRAM memory */

#define PERIPH_BASE                 0x40000000U /* Start address of the peripheral bus */
#define APB1PERIPH_BASE             PERIPH_BASE /* Start address of the APB1 bus */
#define APB2PERIPH_BASE             0x40010000U /* Start address of the APB2 bus */
#define APHPERIPH_BASE              0x40018000U /* Start address of the AHB bus */
#define RCC_BASEADDR                (APHPERIPH_BASE + 0x9000)

/* Address from APB2 Peripherals APB2 */
#define GPIOA_BASEADDR              (APB2PERIPH_BASE + 0x0800)
#define GPIOB_BASEADDR              (APB2PERIPH_BASE + 0x0C00)
#define GPIOC_BASEADDR              (APB2PERIPH_BASE + 0x1000)
#define GPIOD_BASEADDR              (APB2PERIPH_BASE + 0x1400)
#define GPIOE_BASEADDR              (APB2PERIPH_BASE + 0x1800)
#define GPIOF_BASEADDR              (APB2PERIPH_BASE + 0x1C00)
#define GPIOG_BASEADDR              (APB2PERIPH_BASE + 0x2000)
#define EXTI_BASEADDR               0x40010400 /* Start address of the EXTI bus */

/* Address from APB1 Peripherals APB1 */
#define SPI2_BASEADDR               (APB1PERIPH_BASE + 0x3800)
#define SPI3_BASEADDR               (APB1PERIPH_BASE + 0x3C00)
#define USART2_BASEADDR             (APB1PERIPH_BASE + 0x4400)
#define USART3_BASEADDR             (APB1PERIPH_BASE + 0x4800)
#define UART4_BASEADDR              (APB1PERIPH_BASE + 0x4C00)
#define UART5_BASEADDR              (APB1PERIPH_BASE + 0x5000)
#define I2C1_BASEADDR               (APB1PERIPH_BASE + 0x5400)
#define I2C2_BASEADDR               (APB1PERIPH_BASE + 0x5800)

/* Structure to hold the registers from GPIOs on STM32F103xx */
typedef struct{
    volatile uint32_t CRL;
    volatile uint32_t CRH;
    volatile uint32_t IDR;
    volatile uint32_t ODR;
    volatile uint32_t BSRR;
    volatile uint32_t BRR;
    volatile uint32_t LCKR;
}GPIO_RegDef_t;

/* Structure to hold the registers from RCC on STM32F103xx*/
typedef struct{
    volatile uint32_t CR;
    volatile uint32_t CFGR;
    volatile uint32_t CIR;
    volatile uint32_t APB2RSTR;
    volatile uint32_t APB1RSTR;
    volatile uint32_t AHBENR;
    volatile uint32_t APB2ENR;
    volatile uint32_t APB1ENR;
    volatile uint32_t BDCR;
    volatile uint32_t CSR;
    volatile uint32_t AHBSTR;
    volatile uint32_t CFGR2;
}RCC_RegDef_t;

/* Macro for GPIOs memory positions */
# define GPIOA                      ((GPIO_RegDef_t*) GPIOA_BASEADDR)
# define GPIOB                      ((GPIO_RegDef_t*) GPIOB_BASEADDR)
# define GPIOC                      ((GPIO_RegDef_t*) GPIOC_BASEADDR)
# define GPIOD                      ((GPIO_RegDef_t*) GPIOD_BASEADDR)
# define GPIOE                      ((GPIO_RegDef_t*) GPIOE_BASEADDR)
# define GPIOF                      ((GPIO_RegDef_t*) GPIOF_BASEADDR)
# define GPIOG                      ((GPIO_RegDef_t*) GPIOG_BASEADDR)

GPIO_RegDef_t *pGPIOA = GPIOA;
GPIO_RegDef_t *pGPIOB = GPIOB;
GPIO_RegDef_t *pGPIOC = GPIOC;
GPIO_RegDef_t *pGPIOD = GPIOD;
GPIO_RegDef_t *pGPIOE = GPIOE;
GPIO_RegDef_t *pGPIOF = GPIOF;
GPIO_RegDef_t *pGPIOG = GPIOG;

/* Macro for RCC memory position */
#define RCC                         ((RCC_RegDef_t*) RCC_BASEADDR)

/* Macro for clock enable on APB2 bus peripherals */
#define GPIOA_PCLK_EN               (RCC->APB2ENR |= (1 << 2))
#define GPIOB_PCLK_EN               (RCC->APB2ENR |= (1 << 3))
#define GPIOC_PCLK_EN               (RCC->APB2ENR |= (1 << 4))
#define GPIOD_PCLK_EN               (RCC->APB2ENR |= (1 << 5))
#define GPIOE_PCLK_EN               (RCC->APB2ENR |= (1 << 6))

/* Macro for clock enable on APB1 bus peripherals */
#define SPI2_PCLK_EN                (RCC->APB1ENR |= (1 << 14))
#define SPI3_PCLK_EN                (RCC->APB1ENR |= (1 << 15))
#define USART2_PCLK_EN              (RCC->APB1ENR |= (1 << 17))
#define USART3_PCLK_EN              (RCC->APB1ENR |= (1 << 18))
#define UART4_PCLK_EN               (RCC->APB1ENR |= (1 << 19))
#define UART5_PCLK_EN               (RCC->APB1ENR |= (1 << 20))
#define I2C1_PCLK_EN                (RCC->APB1ENR |= (1 << 21))
#define I2C2_PCLK_EN                (RCC->APB1ENR |= (1 << 22))

/* Macro for clock disable on APB2 bus peripherals */
#define GPIOA_PCLK_DI               (RCC->APB2ENR &= ~(1 << 2))
#define GPIOB_PCLK_DI               (RCC->APB2ENR &= ~(1 << 3))
#define GPIOC_PCLK_DI               (RCC->APB2ENR &= ~(1 << 4))
#define GPIOD_PCLK_DI               (RCC->APB2ENR &= ~(1 << 5))
#define GPIOE_PCLK_DI               (RCC->APB2ENR &= ~(1 << 6))

/* Macro for clock disable on APB1 bus peripherals */
#define SPI2_PCLK_DI                RCC->APB1ENR &= ~(1 << 14)
#define SPI3_PCLK_DI                RCC->APB1ENR &= ~(1 << 15)
#define USART2_PCLK_DI              RCC->APB1ENR &= ~(1 << 17)
#define USART3_PCLK_DI              RCC->APB1ENR &= ~(1 << 18)
#define UART4_PCLK_DI               RCC->APB1ENR &= ~(1 << 19)
#define UART5_PCLK_DI               RCC->APB1ENR &= ~(1 << 20)
#define I2C1_PCLK_DI                RCC->APB1ENR &= ~(1 << 21)
#define I2C2_PCLK_DI                RCC->APB1ENR &= ~(1 << 22)

/* Macro to reset the GPIOx registers */
#define GPIOA_REG_RESET()           do {(RCC->APB2RSTR |= (1 << 2));    (RCC->APB2RSTR &= (1 << 2));} while(0)
#define GPIOB_REG_RESET()           do {(RCC->APB2RSTR |= (1 << 3));    (RCC->APB2RSTR &= (1 << 3));} while(0)
#define GPIOC_REG_RESET()           do {(RCC->APB2RSTR |= (1 << 4));    (RCC->APB2RSTR &= (1 << 4));} while(0)
#define GPIOD_REG_RESET()           do {(RCC->APB2RSTR |= (1 << 5));    (RCC->APB2RSTR &= (1 << 5));} while(0)
#define GPIOE_REG_RESET()           do {(RCC->APB2RSTR |= (1 << 6));    (RCC->APB2RSTR &= (1 << 6));} while(0)

#define ENABLE                      1
#define DISABLE                     0
#define SET                         ENABLE
#define RESET                       DISABLE
#define GPIO_PIN_SET                SET
#define GPIO_PIN_RESET              RESET

#include "stm32f103xx_gpio_driver.h"

#endif

stm32f103xx_gpio_driver.h**

#ifndef INC_STM32F103XX_GPIO_DRIVER_H_
#define INC_STM32F103XX_GPIO_DRIVER_H_

#include "stm32f103xx.h"

typedef struct{
    uint8_t GPIO_PinNumber;
    uint8_t GPIO_PinMode;
    uint8_t GPIO_PinSpeed;
    uint8_t GPIO_PinPuPdControl;
    uint8_t GPIO_PinOPType;
    uint8_t GPIO_PinAltFunMode;
}GPIO_PinConfig_t;

typedef struct{
    GPIO_RegDef_t *pGPIOx;              /* Holds the base address of the GPIO port to which the pin belongs */
    GPIO_PinConfig_t GPIO_PinConfig;    /* Holds the GPIO pin configuration settings */
}GPIO_Handle_t;

/* GPIO possible modes */
#define GPIO_MODE_INPUT         0
#define GPIO_MODE_OUTPUT_10MHZ  1
#define GPIO_MODE_OUTPUT_2MHZ   2
#define GPIO_MODE_OUTPUT_50MHZ  3

/* GPIO output mode */
#define GPIO_OUT_PP             0
#define GPIO_OUT_OD             1
#define GPIO_ALT_PP             2
#define GPIO_ALT_OD             3

/* GPIO input mode */
#define GPIO_IN_ANL             0
#define GPIO_IN_FI              1
#define GPIO_IN_PUPD            2

/* GPIO pin number */
#define GPIO_PIN_0              0
#define GPIO_PIN_1              1
#define GPIO_PIN_2              2
#define GPIO_PIN_3              3
#define GPIO_PIN_4              4
#define GPIO_PIN_5              5
#define GPIO_PIN_6              6
#define GPIO_PIN_7              7
#define GPIO_PIN_8              8
#define GPIO_PIN_9              9
#define GPIO_PIN_10             10
#define GPIO_PIN_11             11
#define GPIO_PIN_12             12
#define GPIO_PIN_13             13
#define GPIO_PIN_14             14
#define GPIO_PIN_15             15

/***************************************************************************************************
 *                              APIs supported by this driver
 *                  For more informations about the APIs check the function definitions
************************************************************************************************** */

/*
 * Peripheral clock setup
 */

void GPIO_PeriClockControl(GPIO_RegDef_t *pGPIOx, uint8_t EnorDi);

/*
 * Initialize and Disable Initialization
 */
void GPIO_Init(GPIO_Handle_t *pGPIOHandle);
void GPIO_Deinit(GPIO_RegDef_t *pGPIOx);

/*
 * Data read and write
 */
uint8_t GPIO_ReadFromInputPin(GPIO_RegDef_t *pGPIOx, uint8_t PinNumber);
uint16_t GPIO_ReadFromInputPort(GPIO_RegDef_t *pGPIOx);
void GPIO_WriteToOutputPin(GPIO_RegDef_t *pGPIOx, uint8_t PinNumber, uint8_t Value);
void GPIO_WriteToOutputPort(GPIO_RegDef_t *pGPIOx, uint8_t Value);
void GPIO_ToggleOutputPin(GPIO_RegDef_t *pGPIOx, uint8_t PinNumber);

/*
 * IRQ Configuration and ISR Handling
 */
void GPIO_IRQConfig(uint8_t IRQNumber, uint8_t IRQPriority, uint8_t EnorDi);
void GPIO_IRQHandling(uint8_t PinNumber);

#endif

stm32f103xx_gpio_driver.c**

#include "stm32f103xx_gpio_driver.h"
/*
 * Peripheral clock setup
 */

void GPIO_PeriClockControl(GPIO_RegDef_t *pGPIOx, uint8_t EnorDi){
    if(EnorDi == ENABLE){
        if(pGPIOx == GPIOA)
            GPIOA_PCLK_EN;
        else if(pGPIOx == GPIOB)
            GPIOB_PCLK_EN;
        else if(pGPIOx == GPIOC)
            GPIOC_PCLK_EN;
        else if(pGPIOx == GPIOD)
            GPIOD_PCLK_EN;
        else if(pGPIOx == GPIOE)
            GPIOE_PCLK_EN;
    }
    else{
        if(pGPIOx == GPIOA)
            GPIOA_PCLK_DI;
        else if(pGPIOx == GPIOB)
            GPIOB_PCLK_DI;
        else if(pGPIOx == GPIOC)
            GPIOC_PCLK_DI;
        else if(pGPIOx == GPIOD)
            GPIOD_PCLK_DI;
        else if(pGPIOx == GPIOE)
            GPIOE_PCLK_DI;
    }
}

/*
 * Initialize and Disable Initialization
 */
void GPIO_Init(GPIO_Handle_t *pGPIOHandle){
    uint32_t temp; /* Temporary variable to set the bits on GPIO registers */

    /* Configuration of the GPIO pin register depending from the port selected */
    temp = (pGPIOHandle->GPIO_PinConfig.GPIO_PinMode << (2*pGPIOHandle->GPIO_PinConfig.GPIO_PinNumber));

    if(pGPIOHandle->GPIO_PinConfig.GPIO_PinNumber <= 7)
        pGPIOHandle->pGPIOx->CRL |= temp;
    else
        pGPIOHandle->pGPIOx->CRH |= temp;
    temp = 0;

    /* Configuration of the GPIO input/output and speed */

    temp = (pGPIOHandle->GPIO_PinConfig.GPIO_PinSpeed << (2*(pGPIOHandle->GPIO_PinConfig.GPIO_PinNumber-7)));

    /* Configuration of the GPIO Pull-up/Pull-down */


    /* Configuration of the output/input */


    /* Configuration of the alternative functionality */
}
void GPIO_Deinit(GPIO_RegDef_t *pGPIOx){
        if(pGPIOx == GPIOA)
            GPIOA_REG_RESET();
        else if(pGPIOx == GPIOB)
            GPIOB_REG_RESET();
        else if(pGPIOx == GPIOC)
            GPIOC_REG_RESET();
        else if(pGPIOx == GPIOD)
            GPIOD_REG_RESET();
        else if(pGPIOx == GPIOE)
            GPIOE_REG_RESET();
}

/*
 * Data read and write
 */
uint8_t GPIO_ReadFromInputPin(GPIO_RegDef_t *pGPIOx, uint8_t PinNumber){
    uint8_t value;
    value = ((pGPIOx->IDR >> PinNumber) & 0x00000001);
    return value;
}
uint16_t GPIO_ReadFromInputPort(GPIO_RegDef_t *pGPIOx){
    uint8_t value;
    value = pGPIOx->IDR;
    return value;
}
void GPIO_WriteToOutputPin(GPIO_RegDef_t *pGPIOx, uint8_t PinNumber, uint8_t value){
    if(value == GPIO_PIN_SET) /* Write 1 to the output data register at the bit field corresponding pinNumber */
        pGPIOx->ODR |= (1 << PinNumber);
    else
        pGPIOx->ODR &= ~(1 << PinNumber);
}
void GPIO_WriteToOutputPort(GPIO_RegDef_t *pGPIOx, uint8_t value){
    pGPIOx->ODR = value;
}
void GPIO_ToggleOutputPin(GPIO_RegDef_t *pGPIOx, uint8_t PinNumber){
    pGPIOx->ODR = pGPIOx->ODR ^= (1 << PinNumber);
}

/*
 * IRQ Configuration and ISR Handling
 */
void GPIO_IRQConfig(uint8_t IRQNumber, uint8_t IRQPriority, uint8_t EnorDi){

}
void GPIO_IRQHandling(uint8_t PinNumber){

}

总有8个错误,说pGPIOA、pGPIOB、pGPIOC、pGPIOD、pGPIOE、pGPIOF和pGPIOG有多个定义。

gudnpqoy

gudnpqoy1#

GPIO_RegDef_t *pGPIOA = GPIOA;
GPIO_RegDef_t *pGPIOB = GPIOB;
GPIO_RegDef_t *pGPIOC = GPIOC;
GPIO_RegDef_t *pGPIOD = GPIOD;
GPIO_RegDef_t *pGPIOE = GPIOE;
GPIO_RegDef_t *pGPIOF = GPIOF;
GPIO_RegDef_t *pGPIOG = GPIOG;

这不应该在stm32*. h中。你可以多次声明变量,但不能多次定义它们(在初始化时给予值)。每次文件stm32*.h包含在每个.c中时,都要定义它们,因为它们有一个值集。
如果你想把它们作为全局变量,这似乎是目标,你必须只定义一次,否则每个包含该头文件的.c文件都会有自己的同名全局变量,所以它会出错。因此,最好在.c文件中定义全局变量,所有其他文件都需要有相同变量的“extern”声明(或者它们都可以包括一些具有“extern”行的头文件-这在预处理器简单地将.h文件的内容粘贴到.c文件后的每个“#include”之后是一样的)。
例如,您可以将pGPIOx定义放在main. c中的main()之上,如果stm32*.h具有extern GPIO_RegDef_t *pGPIOA;,则包含它的每个文件都可以访问main. c中声明的变量。
但是,最好不要更改默认库文件。您可以创建global_var. c(它可以自由地包含stm32*.h,因此您可以使用相同的类型)并将具有值的定义放入其中,然后创建gloval_var. h并将“extern”声明放入其中。每个包含global_var. h的.c都可以访问它们。它将使您的库文件保持其原始形式,并为您提供所有优势。
global_var.c:

#include "global_var.h"        //includes all the definitions for MCU types

GPIO_RegDef_t *pGPIOA = GPIOA; //definition
GPIO_RegDef_t *pGPIOB = GPIOB;
GPIO_RegDef_t *pGPIOC = GPIOC;
GPIO_RegDef_t *pGPIOD = GPIOD;
GPIO_RegDef_t *pGPIOE = GPIOE;
GPIO_RegDef_t *pGPIOF = GPIOF;
GPIO_RegDef_t *pGPIOG = GPIOG;

global_var.h:

#include "whatever.h"
#include "stm32f103xx.h"

extern GPIO_RegDef_t *pGPIOA;  //declaration
extern GPIO_RegDef_t *pGPIOB;
extern GPIO_RegDef_t *pGPIOC;
extern GPIO_RegDef_t *pGPIOD;
extern GPIO_RegDef_t *pGPIOE;
extern GPIO_RegDef_t *pGPIOF;
extern GPIO_RegDef_t *pGPIOG;

现在,每个包含global_var. h的.c文件,将字面上复制粘贴this来代替#include(因为这就是#include所做的),因此它们将有一个带有“extern”的变量声明,它说“在此翻译单元之外查找该变量”。或者,您可以直接将这些行放在需要使用它们的.c文件中。在预处理器将#include粘贴到.c之后,它将是完全相同的东西。
作为“进一步阅读”,我建议涵盖有关编译预处理器的材料(“#include”和“#define”如何工作,“翻译单元”是什么,除其他外,没有什么困难),“extern”和全局变量。最好是这个顺序。
关于全局变量的高质量讨论可以在这里找到,前半部分可接受的答案与您相关:stackoverflow

相关问题