3

我正在尝试编写一个可以将数据移出到 74HC595 移位寄存器的函数,该移位寄存器可以移出 8、16 和 32 位值。

使用重载函数,我有这个:

/**********************************************************************************
* Software SPI Pin Settings
*********************************************************************************/
#define SPIPINPORT  PORTB   //The Port that the Pins are on.  
#define LatchPin    2   //_RCLK  Shift register clock pin       
#define DataPin     3   //SER DS Serial data input              
#define ClockPin    5

/**********************************************************************************
* Preproccesor PIN to PIN Mask
*********************************************************************************/
#define LATCHMASK   (1 << LatchPin) 
#define MOSIMASK    (1 << DataPin)              
#define CLOCKMASK   (1 << ClockPin) 

/**********************************************************************************
* Macros
*********************************************************************************/
#define tggl(port,bit) (port)^=(1<<(bit))
#define LATCH   (SPIPINPORT &=~ LATCHMASK) 
#define unLATCH (SPIPINPORT |= LATCHMASK)  
#define PULSE   { tggl(SPIPINPORT,ClockPin); tggl(SPIPINPORT,ClockPin); }


void zShiftClass::ShiftOut(uint8_t value)
{
    LATCH;
    for (uint8_t i = 0; i <= 7; i++) 
    {   
        if( !!(value&(1<<i)) == true)   //If value is not a 1, turn off MOSIMASK
        { SPIPINPORT |= MOSIMASK; } 
        else    
        { SPIPINPORT &= ~MOSIMASK; }        

        PULSE;  //Pulse the Clock
    }
    unLATCH;
}

void zShiftClass::ShiftOut(uint16_t value)
{
    LATCH;
    for (uint8_t i = 0; i <= 15; i++) 
    {   
        if( !!(value&(1<<i)) == true)   //If value is not a 1, turn off MOSIMASK
        { SPIPINPORT |= MOSIMASK; } 
        else    
        { SPIPINPORT &= ~MOSIMASK; }        

        PULSE;  //Pulse the Clock
    }
    unLATCH;
}


void zShiftClass::ShiftOut(uint32_t value)
{
    LATCH;
    for (uint8_t i = 0; i <= 31; i++) 
    {   
        if( !!(value&(1<<i)) == true)   //If value is not a 1, turn off MOSIMASK
        { SPIPINPORT |= MOSIMASK; } 
        else    
        { SPIPINPORT &= ~MOSIMASK; }        

        PULSE;  //Pulse the Clock
    }
    unLATCH;
}

我想用这个模板来替换这些功能:

template<typename TYPE>void Shift(TYPE value)
{
    uint8_t loops = (( 8 * sizeof(value) ) - 1 );

    LATCH;
    for (uint8_t i = 0; i <= loops; i++) 
    {   
        if( !!(value&(1<<i)) == true)   //If value is not a 1, turn off MOSIMASK
        { SPIPINPORT |= MOSIMASK; } 
        else    
        { SPIPINPORT &= ~MOSIMASK; }        

        PULSE;  //Pulse the Clock
    }
    unLATCH;
}

当我编译时,我收到以下错误:

 Compiling 'zLEDArray' for 'Arduino Uno' 
 zLEDArray.ino : variable or field 'Shift' declared void 
 zLEDArray.ino : 'TYPE' was not declared in this scope
 Error compiling

我究竟做错了什么?

4

2 回答 2

4

Okay, this falls in the category of "beware of dev tools bearing gifts". The Arduino sketch tool is your problem. If you turn on verbose compiler output on the preferences menu, you will get some insight into what happens. With your code, I can duplicate your error. When compiling a test project called template1, the same error is reported, but now can see the compiler command line:

D:\arduino-dev\arduino-1.0.3\hardware\tools\avr\bin\avr-g++ -c ...yada yada
more yada... e:\Temp\build3528223623599856131.tmp\template1.cpp ...
template1:14: error: variable or field 'Shift' declared void
template1:14: error: 'TYPE' was not declared in this scope

The key point is that .CPP file. That is a file that the dev environment constructs from your .INO and is what is the actual input to the compiler. If you go grab that file, you will see all your code with some bonus lines included:

#include "Arduino.h"
void Shift(TYPE value);
void setup();
void loop();

The build tool added for you, 4 lines:

  • the Arduino header (because nobody remembers this)
  • 3 forward declarations for functions that it figured out by parsing code

The attempt at producing a forward declaration from the function template is incorrect, and produces the code that results in the compiler error.

The solution is to move the template out from the .INO file.

  1. Create a library folder, say T1.
  2. Create a .H file in that folder with the template code, say tspi.h.
  3. Import the library to your project.
  4. Make sure the #include line is after the first line of code in your .INO (more weirdness - the tool will insert a #include "Arduino.h" after all the comments but before first line of code. If you leave your include at the top of the .INO file, it will be processed before the Arduino header)
于 2013-08-06T07:26:52.863 回答
3

您可以通过在 ino 文件中添加正确的前向声明来消除错误。不直观的是,如果在使用函数之前定义函数,也必须这样做:

template <typename TYPE> void Shift(TYPE value);

// you may use the function here or you can have the declaration
// immediately before the definition

template<typename TYPE>void Shift(TYPE value)
{
    // your implementation
}

jdr5ca 的回答中解释了为什么会出现这种情况。感谢您的澄清,我通过反复试验发现了这一点。

于 2016-01-10T14:04:49.803 回答