Здравствуйте!
есть измеритель выполнены на atmega8.В перспективе измеритель температуры до 500 градусов .
Опорное значение напряжения для ADC - 5 вольт .
функция sprintf используется со спецификатором -"d" , т е работаем с целыми числами (без запятой).
Суть проблемы такова:
Если измеряемое значение напряжения (от 0-до5в) изменять то на дисплее периодически выводятся абсурдные значения (но не всегда), значительно больше максимального значения для 10 бит- 1023 .
Но вот если не крутить подстроечник и не изменять значение напряжения на входе , то на дисплее отображаются правильные значения .
следует отметить .
Что в протеусе , что на макете работают аналогично , т е проблема в прошивке .
исходник:
/* -
для AVR studio6
Проект = простой вольтметр на атмега 8 . конфигурация LCD прям в теле основного листинга , без отдельного хедера для 4 битной шины обмена с дисплеем .
*/
Раздел: AVR
есть измеритель выполнены на 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);
}
}
Раздел: AVR