Например TDA7294

Форум РадиоКот • Просмотр темы - Помогите ужать програаму, немного не влезает в ATTiny13
Форум РадиоКот
Здесь можно немножко помяукать :)

Текущее время: Пн июл 28, 2025 04:14:07

Часовой пояс: UTC + 3 часа


ПРЯМО СЕЙЧАС:



Начать новую тему Ответить на тему  [ Сообщений: 87 ]  1, , , ,  
Автор Сообщение
Не в сети
 Заголовок сообщения: Помогите ужать програаму, немного не влезает в ATTiny13
СообщениеДобавлено: Вт окт 07, 2014 20:26:40 
Друг Кота
Аватар пользователя

Карма: 117
Рейтинг сообщений: 1531
Зарегистрирован: Ср сен 18, 2013 10:08:26
Сообщений: 4732
Откуда: Санкт-Петербург
Рейтинг сообщения: 0
Мяяяяу
Помогите ужать программу АмперВольтметра на ATTiny13.
Буквально немного нехватает памяти.
Индикация динамическая в прерывании таймера.
В прерывании АЦП преобразования условных единиц в цифры на дисплее. Дисплей 4х2 семисегментный.
До этого проект был только для вольтметра, памяти соответственно хватало.

Спойлер
Код:
#include <tiny13a.h>
#include <delay.h>

// Declare your global variables here

void wr_reg(char cData)
{
    char temp = cData;
    char i=0;
    for(i=0; i<8; i++)
    {
        PORTB.1 = (temp & 0x80);
        #asm("nop");
        PORTB.0 = 1;
        #asm("nop");       
        PORTB.0 = 0;
        temp = temp << 1;
    }
}

void latch_reg()
{
    #asm("nop");
    PORTB.2 = 1;
    #asm("nop");         
    PORTB.2 = 0;
}

char cSeg[]={
0b00111111, // 0
0b00000110, // 1
0b01011011, // 2
0b01001111, // 3
0b01100110, // 4
0b01101101, // 5
0b01111101, // 6
0b00000111, // 7
0b01111111, // 8
0b01101111  // 9
};

char cDec = 0;
volatile char cDigit[][2] = {
{0,0b00000001},{0,0b00000010},{0,0b00000100},{0,0b00001000},
{0,0b00010000},{0,0b00100000},{0,0b01000000},{0,0b10000000}};
interrupt [TIM0_COMPA] void timer0_compa_isr(void)
{
    wr_reg(cDigit[cDec][1]);
    wr_reg(cDigit[cDec][0]);
    //wr_reg(~cSeg[cDec]);
    latch_reg();
    cDec += 1;
    if( cDec > 7 )
        cDec = 0;
       
    TCNT0 = 0;
}

#define FIRST_ADC_INPUT 2
#define LAST_ADC_INPUT 3
unsigned int adc_data[LAST_ADC_INPUT-FIRST_ADC_INPUT+1];
#define ADC_VREF_TYPE 0x00

unsigned long ulVoltsSum = 0;
char sCounterVSum = 0;

unsigned long ulAmpersSum = 0;
char sCounterASum = 0;

// ADC interrupt service routine
// with auto input scanning
interrupt [ADC_INT] void adc_isr(void)
{
static unsigned char input_index=0;
// Read the AD conversion result
adc_data[input_index]=ADCW;
// Select next ADC input
if (++input_index > (LAST_ADC_INPUT-FIRST_ADC_INPUT))
   input_index=0;
ADMUX=(FIRST_ADC_INPUT | (ADC_VREF_TYPE & 0xff))+input_index;

if( input_index == 3 )
{
    ulVoltsSum += 5000UL*adc_data[input_index]/1024;
    sCounterVSum++;
    if( sCounterVSum == 255 )
    {
        cDigit[0][0] = ~cSeg[((ulVoltsSum/sCounterVSum/1000)%10)];
        cDigit[1][0] = ~cSeg[((ulVoltsSum/sCounterVSum/100 )%10)];
        cDigit[2][0] = ~cSeg[((ulVoltsSum/sCounterVSum/10  )%10)];
        cDigit[3][0] = ~cSeg[((ulVoltsSum/sCounterVSum/1   )%10)];
        ulVoltsSum = 0;
        sCounterVSum = 0;       
    }
}

if( input_index == 2 )
{   
    ulAmpersSum += 5000UL*adc_data[input_index]/1024;
    sCounterASum++;
    if( sCounterASum == 255 )
    {
        cDigit[4][0] = ~cSeg[((ulAmpersSum/sCounterASum/1000)%10)];
        cDigit[5][0] = ~cSeg[((ulAmpersSum/sCounterASum/100 )%10)];
        cDigit[6][0] = ~cSeg[((ulAmpersSum/sCounterASum/10  )%10)];
        cDigit[7][0] = ~cSeg[((ulAmpersSum/sCounterASum/1   )%10)];
        ulAmpersSum = 0;
        sCounterASum = 0;       
    }
}
                 
// Delay needed for the stabilization of the ADC input voltage
delay_us(10);
// Start the AD conversion
ADCSRA|=0x40;
}


