как - это Вы уже написали. Где - в каждом случае switch.
Код:
case 0: PORTD = (unsigned char)(~(SEGMENTE[display % 1000/100])); // Выводим первый разряд if (display < 10) { // или 100, 1000... PORTD |= 0x80; //и добавляем десятичную точку если число меньше 10 } break;
только вот с display % 1000/100 разберитесь, это выглядит странно. И не факт, что оптимизатор не упростит операции с равным приоритетом до display % 10
нужно поставить после второго сегмента, когда будет более 9,99 , то есть 10,1
Я дал не полную информацию, в коде фиксированная точка и для 4-х разрядного все как бы нормально (switch из четырех case ну и 9,99 сменяется на 10,01), а на 3-х разрядным (switch из трех case) после 9,99 сменяется например на 0, 01 то есть теряется десятичный знак.
до 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; }
Вы просто вставили мой пример во все случаи, не изменив? Забавно. А мне казалось, совершенно понятно, что он делает, и что более доступно быть не может... Простой вопрос: если display = 9, в каких разрядах условие if (display < 10) не выполнится?
lord99 писал(а):
Может нужен float для переменной?
Может быть. А может, double. Вы же программу пишите, Вам виднее, что у Вас там хранится и с какой точностью и какими ресурсами готовы пожертвовать... Но я бы в данном случае не тип переменной выбирал, а книжку по программированию.
вопрос: если display = 9, в каких разрядах условие if (display < 10) не выполнится?
Если 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 разрядном).СпойлерВ протеусе все видно.
Если 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.
Добавлю проблему. Плавающая точка на дисплее должна иметь гистерезис, то есть переключаться вверх и вниз с разными порогами. Иначе считать показания на границе переключений будет невозможно. Дисплей будет постоянно прыгать между двумя точками.
с 1 вариантом (базовый вариант, от этого я хочу уйти) ставим точку где хотим и пользуемся не зависимо от количества разрядов. Недостаток в трех разрядном предел измерения до 9,99вольт и - измерение с точностью 0,01вольт, или измерение до 99,9вольт с точностью 0,1вольт (во всем диапазоне). В 4-х разрядном индикаторе предел и точность - измерение до 99,99вольт с точностью 0,01вольт.
Я может не правильно себе представляю, что значит точка не фиксирована. Чтобы использовать индикатор с меньшим размером (берем 3разряда) и измеряем до 10 вольт будет с точностью 0,01вольт. После 9,99вольт пусть точка сместится в право на 1 разряд, как я и сделал с помощью оператора switch. Вариант 2 или 3 не могу выбрать, потому, что так глубоко не изучал это и не хватает знаний. Думаю что мне больше подходит Вариант 3, вот как в китайском вольтамперметре измерение напряжений до 9,99вольт и переключение точки после этого на 10,0вольт.
Вложения:
Комментарий к файлу: Чтоб было яснее, вот что есть на данный момент. main.c [3.61 KiB]
Скачиваний: 46
Я посмотрел исходный код, и возникла пара замечаний: 1). Это не связано напрямую с отображением на дисплее, но всё же: среднее арифметическое значение АЦП это не очень правильно. Например, измеряем 250 раз (именно столько в коде) напряжение 4 В. 240 раз выдало 4, а 10 раз было по каким-то причинам 0. Нам очевидно, что 0 - неверные значения, и их надо игнорировать. Но в итоге программа выдаст 3.84. Устраивает такая погрешность? 2). В коде обработки данных АЦП есть такой комментарий: /* Вычисляем среднее значение АЦП, вольты переводим в милливольты умножением на 100,а не на 1000. Из-за расположения точки в индикаторе. */ Это означает, что автор кода что-то такое напридумывал, что не оглядываясь на это, нельзя что-либо менять в дисплейной части. Особенно расположение точки
пара замечаний: 1).Например, измеряем 250 раз (именно столько в коде) напряжение 4 В. 240 раз выдало 4, а 10 раз было по каким-то причинам 0. Нам очевидно, что 0 - неверные значения, и их надо игнорировать. Но в итоге программа выдаст 3.84. Устраивает такая погрешность?
Да, действительно это много, получается 4%. Стесняюсь спросить, каким образом было сделано измерение? вы изменили настройки T2, или используете стороннее приложение, чтоб так на лету задавать количество измерений? Поведайте первокласнику в изучении, я то же так хочу. 2).В комментариях к оригиналу проекта был вопрос почему на 100, а не на 1000, я просто этот комментарий вставил в этот исходник и переписал код под CV.
среднее арифметическое значение АЦП это не очень правильно.
Это "первая проба пера", как нужно? -другая формула? Не много баловался с 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 почти совпадало.
никаким, я просто предположил подобную ситуацию, для наглядности, что даже при 250 выборках небольшое количество ложных данных сильно влияет на среднее арифметическое.
Плавающая точка на дисплее должна иметь гистерезис, то есть переключаться вверх и вниз с разными порогами. Иначе считать показания на границе переключений будет невозможно.
Это касается не только точки. При (относительно) частом обновлении показания дисплея могут раздражать. Хотя, некоторым даже нравятся подобные "переливы".)
При (относительно) частом обновлении показания дисплея могут раздражать.
Ваша правда, вот если говорить за этот проект, то в протеусе "бегает" последний разряд (к примеру 4,21v-4,23v) и на реальном железе так будет? А другой подход в проекте с дисплеем на Lcd, показания как вкопанные стоят. С не фиксированной точкой вопрос остался.
я просто предположил подобную ситуацию, для наглядности, что даже при 250 выборках небольшое количество ложных данных сильно влияет на среднее арифметическое.
Мне попадалось сообщение, человек в протеусе видел и считал эти выборки, правой кн.контекстное меню по мк/ConfigureDiagnostics/ADC modules/debug/ok но я не разобрался в цифрах результатов.
Вложения:
Комментарий к файлу: proteus test.rar [28.64 KiB]
Скачиваний: 37
Комментарий к файлу: ВОЛЬТМЕТР с LCD 1602 test.hex [11.96 KiB]
Скачиваний: 31
только вот с display % 1000/100 разберитесь, это выглядит странно. И не факт, что оптимизатор не упростит операции с равным приоритетом до display % 10
Что именно "странно"? Обычное выражение. Пусть и не самое оптимальное. Выделение значения 2-й цифры display. И с чего оптимизатор должен делать такую дичь??? "%1000/100" не эквивалентно "/10". И адекватный оптимизатор не станет такого делать.
Если требуется определённый порядок выполнения операций с равным приоритетом, то используют скобки. Знаете такие символы ()? Дичь - это писать без них. А оптимизатор легко упростит, если захочет, потому что ему абсолютно похер, что это программист решил какую-то цифру в числе выделить. Только не до %10, это уже я ошибся, а до %100000 (или сколько там нулей получается...) Это я ещё не говорю о том, что если спросить про приоритеты, то что про них расскажут начинающие...
Если требуется определённый порядок выполнения операций с равным приоритетом, то используют скобки. Знаете такие символы ()? Дичь - это писать без них. А оптимизатор легко упростит, если захочет, потому что ему абсолютно похер, что это программист решил какую-то цифру в числе выделить.
Опять бред несёте... Вам бы учебник по си почитать что-ли? Который сами же рекомендовали выше. Язык си чётко регламентирует как приоритеты операций, так и направление их выполнения на разных уровнях приоритета. В выражении display % 1000 /100 все операции имеют одинаковый приоритет и направление выполнения - слева направо. И никаких оптимизаций вменяемый оптимизатор здесь не сделает.
А скобки где ни попадя, городят только неумехи, не сумевшие прочитать и усвоить порядок приоритета и направление операций.
Приоритет должен быть один: писать так, чтобы понял даже дебил. Поэтому скобок жалеть не стоит
Ну если пишете для дебила. Но обычно программист пишет для себя. Чтобы самому потом можно было прочитать и разобраться. Так что - если вы пишете в расчёте на дебила при том что читать это будете сами, то..... печалька
я бы тебе мог кучу примеров привести, где ты задолбаешься вспоминать приоритеты, но ты же поступишь нечестно, полезешь в гугл смотреть, поэтому, оставайся в своём заблуждении, "пишущий для себя".
я бы тебе мог кучу примеров привести, где ты задолбаешься вспоминать приоритеты, но ты же поступишь нечестно, полезешь в гугл смотреть, поэтому, оставайся в своём заблуждении, "пишущий для себя".
Я могу согласиться, что иногда скобки (даже если они реально не нужны) полезно поставить если выражение очень сложное, громоздкое и визуально трудно воспринимается. Но лепить их в простейшем выражении из всего двух элементарных операций... - это, имхо, верх маразма.
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 9
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения