Подскажите новичку что сделал не так при прошивке Тиньки13

Вот перед сном что-то захотелось “по ковыряться”.
Застрял на метке goto (понятия не имею что не так, о goto вообще ничего не знаю и никогда не использовал):

пшик
/*
  timer pshik

  made slav0n

  Chip type : ATtiny13
  9.6 MHz / 8 = 1.2
  фузы заводские
  ;Hfuse FF
  ;Lfuse 6A
 ****************************************************/

#include <avr/io.h>
#include <avr/eeprom.h>
#include <avr/wdt.h>
#include <util/delay.h>

//#include “m8_128.h”

#define LED_pl PB1
#define LED_mn PB0
#define GATE PB2
#define BUTTON_PSHIK PB4

#define adr_set_hrs 1
#define adr_binary adr_set_hrs + 1
#define adr_unary adr_binary + 1

typedef  uint8_t  u8;
typedef  uint32_t u32;

//============================================================

int main(void) {

  WDTCR = (1 << WDE) | //выпускаем сторожевую собаку
          // (0<<WDP3)|(0<<WDP2)|(0<<WDP1)|(1<<WDP0); //32mc
          // (0<<WDP3)|(0<<WDP2)|(1<<WDP1)|(0<<WDP0); //64mc
          // (0<<WDP3)|(0<<WDP2)|(1<<WDP1)|(1<<WDP0); //0.125c
          // (0<<WDP3)|(1<<WDP2)|(0<<WDP1)|(1<<WDP0); //0.5c
          // (0<<WDP3)|(1<<WDP2)|(1<<WDP1)|(0<<WDP0); //1c
          // (0<<WDP3)|(1<<WDP2)|(1<<WDP1)|(1<<WDP0); //2c
          (1 << WDP3) | (0 << WDP2) | (0 << WDP1) | (0 << WDP0); //4c
  // (1<<WDP3)|(0<<WDP2)|(0<<WDP1)|(1<<WDP0); //8c

  PORTB |= (1 << LED_pl) | (1 << BUTTON_PSHIK);

  _delay_us(100);
  while (bit_is_clear(PINB, LED_mn)) {
    wdt_reset();

    u8 set_hrs = eeprom_read_byte((const uint8_t*)adr_set_hrs) + 1;
    if (set_hrs >= 5) set_hrs = 0;

    u8 i = set_hrs;
    do {
      DDRB |= (1 << LED_pl); //зажигаем светодиод от кнопки
      _delay_ms(200);
      wdt_reset();
      DDRB &= ~(1 << LED_pl); //тушим светодиод
      _delay_ms(200);
      wdt_reset();
    } while (i--);


    _delay_ms(400);
    wdt_reset();
    _delay_ms(400);
    wdt_reset();
    // eeprom_update_byte(adr_set_hrs, set_hrs);
    eeprom_write_byte((uint8_t*)adr_set_hrs, set_hrs);
    eeprom_write_byte((uint8_t*)adr_binary, 0); // сбрасываем бинарный счетчик
  }

  if (bit_is_clear(PINB, BUTTON_PSHIK)) goto M_PSHIK; //пшикаем и сбрасываем таймер

  DDRB |= (1 << LED_pl) | (1 << LED_mn); //зажигаем светодиод
  _delay_ms(10);

  u8 p_ctr[4];
  u8 p_old[4];

  eeprom_read_block(p_ctr, (const void*)adr_unary, 4); // читаем унарный счетчик
  memcpy(p_old, p_ctr, 4);

  // u8 *ctr_unary = p_ctr;
  u32 *ctr_unary = (u32*)p_ctr;
  *ctr_unary <<= 1; //инкремент унарный счетчик
  if (*ctr_unary == 0)
  {
    *ctr_unary = 0xffffffff;
    // *ctr_unary = 0xff;

    /*   */
    int ct_binary = eeprom_read_byte((const uint8_t*)adr_binary); // читаем бинарный счетчик
    ct_binary++;

    //здесь можем сравнить бинарный счетчик с чем-либо
    int set_hrs = eeprom_read_byte((const uint8_t*)adr_set_hrs);
    if (set_hrs >= 5)set_hrs = 0;

    if (ct_binary == (set_hrs + 1) * 24)
      // if(ct_binary == (set_hrs+1))
    {

M_PSHIK:

      ct_binary = 0; // сбрасываем бинарный счетчик

      DDRB  |= (1 << GATE);
      PORTB |= (1 << GATE);
      wdt_reset();
      _delay_ms(500);
      wdt_reset();
      _delay_ms(500);
      wdt_reset();
      PORTB &= ~(1 << GATE);
      DDRB  &= ~(1 << GATE);
    }

    eeprom_write_byte((const uint8_t*)adr_binary, ct_binary);
  }

  /* */
  //------- пишем 4 байта унарного счетчика в EEPROM ----------------------
  for (u8 i = 0; i < 4; i++)
  {
    if (p_old[i] != p_ctr[i]) //пишем только если байт измнился
    {
      while (EECR & (1 << EEPE)); // Wait for completion of previous write

      // Set Programming mode
      //  EECR = (0<<EEPM1)|(0>>EEPM0); //Erase-Write
      if (p_ctr[i] == 0xff)EECR = (0 << EEPM1) | (1 >> EEPM0); //Erase Only
      else        EECR = (1 << EEPM1) | (0 >> EEPM0); //Write Only

      EEARL = adr_unary + i;  //ucAddress;
      EEDR = p_ctr[i];    //ucData;

      EECR |= (1 << EEMPE); // Write logical one to EEMWE
      EECR |= (1 << EEPE); // Start eeprom write by setting EEWE
    }
  }
  //-------------------------------------------------------------------------

  DDRB &= ~((1 << LED_pl) | (1 << LED_mn)); //тушим светодиод
  PORTB &= ~((1 << LED_pl) | (1 << LED_mn));

  MCUCR |= (1 << SE) | (1 << SM1) | (0 << SM0); //power down

  asm("sleep");
}

