Помогите разобраться программой

Обсуждаем контроллеры компании Atmel.
Ответить
Аватара пользователя
Bahmut
Первый раз сказал Мяу!
Сообщения: 32
Зарегистрирован: Вс окт 28, 2012 17:46:17
Откуда: Краматорск

Помогите разобраться программой

Сообщение Bahmut »

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

Код: Выделить всё

#include <mega8515.h>
 
#asm
   .equ __lcd_port=0b00011000 ;PORTB
#endasm
#include <lcd.h>
#include <delay.h>
 
int sb = 0; 
int mb = 0;
int chb = 0;
int sr = 0; 
int mr = 0;
int chr = 0;


void main(void)
  {
    DDRA=0b11111111; 
    PORTA=0b00000000;
    DDRD=0b00000000;
    PORTD=0b11111111;
    GICR=0b11000000;
    MCUCR=0b00000100; 
 
    TCCR1A=0b00000000;
    TCCR1B=0b00000101;
    TCNT1H=0b00000000;
    TCNT1L=0b00000000;
    ICR1H=0b00000000;
    ICR1L=0b00000000;
    OCR1AH=0b00011110;
    OCR1AL=0b10000101;
 
    TIMSK=0b00010000; 
 
    lcd_init(16);
 
    #asm("sei")

    void red(void)    // первая функция 
{ lcd_gotoxy(0,0);
        lcd_putsf("Blue");
        lcd_gotoxy(8,0); 
        lcd_putchar(chb/10+0x30);
        lcd_putchar(chb%10+0x30);
        lcd_putchar(0x3A); 
        lcd_putchar(mb/10+0x30);
        lcd_putchar(mb%10+0x30);
        lcd_putchar(0x3A); 
        lcd_putchar(sb/10+0x30);
        lcd_putchar(sb%10+0x30);
   while (PIND.0==1)
     {
       PORTA.0=0; delay_ms(3000); 
       PORTA.0=1; delay_ms(500);  
       sr++;
        if(sr>59) 
          { 
            mr++; 
            sr=0;
            if(mr>59)
              {
                chr++;
                mr=0;
         
                if(chr>23)
                  {
                    chr=0;
                  }
              }  
         
         }
     
     }   
}
void blue(void)  // вторая функция
{
   while (PIND.1==1)
     {
       PORTA.7=0; delay_ms(3000); 
       PORTA.7=1; delay_ms(500);  
       sb++; 
        if(sb>59) 
          { 
            mb++; 
            sb=0;
            if(mb>59)
              {
                chb++;
                mb=0;
         
                if(chb>23)
                  {
                    chb=0;
                  }
              }  
         
         }
         lcd_gotoxy(0,1);
        lcd_putsf("Red");
        lcd_gotoxy(8,1); 
        lcd_putchar(chr/10+0x30);
        lcd_putchar(chr%10+0x30);
        lcd_putchar(0x3A); 
        lcd_putchar(mr/10+0x30);
        lcd_putchar(mr%10+0x30);
        lcd_putchar(0x3A); 
        lcd_putchar(sr/10+0x30);
        lcd_putchar(sr%10+0x30);
     }
                    
       
    
  
}
   
  } 
Изображение
Последний раз редактировалось Аlex Сб сен 14, 2013 13:34:17, всего редактировалось 1 раз.
Причина: Тег [code]
Реклама
Аватара пользователя
blackx
Говорящий с текстолитом
Сообщения: 1518
Зарегистрирован: Пт дек 28, 2012 21:56:46
Откуда: St. Petersburg

Re: Помогите разобраться программой

Сообщение blackx »

Подскажу только в дизайне программы.

Создаете глобальную volatile переменную типа int timer_selected, объявляете две константы #define TIMER_1 1 и #define TIMER_2 2.
Соответственно для каждого таймера заводите int timer_1_counter, int timer_2_counter - где будет храниться собственно счет.

Далее пишете функцию, которая будет вызываться каждую секунду из прерывания таймера. Функция должна выводить на дисплей сначала счет первого таймера, потом второго (например, на первой и на второй строке) и выводить на дисплей пометку - какой таймер сейчас работает.

Теперь нужно сделать переключение timer_selected по нажатию кнопок. Это можно сделать в цикле, который поместить прямо в main(). Проверяем циклически оба вывода, с которыми соединены кнопки. Если нажата одна из кнопок, обновляем значение timer_selected (или TIMER_1 или TIMER_2). Защита от дребезга в таком устройстве не нужна, если повторные нажатия одной кнопки не должны приводить к каким-нибудь дополнительным эффектам.
Изображение only pure true norwegian blackx Изображение
Реклама
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Помогите разобраться программой

Сообщение Аlex »

... из прерывания таймера. Функция должна выводить на дисплей ...
Может не стОит нагружать обработчик такими массивными функциями ? :roll: ИМХО, вывод на дисплей - задача для основного цикла.
Хотя, если время обработки прерываний не будет больше периода вызова любого из прерываний и не помешает работе основного цикла, то можно и в прерывание запихивать что угодно. Только нужно задумываться о будущем этой программы.
Аватара пользователя
Bahmut
Первый раз сказал Мяу!
Сообщения: 32
Зарегистрирован: Вс окт 28, 2012 17:46:17
Откуда: Краматорск

Re: Помогите разобраться программой

Сообщение Bahmut »

Код: Выделить всё

#include <mega8515.h>
 
#asm
   .equ __lcd_port=0b00011000 ;PORTB
#endasm
#include <lcd.h>
#include <delay.h>
#define blue_LED PORTA.7  // вместо PORTA.7 возможна запись blue_LED
#define red_LED PORTA.0   // вместо PORTA.0 возможна запись red_LED

int BUTTON ; // Описал кнопку
volatile int sb = 0 ; //
volatile int mb = 0; //
volatile int chb = 0 ;// Обнуление таймеров
volatile int sr = 0 ; //
volatile int mr = 0 ; //
volatile int chr = 0 ;//

interrupt [TIM1_COMPA] void timer1_compa_isr(void) 
 {
  TCNT1H=0;
  TCNT1L=0;
 }

interrupt[2] void BUTTON_RED(void) //Обработчик прерываний на INT0.
  {
     BUTTON = 1;   
  }      

interrupt[3] void BUTTON_BLUE(void) //Обработчик прерываний на INT1.
  {
     BUTTON = 2;
  } 
      
void red ( int sr, int mr, int chr)
  {
       red_LED = 1; delay_ms(500); 
       red_LED = 0; delay_ms(3000);  
       sr++; // увеличиваем переменную каждую секунду
        if(sr>59)  // обнуляем секунды после 59
          { 
            mr++; 
            sr=0;
            if(mr>59)
              {
                chr++;
                mr=0;
         
                if(chr>23)
                  {
                    chr=0;
                  }
              }  
         
         }
      
        lcd_gotoxy(8,0); 
        lcd_putchar(chb/10+0x30);
        lcd_putchar(chb%10+0x30);
        lcd_putchar(0x3A); 
        lcd_putchar(mb/10+0x30);
        lcd_putchar(mb%10+0x30);
        lcd_putchar(0x3A); 
        lcd_putchar(sb/10+0x30);
        lcd_putchar(sb%10+0x30);
        //return (sr, mr, chr);
  }      
  
      
void blue ( int sb, int mb, int chb) 
  {  
    blue_LED = 1; delay_ms(500); 
       blue_LED = 0; delay_ms(3000);  
       sb++; // увеличиваем переменную каждую секунду
        if(sb>59)  // обнуляем секунды после 59
          { 
            mb++; 
            sb=0;
            if(mb>59)
              {
                chb++;
                mb=0;
         
                if(chb>23)
                  {
                    chb=0;
                  }
              }  
         
         }
         
        lcd_gotoxy(8,1); 
        lcd_putchar(chr/10+0x30);
        lcd_putchar(chr%10+0x30);
        lcd_putchar(0x3A); 
        lcd_putchar(mr/10+0x30);
        lcd_putchar(mr%10+0x30);
        lcd_putchar(0x3A); 
        lcd_putchar(sr/10+0x30);
        lcd_putchar(sr%10+0x30);
        //return (sb, mb, chb);
  } 
void main(void)
  {
    DDRA=0b11111111;        // Все выводы порта А - выходы.
    PORTA=0b00000000;       // На всех выводах порта А лог.0.
    DDRD=0b00000000;        // Все выводы порта D - входы. 
    PORTD=0b11111111;       // Ко всем выводам порта D подтянем питание, т.е. на всех выводах - лог.1.  
    GICR=0b11000000;        // Разрешим внешние прерывания по INT0 и INT1.  
    MCUCR=0b00000101;       // Прерывание срабатывает по любому изменению уровня на выводах INT0 и INT1.
 
    TCCR1A=0b00000000;      // OC1A/OC1B - отключены.
    TCCR1B=0b00000101;      // Предделитель установлен 1/1024.
    TCNT1H=0b00000000;      // ???
    TCNT1L=0b00000000;      // ???
    ICR1H=0b00000000;       // ???
    ICR1L=0b00000000;       // ???
    OCR1AH=0b00011110;      // ???
    OCR1AL=0b10000101;      // ???
 
    TIMSK=0b00010000;       //
    #asm("sei") ; 
    
    
    lcd_init(16);            // Инициализация LCD
    lcd_gotoxy(0,0);
    lcd_putsf("Blue");
    lcd_gotoxy(0,1);
    lcd_putsf("Red");
   
                       
    BUTTON = 0;
  
   while (1)
   {  
     switch (BUTTON)
     {
       case 1: red ( sb, mb, chb ); break;  
       case 2: blue ( sr, mr, chr ); break;
     }      
   };        
  } 

Вот так у меня получилось, не пойму как запустить таймер отдельно для каждого счётчика.
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
Bahmut
Первый раз сказал Мяу!
Сообщения: 32
Зарегистрирован: Вс окт 28, 2012 17:46:17
Откуда: Краматорск

Re: Помогите разобраться программой

Сообщение Bahmut »

Разобрался. :))
Реклама
Ответить

Вернуться в «AVR»