Здесь есть что-то неоптимальное:
uint8_t low_value = ADC & 0x00FF;
Вы читаете ADC
, 16-битный регистр, реализованный как пара 8-битных регистров. Как показано в разборке, для этого требуются две инструкции in
, по одной на байт. И тогда вы просто выбрасываете один из этих байтов. Вы можете подумать, что компилятор достаточно умен, чтобы не читать байт, который он собирается сразу отбросить. К сожалению, он не может этого сделать, поскольку регистры ввода-вывода объявлены как volatile
. Компилятор вынужден обращаться к регистру столько раз, сколько это делает исходный код.
Если вам нужен только младший байт, вы должны читать только этот байт:
uint8_t low_value = ADCL;
Затем вы написали :
uint8_t high_value = ADC & 0xFF00;
Как объяснялось в предыдущем ответе, high_value
будет равно нулю. Однако компилятору придется снова прочитать два байта, потому что регистр ввода-вывода - volatile
. Если вы хотите прочитать старший байт, прочтите ADCH
.
Но зачем вам читать эти два байта один за другим? Чтобы собрать их обратно в 16-битную переменную? В таком случае нет необходимости читать их отдельно. Вместо этого просто прочитайте 16-битный регистр самым простым способом:
uint16_t value = ADC;
Долгое время a go, g cc не знал, как обрабатывать 16-битные регистры, и людям приходилось прибегать к чтению байтов один за другим, а затем склеивать их вместе. Вы все еще можете найти в Интернете очень старый пример кода, который делает это. Сегодня нет абсолютно никаких причин продолжать программировать таким образом.
Тогда вы написали:
//problem here
Нет, проблема не в этом. Это не то, что сгенерировало инструкцию rjmp
. Проблема, вероятно, кроется сразу после этой строки в коде, который вы решили не публиковать. У вас какая-то ошибка, которая проявляется только при включенной оптимизации. Это типично для кода, который производит неопределенное поведение : работает, как ожидалось, с отключенной оптимизацией, затем делает странные «необъяснимые» вещи, когда вы включаете оптимизацию.