Вопросы по С/С++ (СИ)

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1590
Зарегистрирован: Вс июн 24, 2012 16:07:00
Откуда: Лен.Обл.

Сообщение da-nie »

Зачем паковать байт? Байт он всегда байт - как его ни пакуйте - а sizeof(t_point) в конкретном случае будет 1.
В вашем конкретном случае будет. А в общем случае - нет. Поэтому если у вас есть структура и вы хотите минимизировать размер занимаемой ею памяти, то всегда следует включать выравнивание к одному байту.

Код: Выделить всё

struct ccc* c = (struct ccc*)bb;

                  // содержимое bb -> 0х00, 0x00
   c->x = 0x07;   // содержимое bb -> 0х07, 0x00
   c->y = 0x07;   // содержимое bb -> 0х3F, 0x00
   c->z = 0x07;   // содержимое bb -> 0х3F, 0x07
Опасная вещь.
Стандарт не определяет:
— The alignment of the addressable storage unit allocated to hold a bit-field
И отдает на откуп компиляторам:
— Whether a ‘‘plain’’ int bit-field is treated as a signed int bit-field or as an
unsigned int bit-field
— Allowable bit-field types other than _Bool, signed int, and unsigned int
— Whether atomic types are permitted for bit-fields
— Whether a bit-field can straddle a storage-unit boundary
— The order of allocation of bit-fields within a unit
— The alignment of non-bit-field members of structures. This should present
no problem unless binary data written by one implementation is read by another.

https://habrahabr.ru/post/142662/
И день и ночь в пути...
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
Контактная информация:
Реклама
Потрогал лапой паяльник
Сообщения: 359
Зарегистрирован: Чт авг 08, 2013 01:06:54

Сообщение Пока_без_кота »

Доброго времени суток. Прошу помощи. Почему код

Код: Выделить всё

		uint8_t i;

		for (i = 0; i < 4; i++)
		{
			spi_put(0);
			spi_wait();
			keys[i] = TM1638_convert_byte(spi_get());
		}
не работает так же как код

Код: Выделить всё

		spi_put(0);
		spi_wait();
		keys[0] = TM1638_convert_byte(spi_get());

		spi_put(0);
		spi_wait();
		keys[1] = TM1638_convert_byte(spi_get());

		spi_put(0);
		spi_wait();
		keys[2] = TM1638_convert_byte(spi_get());

		spi_put(0);
		spi_wait();
		keys[3] = TM1638_convert_byte(spi_get());
В дизасме видно, что во втором случае при присваению элементу массива последовательно вызываются 2 функции, а в первом только 1:
Спойлер

Код: Выделить всё

223:      			spi_put(0);
+000000B7:   E080        LDI       R24,0x00       Load immediate
+000000B8:   D0A9        RCALL     PC+0x00AA      Relative call subroutine
224:      			spi_wait();
+000000B9:   D0D3        RCALL     PC+0x00D4      Relative call subroutine
225:      			keys[keys_code] = TM1638_convert_byte(spi_get());
+000000BA:   D0CF        RCALL     PC+0x00D0      Relative call subroutine
+000000BB:   5011        SUBI      R17,0x01       Subtract immediate
221:      		for (keys_code = 0; keys_code < 4; keys_code++)
+000000BC:   F7D1        BRNE      PC-0x05        Branch if not equal
229:      		spi_put(0);
+000000BD:   E080        LDI       R24,0x00       Load immediate
+000000BE:   D0A3        RCALL     PC+0x00A4      Relative call subroutine
230:      		spi_wait();
+000000BF:   D0CD        RCALL     PC+0x00CE      Relative call subroutine
231:      		keys[0] = TM1638_convert_byte(spi_get());
+000000C0:   D0C9        RCALL     PC+0x00CA      Relative call subroutine
+000000C1:   DF74        RCALL     PC-0x008B      Relative call subroutine
+000000C2:   2F08        MOV       R16,R24        Copy register
Код всей функции:
Спойлер

Код: Выделить всё

