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

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Аватара пользователя
Мikа
Потрогал лапой паяльник
Сообщения: 343
Зарегистрирован: Пн апр 01, 2013 15:13:40
Откуда: Москва

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

Сообщение Мikа »

unsigned char h=0;
unsigned char m=0;
unsigned char s=0;
unsigned long t=0;


t=36000;

h=(t/3600);
m=((t-(h*3600U))/60U);//Вычисление минут
s=((t-(h*3600U))-(m*60U));

То есть

(h)char = (long/int);
(m)char = (long - (char * int))/int);
(s)=((t-(char*int))-((char*int));

К сожалению не понимаю, в каком порядке что во что преобразуется.
Видимо, где-то переполнится один из char. Хотя, с другой стороны, проблему решили U около констант. Значит, проблема была в переполнении константы. Причём это переполнение первый раз появлялось при t == 36000. 35999 раз до этого всё было хорошо :D
Кажется, ответ виден.
h == 1 ... 9, в диапазоне t == 0 ... 32400. Что умещается в -32768 ... 32767, отведённые под int.
А при t == 36000 h == 10.
И когда умножается h*3600 == 36000, которые больше диапазона int.
Ура, теперь вообще всё понятно!
Большое спасибо за подсказки, коты!
Почему я здесь и задаю тупые вопросы?
Потому что хочу научиться.
Аватара пользователя
Chip115
Сверлит текстолит когтями
Сообщения: 1132
Зарегистрирован: Пт фев 16, 2007 14:18:20
Откуда: Новосибирск
Контактная информация:

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

Сообщение Chip115 »

Всем привет!
Как бороться с нехваткой памяти программ в МК? Камень STM32F100C4xxx
У меня на борту 16к, а код отожрал 16,5к. Включаю оптимизацию в иаре на максимум - код сокращается до 13к, но начинаются глюки вроде неправильного преобразования АЦП (может и правильно, но из-за оптимизации что-то нарушилось).
Первое что пришло в голову - это отказаться от stdperiphlib. А вообще на что надо обратить внимание при написании кода что бы не попасть в такую ситуацию?
Теория — это когда все известно, но ничего не работает. Практика — это когда все работает, но никто не знает почему. Мы же объединяем теорию и практику: ничего не работает… и никто не знает почему!
© Альберт Эйнштейн
HHIMERA
Друг Кота
Сообщения: 4583
Зарегистрирован: Вс дек 05, 2010 06:10:34
Откуда: ЮВ

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

Сообщение HHIMERA »

1. Применить камень с большей флэш...
2. Отказаться от SPL и поиграться оптимизацией...
3. Попробовать Кейл...
4. Заюзать частичную/полную хардварную реализацию девайса... т.е. заюзать хардварэ по полной... насколько возможно... Тогда основные расходы составит инициализация железа... что в принципе, в любом случае, неизбежно...
"Я не даю готовых решений, я заставляю думать!"(С)
Аватара пользователя
Леонид Иванович
Друг Кота
Сообщения: 4779
Зарегистрирован: Сб апр 02, 2011 12:40:46
Откуда: Минск
Контактная информация:

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

Сообщение Леонид Иванович »

Chip115 писал(а):Включаю оптимизацию в иаре на максимум - код сокращается до 13к, но начинаются глюки


Это ненормально. Всегда в IAR использую самый высокий уровень оптимизации, всё работает, как надо. Ищите ошибки в программе. Типичная ошибка в таких случаях - отсутствие volatile при объявлении переменных, которые одновременно используются в прерывании и в основной программе.
Аватара пользователя
Vlad399
Открыл глаза
Сообщения: 57
Зарегистрирован: Сб фев 28, 2009 19:25:24
Откуда: MSK

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

Сообщение Vlad399 »

Всем привет! Что-то меня заклинило и не могу решить простую проблему - нужно в 3-х младших разрядах порта В организовать счетчик от 0 до 7. Все остальные разряды порта должны оставаться неизменными. Делаю так:

while (1)
{PORTB = cnt_t0; // Так считает, но разряды 3...7 обнуляются
if (++cnt_t0 ==8 ) {cnt_t0 = 0;}} //cnt_t0 - счетчик от 0 до 7
PORTB ^=(1<<3); //Для контроля влияния счетчика на другие разряды. Должен быть меандр со скважностью 2
}

