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

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Аватара пользователя
Viper_Snake
Электрический кот
Сообщения: 1046
Зарегистрирован: Вс мар 01, 2009 19:47:16
Откуда: Ростов-на-Дону

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

Сообщение Viper_Snake »

[uquote="veso74",url="/forum/viewtopic.php?p=4267986#p4267986"]Идея:

В:

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

C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino\wiring_shift.c
строка 25..38, посмотрите как написано shiftIn() для 8 бит. Напишите напр. локальную функцию (под другим именем) для 4 * 8 бита (long) или больше (5 байт) (при этом, конечно, соблюдая разрядность новых типов данных - некоторые типы перейдут на uint64_t. А можете оптимизировать: до uint32_t, как написали напр. есть ненужный байт).

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

uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) {
	uint8_t value = 0;
	uint8_t i;

	for (i = 0; i < 8; ++i) {
		digitalWrite(clockPin, HIGH);
		if (bitOrder == LSBFIRST)
			value |= digitalRead(dataPin) << i;
		else
			value |= digitalRead(dataPin) << (7 - i);
		digitalWrite(clockPin, LOW);
	}
	return value;
}
[/uquote]

Ну это как вариант, но потом придется 8-ми байтную простыню разбирать - узкоглазые с этим 5-ти байтным регистром как всегда подосрали ..
Не важно чем все начнется. Важно чем кончится!
veso74
Поставщик валерьянки для Кота
Сообщения: 1905
Зарегистрирован: Сб май 05, 2012 20:24:52
Откуда: KN34PC, Болгария
Контактная информация:

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

Сообщение veso74 »

Viper_Snake, можете написать фразу другими словами? С русского толком не переводится до БГ :), и не могу понять смисл.
Чувствую, что что-то не нравится, но что это ...
Аватара пользователя
Viper_Snake
Электрический кот
Сообщения: 1046
Зарегистрирован: Вс мар 01, 2009 19:47:16
Откуда: Ростов-на-Дону

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

Сообщение Viper_Snake »

[uquote="veso74",url="/forum/viewtopic.php?p=4268016#p4268016"]Viper_Snake, можете написать фразу другими словами? С русского толком не переводится до БГ :), и не могу понять смисл.
Чувствую, что что-то не нравится, но что это ...[/uquote]

Я извиняюсь. Вариант хороший, но после его применения придется работать с большой переменной размером 8 байт. Китайцы с 5 битным регистром клавиатуры сделали очень нехорошо - в 4 бита не вместится, 8 бит - 3 бита лишние.
Не важно чем все начнется. Важно чем кончится!
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

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

Сообщение VladislavS »

Если не выходить за пределы ардуины, то я бы вот так написал.
Спойлер

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

uint32_t readTMData() 
{  
  digitalWrite(PIN_STB, LOW);
  shiftOut(PIN_DIO, PIN_CLK, LSBFIRST, 0x42);
  pinMode(PIN_DIO, INPUT_PULLUP);
  delayMicroseconds(1);
  uint8_t tmp1 = shiftIn(PIN_DIO, PIN_CLK, LSBFIRST);
  uint8_t tmp2 = shiftIn(PIN_DIO, PIN_CLK, LSBFIRST);
  shiftIn(PIN_DIO, PIN_CLK, LSBFIRST);
  uint8_t tmp3 = shiftIn(PIN_DIO, PIN_CLK, LSBFIRST);
  uint8_t tmp4 = shiftIn(PIN_DIO, PIN_CLK, LSBFIRST);
  pinMode(PIN_DIO, OUTPUT);
  digitalWrite(PIN_STB, HIGH);
  return (uint32_t(0x80+tmp1)<<24)+(uint32_t(tmp2)<<16)+(uint32_t(tmp3)<<8)+tmp4;
}
Включить максимальную оптимизацию и молиться.

Чувствую, потребуются пояснения. Если это 8-битка, то операции сдвига локальных переменных на 24, 16 и 8 бит будут бесплатными. Результат возвращается через четыре РОН. Из shiftIn данные будут сразу в эти регистры записываться без каких-либо сдвигов.
Последний раз редактировалось VladislavS Вт авг 02, 2022 21:43:06, всего редактировалось 2 раза.
veso74
Поставщик валерьянки для Кота
Сообщения: 1905
Зарегистрирован: Сб май 05, 2012 20:24:52
Откуда: KN34PC, Болгария
Контактная информация:

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

Сообщение veso74 »

Спойлерuint32_t readTMData() {
uint32_t data = 0;

for (uint8_t i = 0; i < 32; ++i) {
digitalWrite(PIN_CLK, HIGH);
data |= digitalRead(PIN_DIO) << i;
digitalWrite(PIN_CLK, LOW);
}

bitSet(data, 31); // ставим 31-й бит в 1

pinMode(PIN_DIO, OUTPUT);
digitalWrite(PIN_STB, HIGH);

return data;
}
...
uint32_t a = readTMData();
Последний раз редактировалось veso74 Вт авг 02, 2022 21:48:38, всего редактировалось 2 раза.
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

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