uint8_t TM1638_get_keys(void)
{
	uint8_t keys_code,key_number;
	uint8_t keys[4] = { 0 };
	
	TM1638_STB_LOW();	
	TM1638_write_byte(TM1638_CMD_READ_KEYS);
//	_delay_us(2);														// Минимально необходимая по даташиту задержка 2 мкс - можно убрать, все равно есть задержка после поднятия CLK в процедуре записи байта
#ifdef	USE_USI_FOR_TM1638
	half_spi_init_receive();											// Init SPI driver as RECEIVED master.
	_delay_us(100);
#else
	TM1638_DIO_INPUT();													// Установим ногу на вход !!!
#endif

#ifdef	USE_USI_FOR_TM1638

		for (keys_code = 0; keys_code < 4; keys_code++)
		{
			spi_put(0);
			spi_wait();
			keys[keys_code] = TM1638_convert_byte(spi_get());
		}

/*	ВОТ ТАКОЙ КОД РАБОТАЕТ КАК НАДО	
		spi_put(0);
		spi_wait();
		keys[0] = TM1638_convert_byte(spi_get());

		spi_put(0);
		spi_wait();
		keys[1] = TM1638_convert_byte(spi_get());

		spi_put(0);
		spi_wait();
		keys[2] = TM1638_convert_byte(spi_get());

		spi_put(0);
		spi_wait();
		keys[3] = TM1638_convert_byte(spi_get());
*/

#else
	
	for (keys_code = 0; keys_code < 4; keys_code++)						// Будем читать 4 байта состояний кнопок
	{
		for (key_number = 0; key_number < 8; key_number++)				// Перебор всех кнопок этого байта
		{
			TM1638_CLK_LOW();
			_delay_us(TM1638_DELAY_US);
			TM1638_CLK_HIGH();

			if (TM1638_DIO_READ())										// Если есть нажатая кнопка
			{
				keys[keys_code] |= (1<<key_number);						// Устанавливаем в ЭТОМ байте бит ЭТОЙ кнопки
			}

			_delay_us(TM1638_DELAY_US);			
		}
	}
#endif

	TM1638_STB_HIGH();

#ifdef	USE_USI_FOR_TM1638
	half_spi_reinit_transmit();											// Init SPI driver as TRANSMIT master.

#else
	TM1638_DIO_OUTPUT();												// Вернем ногу на выход !!!
#endif

	_delay_us(TM1638_DELAY_US);

	TM1638_send_comm(TM1638_CMD_SET_DATA | TM1638_SET_DATA_F_ADDR);		// Установка режима работы - Запись в индикатор, Фиксированный адрес

	_delay_us(TM1638_DELAY_US);

	keys_code = keys[0] | (keys[1]<<1) | (keys[2]<<2) | (keys[3]<<3);	// Собираем состояние всех кнопок в 1 байт (0 и 4 бит каждого из 4 принятых байт)

#ifdef RETURN_KEY_NUMBER
	if (keys_code)														// Если нажата кнопка - вычисляем ее номер (Внимание, будет передана только 1, самая младшая кнопка !!!)
	{
		for (key_number = 0; key_number < 8; key_number++, keys_code >>=1)
		{
			if (keys_code & 0x01)										// Если 0 бит установлен, найдена нажатая кнопка (Внимание, первой будет найдена кнопка из младшего бита)
			{
				return key_number+1;									// Возвращаем порядковый номер первой найденой нажатой кнопки
			}				
		}
	}
#endif

	return keys_code;													// Возвращаем состояние всех кнопок
}
Реклама
Модератор
Аватара пользователя
Сообщения: 4618
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

da-nie писал(а):
как его ни пакуйте - а sizeof(t_point) в конкретном случае будет 1.
В вашем конкретном случае будет. А в общем случае - нет.
Хотелось бы увидеть пример такого случая, при котором sizeof(t_point) будет не равен 1. Можете привести ?
da-nie писал(а):Поэтому если у вас есть структура и вы хотите минимизировать размер занимаемой ею памяти, то всегда следует включать выравнивание к одному байту.
Размер структуры = 1 байт. Куда дальше минимизировать ?
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 353
Зарегистрирован: Вс янв 19, 2014 22:41:55

Сообщение Siarzhuk »

[uquote="da-nie",url="/forum/viewtopic.php?p=3322178#p3322178"]В вашем конкретном случае будет. А в общем случае - нет. Поэтому если у вас есть структура и вы хотите минимизировать размер занимаемой ею памяти, то всегда следует включать выравнивание к одному байту.[/uquote]
К байту, а мы речь ведём о битах. И включать его следует не всегда а лишь тогда когда данный эффект требуется - при обмене с внешним миром если структура данных жёстко определена не нами да в случае очень уж сиротских ресурсов у нас - когда в .data уже 0, а в .text ещё место есть и можно заколоть корову эффективности, чтобы вымолить пару байт на данные (битовые поля в ту же кассу кстати работают иногда). Ну и из эстетических соображений - зело уродски выглядит как на мой взгляд. ;-)

[uquote="da-nie",url="/forum/viewtopic.php?p=3322178#p3322178"]Опасная вещь.[/uquote]
Не опаснее указателя. :lol: А про платформо-зависимость я даже на пальцах фокусы показал.
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! ;-)
Реклама
Эиком - электронные компоненты и радиодетали
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1590
Зарегистрирован: Вс июн 24, 2012 16:07:00
Откуда: Лен.Обл.

Сообщение da-nie »

Хотелось бы увидеть пример такого случая, при котором sizeof(t_point) будет не равен 1. Можете привести ?
Любая структура, в которую вы кроме имеющихся битовых полей добавите дополнительные данные. В вашем частном случае структура имеет размер 1 байт. Но если потом будут добавлены дополнительные элементы (а это часто требуется - скажем, добавят цвет), то может проявиться выравнивание структур и структура окажется не минимального достижимого размера. Поэтому стоит всегда дописывать указание компилятору на выравнивание структур.
Размер структуры = 1 байт. Куда дальше минимизировать ?
Это он сейчас один байт. Программы имеют свойство развиваться и структуры имеют свойство изменяться. Бывает даже, что копируются структуры из старой программы и дорабатываются в новой. И вот тогда размер не будет один байт. А вот насколько он окажется больше ожидаемого зависит от выравнивания. При этом вы можете даже и не заметить, что потеряли достаточно много памяти всего лишь добавив к этой структуре, например, 32 битный цвет точки и создав штук 100 таких структур (800-500=300 байт потеряно впустую). #pragma pack(1) спасёт от этой проблемы.
И день и ночь в пути...
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
Контактная информация:
Реклама
Модератор
Аватара пользователя
Сообщения: 4618
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

da-nie писал(а):Это он сейчас один байт.
Аlex писал(а):Вашу пару можно сократить до 1 байта, при таких условиях.
:)

Ежу понятно, что если в структуру добавить ещё поля, она увеличится в размерах. Но почему её в данном виде нужно паковать, Вы нам секрет так и не открыли.
Реклама
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1590
Зарегистрирован: Вс июн 24, 2012 16:07:00
Откуда: Лен.Обл.

Сообщение da-nie »

К байту, а мы речь ведём о битах. И включать его следует не всегда а лишь тогда когда данный эффект требуется - при обмене с внешним миром
Не только. Если у вас, например, на atmega8 есть крошечное ОЗУ, то создав массив структур вы потеряете довольно много памяти.
Ну и из эстетических соображений - зело уродски выглядит как на мой взгляд.
Если для вас главное - минимизация размера памяти, занимаемых структурой, то этот подход избавит от незамеченного увеличения размера структуры только потому, что вы что-то в неё добавили.
Не опаснее указателя.
Опаснее. Указатель редко используют не по назначению (скажем, разность указателей брать весьма опасно, но так, обычно, и не делают).
Это хорошо, когда процессор достаточно обычный. А у меня вот валяется 1967ВЦ1Т. У него в компиляторе байт 32-битный.

Ежу понятно, что если в структуру добавить ещё поля, она увеличится в размерах. Но почему её в данном виде нужно паковать, Вы нам секрет так и не открыли.
Потому что если вы добавите туда ещё поле с unsigned long Color, то размер будет не 5, а 8 без #pragma pack(1). И 5 с #pragma pack().
А в конкретном виде, как у вас, её нужно выравнивать потому, чтобы в дальнейшем избежать сюрпризов. Это просто рекомендация на будущее, чтобы не было потом мучительно больно.
Последний раз редактировалось da-nie Вс мар 04, 2018 11:05:14, всего редактировалось 1 раз.
И день и ночь в пути...
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
Контактная информация:
Модератор
Аватара пользователя
Сообщения: 4618
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

da-nie писал(а):Поэтому стоит всегда дописывать указание компилятору на выравнивание структур.
Не стоит этого делать всегда, не говорите ерунды. Упаковывать структуры нужно только в крайне необходимых ситуациях.

Добавлено after 1 minute 35 seconds:
da-nie писал(а):А в конкретном виде, как у вас, её нужно выравнивать потому, чтобы в дальнейшем избежать сюрпризов.
О каких сюрпризах идёт речь ? То, что структура займёт больше памяти ? :)))
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1590
Зарегистрирован: Вс июн 24, 2012 16:07:00
Откуда: Лен.Обл.

Сообщение da-nie »

Не стоит этого делать всегда, не говорите ерунды. Упаковывать структуры нужно только в крайне необходимых ситуациях.
У вас задача стоит в уменьшении размера памяти. Вреда от #pragma pack(1) в вашем случае у вас всё равно не будет (он не повлияет на ваш вариант, но может повлиять при модификации структуры).

Добавлено after 48 seconds:
О каких сюрпризах идёт речь ? То, что структура займёт больше памяти ?
Да. В условиях этой памяти в 1 кб это может быть очень важно.

P.S. Соврал, не 1967ВЦ1Т - тоже ВЦ, но по-другому как-то называется. Аналог процессора середины 80-х. Мерзость, короче.
И день и ночь в пути...
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
Контактная информация:
Модератор
Аватара пользователя
Сообщения: 4618
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

Вы увиливаете от темы, ссылаясь на "потом". Не будет у человека никаких "потом". У него есть конкретные условия, при которых ему был предложен вариант ужать координаты до 1 байта, вместо им используемых 2-ух. И почему, в конкретном случае (!), без #pragma pack это должно не получиться ("Иначе фокус может не получиться") - до сих пор остаётся загадкой.

Добавлено after 6 minutes 49 seconds:
PS: Не подумайте ничего плохого, я этот диалог развил не ради того, чтобы пообщаться от безделия. Просто Вас читают люди, и совет "нужно всегда упаковывать", чтобы потом не нарваться на какие-то там грабли - очень плохой. Нужно говорить "никогда не упаковывайте без надобности" !
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1590
Зарегистрирован: Вс июн 24, 2012 16:07:00
Откуда: Лен.Обл.

Сообщение da-nie »

И почему, в конкретном случае (!), без #pragma pack это должно не получиться ("Иначе фокус может не получиться") - до сих пор остаётся загадкой.
Читайте внимательнее - "фокус может не получиться". Я не утверждал, что в конкретном случае не получится.
Вы увиливаете от темы, ссылаясь на "потом".
Вообще-то, жизненный цикл программы это самое "потом" предполагает всегда. Знаете, как часто могут перетряхиваться самые простые структуры данных в программе? Добавили одно - убрали другое. Поменяли дисплей на с большим разрешением - не хватает старого размера битового поля для координат. И так далее. Ещё раз для тех, кому обедню два раза не служат: хорошим тоном при желании минимизировать объём структуры будет указание выравнивания к 1 байту с самого начала. Иначе потом, по мере развития проекта, может оказаться, что память уже исчерпана, а вы и не заметили, почему.
PS: Не подумайте ничего плохого, я этот диалог развил не ради того, чтобы пообщаться от безделия. Просто Вас читают люди, и совет "нужно всегда упаковывать", чтобы потом не нарваться на какие-то там грабли - очень плохой. Нужно говорить "никогда не упаковывайте без надобности" !
А я подумаю именно плохое. ;) Потому что у меня такой коллега есть - он всегда отвечает и ругается на то, чего ему никто не говорил и он по сути просто так понял, домыслив часть сам. Совет был дан для случая, когда вам нужно минимизировать объём занимаемой памяти - разве вы не этим занимались? А так - выравнивание ни к чему плохому не приведёт, кроме как к возможному снижению производительности.
Последний раз редактировалось da-nie Вс мар 04, 2018 11:26:55, всего редактировалось 1 раз.
И день и ночь в пути...
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
Контактная информация:
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 353
Зарегистрирован: Вс янв 19, 2014 22:41:55

