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

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить
Грызет канифоль
Аватара пользователя
Сообщения: 275
Зарегистрирован: Вс окт 20, 2019 13:03:56

Сообщение Shuspano »

[uquote="NStorm",url="/forum/viewtopic.php?p=3797767#p3797767"]Не у всех AVR есть.[/uquote]
Ну в основном есть. Всегда можно распотрошить ардуину. 8051 с I2C можно пересчитать по пальцам одной руки, и часто они не от мира сего по устройству
Да и реализация выше в общем-то особо к платформе не привязана.
Да, действительно. Просто и понятно. Спасибо.

А не поможете еще разок, объясните эту конструкцию?

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

		while((SCLPIN & (1<<SCL))==0);
		
		if(SDAPIN &(1<<SDA))
			data|=(0x80>>i);
Реклама
Модератор
Аватара пользователя
Сообщения: 19100
Зарегистрирован: Сб авг 14, 2010 15:05:51
Откуда: г. Озерск, Челябинская обл.

Сообщение Starichok51 »

Shuspano писал(а):на астме
астма - это болезнь.
а ассемблер сокращенно будет асм.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Реклама
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18787
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

Shuspano писал(а):объясните эту конструкцию?
    

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

 while((SCLPIN & (1<<SCL))==0);
бесконечное ожидание момента, когда бит SCL в регистре (?) SCLPIN станет равным 1.

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

if(SDAPIN &(1<<SDA))
         data|=(0x80>>i);
если бит SDA в регистре SDAPIN установлен, то установить i-й слева (повбывал бы!) бит в переменной data
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Опытный кот
Сообщения: 768
Зарегистрирован: Вс янв 19, 2014 00:55:09

Сообщение MOHCTEP »

ARV писал(а):цикл по маске
съел на 6 байт побольше флеша, сравнительно с циклом, где маска не меняется.

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

// 	uint8_t bit = 8;
// 	while(bit--){
// 		draw_pixel(x, y, byte & 0x80, width);
// 		byte <<= 1;
// 		y++;
// 	}
// + 6 bytes FLASH
	for (uint8_t mask = 0x80; mask; mask >>=1)	{
		draw_pixel(x, y, byte & mask, width);
		y++;
	}
А жаль. Вариант ARV выглядит эстетичнее.
Последний раз редактировалось MOHCTEP Пт фев 28, 2020 16:42:13, всего редактировалось 2 раза.
Реклама
Эиком - электронные компоненты и радиодетали
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18787
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

даже любопытно увидеть листинги вариантов :)
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

MOHCTEP, Вы не те алгоритмы сравниваете. Что сдвиг маски, что сдвиг byte - это практически одно и тоже, видимо с неболшими нюансами

А вот тут (собственно от этой печки идет пляска), сдвиг Byte производится на i раз при каждой итерации цикла. Так как отсутствует инструкция сдвига на несколько бит, то скомпилится цикл в цикле и почем зря.

Добавлено after 7 minutes 26 seconds:
Возможно, основное отличие тут
между этим

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

byte & 0x80
и этим

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

byte & mask
В первом случае всегда проверяется старший бит в переменной, а во втором побитовое И между двумя переменными.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Реклама
Опытный кот
Сообщения: 768
Зарегистрирован: Вс янв 19, 2014 00:55:09

Сообщение MOHCTEP »

ARV, :beer:
Z_h_e, да-да, я видел начало этой эпопеи. Там все объяснили, рассказали, вот канделябр только жалко - раритет все таки. :)) Понравился сам алгоритм от ARV. Простой, изящный, легко читается.
Спасибо за ответ. Теперь понятно, куда "лишние" байты делись.
Опытный кот
Аватара пользователя
Сообщения: 867
Зарегистрирован: Пт фев 27, 2015 12:00:53
Откуда: Рязанская область

Сообщение Serzh2000 »

помогите понять как читает строчки атмега и сделать задержку...

есть код

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

1начало
2...
3...
4for (int q = 0; q < 12;q++ ) {
5  ...
6  ...
7 refreshAll(); }    // вывод на экран
8...
9...
10...
11конец
атмега выполнила 1 стр. 2, 3, 4-7,4-7...( и так 12 раз) 8,9,10,11 затем 1,2 и т.д

правильно!?

добавим в код функцию millis();
Спойлерmillis() – Возвращает количество миллисекунд, прошедших с запуска. Возвращает unsigned long, от 1 до 4 294 967 295 миллисекунд (~50 суток), имеет разрешение 1 миллисекунда, после переполнения сбрасывается в 0. Работает на системном таймере Timer 0

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

