Arduino:在没有编辑库的情况下更改定义 [已解决,编译器中的错误,可用的解决方法] [英] Arduino: Change defines without edit library [solved, bug in compiler, workaround available]

查看:16
本文介绍了Arduino:在没有编辑库的情况下更改定义 [已解决,编译器中的错误,可用的解决方法]的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在下面查看我的答案

我对 Arduino 平台还很陌生,现在正在使用 AdaFruit 的 attiny85 (Trinket) 库创建一个 USB HID 项目.另请参阅我之前回答的有关此库选项的问题:更改/覆盖饰品 (attiny85) USB 标识名称, 设备名称

I'm fairly new to the Arduino platform and creating now an USB HID project with the attiny85 (Trinket) library of AdaFruit. See also my previous answered question about the options of this library: Change/Override Trinket (attiny85) USB identification name, device name

我遇到了一个罕见的 C 相关限制(另请参阅上一个问题链接中的最新评论),即通过分离编译对二进制文件进行分离的后期绑定.如果你想改变 USB 设备的选项,你必须改变库本身,对我来说有点奇怪,因为它是一个库.

I'm stumped on a rare C-related limitation (see also latest comment at answer in link above to previous question), the separated late binding of binaries by separated compiling. If you want to change options of the USB device, you have to change the library itself, kinda weird to me because it's a library.

例如,如果您在加载库之前包含具有更改选项的头文件,则不会发生任何更改,因为库不知道它,因为它也必须包含在此库中.

For example, if you include a header file with changed options before you loading the library, nothing is changed because it is unknown by the library because it must be included by this library either.

示例:这不起作用:

#include "myUSBOptions.h"
#include "TrinketHidCombo.h"

另一种方法:

所以我需要为每个项目更改库本身,在本例中为 usbconfig.h 文件.这对我来说听起来有点愚蠢,因为它是一个库,可以被其他项目使用.这可能是 Adafruit 库中的设计错误,诸如供应商名称、设备名称等必须是该库之外的可选内容,并且您的设置可以在库更新时被覆盖.而且...您需要为每个单独的项目再次编辑该文件.

So I need to change the library itself for each project, in this case the usbconfig.h file. That's sounds a kind of stupid to me because it's a library and can be used by other projects. Maybe this is a design error in the Adafruit library, such things like vendorname, devicename etc must be optional OUTSIDE this library and also your settings can be overwritten when there is an update of the library. And... you need to edit the file again for each separated project.

所以我想出了在 usbconfig.h 文件中包含一个可选头文件的想法,#include "user_usbconfig.h" 只需要一个更改.但这不是唯一的 usbconfig.h 文件,至少有三个版本可用!在项目目录中创建一个 user_usbconfig.h 文件,编写一个批处理文件使其自动化并将其包含在项目目录中,以便您在切换项目时只需单击它即可更改选项.

So I came up with the idea to include an optional header file in the usbconfig.h file, #include "user_usbconfig.h" that requires only one change. But that's not the only usbconfig.h file, at least three versions are available! Create one user_usbconfig.h file in the project directory, Wrote a batch file for to automate it and include it in the project directory so you can change the options by simply clicking on it when switching project.

在 usbconfig.h 文件中添加的行:

.......

#include "cmdline_defs.h"

#ifndef __usbconfig_h_included__
#define __usbconfig_h_included__

#include "user_usbconfig.h" // <-- added this

.......

例如项目中包含的 user_usbconfig.h

/* DEVICE SETTINGS */

/* Version number of the device: Minor number first, then major number. */
#define USB_CFG_DEVICE_VERSION  0x00, 0x01


/* VENDOR_NAME
 * These two values define the vendor name returned by the USB device. The name
 * must be given as a list of characters under single quotes. The characters
 * are interpreted as Unicode (UTF-16) entities.
 * If you don't want a vendor name string, undefine these macros.
 * ALWAYS define a vendor name containing your Internet domain name if you use
 * obdev's free shared VID/PID pair. See the file USB-IDs-for-free.txt for
 * details.
 */
#define USB_CFG_VENDOR_NAME     'm', 'y', 'C', 'o', 'm', 'p', 'a', 'n', 'y', 'n'
#define USB_CFG_VENDOR_NAME_LEN 10


/* DEVICE_NAME
 * Same as above for the device name. If you don't want a device name, undefine
 * the macros. See the file USB-IDs-for-free.txt before you assign a name if
 * you use a shared VID/PID.
 */
#define USB_CFG_DEVICE_NAME     'm', 'y', 'D', 'e', 'v', 'i', 'c', 'e'
#define USB_CFG_DEVICE_NAME_LEN 8


/* SERIAL_NUMBER
 * Same as above for the serial number. If you don't want a serial number,
 * undefine the macros.
 * It may be useful to provide the serial number through other means than at
 * compile time. See the section about descriptor properties below for how
 * to fine tune control over USB descriptors such as the string descriptor
 * for the serial number.
 */
