keil 工程头文件包涵及结构体重定义问题

2023-05-16

最近在写一个太阳能电池控制板的项目,这两天真是收获颇丰,把指针又从新学了一遍,还是项目坑死人啊啊啊啊啊

下面是我在建立工程时遇到的问题:

1)头文件包涵问题:

原先写的程序都是小程序,很少遇到许多.c 和.h和在一起的进行编译的境况,这样在许多编译单位一起链接的时候就会出现重定义情况

解决办法:

 独立建立一个include.h 文件,将所有其他文件的.h 都包涵在内,例如:

#ifndef INCLUDE_H_
#define INCLUDE_H_

#include "config.h"		//前后两个位置不能变
#include "STC15Fxxxx.H"	 
#include "intrins.h"   

#ifdef _ADC
#include "ADC.h"
#endif

#ifdef _DELAY
#include "delay.h"
#endif	  

#ifdef  _EEPROM
#include "EEPROM.h"
#endif		 

#ifdef __EXTI 
#include "Exti.h"
#endif			

#ifdef  _GPIO 
#include "GPIO.h"
#endif			  

#ifdef _PCA
#include "PCA.h"
#endif			  
   
...... //还有许多

#endif
这样在每个编译单位(独立可以编译的.h和.c)的开头加上include.h 


注意: 由于在每个头文件包涵之前加入的是#ifdef 和#endif  如下:

#ifdef  _XXXXX //标示符
#include xxxxx//头文件名
#endif		
所以要提前进行宏定义 (#define )

 

我是在config.h配置文件中进行宏定义的

#ifndef		__CONFIG_H
#define		__CONFIG_H 
/*********************************************************/

#define MAIN_Fosc		22118400L	//定义主时钟
//#define MAIN_Fosc		12000000L	//定义主时钟
//#define MAIN_Fosc		11059200L	//定义主时钟
//#define MAIN_Fosc		 5529600L	//定义主时钟
//#define MAIN_Fosc		24000000L	//定义主时钟

/*********************************************************/
#define _ADC

#define _DELAY

#define  _EEPROM

#define __EXTI 

#define  _GPIO 

#define _PCA

#define _SOFT_UART 

#define _TIMER 

#define _USART

#define _BSP_LCD

#define _BSP_KEY

    ............


/**************************************************************************/

#define Main_Fosc_KHZ	(MAIN_Fosc / 1000)

/***********************************************************/

#endif

这样的好处是可以随时添加或屏蔽掉编译的文件,在有很多编译单位进行调试时可以先注释掉无关的编译单位,能迅速的找到问题,方便快捷!!!


当然需要在每个.h 头文件的最前和结尾分别方加上

#ifndef		__XXXXXX_H
#define		__XXXXXX_H 


#endif
这样就可以避免重定义了

//

实际顺序: 现在每个头文件中加入

#ifndef		__XXXXXX_H
#define		__XXXXXX_H 


#endif
 然后在include.h中加入所有的头文件


最后再设置config.h 将需要进行编译连接的编译单位进行宏定义

//

2)结构体&&枚举初始化赋值问题

同样是在建立大型工程时遇到的问题,小程序在一个.c 和.h 中无需注意结构体初始化问题,但是有多个编译单位,就会遇到重定义等问题

在keil 中,声明定义结构体可以在.h 中,但是初始化只能在.c 中进行,否则会报错,这一点不管是在大工程或者小程序里都是一样的

compiling analysis.c...

..\SOLARENERGY\APP\ANALYSIS\INC\ANALYSIS.H(29): error C141: syntax error near '='
compiling comm.c...

..\SOLARENERGY\APP\ANALYSIS\INC\ANALYSIS.H(29): error C141: syntax error near '='
compiling Crc16.c...

但是如果是枚举在.h 中进行初始化的话,会报重定义的错误

例如:enum{V,KW,A,KWh,AllUnit}Choice_Unit=V;(这句话在bsp_lcd.h中)

*** ERROR L104: MULTIPLE PUBLIC DEFINITIONS
    SYMBOL:  CHOICE_UNIT
    MODULE:  .\bsp_uart.obj (BSP_UART)

*** ERROR L104: MULTIPLE PUBLIC DEFINITIONS
    SYMBOL:  BATTERYORSOLARMODE
    MODULE:  .\bsp_uart.obj (BSP_UART)
这个解决办法是将Choice_Unit=V;放在相应的.c中就可以了 (例如将这句话放在bsp_lcd.c中)

3) 结构体定义和声明问题

在keil 中最好使用如下的结构体定义方式

typedef struct XXXXXXXXXXX // 结构体标识
{

    ..........


}XXXXXX(结构体类型);
这样在以后的函数定义时就不需要考虑是否加struct 了 

如果如下使用的形式时

