Реклама на сайте English version  DatasheetsDatasheets

KAZUS.RU - Электронный портал. Принципиальные схемы, Datasheets, Форум по электронике

Новости электроники Новости Литература, электронные книги Литература Документация, даташиты Документация Поиск даташитов (datasheets)Поиск PDF
  От производителей
Новости поставщиков
В мире электроники

  Сборник статей
Электронные книги
FAQ по электронике

  Datasheets
Поиск SMD
Он-лайн справочник

Принципиальные схемы Схемы Каталоги программ, сайтов Каталоги Общение, форум Общение Ваш аккаунтАккаунт
  Каталог схем
Избранные схемы
FAQ по электронике
  Программы
Каталог сайтов
Производители электроники
  Форумы по электронике
Помощь проекту

AVR Раздел по микроконтроллерам компании Atmel - AVR / ATtiny / ATmega / ATMega128 / ATxmega, вопросы по программированию в AVR studio и все, относящееся к AVR...

 
Опции темы
Непрочитано 19.01.2024, 01:09  
Godzilla82
Почётный гражданин KAZUS.RU
 
Регистрация: 29.10.2006
Сообщений: 1,446
Сказал спасибо: 99
Сказали Спасибо 317 раз(а) в 233 сообщении(ях)
Godzilla82 на пути к лучшему
Сообщение Re: Таймер на AVR ATMEGA128

Опишите задачу полностью: что за таймер, какой дисплей, сколько кнопок и что они должны делать, какие внешние устройства...
Реклама:
Godzilla82 вне форума  
Непрочитано 19.01.2024, 10:57  
Devil Byte
Временная регистрация
 
Регистрация: 07.03.2019
Сообщений: 87
Сказал спасибо: 11
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
Devil Byte на пути к лучшему
По умолчанию Re: Таймер на AVR ATMEGA128

Сообщение от Godzilla82 Посмотреть сообщение
Опишите задачу полностью:
Здравствуйте!
Дисплей nokia 5510, камень avr atmega 128/
Обычный таймер обратного отчета. Таймер содержит в себе, миллисекунды, секунды, десятки секунд, минуты, десятки минут.

Есть кнопки для увеличения и уменьшения выбранной части времени. Выбор доли времени осуществляется отдельной кнопкой, по нажатию которой сдвигается курсор от миллисекунд в сторону десятков минут.
Есть еще две кнопки одна кнопку служит для запуска отсчета, вторая для паузы.
Периферии пока ни какой нет. Но в целом это будет несколько реле на разных портах.
Я конечно дико извиняюсь за кашу в коде. Это в силу моего мизерного опыта, я только учусь.
МОжет посмотрите код и дадите пару советов? исходники прикладываю

Текущий вид кода:
Нажмите, чтобы открыть спойлер

PHP код:
#define F_CPU 8000000UL
#include ‹avr/io.h›
#include ‹util/delay.h›
#include ‹avr/interrupt.h›
#include ‹util/atomic.h›
#include ‹stdlib.h›
#include ‹avr/sleep.h›
#include ‹avr/cpufunc.h›
#include "n5110.h"

//-------------------------------------------------------------------------------------------------------------------------
// Создаю переменные для получения времени
volatile uint32_t dmilliseconds 0;
volatile uint32_t seconds_on_tiki 0;
volatile uint32_t milliseconds 0;
volatile uint32_t seconds 0;
volatile uint32_t tens_of_seconds 0;
volatile uint32_t minutes 0;
volatile uint32_t tens_of_minutes 0;
volatile uint32_t time_in_sec 0;
volatile uint32_t time_in_thensec 0;
volatile uint32_t time_in_min 0;
volatile uint32_t time_in_thenmin 0;
unsigned int milis 0;
volatile uint8_t  timer_state 0;
volatile int  iterator =1;
volatile int  count =0,count_line =0;
volatile int  x1 =0y1 =0x2 =0y2 =0;
char line PIXEL_ON;

//-------------------------------------------------------------------------------------------------------------------------
void time (unsigned int tiki)                            // Создаю функцию для дробления 5х значного числа на разряды
{
    
seconds_on_tiki tiki 10// всего секунд в tiki
    
dmilliseconds tiki 10// десятые доли секунды (0..9)
    
    
minutes seconds_on_tiki 60// минуты (0..99)
    
seconds seconds_on_tiki 60// секунды (0..59)
    
    
tens_of_minutes minutes /10//Десятки минут
    
time_in_min minutes %10// минуты
    
    
tens_of_seconds seconds/10;
    
time_in_sec seconds %10;
}

void display_timer_state(void)
{
    if (
timer_state == 1)
    {
        
// Timer is ON
        
Lcd_print(03FONT_1X, (unsigned char *)PSTR("timer ON"));

    }
    else
    {
        
// Timer is paused
        
Lcd_print(03FONT_1X, (unsigned char *)PSTR("timer pause"));
        
        
    }
}
//-------------------------------------------------------------------------------------------------------------------------
void timer1_ini(void)                                    //настройка таймера счетчика первого
{
    
TCNT1 0;                                            // обнуляем счетный регистр
    
OCR1A 3125;                                        // Указываем число для сравнения в регистр сравнения
    
TIMSK |= (1‹‹OCIE1A);                                // Включаем бит разрешения сравнения с OCR1A
}
//-------------------------------------------------------------------------------------------------------------------------
void timer1_start(void)                                    //Запуск первого таймера счетчика с предделителем на 256 и разрешением сравнения
{
    
TCCR1B |= (1‹‹WGM12)|(1‹‹CS12);
}
//-------------------------------------------------------------------------------------------------------------------------
void timer1_stop(void)                                  //Остановка первого таймера
{
    
TCCR1B &= ~((1‹‹WGM12)|(1‹‹CS12));
}
//-------------------------------------------------------------------------------------------------------------------------
ISR(TIMER1_COMPA_vect)                                    // Создаю макрос тиканья таймера
{
    if (--
milis==0)
    {
        
TCCR1B &=~(1‹‹CS12);
        
milis 0;
        
//PORTD |= (1‹‹0);

    
}
}
//-------------------------------------------------------------------------------------------------------------------------
void button_on(void)                                    // Активирую порты D и Е на выход, что бы использовать кнопки
{
    
DDRD 0x00;
    
PORTD |= (1‹‹0) | (1‹‹1) | (1‹‹2) | (1‹‹3);
}
//-------------------------------------------------------------------------------------------------------------------------
void displey_start(void)                                    // Активирую Порт B на выход, для того что бы активировать дисплей
{
    
DDRB &= ~((1‹‹PINB0) | (1‹‹PINB1) | (1‹‹PINB2) | (1‹‹PINB3) | (1‹‹PINB4) | (1‹‹PINB5));
    
PORTB 0x00;
    
Lcd_init();
    
Lcd_clear();
    
Lcd_update();
    
LcdContrast(62);
}