void main(void)
{
// Declare your local variables here

// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

// Input/Output Ports initialization
// Port B initialization
// Func5=In Func4=In Func3=In Func2=In Func1=In Func0=Out
// State5=T State4=T State3=T State2=T State1=T State0=0
PORTB=0x00;
DDRB=0x07;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 9400,000 kHz
// Mode: Normal top=0xFF
// OC0A output: Clear on compare match
// OC0B output: Disconnected
TCCR0A=0x00;
TCCR0B=0x05;
TCNT0=0x00;
OCR0A=0x20;
OCR0B=0x00;

// External Interrupt(s) initialization
// INT0: Off
// Interrupt on any change on pins PCINT0-5: Off
GIMSK=0x00;
MCUCR=0x00;

// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=0x04;

// Analog Comparator initialization
// Analog Comparator: Off
ACSR=0x80;
ADCSRB=0x00;
DIDR0=0x00;

// ADC initialization
// ADC Clock frequency: 73,438 kHz
// ADC Bandgap Voltage Reference: Off
// ADC Auto Trigger Source: ADC Stopped
// Digital input buffers on ADC0: Off, ADC1: Off, ADC2: On, ADC3: On
DIDR0&=0x03;
DIDR0|=0x24;
ADMUX=FIRST_ADC_INPUT | (ADC_VREF_TYPE & 0xff);
ADCSRA=0xCF;

#asm("sei")

   while(1)
   {
   }
}


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Помогите ужать програаму, немного не влезает в ATTiny13
СообщениеДобавлено: Вт окт 07, 2014 20:44:08 
Ум, честь и совесть. И скромность.
Аватар пользователя

Карма: 98
Рейтинг сообщений: 2116
Зарегистрирован: Чт дек 28, 2006 08:19:56
Сообщений: 18403
Откуда: Новочеркасск
Рейтинг сообщения: 2
Медали: 2
Получил миской по аватаре (1) Мявтор 3-й степени (1)
кажется я вам уже советовал избавиться от формирования символов из чисел в обработчиках прерываний... тем более при помощи обращения к функциям. хотите помощи - слушайте советы.

P.S. возможно, я советовал и не вам - наредкость однотипные проблемы постоянно светятся... если что - заранее извините.

_________________
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!


Вернуться наверх
 
 Заголовок сообщения: Re: Помогите ужать програаму, немного не влезает в ATTiny13
СообщениеДобавлено: Вт окт 07, 2014 21:33:05 
Попробуйте переписать на асме. должно влезть


Вернуться наверх
   
 
Не в сети
 Заголовок сообщения: Re: Помогите ужать програаму, немного не влезает в ATTiny13
СообщениеДобавлено: Вт окт 07, 2014 22:16:27 
Мучитель микросхем

Карма: 8
Рейтинг сообщений: 101
Зарегистрирован: Чт ноя 13, 2008 16:33:42
Сообщений: 410
Рейтинг сообщения: 2
Если хватит 63 (или 64) измерений вместо 255 (а их таки достаточно), то элементарно:

Спойлер
Код:
unsigned int ulVoltsSum = 0;
char sCounterVSum = 0;

unsigned int ulAmpersSum = 0;
char sCounterASum = 0;

