Заранее извиняюсь, если не в тот раздел...
Давненько почитываю ваш форум, вот наконец-таки решился прописаться здесь. Сам я к вам с "соседнего" rcdesign.ru, ибо аз есм моделист, но паяльник люблю не меньше моделек
вобщем-то идея такая:
на 32й меге (пока, на ней прототипирование) сделано меню из N пунктов, меню перещелкивает кольцом по инкременту от п.1 до N от кнопки на прерывании INT2. в пункте 1 прописана функция чтения и записи АЦП на 2хстрочный ЖКИ 2х16. Проблема в следующем: хоть и ф-ия меню и чтения/записи в ЖКИ прописана в цикле while (1), у меня проц наотрез не хочет непрерывно читать. если прощелкать 3 раза (пройти по кругу), то уже можно увидить новое значение, кароче говоря не обновляется. Код прилагаю. Сам когда-то давно на сях рубился, сейчас все вспоминаю, так что не ругайте, местами он-таки кривоват.
Пишу под AVRStudio 5.0 GCC
Заранее благодарю!
- Код: Выделить всё
#include <avr/io.h>
#include <avr/interrupt.h>
#define RS 2 // RS - PORTC 2
#define E 3 // E - PORTC 3
unsigned char mode=0; // индекс меню
unsigned char flag=0; // флаг установки меню
unsigned int u; //показание ацп
void delay (unsigned long int a) // программа задержки
{
unsigned long int b;
for (b=a;b>0;b--);
}
void lcd_command (unsigned char lcd) // функция отправки командв в ЖКИ
{
unsigned char temp;
temp=(lcd&~(1<<RS))|(1<<E); // старшая тетрада
PORTC=temp;
asm ("nop");
PORTC=temp&~(1<<E);
temp=((lcd*16)&~(1<<RS))|(1<<E); // младшая тетрада
PORTC=temp;
asm ("nop");
PORTC=temp&~(1<<E);
delay (100);
}
void lcd_data (unsigned char lcd) // отправка данных в ЖКИ
{
unsigned char temp;
temp=lcd|(1<<RS)|(1<<E); // старшая тетрада
PORTC=temp;
asm ("nop");
PORTC=temp&~(1<<E);
temp=(lcd*16)|(1<<RS)|(1<<E); // младшая тетрада
PORTC=temp;
asm ("nop");
PORTC=temp&~(1<<E);
delay(100);
}
void lcd_init (void) // инициализация ЖКИ
{
lcd_command(0x2c);
delay (1000);
lcd_command(0x0c);
delay (1000);
lcd_command(0x01);
delay (1000);
}
void clean_lcd (void) // очистка ЖКИ
{
lcd_command(0x01);
}
ISR (INT2_vect) // обработчик прерывания по нажатию кнопки
{
if (mode++ == 2) mode=0; // инкремент индекса меню, если ==2, то сбрасываем в 0
flag=0; // разрешаем флаг записи
GIFR=0x00; // сбрасываем флаг прерывания
return;
}
unsigned int ADC_read (void) // чтение регисра АЦП
{
unsigned int v;
ADCSRA|=(1<<ADSC);
while ((ADCSRA&_BV(ADIF))==0x00);
v=(ADCL|ADCH<<8);
return v;
}
void write_adc (unsigned int u) // функция записи результата АЦП (пока)
{
lcd_command(0xC0); // перевод на 2ю строку
unsigned int j; // переменная
j=u/1000; // вычисляем тысячи
if (j==0)
{
lcd_data(' '); // если 0 то пришем пусто
}
else
{
lcd_data(0x30+j); // если нет, то 0+j
}
u=u-j*1000; // остаток сотен
j=u/100; // вычисляем...
lcd_data(0x30+j); // то же самое и так до едениц
u=u-j*100;
j=u/10;
lcd_data(0x30+j);
u=u-j*10;
j=u;
lcd_data(0x30+j);
}
void menu(void) // функция меню
{
if (mode==0) // если индекс == 0
{
if (flag==0) // и запись разрешена
{
clean_lcd(); // чистим ЖКИ
lcd_data('1'); // пишем "1."
lcd_data('.');
flag=1; // запрещяем инкремент индекса на всякий случай
write_adc(u); // пишем в 1м разделе меню рез-т АЦП
}
}
else
if (mode==1) // тоже самое, но п. "2."
{
if (flag==0)
{
clean_lcd();
lcd_data('2');
lcd_data('.');
flag=1;
}
}
else
if (mode==2) // тоже самое, но п. "3."
{
if (flag==0)
{
clean_lcd();
lcd_data('3');
lcd_data('.');
flag=1;
}
}
}
int main(void)
{
DDRB&=~(1<<2);
PORTB=0x04;
DDRC|=0xfc;
delay(3000);
lcd_init();
GICR|=(1<<INT2); // разрешить прерывания от INT2
ADCSRA=(1<<ADEN)|(1<<ADPS2)|(0<<ADPS1)|(1<<ADPS0); // ВКЛ АЦП
ADMUX=(1<<REFS1)|(1<<REFS0)|(0<<MUX0)|(0<<MUX1)|(0<<MUX2)|(0<<MUX3); // настраиваем АЦП...
sei();
while(1)
{
u=ADC_read(); // бесконечно преобразуем и пишем в меню
menu();
delay(6000);
}
}