Так: PORTB |= cnt_t0; Не считает, все разряды заполняются 1.

Пробовал массу других вариантов, но на правильный так и не наткнулся.
Все это происходит в CVAVR, проверяется на реальной Меге8 с помощью осциллографа.
Ежели кто знает как правильно, плз, наведите на путь истинный.
Спасибо.
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

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

Сообщение WiseLord »

Ну, например так:

Код: Выделить всё

uint8_t i;
for (i = 0; i < 8; i++) {
  PORTB &= 0xF8;
  PORTB |= i;
}
Аватара пользователя
oleg110592
Друг Кота
Сообщения: 3832
Зарегистрирован: Сб сен 10, 2011 17:46:25

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

Сообщение oleg110592 »

может лучше так, чтоб нули лишние не проскакивали

Код: Выделить всё

uint8_t i, t;
for (i = 0; i < 8; i++) {
  t = PINB;
  t &= 0xF8;
  t |= i;
  PORTB = t;
}
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

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

Сообщение WiseLord »

Думаю, нулей не будет.
Оптимизатор компилятора сделает все преобразования в каком-нибудь регистре, и лишь под конец выдаст в порт результат. Самому насчёт этого можно не заморачиваться. Либо, если так уж хочется, сделать проще - что-то вроде

Код: Выделить всё

PORTB = (PORTB & 0xF8) | i;
Плюс, думаю, лучше в вашем варианте всё же не t = PINB, а t = PORTB.
Аватара пользователя
oleg110592
Друг Кота
Сообщения: 3832
Зарегистрирован: Сб сен 10, 2011 17:46:25

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

Сообщение oleg110592 »

так лучшее, листинг:

Код: Выделить всё

вариант 1
; PORTB &= 0xF8;
         IN   R30,0x5
         ANDI R30,LOW(0xF8)
         OUT  0x5,R30
; PORTB |= i;
        IN   R30,0x5
         OR   R30,R4
         OUT  0x5,R30
........

вариант 2
; PORTB = (PORTB & 0xF8) | i;
         IN   R30,0x5
         ANDI R30,LOW(0xF8)
         OR   R30,R4
         OUT  0x5,R30
Аватара пользователя
Vlad399
Открыл глаза
Сообщения: 57
Зарегистрирован: Сб фев 28, 2009 19:25:24
Откуда: MSK

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

Сообщение Vlad399 »

Спасибо за помощь! Все работает в лучшем виде. :)) И нулей никаких нет. :)
Аватара пользователя
aam
Собутыльник Кота
Сообщения: 2994
Зарегистрирован: Сб фев 20, 2010 14:00:12
Откуда: Москва

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

Сообщение aam »

Скажите, как правильно написать

Код: Выделить всё

CBI(port, pin) asm("cbi port, pin")

?
Понятно, что внутри кавычек препроцессор не подставляет. С комбинациями ## и # что-то запутался... :oops:
Аватара пользователя
ploop
Модератор
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

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

Сообщение ploop »

А зачем вам это? Ставьте нужный бит прямо на Си и всё, компилятор сам оптимизирует как надо.
Аватара пользователя
aam
Собутыльник Кота
Сообщения: 2994
Зарегистрирован: Сб фев 20, 2010 14:00:12
Откуда: Москва

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

Сообщение aam »

А как его ставить на си? Если напишу что-то типа:

Код: Выделить всё

 PORTB|=1<<PB2, 

то компилятор запихнет 3 команды - загрузить содержимое в регистр, сделать И, потом обратно записать.
А так точно 1 команда будет.
a_skr
Вымогатель припоя
Сообщения: 630
Зарегистрирован: Пн июн 14, 2010 13:07:29
Откуда: Жуковский

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

Сообщение a_skr »

WinAVR при оптимизации -O2 и выше все нормально делает:

Код: Выделить всё

  PORTB |= 1<<PB2;
  7a:   2a 9a          sbi   0x05, 2   ; 5
  PORTB &= ~(1<<PB2);
  7c:   2a 98          cbi   0x05, 2   ; 5