Сообщение Siarzhuk »

[uquote="da-nie",url="/forum/viewtopic.php?p=3322375#p3322375"]
К байту, а мы речь ведём о битах. И включать его следует не всегда а лишь тогда когда данный эффект требуется - при обмене с внешним миром
Не только. Если у вас, например, на atmega8 есть крошечное ОЗУ, то создав массив структур вы потеряете довольно много памяти.[/uquote]
Это то, что вы из моих слов отцитировали. А теперь, внимание, моя фраза полностью:
[uquote="Siarzhuk",url="/forum/viewtopic.php?p=3322345#p3322345"]К байту, а мы речь ведём о битах. И включать его следует не всегда а лишь тогда когда данный эффект требуется - при обмене с внешним миром если структура данных жёстко определена не нами да в случае очень уж сиротских ресурсов у нас - когда в .data уже 0, а в .text ещё место есть и можно заколоть корову эффективности, чтобы вымолить пару байт на данные.[/uquote]
[За кулисами слышен плач канделябра в вашу сторону.] Т.е. вы мне оппонируете тем, что я же и озвучил [опуская мой ©] - это несеръёзно. Точно также как возводить в аксиому заклинание "прагма пак - ставь всегда". В большинстве случаев это только снижает производительность при работе с данными. А если носитель памяти имеет ограничения по выравниванию доступа, то [при дурном компиляторе] тот, кто вам доверился потратит некоторое время своей жизни на поиск источника проблемы. Так что, несите людям знания, а не молитвы. ;-)
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! ;-)
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1590
Зарегистрирован: Вс июн 24, 2012 16:07:00
Откуда: Лен.Обл.

Сообщение da-nie »

когда в .data уже 0, а в .text ещё место есть и можно заколоть корову эффективности, чтобы вымолить пару байт на данные.
Вы правда считаете, что я должен гадать, что вы хотели сказать этой фразой? ;)
Так что, несите людям знания, а не молитвы.
Не выдумывайте. ;)
И день и ночь в пути...
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
Контактная информация:
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 353
Зарегистрирован: Вс янв 19, 2014 22:41:55

Сообщение Siarzhuk »

[uquote="da-nie",url="/forum/viewtopic.php?p=3322397#p3322397"]Вообще-то, жизненный цикл программы это самое "потом" предполагает всегда. Знаете, как часто могут перетряхиваться самые простые структуры данных в программе?[/uquote]
Раздел темы "Разные вопросы по МК", форум любительский, тема "Вопросы по С/С++" - вряд-ли это место для лекций о филологии, управлению проектами, общих принципах написания надёжного кода, автоматизации тестирования и т.п. [О, Коте Всемогущий, не сочти это за самовольное модерирование.] 99% аудитории хочет видеть конкретные ответы на интересующие их вопросы, да и только. И хорошие привычки им прививать нужно дозированно, не перенагружая их входные цепи информацией. Такой вот мой вам оффтопичный намёк. ;-)

Добавлено after 11 minutes 16 seconds:
[uquote="da-nie",url="/forum/viewtopic.php?p=3322522#p3322522"]
когда в .data уже 0, а в .text ещё место есть и можно заколоть корову эффективности, чтобы вымолить пару байт на данные.
Вы правда считаете, что я должен гадать, что вы хотели сказать этой фразой?[/uquote]
Двух слов .data и .text - sapienti sat, чтобы понять о чём речь. У вас пробел в знаниях.
[uquote="da-nie",url="/forum/viewtopic.php?p=3322522#p3322522"]Не выдумывайте. ;)[/uquote]
Т.е. на моей актуальной платформе RX63N + 32 MB etx. SDRAM ваша аксиома о всегдашности использования упаковки структур принесёт что-то кроме замусоривания кода - это выдумка? :))) И про word-aligned memory access вы тоже не слышали. [Канделябр, заходи...]
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! ;-)
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1590
Зарегистрирован: Вс июн 24, 2012 16:07:00
Откуда: Лен.Обл.

Сообщение da-nie »

99% аудитории хочет видеть конкретные ответы на интересующие их вопросы, да и только.
Телепатией не обладаю. Уж извините. :music:

Добавлено after 14 minutes 29 seconds:
Двух слов .data и .text - sapienti sat, чтобы понять о чём речь. У вас пробел в знаниях.
Всегда удивляла подобная самоуверенность, переходящая в наглость. ;) Вы правда думаете, что будете писать что вздумается и при этом ожидать, что вас поймут? Да откуда бы?! Секция .data - содержит статические инициализированные данные. А про секцию .bss вы как-то забыли. И про кучу тоже не вспомнили. Забыли вы и про то, что переменные могут создаваться и на стеке (и рекурсию на МК никто не запрещал - есть и такие задачи). Да даже может потребоваться передать структуру по значению в функцию - и то на 1 КБ ОЗУ памяти может не хватить. Поэтому я написал, как оно и должно быть написано - мало памяти. А вы по сути написали, что если вы заняли всю память под .data, то... Но речь не идёт о том, чтобы занять всю память одной секцией. Речь идёт о том, что при работе программы памяти может не хватить (в том числе в процессе выполнения) (а так оно и бывает чаще всего). Поэтому написали вы совсем не то же самое, что и я.
Т.е. на моей актуальной платформе RX63N + 32 MB etx. SDRAM ваша аксиома о всегдашности использования упаковки структур принесёт что-то кроме замусоривания кода - это выдумка?
Вообще, вы странные люди. Я вам давно объяснил, о чём написал. Но вы продолжаете упорно сами придумывать случаи, где вам выравнивание структур мешает.
Последний раз редактировалось da-nie Вс мар 04, 2018 15:25:44, всего редактировалось 3 раза.
И день и ночь в пути...
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 7382
Зарегистрирован: Пт авг 28, 2009 21:34:30
Откуда: 845-й км.

Сообщение uldemir »

[uquote="Пока_без_кота",url="/forum/viewtopic.php?p=3322257#p3322257"]Доброго времени суток. Прошу помощи. Почему код...[/uquote]
Думаю, ошибка в этой строчке:

Код: Выделить всё

		for (key_number = 0; key_number < 8; key_number++, keys_code >>=1)
вы бы уточнили при каких дефайнах собираете.
А люди посмотрят и скажут: "Собаки летят. Вот и осень."
Потрогал лапой паяльник
Сообщения: 359
Зарегистрирован: Чт авг 08, 2013 01:06:54

Сообщение Пока_без_кота »

Спасибо, возможно это так, но я пробовал компилировать и без дефайна для поика порядкового номера нажатой кнопки, и оно все равно не работало. Я тут уже и так и эдак крутил, и даже вроде "оптимизировал" до варианта без массива, сложение 4-х байт в один произвожу прямо в цикле. Получилось даже компактнее, и главное работает (тут переменные немного переименовал, для большей понятности для себя) :)))

Код: Выделить всё

	for (keys_byte = 0; keys_byte < 4; keys_byte++)						// Будем читать 4 байта состояний кнопок
	{
		spi_put(0);
		spi_wait();
		keys_code |= (TM1638_convert_byte(spi_get()))<<keys_byte;		// Каждый следующий байт накладывается на предыдущий со сдвигом влево на величину порядкового номер принятого байта (начиная с 0 !!!)
	}
П.С. Описываемая проблема относилась к варианту при использовании дефайна USE_USI_FOR_TM1638.

Теперь вся функция выглядит вот так:
Спойлер

Код: Выделить всё