Сообщение VladislavS »

veso74, там 5 байт, из которых часть не нужна.
veso74
Поставщик валерьянки для Кота
Сообщения: 1905
Зарегистрирован: Сб май 05, 2012 20:24:52
Откуда: KN34PC, Болгария
Контактная информация:

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

Сообщение veso74 »

Спойлер

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

uint32_t readTMData() {
  uint64_t data = 0;

  for (uint8_t i = 0; i < 16; ++i) {
    digitalWrite(PIN_CLK, HIGH);
    data |= digitalRead(PIN_DIO) << i;
    digitalWrite(PIN_CLK, LOW);
  }

  for (uint8_t i = 24; i < 40; ++i) {
    digitalWrite(PIN_CLK, HIGH);
    data |= digitalRead(PIN_DIO) << i;
    digitalWrite(PIN_CLK, LOW);
  }

  bitSet(data, 31);  // ставим 31-й бит в 1

  pinMode(PIN_DIO, OUTPUT);
  digitalWrite(PIN_STB, HIGH);

  return data;
}
...
uint32_t a = readTMData();
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

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

Сообщение VladislavS »

veso74, не то. Считать надо 40 бит. Из них взять 32.
veso74
Поставщик валерьянки для Кота
Сообщения: 1905
Зарегистрирован: Сб май 05, 2012 20:24:52
Откуда: KN34PC, Болгария
Контактная информация:

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

Сообщение veso74 »

сложно, сейчас перенесу на бумагу, другого выхода нет :)
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

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

Сообщение VladislavS »

veso74, не стоит. Понятно что вы хотите сделать. На 8-битке это будет работать хуже.
veso74
Поставщик валерьянки для Кота
Сообщения: 1905
Зарегистрирован: Сб май 05, 2012 20:24:52
Откуда: KN34PC, Болгария
Контактная информация:

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

Сообщение veso74 »

Спойлер

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

uint32_t readTMData() {
  uint32_t data = 0;

  for (uint8_t i = 0; i < 16; ++i) {
    digitalWrite(PIN_CLK, HIGH);
    data |= digitalRead(PIN_DIO) << i;
    digitalWrite(PIN_CLK, LOW);
  }

  digitalRead(PIN_DIO);  // ???

  for (uint8_t i = 24; i < 32; ++i) {
    digitalWrite(PIN_CLK, HIGH);
    data |= digitalRead(PIN_DIO) << i;
    digitalWrite(PIN_CLK, LOW);
  }

  bitSet(data, 31);  // ставим 31-й бит в 1

  pinMode(PIN_DIO, OUTPUT);
  digitalWrite(PIN_STB, HIGH);

  return data;
}
Ок, не уверен, как он перейдет с 16 на 24 бита. Ладно, мне нечего пробовать. Я дал это только как идею, в реальном использовании, если необходимо, измените его в соответствии с потребностями.
Последний раз редактировалось veso74 Вт авг 02, 2022 22:09:02, всего редактировалось 2 раза.
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

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

Сообщение VladislavS »

Ну почти, только между двумя 16-битными чтениями не digitalRead, а shiftIn (или просто 8 клоков) нужен. Но, повторюсь, это будет хуже пяти 8-битных shiftIn из-за длинных сдвигов.
veso74
Поставщик валерьянки для Кота
Сообщения: 1905
Зарегистрирован: Сб май 05, 2012 20:24:52
Откуда: KN34PC, Болгария
Контактная информация:

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

Сообщение veso74 »

Короче как бы взяли 40 бит, вычеркнули 8 и упаковали до 32 (изменив 31-й байт)?
Время определяющее? (светодиодная индикация напр. или что-то еще?)

я бы поставил expander, он бы сигнализировал по interrupt при действие и никак не занимать бы центральный mcu в другое время (с сканирования неактивных кнопок). Но это без знания Вашего устройства.
MOHCTEP
Опытный кот
Сообщения: 768
Зарегистрирован: Вс янв 19, 2014 00:55:09

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

Сообщение MOHCTEP »

Еще вариант псевдокода, собственно идеи ради, так как как в железке проверить не могу.

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

union result{
	uint8_t bytes[4];
	ulong data;
}

void readTMData(){
	uint8_t count = 0;
	for(uint8_t i = 0; i < 5; i++){// bytes from TM1628
		if(i == 2) continue;
		result.bytes[count++] = shiftIn(PIN_DIO, PIN_CLK, LSBFIRST);
	}
	result.bytes[3] |= 0x80; // ставим 7-й бит в 1.
	// используем result.data для анализа кнопок
}
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

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

Сообщение VladislavS »

MOHCTEP, 3-й байт таки тоже надо вычитывать, но не использовать. При оптимизации по скорости есть большая вероятность, что компилятор раскрутит ваш цикл до моей версии.

И union тут не нужен совсем. Компиляторы прекрасно умеют писать байты в 32-битные переменные просто в один из четырёх восьмибитных регистров.
MOHCTEP
Опытный кот
Сообщения: 768
Зарегистрирован: Вс янв 19, 2014 00:55:09

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

Сообщение MOHCTEP »

VladislavS, Верно - не учел. Придется условие раскрыть. Как-то так, наверное, если без объединения.

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

ulong data;
void readTMData(){
   for(uint8_t i = 0; i < 5; i++){// bytes from TM1628
      if(i == 2){
		  shiftIn(PIN_DIO, PIN_CLK, LSBFIRST); // в космос
		  continue;
	  }
	  data <<= 8;
	  data |= shiftIn(PIN_DIO, PIN_CLK, LSBFIRST);
   }
   data |= 0x80000000; // ставим 31-й бит в 1.
}
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

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

Сообщение ARV »

что-то я не понимаю: 2 лишних байта ОЗУ так критичны? 40 бит это 5 байт, считывайте все 5, а потом спокойно работайте побайтово с тремя нужными, обращаясь к нужным битам при помощи маски. или я упускаю что-то важное?
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
Viper_Snake
Электрический кот
Сообщения: 1046
Зарегистрирован: Вс мар 01, 2009 19:47:16
Откуда: Ростов-на-Дону

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

Сообщение Viper_Snake »

[uquote="MOHCTEP",url="/forum/viewtopic.php?p=4268053#p4268053"]VladislavS, Верно - не учел. Придется условие раскрыть. Как-то так, наверное, если без объединения.

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

ulong data;
void readTMData(){
   for(uint8_t i = 0; i < 5; i++){// bytes from TM1628
      if(i == 2){
		  shiftIn(PIN_DIO, PIN_CLK, LSBFIRST); // в космос
		  continue;
	  }
	  data <<= 8;
	  data |= shiftIn(PIN_DIO, PIN_CLK, LSBFIRST);
   }
   data |= 0x80000000; // ставим 31-й бит в 1.
}
[/uquote]
Изящно, но с точки зрения оптимизации те же яйца что у меня только в профиль. )

Добавлено after 19 minutes 7 seconds:
[uquote="ARV",url="/forum/viewtopic.php?p=4268056#p4268056"]что-то я не понимаю: 2 лишних байта ОЗУ так критичны? 40 бит это 5 байт, считывайте все 5, а потом спокойно работайте побайтово с тремя нужными, обращаясь к нужным битам при помощи маски. или я упускаю что-то важное?[/uquote]

Да в общем то ОЗУ хоть жопой ешь - контроллер tiny84 - 512 байт целых. Вопрос в другом - я ведь не зря сказал, что в ардуиновской среде ковыряюсь - мне удобнее взять стандартный тип переменной, чем свою 5-ти байтную сочинять. Весь этот онанизм вприсядку связан с тем, что появилась необходимость доработать уже сделанное ранее устройство и тут внезапно выяснилось, что надо где то добыть 3 дополнительных порта контроллера, один еще и в роли ацп. А порты внезапно все уже заняты и чтобы их освободить, три входа под датчики типа сухой контакт пришлось отдолжить у TM1628. В ДШ для этого очень удачно под индикацию не задействованы ноги SEG8 - SEG10. Кстати, не верьте ДШ TM1628 - ее бессовестно скопировали с AIP1628. Разница по ДШ как раз в пятом байте регистра кнопок - в ДШ на TM1628 их почему то гарисовано только 4. И схема подключения кнопок в 2-х местах разная.
Не важно чем все начнется. Важно чем кончится!
MOHCTEP
Опытный кот
Сообщения: 768
Зарегистрирован: Вс янв 19, 2014 00:55:09

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

Сообщение MOHCTEP »

Viper_Snake, Скорей всего ваша правда. Код на голеностопе состряпан, проверить не на чем. Думал, может циклом по-оптимальней будет.
Viper_Snake писал(а):Да в общем то ОЗУ хоть жопой ешь - контроллер tiny84 - 512 байт целых.
:)) Мне этак примерно с tiny13 довелось помучиться, в озу "вписался", но прошивка занимала 1025 байт.
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

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

Сообщение VladislavS »

На 8-битке ещё вот так будет достаточно эффективно. Можно как 4, так и все 5 байт вытащить одинаково.
Спойлер

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

void readTMData(uint8_t *pdata)
{ 
  digitalWrite(PIN_STB, LOW);
  shiftOut(PIN_DIO, PIN_CLK, LSBFIRST, 0x42);
  pinMode(PIN_DIO, INPUT_PULLUP);
  delayMicroseconds(1);
  *pdata++ = shiftIn(PIN_DIO, PIN_CLK, LSBFIRST) | 0x80;
  *pdata++ = shiftIn(PIN_DIO, PIN_CLK, LSBFIRST);
  shiftIn(PIN_DIO, PIN_CLK, LSBFIRST);
  *pdata++ = shiftIn(PIN_DIO, PIN_CLK, LSBFIRST);
  *pdata = shiftIn(PIN_DIO, PIN_CLK, LSBFIRST);
  pinMode(PIN_DIO, OUTPUT);
  digitalWrite(PIN_STB, HIGH);
}
Ну а дальше - вылазить из ардуины.
Ответить

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