// ADC interrupt service routine
// with auto input scanning
interrupt [ADC_INT] void adc_isr(void)
{
unsigned char i;
static unsigned char input_index=0;
// Read the AD conversion result
adc_data=ADCW;
// Select next ADC input
if (++input_index > LAST_ADC_INPUT)
   input_index=FIRST_ADC_INPUT;
ADMUX=ADC_VREF_TYPE +input_index;

if( input_index == 2 )
{
    ulVoltsSum += adc_data;
    sCounterVSum++;
    if( sCounterVSum == 64 )
   
    {
        ulVoltsSum=(5000UL*ulVoltsSum)/1024/64;
        ulVoltsSum=(5000UL*ulVoltsSum)/1024/64;
        i=4;
        while (i>0) {
           cDigit[i][0] = ~cSeg[ulVoltsSum%10];
           ulVoltsSum /=10;
           i--;
        }
/*
        cDigit[0][0] = ~cSeg[((ulVoltsSum/1000)%10)];
        cDigit[1][0] = ~cSeg[((ulVoltsSum/100 )%10)];
        cDigit[2][0] = ~cSeg[((ulVoltsSum/10  )%10)];
        cDigit[3][0] = ~cSeg[((ulVoltsSum/1   )%10)];
*/
        ulVoltsSum = 0;
        sCounterVSum = 0;       
    }
}

if( input_index == 3 )
{   
    ulAmpersSum += adc_data;
    sCounterASum++;
    if( sCounterASum == 64 )
    {
        ulAmpersSum=(5000UL*ulAmpersSum)/1024/64;
        i=8;
        while (i>3) {
           cDigit[i][0] = ~cSeg[ulAmpersSum%10];
           ulAmpersSum /=10;
           i--;
        }
/*          
        cDigit[4][0] = ~cSeg[((ulAmpersSum/1000)%10)];
        cDigit[5][0] = ~cSeg[((ulAmpersSum/100 )%10)];
        cDigit[6][0] = ~cSeg[((ulAmpersSum/10  )%10)];
        cDigit[7][0] = ~cSeg[((ulAmpersSum/1   )%10)];
*/
        ulAmpersSum = 0;
        sCounterASum = 0;       
    }
}
                 
// Delay needed for the stabilization of the ADC input voltage
delay_us(10);
// Start the AD conversion
ADCSRA|=0x40;
}

Заодно зачем adc_data массив?
Ну и с input_index разберитесь.
Можно еще оптимизировать, но и так влезет.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Помогите ужать програаму, немного не влезает в ATTiny13
СообщениеДобавлено: Ср окт 08, 2014 05:42:37 
Прорезались зубы
Аватар пользователя

Зарегистрирован: Чт фев 28, 2013 14:16:10
Сообщений: 222
Рейтинг сообщения: 2
Gisteresis писал(а):
Буквально немного нехватает памяти.

А чего не хватает, флеша или ОЗУ?
Если ОЗУ то проще от массивов избавиться и сделать обычные switch.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Помогите ужать програаму, немного не влезает в ATTiny13
СообщениеДобавлено: Ср окт 08, 2014 07:09:14 
Опытный кот
Аватар пользователя

Карма: 6
Рейтинг сообщений: 54
Зарегистрирован: Ср июн 11, 2014 09:43:13
Сообщений: 721
Откуда: США
Рейтинг сообщения: 2
Можно еще без всяких переделок попробовать изменить уровень оптимизации на больший в настройках проекта. ;) Правда, после этого программа бывает работает не так, как при стандартном уровне оптимизации. )

_________________
Fucking static initialization order fiasco


Вернуться наверх
 
Распродажа паяльного оборудования ATTEN!
Паяльные станции, паяльники и аксессуары по самой выгодной цене.

По промокоду radiokot скидка 10%
Не в сети
 Заголовок сообщения: Re: Помогите ужать програаму, немного не влезает в ATTiny13
СообщениеДобавлено: Ср окт 08, 2014 08:18:13 
Друг Кота
Аватар пользователя

Карма: 117
Рейтинг сообщений: 1531
Зарегистрирован: Ср сен 18, 2013 10:08:26
Сообщений: 4732
Откуда: Санкт-Петербург
Рейтинг сообщения: 0
AVR, вы советовали мне. Но я не понимаю чем это поможет? Ну перенесу я код из одного места в другое. Памяти от этого прибавится?

