Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить

Re: Вопросы по С/С++ (СИ)

Чт апр 29, 2021 20:21:28

Ну раз неожиданно, то видимо NO :)
А так видимо потому что в знаковых целых отрицательный минимум на 1 больше по модулю, чем максимум. Получаем abs(INT_MIN) = 0 из-за переполнения? Отправляю пост и иду проверять )

Добавлено after 5 minutes 51 second:
Проверил. От части я прав. Вернется NO, но abs(INT_MIN) будет не 0, а неизменно -2147483648, забыл что у abs возвращаемое значение тоже знаковое. Ну понятно, это результат работы abs просто, где оно в данном случае оборачивается просто "по кругу" на данном числе.

Re: Вопросы по С/С++ (СИ)

Чт апр 29, 2021 21:33:40

Есть регистр CRC32->DI32. Он 16 разрядный, но я хочу данные ему скармливать побайтно. Как это написать?
(uint8_t) (CRC32->DI32) = *ptr++; - даёт ошибку "expression must be a modifiable lvalue".

Re: Вопросы по С/С++ (СИ)

Чт апр 29, 2021 23:02:29

если uint8_t *ptr; то CRC32->DI32 = *ptr++; и будет побайтно получать данные

Re: Вопросы по С/С++ (СИ)

Пт апр 30, 2021 05:47:22

Настоящая байтовая запись в регистр (если он это поддерживает) делается так
Код:
*(volatile uint8_t *)&CRC32->DI32 = *ptr++;
Для побайтого чтения источника данных достаточно uint8_t *ptr;

Нужно вам побайтовое чтение или побайтовая запись читайте описание регистра вашего микроконтроллера.

Re: Вопросы по С/С++ (СИ)

Пт апр 30, 2021 06:59:01

Да, мне нужна "байтовая" запись. Вы же заметили, что регистр принадлежит аппаратному вычислителю CRC. А ему не всё равно, записать 0xFF или 0x00FF.

Когда я запряг под это дело DMA с байтовым обменом - всё считалось правильно, а когда попытался вот так ручками - сумма не сходилась.

Re: Вопросы по С/С++ (СИ)

Вс май 02, 2021 11:08:31

Давеча экспериментировал со стартапом. Заметил, что GCC распознаёт паттерны копирования и установки памяти и заменяет их вызовами memcpy и memset. Вот эти два варианта после компиляции дают одинаковый результат.
Код:
extern uint32_t _sidata[], _sdata[], _edata[];
for(uint32_t *pSrc=_sidata, *pDst=_sdata; pDst!=_edata; *pDst++=*pSrc++);
    
extern uint32_t _sbss[], _ebss[];
for(uint32_t *pDst=_sbss; pDst!=_ebss; *pDst++=0);
Код:
extern uint8_t _sidata[], _sdata[], _edata[];
memcpy(_sdata, _sidata, _edata-_sdata);

extern uint8_t _sbss[], _ebss[];
memset(_sbss, 0, _ebss-_sbss);
И в обоих случаях это будет побайтовое копирование, причём и при оптимизации на скорость. Что, по меньшей мере, странно. Чтобы уговорить компилятор быстро пословно скопировать надо volatile расставить.
Код:
for(volatile uint32_t *pSrc=_sidata, *pDst=_sdata; pDst!=_edata; *pDst++=*pSrc++);
for(volatile uint32_t *pDst=_sbss; pDst!=_ebss; *pDst++=0);
Получается редкий случай, когда volatile и скорости добавляет, и размер уменьшает (если memset или memcpy больше нигде в коде не используются).

Re: Вопросы по С/С++ (СИ)

Ср май 19, 2021 22:18:22

