Страница 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);
}
}