struct XXXXXXXX(结构体名字)//这样解释不太准确哈~
{   
     ........ 
};
定义变量貌似只能在相应的.c 中 而且在函数声明和实现时,形参的定义必须是(struct+结构体名字)的形式

例如:void exp(struct XXXX  ,uint ,.......);

4) extern 的问题

 extern 相当于声明了一个外部函数或者变量,指的是此函数或者变量在其他文件中已经进行了声明或者定义,在此文件中只是进行引用罢了

工程中有多个编译单位时,如果需要将函数或者变量定义为可以被其他文件进行访问或者引用时

在.h 中加入(extern + 函数或者变量名) 进行声明

在相应的.c 中进行定义

如果其他文件需要引用,则只需在自己的.c再次定义一下(其实不定义貌似也没错),然后就可以直接使用变量和函数了

delay.h

extern void Delay100us(u8);
extern void Delay1ms(u8);
extern void Delay10ms(u8);
extern void Delay100ms(u8);
delay.c

//==============================================================================
//Subroutine:	Delay100us
//==============================================================================
 void Delay100us(u8 Counter)
{
    while (Counter--)
    {
        Delay2us(150);
    }
}

//==============================================================================
//Subroutine:	Delay1ms
//==============================================================================
 void Delay1ms(u8 Counter)
{
    while (Counter--)
    {
        Delay100us(11);
    }
}

//==============================================================================
//Subroutine:	Delay10ms
//==============================================================================
 void Delay10ms(u8 Counter)
{
    while (Counter--)
    {
        Delay1ms(11);
    }
}

//==============================================================================
//Subroutine:	Delay100ms
//==============================================================================
 void Delay100ms(u8 Counter)
{
    while (Counter--)
    {
        Delay1ms(101);
    }
}	  
main.c

/*main.c	

///text:LCD 2014年5月2日16:35:29 /	
		LCD_Init();
      Display(0x00);
	 LCD_Write_Data(1,0x01);
	 Display(0x00);
    //  LCD_Write_Data(24,7);
	//while(1) ;
    while (1)
    {
        unsigned char i,j;
        for (j=0;j<10;j++)
        {
            for (i=1;i<=17;i++)
            {
                if (i==17)
                    SetValue(i, j,0) ;
                else
                    SetValue(i, j,1) ;


            }
            Delay10ms(10);
        }
    }

    SetValue(17, 7,1);
/	   
*/





















本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

keil 工程头文件包涵及结构体重定义问题 的相关文章

  • 高程初识

    高程是指某一点相对于基准面的高度 xff0c 目前常用的高程系统共有正高 正常高 力高和大地高程4种 xff0c 而高程基准各国均有不同定义 高程系统则是定义某点沿特定的路径到一个参考面上距离的一维坐标系统 高程系统 地球上某一点的高程通常
  • Source Insight4 设置相对路径

    source insight4 设置相对路径步骤 xff1a 1 xff09 新建工程 2 xff09 选择 project source directory时 xff0c 必须选择工程的根目录 xff01 3 xff09 选择文件并添加
  • STM32F407 Flash操作笔记

    简述 STM32F4XX的闪存擦除方式分为两种 xff1a 扇区擦除 xff08 最小单元16K xff09 和整片擦除 在实际应用中 xff0c 为满足重要信息的存储 xff0c 需将信息存入FLASH中 xff0c 针对以上两种擦除方式
  • STM32 软件按键消抖

    引言 通常按键所用的开关都是机械弹性开关 xff0c 当机械触点断开 闭合时 xff0c 由于机械触点的弹性作用 xff0c 一个按键开关在闭合时不会马上就稳定的接通 xff0c 在断开时也不会一下子彻底断开 xff0c 而是在闭合和断开的
  • STM32 中断函数SysTick_Handler理解

    目的 滴答定时器整理 xff08 STM32F103 xff09 用了一段时间的滴答定时器 xff0c 突然忘记其中配置方法 xff0c 重新翻阅手册及博文 xff0c 在此记录备忘 SysTick的重装寄存器决定了定时器频率 xff0c
  • srilm的安装与使用(标贝科技)

    欢迎体验标贝语音开放平台 地址 xff1a https ai data baker com source 61 qaz123 xff08 注 xff1a 填写邀请码hi25d7 xff0c 每日免费调用量还可以翻倍 xff09 一 简介 简
  • 信号强度(RSSI)知识整理

    为什么无线信号 xff08 RSSI xff09 是负值 答 xff1a 其实归根到底为什么接收的无线信号是负值 xff0c 这样子是不是容易理解多了 因为无线信号多为mW级别 xff0c 所以对它进行了极化 xff0c 转化为dBm而已
  • JLink 警告:The connected J-Link is defective,Proper operation cannot be guaranteed.

    概述 安装j link较新版本 xff08 JLink Windows V632b exe xff09 的驱动 xff0c 每烧录一次程序报一次警告 xff0c 警告如下 xff1a The connected J Link is defe
  • [PYTHON]修改当前进程环境变量

    myenv 61 os environ myenv 34 PATH 34 61 34 xxxx 34 43 myenv 34 PATH 34 注意 xff1a 此方法仅在python的当前进程中生效 xff0c 如果此时通过subproce
  • SO库版本号管理

    一 输入版本号 功能由Cmake软件实现 1 建立一个空白txt xff0c 重命名为config h in 输入代码 xff1a defineMAJOR VERSION 64 MAJOR VERSION 64 defineMINOR VE
  • VINS-MONO实践

    1 配置ros xff08 运行VINS需要 xff0c 记得换源 xff0c 会快一些 xff09 sudo apt get install ros melodic cv bridge ros melodic tf ros melodic
  • EuRoC数据集介绍

    数据集官网 xff1a https projects asl ethz ch datasets doku php id 61 kmavvisualinertialdatasets EuRoC数据集 微型飞行器 xff08 MAV xff09
  • TUM数据集

    TUM数据集下载链接 https vision in tum de data datasets rgbd dataset download https vision in tum de data datasets visual inerti
  • evo评测VINS-MONO---指标解析、算法精度分析(数据集)

    上篇博文已通过代码修改 数据格式转换 数据测试实现使用evo评测VINS MONO xff0c 该篇将详细介绍evo评测出的数据指标 xff0c 以及VINS MONO在数据集下的精度情况 EVO评价指标介绍 绝对轨迹误差 xff08 AT
  • ZED2相机说明书

    经前期调研及摄像头参数对比 xff0c 最终选择STEREOLABS公司的ZED2双目立体摄像头作为后期VINS系统的硬件平台 xff0c 下面先给出ZED2 的产品说明书 产品特点 1 空间目标检测 根据空间环境检测和跟踪对象 通过结合A
  • 解决NVIDIA-SMI has failed because it couldn‘t communicate with the NVIDIA driver

    问题解决 终端输入 xff1a nvidia smi NVIDIA span class token operator span SMI has failed because it couldn span class token numbe
  • Mysql 事务(标贝科技)

    文章目录 事务InnoDB对ACID的支持隔离级别不同隔离级别下读读取数据可能出现的情况不可重复读和幻读区别 redo log xff08 共享表空间 xff09 redo log block刷redo log策略 xff1a innodb
  • Ubuntu20.04运行Vins-fusion

    因已安装ROS noetic xff0c eigen xff0c opencv及ceres等库 xff0c 这部分环境配置就不细讲 xff0c 直接下载VINS FUSION的代码库 下载编译 cd span class token ope
  • 坐标系之间的转换关系(ECEF、LLA、ENU)

    一 坐标系简介 1 ECEF坐标系 也叫地心地固直角坐标系 其原点为地球的质心 xff0c x轴延伸通过本初子午线 xff08 0度经度 xff09 和赤道 xff08 0deglatitude xff09 的交点 z轴延伸通过的北极 xf
  • Python画图常用的颜色及标识

    matplotlib中color可用的颜色 xff1a aliceblue F0F8FF antiquewhite FAEBD7 aqua 00FFFF aquamarine 7FFFD4 azure F0FFFF beige F5F5DC

