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

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить
Друг Кота
Сообщения: 12867
Зарегистрирован: Сб дек 18, 2021 19:25:32

Сообщение Martian »

как - это Вы уже написали. Где - в каждом случае switch.

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

case 0:
   PORTD = (unsigned char)(~(SEGMENTE[display % 1000/100])); // Выводим первый разряд
   if (display < 10) { // или 100, 1000...
     PORTD |= 0x80; //и добавляем десятичную точку если число меньше 10
   }
   break;
только вот с display % 1000/100 разберитесь, это выглядит странно. И не факт, что оптимизатор не упростит операции с равным приоритетом до display % 10

посмотрите на div_t и div()
Контактная информация:
Реклама
Родился
Сообщения: 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;
}
Реклама
Друг Кота
Сообщения: 12867
Зарегистрирован: Сб дек 18, 2021 19:25:32

Сообщение Martian »

Вы просто вставили мой пример во все случаи, не изменив? Забавно. А мне казалось, совершенно понятно, что он делает, и что более доступно быть не может...
Простой вопрос: если display = 9, в каких разрядах условие if (display < 10) не выполнится?
lord99 писал(а):Может нужен float для переменной?
Может быть. А может, double. Вы же программу пишите, Вам виднее, что у Вас там хранится и с какой точностью и какими ресурсами готовы пожертвовать... Но я бы в данном случае не тип переменной выбирал, а книжку по программированию.
Контактная информация:
Родился
Сообщения: 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 КБ) 48 скачиваний
Реклама
Эиком - электронные компоненты и радиодетали
Друг Кота
Сообщения: 12867
Зарегистрирован: Сб дек 18, 2021 19:25:32

Сообщение Martian »

lord99 писал(а):Если display=9, то условие выполнится во всех разрядах (см. скрин)
Вот именно. Вам же это не нужно?
Давайте поэтапно.
Необходимо определить, как будет отображаться число.
Есть несколько вариантов, опишу три (но их больше):
1. Точка всегда фиксированная, стоит в каком-то из разрядов. Например, есть три разряда (максимальное число 999), допустим, во втором всегда стоит точка. Тогда максимальное число - 99.9, и тут делать ничего не надо, просто добавляем во втором разряде свечение точки. Именно подобный способ использовался в примере, который взят за основу.
2. Точка не фиксирована, но после неё фиксированное число знаков. То есть, можно отобразить числа 1.0, 99.2, но нельзя 1.02 и т. д. Если оговорить, что число выравнивается вправо, то это станет вариант 1.
3. Точка не фиксирована, но после неё отображается столько знаков, сколько влезет. Чем это отличается от второго варианта? Тем, что число 9.489 во втором варианте отобразится как 9.4 или 9.5 в зависимости от выбранного варианта округления, а в третьем - как 9.48, если мы добавим 1, то 10.4, если добавим ещё 100, то 110. Если нули не отображать и выравнивание вправо, то у чисел 9.0000 и 110.489 точка стоит в одном и том же разряде, так как они отобразятся как 9. и 100.

Как должно отображаться число у Вас?
Контактная информация:
Реклама
Друг Кота
Аватара пользователя
Сообщения: 25400
Зарегистрирован: Чт янв 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 КБ) 57 скачиваний
Друг Кота
Сообщения: 12867
Зарегистрирован: Сб дек 18, 2021 19:25:32

Сообщение Martian »

Я посмотрел исходный код, и возникла пара замечаний:
1). Это не связано напрямую с отображением на дисплее, но всё же: среднее арифметическое значение АЦП это не очень правильно. Например, измеряем 250 раз (именно столько в коде) напряжение 4 В. 240 раз выдало 4, а 10 раз было по каким-то причинам 0. Нам очевидно, что 0 - неверные значения, и их надо игнорировать. Но в итоге программа выдаст 3.84. Устраивает такая погрешность?
2). В коде обработки данных АЦП есть такой комментарий:
/* Вычисляем среднее значение АЦП, вольты переводим в милливольты умножением на 100,а не на 1000.
Из-за расположения точки в индикаторе. */
Это означает, что автор кода что-то такое напридумывал, что не оглядываясь на это, нельзя что-либо менять в дисплейной части. Особенно расположение точки :)
Контактная информация:
Родился
Сообщения: 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 почти совпадало.
Друг Кота
Сообщения: 12867
Зарегистрирован: Сб дек 18, 2021 19:25:32

Сообщение Martian »

lord99 писал(а): каким образом было сделано измерение?
никаким, я просто предположил подобную ситуацию, для наглядности, что даже при 250 выборках небольшое количество ложных данных сильно влияет на среднее арифметическое.
lord99 писал(а):как нужно? -другая формула?
ну, хотя бы так: http://we.easyelectronics.ru/Theory/che ... filtr.html в комментариях там есть отсылки к более серьёзной литературе.
Контактная информация:
OKF
Это не хвост, это антенна
Сообщения: 1407
Зарегистрирован: Вт июн 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 КБ) 50 скачиваний
test.hex
ВОЛЬТМЕТР с LCD 1602
(11.96 КБ) 46 скачиваний
Мудрый кот
Сообщения: 1735
Зарегистрирован: Вт авг 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". И адекватный оптимизатор не станет такого делать.
Друг Кота
Сообщения: 12867
Зарегистрирован: Сб дек 18, 2021 19:25:32

Сообщение Martian »

Если требуется определённый порядок выполнения операций с равным приоритетом, то используют скобки. Знаете такие символы ()? Дичь - это писать без них. А оптимизатор легко упростит, если захочет, потому что ему абсолютно похер, что это программист решил какую-то цифру в числе выделить. Только не до %10, это уже я ошибся, а до %100000 (или сколько там нулей получается...)
Это я ещё не говорю о том, что если спросить про приоритеты, то что про них расскажут начинающие...
Контактная информация:
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18678
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

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

Мой уютный бложик... заходите!
Контактная информация:
Мудрый кот
Сообщения: 1735
Зарегистрирован: Вт авг 15, 2017 10:51:13

Сообщение jcxz »

[uquote="Martian",url="/forum/viewtopic.php?p=4542069#p4542069"]Если требуется определённый порядок выполнения операций с равным приоритетом, то используют скобки. Знаете такие символы ()? Дичь - это писать без них. А оптимизатор легко упростит, если захочет, потому что ему абсолютно похер, что это программист решил какую-то цифру в числе выделить.[/uquote]Опять бред несёте... Вам бы учебник по си почитать что-ли? Который сами же рекомендовали выше. 8)
Язык си чётко регламентирует как приоритеты операций, так и направление их выполнения на разных уровнях приоритета.
В выражении display % 1000 /100 все операции имеют одинаковый приоритет и направление выполнения - слева направо. И никаких оптимизаций вменяемый оптимизатор здесь не сделает.

А скобки где ни попадя, городят только неумехи, не сумевшие прочитать и усвоить порядок приоритета и направление операций.
Друг Кота
Сообщения: 12867
Зарегистрирован: Сб дек 18, 2021 19:25:32

Сообщение Martian »

Сочувствую.
Контактная информация:
Мудрый кот
Сообщения: 1735
Зарегистрирован: Вт авг 15, 2017 10:51:13

Сообщение jcxz »

[uquote="ARV",url="/forum/viewtopic.php?p=4542094#p4542094"]Приоритет должен быть один: писать так, чтобы понял даже дебил. Поэтому скобок жалеть не стоит[/uquote]Ну если пишете для дебила. Но обычно программист пишет для себя. Чтобы самому потом можно было прочитать и разобраться.
Так что - если вы пишете в расчёте на дебила при том что читать это будете сами, то..... печалька :)))
Друг Кота
Сообщения: 12867
Зарегистрирован: Сб дек 18, 2021 19:25:32

Сообщение Martian »

я бы тебе мог кучу примеров привести, где ты задолбаешься вспоминать приоритеты, но ты же поступишь нечестно, полезешь в гугл смотреть, поэтому, оставайся в своём заблуждении, "пишущий для себя".
Контактная информация:
Мудрый кот
Сообщения: 1735
Зарегистрирован: Вт авг 15, 2017 10:51:13

Сообщение jcxz »

[uquote="Martian",url="/forum/viewtopic.php?p=4542103#p4542103"]я бы тебе мог кучу примеров привести, где ты задолбаешься вспоминать приоритеты, но ты же поступишь нечестно, полезешь в гугл смотреть, поэтому, оставайся в своём заблуждении, "пишущий для себя".[/uquote]Я могу согласиться, что иногда скобки (даже если они реально не нужны) полезно поставить если выражение очень сложное, громоздкое и визуально трудно воспринимается. Но лепить их в простейшем выражении из всего двух элементарных операций... - это, имхо, верх маразма. :dont_know:
Ответить

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