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

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить
Друг Кота
Аватара пользователя
Сообщения: 7382
Зарегистрирован: Пт авг 28, 2009 21:34:30
Откуда: 845-й км.

Сообщение uldemir »

Это не спортивно... на stack overflow нашел такой топик:

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

#define mkstrX(s) #s
#define mkstr(s) mkstrX(s)
#define PROJECT "..\\" mkstr(ID) "_data_var.h"
Но...

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

#define I2C_DEV         "I2C" mkstr(I2C_DEV_NUM)
даёт фигню.. Оно годится для сгенерить строку, а не подсунуть что-то, что еще должно по дефайну раскрыться.
Реклама
Друг Кота
Аватара пользователя
Сообщения: 7382
Зарегистрирован: Пт авг 28, 2009 21:34:30
Откуда: 845-й км.

Сообщение uldemir »

Если бы всё было так просто...:

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

../i2c_drv2_emlib.c:49:25: error: 'I2CI2C_DEV_NUM_IRQn' undeclared (first use in this function)
   49 | #define I2C_IRQn        I2C##I2C_DEV_NUM##_IRQn
      |                         ^~~
../i2c_drv2_emlib.c:92:20: note: in expansion of macro 'I2C_IRQn'
   92 |   NVIC_SetPriority(I2C_IRQn, I2C_IRQ_PRI);
      |                    ^~~~~~~~
Оно внутри другого дефайна не раскрывает I2C_DEV_NUM
Реклама
Мудрый кот
Сообщения: 1838
Зарегистрирован: Вт авг 15, 2017 10:51:13

Сообщение jcxz »

[uquote="uldemir",url="/forum/viewtopic.php?p=4488953#p4488953"]#define I2C_DEV I2C ## I2C_DEV_NUM - не срабатывает[/uquote]У меня есть пачка макросов:

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

#define concatVOID
#define concat_SUBST2(a, b, c, d, e, f, g, h, i, j, k, l, ...) \
        a##b##c##d##e##f##g##h##i##j##k##l
#define concat_SUBST(...) concat_SUBST2(__VA_ARGS__)
#define concat(...) concat_SUBST(__VA_ARGS__, concatVOID, concatVOID, \
        concatVOID, concatVOID, concatVOID, concatVOID, concatVOID, concatVOID, \
        concatVOID, concatVOID, concatVOID, concatVOID, concatVOID, concatVOID)
Поэтому если бы мне нужно было, то сделал бы так:
#define I2C_DEV concat(I2C, I2C_DEV_NUM)

Если компилятор не поддерживает макросы с переменным числом аргументов, то можно сделать такие:

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

#define concatAB_(a, b) a##b
#define concatABC_(a, b, c) a##b##c
#define concatABCD_(a, b, c, d) a##b##c##d
#define concatABCDE_(a, b, c, d, e) a##b##c##d##e
#define concatABCDEF_(a, b, c, d, e, f) a##b##c##d##e##f
#define concatAB(a, b) concatAB_(a, b)
#define concatABC(a, b, c) concatABC_(a, b, c)
#define concatABCD(a, b, c, d) concatABCD_(a, b, c, d)
#define concatABCDE(a, b, c, d, e) concatABCDE_(a, b, c, d, e)
#define concatABCDEF(a, b, c, d, e, f) concatABCDEF_(a, b, c, d, e, f)
и тогда:
#define I2C_DEV concatAB(I2C, I2C_DEV_NUM)
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

Доброго времени суток.
Вопрос по IAR.
Вот синтаксис обработчика прерывания.

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

#pragma vector=vect_num
__interrupt void func(void){}
А какой синтаксис применить, чтобы повесить на несколько векторов один обработчик?
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Реклама
Эиком - электронные компоненты и радиодетали
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

Будете долго смеяться.

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

#pragma vector=vect_num1, vect_num2
__interrupt void func(void){}
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

VladislavS писал(а):Будете долго смеяться.
Не буду ни разу. Не сомневался, что должно быть просто. Интуитивно попробовал так,

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

#pragma vector=vect_num1
#pragma vector=vect_num2
__interrupt void func(void){}
Проект собрался, с ворнингом и не так :)

Ваш вариант самое то, даже в дизассемблере проверил )).
Спасибо. :beer:
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

Всем доброго времени суток.

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

struct example
{
    int a;
    int b;
    int c;
};
Чисто гипотетически, на уровне препроцессора, можно определить на каком месте по порядку в структуре находится какой-нибудь из ее элементов?
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Встал на лапы
Аватара пользователя
Сообщения: 145
Зарегистрирован: Пн апр 02, 2012 15:56:23

Сообщение azhel12 »

[uquote="Z_h_e",url="/forum/viewtopic.php?p=4531616#p4531616"]Всем доброго времени суток.
Чисто гипотетически, на уровне препроцессора, можно определить на каком месте по порядку в структуре находится какой-нибудь из ее элементов?[/uquote]

ЕМНИП в Си как минимум прямо в стандарте закреплено, что в порядке объявления, в C++ вроде нет, но это надо постараться найти компилятор, который их поменяет местами (стандартные GCC, Clang, MSVC так не делают).

Если нужна 100% гарантия, можно воспользоваться макросом offsetof, который позволяет вычислить смещение поля (ну а дальше сравнить их).
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

Порядок элементов компилятор сделает последовательным, однозначно.
azhel12 писал(а):можно воспользоваться макросом offsetof
попробую.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Родился
Сообщения: 16
Зарегистрирован: Пт апр 02, 2021 18:53:28

Сообщение lord99 »

Доброго времени суток. Подскажите где почитать, как сделать плавающую точку для 7 сегментного индикатора. Вот кусок кода где точка после первой цифры (например 9,05),
switch(seg_counter)
{
case 0:
PORTD = ~((SEGMENTE[display % 1000/100])|0x80); // Выводим второй разряд и добавляем десятичную точку
break;
case 1:
PORTD = ~(SEGMENTE[display % 100/10]); // Выводим второй разряд
break;
case 2:
PORTD = ~(SEGMENTE[display % 10]); // Выводим третий разряд
break;
}
if (seg_counter++ > 2) seg_counter = 0;
}
а нужно автоматом поставить после второй, когда будет более 9,99 , то есть 10,1
Родился
Сообщения: 16
Зарегистрирован: Пт апр 02, 2021 18:53:28

Сообщение lord99 »

[uquote="Martian",url="/forum/viewtopic.php?p=4540593#p4540593"]Вариантов решения несколько проще всего сравнить в каждом случае число, меньше ли оно 10[/uquote]
if(a>b) ... else ...? Но где и как?
Родился
Сообщения: 16
Зарегистрирован: Пт апр 02, 2021 18:53:28

Сообщение lord99 »

[uquote=""lord99",url="/forum/viewtopic.php?p=4540553#p4540553"]нужно поставить после второго сегмента, когда будет более 9,99 , то есть 10,1[/uquote]
Я дал не полную информацию, в коде фиксированная точка и для 4-х разрядного все как бы нормально (switch из четырех case ну и 9,99 сменяется на 10,01), а на 3-х разрядным (switch из трех case) после 9,99 сменяется например на 0, 01 то есть теряется десятичный знак.
[uquote="Martian",url="https://radiokot.ru/forum/ucp.php?i=pm&mode=compose&action=quotepost&sid=8e23c0da54a0c960a5390b7ec2756097&p=4540623"]в каждом случае switch[/uquote]
до 10- показания 999 без точки и сменяется на 001 (то же без точки), если более 10 вольт. Может нужен float для переменной? volatile unsigned int display = 0;
Спойлерswitch(seg_counter)
{
case 0:
PORTD = (unsigned char)(~(SEGMENTE[display % 1000/100]));
if (display < 10) {
PORTD |= 0x80;
}
break;
case 1:
PORTD = (unsigned char)(~(SEGMENTE[display % 100/10]));
if (display < 10) {
PORTD |= 0x80;
}
break;
case 2:
PORTD = (unsigned char)(~(SEGMENTE[display % 10]));
if (display < 10) {
PORTD |= 0x80;
}
break;
}
if (seg_counter++ > 2) seg_counter = 0;
}
Родился
Сообщения: 16
Зарегистрирован: Пт апр 02, 2021 18:53:28

Сообщение lord99 »

Был очень занят, с ответом задержался.
[uquote="Martian",url="/forum/viewtopic.php?p=4540842#p4540842"]Вы же программу пишите, Вам виднее,[/uquote]
Исходник не мой, я только начинаю учиться.[uquote="Martian",url="/forum/viewtopic.php?p=4540842#p4540842"]вопрос: если display = 9, в каких разрядах условие if (display < 10) не выполнится?[/uquote] Если display=9, то условие выполнится во всех разрядах (см. скрин)
СпойлерИзображение Изображение Изображение
Переключение диапазона с 9,99v на 10,1v точкой я сделал так
Спойлерswitch(seg_counter)
{
case 0:
PORTD = ~((SEGMENTE[display % 1000/100])); // Выводим первый разряд и добавляем десятичную точку
// PORTD = (unsigned char)(~(SEGMENTE[display % 1000/100])); //
if (display < 999) //
{
PORTD &= ~ 0x80; //
}
break;
case 1:
PORTD = ~(SEGMENTE[display % 100/10]); // Выводим второй разряд и переключаем десятичную точку на 2-й разряд
//PORTD = (unsigned char)(~(SEGMENTE[display % 100/10]));
if (display > 999)
{
PORTD &= ~ 0x80; //
}
break;
case 2:
// PORTD = (unsigned char)(~(SEGMENTE[display %10]));
PORTD = ~(SEGMENTE[display % 10]); // Выводим третий разряд
break;
}
if (seg_counter++ > 2) seg_counter = 0;
}
Точка разряда переключается, но показания не верные, при реальных U=10,23v на индикаторе 01,8v Если бы был сдвиг в право, получили бы 10,18v то есть 10,2v для 3-х разрядов (если проверять на индикаторе 4 разрядном).
СпойлерИзображение Изображение
В протеусе все видно.
Вложения
proteus.rar
(34.11 КБ) 59 скачиваний
Друг Кота
Аватара пользователя
Сообщения: 25862
Зарегистрирован: Чт янв 10, 2008 22:01:02
Откуда: Московская область, Фрязино

Сообщение КРАМ »

Добавлю проблему.
Плавающая точка на дисплее должна иметь гистерезис, то есть переключаться вверх и вниз с разными порогами. Иначе считать показания на границе переключений будет невозможно. Дисплей будет постоянно прыгать между двумя точками.
Родился
Сообщения: 16
Зарегистрирован: Пт апр 02, 2021 18:53:28

Сообщение lord99 »

[uquote="Martian",url="/forum/viewtopic.php?p=4541521#p4541521"]Как должно отображаться число у Вас?[/uquote]
с 1 вариантом (базовый вариант, от этого я хочу уйти) ставим точку где хотим и пользуемся не зависимо от количества разрядов. Недостаток в трех разрядном предел измерения до 9,99вольт и - измерение с точностью 0,01вольт, или измерение до 99,9вольт с точностью 0,1вольт (во всем диапазоне). В 4-х разрядном индикаторе предел и точность - измерение до 99,99вольт с точностью 0,01вольт.[uquote="Martian",url="/forum/viewtopic.php?p=4541521#p4541521"]Давайте поэтапно. Есть несколько вариантов[/uquote] Я может не правильно себе представляю, что значит точка не фиксирована. Чтобы использовать индикатор с меньшим размером (берем 3разряда) и измеряем до 10 вольт будет с точностью 0,01вольт. После 9,99вольт пусть точка сместится в право на 1 разряд, как я и сделал с помощью оператора switch. Вариант 2 или 3 не могу выбрать, потому, что так глубоко не изучал это и не хватает знаний. Думаю что мне больше подходит Вариант 3, вот как в китайском вольтамперметре измерение напряжений до 9,99вольт и переключение точки после этого на 10,0вольт.
Вложения
main.c
Чтоб было яснее, вот что есть на данный момент.
(3.61 КБ) 65 скачиваний
Родился
Сообщения: 16
Зарегистрирован: Пт апр 02, 2021 18:53:28

Сообщение lord99 »

[uquote="Martian",url="/forum/viewtopic.php?p=4541769#p4541769"]пара замечаний:
1).Например, измеряем 250 раз (именно столько в коде) напряжение 4 В. 240 раз выдало 4, а 10 раз было по каким-то причинам 0. Нам очевидно, что 0 - неверные значения, и их надо игнорировать. Но в итоге программа выдаст 3.84. Устраивает такая погрешность?[/uquote]Да, действительно это много, получается 4%. Стесняюсь спросить, каким образом было сделано измерение? вы изменили настройки T2, или используете стороннее приложение, чтоб так на лету задавать количество измерений? Поведайте первокласнику в изучении, я то же так хочу.
2).В комментариях к оригиналу проекта был вопрос почему на 100, а не на 1000, я просто этот комментарий вставил в этот исходник и переписал код под CV.
[uquote="Martian",url="/forum/viewtopic.php?p=4541769#p4541769"]среднее арифметическое значение АЦП это не очень правильно.[/uquote]Это "первая проба пера", как нужно? -другая формула? Не много баловался с arduino ide, в одном из скетч как зарядка для акк, делалось 2 измерения, одно 1ms
Спойлер// Измерение UAK, длительность 1мс
float readU0() {
long U1 = 0; //Напряжение на АКБ
float result = 0.0;
float V1 = 0.0;
float K0 = 0.0030324; // pro mini (12.69) UAK 9,01,24
delayMicroseconds(100);
for (int j = 1; j <= 8; j++)
{
U1 += analogRead(A0);
}
V1 = U1 * K0;
result = V1;
return result;
}
другое 100ms
Спойлер// Измерение UAK 128, длительность 100мс
float readU016() {
long U1 = 0; //Напряжение на АКБ
float result = 0.0;
float V1 = 0.0;
float K1=0.00018951;//это Pro mini (12.73>>12.69) UK
delay(86);
for (int j = 1; j <= 128; j++)
{
U1 += analogRead(A0);
}
V1 = U1 * K1;
result = V1;
return result;
}
Погрешность была не знаю какая, ну с мультметром и Lcd 1602 почти совпадало.
OKF
Это не хвост, это антенна
Сообщения: 1452
Зарегистрирован: Вт июн 07, 2011 08:03:18

Сообщение OKF »

[uquote="КРАМ",url="/forum/viewtopic.php?p=4541633#p4541633"]Плавающая точка на дисплее должна иметь гистерезис, то есть переключаться вверх и вниз с разными порогами. Иначе считать показания на границе переключений будет невозможно.[/uquote]
Это касается не только точки. При (относительно) частом обновлении показания дисплея могут раздражать. Хотя, некоторым даже нравятся подобные "переливы".)
Родился
Сообщения: 16
Зарегистрирован: Пт апр 02, 2021 18:53:28

Сообщение lord99 »

[uquote="КРАМ",url="/forum/viewtopic.php?p=4541633#p4541633"]При (относительно) частом обновлении показания дисплея могут раздражать.[/uquote]Ваша правда, вот если говорить за этот проект, то в протеусе "бегает" последний разряд (к примеру 4,21v-4,23v) и на реальном железе так будет? А другой подход в проекте с дисплеем на Lcd, показания как вкопанные стоят. С не фиксированной точкой вопрос остался.
[uquote="Martian",url="/forum/viewtopic.php?p=4541633#p4541633"]я просто предположил подобную ситуацию, для наглядности, что даже при 250 выборках небольшое количество ложных данных сильно влияет на среднее арифметическое.[/uquote]Мне попадалось сообщение, человек в протеусе видел и считал эти выборки, правой кн.контекстное меню по мк/ConfigureDiagnostics/ADC modules/debug/ok но я не разобрался в цифрах результатов.
Вложения
test.rar
proteus
(28.64 КБ) 58 скачиваний
test.hex
ВОЛЬТМЕТР с LCD 1602
(11.96 КБ) 54 скачивания
Мудрый кот
Сообщения: 1838
Зарегистрирован: Вт авг 15, 2017 10:51:13

Сообщение jcxz »

[uquote="Martian",url="/forum/viewtopic.php?p=4540623#p4540623"]только вот с display % 1000/100 разберитесь, это выглядит странно. И не факт, что оптимизатор не упростит операции с равным приоритетом до display % 10[/uquote]Что именно "странно"? Обычное выражение. Пусть и не самое оптимальное. Выделение значения 2-й цифры display.
И с чего оптимизатор должен делать такую дичь??? "%1000/100" не эквивалентно "/10". И адекватный оптимизатор не станет такого делать.
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18787
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

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

Мой уютный бложик... заходите!
Контактная информация:
Ответить

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