сделал часы с датчиком BME280
все работает как я хотел, НО зависает все (то есть на экране часы, температура, давление, влажность написаны, но не изменяются и на кнопки не реагирует) питание отключишь все работает дальше и часы не сбиваются правильно идут.
могут час или пять , полдня работать , а потом опять зависнуть. самое большое полтора суток отработали.
ардуино менял. мне кажется в коде накосячил... :facepalm: может кто глянет свежим глазом что не так! :dont_know:
Вложения
meteostanciya_moi.ino.hex
(59.51 KiB) Скачиваний: 145
meteostanciya_moi.zip
(7.91 KiB) Скачиваний: 145

Re: Вопросы по С/С++ (СИ)

Пт май 28, 2021 20:26:55

ну зависает часы с датчиком ВМЕ280 хоть ты тресни...
скажите, а у меня датчик через провод (витая пара UTP 2х2х0,5 ) 3 метра подключен к ардуине, может из за этого виснуть?
или может все незадействованные ноги ардуино посадить на минус, чтобы не ловили помехи какие-нибудь
или подключить к земле, - используя параметр INPUT_PULLUP?
блоки питания менял и 5 вольтовый был , и сейчас 7,5 вольтовый через кренку, конденсатор 2200мкф, 0,1мкф стоит от какой-то тв приставки, все одно виснет...
посоветуйте , что еще бы можно сделать. :dont_know:

Re: Вопросы по С/С++ (СИ)

Пт май 28, 2021 21:26:28

или подключить к земле, - используя параметр INPUT_PULLUP?

или может все незадействованные ноги ардуино посадить на минус, чтобы не ловили помехи какие-нибудь

Это конечно полная ерунда написана. От непонимания.

3 метра подключен к ардуине, может из за этого виснуть?

Может. Попробуйте для начала подключить коротким проводом его. Чтобы исключить остальные проблемы.

Re: Вопросы по С/С++ (СИ)

Вт июн 08, 2021 11:10:31

Всем здрасте.
До этого программировал avr в Flowcode.
Я новичок в Си, месяц читаю и в большинстве всё понятно.
НО, откуда берут какой #include в каком случае, как например для задержки времени _delay_us надо включить <avr/delay.h>, но нигде не говорят где и в каком случае подключать другие файлы библиотеки и какие переменные/имена использовать из той библиотеки.
К примеру хочу I2C, какой #include< > мне для этого нужен и какие имена из него использовать и т.д.?

Re: Вопросы по С/С++ (СИ)

Вт июн 08, 2021 14:09:31

все это берут из документации к тулчейну.

Re: Вопросы по С/С++ (СИ)

Вт июн 08, 2021 15:29:21

sakvvvvvv, если avr-gcc, то:
https://www.nongnu.org/avr-libc/user-ma ... dules.html
https://www.nongnu.org/avr-libc/user-manual/pages.html

Re: Вопросы по С/С++ (СИ)

Ср июн 09, 2021 13:44:20

все это берут из документации к тулчейну.

Тулчей, значит тулчей.

Добавлено after 49 seconds:

Это уже ближе, спасибо.

Re: Вопросы по С/С++ (СИ)

Ср июн 09, 2021 15:11:12

Тулчей, значит тулчей.

Тулчейн. https://en.wikipedia.org/wiki/Toolchain

Re: Вопросы по С/С++ (СИ)

Пн июн 14, 2021 10:33:50

что-то я не понимаю, что происходит: или у меня работает код, который работать не должен, а правильный не работает, или я чего-то не понимаю.
Код:
ISR(TIMER1_OVF_vect){
   static uint8_t   entry;
   static uint8_t   pos;
   static pos_t *scr = screen;
   regs_t   regs;

   // считаем входы
   if(++entry >= IND_RPT){
      entry = 0;
      // каждые 2 мс
      two_ms++;
      // смена разряда
      scr++;
      if(++pos >= POS_CNT){
         pos = 0;
         scr = screen;
      }
      regs.word = _BV(11+pos);
   }
   // готовим один из двух символов для вывода
   regs.word &= 0xf800;
   regs.word |= digs[scr->symbol[entry >= scr->bright]];

   // выдача в сдвиговые регистры через SPI
   SPDR = regs.bytes[1];
   while(bit_is_clear(SPSR, SPIF));
   SPDR = regs.bytes[0];
   while(bit_is_clear(SPSR, SPIF));
   // строб для защелкивания данных
   PORTB |= LOAD_PIN;
   PORTB &= ~LOAD_PIN;
}
вот такой код для динамической индикации. каждые 2 мс происходит смена разряда, а каждый заход в обработчик происходит обновление символов (символов два, сначала выводится один, а когда количество входов превысит заданное значение - другой, таким образом реализована "плавная" смена символов).

так вот, код этот РАБОТАЕТ. но, если внимательно посмотреть на него, а именно на структуру regs, то станет понятно, что работать он НЕ ДОЛЖЕН: структура локальная, значит, содержимое её при каждом новом входе не определено, а значит, строка после комментария "готовим один из двух символов для вывода" не имеет смысла - подавлять часть разрядов поля структуры для того, чтобы сохранить биты управления разрядом индикатора, нет смысла - там неизвестно что может быть! кстати, некоторые версии компилятора avr-gcc предупреждают, что переменная тут может быть не проинициализирована, некоторые этот факт игнорируют, но при оптимизации -O3 код работает после компиляции любой версией (проверял 4 разных, от 4.хх.хх до 10.хх.хх). и еще кстати, при -Os код не работает так же независимо от версии компилятора.

казалось бы, в чем беда? делаем структуру static и... и код НЕ РАБОТАЕТ!!!!!!!! :o то есть когда от прерывания к прерыванию я сохраняю состояние структуры, т.е. значение битов, управляющих разрядами индикатора, это не только не делает нерабочий код рабочим, но и полностью рушит индикацию!

может кто-нибудь пояснить, что происходит?! :shock:

да, структура regs такая:
Код:
typedef union{
   uint8_t      bytes[2];         // 2 байта для выдачи в регистры
   uint16_t      word;
} regs_t;
идея индикации следующая: старшие 5 битов в regs.word задают номер светящегося разряда индикатора, а остальные - выводимый символ (для ГРИ это 1 бит в нужном разряде). потом эти 16 бит выдаются побайтно в регистры 74HC595 и управляют индикаторами.

Re: Вопросы по С/С++ (СИ)

Пн июн 14, 2021 12:32:02

В качестве предположения.

То, что код работает, хотя и не должен - можно сослаться на "везение" в том смысле, что regs всегда попадает на один и тот же определённый адрес при определённом уровне оптимизации.

А вот то, что код не работает в случае static - да, более странно. Но не может ли быть так, что доступ к "статической" структуре получается с точки зрения ассемблера более длинным, что в итоге является той каплей, что прерывание не успевает выполниться за нужное время?

Я о том, что два while() внутри прерывания при передаче по SPI могут быть "впритирку" ко времени между вызовами сосбственно прерываний.

Re: Вопросы по С/С++ (СИ)

Пн июн 14, 2021 12:42:13

WiseLord писал(а):Но не может ли быть так, что доступ к "статической" структуре получается с точки зрения ассемблера более длинным, что в итоге является той каплей, что прерывание не успевает выполниться за нужное время?
да, но что в таком случае может происходить? только то, что основной цикл станет выполняться очень медленно, а динамическая индикация продолжится, хоть и с некоторыми артефактами вроде разной яркости разрядов.

у меня же происходит вообще странное: во всех разрядах начинают "призрачно" дублироваться цифры соседних, т.е. в кажом разряде светится правильная цифра наиболее ярко, и слегка просвечивают цифры, которые на всех остальных. будто у меня команда, маскирующая "символьную" часть структуры, не выполняет свою задачу...

самое-то главное: что делать-то? проблему я вычислил случайно, когда стал пытаться добиться выключения разряда вообще - стоит что-то в обработчик добавить, и начинаются проблемы. писать обработчик на ассемблере очень не хочется - отвык уже.

Re: Вопросы по С/С++ (СИ)

Пн июн 14, 2021 13:41:43

только то, что основной цикл станет выполняться очень медленно, а динамическая индикация продолжится, хоть и с некоторыми артефактами вроде разной яркости разрядов.
у меня же происходит вообще странное: во всех разрядах начинают "призрачно" дублироваться цифры соседних, т.е. в кажом разряде светится правильная цифра наиболее ярко, и слегка просвечивают цифры, которые на всех остальных. будто у меня команда, маскирующая "символьную" часть структуры, не выполняет свою задачу...

Что тут непонятного?
regs.word |= digs[scr->symbol[entry >= scr->bright]]; выполняется в каждом ISR.
Не знаю что такое digs, предположу что оно хранит младшие 11 бит. Тогда эти 11 бит будут верными при каждом вызове ISR.
Если эти 11 бит - карта сегментов, то она всегда будет правильной передаваться в SPI. А старшие 5 бит (позиция?) будут неправильными. И то - если других прерываний нет, то место занимаемое в стеке regs может оказаться неразрушенным (и сохраниться от момента последней правильной записи старших 5 бит). Тогда и позиция будет передаваться правильная. Но иногда (когда содержимое regs трётся в стеке другой процедурой), то позиция будет неправильная (при правильных сегментах). А значит и будет наблюдаться - в основном правильное отображение, но иногда символы будут попадать в неправильные случайные позиции. Это будет редко, поэтому светится они там будут слабо.

PS: Ожидание завершения передачи по SPI в while() внутри ISR - это конечно верх быдлокодинга... :o
Если конечно там (в МК) имеется FIFO глубиной >= 2 байта и while() ожидает не завершения передачи, а завершения записи в FIFO, то тогда - нормально.

Re: Вопросы по С/С++ (СИ)

Пн июн 14, 2021 16:13:51

jcxz писал(а):Что тут непонятного?
а вы посмотрите внимательно:
regs.word &= 0xf800;
regs.word |= digs[scr->symbol[entry >= scr->bright]];

младшие 11 бит в каждом прерывании меняются, а старшие 5 - только каждое 62 прерывание. то есть так должно быть, если regs будет static.
вопрос не в том, почему без static работает (хоть это и странно, но вполне логичное объяснение вы сами и дали), вопрос в том, почему со static не работает?!
ведь благодаря static старшие биты сохраняются не из-за случая в стеке/памяти, а абсолютно однозначно! то есть должно быть лучше, а по факту - становится хуже.
как это объясните?
jcxz писал(а):Ожидание завершения передачи по SPI в while() внутри ISR - это конечно верх быдлокодинга
SPI работает на частоте вдвое меньше тактовой, т.е. передача 1 байта требует 16 тактов - пока исполнится код, организующий ожидание, пройдет половина этого интервала.
вам известны более красивые способы отправки двух байт с последующей дрыгоножной выдачей строба на классическом AVR? посоветуйте, я всегда готов учиться хорошему. а грубить я умею и сам.

чисто теоретически вывод в регистры можно делать в главном цикле, а в прерывании обойтись классическими флагами, но, боюсь, это приведет к гораздо большим проблемам с индкацией...

Re: Вопросы по С/С++ (СИ)

Вт июн 15, 2021 07:06:30

У вас структура regs определяется каждый раз при запуске прерывания и имеет в качестве данных мусор (что вы и написали).
А первое присвоение происходит в условии if. А если условие ложное то структура не заполниться и строки
Код:
   regs.word &= 0xf800;
   regs.word |= digs[scr->symbol[entry >= scr->bright]];

будут работать с мусором
Использование static заставляет компилятор оптимизировать данный код (скорее всего он выкидывает часть)
Ответить