Форум программистов, компьютерный форум, киберфорум
Наши страницы
Микроконтроллеры Atmega AVR
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.71/7: Рейтинг темы: голосов - 7, средняя оценка - 4.71
gin_1995
0 / 0 / 0
Регистрация: 13.10.2015
Сообщений: 31
1

Timer1 считает до 32768, а не до 65536

31.10.2015, 13:12. Просмотров 1299. Ответов 51
Метки нет (Все метки)

Нужен больший диапазон, т.е. чтобы измерять можно было до 50 тысяч единиц, а на деле получается, что таймер не уходит дальше 32768, переваливая эту цифру он начинает считать в обратном порядке но уже со знаком минус перед числом.
Как его заставить считать в положительной области до конца диапазона? Искренне не могу понять в каком регистре была допущена ошибка.
0
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
31.10.2015, 13:12
Ответы с готовыми решениями:

atmega32A Timer1
возможно ли получить две разных частоты (меиндр) на выводах OC1A и OC1B?...

timer1 - 16 bit
Здравствуйте! Тренируюсь в avr studyo 5 c симулятором на tiny2313 по М.С....

Предделитель Timer/Counter2 на Atmega162 на 32768
Доброе время суток. Хочу на Atmega162 (Toss0/Toss1) повесить часовой кварц. Но...

Atmega8 не работает Timer1
Не могу понять в чем проблема, Timer0 запустил и работает, а первый вообще не...

Настройка Timer1 на ATtiny2313
Стараюсь настроить Timer1 на время 0.01секунды при частоте 4Мгц , но при...

51
VladimirU
132 / 110 / 20
Регистрация: 14.02.2013
Сообщений: 799
01.11.2015, 00:13 21
Тогда используйте unsigned long
0
gin_1995
0 / 0 / 0
Регистрация: 13.10.2015
Сообщений: 31
01.11.2015, 00:17  [ТС] 22
VladimirU, уже пытался
это не помогает, и ситуация аналогична описанной мной ранее.
0
VladimirU
132 / 110 / 20
Регистрация: 14.02.2013
Сообщений: 799
01.11.2015, 11:47 23
Продолжаем разговор.
Что такое pause ? Переменная?
0
gin_1995
0 / 0 / 0
Регистрация: 13.10.2015
Сообщений: 31
01.11.2015, 13:05  [ТС] 24
VladimirU, да, это переменная, в неё записывается данные с регистров TCNT1(H/L) путём pause=TCNT1, т.к. в итоге данные с двух регистров объединяются в этот один для считывания. Потом нужный результат выводится на ТЖКИ, т.е. время, которое насчитал счётчик до того момента, пока не поступает нарастающий фронт. В случае, если мы выходим за пределы допустимого диапазона, т.е. за 65536, должен поступить сигнал о том, что на ТЖКИ надо вывести сообщение о том, что пауза больше граничного числа.
0
ValeryS
Модератор
7401 / 5599 / 710
Регистрация: 14.02.2011
Сообщений: 19,047
Завершенные тесты: 1
01.11.2015, 15:18 25
gin_1995, ты чего накрутил?
я тебе показал два способа а ты оба загнал в свою программу
выбери один и перепиши программу
приведи сюда листинг
и сообщи что значит
Цитата Сообщение от gin_1995 Посмотреть сообщение
всё равно не работает,
что именно и как не работает, и что должно работать?
программа должна подсчитать время нажатия кнопки?
1
gin_1995
0 / 0 / 0
Регистрация: 13.10.2015
Сообщений: 31
01.11.2015, 15:45  [ТС] 26
ValeryS,
ты чего накрутил?
я тебе показал два способа а ты оба загнал в свою программу
выбери один и перепиши программу
я и так и так пытался её делать, и как вариант сделал целых два способа.
сейчас сделаю листинг.

Вот, это программа с вторым вашим способом, который заключался в том, что нужно изменить тип используемых данных, он не помог. Выглядит это так, что при задаче числа через источник до 65536 он выводит его верно на ТЖКИ, тут нареканий нет, а при переходе через эту границу, сообщения на ТЖКИ просто начинают моргать. видимо работает так прерывание, но он показывает число 61 тысячу с копейками и так и моргает, а должен выводит сообщение Tpause>65536 и на этом всё как бы.
Кликните здесь для просмотра всего текста

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#include <mega16.h>
#include <stdio.h>
#include <delay.h>
#include "LCD(EasyAVR)_Functions.c" //включение файла с функциями для ЖКИ, включенного как на EasyAVR5A
 
unsigned long pause;             //длительность паузы в целом количестве микросекунд
char string_lcd1[17];           //текстовый буфер для 1-ой строки LCD
char string_lcd2[17];           //текстовый буфер для 2-ой строки LCD
 
 
// External Interrupt 2 service routine
interrupt [EXT_INT2] void ext_int2_isr(void)
    {
        // Place your code here
        if (MCUCSR==0x00)    
            {
                TCCR1A=0x00;   //Регистр TCCR1A служит для задания режимов работы таймера/счётчика 1 (Normal)
                TCCR1B=0x02;   //Скорость счёта ТС1 устанавливается в регистре TCCR1B  (CS12)
                MCUCSR=0x40;   //следующее прерывание (конец паузы) - по фронту
            }
                else
                    {
                        TCCR1A=0x00;    //Таймер остановлен
                        TCCR1B=0x00;    //Таймер остановлен
                        pause=TCNT1;    //Когда CPU производит запись в старший байт (TCNT1H) записываемые данные  
                                        //размещаются в регистре TEMP. Затем, когда CPU производит запись в младший байт (TCNT1L)
                                        //данные младшего байта объединяются с байтом данных регистра TEMP и все 16 битов 
                                        //одновременно переписываются в регистр таймера/счетчика TCNT1.
                        TCNT1H=0x00;    //сброс TCNT1(H/l) для подготовки к следующему измерению
                        TCNT1L=0x00;    //сброс TCNT1(H/l) для подготовки к следующему измерению
                        MCUCSR=0x00;    //следующее прерывание INT2 - по срезу 
                    }
            }           
 
// Timer1 input capture interrupt service routine
interrupt [TIM1_CAPT] void timer1_capt_isr(void)
    {
        // Place your code here
        pause+=65536;    //метка переполнения pause > 65535
        TCCR1A=0x00;    //Останов TCNT1(H/L)
        TCCR1B=0x00;    //Останов TCNT1(H/L)
        TCNT1H=0x00;    //Обнуление TCNT1(H/L)
        TCNT1L=0x00;    //Обнуление TCNT1(H/L)
        MCUCSR=0x00; 
    }
 
void main(void)
    {
        // Input/Output Ports initialization
        PORTD=0x00;
        DDRD=0xFF;
 
        // Timer/Counter 1 initialization
        // Clock source: System Clock
        // Clock value: 8000,000 kHz
        // Mode: Normal top=0xFFFF
        // OC1A output: Disconnected
        // OC1B output: Disconnected
        // Noise Canceler: Off
        // Input Capture on Falling Edge
        // Timer Period: 8,192 ms
        // Timer1 Overflow Interrupt: Off
        // Input Capture Interrupt: On
        // Compare A Match Interrupt: Off
        // Compare B Match Interrupt: Off
        TCCR1A=(0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10);
        TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (0<<WGM12) | (0<<CS12) | (0<<CS11) | (1<<CS10);
        TCNT1H=0x00;
        TCNT1L=0x00;
        ICR1H=0x00;
        ICR1L=0x00;
        OCR1AH=0x00;
        OCR1AL=0x00;
        OCR1BH=0x00;
        OCR1BL=0x00;
 
        // External Interrupt(s) initialization
        // INT0: Off
        // INT1: Off
        // INT2: On
        // INT2 Mode: 
        GICR|=0x20;
        MCUCR=0x00;
        MCUCSR=0x01;            //прерывание INT2 - по срезу
        GIFR=0x20;
        
        // Timer(s)/Counter(s) Interrupt(s) initialization
        TIMSK=(0<<OCIE2) | (0<<TOIE2) | (0<<TICIE1) | (0<<OCIE1A) | (0<<OCIE1B) | (1<<TOIE1) | (0<<OCIE0) | (0<<TOIE0);
 
        sprintf (string_lcd1,"Measuring Pause time");   //Формирование текстового буфера для 1-ой строки LCD
        lcd_init();                                     //Инициализация LCD дисплея
        lcd_write(string_lcd1);                         //Выводим на LCD 1-ю строку текста
        lcd_send(COMMAND, 0xC0);                        //Переходим на 1-е знакоместо второй строки
 
        // Global enable interrupts
        #asm("sei")
 
        while (1)
            {   
                if (pause>65535) // если пауза больше 65536 получается то вывести сообщение о переполнении  
                    sprintf (string_lcd2,"Tpause>65536 mks");    
                else  //в противном случае вывести число в допустимом диапазоне
                    sprintf (string_lcd2,"Tpause=%5u mks",(unsigned long)pause); 
                    //sprintf (string_lcd2,"Tpause=%5d mks",pause);   //Формирование текстового буфера для 2-ой строки LCD
                    lcd_write(string_lcd2); 
                    lcd_send(COMMAND, 0xC0);            //Переходим на 1-е знакоместо второй строки и повторяем все заново
            }                                                       
    }


Теперь вариант с флагом, который вы говорили сделать. Ситуация та же, до границы нормально показывает числа, а после её перехода всё моргает и показывается это число в 61 тысячу с копейками вместо нужного сообщения.
Кликните здесь для просмотра всего текста

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#include <mega16.h>
#include <stdio.h>
#include <delay.h>
#include "LCD(EasyAVR)_Functions.c" //включение файла с функциями для ЖКИ, включенного как на EasyAVR5A
 
unsigned long pause;             //длительность паузы в целом количестве микросекунд
char flag=0;                        //переменная флага переполнения
char string_lcd1[17];           //текстовый буфер для 1-ой строки LCD
char string_lcd2[17];           //текстовый буфер для 2-ой строки LCD
 
 
// External Interrupt 2 service routine
interrupt [EXT_INT2] void ext_int2_isr(void)
    {
        // Place your code here
        if (MCUCSR==0x00)    
            {
                TCCR1A=0x00;   //Регистр TCCR1A служит для задания режимов работы таймера/счётчика 1 (Normal)
                TCCR1B=0x02;   //Скорость счёта ТС1 устанавливается в регистре TCCR1B  (CS12)
                MCUCSR=0x40;   //следующее прерывание (конец паузы) - по фронту
                flag=0;  //обнуление флага переполнения
            }
                else
                    {
                        TCCR1A=0x00;    //Таймер остановлен
                        TCCR1B=0x00;    //Таймер остановлен
                        pause=TCNT1;    //Когда CPU производит запись в старший байт (TCNT1H) записываемые данные  
                                        //размещаются в регистре TEMP. Затем, когда CPU производит запись в младший байт (TCNT1L)
                                        //данные младшего байта объединяются с байтом данных регистра TEMP и все 16 битов 
                                        //одновременно переписываются в регистр таймера/счетчика TCNT1.
                        TCNT1H=0x00;    //сброс TCNT1(H/l) для подготовки к следующему измерению
                        TCNT1L=0x00;    //сброс TCNT1(H/l) для подготовки к следующему измерению
                        MCUCSR=0x00;    //следующее прерывание INT2 - по срезу 
                    }
            }           
 
// Timer1 input capture interrupt service routine
interrupt [TIM1_CAPT] void timer1_capt_isr(void)
    {
        // Place your code here
        flag=1;          //флаг переполнение при условии переполнения
        TCCR1A=0x00;    //Останов TCNT1(H/L)
        TCCR1B=0x00;    //Останов TCNT1(H/L)
        TCNT1H=0x00;    //Обнуление TCNT1(H/L)
        TCNT1L=0x00;    //Обнуление TCNT1(H/L)
        MCUCSR=0x00; 
    }
 
void main(void)
    {
        // Input/Output Ports initialization
        PORTD=0x00;
        DDRD=0xFF;
 
        // Timer/Counter 1 initialization
        // Clock source: System Clock
        // Clock value: 8000,000 kHz
        // Mode: Normal top=0xFFFF
        // OC1A output: Disconnected
        // OC1B output: Disconnected
        // Noise Canceler: Off
        // Input Capture on Falling Edge
        // Timer Period: 8,192 ms
        // Timer1 Overflow Interrupt: Off
        // Input Capture Interrupt: On
        // Compare A Match Interrupt: Off
        // Compare B Match Interrupt: Off
        TCCR1A=(0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10);
        TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (0<<WGM12) | (0<<CS12) | (0<<CS11) | (1<<CS10);
        TCNT1H=0x00;
        TCNT1L=0x00;
        ICR1H=0x00;
        ICR1L=0x00;
        OCR1AH=0x00;
        OCR1AL=0x00;
        OCR1BH=0x00;
        OCR1BL=0x00;
 
        // External Interrupt(s) initialization
        // INT0: Off
        // INT1: Off
        // INT2: On
        // INT2 Mode: 
        GICR|=0x20;
        MCUCR=0x00;
        MCUCSR=0x01;            //прерывание INT2 - по срезу
        GIFR=0x20;
        
        // Timer(s)/Counter(s) Interrupt(s) initialization
        TIMSK=(0<<OCIE2) | (0<<TOIE2) | (0<<TICIE1) | (0<<OCIE1A) | (0<<OCIE1B) | (1<<TOIE1) | (0<<OCIE0) | (0<<TOIE0);
 
        sprintf (string_lcd1,"Measuring Pause time");   //Формирование текстового буфера для 1-ой строки LCD
        lcd_init();                                     //Инициализация LCD дисплея
        lcd_write(string_lcd1);                         //Выводим на LCD 1-ю строку текста
        lcd_send(COMMAND, 0xC0);                        //Переходим на 1-е знакоместо второй строки
 
        // Global enable interrupts
        #asm("sei")
 
        while (1)
            {   
                if (flag==1) //если флаг прерывания по переполнению равен единицы, то вывести сообщение
                    sprintf (string_lcd2,"Tpause>65536 mks");    
                else  //в противном случае вывести число в допустимом диапазоне
                    sprintf (string_lcd2,"Tpause=%5u mks",(unsigned long)pause); 
                    //sprintf (string_lcd2,"Tpause=%5d mks",pause);   //Формирование текстового буфера для 2-ой строки LCD
                    lcd_write(string_lcd2); 
                    lcd_send(COMMAND, 0xC0);            //Переходим на 1-е знакоместо второй строки и повторяем все заново
            }                                                       
    }


что именно и как не работает, и что должно работать?
программа должна подсчитать время нажатия кнопки?
Программа должна выводить, говоря грубо, два сообщения в двух случаях. В случае, если мы на источнике подаём 60 мс, то на ТЖКИ должно появиться Tpause= 60000 mks (первая картинка), в случае, если мы задаём, скажем 80мс, на ТЖКИ должно быть выведено сообщение Tpause>65536 mks, а показывает неправильно и постоянно моргает (вторая картинка). Никаких кнопок нет. Просто сразу же по подключению должна идти обработка. Прикладываю два скрина, показывающих работу.

Вроде всё объяснил.
0
Миниатюры
Timer1 считает до 32768, а не до 65536   Timer1 считает до 32768, а не до 65536  
ValeryS
Модератор
7401 / 5599 / 710
Регистрация: 14.02.2011
Сообщений: 19,047
Завершенные тесты: 1
01.11.2015, 16:28 27
перепиши прерывания так (вариант с long)
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
interrupt [EXT_INT2] void ext_int2_isr(void)
    {
        // Place your code here
        if (MCUCSR==0x00)    
            {
                TCCR1A=0x00;   //Регистр TCCR1A служит для задания режимов работы таймера/счётчика 1 (Normal)
                TCCR1B=0x02;   //Скорость счёта ТС1 устанавливается в регистре TCCR1B  (CS12)
                MCUCSR=0x40;   //следующее прерывание (конец паузы) - по фронту
                pause=0; 
            }
                else
                    {
                        TCCR1A=0x00;    //Таймер остановлен
                        TCCR1B=0x00;    //Таймер остановлен
                        pause+=TCNT1;    //Когда CPU производит запись в старший байт (TCNT1H) записываемые данные  
                                        //размещаются в регистре TEMP. Затем, когда CPU производит запись в младший байт (TCNT1L)
                                        //данные младшего байта объединяются с байтом данных регистра TEMP и все 16 битов 
                                        //одновременно переписываются в регистр таймера/счетчика TCNT1.
                        TCNT1H=0x00;    //сброс TCNT1(H/l) для подготовки к следующему измерению
                        TCNT1L=0x00;    //сброс TCNT1(H/l) для подготовки к следующему измерению
                        MCUCSR=0x00;    //следующее прерывание INT2 - по срезу 
                    }
            }      
interrupt [TIM1_CAPT] void timer1_capt_isr(void)
    {
        // Place your code here
        pause+=65536;    //метка переполнения pause > 65535
 
    }
и скажи что будет
просто у меня сейчас нет компилятора для AVRки под рукой, посему пишу по памяти
1
gin_1995
0 / 0 / 0
Регистрация: 13.10.2015
Сообщений: 31
01.11.2015, 17:47  [ТС] 28
ValeryS, нет, увы не помогло.
при низких значениях, они все моргают часто, т.к. происходит обнуление переменной постоянное.
а при переполнении он всё равно показывает число в 61 тысячу с копейками и никуда дальше не двигается.
если убрать обнуление переменной, то при низких значениях постоянный вывод сообщения о переполнении, а при переполнении опять число в 61 тысячу с копейками.
0
VladimirU
132 / 110 / 20
Регистрация: 14.02.2013
Сообщений: 799
01.11.2015, 18:00 29
Покажите где и как вы объявили переменную pause?
0
gin_1995
0 / 0 / 0
Регистрация: 13.10.2015
Сообщений: 31
01.11.2015, 18:03  [ТС] 30
VladimirU, как обычно, после библиотек
C
1
unsigned long pause;
ещё при выводе на ТЖКИ
C
1
sprintf (string_lcd2,"Tpause=%5u mks",(unsigned long)pause);
0
VladimirU
132 / 110 / 20
Регистрация: 14.02.2013
Сообщений: 799
01.11.2015, 18:14 31
unsigned long pause=0;

когда объявляете переменную глобальную или локальную то не забывайте всегда ей присваивать нулевое значение если нет необходимости присвоение какого то другого конкретного значения.
1
gin_1995
0 / 0 / 0
Регистрация: 13.10.2015
Сообщений: 31
01.11.2015, 18:25  [ТС] 32
VladimirU, хорошо, спасибо. Учту на будущее.
Только это никак не помогло.
0
ValeryS
Модератор
7401 / 5599 / 710
Регистрация: 14.02.2011
Сообщений: 19,047
Завершенные тесты: 1
01.11.2015, 18:48 33
Цитата Сообщение от VladimirU Посмотреть сообщение
е переменную глобальную или локальную то не забывайте всегда ей присваивать нулевое значение
глобальные переменные обнуляются при объявлении
т,е
C
1
2
int a
int a=0;
одно и тожеgin_1995,
так у тебя несколько импульсов что ли?
так она и будет моргать, поскольку pause постоянно обновляется
вот вариант с флагом, проверяй
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#include <mega16.h>
#include <stdio.h>
#include <delay.h>
#include "LCD(EasyAVR)_Functions.c" //включение файла с функциями для ЖКИ, включенного как на EasyAVR5A
 
unsigned long pause;             //длительность паузы в целом количестве микросекунд
char flag=0;                        //переменная флага переполнения
char string_lcd1[17];           //текстовый буфер для 1-ой строки LCD
char string_lcd2[17];           //текстовый буфер для 2-ой строки LCD
 
 
// External Interrupt 2 service routine
interrupt [EXT_INT2] void ext_int2_isr(void)
    {
        // Place your code here
        if (MCUCSR==0x00)    
            {
                TCCR1A=0x00;   //Регистр TCCR1A служит для задания режимов работы таймера/счётчика 1 (Normal)
                TCCR1B=0x02;   //Скорость счёта ТС1 устанавливается в регистре TCCR1B  (CS12)
                MCUCSR=0x40;   //следующее прерывание (конец паузы) - по фронту
                flag=0;  //обнуление флага переполнения
            }
                else
                    {
                        TCCR1A=0x00;    //Таймер остановлен
                        TCCR1B=0x00;    //Таймер остановлен
                        pause=TCNT1;    //Когда CPU производит запись в старший байт (TCNT1H) записываемые данные  
                                        //размещаются в регистре TEMP. Затем, когда CPU производит запись в младший байт (TCNT1L)
                                        //данные младшего байта объединяются с байтом данных регистра TEMP и все 16 битов 
                                        //одновременно переписываются в регистр таймера/счетчика TCNT1.
                        TCNT1H=0x00;    //сброс TCNT1(H/l) для подготовки к следующему измерению
                        TCNT1L=0x00;    //сброс TCNT1(H/l) для подготовки к следующему измерению
                        MCUCSR=0x00;    //следующее прерывание INT2 - по срезу 
                    }
            }           
 