vdavid, спасибо попробую.
adc массив только потому что это сгенерировал генератор кода. По этому поводу прошу не бить, понимаю что генератором пользоваться неприлично и все такое.
Что бы вы еще оптимизировали? (это мне для общего развития)

ks0, компилятор говорит что РАМ, но увеличиваю рам чтобы все глобальные переменные влезли. Потом появляется окно в котором говорится что мы вылезли за пределы 512слов... что то порядка 546слов получалось. (В общем более одного килобайта)

Pink-Pank. Пишу в CVAVR, там и так по умолчанию максимум стоит.

На чистый асм переходить не хочется.

Вообще у меня приличный опыт программирования под комп. Микроконтроллеры конечно имеют свою специфику. Пока плохо ее понимаю. Можете что нибудь рекомендовать на эту тему? Книжечку, статью, советы...
В комповых прогах массив по объему ничем не отличается от такого же количества переменных. В МК есть разница?


Последний раз редактировалось Gisteresis Ср окт 08, 2014 08:29:55, всего редактировалось 1 раз.

Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Помогите ужать програаму, немного не влезает в ATTiny13
СообщениеДобавлено: Ср окт 08, 2014 08:23:17 
Опытный кот
Аватар пользователя

Карма: 6
Рейтинг сообщений: 54
Зарегистрирован: Ср июн 11, 2014 09:43:13
Сообщений: 721
Откуда: США
Рейтинг сообщения: 2
Чтобы понимать МК - только ассемблер и доскональное изучение даташита. )) А проект CV можете выложить в архиве? )

_________________
Fucking static initialization order fiasco


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Помогите ужать програаму, немного не влезает в ATTiny13
СообщениеДобавлено: Ср окт 08, 2014 08:31:23 
Друг Кота
Аватар пользователя

Карма: 117
Рейтинг сообщений: 1531
Зарегистрирован: Ср сен 18, 2013 10:08:26
Сообщений: 4732
Откуда: Санкт-Петербург
Рейтинг сообщения: 0
Могу. Вечером сделаю.
Цель проекта. Обычный ампер вольтметр. Но я как то проектов под Си не нашел, поэтому написал сам. Уже и плата готова. Тем более хотелось написать самому, чтобы получить опыт.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Помогите ужать програаму, немного не влезает в ATTiny13
СообщениеДобавлено: Ср окт 08, 2014 08:43:55 
Друг Кота
Аватар пользователя

Карма: 8
Рейтинг сообщений: 28
Зарегистрирован: Вс мар 22, 2009 17:31:41
Сообщений: 4077
Рейтинг сообщения: 2
Gisteresis писал(а):
Вообще у меня приличный опыт программирования под комп.

Вот в этом и проблема.
На микроконтроллере важно не что-бы код был красивый, а занимал мало памяти и быстро выполнялся.

Например temp = temp << 1; можно заменить на temp<<=1;
или вот cDec += 1; ---> cDec++;

а лучше
wr_reg(cDigit[cDec][1]);
wr_reg(cDigit[cDec][0]);
//wr_reg(~cSeg[cDec]);
latch_reg();
cDec += 1;
if( cDec > 7 )
cDec = 0;

написать так (но это под сомнением)
wr_reg(cDigit[cDec&0b111][1]);
wr_reg(cDigit[cDec&0b111][0]);
//wr_reg(~cSeg[cDec]);
latch_reg();


cDigit[0][0] = ~cSeg[((ulVoltsSum/sCounterVSum/1000)%10)]; Я думаю эти строки и заняли всю память, к тому-же они дублируются, а не сделанны подпрограммой

_________________
Раз reset, два reset - полyчи на диске bad !
Тpанзистоp p-n-p. Plug-n-Play ?
У кого что сбоит, тот о том и говорит.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Помогите ужать програаму, немного не влезает в ATTiny13
СообщениеДобавлено: Ср окт 08, 2014 08:51:58 
Друг Кота
Аватар пользователя