随机推荐

  • .npy文件打开方式

    在用evo评测slam算法定位精度时 xff0c 使用 save results a zip 生成的结果中包含的 npy文件 xff0c 如果要查看里面详细的数值 xff0c 则可通过以下方式打开文件并查看 1 xff09 找到要查看的 n
  • IMU误差模型简介及VINS使用说明

    1 IMU误差来源 2 IMU噪声模型 Noise and Bias kalibr中的imu noise model 参考 xff1a https github com ethz asl kalibr wiki IMU Noise Mode
  • 泰勒公式(泰勒展开式)通俗介绍+本质详解

    比较通俗地讲解一下泰勒公式是什么 泰勒公式 xff0c 也称泰勒展开式 是用一个函数在某点的信息 xff0c 描述其附近取值的公式 如果函数足够平滑 xff0c 在已知函数在某一点的各阶导数值的情况下 xff0c 泰勒公式可以利用这些导数值
  • Leetcode ->94 二叉树的中序遍历

    题目 算法思路及代码实现 span class token macro property span class token directive hash span span class token directive keyword inc
  • Unix、UTC、GPS时间戳及转换

    UTC时间 UTC时间的英文全称 xff1a Universal Time Coordinated xff0c 中文名称 xff1a 协调世界时 俗的理解为 xff0c 这个时间是全世界通用的 xff0c 即全世界都公用的一个时间 可以认为
  • 自动驾驶中地图匹配定位技术总结

    引言 汽车定位是让自动驾驶汽车知道自身确切位置的技术 xff0c 在自动驾驶系统中担负着相当重要的职责 汽车定位涉及多种传感器类型和相关技术 xff0c 主要可分为卫星定位 惯性导航定位 地图匹配定位以及多传感器融合定位几大类 其中地图匹配
  • Firefox 常用扩展插件及脚本推荐 打造你不一样的Firefox

    前言 xff1a 进入2011年以来 xff0c 整个浏览器领域的竞争越发激烈 xff0c 随着IE9正式版的发布 Chrome Opera等浏览器厂商也相继更新 发布了新的版本 经过多次跳票之后 xff0c FireFox4 0正式版终于
  • mysql 锁(标贝科技)

    标贝科技 https ai data baker com source 61 qwer12 填写邀请码fwwqgs xff0c 每日免费调用量还可以翻倍 mysql 锁 锁类型 类型 表级锁 xff1a 开销小 xff0c 加锁快 xff1
  • STM32G4学习笔记之DAC+FMAC

    1 高性能DAC G4系列一共有四个DAC 前两个为低速采集DAC xff08 1MHz xff09 xff0c 后两个为高速 可达15MHz DAC1 DAC2的采样速率最大为1MHz xff0c DAC3 DAC4的采样速率最大为15M
  • 逆变电路之单极性调制与双极性调制

    就调制脉冲的极性而言 单相全桥逆变器pwm调制技术主要分为单极性调制与双极性调制 下面就其调制原理分别做简单的介绍 1 单极性调制 单极性调制的原理如图所示 调制信号ur为正弦波 载波uc在ur的正半周为正极性的三角波 在ur的负半周 为负
  • OTL电路与OCL功放电路的区别

    一 OTL电路 OTL xff08 Outputtransformerless xff09 电路是一种没有输出变压器的功率放大电路 过去大功率的功率放大器多采用变压器耦合方式 xff0c 以解决阻抗变换问题 xff0c 使电路得到最佳负载值
  • 运放失真罪魁祸首之压摆率和增益带宽积

    1 什么叫压摆率 xff1f 做1pps驱动电路 1 xff0c 1PPS xff1a 秒脉冲英文全称 xff1a Pulse Per Second 1pps概念 要求上升沿 5ns xff0c FPGA输出的信号用运放跟随增强驱动后 xf
  • 电源反馈电路设计经验(PC817光耦隔离+TL431)

    身边的很多小伙伴好像都对电源的反馈电路的计算以及原理不太了解 xff0c 这里给大家系统的讲解一下 xff1a 废话不都说 xff0c 咱们直接上干货 在分析电路前需要注意的关键点 1 光耦的输入端 xff08 二极管端 xff09 的电流
  • 一分钟带你了解常用的V-I、I-V转换电路

    下面我将给大家介绍6种常用的V I I V转换电路 1 0 xff0d 5V 0 xff0d 10mA的V I变换电路 图1是由运放和阻容等元件组成的V I变换电路 xff0c 能将0 5V的直流电压信号线性地转换成0 xff0d 10mA
  • 奈奎斯特采样定理-为什么采样率需要时被测信号最高频率的两倍

    奈奎斯特采样定理 采样定理在1928年由美国电信工程师H 奈奎斯特首先提出来的 xff0c 因此称为奈奎斯特采样定理 1933年由苏联工程师科捷利尼科夫首次用公式严格地表述这一定理 xff0c 因此在苏联文献中称为科捷利尼科夫采样定理 19
  • 傅里叶变换简单解析

    这里有两个频率 一个是信号本身的频率 位1 3sec 一个下面矢量绕圆的频率 为1 0 79sec 下面这个频率是我们可以改变的 这就是所谓的窗 即我们选取多长的一段信号用来进行傅里叶变换分析 当截取的窗的周期等于信号周期1 3sec时 就
  • 组合逻辑与时序逻辑

    我前段时间对这两个逻辑的概念有点混淆 xff0c 所以就百度查看了一下 xff0c 排名第一的结果就出现了这样的解释 xff1a 数字电路根据逻辑功能的不同特点 xff0c 可以分成两大类 xff0c 一类叫组合逻辑电路 xff08 简称组
  • AD2020如何安装库

    首先快捷键op打开下面界面 然后找到库的位置安装就可以了
  • 白话Android音频系统原理(上)(标贝科技)

    白话Android音频系统原理 xff08 上 xff09 一 基本原理二 初始化准备工作三 播放流程四 录音流程 标贝科技 https ai data baker com source 61 qwer12 填写邀请码fwwqgs xff0
  • keil 工程头文件包涵及结构体重定义问题

    最近在写一个太阳能电池控制板的项目 xff0c 这两天真是收获颇丰 xff0c 把指针又从新学了一遍 xff0c 还是项目坑死人啊啊啊啊啊 下面是我在建立工程时遇到的问题 xff1a 1 头文件包涵问题 xff1a 原先写的程序都是小程序