// Timer1 input capture interrupt service routine
interrupt [TIM1_CAPT] void timer1_capt_isr(void)
    {
        // Place your code here
        flag=1;          //флаг переполнение при условии переполнения
        //TCCR1A=0x00;    //Останов TCNT1(H/L) не нужно останавливать таймер
        //TCCR1B=0x00;    //Останов TCNT1(H/L)
       // TCNT1H=0x00;    //Обнуление TCNT1(H/L)  это вообще лишние телодвижения
       // TCNT1L=0x00;    //Обнуление TCNT1(H/L)
       // MCUCSR=0x00;  зачем перестраиваешь внешнее прерывание
    }
 
void main(void)
    {
        // Input/Output Ports initialization
        PORTD=0x00;
        DDRD=0xFF;
 
        // Timer/Counter 1 initialization
        // Clock source: System Clock
        // Clock value: 8000,000 kHz
        // Mode: Normal top=0xFFFF
        // OC1A output: Disconnected
        // OC1B output: Disconnected
        // Noise Canceler: Off
        // Input Capture on Falling Edge
        // Timer Period: 8,192 ms
        // Timer1 Overflow Interrupt: Off
        // Input Capture Interrupt: On
        // Compare A Match Interrupt: Off
        // Compare B Match Interrupt: Off
        TCCR1A=(0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10);
        TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (0<<WGM12) | (0<<CS12) | (0<<CS11) | (1<<CS10);
        TCNT1H=0x00;
        TCNT1L=0x00;
        ICR1H=0x00;
        ICR1L=0x00;
        OCR1AH=0x00;
        OCR1AL=0x00;
        OCR1BH=0x00;
        OCR1BL=0x00;
 
        // External Interrupt(s) initialization
        // INT0: Off
        // INT1: Off
        // INT2: On
        // INT2 Mode: 
        GICR|=0x20;
        MCUCR=0x00;
        MCUCSR=0x01;            //прерывание INT2 - по срезу
        GIFR=0x20;
        
        // Timer(s)/Counter(s) Interrupt(s) initialization
        TIMSK=(0<<OCIE2) | (0<<TOIE2) | (0<<TICIE1) | (0<<OCIE1A) | (0<<OCIE1B) | (1<<TOIE1) | (0<<OCIE0) | (0<<TOIE0);
 
        sprintf (string_lcd1,"Measuring Pause time");   //Формирование текстового буфера для 1-ой строки LCD
        lcd_init();                                     //Инициализация LCD дисплея
        lcd_write(string_lcd1);                         //Выводим на LCD 1-ю строку текста
        lcd_send(COMMAND, 0xC0);                        //Переходим на 1-е знакоместо второй строки
 
        // Global enable interrupts
        #asm("sei")
 
        while (1)
            {   
                if (flag==1) //если флаг прерывания по переполнению равен единицы, то вывести сообщение
                    sprintf (string_lcd2,"Tpause>65536 mks");    
                else  //в противном случае вывести число в допустимом диапазоне
                    sprintf (string_lcd2,"Tpause=%5u mks",(unsigned long)pause); 
                    //sprintf (string_lcd2,"Tpause=%5d mks",pause);   //Формирование текстового буфера для 2-ой строки LCD
                    lcd_write(string_lcd2); 
                    lcd_send(COMMAND, 0xC0);            //Переходим на 1-е знакоместо второй строки и повторяем все заново
            }                                                       
    }
при срабатывании таймеры ты зачем то меняешь условия для внешнего прерывания, я заремарил

я не проверял как у тебя настроены прерывания

подумай о том что индикация у тебя идет постоянно,а нужно выводить когда в pause легитимные значения
1
gin_1995
0 / 0 / 0
Регистрация: 13.10.2015
Сообщений: 31
01.11.2015, 21:06  [ТС] 34
ValeryS, с флагами не работает, и вы не поняли сути.
для проверки подан период в 100 мс, в нём, скажем, 60мс идёт пауза, а остальные 40мс импульс, и на экране должно выводиться Tpause=60000 mks. - так работает верно.
далее
для проверки подан период в 100 мс, в нём, скажем, 80мс идёт пауза, а остальные 20мс импульс, и на экране должно выводиться Tpause>65536 mks. - это сделать не получается никак.

на железе же подключается генератор, который регулирует время этой паузы но в реальном веремени, т.е. от 0 и до конца возможностей этого генератора, и за это время меняются значения, и как только значения переступят 65536 должно выводиться сообщение Tpause>65536 mks до тех пор, пока не будут поданы меньшие значения, и эта надпись сменится, например на Tpause=60000 mks. я уже не знаю как более развёрнуто пояснить то, что нужно.

в вашем же примере с флагами, не понятно, по какой причине он переключится на единицу, условие для этого какое? как я понимаю, сначала он равен нуля, а потом с чего-то должен стать равен единице. для этого надо включить прерывание по переполнению в микроконтроллере?

да, индикация идёт постоянно и на ней постоянно меняются значения когда в pause легитимные значения, и показывает одно неизменное значение, когда в pause не легитимные значения.

Добавлено через 2 часа 2 минуты
ValeryS,
прошу прощения, не сразу заметил это ваше замечание
при срабатывании таймеры ты зачем то меняешь условия для внешнего прерывания, я заремарил
почему я так сделал, ну логика была такая, что если идёт переполнение, то мы обнуляем все регистры для подготовки к следующему измерению. поэтому меня условия. возможно я просто не так это делал. но при всём при этом это не дало никаких результатов.
0
ValeryS
Модератор
7401 / 5599 / 710
Регистрация: 14.02.2011
Сообщений: 19,047
Завершенные тесты: 1
02.11.2015, 07:57 35
Цитата Сообщение от gin_1995 Посмотреть сообщение
в вашем же примере с флагами, не понятно, по какой причине он переключится на единицу, условие для этого какое?
при переполнении таймера флаг устанавливается в 1 т.е счетчик таймера досчитал до 65535 и при следующем тике будет 0 и сработает прерывание где и установится флаг,флаг- переполнения
а в основной программе проверяется если он установлен то выводится "Tpause>65536 mks"
Цитата Сообщение от gin_1995 Посмотреть сообщение
то мы обнуляем все регистры для подготовки к следующему измерению.
и в результате ты меняешь условия внешнего прерывания вместо спада он опять ждет фронт
а если его не будет? одиночный импульс например
у меня нет сейчас времени подробно проанализировать твою программу и поэтому советы такие "драные"
все что ты изобретаешь давно известно под именем частотомер с методом обратного отсчета
поищи и почитай теорию
главная проблема твоей программы, что постоянно выдается измеряемый сигнал, а нужно его где то зафиксировать и выдавать только тогда когда замер закончен
1
gin_1995
0 / 0 / 0
Регистрация: 13.10.2015
Сообщений: 31
02.11.2015, 11:05  [ТС] 36
ValeryS, спасибо, попытался учесть ваши рекомендации, пересобрав проект с нуля.
теперь всё работает хорошо, почти, теперь сообщение выводится при переполнении, но она быстро сменяется числом которое идёт от нуля за переполнение, но потом опять сообщение о переполнении, т.е. моргает вот так вот. Т.е. если я ему подаю, скажем, 80 мс, то он выводит сначала сообщение Tpause>65536, а потом резко переключается на Tpause=14464, и вот так вот они друг друга сменяют через доли секунды. Но это я думаю из-за того, как вы сказали, что нет фиксации измерения, если я правильно понял. Может тут надо добавить ожидание, типа команды delay(50) или чего-то подобного?

Вот кусок кода:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/*******************************************************
Chip type               : ATmega16
Program type            : Application
AVR Core Clock frequency: 8,000000 MHz
Memory model            : Small
External RAM size       : 0
Data Stack size         : 256
*******************************************************/
 
#include <mega16.h>
#include <stdio.h>
#include <delay.h>
#include "LCD(EasyAVR)_Functions.c" //включение файла с функциями для ЖКИ, включенного как на EasyAVR5A
 
// Declare your global variables here
unsigned long pause=0;             //длительность паузы в целом количестве микросекунд
char flag=0;                        //переменная флага переполнения
char string_lcd1[17];           //текстовый буфер для 1-ой строки LCD
char string_lcd2[17];           //текстовый буфер для 2-ой строки LCD
 
// External Interrupt 2 service routine
interrupt [EXT_INT2] void ext_int2_isr(void)
    {
    // Place your code here
        if (MCUCSR==0x00)    
            {
                TCCR1A=0x00;   //Регистр TCCR1A служит для задания режимов работы таймера/счётчика 1 (Normal)
                TCCR1B=0x02;   //Скорость счёта ТС1 устанавливается в регистре TCCR1B  (CS12)
                MCUCSR=0x40;   //следующее прерывание (конец паузы) - по фронту
                flag=0;  //обнуление флага переполнения
            }
        else
            {
            TCCR1A=0x00;    //Таймер остановлен
            TCCR1B=0x00;    //Таймер остановлен
            pause=TCNT1;    //Когда CPU производит запись в старший байт (TCNT1H) записываемые данные  
                            //размещаются в регистре TEMP. Затем, когда CPU производит запись в младший байт (TCNT1L)
                            //данные младшего байта объединяются с байтом данных регистра TEMP и все 16 битов 
                            //одновременно переписываются в регистр таймера/счетчика TCNT1.
            TCNT1H=0x00;    //сброс TCNT1(H/l) для подготовки к следующему измерению
            TCNT1L=0x00;    //сброс TCNT1(H/l) для подготовки к следующему измерению
            MCUCSR=0x00;    //следующее прерывание INT2 - по срезу 
            }
    }
 
// Timer1 overflow interrupt service routine
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
    {
        // Place your code here
        flag=1;          //флаг переполнение при условии переполнения
    }
 