Карма: 49
Рейтинг сообщений: 392
Зарегистрирован: Вс июл 12, 2009 19:15:29
Сообщений: 7013
Откуда: Ижевск
Рейтинг сообщения: 2
Сначала хотел было посоветовать убрать нопы в функции вывода. А потом увидел ЭТО:
Код:
        cDigit[0][0] = ~cSeg[((ulVoltsSum/sCounterVSum/1000)%10)];
        cDigit[1][0] = ~cSeg[((ulVoltsSum/sCounterVSum/100 )%10)];
        cDigit[2][0] = ~cSeg[((ulVoltsSum/sCounterVSum/10  )%10)];
        cDigit[3][0] = ~cSeg[((ulVoltsSum/sCounterVSum/1   )%10)];

:shock:
Ещё бы не хватало памяти!!! Это деление всё и сжирает. Не интереснее ли вместо /10 написать *2560 и /256. Умножение разложить на степени двойки, а деление - отсечкой младшего байта? Кстати, сам компилятор это сделает, без потуг со стороны писателя.

_________________
Docendo discimus


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Помогите ужать програаму, немного не влезает в ATTiny13
СообщениеДобавлено: Ср окт 08, 2014 08:54:06 
Друг Кота
Аватар пользователя

Карма: 49
Рейтинг сообщений: 392
Зарегистрирован: Вс июл 12, 2009 19:15:29
Сообщений: 7013
Откуда: Ижевск
Рейтинг сообщения: 4
WandererSc писал(а):
Например temp = temp << 1; можно заменить на temp<<=1;
или вот cDec += 1; ---> cDec++;

Никакого смысла в этом нет, ассемблерный код будет одинаковый, выигрыша в памяти не даст.
PS. Извинйте за оверпост.

_________________
Docendo discimus


Последний раз редактировалось pyzhman Ср окт 08, 2014 08:54:54, всего редактировалось 1 раз.

Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Помогите ужать програаму, немного не влезает в ATTiny13
СообщениеДобавлено: Ср окт 08, 2014 08:54:46 
Опытный кот
Аватар пользователя

Карма: 6
Рейтинг сообщений: 54
Зарегистрирован: Ср июн 11, 2014 09:43:13
Сообщений: 721
Откуда: США
Рейтинг сообщения: 2
Цитата:
Например temp = temp << 1; можно заменить на temp<<=1;
или вот cDec += 1; ---> cDec++;


Компилятор вообще-то и то, и то скомпилирует в одно и то же. Это просто разные формы записи одного и то же.

А вот это место вызывает сомнения:
Код:
void wr_reg(char cData)
{
    char temp = cData;
    char i=0;
    for(i=0; i<8; i++)
    {
        PORTB.1 = (temp & 0x80);
        #asm("nop");
        PORTB.0 = 1;
        #asm("nop");       
        PORTB.0 = 0;
        temp = temp << 1;
    }
}


Вообще можно PORTB.1 = (cData & 0x80); сразу написать..

у тини 13 всего 64 байта ОЗУ. С учетом вызова функций и стека - того меньше. Можно вот этот массив константный запихнуть во флеш:

Код:
flash char cSeg[]={
0b00111111, // 0
0b00000110, // 1
0b01011011, // 2
0b01001111, // 3
0b01100110, // 4
0b01101101, // 5
0b01111101, // 6
0b00000111, // 7
0b01111111, // 8
0b01101111  // 9
};


RAM уже будет хватать. А вот с флеш надо будет думать. Правильно подметили - деление много сжирает.

_________________
Fucking static initialization order fiasco


Последний раз редактировалось Pink-Pank Ср окт 08, 2014 09:14:48, всего редактировалось 1 раз.

Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Помогите ужать програаму, немного не влезает в ATTiny13
СообщениеДобавлено: Ср окт 08, 2014 08:59:37 
Друг Кота
Аватар пользователя

Карма: 49
Рейтинг сообщений: 392
Зарегистрирован: Вс июл 12, 2009 19:15:29
Сообщений: 7013
Откуда: Ижевск
Рейтинг сообщения: 2
Тогда cData придётся курёчить, а вдруг она еще как-то там в теле используется? Если же нет, то, конечно, проще сразу её двигать.
Ещё:
вот это
Код:
ulVoltsSum/sCounterVSum
хотя бы не прописывать каждый раз, а присвоить значение временной переменной и с ней уже оперировать.

_________________
Docendo discimus


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Помогите ужать програаму, немного не влезает в ATTiny13
СообщениеДобавлено: Ср окт 08, 2014 09:15:15 
Опытный кот
Аватар пользователя

Карма: 6
Рейтинг сообщений: 54
Зарегистрирован: Ср июн 11, 2014 09:43:13
Сообщений: 721
Откуда: США
Рейтинг сообщения: 2
Так она локальная все равно.. Что бы ее не покуречить?

Код:
char cDec = 0;


volatile

_________________
Fucking static initialization order fiasco


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Помогите ужать програаму, немного не влезает в ATTiny13
СообщениеДобавлено: Ср окт 08, 2014 09:25:55 
Друг Кота
Аватар пользователя

Карма: 117
Рейтинг сообщений: 1531
Зарегистрирован: Ср сен 18, 2013 10:08:26
Сообщений: 4732
Откуда: Санкт-Петербург
Рейтинг сообщения: 0
Функция wr_reg используется для записи в регистр 74HC595. Их на плате 2 штуки и используются для динамической индикации на семисегментниках. Первый выводит число, второй активирует декаду.
Чтобы проще было декады активировать я создал структуру
Код:
volatile char cDigit[][2] = {
{0,0b00000001},{0,0b00000010},{0,0b00000100},{0,0b00001000},
{0,0b00010000},{0,0b00100000},{0,0b01000000},{0,0b10000000}};

первое значение это значение декады, а второе это адрес декады.

Далее это используется в таймере. Который поочередно активирует декады. Он занимается только динамическим выводом.

Pink-Pank писал(а):
Зачем в конце temp = temp << 1?

Так это нужно для вывода на ногу и потом в регистр 595.
Если мы будем саму переменную сдвигать то она повредится и при следующем выводе будет шлак.

Я понимаю, что проблема в привычке программирования под комп. Ваши советы лучше всяких мануалов продвигают понимание. Респект.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Помогите ужать програаму, немного не влезает в ATTiny13
СообщениеДобавлено: Ср окт 08, 2014 09:32:02 
Опытный кот
Аватар пользователя

Карма: 6
Рейтинг сообщений: 54
Зарегистрирован: Ср июн 11, 2014 09:43:13
Сообщений: 721
Откуда: США
Рейтинг сообщения: 2
cData не повредится - она локальная. Функции передается значение, а не ссылка на переменную.

latch_reg() - проще от этой функции вообще избавиться и кинуть ее код сразу в прерывание - больше нигде она не используется.

unsigned long ulVoltsSum = 0;
char sCounterVSum = 0;

unsigned long ulAmpersSum = 0;
char sCounterASum = 0;

adc_data[]

аналогично, volatile, либо засовываете их в само прерывание с модификатором static

Вывод на дисплей можно организовать несколько иначе. Можно цифры для вывода хранить в BCD формате (в два раза меньше места займут в ОЗУ), а преобразование их в нужный код индикатора делать непосредственно перед выводом. Получится довольно быстро и экономно.

Обнуление регистров периферии при инициализации также можно выкинуть - там и так нули будут при сбросе.

Цитата:
// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif


можно выкинуть и при прошивке просто не ставить фьюз DIV8

еще немного больше скорости и меньше места, если сделать так:

Код:
flash char cSeg[]={
~0b00111111, // 0
~0b00000110, // 1
~0b01011011, // 2
~0b01001111, // 3
~0b01100110, // 4
~0b01101101, // 5
~0b01111101, // 6
~0b00000111, // 7
~0b01111111, // 8
~0b01101111  // 9
};


Код:
if( sCounterVSum == 255 )
    {
        cDigit[0][0] = cSeg[((ulVoltsSum/sCounterVSum/1000)%10)];
        cDigit[1][0] = cSeg[((ulVoltsSum/sCounterVSum/100 )%10)];
        cDigit[2][0] = cSeg[((ulVoltsSum/sCounterVSum/10  )%10)];
        cDigit[3][0] = cSeg[((ulVoltsSum/sCounterVSum)%10)];
        ulVoltsSum = 0;
        sCounterVSum = 0;       
    }


Т.е. инверсию сразу применили к константам.