ISR(INT0_vect)
{
    
// Изменение значения переменной iterator в зависимости от текущего значения
    
if (count==1iterator 10;
    if (
count==2iterator 100;
    if (
count==3iterator 600;
    if (
count==4iterator 6000;
    if (
count›=5) {count 0iterator 1;}
}
//-------------------------------------------------------------------------------------------------------------------------
char buff[20];
int main(void)
{
    
// временная переменная для сохранения состояния прерываний
    
unsigned char keep_interrupt_status;
    
// временная переменная для счетчика тиков
    
unsigned int safe_desec;
    
button_on();
    
displey_start();
    
timer1_ini();
    
timer1_start();
    
// глобальные прерывания включены
    
timer1_stop();
    
// Настройка прерывания INT0 при нажатии кнопки
    
EIMSK |= (‹‹ INT0); // Разрешение внешнего прерывания INT0
    
EICRA |= (‹‹ ISC00); // Прерывание INT0 происходит при любом изменении на линии
    
sei();
    while (
1)
    {
        
keep_interrupt_status SREG// сохранить состояние прерываний
        
cli(); // запрет прерываний
        
safe_desec milis// АТОМАРНО копируем счетчик тиков во временную переменную
        
SREG keep_interrupt_status// восстановить состояние прерываний

        
time(safe_desec);

        
// Формирование строки для вывода на дисплей
        
buff[0] = tens_of_minutes '0'// десятки минут (0..9) ASCII
        
buff[1] = time_in_min '0'// единицы минут (0..9) ASCII
        
buff[2] = ':'// разделитель
        
buff[3] = tens_of_seconds '0'// десятки секунд (0..5) ASCII
        
buff[4] = time_in_sec '0'// единицы секунд (0..9) ASCII
        
buff[5] = ':'// разделитель
        
buff[6] = dmilliseconds '0'// десятые доли секунды (0..9) ASCII
        
buff[7] = '\0'// NUL-терминатор строки

        
if (~PIND&(1‹‹4))
        {
            
count++; //10, 100, 600,  6000
            
count_line++;
            
_delay_ms(150);
        }
        
            if (
count==1iterator 10;
            if (
count==2iterator 100;
            if (
count==3iterator 600;
            if (
count==4iterator 6000;
            if (
count›=5) {count 0iterator 1;}
        
        if (
count_line==0) {x1=42y1=9x2=46y2=9;}
        if (
count_line==1) {x1=24y1=9x2=28y2=9;}
        if (
count_line==2) {x1=18y1=9x2=22y2=9;}
        if (
count_line==3) {x1=6y1=9x2=10y2=9;}
        if (
count_line==4) {x1=0y1=9x2=4y2=9;}
        if (
count_line›=5) {count_line=0x1=42y1=9x2=46y2=9;}
        
        if (~
PIND&(1‹‹0))
        {
            
milis+=iterator//10, 100, 600,  6000

            
_delay_ms(150);
        }

        if (~
PIND&(1‹‹1))
        {
            
time(milis);  // Обновляем переменные перед увелечением итератора
            
if (tens_of_minutes != || time_in_min != || tens_of_seconds != || time_in_sec != || dmilliseconds != 0)
            {
                
// Проверяем, что хотя бы одна из переменных не равна нулю
                
milis-=iterator;
                
_delay_ms(150);
            }
            
            if(
milis‹=0milis 0;
            
        }
        
                    if (
tens_of_minutes == && time_in_min == && tens_of_seconds == && time_in_sec == && dmilliseconds == 0)
                    {

                        
line PIXEL_ON;
                    }
        
        if (~
PIND&(1‹‹2))
        {
            
time(milis);  // Обновляем переменные перед запуском таймера
            
if (tens_of_minutes != || time_in_min != || tens_of_seconds != || time_in_sec != || dmilliseconds != 0)
            {
                
// Проверяем, что хотя бы одна из переменных не равна нулю
                
timer1_start();
                
line PIXEL_OFF;
            }
            
_delay_ms(150);
        }
        
        if (~
PIND&(1‹‹3))
        {
            
time(milis);  // Обновляем переменные перед остановкой таймера
            
if (tens_of_minutes != || time_in_min != || tens_of_seconds != || time_in_sec != || dmilliseconds != 0)
            {
                
// Проверяем, что хотя бы одна из переменных не равна нулю
                
timer1_stop();
                
line PIXEL_ON;
            }
            
_delay_ms(150);
        }

        
Lcd_clear();
        
char buff[20];
        
itoa(tens_of_minutesbuff10);
        
Lcd_print(00FONT_1X,(unsigned char *)buff);
        
        
itoa(time_in_minbuff10);
        
Lcd_print(10FONT_1X,(unsigned char *)buff);
        
Lcd_prints(20FONT_1X,(unsigned char *)PSTR(":"));
        
        
itoa(tens_of_secondsbuff10);
        
Lcd_print(30FONT_1X,(unsigned char *)buff);
        
itoa(time_in_secbuff10);
        
Lcd_print(40FONT_1X,(unsigned char *)buff);
        
Lcd_prints(50FONT_1X,(unsigned char *)PSTR(":"));
        
        
itoa(dmillisecondsbuff10);
        
Lcd_print(70FONT_1X,(unsigned char *)buff);

        
Lcd_line x1y1x2y2line );
        
Lcd_update();
        
_delay_ms(50);

    }


Из всего этого думаю что надо использовать не блокирующие задержки, то есть перевести обработку нажатия кнопок в нулевой таймер. и часть if превратить функцию, например курсор для выбора времени. Еще заметил странность при работе кнопки уменьшения. Например если выставить 12 секунд, потом начать уменьшать десятки, то в какой то момент таймер перескочит например на 18 часов и так далее
=
Вложения:
Тип файла: rar proteus.rar (29.4 Кб, 0 просмотров)
Тип файла: rar My timer.rar (89.2 Кб, 0 просмотров)

Последний раз редактировалось Devil Byte; 19.01.2024 в 17:43.
Devil Byte вне форума  
Непрочитано 19.01.2024, 21:50  
Godzilla82
Почётный гражданин KAZUS.RU
 
Регистрация: 29.10.2006
Сообщений: 1,446
Сказал спасибо: 99
Сказали Спасибо 317 раз(а) в 233 сообщении(ях)
Godzilla82 на пути к лучшему
Сообщение Re: Таймер на AVR ATMEGA128

PHP код:
 
#include ‹io.h›
#include ‹alcd.h›
#include ‹stdio.h›

#define _ALTERNATE_PUTCHAR_

#define KEY_SELECT              0x01
#define KEY_INC                 0x02
#define KEY_DEC                 0x04
#define KEY_START               0x08
#define KEY_PAUSE               0x10

#define MODE_SELECT             0
#define MODE_RUN                1
#define MODE_PAUSE              2
#define MODE_DONE               3

unsigned char                   key_pressed                     0;
unsigned char                   key_previous                    0;
unsigned char                   key_current                     0;
unsigned char                   update                          1;
unsigned char                   timer_mode                      0;
unsigned char                   timer_select                    0;
signed char                     time_ts                         0;
signed char                     time_ss                         0;
signed char                     time_ds                         1;
signed char                     time_mm                         0;
signed char                     time_dm                         0;

interrupt [TIM1_COMPAvoid timer1_compa_isr(void)
{
key_current = ~PIND;
key_pressed |= key_current key_previous key_current;
key_previous key_current;
if(
timer_mode == MODE_RUN)  {
                            
update 1;
                            
time_ts--;
                            if(
time_ts ‹ 0) {
                                            
time_ts 9;
                                            
time_ss--;
                                            if(
time_ss ‹ 0) {
                                                            
time_ss 9;
                                                            
time_ds--;
                                                            if(
time_ds ‹ 0) {
                                                                            
time_ds 5;
                                                                            
time_mm--;
                                                                            if(
time_mm ‹ 0) {
                                                                                            
time_mm 9;
                                                                                            
time_dm--;
                                                                                            if(
time_dm ‹ 0) {
                                                                                                            
time_dm time_mm time_ds time_ss time_ts 0;
                                                                                                            
timer_mode MODE_DONE;
                                                                                                            }
                                                                                            }
                                                                            }
                                                            }
                                            }
                            }
}

void init(void)
{
DDRD 0;
PORTD 0x1F;

// Timer1: 31,250 kHz; 0,1 s; CTC top=OCR1A;
TCCR1A 0;
TCCR1B = (1‹‹WGM12) | (1‹‹CS12);
OCR1AH 0x0C;
OCR1AL 0x34;
TIMSK = (1‹‹OCIE1A);
}

void putchar(char c)
{
lcd_putchar(c);
}

void main(void)
{
unsigned char i;
init();
lcd_init(20);
#asm("sei")
while(1)    {
            if(
key_pressed KEY_START)     {
                                            
key_pressed 0;
                                            
update 1;
                                            switch(
timer_mode)              {
                                                                            case 
MODE_DONE:
                                                                            
timer_mode MODE_SELECT;
                                                                            
timer_select 0;
                                                                            break;

                                                                            default:
                                                                            
timer_mode MODE_RUN;
                                                                            }
                                            }
            if(
key_pressed KEY_PAUSE)     {
                                            
key_pressed 0;
                                            switch(
timer_mode)              {
                                                                            case 
MODE_RUN:
                                                                            
timer_mode MODE_PAUSE;
                                                                            
update 1;
                                                                            break;

                                                                            case 
MODE_PAUSE:
                                                                            
timer_select 0;
                                                                            
timer_mode MODE_SELECT;
                                                                            
update 1;
                                                                            break;
                                                                            }
                                            }
            if(
key_pressed KEY_SELECT)    {
                                            
key_pressed 0;
                                            switch(
timer_mode)              {
                                                                            case 
MODE_SELECT:
                                                                            if(++
timer_select › 4timer_select 0;
                                                                            
update 1;
                                                                            break;
                                                                            }
                                            }
            if(
key_pressed KEY_INC)       {
                                            
key_pressed 0;
                                            
update 1;
                                            if(
timer_mode == MODE_SELECT)
                                            switch(
timer_select)            {
                                                                            case 
0:     time_dm++;      if(time_dm › 9time_dm 0;    break;
                                                                            case 
1:     time_mm++;      if(time_mm › 9time_mm 0;    break;
                                                                            case 
2:     time_ds++;      if(time_ds › 5time_ds 0;    break;
                                                                            case 
3:     time_ss++;      if(time_ss › 9time_ss 0;    break;
                                                                            case 
4:     time_ts++;      if(time_ts › 9time_ts 0;    break;
                                                                            }
                                            }
            if(
key_pressed KEY_DEC)       {
                                            
key_pressed 0;
                                            
update 1;
                                            if(
timer_mode == MODE_SELECT)
                                            switch(
timer_select)            {
                                                                            case 
0:     time_dm--;      if(time_dm ‹ 0time_dm 9;    break;
                                                                            case 
1:     time_mm--;      if(time_mm ‹ 0time_mm 9;    break;
                                                                            case 
2:     time_ds--;      if(time_ds ‹ 0time_ds 5;    break;
                                                                            case 
3:     time_ss--;      if(time_ss ‹ 0time_ss 9;    break;
                                                                            case 
4:     time_ts--;      if(time_ts ‹ 0time_ts 9;    break;
                                                                            }
                                            }
            if(
update)                      {
                                            
update 0;
                                            
lcd_clear();
                                            
printf("%d%d:%d%d.%d",time_dm,time_mm,time_ds,time_ss,time_ts);
                                            switch(
timer_mode)              {
                                                                            case 
MODE_PAUSE:    lcd_gotoxy(0,1);    printf("PAUSE");    break;
                                                                            case 
MODE_DONE:     lcd_gotoxy(0,1);    printf("DONE ");    break;
                                                                            case 
MODE_SELECT:
                                                                            
timer_select;
                                                                            if(
› 1i++;
                                                                            if(
› 4i++;
                                                                            
lcd_gotoxy(i,0);
                                                                            
_lcd_write_data(0b00001110);
                                                                            break;
                                                                            }

                                            }
            }

Вложения:
Тип файла: zip TIMER_M128.zip (16.0 Кб, 0 просмотров)

Последний раз редактировалось Godzilla82; 20.01.2024 в 00:06.
Godzilla82 вне форума  
Сказали "Спасибо" Godzilla82
Devil Byte (20.01.2024)
Непрочитано 20.01.2024, 20:46  
Devil Byte
Временная регистрация
 
Регистрация: 07.03.2019
Сообщений: 87
Сказал спасибо: 11
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
Devil Byte на пути к лучшему
По умолчанию Re: Таймер на AVR ATMEGA128

Сообщение от Godzilla82 Посмотреть сообщение
PHP код:
#include ‹io.h›
#include ‹alcd.h›
#include ‹stdio.h› 
Спасибо! в общем попробовал прокомментировать ваш код, есть какие то непонятные для меня моменты. но в целом все ясно.
Прошу Вас посмотреть, и ответить правильно ли я все понял, и ответить на вопросы в комментариях:

Нажмите, чтобы открыть спойлер

PHP код:
#define _ALTERNATE_PUTCHAR_                // не понял что за дефайн для альтернативного вывода символа?

#define KEY_SELECT              0x01    // Значение кнопки для выбора
#define KEY_INC                 0x02    // Значение для кнопки инкремента
#define KEY_DEC                 0x04    // Значение для кнопки декремента
#define KEY_START               0x08    // Значение для кнопки старт
#define KEY_PAUSE               0x10    // Значение для кнопки пауза

#define MODE_SELECT             0        // Режим выбора времени
#define MODE_RUN                1        // Режим запуска таймера
#define MODE_PAUSE              2        // Режим паузы таймера
#define MODE_DONE               3        // Режим завершения отсчета таймера

unsigned char  key_pressed    0;        // Распознавание нажатия клавиши
unsigned char  key_previous   0;        // Не понял предназначение этой переменной
unsigned char  key_current    0;        // По идее переменная которой должны присваиваться значения пинов порта D
unsigned char  update         1;        // Переменная для обновления времени как при выборе времени так и при запущенном таймере
unsigned char  timer_mode     0;        // Переменная которая получает значение MODE
unsigned char  timer_select   0;        // Понял что переменная позволяет выбирать место установки времени за счет своей итерации,
signed char    time_ts        0;        // Десятки секунд
signed char    time_ss        0;        // Секунды
signed char    time_ds        1;        // Миллисекунды
signed char    time_mm        0;        // Минуты
signed char    time_dm        0;        // Десятки минут




ISR(TIMER1_COMPA_vect// в вашем коде написано interrupt [TIM1_COMPA] void timer1_compa_isr(void) ... я честно не понял как это работает, что должнро попасть в прерывания? ведь нельзя определять функцию внутри функции
{

}
void timer1_compa_isr(void// по идее это функция определения срабатывания кнопок
{
    
key_current = ~PIND// Не понял для чего данная переменная каждый раз будет получать инвертированное значение с пинов?
    
key_pressed |= key_current key_previous key_current// В зависимости от результатов получим модификацию переменной key_pressed, но не понимаю как работает это выражение
    
key_previous key_current// Почему такое присвоение? зависит от первого результата?
    
    // Функция работы таймера обратный отсчет
    
if(timer_mode == MODE_RUN)  // Если таймер запущен начинаем уменьшать значения на 1
    
{
        
update 1;
        
time_ts--;
        if(
time_ts ‹ 0) {time_ts 9time_ss--;} // Если десятки секунд равны нулю, то уменьшаем секунды
        
if(time_ss ‹ 0) {time_ss 9time_ds--;} // Если секунды равны нулю, то уменьшаем миллисекунды
        
if(time_ds ‹ 0) {time_ds 5time_mm--;} // Если десятки секунды равны нулю, то уменьшаем минуты
        
if(time_mm ‹ 0) {time_mm 9time_dm--;} // Если минуты равны нулю, то уменьшаем десятки минут
        
if(time_dm ‹ 0)                              // Если десятки минут равны нулю, то можно считать таймер истекшим и приравнять все значения нулю. Затем установить режим таймера как завершенный
        
{
            
time_dm time_mm time_ds time_ss time_ts 0;
            
timer_mode MODE_DONE;
        }
    }
}


void init(void// Тут в целом все понятно - функция запуск таймера с настройками и настройка порта D для кнопок
{
    
DDRD 0;
    
PORTD 0x1F;

    
// Timer1: 31,250 kHz; 0,1 s; CTC top=OCR1A;
    
TCCR1A 0;
    
TCCR1B = (1‹‹WGM12) | (1‹‹CS12);
    
OCR1AH 0x0C;
    
OCR1AL 0x34;
    
TIMSK = (1‹‹OCIE1A);
}

void putchar(char c// Не совсем понял что за символ, но предполагаю что это символ "земля" для примененного дисплея
{
    
lcd_putchar(c);
}

int main(void)
{
    
unsigned char i// видимо эта переменная нужна для выбранного дисплея
    
init();          // инициализация таймера и порта кнопок
    
lcd_init(20);    // инициализация вашего дисплея
    #asm("sei")     // разрешение прерывания. А разве их ненужно потом ни где запрещать?
    
    
while(1)
    {
        
// Условный опереатор для определения работы кнопки старт
        
if(key_pressed KEY_START)            // Здесь проверяем установлен ли бит KEY_START в переменной key_pressed
        
{
            
key_pressed 0;                // Если условие истинно то переменной присваивается 0 
            
update 1;                        // Значение update = 1. А надо ли каждый раз говорить о том что она равна единице? так как она и так в дефайне =1?
            
switch(timer_mode)                // Оператор нужен для отслеживания и отлавливания timer_mode
            
{
                case 
MODE_DONE:                // Если в этом кейсе словили переменную о завершении работы таймера
                
timer_mode MODE_SELECT;   // То переводим timer_mode в режим выбора времени для изменения
                
timer_select 0;            // timer_select присваиваем 0, что бы он встал в самом конце времени
                
break;

                default:                    
// Если первый кейс не сработал  
                
timer_mode MODE_RUN;      // то по умолчанию запускаем работу таймера путем присвоения timer_mode = MODE_RUN
            
}
        }
        
        
// Условный оператор для определения работы кнопки старт
        
if(key_pressed KEY_PAUSE)            // Здесь проверяем установлен ли бит KEY_PAUSE в переменной key_pressed                
        
{
            
key_pressed 0;
            switch(
timer_mode)                // 
            
{
                case 
MODE_RUN:                // Если в этом кейсе словили переменную о том что таймер в работе
                
timer_mode MODE_PAUSE;    // то устанавливаем переводим режим таймера в паузу
                
update 1;
                break;

                case 
MODE_PAUSE:            // Получается что после отработки первого кейса должны в этом кейсе словить режим паузы таймера
                
timer_select 0;
                
timer_mode MODE_SELECT;   // и присвоить режим выбора времени, пока стоит пауза
                
update 1;
                break;
            }
        }
        
        
// Условный оператор для определения работы кнопки выбора времени
        
if(key_pressed KEY_SELECT)        // Здесь проверяем установлен ли бит KEY_SЕLECT в переменной key_pressed
        

            
key_pressed 0;                // 
            
switch(timer_mode)
            {
                
//не совсем понял как свич определяет режим селект? за счет того что в других свитчах он выставляется сам?
                
case MODE_SELECT:          // Должны отловить режим таймера селект, но не совсем понимаю как свич должен отследить режим селекта
                
if(++timer_select › 4timer_select 0// при успешном отлове можем инкрементировать переменную timer_select для смещения курсора 
                
update 1;
                break;
            }
        }
        
        
// Условный оператор для определения работы кнопки увеличения времени
        
if(key_pressed KEY_INC)            // Здесь проверяем установлен ли бит KEY_INC в переменной key_pressed
        
{
            
key_pressed 0;
            
update 1;
            if(
timer_mode == MODE_SELECT)    // Если кнопка увеличения времени нажата и режим таймера в режиме выбора
            
switch(timer_select)            // то в зависимости от значения переменной  timer_select будем увеличивать выбранную часть времени
            
{
                case 
0:     time_dm++;      if(time_dm › 9time_dm 0;    break; //в кейсах ифами не даем перевалить времени за определенные значения
                
case 1:     time_mm++;      if(time_mm › 9time_mm 0;    break;
                case 
2:     time_ds++;      if(time_ds › 5time_ds 0;    break;
                case 
3:     time_ss++;      if(time_ss › 9time_ss 0;    break;
                case 
4:     time_ts++;      if(time_ts › 9time_ts 0;    break;
            }
        }
        
        
// Условный оператор для определения работы кнопки увеличения времени 
        
if(key_pressed KEY_DEC)            // Все тоже самое как и для кнопки увеличения, только в обратном порядке
        
{
            
key_pressed 0;
            
update 1;
            if(
timer_mode == MODE_SELECT)
            switch(
timer_select)
            {
                case 
0:     time_dm--;      if(time_dm ‹ 0time_dm 9;    break;
                case 
1:     time_mm--;      if(time_mm ‹ 0time_mm 9;    break;
                case 
2:     time_ds--;      if(time_ds ‹ 0time_ds 5;    break;
                case 
3:     time_ss--;      if(time_ss ‹ 0time_ss 9;    break;
                case 
4:     time_ts--;      if(time_ts ‹ 0time_ts 9;    break;
            }
        }
        
        
// Не понимаю почему это все заключено в условный оператор?
        
if(update)   
        {
            
update 0;                                                        // почему тут она равна нулю?
            
lcd_clear();                                                    // дисплей...
            
printf("%d%d:%d%d.%d",time_dm,time_mm,time_ds,time_ss,time_ts); // дисплей...
            
switch(timer_mode)              
            {
                case 
MODE_PAUSE:    lcd_gotoxy(0,1);    printf("PAUSE");    break; // при режиме паузы, выводим на дисплей сообщение о паузе
                
case MODE_DONE:     lcd_gotoxy(0,1);    printf("DONE ");    break; //  при режиме завершения выводим на дисплей сообщение о завершении
                
case MODE_SELECT:                                                  //  вот тут не совсем понятно почему timer_select инкриминируется с помощью i? вроде выше он сам по себе работает
                
timer_select;                                                        
                if(
› 1i++;                                                      // и вот эти иф  не понял что делают?
                
if(› 4i++;
                
lcd_gotoxy(i,0);                                                  // дисплей...                            
                
_lcd_write_data(0b00001110);                                      // дисплей...
                
break;
            }

        }
    }


Спасибо большое!
Devil Byte вне форума  
Непрочитано 20.01.2024, 23:06  
Godzilla82
Почётный гражданин KAZUS.RU
 
Регистрация: 29.10.2006
Сообщений: 1,446
Сказал спасибо: 99
Сказали Спасибо 317 раз(а) в 233 сообщении(ях)
Godzilla82 на пути к лучшему
Сообщение Re: Таймер на AVR ATMEGA128

Сообщение от Devil Byte Посмотреть сообщение
PHP код:
 
#define _ALTERNATE_PUTCHAR_    // не понял что за дефайн для альтернативного вывода символа? 
Дефайн, который позволяет написать свою функцию putchar().

Сообщение от Devil Byte Посмотреть сообщение
PHP код:
 
unsigned char  key_previous   
0;    // Не понял предназначение этой переменной 
Нужна, чтобы понять, что состояние порта изменилось.

Сообщение от Devil Byte Посмотреть сообщение
PHP код:
unsigned char  update         1;        // Переменная для обновления времени как при выборе времени так и при запущенном таймере 
Флаг обновления данных на дисплее. Устанавливаем в 1, если нужно обновить данные на экране.

Сообщение от Devil Byte Посмотреть сообщение
PHP код:
unsigned char  timer_select   0// Понял что переменная позволяет выбирать место установки времени за счет своей итерации 
Переменная указывает, что именно нужно менять нажатиями кнопок "+" и "-".

Сообщение от Devil Byte Посмотреть сообщение
PHP код:
signed char    time_ts        0;        // Десятки секунд 
Десятые доли секунды

Сообщение от Devil Byte Посмотреть сообщение
PHP код:
signed char    time_ds        1;        // Миллисекунды 
Десятки секунд

Сообщение от Devil Byte Посмотреть сообщение
PHP код:
ISR(TIMER1_COMPA_vect// в вашем коде написано interrupt [TIM1_COMPA] void timer1_compa_isr(void) ... 
я честно не понял как это работаетчто должнро попасть в прерыванияведь нельзя определять функцию внутри функции 
Это конструкция, описывающая функцию прерывания в компиляторе CodeVision AVR.

Сообщение от Devil Byte Посмотреть сообщение
PHP код:
void timer1_compa_isr(void// по идее это функция определения срабатывания кнопок 
Это функция определяет, как нажатые кнопки, так и выполняет отсчёт времени.

Сообщение от Devil Byte Посмотреть сообщение
PHP код:
key_current = ~PIND// Не понял для чего данная переменная каждый раз будет получать инвертированное значение с пинов? 
Потому, что кнопки замыкают пин на землю. И нажатая кнопка - это соответствующий бит будет равен нулю.

Сообщение от Devil Byte Посмотреть сообщение
PHP код:
key_pressed |= key_current key_previous key_current// В зависимости от результатов получим модификацию переменной key_pressed,
но не понимаю как работает это выражение 
текущее значение порта через битовую операцию "исключающее или" с предыдущим значением порта даёт единицы там, где
произошло изменение. Чтобы биты нажатых кнопок не устанавливались при отпускании кнопок, результат проходит через побитовую опрецию "и"
с текущим значением нажатых кнопок (там уже, после инверсии порта, нажатой кнопке соответствует логическая единица).

Сообщение от Devil Byte Посмотреть сообщение
PHP код:
key_previous key_current// Почему такое присвоение? зависит от первого результата? 
Просто запоминает предудущее состояние порта для последующего вызова прерывания.

Сообщение от Devil Byte Посмотреть сообщение
PHP код:
 
        
if(time_ts ‹ 0) {time_ts 9time_ss--;} // Если десятки секунд равны нулю, то уменьшаем секунды
        
if(time_ss ‹ 0) {time_ss 9time_ds--;} // Если секунды равны нулю, то уменьшаем миллисекунды
        
if(time_ds ‹ 0) {time_ds 5time_mm--;} // Если десятки секунды равны нулю, то уменьшаем минуты
        
if(time_mm ‹ 0) {time_mm 9time_dm--;} // Если минуты равны нулю, то уменьшаем десятки минут
        
if(time_dm ‹ 0)    // Если десятки минут равны нулю, то можно считать таймер истекшим и приравнять все значения нулю...
        
{
            
time_dm time_mm time_ds time_ss time_ts 0;
            
timer_mode MODE_DONE;
        } 
Вы опять все не так переписали. Я же даже отступы сделал, чтобы наглядно видно было, какой код к какому циклу относится.
Работать будет, но проверки будут делаться каждый раз, а не только тогда, когда они нужны.


Сообщение от Devil Byte Посмотреть сообщение
PHP код:
void putchar(char c// Не совсем понял что за символ, но предполагаю что это символ "земля" для примененного дисплея 
Функция, которая вызывается (в частности, функцией printf() для вывода символа на экран.
Я её переписал так, чтобы вывод происходил на дисплей.

Сообщение от Devil Byte Посмотреть сообщение
PHP код:
unsigned char i// видимо эта переменная нужна для выбранного дисплея 
На экране таймер отображается в виде:
00:00.0

timer_select - это:
0 - для десятков минут
1 - для единиц минут
2 - для десятков секунд
3 - для единиц секунд
4 - для десятой части секунд

Эта переменная нужна для вычисления номера символа, который будет изменяться кнопками "+" и "-":
0 - для десятков минут
1 - для единиц минут
3 - для десятков секунд
4 - для единиц секунд
6 - для десятой части секунд

Сообщение от Devil Byte Посмотреть сообщение
PHP код:
#asm("sei")     // разрешение прерывания. А разве их ненужно потом ни где запрещать? 
А зачем? Пусть работают.

Сообщение от Devil Byte Посмотреть сообщение
PHP код:
update 1// Значение update = 1. А надо ли каждый раз говорить о том что она равна единице? так как она и так в дефайне =1? 
В каком ещё дефайне?
Если кнопка была нажата, то программа изменила какие-то данные. Соостветственно, нужно отобразить изменения.

Сообщение от Devil Byte Посмотреть сообщение
PHP код:
timer_select 0;    // timer_select присваиваем 0, что бы он встал в самом конце времени 
Чтобы указатель того, что будет меняться кнопками "+" и "-" указывал на десятки минут (в начало строки),
а не в "самый конец времени".

Сообщение от Devil Byte Посмотреть сообщение
PHP код:
case MODE_PAUSE// Получается что после отработки первого кейса должны в этом кейсе словить режим паузы таймера 
Нет, если отработал первый case, то после break управление переходит на операторы после фунции switch().
Другими словами. Первым нажатием мы переводим таймер в режим паузы, вторым нажатием - в режим выбора времени.

Сообщение от Devil Byte Посмотреть сообщение
PHP код:
//не совсем понял как свич определяет режим селект? за счет того что в других свитчах он выставляется сам? 
При запуске программы он равен MODE_SELECT.

Сообщение от Devil Byte Посмотреть сообщение
PHP код:
// Не понимаю почему это все заключено в условный оператор?
if(update
Если переменная update не равна нулю, то нужно обновить данные на экране. Их не нужно обновлять 1000 раз в секунду.
Например, если мы в режиме задания времени отсчёта и ничего не нажимаем, то обновлять данные на экране не нужно.

Сообщение от Devil Byte Посмотреть сообщение
PHP код:
update 0// почему тут она равна нулю? 
Присваиваем переменной update значение ноль, так как данные на экране сейчас будут обновлены.
И следующее обновление данных будет только тогда, когда в программе она снова установится в 1.

Сообщение от Devil Byte Посмотреть сообщение
PHP код:
case MODE_SELECT//  вот тут не совсем понятно почему timer_select инкриминируется с помощью i? вроде выше он сам по себе работает 
Объяснял выше.

Сообщение от Devil Byte Посмотреть сообщение
PHP код:
_lcd_write_data(0b00001110); 
Включает отображение курсора, который был перемещён на позицию цифры, которая будет меняться кнопками "+" и "-".

Последний раз редактировалось Godzilla82; 21.01.2024 в 13:53.
Godzilla82 вне форума  
Непрочитано 21.01.2024, 13:48  
Devil Byte
Временная регистрация
 
Регистрация: 07.03.2019
Сообщений: 87
Сказал спасибо: 11
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
Devil Byte на пути к лучшему
По умолчанию Re: Таймер на AVR ATMEGA128

Godzilla82, Приветсвую Вас!
Пробую разобраться...
Добавил в if (update) в свитч вывод курсора под цифрами. Но есть баг. Если ставлю таймер на паузу, то курсор не смещается по нажатию кнопки. НО если нажать на паузу два раза, то курсор начинает двигаться.
В чем загвоздка?

Нажмите, чтобы открыть спойлер

PHP код:
            switch(timer_mode)
            {
                case 
MODE_PAUSE:    //lcd_gotoxy(0,1);    printf("PAUSE");    break;
                
case MODE_DONE:    // lcd_gotoxy(0,1);    printf("DONE ");    break;
                
case MODE_SELECT:                                                 
                
timer_select;
                if(
› 1i++;                                                     
                if(
› 4i++;
                        
// выставление координат для смещения курсора
                        
if (timer_select==4) {x1=42y1=9x2=46y2=9;} 
                        if (
timer_select==3) {x1=24y1=9x2=28y2=9;}
                        if (
timer_select==2) {x1=18y1=9x2=22y2=9;}
                        if (
timer_select==1) {x1=6y1=9x2=10y2=9;}
                        if (
timer_select==0) {x1=0y1=9x2=4y2=9;}
                        if (
timer_select›=5) {timer_select=0x1=42y1=9x2=46y2=9;}
                
Lcd_line x1y1x2y2line );
                
Lcd_update();
                
//_delay_ms(20);

                
break;
            } 

Последний раз редактировалось Devil Byte; 21.01.2024 в 14:22.
Devil Byte вне форума  
Непрочитано 21.01.2024, 14:28  
Godzilla82
Почётный гражданин KAZUS.RU
 
Регистрация: 29.10.2006
Сообщений: 1,446
Сказал спасибо: 99
Сказали Спасибо 317 раз(а) в 233 сообщении(ях)
Godzilla82 на пути к лучшему
Сообщение Re: Таймер на AVR ATMEGA128

Весь код покажите. В этом коде вы break закомментировали.
В том коде, что я приводил так и должно быть. Первое нажатие - просто пауза. А второе - установка времени.

Сообщение от Devil Byte Посмотреть сообщение
PHP код:

timer_select;
if(
› 1i++;                                                     
if(
› 4i++; 
Зачем этот код, если вы используете timer_select.

Сообщение от Devil Byte Посмотреть сообщение
PHP код:
if (timer_select›=5) {timer_select=0x1=42y1=9x2=46y2=9;} 
Зачем "›="? Зачем делаете timer_select=0? Тут нужно только отображение результатов. Менять значения переменных не надо.

Последний раз редактировалось Godzilla82; 21.01.2024 в 14:41.
Godzilla82 вне форума  
Непрочитано 21.01.2024, 15:19  
Devil Byte
Временная регистрация
 
Регистрация: 07.03.2019
Сообщений: 87
Сказал спасибо: 11
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
Devil Byte на пути к лучшему
По умолчанию Re: Таймер на AVR ATMEGA128

Сообщение от Godzilla82 Посмотреть сообщение
Весь код покажите. В этом коде вы break закомментировали.
В том коде, что я приводил так и должно быть. Первое нажатие - просто пауза. А второе - установка времени.
А точно, что то я даже внимания и не обратил.... Тоже интересно решение.

Сообщение от Godzilla82 Посмотреть сообщение
Зачем этот код, если вы используете timer_select.
Поучается что в принципе i можно исключить?

Сообщение от Godzilla82 Посмотреть сообщение
Весь код покажите. В этом коде вы break закомментировали.
В том коде, что я приводил так и должно быть. Первое нажатие - просто пауза. А второе - установка времени.

Зачем этот код, если вы используете timer_select.

Зачем "›="? Зачем делаете timer_select=0? Тут нужно только отображение результатов. Менять значения переменных не надо.
Да понял, просто я наскоряк воткнул кусок из своего кода, и неубрал обнуление селекта. в своем коде я использовал это что бы каждый раз возвращаться в конец/ начало строки.

И еще все таки прошу немного пояснить за кнопки... Тут же явно не указаны пины кнопок. Как происходит определение пина? Почему они имеют именно такое значение:
И не будет ли дребезга на реальном девайсе? просто пока не могу проверить так как на вахте.
Нажмите, чтобы открыть спойлер
[B]#define KEY_SELECT 0x01
#define KEY_INC 0x02
#define KEY_DEC 0x04
#define KEY_START 0x08
#define KEY_PAUSE 0x10/B].

и еще как на таймере при включение появляется единица в десятках часов??

Последний раз редактировалось Devil Byte; 21.01.2024 в 15:28.
Devil Byte вне форума  
Непрочитано 21.01.2024, 16:59  
Godzilla82
Почётный гражданин KAZUS.RU
 
Регистрация: 29.10.2006
Сообщений: 1,446
Сказал спасибо: 99
Сказали Спасибо 317 раз(а) в 233 сообщении(ях)
Godzilla82 на пути к лучшему
Сообщение Re: Таймер на AVR ATMEGA128

Сообщение от Devil Byte Посмотреть сообщение
Поучается что в принципе i можно исключить?
Да
Но можно сделать так:
PHP код:

timer_select;
if(
› 1i++;                                                     
if(
› 4i++;
Lcd_line (6949line);
Lcd_update(); 


Сообщение от Devil Byte Посмотреть сообщение
Тут же явно не указаны пины кнопок. Как происходит определение пина? Почему они имеют именно такое значение
Как раз тут они явно и указаны. Я не знаю, куда они у вас подключены. Я их подключил на порт D (во вложении я выкладывал файл протеуса и прошивку).

Сообщение от Devil Byte Посмотреть сообщение
И не будет ли дребезга на реальном девайсе?
Тут применён именно антидребезговый алгоритм. Лучше, конечно, опрашивать с интервалом 50 мс, но и 100 сойдёт.

Сообщение от Devil Byte Посмотреть сообщение
как на таймере при включение появляется единица в десятках часов??
При объявлении переменных явно задана.
Только не в десятках часов (у вас вроде как минуты максимум, а не часы), а в десятках секунд.

Последний раз редактировалось Godzilla82; 21.01.2024 в 17:02.
Godzilla82 вне форума  
Непрочитано 21.01.2024, 18:32  
Devil Byte
Временная регистрация
 
Регистрация: 07.03.2019
Сообщений: 87
Сказал спасибо: 11
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
Devil Byte на пути к лучшему
По умолчанию Re: Таймер на AVR ATMEGA128

Сообщение от Godzilla82 Посмотреть сообщение
Как раз тут они явно и указаны.
Тогда я не совсем понимаю.... например #define KEY_PAUSE 0x10
В двоичной системе это 22, а в десятичной 16, но в порте D эта кнопка сидит на 4 пине...
Devil Byte вне форума  
 

Закладки
Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Внешний сторожевой таймер для ATMega128 vladomir AVR 10 13.04.2022 19:12
Есть таймер на на AVR запитанный от сети через резистор azlk3000 Источники питания и свет 1 29.12.2012 09:51
Литература по микроконтроллерам (AVR, PIC, ПЛИС и т.д.). Сборка книг - (256 книг+ 27 CD c примерами из книг) [обновление 2011, PDF, DJVU] yurinform Микроконтроллеры, АЦП, память и т.д 5 05.07.2011 19:00
Архив проектов на AVR fmssp Proteus, KiCAD и другие ECAD 4 25.10.2010 17:14
помогите с AVR ATmega128 zuuuuk Микроконтроллеры, АЦП, память и т.д 0 11.02.2007 02:25


Часовой пояс GMT +4, время: 22:25.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot