Четверг, 25.04.2024, 07:08
Микроконтроллерная техника AVR
Главная Регистрация Вход
Приветствую Вас, Гость · RSS
[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 1 из 1
  • 1
Форум » Микроконтроллеры » Вопросы по МК » Помогите новичку. Atmega16 (Atmega16+таймер реального вреемни+вывод семисегментник)
Помогите новичку. Atmega16
Sany81Дата: Вторник, 29.06.2010, 14:03 | Сообщение # 1
Рядовой
Группа: Пользователи
Сообщений: 3
Репутация: 0
Статус: Offline
Добрый день.
Есть МК ATmega16, есть светодиодный индикатор 4 семисегментных символа(далее дисплей), подключеный через 2 регистра КР1533ИР24(это не суть важно)
Проблема в том что хочу вывести время на дисплей не в цикле основной программы а в таймере, что бы при паузах в основной функие, дисплей продолжал выводить информацию по прерыванию таймера.
И так, вот программа:

#include <mega16.h>
#include <delay.h>

unsigned i,j;
unsigned char hour,min,sek;
unsigned int msek;
unsigned char simbols[11]=
{
0b11111100, //0
0b01100000, //1
0b11011010, //2
0b11110010, //3
0b01100110, //4
0b10110110, //5
0b10111110, //6
0b11100000, //7
0b11111110, //8
0b11110110, //9
0b00000001 // точка, в зависимости от разряда верхняя или нижняя
};
unsigned char znak[4];

// Timer 1 output compare A interrupt service routine
interrupt [TIM1_COMPA] void timer1_compa_isr(void){
// Place your code here
TCNT1H=0;
TCNT1L=0;

msek++;

if (i==0)
{
znak[0]=simbols[min/10];
znak[1]=simbols[min%10];
znak[2]=simbols[sek/10];
znak[3]=simbols[sek%10];
}

PORTD.7=1;
for (j=0;j<8;j++)
{
PORTD.6=1;
if (j==(i+4))
{
PORTD.5=0;
}
else
{
PORTD.5=1;
}
PORTD.6=0;
}
for (j=0;j<8;j++)
{
PORTD.6=1;
PORTD.5=!(znak[i]&1);
znak[i]>>=1;
PORTD.6=0;
};
PORTD.6=1;
PORTD.7=0;

i++;
if (i>3) i=0;
}

// Declare your global variables here

void main(void)
{
hour=0;
min=0;
sek=0;
msek=0;
min_old=255;

PORTA=0x00;
DDRA=0xFF;

PORTB=0x07;
DDRB=0xFF;

PORTC=0x00;
DDRC=0xFF;

PORTD=0xE0;
DDRD=0xFF;

TCCR1A=0x00;
TCCR1B=0x01;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x2E;
OCR1AL=0xE0;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x10;

// Global enable interrupts
#asm("sei")

while (1)
{

if (msek>1000)
{
msek=msek-1000;
sek++;
}
if (sek>59)
{
sek=sek-60;
min++;
}
if (min>59)
{
min=min-60;
hour++;
}
if (hour>23)
{
hour=hour-24;
}
if (!PINB.0)
{
hour++;
delay_ms(250);
}
if (!PINB.1)
{
min++;
delay_ms(250);
};

//если выполнять этот код, то работает нормально, но я хочу через таймер сделать
/* for (i=0;i<4;i++){
{
znak[0]=simbols[min/10];
znak[1]=simbols[min%10];
znak[2]=simbols[sek/10];
znak[3]=simbols[sek%10];
}

for (j=0;j<8;j++)
{
PORTD.6=1;
if (j==(i+4))
{
PORTD.5=0;
}
else
{
PORTD.5=1;
}
PORTD.6=0;
}
for (j=0;j<8;j++)
{
PORTD.6=1;
PORTD.5=!(znak[i]&1);
znak[i]>>=1;
PORTD.6=0;
};
PORTD.6=1;
PORTD.7=0;
delay_us(100);
PORTD.7=1;
}
*/

}

Если тестить его в VMLAB, то все идет на ура, но вот на реальном МК происходят глюки, подаю питание на МК, он отсчитывает 3 сек и после этого прибавляет минутуи 6 сек, далее считает до 1:35 и опять перескакивает на минуту с лишним.
При этом, если убрать вывод на дисплей из таймера и вписать в основную функцию, то работает нормально, не перескакивает.
Подскажите где и что не так.

З.Ы. кварц на 12М

Добавлено (29.06.2010, 14:03)
---------------------------------------------
С этой проблемой разобрался, пересадил вывод на дисплей на другой (0)таймер.
Теперь встала другая проблема, время отстает очень сильно. Думаю кменьшать делитель счетчика нет смысла, так как после каждого изменения кода, придется снова подбирать новый делитель.
Появилась идея сделать таймер1 асинхронным.
Подскажите, как правильно это организовать.

 
HiSERДата: Вторник, 29.06.2010, 21:52 | Сообщение # 2
Продвинутый автор!
Группа: Проверенные
Сообщений: 254
Репутация: 11
Статус: Offline
Я бы сделал отображение в основном цикле, а клавиши обрабатывал по прерыванию.
Асинхронный таймер только второй + внешний кварц на 32768Hz, при этом МК тактируется от внутреннего RC
Как с ним работать написано в даташите http://www.alldatasheet.com/datashe....16.html
Страница 111, на странице 125 порядок включения


Сообщение отредактировал HiSER - Вторник, 29.06.2010, 21:53
 
Sany81Дата: Среда, 30.06.2010, 10:09 | Сообщение # 3
Рядовой
Группа: Пользователи
Сообщений: 3
Репутация: 0
Статус: Offline
Я почти так и сделал только что.
Нашел часы, вытащил кварц(в магазинах какой то дефицит кварцев), Запустил асинхронно второй таймер, в котором увеличиваю секунды/минуты/часы.
Вывод информации идет на первом таймере.
А все остальное уже в основном цикле, теперь паузы в основном цикле не мешают ни часам ни выводу информации.
 
Форум » Микроконтроллеры » Вопросы по МК » Помогите новичку. Atmega16 (Atmega16+таймер реального вреемни+вывод семисегментник)
  • Страница 1 из 1
  • 1
Поиск:

Хостинг от uCoz