1начало
2...
3...
4for (int q = 0; q < 12;q++ ) {
5  ...
6  ...
7 refreshAll();     // вывод на экран
8 millis() % 75==0; } //нужна здесь пауза 900мс/12=75мс
9...
10...
11конец

как бы я хотел

атмега выполнила 1 стр. 2, 3, 4-7 8 стр. так как millis не равно нулю атмега выполняет 9,10,11,1,2 (прошло 75 мс) и millis равно нулю, амега выполнит 4-7,8 и вернется где прервала выполнение ко 2 стр.3,9,10,11,1,2 и т.д


на практике все не так и я чего то не понимаю... :dont_know:
https://www.radiokot.ru/forum/viewtopic ... 2#p3799892
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Serzh2000 писал(а): затем 1,2 и т.д

правильно!?
неправильно
Serzh2000 писал(а):8 millis() % 75==0; } //нужна здесь пауза 900мс/12=75мс
millis к паузе вообще отношения не имеет. Собственно, если бы Вы прочитали сами то, что процитировали по этому поводу, то тоже поняли бы это.
Контактная информация:
Опытный кот
Аватара пользователя
Сообщения: 867
Зарегистрирован: Пт фев 27, 2015 12:00:53
Откуда: Рязанская область

Сообщение Serzh2000 »

неправильно
??? а как же контролер читает
millis к паузе вообще отношения не имеет.

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

1начало
2...
3...
4for (int q = 0; q < 12;q++ ) {
5  ...
6  ...
7 refreshAll();     // вывод на экран
8 my_millis(10);  } //нужна здесь пауза 
9...
10...
11конец
12 void my_millis(uint32_t us) {
13 uint32_t tmr = millis();
14  while (millis() - tmr < us);
15 }
вот так пауза есть, но она как и функция delay(); все тормозит
Спойлер//----------------------------------------------------------------------- ВЫВОД ПОЛНЫХ ЧАСОВ
void showClockMed(){ //

clrAll(); // очищает экран полностью (смотрим вкладку "max7219.h")


int flag = millis() % 1000; // счетчик будет считать до тысячи и все заново
if ( flag > 500) { setCol(10, 0x24);} // если флаг больше 500, рисуем точки



// выводим цифры, которые не изменились
if (s0 == lasts0){showDigit(s0, 28, dig3x7s);}
if (s1 == lasts1){showDigit(s1, 24, dig3x7s);}
if (m0 == lastm0){showDigit(m0, 17, dig4x8);}
if (m1 == lastm1){showDigit(m1, 12, dig4x8);}
if (h0 == lasth0){showDigit(h0, 5, dig4x8);}
if ((h1>0)&&(h1 == lasth1)){showDigit(h1, 0, dig4x8);}



for (int q = 0; q < 12; q++ ) { // а теперь цикл по изменившимся цифрам

if (s0 != lasts0){showDigit( s0 * 12 + q, 28, dig3x7q);}
if (s1 != lasts1){showDigit( s1 * 12 + q, 24, dig3x7q);}
if (m0 != lastm0){showDigit( m0 * 12 + q, 17, dig4x8q);}
if (m1 != lastm1){showDigit( m1 * 12 + q, 12, dig4x8q);}
if (h0 != lasth0){showDigit( h0 * 12 + q, 5, dig4x8q);}
if ((h1>0)&&(h1 != lasth1)){showDigit( h1 * 12 + q, 0, dig4x8q);}




refreshAll(); // обновляем экран после каждой строки
my_millis(25); // задержка для плавного вывода цифр
}
lasth1 = h1; lasth0 = h0; lastm1 = m1; lastm0 = m0; lasts1 = s1; lasts0 = s0; // для того чтобы знать изменилась цифра или нет

}
//-----------------------------------------------------------------------


void my_millis(uint32_t us) {
uint32_t tmr = millis();
while (millis() - tmr < us);
}
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

У Вас противоречивые хотелки - и паузу хотите, и чтобы не тормозило. В последовательно выполняющемся коде так не бывает.

Если не хотите тормозов, просто не используйте задержки вообще. Ни в виде отдельной delay() функции, ни в виде аналога на основе millis() - без разницы, каким способом контроллер будет висеть заказанное время в одном месте.
Контактная информация:
Опытный кот
Аватара пользователя
Сообщения: 867
Зарегистрирован: Пт фев 27, 2015 12:00:53
Откуда: Рязанская область

Сообщение Serzh2000 »

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

Сообщение WiseLord »

Любая задержка - это именно задержка. То есть, останавливает всю программу. А будучи помещена в теле цикла - сделает это N раз, соответственно.

Если нужно, чтобы выполняла действие, как только пришло время - задержка тут не нужна. Нужно именно что-то вроде if (пришло время что-то сделать) { делаем что-то }. Без каких-либо задержек.
Контактная информация:
Опытный кот
Аватара пользователя
Сообщения: 867
Зарегистрирован: Пт фев 27, 2015 12:00:53
Откуда: Рязанская область

Сообщение Serzh2000 »

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

int q = 0;
1начало
2...
3...
4 if (millis() % 75==0)  {
5 q++ ;
6  ...
7 refreshAll();     // вывод на экран
8 if (q < 12) { q=0;}
9 } 
10...
11...
12 конец
типа так?
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Да, что-то вроде. Цикл не нужен. За один вызов этого кода эта "частичная" отрисовка должна отработать только один раз. А уже на следующем вызове функции, значение q будет уже другое и отрисовано будет уже по-другому. Естественно, q должна быть либо глобальной, либо статической переменной, чтобы сохранять значение между вызовами этого кода.

P.S. Только if (q < 12) { q=0;} - неправильное условие - всегда будет на 0 выходить.

Опять же, условие if (millis() % 75==0) не очень корректное. Потому что именно в эту (одну из 75) миллисекунду, когда остаток от деления на 75 равен нулю, очень велик шанс, что будет выполняться код совсем где-то в другом месте, так что, пока программа придёт к этому месту, всё уже поменяется, и это условие не выполнится.

Лучше значение, возвращаемое millis(), запомнить (например, в переменной oldMillis). А затем, когда снова программа придёт к этому месту, проверить, сколько прошло времени. То есть, что-то вроде.

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

static unsigned long oldMillis = 0;

...
unsigned long now = millis();
if (now - oldMIllis >= 75) {
    // делаем что-то;
   oldMillis = now;
}
Тогда это "что-то" будет делаться не чаще раза в 75мс. А если где-то что-то подвиснет на пару миллисекунд в другом месте, то всё равно выполнится. Пусть, не через ровно 75, а на пару миллисекунд больше - некритично.
Контактная информация:
Опытный кот
Аватара пользователя
Сообщения: 867
Зарегистрирован: Пт фев 27, 2015 12:00:53
Откуда: Рязанская область

Сообщение Serzh2000 »

что то стало получаться, спасибо.
программа перестала тормозить
буду думать дальше.
Опытный кот
Сообщения: 768
Зарегистрирован: Вс янв 19, 2014 00:55:09

Сообщение MOHCTEP »

Есть данные разной байтовой величины и знака. Необходимо сложить их побайтово в буферный массив и отправить в воздух. Оформил это дело в структуру и при попытке записи ее в буфер, 7 студия выдает ворнинг и мессагу, при чем - через раз. Бывает, что и спокойно откомпилирует. Как это дело побороть, подскажите пожалуйста.

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

struct payload_t{
	uint8_t a;
	uint32_t b;
	int16_t c;
	uint8_t d;
	uint8_t e;
	uint8_t f;
} payload;

//************
void tx_data(){
	TX_send(&payload, sizeof(payload));
	...
}

//************
void TX_send(uint8_t* buf, uint8_t len){
	...
	_write(W_TX_PAYLOAD, buf, len);
	...
}
Message expected 'uint8_t *' but argument is of type 'struct payload_t *'
Warning passing argument 1 of 'TX_send' from incompatible pointer type
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Привести аргумент к типу, который требует функция TX_send:

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

TX_send((uint8_t*)&payload, sizeof(payload));
Либо объявить эту функцию иначе, подразумевая, что в неё может быть передан любой тип указателя:

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

void TX_send(void* buf, uint8_t len);
Контактная информация:
Опытный кот
Сообщения: 768
Зарегистрирован: Вс янв 19, 2014 00:55:09

Сообщение MOHCTEP »

WiseLord, Спасибо! Ваш 1 вариант убрал "ругань". Не пойму никак сакральную суть этих указателей...
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Функция ожидает указатель на беззнаковый байт, а Вы подсовываете её указатель на структуру. Хотя по сути значение обоих этих указателей (адрес) одно и то же, но для C это разные типы данных.

Почему это важно... ну, например, если для указателя p сделать p++ (увеличить адрес), то если это указатель на uint8_t, то получится прыжок на 1 байт, а для указателя на структуру выйдет прыжок на размер структуры.
Контактная информация:
Ответить

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