uint8_t TM1638_get_keys(void)
{
	uint8_t keys_code = 0,keys_byte,key_number;
	
	TM1638_STB_LOW();	
	TM1638_write_byte(TM1638_CMD_READ_KEYS);
//	_delay_us(2);														// Минимально необходимая по даташиту задержка 2 мкс - можно убрать, все равно есть задержка после поднятия CLK в процедуре записи байта

#ifdef	USE_USI_FOR_TM1638
	half_spi_init_receive();											// Init SPI driver as RECEIVED master.

#else
	TM1638_DIO_INPUT();													// Установим ногу на вход !!!
#endif

#ifdef	USE_USI_FOR_TM1638
	for (keys_byte = 0; keys_byte < 4; keys_byte++)						// Будем читать 4 байта состояний кнопок
	{
		spi_put(0);
		spi_wait();
		keys_code |= (TM1638_convert_byte(spi_get()))<<keys_byte;		// Каждый следующий байт накладывается на предыдущий со сдвигом влево на величину порядкового номер принятого байта (начиная с 0 !!!)
	}

#else
	uint8_t key_code = 0;

	for (keys_byte = 0; keys_byte < 4; keys_byte++)						// Будем читать 4 байта состояний кнопок
	{
		for (key_number = 0; key_number < 8; key_number++)				// Перебор всех кнопок этого байта
		{
			TM1638_CLK_LOW();
			_delay_us(TM1638_DELAY_US);
			TM1638_CLK_HIGH();

			if (TM1638_DIO_READ())										// Если есть нажатая кнопка
			{
				key_code |= (1<<key_number);							// Устанавливаем бит нужной кнопки 
				keys_code |= key_code<<keys_byte;						// и накладываем этот байт на предыдущий со сдвигом влево на величину порядковго номера принятого байта (начиная с 0 !!!)
			}

			_delay_us(TM1638_DELAY_US);			
		}
	}
#endif

	TM1638_STB_HIGH();

#ifdef	USE_USI_FOR_TM1638
	half_spi_reinit_transmit();											// Init SPI driver as TRANSMIT master.

#else
	TM1638_DIO_OUTPUT();												// Вернем ногу на выход !!!
#endif

	_delay_us(TM1638_DELAY_US);

	TM1638_send_comm(TM1638_CMD_SET_DATA | TM1638_SET_DATA_F_ADDR);		// Установка режима работы - Запись в индикатор, Фиксированный адрес

	_delay_us(TM1638_DELAY_US);

#ifdef RETURN_KEY_NUMBER
	if (keys_code)														// Если нажата кнопка - вычисляем ее номер (Внимание, будет передана только 1, самая младшая кнопка !!!)
	{
		for (key_number = 0; key_number < 8; key_number++, keys_code >>=1)
		{
			if (keys_code & 0x01)										// Если 0 бит установлен, найдена нажатая кнопка (Внимание, первой будет найдена кнопка из младшего бита)
			{
				return key_number+1;									// Возвращаем порядковый номер первой найденой нажатой кнопки
			}				
		}
	}
#endif

	return keys_code;													// Возвращаем состояние всех кнопок
}
Друг Кота
Аватара пользователя
Сообщения: 7382
Зарегистрирован: Пт авг 28, 2009 21:34:30
Откуда: 845-й км.

Сообщение uldemir »

нет, это моя ошибка - строка правильная.

Причина пропадания вызова может быть шуткой оптимизатора. Мне сначала показалось, что вы там не сдвигаете keys_code и поэтому оптимизатор выбросил вычисление, которое в конце-концов не понадобится. Поэтому внимательно проверьте, что для вычисления вашего return keys_code это действительно нужно. кстаи, причина может быть внутри функции TM1638_convert_byte(

Мне как-то IAR тоже так был "соптимизировавши". Благодаря ему я и нашел ошибку. Причем, при компиляции с пониженным уровнем оптимизации всё работало
А люди посмотрят и скажут: "Собаки летят. Вот и осень."
Родился
Сообщения: 7
Зарегистрирован: Пт мар 02, 2018 16:31:19

Сообщение Shrike1987 »

Уважаемый Siarzhuk!
Благодарю за код!

При попытки скомпилировать его получаю две ошибки в строке:

Код: Выделить всё

for (p0 = Font2[C].Line, p = Font2[C].Line + 1; 0 == p->eol; p0 = p, p++) 
Сами ошибки: ..\Src\Font.c(51): error: #513: a value of type "const t_point *" cannot be assigned to an entity of type "t_point *"

Чего ему не нравится? Мне вот реализация ооочень даже нравится )))
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Так ведь прямым текстом написано, что. Разные типы указателей.
Контактная информация:
Ответить

Вернуться в «Разные вопросы по МК»