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

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить
Друг Кота
Аватара пользователя
Сообщения: 3832
Зарегистрирован: Сб сен 10, 2011 17:46:25

Сообщение oleg110592 »

[uquote="Shuspano",url="/forum/viewtopic.php?p=3841090#p3841090"]Не, так не компиляется[/uquote]
так норм.
Изображение
Реклама
Грызет канифоль
Аватара пользователя
Сообщения: 275
Зарегистрирован: Вс окт 20, 2019 13:03:56

Сообщение Shuspano »

В общем, это сделать невозможно. Как только не пробовал, засыпает ошибками. Потому, буду использовать первоначальный рабочий вариант.
Простых понятных примеров рабочего прогмема класса хеллворлд найти не могу, везде либо простынки где непонятно что к чему, либо еще менее понятные какие-то двухкоординатные char[j]
Хочу допилить и сделать покрасивше подпрограммы для индикатора. В связи с тем вопрос: а как ставить и снимать биты в unsigned char в одной строке одновременно?
Реклама
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

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

a |= (1<3); // установить бит 3 переменной a
a &= ~(1<<3); // очистить бит 3 переменной a
Ну или макрос _BV есть
Контактная информация:
Грызет канифоль
Аватара пользователя
Сообщения: 275
Зарегистрирован: Вс окт 20, 2019 13:03:56

Сообщение Shuspano »

Так я знаю. Но вроде как можно в одну строку... или нет?
Реклама
Эиком - электронные компоненты и радиодетали
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

А чем это не в одну строку? Или нужно и то и другое сразу? Если так, то можно тое накрутить каким-нибудь макросом, но стандартного простого способа вроде как нет.

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

a = (a | ((1<<2) | (1<<0))) & ~((1<<4) | (1<<1));
Контактная информация:
Реклама
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Сообщение NStorm »

Нуу.... проще и нагляднее в 2 строки написать, если не все биты меняются. А то получается хрень, вроде такой:

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

a = (a | (1 << 0)) & (a & ~(1 << 1));
Добавлено after 4 minutes 39 seconds:
А, ну да, WiseLord правильнее написал, у меня лишний шаг И.
Реклама
Друг Кота
Аватара пользователя
Сообщения: 3386
Зарегистрирован: Пн окт 11, 2010 19:00:08

Сообщение Мурик »

NStorm писал(а):Нуу.... проще и нагляднее в 2 строки написать

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

a = (a | (1 << 0)) 
  & (a & ~(1 << 1));
Так нагляднее, а с точки зрения компилятора это одна строка.
Модератор
Аватара пользователя
Сообщения: 4618
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

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

[uquote="Shuspano",url="/forum/viewtopic.php?p=3841172#p3841172"]Но вроде как можно в одну строку...[/uquote]

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

a |= (1<3); a &= ~(1<<3);
:)
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

Господа, не забыаайте, что вы с AVR имеете дело. При работе с портами такие директивы компилятор в CBI и SBI транслирует. Одним выражением (не строкой конечно же, тут вас Аlex круто подколол) будет "чтение - модификация - запись".
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Сообщение NStorm »

При работе с портами такие директивы компилятор в CBI и SBI транслирует
Только если будет меняться всего 1 бит. Если больше 1го, всё-равно будет R-M-W с OR/AND.
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18787
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

[uquote="Shuspano",url="/forum/viewtopic.php?p=3841172#p3841172"]Так я знаю. Но вроде как можно в одну строку... или нет?[/uquote]
В Си нет прямой связи между количеством строк и чем-то ещё, размером кода, например, или скоростью его исполнения. Зато часто прослеживается связь "меньше строк - менее понятно - больше вероятность ошибки".

Добавлено after 2 minutes 14 seconds:
[uquote="NStorm",url="/forum/viewtopic.php?p=3841259#p3841259"]Только если будет меняться всего 1 бит. Если больше 1го, всё-равно будет R-M-W с OR/AND.[/uquote]так вроде и SBI тоже RMW... Или я путаю?
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Сообщение NStorm »

Не, SBI/CBI - одна инструкция на асме.
Зато часто прослеживается связь "меньше строк - менее понятно - больше вероятность ошибки".
Ну это имеет смысл, если по какой-то причине установку и снятие бита надо проводить атомарно, при этом не весь регистр писать. За всё время в реальности ни разу такой необходимости не встречал...
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18787
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

Имхо, с атомарностью многострочность никак не связана.

А SBI, если я не ошибаюсь (давно асм в руки брал), инструкция одна, но работает именно в три этапа со всеми побочными эффектами.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Собутыльник Кота
Аватара пользователя
Сообщения: 2723
Зарегистрирован: Пт сен 07, 2018 20:20:02
Откуда: деревня в Тульской губернии

Сообщение ПростоНуб »

ARV, связана. Если a объявлена volatile, то для этих примеров компилятор сформирует разный код.

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

a = (a | ((1<<2) | (1<<0))) & ~((1<<4) | (1<<1));

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

a |= ((1<<2) | (1<<0));
a &= ~((1<<4) | (1<<1));
А если не volatile, то, скоре всего, код сфорируется одинаковый.
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Сообщение NStorm »

Нет там никаких 3х этапов, путаете что-то.
И конечно не совсем атомарно, будет всё-равно RMW, при этом M в 2 операции - AND, OR. Но запись будет именно в 1 операцию уже.
Грызет канифоль
Аватара пользователя
Сообщения: 275
Зарегистрирован: Вс окт 20, 2019 13:03:56

Сообщение Shuspano »

А вот такой вопросик. Как узнать длину строки в такой конструкции, не считая это вручную:

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

const __flash char lcd_data[] = "строка";
В ассемблере, транслятор может посчитать расстояние между метками, которыми ограничена строка, и так можно узнать ее длину. А тут как это делается?
Собутыльник Кота
Аватара пользователя
Сообщения: 2723
Зарегистрирован: Пт сен 07, 2018 20:20:02
Откуда: деревня в Тульской губернии

Сообщение ПростоНуб »

Shuspano,

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

#define MY_STRING "строка"
#define MY_STRING_LEN sizeof(MY_STRING)

const __flash char lcd_data[] = MY_STRING;
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Сообщение NStorm »

Shuspano, просто sizeof(lcd_data) тоже будет работать.

Добавлено after 2 minutes 13 seconds:
Только ес-но реальный размер, с учетом терминирующего \0 в конца:

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

volatile uint8_t a = 1;
const __flash char lcd_data[] = "stroka";

int main() {
  a = sizeof(lcd_data);
  56:   87 e0           ldi     r24, 0x07       ; 7
  58:   80 93 60 00     sts     0x0060, r24     ; 0x800060 <__data_start>
Возвращает 7 байт (stroka + \0). Если надо именно длину текста посчитать - sizeof() - 1 :)

Добавлено after 1 minute 8 seconds:
Ну и кодировку учитывайте при кириллице. Если вдруг в utf-8 запишите, будет 13 байт соотв, по 2 байта на символ.
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18787
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

ПростоНуб писал(а):связана
я сказал "напрямую", т.е. невозможно заранее предсказать, какой именно код получится от 1, 2 или 3 строчной записи одного и того же действия. например, в случае не-volatile может и 100500 строк превратиться в одну команду :)))
NStorm писал(а):Нет там никаких 3х этапов, путаете что-то.
не поленился, поднял документы... ошибаетесь вы:
Изображение
Shuspano писал(а):Как узнать длину строки в такой конструкции, не считая это вручную:
в конкретно вашем примере, как вам посоветовали, через sizeof. но вообще-то для этого есть в модуле avr/pgmspace.h специальная функция strlen_P, которая вычислит длину любой строки в памяти программ.
Вложения
screenshot-file2.dzsc.com-2020.05.png
(64.35 КБ) 484 скачивания
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Сообщение NStorm »

ARV, это не о том. Полностью же написано всё. Речь идет о том, что в Status Flags нельзя с помощью инструкций CBI/SBI записать, т.к. они работают только с регистрами с 0х00 по 0х1F. Поэтому чтобы записать в Status Flags будет операция RMW - считается Status в один из этих регистров, затем он меняется с помощью CBI/SBI и записывается назад. Если будете менять регистр с 0x00 по 0x1F - он поменяется напрямую SBI/CBI атомарно и в одну операцию (которая 2 такта Fclk выполняется).

EDIT: Тут выше я уже сам запутался и не так перевел. Действительно, в некоторых старых AVR возможно эти инструкции так криво работали. В новых - неактуально, ниже в комментарии описал.
Последний раз редактировалось NStorm Чт май 14, 2020 18:33:14, всего редактировалось 1 раз.
Ответить

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