/*#define USB_CFG_SERIAL_NUMBER   'N', 'o', 'n', 'e' */
/*#define USB_CFG_SERIAL_NUMBER_LEN   0 */

示例源代码 myProject.ino,除了激活 USB 之外什么都不做:

#include "TrinketHidCombo.h"

void setup()
{
  TrinketHidCombo.begin(); 
}

void loop() // Main program - main()
{
  // do nothing, check if USB needs anything done
  TrinketHidCombo.poll();  
}

我创建的批处理文件,添加到项目目录中:

@echo off
rem ********************************************************
rem * setTrinketUSBLibraryOptions.bat                      *
rem * ---------------------------------------------------- *
rem * Author       : Erwin Haantjes                        *
rem * Project      : Arduino Trinket USB                   * 
rem * Dev date     : 11-06-2016                            *
rem * Last changed : 11-06-2016                            *
rem * What it do   : 'Copy' (link) USB options project to  *
rem *                Trinket lib to make settings optional.* 
rem *                                                      *
rem ********************************************************


rem *** Config parts that can be modified if required
SET ARDUINO_LIB_DIR=F:\Program Files\Arduino\DigiSpark\Digispark-Arduino-1.0.4\libraries
SET USER_HEADER_FILE=user_usbconfig.h
SET ATU_HEADER_FILE=usbconfig.h
SET ATU_DIRNAME1=TrinketHidCombo
SET ATU_DIRNAME2=TrinketKeyboard
SET ATU_DIRNAME3=TrinketMouse

SET ATU_HEADER_FILE1=%ARDUINO_LIB_DIR%\%ATU_DIRNAME1%\%ATU_HEADER_FILE%
SET ATU_HEADER_FILE2=%ARDUINO_LIB_DIR%\%ATU_DIRNAME2%\%ATU_HEADER_FILE%
SET ATU_HEADER_FILE3=%ARDUINO_LIB_DIR%\%ATU_DIRNAME3%\%ATU_HEADER_FILE%
SET ATU_USER_HEADER_FILE1=%ARDUINO_LIB_DIR%\%ATU_DIRNAME1%\%USER_HEADER_FILE%
SET ATU_USER_HEADER_FILE2=%ARDUINO_LIB_DIR%\%ATU_DIRNAME2%\%USER_HEADER_FILE%
SET ATU_USER_HEADER_FILE3=%ARDUINO_LIB_DIR%\%ATU_DIRNAME3%\%USER_HEADER_FILE%

rem *** START
echo.
echo.
echo Set Thrinket USB Library options to match your project
echo ------------------------------------------------------
echo.
if "@%1"=="@/?" goto USAGE
if "@%1"=="@-?" goto USAGE
goto INTRO

:USAGE
SET USAGEMODE=true
echo Created by Erwin Haantjes 2016
echo.
echo USAGE:
echo %0 [/?,/C,-?,-C]
echo.
echo SWITCHES:
echo - ?   Shows this help
echo - C   Use copy command instead of symlink to hardcopy the "%USER_HEADER_FILE%" to it's targets
echo.

:INTRO
rem *** WARNING and NOTICE
echo WARNING:
echo - This batch changes/symlink options to be able to config the Trinket USB Library by project easily. Run this file once each time you work on a project to be sure you are using the right settings.
echo - If a physical %USER_HEADER_FILE% file exists in the library directory, it will be deleted!
echo.
echo NOTICE: 
echo - Each "%ATU_HEADER_FILE%" file in (parts/the) Trinket USB library must include the line: #include "%USER_HEADER_FILE%" at top of the file after #define __usbconfig_h_included__ .
echo - Once applying this 'patch', you can change USB settings in the "%USER_HEADER_FILE%" file in this directory on the fly without the need to run this batch again. Just compile it after a change and your changes will be 'visible'. 
echo.
echo.
echo Library directory is set to:
echo %ARDUINO_LIB_DIR%
echo.
echo. 
if "%USAGEMODE%"=="true" goto END
echo Do you want to continue? Press any key.
pause >NUL
echo.

rem *** Check destinations
if exist "%USER_HEADER_FILE%" goto NEXT1
goto ERROR_NO_USER_FILE
:NEXT1
if exist "%ATU_HEADER_FILE1%" goto NEXT2
goto ERROR_LIB_NOT_EXISTS
:NEXT2
if exist "%ATU_HEADER_FILE2%" goto NEXT3
goto ERROR_LIB_NOT_EXISTS
:NEXT3
if exist "%ATU_HEADER_FILE3%" goto NEXT4
goto ERROR_LIB_NOT_EXISTS
:NEXT4
goto APPLY

rem *** ERRORS
:ERROR_NO_USER_FILE
echo ERROR: Create a "%USER_HEADER_FILE%" in this directory first.
goto ABORTED
:ERROR_LIB_NOT_EXISTS
echo %ATU_HEADER_FILE1%
echo ERROR: Check the directory location match your Arduino IDE setup, see "ARDUINO_LIB_DIR" at top of this batch file. Check also if you have the Trinket USB Library currently installed.
goto ABORTED

