Парни, такое дело, есть библиотека OneWireSlave, и решил я внутри ее "похимичить" приклеив туда обработку прерывания, чтобы waitForRequest не тормозила основную программу в Attiny85. К слову сказать не чего бы не делал, если бы на Attiny85 сразу заработало (на Ардуино Нано работало все без внешнего прерывания). Вообщем сделал так: в OneWireSlave.cpp вставил строки:
теперь то что вставил в код библы OneWireSlave.h:
ну, и последняя библа LowLevel.h ( взята отсюда: https://github.com/ntruchsess/OneWireArduinoSlave)
собственно по вопросу "зачем заморачиваться, почему сразу всю не взял?" - пытался, но во-первых ни хрена не работает код из примера, во-вторых сжирает память у Digisparka, ну и в третьих используются прерывания Timer0, что конфликтует с сервой, которой мне необходимо управлять по шине 1-Wire.
Вообщем ломаю голову неделю, что только не пробовал эта ошибка постоянно вылезает. Я так понимаю, что это из-за того, что ф-ция вне объекта находится.
C++:
#include "OneWireSlave.h"
//--------- вставил, что бы не заморачиваться отдельно с регистрами для дуньки и тиньки
#if defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny13__)
#define EICRA _SFR_IO8(0x35)
#define ISC00 0
#define ISC01 1
#define EIMSK _SFR_IO8(0x3B)
#define INT0 6
#define EIFR _SFR_IO8(0x3A)
#define INTF0 6
#endif
//------------------- это взято из другой библы ----------------------------
//Pin interrupt
#define EN_INT {EIMSK|=(1<<INT0);EIFR|=(1<<INTF0);} //enable interrupt
#define DIS_INT EIMSK&=~(1<<INT0); //disable interrupt
#define SET_RISING EICRA=(1<<ISC01)|(1<<ISC00); //set interrupt at rising edge
#define SET_FALLING {EICRA &= ~(1 << ISC00);EICRA|=(1<<ISC01);} //set interrupt at falling edge
#define CHK_INT_EN (EIMSK&(1<<INT0))==(1<<INT0) //test if interrupt enabled
#define PIN_INT ISR(INT0_vect) // the interrupt service routine
//--------------------------------------------------------------------
volatile uint8_t mode; //state
void waitProcess_(uint8_t tmode);
void (*OneWireSlave::rxCallback_)();
uint8_t OneWireSlave::errno;
Pin OneWireSlave::pin_;
PIN_INT {
OneWireSlave::waitProcess_(mode);
}
OneWireSlave::OneWireSlave(uint8_t pin) {
pin_ = Pin(pin);
//pin_bitmask = digitalPinToBitMask(pin);
//baseReg = portInputRegister(digitalPinToPort(pin));
}
void OneWireSlave::begin() { //эту ф-цию вставил
cli();
pin_.inputMode();
SET_FALLING;
EN_INT;
sei(); // enable interrupts
}
void OneWireSlave::waitProcess_(uint8_t tmode)// и эту
{
unsigned long time_stamp;
uint8_t delta=25;
errno = ONEWIRE_NO_ERROR;
DIS_INT;// запрет прерывания INT0;
switch (mode) {
case 0:
time_stamp = micros() + 540;
while (pin_.read() == 0) {
if (micros() > time_stamp) {
errno = ONEWIRE_VERY_LONG_RESET;//импульс RESET оказался слишком длинным (возможно это не RESET, а что-то другое).
return;
}
}
if ((time_stamp - micros()) > 70) {
errno = ONEWIRE_VERY_SHORT_RESET;//импульс RESET оказался слишком коротким. Такая ошибка может появиться, если при ожидании RESET сигнала другое устройство начало передачу данных.
return;
}
delayMicroseconds(30);
//пришел имп.сброса (мастер начал сработу с шиной)
//посылаем PRESENCE
if (OneWireSlave::presence() ) rxCallback_(); // вот тут проблема
/* ошибка
...Arduino\libraries\OneWireSlave\OneWireSlave.cpp:In static member function 'static void OneWireSlave::waitProcess_(uint8_t)':
...Arduino\libraries\OneWireSlave\OneWireSlave.cpp:161:33: error: cannot call member function 'bool OneWireSlave::presence()' without object
if (OneWireSlave::presence() ) rxCallback_();
*/
break;
case 1:
//
break;
}
}
//ф-ция presence() - родная, ее не трогал
bool OneWireSlave::presence(uint8_t delta) {
errno = ONEWIRE_NO_ERROR;
cli();
pin_.writeLow();
pin_.outputMode();// drive output low
sei();
delayMicroseconds(120);
cli();
pin_.inputMode(); // allow it to float
sei();
delayMicroseconds(300 - delta);
if ( !pin_.read()) {
errno = ONEWIRE_PRESENCE_LOW_ON_LINE;
return FALSE;
} else
return TRUE;
}
bool OneWireSlave::presence() {
return presence(25);
}
//остальное все пока по дефолту осталось
C++:
#ifndef _OneWireSlave_h_
#define _OneWireSlave_h_
#include "Arduino.h"
#include "utility/LowLevel.h"
// You can exclude CRC checks altogether by defining this to 0
#ifndef ONEWIRESLAVE_CRC
#define ONEWIRESLAVE_CRC 1
#endif
// Select the table-lookup method of computing the 8-bit CRC
// by setting this to 1. The lookup table no longer consumes
// limited RAM, but enlarges total code size by about 250 bytes
#ifndef ONEWIRESLAVE_CRC8_TABLE
#define ONEWIRESLAVE_CRC8_TABLE 0
#endif
#define FALSE 0
#define TRUE 1
#define ONEWIRE_NO_ERROR 0
#define ONEWIRE_READ_TIMESLOT_TIMEOUT 1
#define ONEWIRE_WRITE_TIMESLOT_TIMEOUT 2
#define ONEWIRE_WAIT_RESET_TIMEOUT 3
#define ONEWIRE_VERY_LONG_RESET 4
#define ONEWIRE_VERY_SHORT_RESET 5
#define ONEWIRE_PRESENCE_LOW_ON_LINE 6
class OneWireSlave {
public:
enum ReceiveEvent
{
RE_Reset, //!< The master has sent a general reset
RE_Byte, //!< The master just sent a byte of data
RE_Error //!< A communication error happened (such as a timeout) ; the library will stop all 1-wire activities until the next reset
};
OneWireSlave(uint8_t pin);
void setRom(unsigned char rom[8]);
void begin();
// ---------- эти ф-ции добавил ----------------------------------------
void setCallbackRX(void (*callback)()) { rxCallback_ = callback; }
static void(*rxCallback_)();
static void waitProcess_(uint8_t tmode);
//----------------------------------------------------------------------
bool waitForRequest(bool ignore_errors);
bool waitReset(uint16_t timeout_ms);
bool waitReset();
bool presence(uint8_t delta);
bool presence();
bool search();
uint8_t sendData(char buf[], uint8_t data_len);
uint8_t recvData(char buf[], uint8_t data_len);
void send(uint8_t v);
uint8_t recv(void);
void sendBit(uint8_t v);
uint8_t recvBit(void);
#if ONEWIRESLAVE_CRC
static uint8_t crc8(char addr[], uint8_t len);
#endif
static uint8_t errno;// пришлось сделать Static, иначе таже ошибка
private:
bool recvAndProcessCmd();
bool waitTimeSlot();
char rom[8];
// interrupt handlers
static Pin pin_;
};
#endif
C++:
#ifndef _LowLevel_h
#define _LowLevel_h
#include <inttypes.h>
#ifdef VS_INTELLISENSE
#define __attribute__(...)
#define digitalPinToPort(pin) 0
#define digitalPinToBitMask(pin) 0
#define portInputRegister(arg1) 0
#endif
#if ARDUINO >= 100
#include "Arduino.h" // for delayMicroseconds, digitalPinToBitMask, etc
#else
#include "WProgram.h" // for delayMicroseconds
#include "pins_arduino.h" // for digitalPinToBitMask, etc
#endif
#if defined(__AVR__)
#define PIN_TO_BASEREG(pin) (portInputRegister(digitalPinToPort(pin)))
#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin))
#define IO_REG_TYPE uint8_t
#define IO_REG_ASM asm("r30")
#define DIRECT_READ(base, mask) (((*(base)) & (mask)) ? 1 : 0)
#define DIRECT_MODE_INPUT(base, mask) ((*((base)+1)) &= ~(mask))
#define DIRECT_MODE_OUTPUT(base, mask) ((*((base)+1)) |= (mask))
#define DIRECT_WRITE_LOW(base, mask) ((*((base)+2)) &= ~(mask))
#define DIRECT_WRITE_HIGH(base, mask) ((*((base)+2)) |= (mask))
#if defined (__AVR_ATtiny85__)
#define CLEARINTERRUPT GIFR |= (1 << INTF0)
#include "UserTimer.h" //ATtiny-support based on TinyCore1 Arduino-core for ATtiny at http://github.com/Coding-Badly/TinyCore1.git
__attribute__((always_inline)) static inline void UserTimer_Init( void )
{
UserTimer_SetToPowerup();
UserTimer_SetWaveformGenerationMode(UserTimer_(CTC_OCR));
}
__attribute__((always_inline)) static inline void UserTimer_Run(short skipTicks)
{
UserTimer_SetCount(0);
UserTimer_SetOutputCompareMatchAndClear(skipTicks);
UserTimer_ClockSelect(UserTimer_(Prescale_Value_64));
}
#define UserTimer_Stop() UserTimer_ClockSelect(UserTimer_(Stopped))
#elif defined (__AVR_ATmega328P__)
#define CLEARINTERRUPT EIFR |= (1 << INTF0)
#define USERTIMER_COMPA_vect TIMER1_COMPA_vect
__attribute__((always_inline)) static inline void UserTimer_Init( void )
{
TCCR1A = 0;
TCCR1B = 0;
// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);
}
__attribute__((always_inline)) static inline void UserTimer_Run(short skipTicks)
{
TCNT1 = 0;
OCR1A = skipTicks;
// turn on CTC mode with 64 prescaler
TCCR1B = (1 << WGM12) | (1 << CS11) | (1 << CS10);
}
#define UserTimer_Stop() TCCR1B = 0
#endif
#elif defined(__MK20DX128__) || defined(__MK20DX256__)
#define PIN_TO_BASEREG(pin) (portOutputRegister(pin))
#define PIN_TO_BITMASK(pin) (1)
#define IO_REG_TYPE uint8_t
#define IO_REG_ASM
#define DIRECT_READ(base, mask) (*((base)+512))
#define DIRECT_MODE_INPUT(base, mask) (*((base)+640) = 0)
#define DIRECT_MODE_OUTPUT(base, mask) (*((base)+640) = 1)
#define DIRECT_WRITE_LOW(base, mask) (*((base)+256) = 1)
#define DIRECT_WRITE_HIGH(base, mask) (*((base)+128) = 1)
#elif defined(__SAM3X8E__)
// Arduino 1.5.1 may have a bug in delayMicroseconds() on Arduino Due.
// http://arduino.cc/forum/index.php/topic,141030.msg1076268.html#msg1076268
// If you have trouble with OneWire on Arduino Due, please check the
// status of delayMicroseconds() before reporting a bug in OneWire!
#define PIN_TO_BASEREG(pin) (&(digitalPinToPort(pin)->PIO_PER))
#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin))
#define IO_REG_TYPE uint32_t
#define IO_REG_ASM
#define DIRECT_READ(base, mask) (((*((base)+15)) & (mask)) ? 1 : 0)
#define DIRECT_MODE_INPUT(base, mask) ((*((base)+5)) = (mask))
#define DIRECT_MODE_OUTPUT(base, mask) ((*((base)+4)) = (mask))
#define DIRECT_WRITE_LOW(base, mask) ((*((base)+13)) = (mask))
#define DIRECT_WRITE_HIGH(base, mask) ((*((base)+12)) = (mask))
#ifndef PROGMEM
#define PROGMEM
#endif
#ifndef pgm_read_byte
#define pgm_read_byte(addr) (*(const uint8_t *)(addr))
#endif
#elif defined(__PIC32MX__)
#define PIN_TO_BASEREG(pin) (portModeRegister(digitalPinToPort(pin)))
#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin))
#define IO_REG_TYPE uint32_t
#define IO_REG_ASM
#define DIRECT_READ(base, mask) (((*(base+4)) & (mask)) ? 1 : 0) //PORTX + 0x10
#define DIRECT_MODE_INPUT(base, mask) ((*(base+2)) = (mask)) //TRISXSET + 0x08
#define DIRECT_MODE_OUTPUT(base, mask) ((*(base+1)) = (mask)) //TRISXCLR + 0x04
#define DIRECT_WRITE_LOW(base, mask) ((*(base+8+1)) = (mask)) //LATXCLR + 0x24
#define DIRECT_WRITE_HIGH(base, mask) ((*(base+8+2)) = (mask)) //LATXSET + 0x28
#else
#error "Please define I/O register types here"
#endif
class Pin
{
private:
volatile IO_REG_TYPE *reg_;
IO_REG_TYPE mask_;
byte interruptNumber_;
byte pinNumber_;
public:
Pin()
: mask_(0)
, reg_(0)
, interruptNumber_((byte)-1)
, pinNumber_(255)
{ }
Pin(uint8_t pin)
{
pinNumber_ = pin;
mask_ = PIN_TO_BITMASK(pin);
reg_ = PIN_TO_BASEREG(pin);
switch (pin)
{
case 2: interruptNumber_ = 0; break;
case 3: interruptNumber_ = 1; break;
default: interruptNumber_ = (byte)-1;
}
}
inline byte getPinNumber() { return pinNumber_; }
inline void inputMode() { DIRECT_MODE_INPUT(reg_, mask_); }
inline void outputMode() { DIRECT_MODE_OUTPUT(reg_, mask_); }
inline bool read() { return DIRECT_READ(reg_, mask_) == 1; }
inline void writeLow() { DIRECT_WRITE_LOW(reg_, mask_); }
inline void writeHigh() { DIRECT_WRITE_HIGH(reg_, mask_); }
inline void write(bool value) { if (value) writeHigh(); else writeLow(); }
inline void attachInterrupt(void (*handler)(), int mode)
{
CLEARINTERRUPT; // очистить все ожидающие прерывания (мы хотим вызывать обработчик только для прерываний, происходящих после его присоединения)
::attachInterrupt(interruptNumber_, handler, mode);
}
inline void detachInterrupt() { ::detachInterrupt(interruptNumber_); }
};
#endif
Вообщем ломаю голову неделю, что только не пробовал эта ошибка постоянно вылезает. Я так понимаю, что это из-за того, что ф-ция вне объекта находится.