Посмотрите код на предмет оптимизации. (вывод на семисегментные индикаторы) - C (СИ)
Формулировка задачи:
/* * 7Segment.c * * Created: 10.09.2016 14:51:07 * Author : igora */ #define F_CPU 8000000 #include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> //Вектор прерывания по таймеру ISR( TIMER2_COMP_vect ) { //Выводим вольтаж PrintLedVolt(); } //Разряды вольт volatile int RV1 = 0; volatile int RV2 = 0; volatile int RV3 = 0; volatile int RV4 = 0; // точка вольт volatile int Vdot = 0; //Разряды ампер volatile int RA1 = 0; volatile int RA2 = 0; volatile int RA3 = 0; volatile int RA4 = 0; // точка ампер volatile int Adot = 0; //Цифры без точки 16чная система const unsigned char digits[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //Время перехода const int perehod = 3; //Задаем начальные установки void preset(){ TIMSK = (1<<OCIE2); // timer2: Режим перехода по совпадению включен TCCR2 = (1<<WGM21); // Устанавливаем режим перехода в прерывание по совпадению TCCR2|= (1<<CS22) |(1<<CS21)| (1<<CS20); // делитель основной частоты 1/1024 OCR2 = 128; //Число при котором уходит в вектор прерывания sei(); // выставляем бит общего разрешения прерываний //ADCSRA ADCSRA |= (1<<ADEN) //Включаем АЦП |(1<<ADPS2)|(1<<ADPS1); //Делитель на 64 //ADMUX ADMUX |= (1<<REFS0) | (1<<REFS0); //Опорное напряжение DDRD = 0xFF; PORTD = 0x00; // ноги для управления катодами семисегментными индикаторами DDRC |=(1<<5) | (1<<4) | (1<<3) | (1<<2) | (1<<1); DDRB |=(1<<2) | (1<<1) | (1<<0); } //Функция расчета напряжения float ReadADC(){ ADMUX |= (0<<MUX3)|(0<<MUX2)|(0<<MUX1)|(0<<MUX0); //Строка только для понятия, какая нога зайдействована как АЦП _delay_us(10); float Vtmp = 0; //Вычисляем средне арифметическое для значения ADC (50 проходов) for(int i = 0; i<50; i++){ ADCSRA |= (1<<ADSC); // Начало преобразования while(ADCSRA &(1<<ADSC)); // Ждем конец преобразования Vtmp += ADC; } return Vtmp/50; } //Функция разбиения дробного числа на разряды для вольт void PutRazryadVolt( double volt){ int y = volt; double z = volt-y; if(y>9){ RV1 = y/10; RV2 = y%10; int RD = z*100; Vdot=2; RV3 = RD/10; RV4 = RD%10; } else if(y<10 && y>=1){ RV1 = y; Vdot = 1; int RD = z*1000; RV2 = RD/100; RD = RD-(100*RV2); RV3 = RD/10; RV4 = RD%10; } else{ RV1 = 0; Vdot = 1; int RD = z*1000; RV2 = RD/100; RD = RD-(100*RV2); RV3 = RD/10; RV4 = RD%10; } } //Функция разбиения дробного числа на разряды для ампер void PutRazryadAmp( double amp){ int y = amp; double z = amp-y; if(y>9){ RA1 = y/10; RA2 = y%10; int RD = z*100; Adot=2; RA3 = RD/10; RA4 = RD%10; } else if(y<10 && y>1){ RA1 = y; Adot = 1; int RD = z*1000; RA2 = RD/100; RD = RD-(100*RA2); RA3 = RD/10; RA4 = RD%10; } else{ RA1 = 0; Adot = 1; int RD = z*1000; RA2 = RD/100; RD = RD-(100*RA2); RA3 = RD/10; RA4 = RD%10; } } //Display 1 //PORTC От 2 ноги до 5 //Display 2 //PORTC 1 нога PORTB 0-2 нога //Функция вывода дробного числа на семисегментный индикатор для вольт void PrintLedVolt(){ if (Vdot == 2){ PORTD=0x00; //display 1 PORTC =(1<<2); PORTD = digits[RV1]; _delay_ms(perehod); PORTC = (1<<3); PORTD = digits[RV2]; PORTD |= (1<<7); //Добавляем точку к разряду _delay_ms(perehod); PORTC = (1<<4); PORTD = digits[RV3]; _delay_ms(perehod); PORTC = (1<<5); PORTD = digits[RV4]; _delay_ms(1);// Задержка меньше основной, для того, чтобы выровнять яркость разрядов } else{ //display 1 PORTD=0x00; PORTC =(1<<2); PORTD = digits[RV1]; PORTD |= (1<<7); //Добавляем точку к разряду _delay_ms(perehod); PORTC = (1<<3); PORTD = digits[RV2]; _delay_ms(perehod); PORTC = (1<<4); PORTD = digits[RV3]; _delay_ms(perehod); PORTC = (1<<5); PORTD = digits[RV4]; _delay_ms(1);// Задержка меньше основной, для того, чтобы выровнять яркость разрядов } } //Функция вывода дробного числа на семисегментный индикатор для ампер void PrintLedAmp(){ if (Adot == 2){ //display 2 PORTC =(1<<1); PORTD = digits[RA1]; _delay_ms(perehod); PORTC &=~0xFF; PORTB = (1<<0); PORTD = digits[RA2]; PORTD |= (1<<7); //Добавляем точку к разряду _delay_ms(perehod); PORTB = (1<<1); PORTD = digits[RA3]; _delay_ms(perehod); PORTB = (1<<2); PORTD = digits[RA4]; _delay_ms(perehod); PORTB &=~0xFF; } else{ //display 2 PORTC =(1<<1); PORTD = digits[RA1]; PORTD |= (1<<7); //Добавляем точку к разряду _delay_ms(perehod); PORTC &=~0xFF; PORTB = (1<<0); PORTD = digits[RA2]; _delay_ms(perehod); PORTB = (1<<1); PORTD = digits[RA3]; _delay_ms(perehod); PORTB = (1<<2); PORTD = digits[RA4]; _delay_ms(perehod); PORTB &=~0xFF; } } int main(void) { preset(); // Запускаем функцию, задающую начальные параметры while (1) { //2.56/1023 чтобы узнать цену деления, умножаем на ReadADC (количество делений), и умножаем на коэффицент делителя //53.76/2.56, чтобы узнать вольтаж PutRazryadVolt(2.49/1024*ReadADC()*(52.29/2.49)); } }
Решение задачи: «Посмотрите код на предмет оптимизации. (вывод на семисегментные индикаторы)»
textual
Листинг программы
ADMUX |= (0<<MUX3)|(0<<MUX2)|(0<<MUX1)|(0<<MUX0); //Строка только для понятия, какая нога зайдействована как АЦП
Объяснение кода листинга программы
- Переменная
ADMUX
- это регистр, который используется для выбора источника аналогового сигнала для АЦП. 0<<MUX3
- это способ выбора определенной ноги для АЦП. В данном случае, это означает, что мы выбираем ногу с номером 0 для использования в качестве аналогового входа.0<<MUX2
- это еще один способ выбора ноги для АЦП. В данном случае, это означает, что мы выбираем ногу с номером 0 для использования в качестве аналогового входа.0<<MUX1
- это еще один способ выбора ноги для АЦП. В данном случае, это означает, что мы выбираем ногу с номером 0 для использования в качестве аналогового входа.0<<MUX0
- это последний способ выбора ноги для АЦП. В данном случае, это означает, что мы выбираем ногу с номером 0 для использования в качестве аналогового входа.- Весь код вместе устанавливает
ADMUX
так, чтобы он использовал ногу с номером 0 в качестве аналогового входа для АЦП.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д