:APPLY
echo All seems to be fine, applying patch (symlinks).....
echo Checking and removing target files....
if exist "%ATU_USER_HEADER_FILE1%" goto REMOVE1
goto APPLY_NEXT2
:REMOVE1
echo Remove symlink of "%ATU_USER_HEADER_FILE1%" ....
del "%ATU_USER_HEADER_FILE1%"

:APPLY_NEXT2
if exist "%ATU_USER_HEADER_FILE2%" goto REMOVE2
goto APPLY_NEXT3
:REMOVE2
echo Remove symlink of "%ATU_USER_HEADER_FILE2%" ....
del "%ATU_USER_HEADER_FILE2%"

:APPLY_NEXT3
if exist "%ATU_USER_HEADER_FILE3%" goto REMOVE3
goto APPLY_NEXT
:REMOVE3
echo Remove file/symlink of "%ATU_USER_HEADER_FILE3%" ....
del "%ATU_USER_HEADER_FILE3%"

:APPLY_NEXT
echo.
if "@%1"== "@/c" goto APPLY_COPY
if "@%1"== "@/C" goto APPLY_COPY
if "@%1"== "@-c" goto APPLY_COPY
if "@%1"== "@-C" goto APPLY_COPY
echo Applying symlinks....
mklink /H "%ATU_USER_HEADER_FILE1%" "%USER_HEADER_FILE%" 
mklink /H "%ATU_USER_HEADER_FILE2%" "%USER_HEADER_FILE%" 
mklink /H "%ATU_USER_HEADER_FILE3%" "%USER_HEADER_FILE%" 
goto SUCCESS

:APPLY_COPY
echo Copy file(s)....
copy "%USER_HEADER_FILE%" "%ATU_USER_HEADER_FILE1%"  
copy "%USER_HEADER_FILE%" "%ATU_USER_HEADER_FILE2%"  
copy "%USER_HEADER_FILE%" "%ATU_USER_HEADER_FILE3%"  
SET COPYMODE=true
goto SUCCESS

:ABORTED
echo Batch aborted due error.
goto END

:SUCCESS
echo.
echo SUCCESS!
echo NOTICE: 
echo - Patch succesfully applied when no error is visible on screen.
if "%COPYMODE%"=="true" echo - Because you specify the copymode switch, you have to take care of updates yourself. Run this batch file again when you have changed USB settings. 

:END
SET USAGEMODE=
SET COPYMODE=
echo.
echo Press any key to exit...
pause >NUL

:DIE
echo.

结论和问题:

虽然这种方法工作正常,但我仍然不满意,想知道是否有更简单的方法,而无需更改库的任何代码行.更即时"的解决方案,因此您不必考虑这一点以避免错误和其他麻烦.

Although this method is working fine, I'm still not satisfied and wonder if there is an easier way to this without changing any line of code of the library. A more "on the fly" solution so you don't have to think about this to avoid errors and other headaches.

推荐答案

经过很长时间,我发现了 Arduino 编译器如何编译代码.这不是 C/C++ 问题,实际上 这是 Arduino 编译器中的错误,即组合和编译顺序.此外,编译器在编译之前添加了一些特定的代码.

After a long time I discover how the Arduino compiler compiles the code. It is not a C/C++ issue, actually it is an error in the Arduino compiler, the combine and compile order. Also the compiler add some specific code before compiling.

解决方法:

使用 exra 项目 h 文件包含您的库/独立性.在包含之前定义将不起作用,因为编译方法在应用定义(在您的 ino 文件中)之前包含 h 文件.例如,使用定义时,要更改库,需要一个单独的 h 文件.例如myproject.inc.h",其中包括您要使用的所有库.

Include your libraries/independencies with use of an exra project h-file. Defines before includes will not work because the compile method includes h-files before the defines (in your ino file) will be applied. When using defines, to change a library for example, requires a separated h-file. For example "myproject.inc.h" which includes all libraries you want to use.

现在您在包含库之前指定的所有定义都将被应用.

Now all defines you specify before including a library will be applied.

示例:

myproject.ino

#include "myproject.inc.h"

void setup()
{
  TrinketHidCombo.begin(); 
}

void loop() // Main program - main()
{
  // do nothing, check if USB needs anything done
  TrinketHidCombo.poll();  
}

<小时>

myproject.inc.h

#define USB_CFG_VENDOR_NAME     'm', 'y', 'C', 'o', 'm', 'p', 'a', 'n', 'y', 'n'
#define USB_CFG_VENDOR_NAME_LEN 10

#include "TrinketHidCombo.h"

这篇关于Arduino:在没有编辑库的情况下更改定义 [已解决,编译器中的错误,可用的解决方法]的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