Страница 1 из 1
Как оптимизировать разбитие 16бит-числа на составляющие ?
Добавлено: Пт май 25, 2018 04:27:34
7seg
Есть функция
Код: Выделить всё
PrintNumber(uint16_t NeberChar,uint8_t NumberTimers)
функция принимает число NeberChar (которое может быть от 0 до 60 000), это число надо вывести на индикатор.
Функция справляется на ура конечно со своим делом, но
почему то мне кажется что деление в лоб не лучшая идея по скорости выполнения.
Код: Выделить всё
data1=NeberChar%10;
data2=(NeberChar%100)/10;
data3=(NeberChar%1000)/100;
data4=(NeberChar%10000)/1000;
data5=(NeberChar/10000);
Мб есть у кого какие идеи ?
//Функция вывода динамической индикации.
Код: Выделить всё
void PrintNumber(uint16_t NeberChar,uint8_t NumberTimers)
{
/***Разбитие числа на разряды***/
/*data1->младший,data5->Старший,data6 отдельный разряд*/
data1=NeberChar%10;
data2=(NeberChar%100)/10;
data3=(NeberChar%1000)/100;
data4=(NeberChar%10000)/1000;
data5=(NeberChar/10000);
data6=NumberTimers; //1..4
AnodCount++;
switch (AnodCount)
{
case 1:
ANOD1=0;ANOD2=1;ANOD3=1;ANOD4=1;ANOD5=1;ANOD6=1;
PrintChar(data1);
break;
case 2:
if (((data2+data3+data4+data5)!=0)|| (ModTimer == 0)) //если сумма старших раааазрядов !=0 то выводим разряд иначе гасим.
{
ANOD1=1;ANOD2=0;ANOD3=1;ANOD4=1;ANOD5=1;ANOD6=1;
PrintChar(data2);
} else PrintChar(99); //гасим разряд.
break;
case 3:
if (((data3+data4+data5)!=0)|| (ModTimer == 0)) //если сумма старших раааазрядов !=0 то выводим разряд иначе гасим.
{
ANOD1=1;ANOD2=1;ANOD3=0;ANOD4=1;ANOD5=1;ANOD6=1;
PrintChar(data3);
} else PrintChar(99); //гасим разряд.
break;
case 4:
if ((data4+data5)!=0) //если сумма старших раааазрядов !=0 то выводим разряд иначе гасим.
{
ANOD1=1;ANOD2=1;ANOD3=1;ANOD4=0;ANOD5=1;ANOD6=1;
PrintChar(data4);
} else PrintChar(99); //гасим разряд.
break;
case 5:
if (data5!=0) //если сумма старших раааазрядов !=0 то выводим разряд иначе гасим.
{
ANOD1=1;ANOD2=1;ANOD3=1;ANOD4=1;ANOD5=0;ANOD6=1;
PrintChar(data5);
} else PrintChar(99); //гасим разряд.
break;
case 6:
if (data6!=0) //если сумма раааазряда !=0 то выводим разряд иначе гасим.
{
ANOD1=1;ANOD2=1;ANOD3=1;ANOD4=1;ANOD5=1;ANOD6=0;
PrintChar(data6);
} else PrintChar(99); //гасим разряд.
AnodCount=0;
break;
}
}
Re: Как оптимизировать разбитие 16бит-числа на составляющие
Добавлено: Пт май 25, 2018 06:26:51
Z_h_e
Возможно будет иметь смысл применить двоично десятичный формат числа. Тогда для динамической индикации ничего преобразовывать не надо будет.
Re: Как оптимизировать разбитие 16бит-числа на составляющие
Добавлено: Пт май 25, 2018 07:20:53
7seg
Z_h_e, Если можно привести пример буду благодарен ).
сейчас индикация выводиться через 595 регистр по spi
Код: Выделить всё
/Функция вывода символов
static void PrintChar (uint8_t Number)
{
switch (Number)
{
case 0:
SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(0<<SEGE)|(0<<SEGF)|(1<<SEGG)|(1<<SEGH);break;
case 1:
SEG_PORT=(1<<SEGA)|(0<<SEGB)|(0<<SEGC)|(1<<SEGD)|(1<<SEGE)|(1<<SEGF)|(1<<SEGG)|(1<<SEGH);break;
case 2:
SEG_PORT=(0<<SEGA)|(0<<SEGB)|(1<<SEGC)|(0<<SEGD)|(0<<SEGE)|(1<<SEGF)|(0<<SEGG)|(1<<SEGH);break;
case 3:
SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(1<<SEGE)|(1<<SEGF)|(0<<SEGG)|(1<<SEGH);break;
case 4:
SEG_PORT=(1<<SEGA)|(0<<SEGB)|(0<<SEGC)|(1<<SEGD)|(1<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break;
case 5:
SEG_PORT=(0<<SEGA)|(1<<SEGB)|(0<<SEGC)|(0<<SEGD)|(1<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break;
case 6:
SEG_PORT=(0<<SEGA)|(1<<SEGB)|(0<<SEGC)|(0<<SEGD)|(0<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break;
case 7:
SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(1<<SEGD)|(1<<SEGE)|(1<<SEGF)|(1<<SEGG)|(1<<SEGH);break;
case 8:
SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(0<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break;
case 9:
SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(1<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break;
case 99: //OFF Все сегменты
SEG_PORT=(1<<SEGA)|(1<<SEGB)|(1<<SEGC)|(1<<SEGD)|(1<<SEGE)|(1<<SEGF)|(1<<SEGG)|(1<<SEGH);break;
}
if ((ModTimer == 0)&&(AnodCount == 3))
{
SEG_PORT &=~(1<<SEGH);
}
}
//Функция вывода динамической индикации.
void PrintNumber(uint16_t NeberChar,uint8_t NumberTimers)
{
/***Разбитие числа на разряды***/
/*data1->младший,data5->Старший,data6 отдельный разряд*/
uint8_t data1=NeberChar%10;
uint8_t data2=(NeberChar%100)/10;
uint8_t data3=(NeberChar%1000)/100;
uint8_t data4=(NeberChar%10000)/1000;
uint8_t data5=(NeberChar/10000);
uint8_t data6=NumberTimers; //1..4
AnodCount++;
switch (AnodCount)
{
case 1:
ANOD1=0;ANOD2=1;ANOD3=1;ANOD4=1;ANOD5=1;ANOD6=1;
PrintChar(data1);
break;
case 2:
if (((data2+data3+data4+data5)!=0)|| (ModTimer == 0)) //если сумма старших раааазрядов !=0 то выводим разряд иначе гасим.
{
ANOD1=1;ANOD2=0;ANOD3=1;ANOD4=1;ANOD5=1;ANOD6=1;
PrintChar(data2);
} else PrintChar(99); //гасим разряд.
break;
case 3:
if (((data3+data4+data5)!=0)|| (ModTimer == 0)) //если сумма старших раааазрядов !=0 то выводим разряд иначе гасим.
{
ANOD1=1;ANOD2=1;ANOD3=0;ANOD4=1;ANOD5=1;ANOD6=1;
PrintChar(data3);
} else PrintChar(99); //гасим разряд.
break;
case 4:
if ((data4+data5)!=0) //если сумма старших раааазрядов !=0 то выводим разряд иначе гасим.
{
ANOD1=1;ANOD2=1;ANOD3=1;ANOD4=0;ANOD5=1;ANOD6=1;
PrintChar(data4);
} else PrintChar(99); //гасим разряд.
break;
case 5:
if (data5!=0) //если сумма старших раааазрядов !=0 то выводим разряд иначе гасим.
{
ANOD1=1;ANOD2=1;ANOD3=1;ANOD4=1;ANOD5=0;ANOD6=1;
PrintChar(data5);
} else PrintChar(99); //гасим разряд.
break;
case 6:
if (data6!=0) //если сумма раааазряда !=0 то выводим разряд иначе гасим.
{
ANOD1=1;ANOD2=1;ANOD3=1;ANOD4=1;ANOD5=1;ANOD6=0;
PrintChar(data6);
} else PrintChar(99); //гасим разряд.
AnodCount=0;
break;
}
}
Re: Как оптимизировать разбитие 16бит-числа на составляющие
Добавлено: Пт май 25, 2018 07:34:06
Engineer_Keen
Можно по очереди отнимать от NeberChar сначала по 10 000, и количество возможных вычитаний (т.е. пока результат остается>0) записать в data1, потом начать отнимать по 1000, результат соответственно в data2, потом соответственно 100 и 10, остаток сохраняется в data5. Я так всегда вывожу результат. В худшем случае получите чуть более 200 тактов на все вычисление (максимум вычитаний для числа типа "59999"), в лучшем около 40 (если "0"). Думаю это немного быстрее чем "4 остатка от деления+4 обычных деления" 16-разрядного числа.
Спойлер
Код: Выделить всё
//код на асме для общего пониманию принципа, си не люблю
HEXTODEC10000:
//YH:YL - число для преобразования
//data1-data5 - результат
.def data1=R16
.def data2=R17
.def data3=R18
.def data4=R19
.def data5=R10
CLR data1 //очищаем результат
CLR data2
CLR data3
CLR data4
LDW ZH,ZL,10000 //грузим константу для вычитания 10 000
S10000: SUB YL,ZL //вычитаем
SBC YH,ZH
BRCS X1000 //проверяем остаток (>0 - прокатило)
INC data1 //прокатило, увеличиваем десятки тысяч
RJMP S10000 //продолжаем вычитать
X1000: ADD YL,ZL //непрокатило, возвращаем 10 000
ADC YH,ZH
LDW ZH,ZL,1000 //переходим на тысячи
S1000: SUB YL,ZL
SBC YH,ZH
BRCS X100
INC data2
RJMP S1000
X100: ADD YL,ZL
ADC YH,ZH
LDW ZH,ZL,100 //теперь сотни
S100: SUB YL,ZL
SBC YH,ZH
BRCS X10
INC data3
RJMP S100
X10: ADD YL,ZL
ADC YH,ZH
S10: SUBI YL,10 //десятки
BRCS X1
INC data4
RJMP S10
X1: SUBI YL,-10
MOV data5,YL //остаток копируем напрямую
RET
Re: Как оптимизировать разбитие 16бит-числа на составляющие
Добавлено: Пт май 25, 2018 07:42:02
ARV
ваш код, 7seg, - лютый трэш.
вы хоть почитайте о том, как организуется преобразование чисел в символьное представление, как организуется динамическая (и не динамическая) индикация на 7-сегментниках... как вообще пишутся программы - про циклы, например, дефайны и т.п.
вопрос у вас настолько примитивный, что просто удивительно, как вы его еще задать смогли - я даже про гугление не говорю, здесь, на радиокоте статей и сообщений на форуме - просто жри не лопни!
ну как же вы так-то, а?
Re: Как оптимизировать разбитие 16бит-числа на составляющие
Добавлено: Пт май 25, 2018 08:24:20
7seg
ARV, естественно все задефайнено.
Дефайны и листинг под спойлером.
Спойлер
Код: Выделить всё
#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
/*_________________BEGIN_TARGET_DEFINE______*/
#define ENABLE_TIM1 TIMSK|= (1<<2)
#define DISABLE_TIM1 TIMSK&= ~(1<<2)
#define ENABLE_SM PORTC|= (1<<1)
#define DISABLE_SM PORTC&= ~(1<<1)
#define ENABLE_SB PORTC|= (1<<2)
#define DISABLE_SB PORTC&= ~(1<<2)
#define ENABLE_PW PORTC|= (1<<3)
#define DISABLE_PW PORTC&= ~(1<<3)
#define ENABLE_OW PORTC|= (1<<4)
#define DISABLE_OW PORTC&= ~(1<<4)
/******************Описание DEFINE SPI**********************/
#define SPI_PORT PORTB
#define SPI_DDR DDRB
#define SPI_MISO 6
#define SPI_MOSI 5
#define SPI_SCK 7
#define SPI_SS 4
/*********Кодировка семи сегментного индикатора.*************/
//________________________*/
#define SEG_PORT TwoOUT.ByteRegister
//__________________Катоды____________________*/
#define SEGA 0
#define SEGB 1
#define SEGC 2
#define SEGD 3
#define SEGE 4
#define SEGF 5
#define SEGG 6
#define SEGH 7
//__________________Аноды_____________________*/
#define ANOD1 OneOUT.Register.DO0
#define ANOD2 OneOUT.Register.DO1
#define ANOD3 OneOUT.Register.DO2
#define ANOD4 OneOUT.Register.DO3
#define ANOD5 OneOUT.Register.DO4
#define ANOD6 OneOUT.Register.DO5
#define DISPLAY_MOD_TIM OneOUT.Register.DO6
#define DISPLAY_MOD_JOB OneOUT.Register.DO7
/*****************SETING_DEFINE_BTN_AND_GRC*****************/
#define BTN_LOCK_TIME 20 //время фиксации дребезга
#define BTN_LONG_TIME 1000 //время фиксации длинного нажатия
//**__________________порт чтения кнопок___________________*/
#define BTN_PORT1 PORTA
#define BTN_DDR1 DDRA
#define BTN_PIN1 PINA
#define BTN_PORT2 PORTD
#define BTN_DDR2 DDRD
#define BTN_PIN2 PIND
#define BTN_PORT3 PORTC
#define BTN_DDR3 DDRC
#define BTN_PIN3 PINC
//**________________пины чтения кнопок___________________**/
//________PORTA_____________*/
#define BTN_LINE_RA (1<<0) //Режим РУЧ/АВТ (PA)
#define BTN_LINE_ST (1<<1) //Режим СЧЕТЧИК/ТАЙМЕР
#define BTN_LINE_PR (1<<2) //MOD PROGRAMMING
#define BTN_LINE_EN (1<<3) //BTN_ENTER
#define BTN_LINE_UP (1<<4) //BTN_UP
#define BTN_LINE_DN (1<<5) //BTN_DOWN
#define BTN_LINE_SM (1<<6) //BTN_SW_СМЫКАНИЕ
#define BTN_LINE_SB (1<<7) //BTN_SW_ШТОК_БАРЫ
//________PORTD_____________*/
#define BTN_LINE_S1 (1<<0) //BTN_START_1 (PD)
#define BTN_LINE_S2 (1<<1) //BTN_START_2
#define GRK_LINE_SM (1<<2) //ГЕРКОН_СМЫКАНИЕ
#define BTN_LINE_PW (1<<3) //BTN_ПРЕД_ВЫДУВ
#define BTN_LINE_OW (1<<4) //BTN_ОСНОВНОЙ_ВЫДУВ
#define GRK_LINE_ZM_IP (1<<5) //ГЕРКОН_ЗАМОК_ИСХ.ПОЛОЖЕНИЕ
#define GRK_LINE_ZM_RP (1<<6) //ГЕРКОН_ЗАМОК_РАБ.ПОЛОЖЕНИЕ
#define BTN_LINE_ZM (1<<7) //BTN_SWITCH_ЗАМОК
//________PORTC_____________*/
#define DAT_LINE_PWR (1<<6) //ДАТЧИК_PWR (PC)
#define BTN_LINE_MOD (1<<7) //BTN_MOD_ZM/NO_ZM
//_______Биты короткого нажатия -> BtnFlags_1_____________*/
#define BTN_SHRT_RA (1<<0) //Режим РУЧ/АВТ
#define BTN_SHRT_ST (1<<1) //Режим СЧЕТЧИК/ТАЙМЕР
#define BTN_SHRT_PR (1<<2) //MOD PROGRAMMING
#define BTN_SHRT_EN (1<<3) //BTN_ENTER
#define BTN_SHRT_UP (1<<4) //BTN_UP
#define BTN_SHRT_DN (1<<5) //BTN_DOWN
#define BTN_SHRT_SM (1<<6) //BTN_SW_СМЫКАНИЕ
#define BTN_SHRT_SB (1<<7) //BTN_SW_ШТОК_БАРЫ
//_______Биты короткого нажатия -> BtnFlags_2______________*/
#define BTN_SHRT_S1 (1<<0) //BTN_START_1
#define BTN_SHRT_S2 (1<<1) //BTN_START_2
#define GRK_SHRT_SM (1<<2) //ГЕРКОН_СМЫКАНИЕ
#define BTN_SHRT_PW (1<<3) //BTN_ПРЕД_ВЫДУВ
#define BTN_SHRT_OW (1<<4) //BTN_ОСНОВНОЙ_ВЫДУВ
#define GRK_SHRT_ZM_IP (1<<5) //ГЕРКОН_ЗАМОК_ИСХ.ПОЛОЖЕНИЕ
#define GRK_SHRT_ZM_RP (1<<6) //ГЕРКОН_ЗАМОК_РАБ.ПОЛОЖЕНИЕ
#define BTN_SHRT_ZM (1<<7) //BTN_SWITCH_ЗАМОК
//_______Биты короткого нажатия -> BtnFlags_3______________*/
#define DAT_SHRT_PWR (1<<0) //ДАТЧИК_PWR
#define BTN_SHRT_MOD (1<<1) //BTN_MOD_ZM/NO_ZM
//_______Биты длинного нажатия -> BtnFlags_3_______________*/
#define BTN_LONG_UP (1<<12) //BTN_UP_LONG
#define BTN_LONG_DN (1<<13) //BTN_DOWN_LONG
/*_________________END_TARGET_DEFINE________*/
/***********************************************************/
/***********************************************************/
//________________(глобальные переменные)___________________*/
volatile uint16_t BtnFlags_1=0;
volatile uint16_t BtnFlags_2=0;
volatile uint16_t BtnFlags_3=0;
volatile uint8_t AnodCount=0; //Счетчик Анодов Сем.Сег.Идникатора.
volatile uint8_t ModTimer = 0; //Режим работы таймера.
volatile uint16_t CountMS=0; //Переменная счетчик MS
volatile uint8_t FlagsEnDiplay=0; //Флаг для работы с Сем.Сег.Идникатором.
volatile uint8_t ModDebug=0xFF; //Ручной режим работы (отладка)(включен по дефолту)
volatile uint8_t ModAuto=0x00; //Автоматический режим работы
void InitTimer0_OVF()
{
TCNT0|=217; //Прерывания настроено на 1.25ms
TIMSK|=(1<<TOIE0);//Разрешить прерывание по переполнению таймера 0.
TCCR0|=(1<<CS02)|(0<<CS01)|(1<<CS00); //Настройка пред делителя. 100 .clk\256
}
void InitTimer1_OVF()
{
TCCR1B|=(1<<CS12)|(0<<CS11)|(0<<CS10); //Пред делитель
TIMSK|=(1<<TOIE1); //Разрешить прерывание по переполнению таймера 1
//TCNT1=65521;
TCNT1=65505 ; //Начальное значение таймера
}
void SPI_Init(void)
{
/*настройка портов ввода-вывода все выводы, кроме MISO выходы*/
SPI_DDR |= (1<<SPI_MOSI)|(1<<SPI_SCK)|(1<<SPI_SS)|(0<<SPI_MISO);
SPI_PORT |= (1<<SPI_MOSI)|(1<<SPI_SCK)|(1<<SPI_SS)|(1<<SPI_MISO);
SPCR = (1<<SPE)|(0<<DORD)|(1<<MSTR)|(0<<CPOL)|(0<<CPHA)|(0<<SPR1)|(0<<SPR0);
SPSR = (0<<SPI2X);
}
//--------------------------------------------------------------------------------------------------------------------
//Функции чтения данных о нажатии кнопок
uint16_t MaskGetOne (void)
{
cli();
uint16_t temp1 = BtnFlags_1;
BtnFlags_1 = 0;
sei();
return temp1;
}
uint16_t MaskGetTwo (void)
{
cli();
uint16_t temp2 = BtnFlags_2;
BtnFlags_2 = 0;
sei();
return temp2;
}
uint16_t MaskGetThree (void)
{
cli();
uint16_t temp3 = BtnFlags_3;
BtnFlags_3 = 0;
sei();
return temp3;
}
//-----------------------------------------------------------------------------------------------------------------------
//ФУНКЦИЯ ОБРАБОТКИ НАЖАТИЙ КЛАВИШ (вызывать в прерывании)
//короткое нажатие устанавливает бит BTN_SHRT_X глобальной переменной BtnFlags
//длинное нажатие устанавливает бит BTN_LONG_X глобальной переменной BtnFlags
void BtnExe (void)
{
static uint8_t BtnLockBit; //защелка (защита от дребезга)
static uint8_t BtnLockCoun; //счетчик защелки (защита от дребезга)
static uint8_t BtnLongCoun; //счетчик длинного нажатия
static uint8_t BtnLastState_1; //последнее состояние кнопок перед отпусканием
static uint8_t BtnLastState_2; //последнее состояние кнопок перед отпусканием
static uint8_t BtnLastState_3; //последнее состояние кнопок перед отпусканием
uint8_t mask_1 = 0;
uint8_t mask_2 = 0;
uint8_t mask_3 = 0;
if (!(BTN_PIN1 & BTN_LINE_RA)) mask_1 = BTN_SHRT_RA;
if (!(BTN_PIN1 & BTN_LINE_ST)) mask_1 = BTN_SHRT_ST;
if (!(BTN_PIN1 & BTN_LINE_PR)) mask_1 = BTN_SHRT_PR;
if (!(BTN_PIN1 & BTN_LINE_EN)) mask_1 = BTN_SHRT_EN;
if (!(BTN_PIN1 & BTN_LINE_UP)) mask_1 = BTN_SHRT_UP;
if (!(BTN_PIN1 & BTN_LINE_DN)) mask_1 = BTN_SHRT_DN;
if (!(BTN_PIN1 & BTN_LINE_SM)) mask_1 = BTN_SHRT_SM;
if (!(BTN_PIN1 & BTN_LINE_SB)) mask_1 = BTN_SHRT_SB;
if(!(BTN_PIN2 & BTN_LINE_S1)) mask_2 = BTN_SHRT_S1;
if(!(BTN_PIN2 & BTN_LINE_S2)) mask_2 = BTN_SHRT_S2;
if(!(BTN_PIN2 & GRK_LINE_SM)) mask_2 = GRK_SHRT_SM;
if(!(BTN_PIN2 & BTN_LINE_PW)) mask_2 = BTN_SHRT_PW;
if(!(BTN_PIN2 & BTN_LINE_OW)) mask_2 = BTN_SHRT_OW;
if(!(BTN_PIN2 & GRK_LINE_ZM_IP)) mask_2 = GRK_SHRT_ZM_IP;
if(!(BTN_PIN2 & GRK_LINE_ZM_RP)) mask_2 = GRK_SHRT_ZM_RP;
if(!(BTN_PIN2 & BTN_LINE_ZM)) mask_2 = BTN_SHRT_ZM;
if(!(BTN_PIN3 & DAT_LINE_PWR)) mask_3 = DAT_SHRT_PWR;
if(!(BTN_PIN3 & BTN_LINE_MOD)) mask_3 = BTN_SHRT_MOD;
if((mask_1)||(mask_2)||(mask_3)) //опрос состояния кнопки
{
if (BtnLockCoun < (BTN_LOCK_TIME/10)) //клавиша нажата
{
BtnLockCoun++;
return; //защелка еще не досчитала - возврат
}
BtnLastState_1 = mask_1;
BtnLastState_2 = mask_2;
BtnLastState_3 = mask_3;
BtnLockBit =1; //нажатие зафиксировано
if (BtnLongCoun >= (BTN_LONG_TIME/10))
{
return; //возврат, т.к. счетчик длин.нажат. досчитал до максимума еще раньше
}
if (++BtnLongCoun >= (BTN_LONG_TIME/10))
{
if (mask_1)
{
BtnFlags_1|= (BtnLastState_1<<8); //счетчик досчитал до максимума - устанавливаем биты длинного нажатия
}
if (mask_2)
{
BtnFlags_2 |= (BtnLastState_2<<8);
}
if (mask_3)
{
BtnFlags_3 |= (BtnLastState_3<<8);
}
}
}
else //клавиша отжата
{
if (BtnLockCoun)
{
BtnLockCoun --;
return; //защелка еще не обнулилась - возврат
}
if (! BtnLockBit) return; //СТАТИЧЕСКИЙ ВОЗВРАТ
BtnLockBit =0; //отжатие зафиксировано
if (BtnLongCoun < (BTN_LONG_TIME/10))
{
if(!(mask_1))
{
BtnFlags_1 |= BtnLastState_1;
} //установка бита короткого нажатия
if (!(mask_2))
{
BtnFlags_2 |= BtnLastState_2;
}
if (!(mask_3))
{
BtnFlags_3 |= BtnLastState_3;
}
}
BtnLongCoun = 0; //сброс счетчика длительности нажатия
}
}
struct UnionBits
{
unsigned DO0: 1;
unsigned DO1: 1;
unsigned DO2: 1;
unsigned DO3: 1;
unsigned DO4: 1;
unsigned DO5: 1;
unsigned DO6: 1;
unsigned DO7: 1;
};
union Byte {
uint8_t ByteRegister;
struct UnionBits Register;
};
union Byte OneOUT; //аноды
union Byte TwoOUT; //Катоды
uint8_t SPI_UpdataByte(uint8_t data)
{
uint8_t report;
SPDR = data;
while(!(SPSR & (1<<SPIF)));
report = SPDR;
return report;
}
void SpiUpdateRegister()
{
SPI_PORT &= ~(1<<SPI_SS);
SPI_UpdataByte(OneOUT.ByteRegister);
SPI_UpdataByte(TwoOUT.ByteRegister);
SPI_PORT |= (1<<SPI_SS);
}
void StartInitIO()
{
OneOUT.ByteRegister=0x00;
TwoOUT.ByteRegister=0x00;
}
//Функция вывода символов
static void PrintChar (uint8_t Number)
{
switch (Number)
{
case 0:
SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(0<<SEGE)|(0<<SEGF)|(1<<SEGG)|(1<<SEGH);break;
case 1:
SEG_PORT=(1<<SEGA)|(0<<SEGB)|(0<<SEGC)|(1<<SEGD)|(1<<SEGE)|(1<<SEGF)|(1<<SEGG)|(1<<SEGH);break;
case 2:
SEG_PORT=(0<<SEGA)|(0<<SEGB)|(1<<SEGC)|(0<<SEGD)|(0<<SEGE)|(1<<SEGF)|(0<<SEGG)|(1<<SEGH);break;
case 3:
SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(1<<SEGE)|(1<<SEGF)|(0<<SEGG)|(1<<SEGH);break;
case 4:
SEG_PORT=(1<<SEGA)|(0<<SEGB)|(0<<SEGC)|(1<<SEGD)|(1<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break;
case 5:
SEG_PORT=(0<<SEGA)|(1<<SEGB)|(0<<SEGC)|(0<<SEGD)|(1<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break;
case 6:
SEG_PORT=(0<<SEGA)|(1<<SEGB)|(0<<SEGC)|(0<<SEGD)|(0<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break;
case 7:
SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(1<<SEGD)|(1<<SEGE)|(1<<SEGF)|(1<<SEGG)|(1<<SEGH);break;
case 8:
SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(0<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break;
case 9:
SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(1<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break;
case 99: //OFF Все сегменты
SEG_PORT=(1<<SEGA)|(1<<SEGB)|(1<<SEGC)|(1<<SEGD)|(1<<SEGE)|(1<<SEGF)|(1<<SEGG)|(1<<SEGH);break;
}
if ((ModTimer == 0)&&(AnodCount == 3))
{
SEG_PORT &=~(1<<SEGH);
}
}
//Функция вывода динамической индикации.
void PrintNumber(uint16_t NeberChar,uint8_t NumberTimers)
{
/***Разбитие числа на разряды***/
/*data1->младший,data5->Старший,data6 отдельный разряд*/
uint8_t data1=NeberChar%10;
uint8_t data2=(NeberChar%100)/10;
uint8_t data3=(NeberChar%1000)/100;
uint8_t data4=(NeberChar%10000)/1000;
uint8_t data5=(NeberChar/10000);
uint8_t data6=NumberTimers; //1..4
AnodCount++;
switch (AnodCount)
{
case 1:
ANOD1=0;ANOD2=1;ANOD3=1;ANOD4=1;ANOD5=1;ANOD6=1;
PrintChar(data1);
break;
case 2:
if (((data2+data3+data4+data5)!=0)|| (ModTimer == 0)) //если сумма старших раааазрядов !=0 то выводим разряд иначе гасим.
{
ANOD1=1;ANOD2=0;ANOD3=1;ANOD4=1;ANOD5=1;ANOD6=1;
PrintChar(data2);
} else PrintChar(99); //гасим разряд.
break;
case 3:
if (((data3+data4+data5)!=0)|| (ModTimer == 0)) //если сумма старших раааазрядов !=0 то выводим разряд иначе гасим.
{
ANOD1=1;ANOD2=1;ANOD3=0;ANOD4=1;ANOD5=1;ANOD6=1;
PrintChar(data3);
} else PrintChar(99); //гасим разряд.
break;
case 4:
if ((data4+data5)!=0) //если сумма старших раааазрядов !=0 то выводим разряд иначе гасим.
{
ANOD1=1;ANOD2=1;ANOD3=1;ANOD4=0;ANOD5=1;ANOD6=1;
PrintChar(data4);
} else PrintChar(99); //гасим разряд.
break;
case 5:
if (data5!=0) //если сумма старших раааазрядов !=0 то выводим разряд иначе гасим.
{
ANOD1=1;ANOD2=1;ANOD3=1;ANOD4=1;ANOD5=0;ANOD6=1;
PrintChar(data5);
} else PrintChar(99); //гасим разряд.
break;
case 6:
if (data6!=0) //если сумма раааазряда !=0 то выводим разряд иначе гасим.
{
ANOD1=1;ANOD2=1;ANOD3=1;ANOD4=1;ANOD5=1;ANOD6=0;
PrintChar(data6);
} else PrintChar(99); //гасим разряд.
AnodCount=0;
break;
}
}
void InitIO_MC(void)
{
DDRA|=0x00; // Config InPut
PORTA|=0x00;
DDRB|=0xFF; // Config OutPut
PORTB=0x00;
DDRC|=(0<<PC7)|(0<<PC6)|(1<<PC5)|(1<<PC4)|(1<<PC3)|(1<<PC2)|(1<<PC1)|(1<<PC0);
PORTC|=0x00;
DDRD|=0x00; // Config IntPut
PORTD|=0x00;
}
//uint8_t TempCount=0;
ISR (TIMER0_OVF_vect)
{
TCNT0|=217;
SpiUpdateRegister();
BtnExe();
FlagsEnDiplay=1;
}
ISR (TIMER1_OVF_vect)
{
TCNT1=65505;
CountMS++;
}
char temptest=0;
uint8_t FlagSM=0;
uint8_t FlagBtnSM=0;
uint8_t FlagSB=0;
uint8_t FlagBtnSB=0;
uint8_t FlagPW=0;
uint8_t FlagBtnPW=0;
uint8_t FlagOW=0;
uint8_t FlagBtnOW=0;
void InputMaskUpdate(uint16_t InputOne,uint16_t InputTwo,uint16_t InputThree)
{
switch(InputOne)
{
case BTN_SHRT_RA:
ModAuto=~ModAuto;
ModDebug=~ModDebug;
DISPLAY_MOD_JOB=ModAuto;
break;
case BTN_SHRT_ST:
ModTimer=~ModTimer;
DISPLAY_MOD_TIM=ModTimer;
break;
case BTN_SHRT_PR:
break;
case BTN_SHRT_EN:
break;
case BTN_SHRT_UP:temptest++;
break;
case BTN_SHRT_DN:temptest--;
break;
case BTN_LONG_UP:temptest+=10;
break;
case BTN_SHRT_SM:
FlagBtnSM=~FlagBtnSM;
break;
case BTN_SHRT_SB:
FlagBtnSB=~FlagBtnSB;
break;
case BTN_LONG_DN:temptest-=10;
break;
default:break;
}
switch(InputTwo)
{
case BTN_SHRT_S1:
break;
case BTN_SHRT_S2:
break;
case GRK_SHRT_SM:
break;
case BTN_SHRT_PW:
FlagBtnPW=~FlagBtnPW;
break;
case BTN_SHRT_OW:
FlagBtnOW=~FlagBtnOW;
break;
case GRK_SHRT_ZM_IP:
break;
case GRK_SHRT_ZM_RP:
break;
case BTN_SHRT_ZM:
break;
default:break;
}
switch(InputThree)
{
case DAT_LINE_PWR:
break;
case BTN_SHRT_MOD:
break;
default:break;
}
}
int main(void)
{
InitIO_MC(); //Иницилизация портов.
_delay_ms(999);
_delay_us(977);
SPI_Init();
StartInitIO();
SpiUpdateRegister();
InitTimer1_OVF();
InitTimer0_OVF();
volatile uint16_t InputMaskOne=0;
volatile uint16_t InputMaskTwo=0;
volatile uint16_t InputMaskThree=0;
sei();
while(1)
{
if (FlagsEnDiplay)
{
PrintNumber((CountMS/10),1);
FlagsEnDiplay=0;
}
InputMaskOne = MaskGetOne();
InputMaskTwo = MaskGetTwo();
InputMaskThree = MaskGetThree();
InputMaskUpdate(InputMaskOne,InputMaskTwo,InputMaskThree);
if (ModDebug)
{
if (FlagBtnSM)
{
ENABLE_SM;
} else DISABLE_SM;
if (FlagBtnSB)
{
ENABLE_SB;
} else DISABLE_SB;
if (FlagBtnPW)
{
while(!(PIND&BTN_LINE_PW))
{
ENABLE_PW;
}
}else DISABLE_PW;
if (FlagBtnOW)
{
ENABLE_OW;
}else if (PIND&BTN_LINE_OW) DISABLE_OW;
}
if (ModAuto)
{
}
}
return 0;
}
Re: Как оптимизировать разбитие 16бит-числа на составляющие
Добавлено: Пт май 25, 2018 08:43:51
ARV
7seg писал(а):Дефайны и листинг под спойлером
от увиденного я в своей оценке вашего кода возведу слово "трэш" в квадрат.
Re: Как оптимизировать разбитие 16бит-числа на составляющие
Добавлено: Пт май 25, 2018 08:48:02
Аlex
Деление на 10 с остатком в цикле - всё преобразование.
Добавлено after 1 minute 25 seconds:
Re: Как оптимизировать разбитие 16бит-числа на составляющие ?
от увиденного я в своей оценке вашего кода возведу слово "трэш" в квадрат.
ARV, да нормально там всё в коде. Что так сильно Вам не понравилось ?
Re: Как оптимизировать разбитие 16бит-числа на составляющие
Добавлено: Пт май 25, 2018 08:50:14
ARV
ну, если нормально, значит у меня болевой порог слишком низкий - у меня кровь из глаз едва не пошла.
Re: Как оптимизировать разбитие 16бит-числа на составляющие
Добавлено: Пт май 25, 2018 08:55:16
Аlex
Ну просто в куче всё, по этому так и смотрится. Если разбить всё по модулям - будет намного лучше

Re: Как оптимизировать разбитие 16бит-числа на составляющие
Добавлено: Пт май 25, 2018 09:10:37
ARV
да, если написать все, как следует - будет лучше.
Re: Как оптимизировать разбитие 16бит-числа на составляющие
Добавлено: Пт май 25, 2018 11:06:17
7seg
Если я понял вас правильно , то оптимальней будет завести массив
uint8_t data[5];
и заполнять его через цикл:
uint8_t TempResult =0;
for (int i = 0; i < 5; i++)
{
TempResult = NeberChar % 10;
NeberChar = NeberChar / 10;
data=TempResult;
}
где NeberChar значение в диапазоне 0..65534 , а data[0]..data[4] и есть искомые значения.
Re: Как оптимизировать разбитие 16бит-числа на составляющие
Добавлено: Пт май 25, 2018 11:29:41
ARV
и завести массив "символов", куда поместить все ваши ужасные (0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(0<<SEGE)|(0<<SEGF)|(1<<SEGG)|(1<<SEGH), чтобы внезапно оказалось, что в вашем массиве data индексы для массива символов...
Добавлено after 2 minutes 26 seconds:
Re: Как оптимизировать разбитие 16бит-числа на составляющие ?
TempResult, кстати, лишняя сущность.
Re: Как оптимизировать разбитие 16бит-числа на составляющие
Добавлено: Пт май 25, 2018 11:49:41
7seg
Тогда наверно будет удобней выводить индикацию в таком формате
void PrintNumber(uint16_t NeberChar,uint8_t NumberTimers)
{
uint8_t TempResult =0;
for (int i = 0; i < 5; i++)
{
TempResult = NeberChar % 10;
NeberChar = NeberChar / 10;
data=TempResult;
AnodCount=i;
OneOUT.ByteRegister &=~(1<<i);
PrintChar(data);
}
}