Помогите ужать программу АмперВольтметра на 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)
{
}
}