Окромя варнингов от такое:

sketch_mar17a:106:1: error: jump to label ‘M_PSHIK’ [-fpermissive]
M_PSHIK:

а если ?

M_PSHIK: ;

Без изменений.
Ладно, лошадь никуда не денется ))

это жеж линейное программирование, а ты внутрь условия лезешь, я бы тебе показал кусок когда, где без goto НУ ОЧЕНЬ СЛОЖНО! если найду, приведу пример

Всё правильно написал было @xDriver , ругается, что между goto и меткой есть инициализация

M_PSHIK:

^~~~~~~

…/main.ino:75:46: note: from here

if (bit_is_clear(PINB, BUTTON_PSHIK)) goto M_PSHIK; //пшикаем и сбрасываем таймер

^~~~~~~

…/main.ino:99:9: note: crosses initialization of ‘int set_hrs’

int set_hrs = eeprom_read_byte((const uint8_t*)adr_set_hrs);

^~~~~~~

…/main.ino:95:9: note: crosses initialization of ‘int ct_binary’

int ct_binary = eeprom_read_byte((const uint8_t*)adr_binary); // читаем бинарный счетчик

^~~~~~~~~

…/main.ino:87:8: note: crosses initialization of ‘u32* ctr_unary’

u32 ctr_unary = (u32)p_ctr;

я решения не нашел, точнее нашел, как мне показалось, но не прокатило)
вот и потер.

По мне так просто объявить, уже не ругается, а там пусть BOOM дальше думает))

int main(void) {
 u32 *ctr_unary;
 int set_hrs;
 int ct_binary;

Не ну это я конечно сделал, правда красных дипломов у нас не имеется))

Спойлер
/*
  timer pshik

  made slav0n

  Chip type : ATtiny13
  9.6 MHz / 8 = 1.2
  фузы заводские
  ;Hfuse FF
  ;Lfuse 6A
 ****************************************************/

#include <avr/eeprom.h>
#include <avr/io.h>
#include <avr/wdt.h>
#include <util/delay.h>

//#include “m8_128.h”

#define LED_pl PB1
#define LED_mn PB0
#define GATE PB2
#define BUTTON_PSHIK PB4

#define adr_set_hrs 1
#define adr_binary (adr_set_hrs + 1)
#define adr_unary (adr_binary + 1)

typedef uint8_t u8;
typedef uint32_t u32;

//============================================================

int main(void)
{

  WDTCR = (1 << WDE) | //выпускаем сторожевую собаку
                       // (0<<WDP3)|(0<<WDP2)|(0<<WDP1)|(1<<WDP0); //32mc
                       // (0<<WDP3)|(0<<WDP2)|(1<<WDP1)|(0<<WDP0); //64mc
                       // (0<<WDP3)|(0<<WDP2)|(1<<WDP1)|(1<<WDP0); //0.125c
                       // (0<<WDP3)|(1<<WDP2)|(0<<WDP1)|(1<<WDP0); //0.5c
                       // (0<<WDP3)|(1<<WDP2)|(1<<WDP1)|(0<<WDP0); //1c
                       // (0<<WDP3)|(1<<WDP2)|(1<<WDP1)|(1<<WDP0); //2c
          (1 << WDP3) | (0 << WDP2) | (0 << WDP1) | (0 << WDP0); // 4c
  // (1<<WDP3)|(0<<WDP2)|(0<<WDP1)|(1<<WDP0); //8c

  PORTB |= (1 << LED_pl) | (1 << BUTTON_PSHIK);

  _delay_us(100);
  while (bit_is_clear(PINB, LED_mn))
  {
    wdt_reset();

    u8 set_hrs = eeprom_read_byte((const uint8_t *)adr_set_hrs) + 1;
    if (set_hrs >= 5)
      set_hrs = 0;

    u8 i = set_hrs;
    do
    {
      DDRB |= (1 << LED_pl); //зажигаем светодиод от кнопки
      _delay_ms(200);
      wdt_reset();
      DDRB &= ~(1 << LED_pl); //тушим светодиод
      _delay_ms(200);
      wdt_reset();
    } while (i--);

    _delay_ms(400);
    wdt_reset();
    _delay_ms(400);
    wdt_reset();
    // eeprom_update_byte(adr_set_hrs, set_hrs);
    eeprom_write_byte((uint8_t *)adr_set_hrs, set_hrs);
    eeprom_write_byte((uint8_t *)adr_binary, 0); // сбрасываем бинарный счетчик
  }

  u8 p_ctr[4];
  u8 p_old[4];
  u32 *ctr_unary;
  int ct_binary;
  int set_hrs;

  if (bit_is_clear(PINB, BUTTON_PSHIK))
    goto M_PSHIK; //пшикаем и сбрасываем таймер

  DDRB |= (1 << LED_pl) | (1 << LED_mn); //зажигаем светодиод
  _delay_ms(10);

  eeprom_read_block(p_ctr, (const void *)adr_unary,
                    4); // читаем унарный счетчик
  memcpy(p_old, p_ctr, 4);

  // u8 *ctr_unary = p_ctr;
  ctr_unary = (u32 *)p_ctr;
  *ctr_unary <<= 1; //инкремент унарный счетчик
  if (*ctr_unary == 0)
  {
    *ctr_unary = 0xffffffff;
    // *ctr_unary = 0xff;

    /*   */
    ct_binary = eeprom_read_byte(
        (const uint8_t *)adr_binary); // читаем бинарный счетчик
    ct_binary++;

    //здесь можем сравнить бинарный счетчик с чем-либо
    set_hrs = eeprom_read_byte((const uint8_t *)adr_set_hrs);
    if (set_hrs >= 5)
      set_hrs = 0;

    if (ct_binary == (set_hrs + 1) * 24)
    // if(ct_binary == (set_hrs+1))
    {

    M_PSHIK:

      ct_binary = 0; // сбрасываем бинарный счетчик

      DDRB |= (1 << GATE);
      PORTB |= (1 << GATE);
      wdt_reset();
      _delay_ms(500);
      wdt_reset();
      _delay_ms(500);
      wdt_reset();
      PORTB &= ~(1 << GATE);
      DDRB &= ~(1 << GATE);
    }

    eeprom_write_byte((uint8_t *)adr_binary, ct_binary);
  }

  /* */
  //------- пишем 4 байта унарного счетчика в EEPROM ----------------------
  for (u8 i = 0; i < 4; i++)
  {
    if (p_old[i] != p_ctr[i]) //пишем только если байт измнился
    {
      while (EECR & (1 << EEPE))
        ; // Wait for completion of previous write

      // Set Programming mode
      //  EECR = (0<<EEPM1)|(0>>EEPM0); //Erase-Write
      if (p_ctr[i] == 0xff)
        EECR = (0 << EEPM1) | (1 >> EEPM0); // Erase Only
      else
        EECR = (1 << EEPM1) | (0 >> EEPM0); // Write Only

      EEARL = adr_unary + i; // ucAddress;
      EEDR = p_ctr[i];       // ucData;

      EECR |= (1 << EEMPE); // Write logical one to EEMWE
      EECR |= (1 << EEPE);  // Start eeprom write by setting EEWE
    }
  }
  //-------------------------------------------------------------------------

  DDRB &= ~((1 << LED_pl) | (1 << LED_mn)); //тушим светодиод
  PORTB &= ~((1 << LED_pl) | (1 << LED_mn));

  MCUCR |= (1 << SE) | (1 << SM1) | (0 << SM0); // power down

  asm("sleep");
}

ну и варнинги поправил, а там да, пусть BOOM дальше думает))

1 лайк

Чё, веселье начинается?

1 лайк

Почти как у классиков же, пятница начинается в понедельник.

1 лайк

ага)

сижу репу чешу, вот почему ругается?

#include <avr/io.h>

int main(void)
{

  for (byte r = 0; r < 255; r++)
  {
    for (byte g = 255; g > 0; g--)
    {
      for (byte b = 0; b < 255; b++)
      {
        if (analogRead(A0) > 250)
        {
          goto bailout;
        }
        // еще код
      }
    }
  }
bailout:
}

а так нет

#include <avr/io.h>

int main(void)
{

  for (byte r = 0; r < 255; r++)
  {
    for (byte g = 255; g > 0; g--)
    {
      for (byte b = 0; b < 255; b++)
      {
        if (analogRead(A0) > 250)
        {
          goto bailout;
        }
        // еще код
      }
    }
  }
bailout: ;
}

Вот что пишут:

A label can’t appear by itself but must always be attached to a statement. If a label is needed by itself, place a null statement after the label.

2 лайка

я вижу Евгений не спит))
а тут как , ну не знаю #pragma какая нибудь поможет?

#include <Arduino.h>

void setup()
{
  if (analogRead(A0) > 250)
  {
    goto bailout;
  }
  // еще код
  int a = 0;

bailout: ;
}

void loop(){};
D:\1\Blink\Blink.ino: In function 'void setup()':
D:\1\Blink\Blink.ino:12:1: error: jump to label 'bailout' [-fpermissive]
 bailout: ;
 ^~~~~~~
D:\1\Blink\Blink.ino:7:10: note:   from here
     goto bailout;
          ^~~~~~~
D:\1\Blink\Blink.ino:10:7: note:   crosses initialization of 'int a'
   int a = 0;
       ^
D:\1\Blink\Blink.ino:10:7: warning: unused variable 'a' [-Wunused-variable]

exit status 1

Compilation error: jump to label 'bailout' [-fpermissive]

В языке нет меток как таковых. Есть помеченные операторы (labeled statements). Ругается, когда после метки не идёт никакой оператор. А если есть (пускай и пустой) то всё нормально.

Допускается несколько меток на один оператор. Например, вот так - нормально:

void setup(void)
{

  for (byte r = 0; r < 255; r++)
  {
    for (byte g = 255; g > 0; g--)
    {
      for (byte b = 0; b < 255; b++)
      {
        if (analogRead(A0) > 250)
        {
          goto bailout1;
        } else goto bailout2;
        // еще код
      }
    }
  }
  
bailout1:
bailout2:
   ;
}
void loop(void) {}
2 лайка

Это предупреждение, ведь переменная объявляется (инициализируется) между goto и меткой, поэтому может возникнуть ситуация, что программа перейдёт по goto, и объявление переменной окажется за бортом, т.е. возникает неоднозначность. Поэтому лучше вынести её объявление в другое место (раньше goto).

да это все понятно, не понятно почему старый добрый С тапк не думает, и почему С++ перестает так думать, стоит только “обрамить”

#include <Arduino.h>

void setup()
{
  if (analogRead(A0) > 250)
  {
    goto bailout;
  }
  // еще код
  {
    int a = 0;
  }
bailout:;
}

void loop(){};

После обрамления область видимости становится другой. Переменная уничтожится ещё до метки, поэтому повода для беспокойства компилятор не видит.

1 лайк

все, въехал, спасибо!
некогда просто не имел дело с goto, позновательно.

А с чего ему так думать, если в нём переменные объявляются всегда в начале функции/блока?

Может, потому, что никакая a в районе метки просто не существует?

Это, наверное, потому что бейсик и фортран не приходилось учить :smile:
Я уже из того почти ничего не помню, но то что там без goto никуда - это факт.

1 лайк