void main(void)
    {
    // Declare your local variables here
 
    // Port D initialization
    PORTD=0x00;
    DDRD=0xFF;
        
    // Timer/Counter 1 initialization
    // Clock source: System Clock
    // Clock value: 8000,000 kHz
    // Mode: Normal top=0xFFFF
    // OC1A output: Disconnected
    // OC1B output: Disconnected
    // Noise Canceler: On
    // Input Capture on Falling Edge
    // Timer Period: 8,192 ms
    // Timer1 Overflow Interrupt: On
    // Input Capture Interrupt: Off
    // Compare A Match Interrupt: Off
    // Compare B Match Interrupt: Off
    TCCR1A=(0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10);
    TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (0<<WGM12) | (0<<CS12) | (0<<CS11) | (1<<CS10);
    TCNT1H=0x00;
    TCNT1L=0x00;
    ICR1H=0x00;
    ICR1L=0x00;
    OCR1AH=0x00;
    OCR1AL=0x00;
    OCR1BH=0x00;
    OCR1BL=0x00;
 
    // Timer(s)/Counter(s) Interrupt(s) initialization
    TIMSK=(0<<OCIE2) | (0<<TOIE2) | (0<<TICIE1) | (0<<OCIE1A) | (0<<OCIE1B) | (1<<TOIE1) | (0<<OCIE0) | (0<<TOIE0);
 
    // External Interrupt(s) initialization
    // INT0: Off
    // INT1: Off
    // INT2: On
    // INT2 Mode: Falling Edge
    GICR|=(0<<INT1) | (0<<INT0) | (1<<INT2);
    MCUCR=(0<<ISC11) | (0<<ISC10) | (0<<ISC01) | (0<<ISC00);
    MCUCSR=(0<<ISC2);
    GIFR=(0<<INTF1) | (0<<INTF0) | (1<<INTF2);
 
    sprintf (string_lcd1,"Measuring Pause time");   //Формирование текстового буфера для 1-ой строки LCD
    lcd_init();                                     //Инициализация LCD дисплея
    lcd_write(string_lcd1);                         //Выводим на LCD 1-ю строку текста
    lcd_send(COMMAND, 0xC0);                        //Переходим на 1-е знакоместо второй строки
 
// Global enable interrupts
#asm("sei")
 
while (1)
      {
        // Place your code here
        if (flag==1)                //если флаг прерывания по переполнению равен единицы, то вывести сообщение 
        sprintf (string_lcd2,"Tpause>65536 mks");    
        else                        //в противном случае вывести число в допустимом диапазоне
        sprintf (string_lcd2,"Tpause=%5u mks",(unsigned long)pause); 
        lcd_write(string_lcd2); 
        lcd_send(COMMAND, 0xC0);    //Переходим на 1-е знакоместо второй строки и повторяем все заново
      }
}
0
ValeryS
Модератор
7401 / 5599 / 710
Регистрация: 14.02.2011
Сообщений: 19,047
Завершенные тесты: 1
02.11.2015, 11:17 37
Цитата Сообщение от gin_1995 Посмотреть сообщение
Может тут надо добавить ожидание, типа команды delay(50) или чего-то подобного?
нет
здесь можно ввести еще один флаг flagDisplay

когда измерение закончено устанавливается в 1
и далее в main

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
while(1)
{
if(flagDisplay==1)
 {
   flagDisplay=0;
    lcd_send(COMMAND, 0xC0);  
        if (flag==1) 
           sprintf (string_lcd2,"Tpause>65536 mks");    
        else                      
            sprintf (string_lcd2,"Tpause=%5u mks",(unsigned long)pause); 
        lcd_write(string_lcd2); 
     
 
 }
 
 
}
индикация будет обновляться, только тогда когда данные корректны
это один из возможных путей
1
gin_1995
0 / 0 / 0
Регистрация: 13.10.2015
Сообщений: 31
02.11.2015, 11:27  [ТС] 38
ValeryS, спасибо большое! теперь всё работает как часы!
когда надо показывается число, когда переполнение - сообщение!
вот кусок кода.
Кликните здесь для просмотра всего текста
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#include <mega16.h>
#include <stdio.h>
#include <delay.h>
#include "LCD(EasyAVR)_Functions.c" //включение файла с функциями для ЖКИ, включенного как на EasyAVR5A
 
// Declare your global variables here
unsigned long pause=0;             //длительность паузы в целом количестве микросекунд
char flag=0;                        //переменная флага переполнения
char flagDisplay=0;
char string_lcd1[17];           //текстовый буфер для 1-ой строки LCD
char string_lcd2[17];           //текстовый буфер для 2-ой строки LCD
 
// External Interrupt 2 service routine
interrupt [EXT_INT2] void ext_int2_isr(void)
    {
    // Place your code here
        if (MCUCSR==0x00)    
            {
                TCCR1A=0x00;   //Регистр TCCR1A служит для задания режимов работы таймера/счётчика 1 (Normal)
                TCCR1B=0x02;   //Скорость счёта ТС1 устанавливается в регистре TCCR1B  (CS12)
                MCUCSR=0x40;   //следующее прерывание (конец паузы) - по фронту
                flag=0;  //обнуление флага переполнения
                flagDisplay=0;
            }
        else
            {
            TCCR1A=0x00;    //Таймер остановлен
            TCCR1B=0x00;    //Таймер остановлен
            pause=TCNT1;    //Когда CPU производит запись в старший байт (TCNT1H) записываемые данные  
                            //размещаются в регистре TEMP. Затем, когда CPU производит запись в младший байт (TCNT1L)
                            //данные младшего байта объединяются с байтом данных регистра TEMP и все 16 битов 
                            //одновременно переписываются в регистр таймера/счетчика TCNT1.
            TCNT1H=0x00;    //сброс TCNT1(H/l) для подготовки к следующему измерению
            TCNT1L=0x00;    //сброс TCNT1(H/l) для подготовки к следующему измерению
            MCUCSR=0x00;    //следующее прерывание INT2 - по срезу 
            flagDisplay=1;}
    }
 
// Timer1 overflow interrupt service routine
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
    {
        // Place your code here
        flag=1;          //флаг переполнение при условии переполнения
        
    }
 
void main(void)
    {
    // Declare your local variables here
 
    // Port D initialization
    PORTD=0x00;
    DDRD=0xFF;
        
    // Timer/Counter 1 initialization
    // Clock source: System Clock
    // Clock value: 8000,000 kHz
    // Mode: Normal top=0xFFFF
    // OC1A output: Disconnected
    // OC1B output: Disconnected
    // Noise Canceler: On
    // Input Capture on Falling Edge
    // Timer Period: 8,192 ms
    // Timer1 Overflow Interrupt: On
    // Input Capture Interrupt: Off
    // Compare A Match Interrupt: Off
    // Compare B Match Interrupt: Off
    TCCR1A=(0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10);
    TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (0<<WGM12) | (0<<CS12) | (0<<CS11) | (1<<CS10);
    TCNT1H=0x00;
    TCNT1L=0x00;
    ICR1H=0x00;
    ICR1L=0x00;
    OCR1AH=0x00;
    OCR1AL=0x00;
    OCR1BH=0x00;
    OCR1BL=0x00;
 
    // Timer(s)/Counter(s) Interrupt(s) initialization
    TIMSK=(0<<OCIE2) | (0<<TOIE2) | (0<<TICIE1) | (0<<OCIE1A) | (0<<OCIE1B) | (1<<TOIE1) | (0<<OCIE0) | (0<<TOIE0);
 
    // External Interrupt(s) initialization
    // INT0: Off
    // INT1: Off
    // INT2: On
    // INT2 Mode: Falling Edge
    GICR|=(0<<INT1) | (0<<INT0) | (1<<INT2);
    MCUCR=(0<<ISC11) | (0<<ISC10) | (0<<ISC01) | (0<<ISC00);
    MCUCSR=(0<<ISC2);
    GIFR=(0<<INTF1) | (0<<INTF0) | (1<<INTF2);
 
    sprintf (string_lcd1,"Measuring Pause time");   //Формирование текстового буфера для 1-ой строки LCD
    lcd_init();                                     //Инициализация LCD дисплея
    lcd_write(string_lcd1);                         //Выводим на LCD 1-ю строку текста
    lcd_send(COMMAND, 0xC0);                        //Переходим на 1-е знакоместо второй строки
 
// Global enable interrupts
#asm("sei")
 
while(1)
{
if(flagDisplay==1)
 {
   flagDisplay=0;
    lcd_send(COMMAND, 0xC0);  
        if (flag==1) 
           sprintf (string_lcd2,"Tpause>65536 mks");    
        else                      
            sprintf (string_lcd2,"Tpause=%5u mks",(unsigned long)pause); 
            lcd_write(string_lcd2); 
}
}


а такой вопрос, уже больше к железу.
на железе это будет работать, грубо говоря, нормально? т.е. там, как я говорил ранее, принцип в том, что постоянно меняется длительность паузы ... индикация тоже будет постоянно меняться, в зависимости от легитимности значений?
0
ValeryS
Модератор
7401 / 5599 / 710
Регистрация: 14.02.2011
Сообщений: 19,047
Завершенные тесты: 1
02.11.2015, 11:30 39
Цитата Сообщение от gin_1995 Посмотреть сообщение
а такой вопрос, уже больше к железу.
на железе это будет работать, грубо говоря, нормально?
если не учитывать некоторых тонкостей, типа подключенного кварца, фьюзов,обвязки камня, в частности конденсаторов, качества сигнала, то железо будет работать как и протеус
1
gin_1995
0 / 0 / 0
Регистрация: 13.10.2015
Сообщений: 31
02.11.2015, 11:31  [ТС] 40
ValeryS, а, ну тогда всё замечательно. тестироватся это всё будет на EasyAVR с каким-то добротным дорогим генератором.
Спасибо вам за консультацию.
0
02.11.2015, 11:31
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
02.11.2015, 11:31

Записать на лист более 65536 строк
Возникла необходимость записи более 65536 строк на лист. Excel выкидует...

Ошибка: out of memory allocating 65536 bytes
ТО есть, ребята. компилирую прогу, 4 подключаемых файлы суть массивы символов,...

Вывод числа +32768
как вывести на экран число +32768d, ведь оно -32768d 8000h И постоянно...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru