Перейти к содержанию

Printf Периодически Возвращает Некорректное Значение


SMACK

Рекомендуемые сообщения

Здравствуйте!

есть измеритель выполнены на atmega8.В перспективе измеритель температуры до 500 градусов .

Опорное значение напряжения для ADC - 5 вольт .

функция sprintf используется со спецификатором -"d" , т е работаем с целыми числами (без запятой).

Суть проблемы такова:

Если измеряемое значение напряжения (от 0-до5в) изменять то на дисплее периодически выводятся абсурдные значения (но не всегда), значительно больше максимального значения для 10 бит- 1023 .

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

следует отметить .

Что в протеусе , что на макете работают аналогично , т е проблема в прошивке .

исходник:

/* -

для AVR studio6

Проект = простой вольтметр на атмега 8 . конфигурация LCD прям в теле основного листинга , без отдельного хедера для 4 битной шины обмена с дисплеем .

*/

#define F_CPU 1000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <stdio.h>
#include <math.h>

#define LCD_E_SET PORTD|= (1<<1)  // установка лог. «1? на линии E
#define LCD_E_CLR PORTD&=~(1<<1) // установка лог. «0? на линии E
#define LCD_RS_SET PORTD|= (1<<0) //установка лог. «1? на линии RS
#define LCD_RS_CLR PORTD&=~(1<<0) // установка лог. «0? на линии RS

#define LCD_COMMAND 0 // макрос, указывающий функции, что передаются команды
#define LCD_DATA 1 // макрос, указывающий функции, что передаются данные

void init_port()//инициализация порта, подключенного  к жки
{
DDRD=0xFF;
PORTD=0x00;
}

void lcd_putnibble(char t) //функция передачи тетрады в жки
{
t<<=4;  // сдвиг в лево (пример) 0b0101 1100<<4 = 0b1100 0000
LCD_E_SET; // установка лог. «1? на линии E
_delay_us(50);
PORTD&=0x0F; // стираем прошлую половинку байта
PORTD|=t;		   // рисуем половинку байта на порте С
LCD_E_CLR;  // установка лог. «0? на линии E
_delay_us(50);
}

/* функция передачи байта в жки.
char c — сам байт
char rs — переменная, указывающая что передается:
rs = 0 — команда (устанавливается линия RS)
rs = 1 — данные (сбрасывается линия RS) */
void lcd_putbyte(char c, char rs)
{
char highc=0; //переменная для хранения старшой части байта
highc=c>>4; //заносим старшую часть байта в преременную
if (rs==LCD_COMMAND) LCD_RS_CLR; //определяем что перередаем данные или команду
else LCD_RS_SET;
lcd_putnibble(highc);
lcd_putnibble©;
}

void lcd_putchar(char c) // то же самое что и lcd_putbyte (почти)
{
char highc=0;
highc=c>>4;
LCD_RS_SET;
lcd_putnibble(highc);
lcd_putnibble©;
}

void lcd_init() //функция инициализации ЖКИ
{
_delay_ms(15);   //ждем 15мс после подачи питания на жки.
lcd_putnibble(0b00000011); //0b00000011<<4 = 0b00110000 (выбор 8битного режима)
_delay_ms(4);
lcd_putnibble(0b00000011); //0b00000011<<4 = 0b00110000 (выбор 8битного режима)
_delay_us(100);
lcd_putnibble(0b00000011); //0b00000011<<4 = 0b00110000 (выбор 8битного режима)
_delay_ms(1);
lcd_putnibble(0b00000010); //0b00000011<<4 = 0b00100000 (выбор 4битного режима)
_delay_ms(1);
lcd_putbyte(0x28, LCD_COMMAND); //0b00101000 (4 битный режим+подкл 2ую строку)
_delay_ms(1);
lcd_putbyte(0x0C, LCD_COMMAND); //0b00001100 (включаем изображение)
_delay_ms(1);
lcd_putbyte(0x06, LCD_COMMAND); //0b00000110 (смещение курсора влево)
_delay_ms(1);
}

void lcd_clear() // функция очистки дисплея и возврата курсора в начальную позицию
{
lcd_putbyte(0x01, LCD_COMMAND);
_delay_us(1500);
}

/* функция перемещения курсора в заданную позицию
col — номер знакоместа по горизонтальной оси (от 0 до 15)
row — номер строки (0 или 1) */
void lcd_gotoxy(char col, char row)
{
char adr;
adr=0x40*row+col;
adr|=0x80;
lcd_putbyte(adr, LCD_COMMAND);
}

void lcd_putstring (char stroka[]) //функция рисовать строки на ЖКИ
{ char unsigned i;
for(i=0;stroka[i]!=0;i++)
lcd_putchar(stroka[i]);
}

void init_adc()
{
ADMUX = 0b01000000; //выбираем источник питания АЦП
ADCSRA|=(1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);// устанавливаем предделитель
ADCSRA|=(1 << ADEN);// Включаем АЦП

}

// Функция запуска преобразования АЦП и чтения результата
unsigned int read_adc(unsigned char adc_input)
{
ADMUX|=0x0E&adc_input; //определяем на какой ножке измеряем V
_delay_us(10); // Задержка на установление опорного напряжения
ADCSRA |= (1 << ADSC); // Запуск преобразования АЦП
while ((ADCSRA & (1 << ADIF))==0);// Ожидание окончания преобразования
return ADCW;
}

int main(void)
{
init_adc();// инициализируем АЦП
init_port();// инициализируем порт ЖКИ
lcd_init();// инициализируем ЖКИ

char buf[3]; //хранение строки для ЖКИ
while(1)

{
lcd_gotoxy(0,0);//перемещаем курсор в верхний левый угол
sprintf(buf,"%d",read_adc(0));/*конвертируем результат в масив buf, - из интересных строк в ней мы пишем , что и как выводим -
sprintf(buf,«%.2fV»,read_adc(0)*0.004883);//
lcd_putstring(buf);//выводим строку хранимую в buf
lcd_gotoxy(10,0);  //перемещаем курсор на координаты 1.3
lcd_putstring("Volts"); //
_delay_ms(200);//частота обновления информации
ADCSRA|=(1<<4);//сбрасываем в 0(ADIF) преобразование завершено(сбрасывается записью сюда 1цы), сбрасываем его принудительно ! (если бы мы использовали обработчик прерывания преобразование завершено - он бы сбросился аппаратно). Сбрасываем его для того чтоб после окончания следующего цикла преобразования знать что цикл завершен и можно считать результат.
_delay_ms(200);

}
}

post-11348-0-97525800-1398009328_thumb.jpg

post-11348-0-30906800-1398009348_thumb.jpg

Изменено пользователем SMACK
Ссылка на комментарий
Поделиться на другие сайты

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

Есть мнение что ты пишешь поверх предыдущего результата без очистки. Т.е. на втором скрине тройка от показаний на первом скрине.

ЗЫ. Кнопочка "code" в окне ответа делает код красивым и более читаемым.

Изменено пользователем marinovsoft
Ссылка на комментарий
Поделиться на другие сайты

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

Есть мнение что ты пишешь поверх предыдущего результата без очистки. Т.е. на втором скрине тройка от показаний на первом скрине.

ЗЫ. Кнопочка "code" в окне ответа делает код красивым и более читаемым.

Идея верная ! уже ее попробовал подключая внутри цикла функцию lcd_clear() .Но вот , что мне в таком решении не нравится - мерцать начинает , при этом просто уменьшая время _delay_ms ее не решает .

Может подскажете как побыстрей дисплей очистить ?

Ссылка на комментарий
Поделиться на другие сайты

Выбираем схему BMS для корректной работы литий-железофосфатных (LiFePO4) аккумуляторов

 Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ, также как и для других, очень важен контроль процесса заряда и разряда, а специализированных микросхем для этого вида аккумуляторов не так много. Инженеры КОМПЭЛ подготовили список имеющихся микросхем и возможных решений от разных производителей. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Когда у меня была подобная проблема, то просто фильтровал число, и на неактивный в данный момент сегмент выводил ' '. Пустое знакоместо. Проблема решалась.

Изменено пользователем zeconir

И пусть судьба не справедлива, Жизнь игра - играй красиво!

И что б не кикнули тебя, Не злить Админа, юзверя!

Люблю "спасибки" :)

Ссылка на комментарий
Поделиться на другие сайты

Может подскажете как побыстрей дисплей очистить ?

Не надо очищать, вполне достаточно покурить c format specifiers и сделать например так

sprintf(buf,"%4d",read_adc(0))

Ссылка на комментарий
Поделиться на другие сайты

Может подскажете как побыстрей дисплей очистить ?

Не надо очищать, вполне достаточно покурить c format specifiers и сделать например так

sprintf(buf,"%4d",read_adc(0))

Супер! Спасибо,в протеусе вроде работает замечательно!

Завтра попробую в живую .

Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
  • Сообщения

    • @Gomerchik а вы контролировали как меняется уровень сигнала на А1 ардуины?
    • Спасибо за совет. Автором данного проекта я не являюсь, мне нужно было воссоздать уличный датчик для метеостанции взамен пропавшего(( Из разного найденного в интернете этот проект работает с моей станцией Орегон (спасибо автору). В понедельник попробую последовать Вашему совету. Но все равно куча непоняток  как блин это работает)) Если дело в неправильной отправки команды, то как на это влияет подключение датчика температуры? Если совсем не подключать таймер, то передача идет один раз (как и прописано в программе), станция принимает и отображает, но минут через сколько-то естественно станция уже ни чего не показывает, но с таймером питание полностью не пропадает с ардуинки, но передача сигнала каким-то образом работает по таймеру.  В моем понимании данная команда подается один раз потому, что таймер должен отключать питание МК после передачи сигнала и каждые 43 сек снова подавать питание (так того требует станция).  Ардуино передает показания температуры отключается полностью и 43 секунды мк не работает.  Сейчас у меня питание пока сделано на подпитке от солнечной батареи, но пару пасмурных дней и аккумулятор съедается до отключения(
    • thickman Так и сделаю. Вытащу из бу БП.  Буду знать, как отличить. Благодарю. Заменил транзисторы на IRFB20N50K. Картина стала, совсем другой.  Похоже трудность не в драйвере, на момент подвозбуда, переходные процессы, в нем, завершены. Увеличил затворные резисторы до 50ом, стало немного лучше.  Не понятно, почему верхний ключ греется несколько сильнее. Возможно, стоит посмотреть ток в коллекторе.  Снабберные емкости временно удалил, изменений не произошло.  Замена ТГР на другой, на кольце MSTN-16A-TH, так же, результата не принесла.   irfb20n50k.pdf
    • А что нить из ассортимента активных щупов производства СССР..))
    • Типа такого: https://aliexpress.ru/item/2044864227.html?sku_id=58855020183
    • поняли неправильно. У ТЛ494 никакой защиты нет, усилители ошибки не защита, они не должны приводить к ложным импульсам. Причем тут "микруха" ?  надо нагружать ВСЁ. До сих пор вообще непонятно о каком ИИП идет речь и сколько у него каналов. Бесполезно схему рисовать? - Помогать так бесполезно. Картина кривая по самое "немогу" продолжаются картинки, снятые через ногу и без цены деления.
×
×
  • Создать...