MaxiMuz 0 23 апреля, 2013 Опубликовано 23 апреля, 2013 (изменено) · Жалоба Элементарная ситуация: Имеется два 16-битных числа , при их сложении нужно отслеживать ситуацию переполнения результата. Пробую: uint16_t temp16; uint16_t sumADC; if ((sumADC+=temp16)>0xffff) { // Отключение АЦП !! ADCSRA=(1<<ADEN);} понимаю что это нет то .... Нужно как можно короче превести это к коду (для AVR): add rd_l,rs_l adc rd_h,rs_h brcs m1 .... Как это все оформляется в Си ? Изменено 23 апреля, 2013 пользователем MaxiMuz Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
arttab 0 24 апреля, 2013 Опубликовано 24 апреля, 2013 · Жалоба а по флагу переполнения не проще ли? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
maksimp 0 24 апреля, 2013 Опубликовано 24 апреля, 2013 · Жалоба Такой именно ассемблерный код как вы хотите может быть и не получится. Варианты: unit16_t x=sumADC; sumADC+=temp16; if (x>0xffffU-temp16) unit16_t x=sumADC; sumADC+=temp16; if (((unit32_t)x+temp16)>0xffffUL) unit32_t x=sumADC+temp16; sumADC=(unit16_t)x; if (x>0xffffUL) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VslavX 0 24 апреля, 2013 Опубликовано 24 апреля, 2013 · Жалоба Можно попробовать так: uint16_t temp16; uint16_t sumADC; sumADC+=temp16; if (sumADC < temp16) { { // Отключение АЦП !! Но ассемблерного варианта скорее всего тоже не получится. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
protector 0 24 апреля, 2013 Опубликовано 24 апреля, 2013 (изменено) · Жалоба uint16_t temp16; uint16_t sumADC; uint32_t sum32; sum32 = sum32 + temp16; if ( sum32 <= 0xFFFFFFFF ) { sumADC = (uint16_t) sum32; } else { //overflow actions } Изменено 24 апреля, 2013 пользователем Alexey K Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Vetal-Soft 0 24 апреля, 2013 Опубликовано 24 апреля, 2013 · Жалоба if ((0xffff-sumADC) < temp16) { . . . Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 24 апреля, 2013 Опубликовано 24 апреля, 2013 · Жалоба А что, arttab дал плохой совет? Доступ к флагам имеется? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ARV 0 24 апреля, 2013 Опубликовано 24 апреля, 2013 · Жалоба uint16_t temp16; uint16_t sumADC; uint32_t sum32; sum32 = sum32 + temp16; if ( sum32 <= 0xFFFFFFFF ) { sumADC = (uint16_t) sum32; } else { //overflow actions } ну, все-таки скорее всего чуть-чуть иначе: uint16_t temp16; uint16_t sumADC; uint32_t sum32; sum32 = sum32 + temp16; if ( sum32 <= 0xFFFF ) // переполнение-то для 16-бит надо отслеживать { sumADC = sum32; } else { //overflow actions } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
protector 0 24 апреля, 2013 Опубликовано 24 апреля, 2013 · Жалоба Согласен. Утро однако:) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrYuran 16 24 апреля, 2013 Опубликовано 24 апреля, 2013 · Жалоба А при сравнении флаг С учитывается? Иначе крайние варианты не катят Тьфу, пардон, uint32 же.. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 24 апреля, 2013 Опубликовано 24 апреля, 2013 · Жалоба uint32_t sum32; В avr-gcc 4.7.x имеется тип __uint24 А что, arttab дал плохой совет? Доступ к флагам имеется? Имеется. Просто обращение к SREG по маске if (SREG & (1<<n)) {...} Лучше всю эту красоту завернуть в макрос типа: #define add16_sat(a,b) \ do \ { \ (a) += (b); \ if (SREG & (1<<SREG_C)) \ { \ (a) = -1U; \ } \ } while (0) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MaxiMuz 0 25 апреля, 2013 Опубликовано 25 апреля, 2013 · Жалоба Такой именно ассемблерный код как вы хотите может быть и не получится. Варианты: unit16_t x=sumADC; sumADC+=temp16; if (x>0xffffU-temp16) unit16_t x=sumADC; sumADC+=temp16; if (((unit32_t)x+temp16)>0xffffUL) unit32_t x=sumADC+temp16; sumADC=(unit16_t)x; if (x>0xffffUL) введение дополнительных переменных , тем более 32 бита как предлагают Alexey K и ARV не приемлемо, тажкж на счету каждый такт. Т.к. процедура выполняется в прерывании и времяни на выполнение оч.мало а по флагу переполнения не проще ли? похоже что это самый лаконичный способ! if (SREG & (1<<SREG_C)) 80: 0f b6 in r0, 0x3f; 63 82: 00 fe sbrs r0, 0 84: 04 c0 rjmp .+8 ; 0x8e <__vector_9+0x48> конечно не "brcc m1" ... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
maksimp 0 25 апреля, 2013 Опубликовано 25 апреля, 2013 · Жалоба введение дополнительных переменных , тем более 32 бита как предлагают Alexey K и ARV не приемлемо, тажкж на счету каждый такт. Т.к. процедура выполняется в прерывании и времяни на выполнение оч.мало Проверьте что в ассемблере получится. Может быть соптимизируется и нормально будет, дополнительные переменные могут быть выкинуты компилятором. похоже что это самый лаконичный способ! if (SREG & (1<<SREG_C)) Он не гаранитированно даёт результат. У вас этот фрагмент кода сейчас такой: uint16_t temp16; uint16_t sumADC; sumADC+=temp16; if (SREG & (1<<SREG_C)) Допустим что есть ещё некоторые переменные, с которыми до того или после того производятся действия, и фрагмент большего размера может быть например что-то вроде: uint16_t x,y; ... x+=y; ... uint16_t temp16; uint16_t sumADC; sumADC+=temp16; if (SREG & (1<<SREG_C)) Компилятор имеет право переставить действия, и иногда он этим правом пользуется, и может получиться в ассемблере уже что-то будто компилированное с такого текста: uint16_t x,y; ... ... uint16_t temp16; uint16_t sumADC; sumADC+=temp16; x+=y; if (SREG & (1<<SREG_C)) и результат будет неверным. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MaxiMuz 0 26 апреля, 2013 Опубликовано 26 апреля, 2013 · Жалоба Проверьте что в ассемблере получится. Может быть соптимизируется и нормально будет, дополнительные переменные могут быть выкинуты компилятором. Он не гаранитированно даёт результат. У вас этот фрагмент кода сейчас такой: uint16_t temp16; uint16_t sumADC; sumADC+=temp16; if (SREG & (1<<SREG_C)) Допустим что есть ещё некоторые переменные, с которыми до того или после того производятся действия, и фрагмент большего размера может быть например что-то вроде: uint16_t x,y; ... x+=y; ... uint16_t temp16; uint16_t sumADC; sumADC+=temp16; if (SREG & (1<<SREG_C)) Компилятор имеет право переставить действия, и иногда он этим правом пользуется, и может получиться в ассемблере уже что-то будто компилированное с такого текста: uint16_t x,y; ... ... uint16_t temp16; uint16_t sumADC; sumADC+=temp16; x+=y; if (SREG & (1<<SREG_C)) и результат будет неверным. я уже пробывал как говорили Они , компил.вводит доп.регистры и код в любом случае получается большой. А по поводу перестановки действий, вполне возможно ожидать от такого компилятора всяких "пакостей" , поэтому я каждый раз заглдядываю в ассемблерный листинг программы Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xvr 12 26 апреля, 2013 Опубликовано 26 апреля, 2013 · Жалоба Сделайте ассемблерную inline функцию. GCC это очень хорошо умеет Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться