Помогите ужать програаму, немного не влезает в ATTiny13

Обсуждаем контроллеры компании Atmel.
Ответить
Опытный кот
Аватара пользователя
Сообщения: 721
Зарегистрирован: Ср июн 11, 2014 09:43:13
Откуда: США

Сообщение Pink-Pank »

Компилятор должен соблюдать порядок действий, предписанный стандартом. ) И если речь идет о плавающей точке - там еще можно сделать такое упрощение. НО с целыми числами.. это должен быть очень плохой компилятор.. )
Fucking static initialization order fiasco
Контактная информация:
Реклама
Друг Кота
Аватара пользователя
Сообщения: 4732
Зарегистрирован: Ср сен 18, 2013 10:08:26
Откуда: Санкт-Петербург

Сообщение Gisteresis »

То есть CV еще и менее оптимально код переводит в инструкции?
Важнее переход к 16-ти битным операциям.
Это как понимать? Чтобы все переменные в выражених и результаты вычислений были не более 16бит?

ПС: Видимо с этого и начинают переходить на другие компиляторы.
Чувствую вы сейчас сожмете так что вся память высвободится :)))
Реклама
Друг Кота
Аватара пользователя
Сообщения: 3832
Зарегистрирован: Сб сен 10, 2011 17:46:25

Сообщение oleg110592 »

Ведь толковый компилятор что должен сделать? Правильно, на этапе компиляции посчитать, что 5000/1024 = 4.
уже предлагал автору подсократить:
5000/1024=1250/256
т.е. достаточно значение ацп умножить на 1250 (получится long) и сдвинуть вправо на 8:
Voltage = (unsigned int)(((unsigned long)ADC*1250)>>8);
Мучитель микросхем
Сообщения: 410
Зарегистрирован: Чт ноя 13, 2008 16:33:42

Сообщение vdavid »

Pink-Pank писал(а):Компилятор должен соблюдать порядок действий, предписанный стандартом.
Таки Вы правы. Стандарт предписывает строгую ассоциативность в случае смешения операций "*" и "/". Это я спутал с другим языком программирования :? .
Gisteresis писал(а):То есть CV еще и менее оптимально код переводит в инструкции?
Совсем не факт. Ваш первоначальный код в GCC был более 1200 байт :( . Если бы была возможность полностью избавиться от 32 бит, то код был бы еще меньше.
oleg110592 писал(а): т.е. достаточно значение ацп умножить на 1250 (получится long) и сдвинуть вправо на 8:
Скорее всего компилятор сам справится с этой задачей. Вот как GCC выполнил "/1024/64" :)) :

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

movw r22,r24
clr r24
clr r25
Реклама
Эиком - электронные компоненты и радиодетали
ks0
Прорезались зубы
Аватара пользователя
Сообщения: 238
Зарегистрирован: Чт фев 28, 2013 14:16:10

Сообщение ks0 »

Gisteresis писал(а): ks0, компилятор говорит что РАМ, но увеличиваю рам чтобы все глобальные переменные влезли. Потом появляется окно в котором говорится что мы вылезли за пределы 512слов... что то порядка 546слов получалось. (В общем более одного килобайта)
Ничего я не понял, извините. Есть флеш (память программы), есть ОЗУ (RAM). Как правило, сколько кодил, чаще не хватает именно RAM.
И что значит "увеличиваю рам". Это как вообще?!
Я посмотрел программу, но у меня только AVR Studio с GCC, не на чем протестить. Но такой функционал однозначно легко вписывается на аттини13. И проблем с флешем вообще быть не должно. А вот в 64 байта рам может и не влезть вся эта куча глобальных переменных! Отвыкайте кодить как на компе.
Здесь иногда для экономии оперативки лучше делать, так

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

switch(a){
case 1: PORTB |= 0b01; break;
case 2: PORTB |= 0b10; break;
case 3: PORTB |= 0b11; break;
.... }
, а не так

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

char n[]={0b01, 0b10, 0b11, ....};
PORTB |= n[a];
А нафига у вас нам volatile нужен?!
Реклама
Мучитель микросхем
Сообщения: 410
Зарегистрирован: Чт ноя 13, 2008 16:33:42

Сообщение vdavid »

ks0 писал(а): А вот в 64 байта рам может и не влезть вся эта куча глобальных переменных!
Как раз в GCC RAM используется на 56%, а вот флеша не хватает. Вам же никто не мешает откомпилировать это в Студии? Правки минимальны. Что касается volatile, то оно там по-делу, поскольку cDigit используется в двух разных прерываниях.
Реклама
Друг Кота
Аватара пользователя
Сообщения: 4732
Зарегистрирован: Ср сен 18, 2013 10:08:26
Откуда: Санкт-Петербург

Сообщение Gisteresis »

Флеш, volatile...
Да, именно так.
ks0
Прорезались зубы
Аватара пользователя
Сообщения: 238
Зарегистрирован: Чт фев 28, 2013 14:16:10

Сообщение ks0 »

itoa использовать был вариант, чтоб от делений избавиться?
Друг Кота
Аватара пользователя
Сообщения: 4732
Зарегистрирован: Ср сен 18, 2013 10:08:26
Откуда: Санкт-Петербург

Сообщение Gisteresis »

Смотрел варианты перевода цифр в строку.
Не дошло. Чем помогает itoa при переводе в код семисегментного? Там что, значение цифры совпадает с таблицей символов?
ks0
Прорезались зубы
Аватара пользователя
Сообщения: 238
Зарегистрирован: Чт фев 28, 2013 14:16:10

Сообщение ks0 »

Простой вариант. Попробуйте делить на sCounterASum когда он приравнивается 0, т.е. байт переполняется, фактически пропишите деление на 256, оно выполнится просто сдвигами. Куча экономии.
Друг Кота
Аватара пользователя
Сообщения: 4732
Зарегистрирован: Ср сен 18, 2013 10:08:26
Откуда: Санкт-Петербург

Сообщение Gisteresis »

Если все еще нужно, выкладываю проект. (с ужасным невлезающим в кристалл кодом)
Вложения
Программа Милливольтметр 0..50В 0..5А Дисплей 4х2.zip
(4.12 КБ) 157 скачиваний
ks0
Прорезались зубы
Аватара пользователя
Сообщения: 238
Зарегистрирован: Чт фев 28, 2013 14:16:10

Сообщение ks0 »

Вот такое работает?

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

    sCounterVSum++;
    if( !sCounterVSum )
    {
	     unsigned int t= *((unsigned int*)&ulVoltsSum+1); // берем старшие 2 байт (т.е. делим на 256)

        cDigit[0][0] = ~cSeg[((t/1000)%10)];
        cDigit[1][0] = ~cSeg[((t/100 )%10)];
        cDigit[2][0] = ~cSeg[((t/10  )%10)];
        cDigit[3][0] = ~cSeg[((t/1   )%10)];

        ulVoltsSum = 0;
    } 
Друг Кота
Аватара пользователя
Сообщения: 4732
Зарегистрирован: Ср сен 18, 2013 10:08:26
Откуда: Санкт-Петербург

Сообщение Gisteresis »

Pink-Pank писал(а):Вот такой код у меня уже влез. Единственное, в настройках проекта поставил поменьше размер стека (14 байт). как раз ровно под его размер.
Код влез. Но работает не так как надо. В момент первого включения цифры пробегаются и все.
Опытный кот
Аватара пользователя
Сообщения: 721
Зарегистрирован: Ср июн 11, 2014 09:43:13
Откуда: США

Сообщение Pink-Pank »

А изначально- то код рабочий был? А то я его не особо ковырял. Только на предмет явных ошибок и неточностей.
Fucking static initialization order fiasco
Контактная информация:
Мучитель микросхем
Сообщения: 410
Зарегистрирован: Чт ноя 13, 2008 16:33:42

Сообщение vdavid »

Gisteresis
Так Вы же ничего не оставили под аппаратный стек. Так работать и не должно.
Попробуйте вот это.
Чуть подправил. Строка при копипасте задвоилась :( .
Вложения
rk1.zip
(4.05 КБ) 141 скачивание
Друг Кота
Аватара пользователя
Сообщения: 4732
Зарегистрирован: Ср сен 18, 2013 10:08:26
Откуда: Санкт-Петербург

Сообщение Gisteresis »

Pink-Pank
Изначально код был рабочий, но под один АЦП, был просто милливольтметр. Остальное все тоже самое.

При переделке в 2 АЦП, забыл изменить ноги вывода. Поправил. Заработал дисплей.

vdavid, вставил ваш код, он заработал. Предыдущий вариант показывал все сегменты на индикаторах.
Последний код стал показывать, но первая декада всегда 0. Значение начинает отображаться со второй декады. Значение выводится правильное.
Не успел попробовать, думаю просто в цикле нужно к i прибавить или отнять 1. Тогда значение будет отображаться с первой декады.

Всем котам спокойной ночи.
Мучитель микросхем
Сообщения: 410
Зарегистрирован: Чт ноя 13, 2008 16:33:42

Сообщение vdavid »

Да, должно быть так:

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

        i=4;
        while (i>0) {
           i--;
           cDigit[i] = ~cSeg[ulVoltsSum%10];
           ulVoltsSum /=10;
        } 
и так:

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

        i=8;
        while (i>4) {
           i--;
           cDigit[i] = ~cSeg[ulAmpersSum%10];
           ulAmpersSum /=10;
        }
Друг Кота
Аватара пользователя
Сообщения: 4732
Зарегистрирован: Ср сен 18, 2013 10:08:26
Откуда: Санкт-Петербург

Сообщение Gisteresis »

Работает, вывел еще десятичную точку. Всетаки 64 отсчетов в усреднении мало, рябит. Сейчас разбираюсь в вашем коде, хочу еще сделать отсчетов 256 (на 300 нормально выводило) и поменять уже на реальные 50В и 5А.
В начале не мог понять почему десятичная точка не выводится, а у меня число выводится по снятым битам, операция |= наоборот ее гасила :facepalm:
Спойлер

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

if( input_index == 2 )
{
    ulVoltsSum += ADCW;
    sCounterVSum++;
    if( sCounterVSum == 64 )
    {
        ulVoltsSum=(5000UL*ulVoltsSum)>>16;
        i=4;
        while (i>0) {
           i--;
           cDigit[i] = ~cSeg[ulVoltsSum%10];
           ulVoltsSum /=10;
        }
        cDigit[1] &= ~0b10000000;
        ulVoltsSum = 0;
        sCounterVSum = 0;        
    } 
}
if( input_index == 3 )
{   
    ulAmpersSum += ADCW;
    sCounterASum++;
    if( sCounterASum == 64 )
    {
        ulAmpersSum=(5000UL*ulAmpersSum)>>16;
        i=8;
        while (i>4) {
           i--;
           cDigit[i] = ~cSeg[ulAmpersSum%10];
           ulAmpersSum /=10;
        }
        cDigit[4] &= ~0b10000000;
        ulAmpersSum = 0;
        sCounterASum = 0;        
    }
}
Мудрый кот
Аватара пользователя
Сообщения: 1810
Зарегистрирован: Чт июн 10, 2010 08:55:35
Откуда: Сибирские Афины

Сообщение Kavka »

Сколько по памяти получилось? А то надо байт 30 минимум на стек оставлять при использовании математики и прерываний.
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Мучитель микросхем
Сообщения: 410
Зарегистрирован: Чт ноя 13, 2008 16:33:42

Сообщение vdavid »

Gisteresis писал(а): Всетаки 64 отсчетов в усреднении мало,
Нет, не мало. О чем речь? Болтанка сильная или частые обновления приводят к мельтишению? Болтанку можно дополнительно уменьшить конденсаторами на входах АЦП. Ну и, естественно, посмотреть на разводку земли. Кроме того шумы будут от коммутации индикаторов. Возможно надо развязать питание МК LC фильтром.
Частота же обновления уменьшается тысячей и одним способом без изменения числа отсчетов.
Впрочем, если очень хочется, то вот Вам 256 отчетов. Пробуйте.
Вложения
rk2.zip
(4.07 КБ) 155 скачиваний
Ответить

Вернуться в «AVR»