电子产业一站式赋能平台

PCB联盟网

搜索
查看: 243|回复: 0
收起左侧

预编译#error的使用

[复制链接]

567

主题

567

帖子

4209

积分

四级会员

Rank: 4

积分
4209
发表于 2022-12-14 08:30:00 | 显示全部楼层 |阅读模式
引言# a  }5 H5 R+ o3 O/ @) o% G
说到预编译,大家立刻就能想到#define、#if、#ifdef和#ifndef等熟悉的预编译命令。其实#include,我们通常放在源文件用来包含头文件,它也是预编译命令。当然这不是这篇文章的重点。这篇文章主要讲解下#error预编译命令,对于什么是预编译,预编译的作用等基础知识点不再讲解,不懂的同学请自行百度。在MCU的开发中,我们经常需要用到Flash存储一些参数,且通常情况下有很多参数需要存储。一般采用一个扇区存储一种类型的参数(可能造成Flash空间浪费),但对于一些内部Flash容量很大的MCU,这样做也是可行的。示例demo如下
  • #define PARA_BATTERY_ADDR   0x08019000  //存储电池参数#define PARA_ETH_ADDR    0x0801B800  //存储网络参数..........#define PARA_USER_CONFIG_ADDR 0x0801C400 //存储用户参数很多开发工程师喜欢这样做,如果参数少时还好,当有很多参数时,这将是一个噩梦。如果这些参数分散在各个文件中,阅读这份源码将是恶心他妈给恶心开门,恶心到家了。
    " f2 `' U) A; a9 C6 [, X/ E$ h当想增加一个参数存储时,如果不很熟悉代码,根本不知道哪个扇区是空闲的。( o' b7 x- ^. c3 o
    优化版本如下,将这这些宏定义统一定义在flashmap.h中
  • #define PARA_STARADDR (0x08000+(100*1024))  //前100K用于存储固件,参数存储开始地址。#define FLASH_SECTOR_SIZE (2*1024)  //Flash每个扇区的大小: t0 B: G5 V2 b% `; ^1 k
    #define PARA_BATTERY_ADDR   PARA_STARADDR //存储电池参数#define PARA_BATTERY_SIZE   (1*FLASH_SECTOR_SIZE) //电池参数所占空间大小
    $ C+ Z( M$ I- H/ N#define PARA_ETH_ADDR    (PARA_BATTERY_ADDR+PARA_BATTERY_SIZE)  //存储网络参数#define PARA_ETH_SIZE    (2*FLASH_SECTOR_SIZE) //网络参数所占空间大小相信大家也看出来了,这样管理参数地址,就显得很合理,不会想增加一个参数时,不知道哪个扇区是空闲的,找到了一个扇区,还是担心受怕,害怕和别的参数存储地址冲突将其覆盖。当然它也有弊端,如果问你PARA_ETH_ADDR存储地址,并不能立刻从代码中看出,这个问题,我一般使用printf打印出来。还有个问题,如果加了很多参数,最后一个参数地址大于Flash空间怎么办,或者软件设计一段Flash空间作为参数区,不被允许超过这个地址。在这个代码结构中,无法从代码中直接获取,有不行使用printf肉眼判断,那么可以使用#error 解决这个问题。/ b2 ^! r8 U# R$ `0 g' x
    #error
    : [; z) x& I' G! L#error 是一种预编译器指示字,用于生成一个编译错误消息 。用法:#error [message] //message为用户自定义的错误提示信息,可缺省。#error 可用于提示编译条件是否满足。编译过程中的任何错误意味着无法生成最终的可执行程序。上面的程序优化为
  • #define PARA_STARADDR (0x08000+(100*1024))  //前100K用于存储固件,参数存储开始地址。#define FLASH_SECTOR_SIZE (2*1024)  //Flash每个扇区的大小
    6 _" k% A1 Q$ q" D  m) H( m0 U#define PARA_BATTERY_ADDR   PARA_STARADDR //存储电池参数#define PARA_BATTERY_SIZE   (1*FLASH_SECTOR_SIZE) //电池参数所占空间大小  \4 A0 u: F; s- u! p/ b( t0 q
    #define PARA_ETH_ADDR    (PARA_BATTERY_ADDR+PARA_BATTERY_SIZE)  //存储网络参数#define PARA_ETH_SIZE    (2*FLASH_SECTOR_SIZE) //网络参数所占空间大小
    ) x4 m# ^: i- E* k#define PARA_END_ADDR  (PARA_ETH_ADDR+PARA_ETH_SIZE)// 参数的结束地址#if (PARA_END_ADDR > 0x0801E000)    #error Flash Map Error#endif这样当你的参数最后地址大于0x0801E000,编译器机会报错,根本编译不过,如下图' S3 }% y4 W9 q0 S4 l+ X

    ofcxntodlo364014186733.png

    ofcxntodlo364014186733.png
    " h6 Q- k/ ]+ B6 t
    类似的,#warning 用于生成编译警告消息。warning可用来提示一些非致命错误。( z# d. O/ f% F) L) t8 u
    其他用法
    * w( ]$ u4 j+ }( c限定宏定义的数值范围,下面SIZE被限制在0到100内。
    - {$ m, s4 K0 F' m- r/ n. d$ ~
  • #define SIZE 10#if SIZE  100#error SIZE must be between 1 and 100.#endifuint8_t buffer[SIZE];指定使用VS编译器
    $ t& Q4 I/ w7 r" @4 u1 s
  • #ifndef _MSC_VER#error require visual studio compiler#endif判断是否定义了某个宏,比如FreeRTOS源码中7 t( |( S! F2 S2 Q7 X
  • #ifndef configMINIMAL_STACK_SIZE    #error Missing definition:  configMINIMAL_STACK_SIZE must be defined in FreeRTOSConfig.h.  configMINIMAL_STACK_SIZE defines the size (in words) of the stack allocated to the idle task.  Refer to the demo project provided for your port for a suitable value.#endifEND
    . t! ?# M+ p2 c! y" b

    0sldhmf1v3t64014186833.gif

    0sldhmf1v3t64014186833.gif

    - O$ b9 P) l7 p3 E

    eifmxbjanuh64014186933.gif

    eifmxbjanuh64014186933.gif

    , j/ ~$ R# j' I1 D, d+ r8 M; I?指针与函数3 D, \. T* X  X0 _" b5 q! Q
    ?聊聊数据溢出的事
    , L* V) [3 i; U?MCU为什么内部不集成晶振 必读
    ; L: \6 i. f( |?表驱动法在STM32中的应用
    6 |2 q! b3 p- ?; I4 H?设计一款兼容ST207和GD207的开发板 必读
  • 回复

    使用道具 举报

    发表回复

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则


    联系客服 关注微信 下载APP 返回顶部 返回列表