А в CVAVR специальные конструкции есть, PORTB.2 = 0;
Аватара пользователя
Kavka
Мудрый кот
Сообщения: 1810
Зарегистрирован: Чт июн 10, 2010 08:55:35
Откуда: Сибирские Афины

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

Сообщение Kavka »

aam писал(а):С комбинациями ## и # что-то запутался...
Может вот это пригодиться viewtopic.php?p=1576663#p1576663
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Аватара пользователя
ploop
Модератор
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

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

Сообщение ploop »

aam писал(а):то компилятор запихнет 3 команды - загрузить содержимое в регистр, сделать И, потом обратно записать.

Если несколько бит ставить - то да, так и сделает. Потому, что по другому нельзя. А вот если один бит (со включенной оптимизацией) то сделает всё правильно.
И да, я проверял.
Аватара пользователя
YS
Друг Кота
Сообщения: 7518
Зарегистрирован: Вс мар 29, 2009 22:09:05
Контактная информация:

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

Сообщение YS »

Как бороться с нехваткой памяти программ в МК? Камень STM32F100C4xxx


1. Если под проект объективно не хватает памяти, то просто взять более просторный камень, благо у ST проблем с совместимостью внутри семейства почти нет, вплоть до pin2pin.

2. Если нехватка памяти вызвана использованием необоснованных излишеств вроде printf/scanf и компании, типов float/double, чрезмерного количества библиотек-протезов для мозга и подобного, то необходимо включить голову и провести комплексный рефакторинг и оптимизацию кода.

компилятор запихнет 3 команды - загрузить содержимое в регистр, сделать И, потом обратно записать.
А так точно 1 команда будет.


Вы не поверите, GCC - очень, очень умный, почти как IAR. :) Если он увидит изменение всего одного бита, то при включенной оптимизации (я обычно оставляю -Os) он 100% подставит sbi/cbi. Одно исключение - sbi и cbi применимы не ко всем адресам.

Вообще, я, бывает, совершенно поражаюсь тому, как эффективно порой компиляторы оптимизируют код. Умная подстановка sbi/cbi - это еще цветочки.

Разумеется, если пишется процедура, которая должна быть не просто максимально быстрой, но 100% предсказуемой по длительности (например, функция общения по 1-Wire), то ее имеет смысл вынести в отдельный модуль и написать целиком на асме.
Разница между теорией и практикой на практике гораздо больше, чем в теории.
Аватара пользователя
BCluster
Собутыльник Кота
Сообщения: 2512
Зарегистрирован: Пн апр 06, 2009 19:33:29
Откуда: Молдова, Кишинев
Контактная информация:

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

Сообщение BCluster »

Согласен с ЛИ насчет того, что при включенной оптимизации, особенно в IAR, надо быть крайне внимательным c volatile. Плюс к тому, для особо тяжелых случаев можно отключить оптимизацию для определенной функции. Но хз, мне ни разу не понадобилось.
Аватара пользователя
ploop
Модератор
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

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

Сообщение ploop »

YS писал(а):Вообще, я, бывает, совершенно поражаюсь тому, как эффективно порой компиляторы оптимизируют код.

Угу, бывает глянешь листинг, почешешь затылок, присвистываешь, и думаешь "блин, а я бы до такого не додумался!" :) Но бывает и наоборот...
Аватара пользователя
Mishany
Электрический кот
Сообщения: 1031
Зарегистрирован: Чт июн 20, 2013 00:00:58
Откуда: москва, м.Сходненская

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

Сообщение Mishany »

кто поможет? как проверить нулевой бит в регистре на 0 или 1 на пример в ADMUX, ни как не могу задействовать два канала ацп, синтаксис под AVRStudio5

Код: Выделить всё

if((ADMUX & 0x0F)==0) // Если нулевой бит регистра равен нулю
или

Код: Выделить всё

if(MUX0 ==0)
(поидее бред)
или

Код: Выделить всё

if(ADMUX & (0<<0))

как привильно будет?
вроде заработала такая запись:

Код: Выделить всё

if(!(ADMUX & (1<<MUX0)))
Последний раз редактировалось Mishany Вт фев 25, 2014 21:17:20, всего редактировалось 1 раз.
Ответить

Вернуться в «Разные вопросы по МК»