А еще можно вот так упростить, чтобы переменную не тискать. ;)
Код:
if( sCounterVSum == 0 )
    {   
        cDigit[0][0] = cSeg[((ulVoltsSum/256000)%10)];
        cDigit[1][0] = cSeg[((ulVoltsSum/25600)%10)];
        cDigit[2][0] = cSeg[((ulVoltsSum/2560)%10)];
        cDigit[3][0] = cSeg[(ulVoltsSum/256%10)];
        sCounterVSum = 0;       
    }


Странно, но в CV сдвиг на 8 занимает в памяти программ больше места, чем деление на 256.. )

Код:
DIDR0&=0x03;
DIDR0|=0x24;


меняем просто на
Код:
DIDR0=0x24;


Вот такой код у меня уже влез. Единственное, в настройках проекта поставил поменьше размер стека (14 байт). как раз ровно под его размер.

Спойлер
Код:
#include <tiny13a.h>
#include <delay.h>

void wr_reg(char cData)
{
    char i=0;
    for(i=0; i<8; i++)
    {
        PORTB.1 = (cData & 0x80);
        #asm("nop");
        PORTB.0 = 1;
        #asm("nop");       
        PORTB.0 = 0;
        cData = cData << 1;
    }
}

flash char cSeg[]={
~0b00111111, // 0
~0b00000110, // 1
~0b01011011, // 2
~0b01001111, // 3
~0b01100110, // 4
~0b01101101, // 5
~0b01111101, // 6
~0b00000111, // 7
~0b01111111, // 8
~0b01101111  // 9
};

volatile char cDigit[][2] = {
{0,0b00000001},{0,0b00000010},{0,0b00000100},{0,0b00001000},
{0,0b00010000},{0,0b00100000},{0,0b01000000},{0,0b10000000}};

interrupt [TIM0_COMPA] void timer0_compa_isr(void)
{
    static char cDec = 0;

    wr_reg(cDigit[cDec][1]);
    wr_reg(cDigit[cDec][0]);
    //wr_reg(~cSeg[cDec]);
    #asm("nop");
    PORTB.2 = 1;
    #asm("nop");         
    PORTB.2 = 0;
    cDec += 1;
    if( cDec > 7 )
        cDec = 0;
}

#define FIRST_ADC_INPUT 2
#define LAST_ADC_INPUT 3
#define ADC_VREF_TYPE 0x00

volatile unsigned int adc_data[LAST_ADC_INPUT-FIRST_ADC_INPUT+1]; 

volatile unsigned long ulVoltsSum = 0;
volatile char sCounterVSum = 0;

volatile unsigned long ulAmpersSum = 0;
volatile char sCounterASum = 0;

// ADC interrupt service routine
// with auto input scanning
interrupt [ADC_INT] void adc_isr(void)
{
static unsigned char input_index=0;
// Read the AD conversion result
adc_data[input_index]=ADCW;
// Select next ADC input
if (++input_index > (LAST_ADC_INPUT-FIRST_ADC_INPUT))
   input_index=0;
ADMUX=(FIRST_ADC_INPUT | (ADC_VREF_TYPE & 0xff))+input_index;

if( input_index == 3 )
{
    ulVoltsSum += 5000UL*adc_data[input_index]/1024;
    sCounterVSum++;
    if( sCounterVSum == 0 )
    {   
        cDigit[0][0] = cSeg[((ulVoltsSum/256000)%10)];
        cDigit[1][0] = cSeg[((ulVoltsSum/25600)%10)];
        cDigit[2][0] = cSeg[((ulVoltsSum/2560)%10)];
        cDigit[3][0] = cSeg[(ulVoltsSum/256%10)];
        sCounterVSum = 0;       
    }
}

if( input_index == 2 )
{   
    ulAmpersSum += 5000UL*adc_data[input_index]/1024;
    sCounterASum++;
    if( sCounterASum == 0 )
    {
        cDigit[4][0] = cSeg[((ulAmpersSum/256000)%10)];
        cDigit[5][0] = cSeg[((ulAmpersSum/25600)%10)];
        cDigit[6][0] = cSeg[((ulAmpersSum/2560)%10)];
        cDigit[7][0] = cSeg[((ulAmpersSum/256)%10)];     
        sCounterASum = 0;   
    }
}
                 
// Start the AD conversion
ADCSRA|=0x40;
}


void main(void)
{

// Input/Output Ports initialization
// Port B initialization
// Func5=In Func4=In Func3=In Func2=In Func1=In Func0=Out
// State5=T State4=T State3=T State2=T State1=T State0=0
DDRB=0x07;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 9400,000 kHz
// Mode: Normal top=0xFF
// OC0A output: Clear on compare match
// OC0B output: Disconnected
TCCR0B=0x05;
OCR0A=0x20;

// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=0x04;

// Analog Comparator initialization
// Analog Comparator: Off
ACSR=0x80;

// ADC initialization
// ADC Clock frequency: 73,438 kHz
// ADC Bandgap Voltage Reference: Off
// ADC Auto Trigger Source: ADC Stopped
// Digital input buffers on ADC0: Off, ADC1: Off, ADC2: On, ADC3: On
DIDR0 = 0x24;
ADMUX=FIRST_ADC_INPUT | (ADC_VREF_TYPE & 0xff);
ADCSRA=0xCF;

#asm("sei")
}

_________________
Fucking static initialization order fiasco


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Помогите ужать програаму, немного не влезает в ATTiny13
СообщениеДобавлено: Ср окт 08, 2014 11:28:12 
Мучитель микросхем

Карма: 8
Рейтинг сообщений: 101
Зарегистрирован: Чт ноя 13, 2008 16:33:42
Сообщений: 410
Рейтинг сообщения: 2
Ну Вы, блин, даете (с) :)
Вполне очевидно, что это:
Код:
        cDigit[0][0] = cSeg[((ulVoltsSum/256000)%10)];
        cDigit[1][0] = cSeg[((ulVoltsSum/25600)%10)];
        cDigit[2][0] = cSeg[((ulVoltsSum/2560)%10)];
        cDigit[3][0] = cSeg[(ulVoltsSum/256%10)];
        sCounterVSum = 0;       
    }

Нужно поменять на что-то такое:
Код:
        unsigned int u;
.....
       ulVoltsSum += ADCW;
.....
        u=(5000UL*ulVoltsSum)/1024/256;
        i=4;
        while (i>0) {
           cDigit[i][0] = ~cSeg[u%10];
           u /=10;
           i--;
        }

Зачем нужно стадо длинных делений, когда их можно заменить на 16-ти битные?
Не знаю, как в CV, а в GCC-AVR код из моего первого поста:
Код:
Device: attiny13a

Program:     812 bytes (79.3% Full)
(.text + .data + .bootloader)

Data:         36 bytes (56.3% Full)
(.data + .bss + .noinit)


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Помогите ужать програаму, немного не влезает в ATTiny13
СообщениеДобавлено: Ср окт 08, 2014 11:39:51 
Опытный кот
Аватар пользователя

Карма: 6
Рейтинг сообщений: 54
Зарегистрирован: Ср июн 11, 2014 09:43:13
Сообщений: 721
Откуда: США
Рейтинг сообщения: 2
Кстати, вынос деления на число за скобки в CV почему-то тоже увеличивало размер. А цикл - да, должно быть меньше

_________________
Fucking static initialization order fiasco


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Помогите ужать програаму, немного не влезает в ATTiny13
СообщениеДобавлено: Ср окт 08, 2014 11:49:14 
Мучитель микросхем

Карма: 8
Рейтинг сообщений: 101
Зарегистрирован: Чт ноя 13, 2008 16:33:42
Сообщений: 410
Рейтинг сообщения: 2
Pink-Pank Почему увеличило, вопрос понятный, но для меньшего "разуточнения" результата здесь важно соблюсти последовательность операций, т.е. сначала таки нужно умножить.
Ведь толковый компилятор что должен сделать? Правильно, на этапе компиляции посчитать, что 5000/1024 = 4. Но мы ведь хотим умножить не на 4, а на 4.88. Не знаю, так ли поступил CV. (GCC так не делает, но ведь в дальнейшем могут допилить).
Уменьшение же размера кода произошло главным образом не из-за цикла. Важнее переход к 16-ти битным операциям.


Вернуться наверх
 
Показать сообщения за:  Сортировать по:  Вернуться наверх
Начать новую тему Ответить на тему  [ Сообщений: 87 ]  1, , , ,  

Часовой пояс: UTC + 3 часа


Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 7


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB
Extended by Karma MOD © 2007—2012 m157y
Extended by Topic Tags MOD © 2012 m157y