Не работает millis Attiny13a (MicroCore) в Proteus

не противоречат. Т.к. согласно даташиту, для изменения регистра WDTCSR нужно сначала сделать танец с бубном: (WDTCSR |= (1<<WDCE) | (1<<WDE):wink: а следующей строчкой уже менять WDTCSR и причем за одну команду. Конечно в реальном коде там переменная, но для понимания что происходит (кто курил тему - поймет) упрощено до минимума и написан комментарий с 4s.

ну и если удобно вам писать (1<<WDTIF) | (1<<WDTIE) | (0<<WDCE) | (0<<WDE) то пишите и редактируйте, я так бы не делал и не делаю. Просто обратил внимание на то, как это воспринимается при взгляде со стороны. И вообще часто приходится много делать неудобных вещей в моменте, но с целью дальнейшей удобочитаемости и понимаемости и собой и другими.

вообще это общепринятая практика при настройке битовых масок.
Но если ВАМ неудобно - не настаиваю :slight_smile:

Конечно, когда долго ищещь тайный смысл за этими (0<<WDCE) | (0<<WDE) - а потом понимаешь, что его там нет! - наверно в первый раз кажется бредом. Но никто и не собирался вкладывать в это какие-то реальные действия с регистром - эта запись ИСКЛЮЧИТЕЛЬНО для удобства редактирования исходного кода программистом.

А вот так - некрасиво :slight_smile:

1 лайк

точно :slight_smile:

конечно в комментариях))

судя по форуму, и не только этому, я так понял, что запустить симуляцию в Протеусе не получалось и эту идею забрасывали. Так вот если штатную функцию из библиотеки wdt.h не использовать, а в коде вместо условного

wdt_enable(timeout);
написать так:

int8_t _WDTCSR = (1<<WDIE); 
if (timeout < 8) _WDTCSR |= timeout; 
else _WDTCSR |= (timeout & ~(1<<WDE)) | (1<<WDP3);

// комментарии из официального даташита
wdt_reset();
cli();
// Clear WDRF in MCUSR 
MCUSR &= ~(1<<WDRF); // WDE is overridden by WDRF in MCUSR. This means that WDE is always set when WDRF is set.
// Write logical one to WDCE and WDE 
WDTCSR |= (1<<WDCE) | (1<<WDE);
// Turn WDT 
WDTCSR = _WDTCSR;
sei();

    // WDTCSR //
    /*----+-----+------+-----+-----+-----+-----+-----+
    | WDIF| WDIE|WDP[3]| WDCE| WDE |     WDP[2:0]    |
    +-----+-----+------+-----+-----+-----+-----+-----+
    | (7) | (6) | (5)  | (4) | (3) | (2) | (1) | (0) |
    +-----+-----+------+-----+-----+-----+-----+-----+
    |     |     |  0   |     |     |  1  |  1  |  0  | 1.0s
    +-----+-----+------+-----+-----+-----+-----+-----+
    |     |     |  1   |     |     |  0  |  0  |  1  | 8.0s
    +-----+-----+------+-----+-----+-----+-----+-----+
    |     |  1  |      |     |  0  |     |     |     | Interrupt Mode
    +-----+-----+------+-----+-----+-----+-----+----*/

то все работает и в железе и в модели в Протеусе

Когда только начинал знакомится с Си и Ардуино меня тоже удивляла запись типа 0 << WDE, безотносительно к “собаке”,
поэтому и попробовал вам пояснить, зачем так пишется.
А так , хозяин-барин ИМХО, лишь бы работало))

может тут собака и порылась?)) с этим WDT много нюансов, и иногда приходится писать // WDE = 0 (!) чтобы понимать, что там обязательно должен быть ноль, а не догадываться из кода. Есть такие биты, в которые нужно писать 1, даже если она там уже записана. В других рядовых случаях возможно действительно удобнее использовать (1<<W1) | (1<<W2) | (0<<W4) | (0<<W5)

это не только в собаке… и не только в АВР

1 лайк

Проблема тут в том, что создаётся ложное ощущение, что этот ноль туда прописывается. Однако, это не так! Если там уже 1, то именно 1 там и останется. Например

WDTCSR |=  (1 << WDTIF) | (0 << WDTIE);

Здесь флаг WDTIE регистра WDTCSR не становится нулём, а остаётся тем же, чем он был. И уж там как повезёт.

Не знаю как кого, но меня это реально сбивает с толку.

Это с непривычки.
Я же считаю, что т.о. видны все биты. Есть, конечно, и любители “дейташитов”.

1 лайк

всех сбивает с толку разное :slight_smile:

Меня например, то, что в такой записи (1 << WDTIF) я следую “по стрелочкам” и вижу тут, что WDTIF записывается в единицу, тогда как на практике все наоборот и это единица записывается в бит WDTIF !
То есть по моей логике надо писать так:

( WDTIF << 1)

1 лайк

так в том и дело, и это сбивает с толку и то это, тоже)) и если уж писать нули для информативности, то тогда почему не для всех восьми бит?? Все-таки мне кажется логичным писать те, что должны стать единицей, остальные убирать, например в комментарий

это вообще какое-то мегазапутывание)) ничего же туда не пишется)) логичнее читать запись (1 << WDTIF) как просто “сдвинуть единицу на WDTIF бит” (в надежде, что кто-то позаботился, чтобы к WDTIF было “прицеплено” правильное число))

Да, согласен. Данная запись читается слева направо.

То есть “число” (не обязательно только 1) сдвинуть влево (<<) на “число” (WDTIF) позиций.

да-да, верно замечено, что именно влево! ведь можно и вправо двигать. И запись 2 >> WTIF совсем не означает ни “записать 2 в WTIF” и ни “достать 2 из WTIF “))

Нагляднее в двоичном виде всё это делать:

uint8_t m, n;
m = 0b00101111 >> 3;
n = 0b00000001 << 5;

m будет иметь значение 0b00000101, n будет иметь значение 0b00100000.