Форум программистов, компьютерный форум, киберфорум
Наши страницы
Микроконтроллеры 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. Просмотров 1324. Ответов 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
paskal
450 / 299 / 28
Регистрация: 15.08.2011
Сообщений: 922
31.10.2015, 13:41 2
Наверно режим таймера не тот установлен.
Только вам конкретно никто ничего не скажет пока вы не расскажете какой процессор, какой включаете режим, итп.
0
gin_1995
0 / 0 / 0
Регистрация: 13.10.2015
Сообщений: 31
31.10.2015, 13:47  [ТС] 3
paskal,
Не знаю, правильно ли я понял, что от меня требуется, но попытаюсь объяснить:
atmega16
Timer/Counter 1 initialization
Clock source: System Clock
Clock value: 8000,000 kHz
Mode: Normal top=0xFFFF
Noise Canceler: Off
Input Capture on Falling Edge
Timer Period: 8,192 ms
Input Capture Interrupt: On
0
ValeryS
Модератор
7407 / 5604 / 711
Регистрация: 14.02.2011
Сообщений: 19,069
Завершенные тесты: 1
31.10.2015, 16:25 4
Лучший ответ Сообщение было отмечено ValeryS как решение

Решение

gin_1995,
используй unsigned int а не int
32767 это 0x7FFF после добавления 1 получится 0x8000
так эти 0x8000 int видит как минус 32768
unsigned int как 32768
1
gin_1995
0 / 0 / 0
Регистрация: 13.10.2015
Сообщений: 31
31.10.2015, 17:46  [ТС] 5
ValeryS, к сожалению, не помогло. Всё равно он так же считает обратно, перевалив за 32767 и пошло -32767, -32766 и т.д. до общего числа "65535" и начинает считать от нуля и выше.
а такой вопрос, как правильно снимать данные с регистров TCNT1H/TCNT1L ?
я делаю так
C
1
pause=TCNT1;
т.к. когда CPU производит запись в старший байт (TCNT1H) записываемые данные размещаются в регистре TEMP. Затем, когда CPU производит запись в младший байт (TCNT1L) данные младшего байта объединяются с байтом данных регистра TEMP и все 16 битов одновременно переписываются в регистр таймера/счетчика TCNT1. Может быть проблема в том, что я не так снимаю данные.
0
ValeryS
Модератор
7407 / 5604 / 711
Регистрация: 14.02.2011
Сообщений: 19,069
Завершенные тесты: 1
31.10.2015, 18:37 6
Цитата Сообщение от gin_1995 Посмотреть сообщение
Всё равно он так же считает обратно, перевалив за 32767 и пошло -32767, -32766 и т.д. до общего числа "65535" и начинает считать от нуля и выше.
не может такого быть
как ты смотришь числа?
приведи кусок кода
1
gin_1995
0 / 0 / 0
Регистрация: 13.10.2015
Сообщений: 31
31.10.2015, 18:42  [ТС] 7
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
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)   //в случае переполнения
                    sprintf (string_lcd2,"Tpause>65536 mks");    
                else  //в случае если доступное число
                    sprintf (string_lcd2,"Tpause=%5d mks",pause);   //Формирование текстового буфера для 2-ой строки LCD
                    lcd_write(string_lcd2); 
                    lcd_send(COMMAND, 0xC0);            //Переходим на 1-е знакоместо второй строки
                                                        //и повторяем все заново
            }                                                       
    }
0
gin_1995
0 / 0 / 0
Регистрация: 13.10.2015
Сообщений: 31
31.10.2015, 18:44  [ТС] 8
ValeryS, вот что показывает мне ТЖКИ при 55мс
0
Миниатюры
Timer1 считает до 32768, а не до 65536  
ValeryS
Модератор
7407 / 5604 / 711
Регистрация: 14.02.2011
Сообщений: 19,069
Завершенные тесты: 1
31.10.2015, 18:53 9
Цитата Сообщение от gin_1995 Посмотреть сообщение
pause=65536; * *//метка переполнения pause > 65535
равносильно что ты написал 0
у int (16 бит) диапазон 0-65535
не вижу как объявлен pause
должен быть так
C
1
unsigned int pause;
1
gin_1995
0 / 0 / 0
Регистрация: 13.10.2015
Сообщений: 31
31.10.2015, 18:56  [ТС] 10
ValeryS, пардон, не захватил верхнюю часть кода.

C
1
2
3
4
5
6
7
8
#include <mega16.h>
#include <stdio.h>
#include <delay.h>
#include "LCD(EasyAVR)_Functions.c" //включение файла с функциями для ЖКИ, включенного как на EasyAVR5A
 
unsigned int pause;             //длительность паузы в целом количестве микросекунд
char string_lcd1[16];           //текстовый буфер для 1-ой строки LCD
char string_lcd2[16];           //текстовый буфер для 2-ой строки LCD
всё объявлено, как вы советовали заранее
0
ValeryS
Модератор
7407 / 5604 / 711
Регистрация: 14.02.2011
Сообщений: 19,069
Завершенные тесты: 1
31.10.2015, 18:59 11
Цитата Сообщение от gin_1995 Посмотреть сообщение
sprintf (string_lcd2,"Tpause=%5d mks",pause); * //Формирование текстового буфера для 2-ой строки LCD
напиши так
C
1
 sprintf (string_lcd2,"Tpause=%5u mks",(unsigned int)pause);
%d выводит число со знаком
%u выводит число без знака

Добавлено через 2 минуты
Цитата Сообщение от gin_1995 Посмотреть сообщение
char string_lcd1[16];
нужно, как минимум
C
1
char string_lcd1[17];
16 знаков плюс терминальный 0
тоже и для второй строки
1
gin_1995
0 / 0 / 0
Регистрация: 13.10.2015
Сообщений: 31
31.10.2015, 19:02  [ТС] 12
ValeryS, спасибо! сам бы не додумался.
но теперь не срабатывает прерывание. как его правильно настроить, чтобы он прерывал при достижении 65536? когда я это делал до 32 тысяч с копейками, всё срабатывало и выводил сообщение при переполнении. а теперь при аналогичной схеме показывает сообщение 61057 и не выводит нужное сообщение.
0
ValeryS
Модератор
7407 / 5604 / 711
Регистрация: 14.02.2011
Сообщений: 19,069
Завершенные тесты: 1
31.10.2015, 19:12 13
Цитата Сообщение от gin_1995 Посмотреть сообщение
но теперь не срабатывает прерывание.
прерывание то срабатывает
но число не может быть больше чем 65535
1 тут несколько путей решения использовать сторонний флаг, который возводить в прерывании
2 использовать переменную pause больше чем 16 бит
типа
C
1
unsigned long int pause;
или
C
1
unsigned long long int pause;
тогда сможешь написать в прерывании
C
1
2
3
4
5
6
interrupt [TIM1_CAPT] void timer1_capt_isr(void) //диагностирование переполнения таймера
    {
        // Place your code here
        pause+=65536;  
..................
    }
1
gin_1995
0 / 0 / 0
Регистрация: 13.10.2015
Сообщений: 31
31.10.2015, 19:19  [ТС] 14
ValeryS, к сожалению, второй путь не помог почему-то.
всё равно прыгает сообщение с 61 тысячью и копейками.
а более никак по данному пути не получится пройти?

а что за первый путь, подробнее можно?
0
VladimirU
132 / 110 / 20
Регистрация: 14.02.2013
Сообщений: 799
31.10.2015, 20:29 15
Запишите не так
C++
1
if (pause>65535)
а вот так
C++
1
if (pause>0XFFFE)
0
gin_1995
0 / 0 / 0
Регистрация: 13.10.2015
Сообщений: 31
31.10.2015, 20:43  [ТС] 16
VladimirU, увы, но нет. всё равно тоже самое. вместо вывода сообщения о переполненни Tpause>65536 mks, он выводит Tpause=61057 mks, которое постоянно моргает.
0
ValeryS
Модератор
7407 / 5604 / 711
Регистрация: 14.02.2011
Сообщений: 19,069
Завершенные тесты: 1
31.10.2015, 20:59 17
Цитата Сообщение от gin_1995 Посмотреть сообщение
а что за первый путь, подробнее можно?
ну все же просто
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
char flag=0;
................................
interrupt [TIM1_CAPT] void timer1_capt_isr(void) //диагностирование переполнения таймера
    {
        // Place your code here
        flag=1;    //метка переполнения pause > 65535
................................................
    while (1) //вывод на ТЖКИ 
            {   
                if (flag==1)   //в случае переполнения
                    sprintf (string_lcd2,"Tpause>65536 mks");    
                else  //в случае если доступное число
                    sprintf (string_lcd2,"Tpause=%5d mks",pause);   //Формирование текстового буфера для 2-ой строки LCD
                    lcd_write(string_lcd2); 
                    lcd_send(COMMAND, 0xC0);            //Переходим на 1-е знакоместо второй строки
                                                        //и повторяем все заново
когда запускаешь таймер то нужно будет обнулить флаг
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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 - по срезу 
                    }
            }
0
gin_1995
0 / 0 / 0
Регистрация: 13.10.2015
Сообщений: 31
31.10.2015, 22:57  [ТС] 18
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
 
unsigned long int pause;             //длительность паузы в целом количестве микросекунд
char flag;                        //переменная флага переполнения
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
        pause+=65536;    //метка переполнения pause > 65535
        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 int)pause); 
                    //sprintf (string_lcd2,"Tpause=%5d mks",pause);   //Формирование текстового буфера для 2-ой строки LCD
                    lcd_write(string_lcd2); 
                    lcd_send(COMMAND, 0xC0);            //Переходим на 1-е знакоместо второй строки
                                                        //и повторяем все заново
            }                                                       
    }


так же могу приложить основные файлы проекта
0
Вложения
Тип файла: rar 1.rar (98.4 Кб, 1 просмотров)
VladimirU
132 / 110 / 20
Регистрация: 14.02.2013
Сообщений: 799
31.10.2015, 23:54 19
65535 unsigned (int)

как вы хотите проверить

pause>65536
если после 65535 идёт 0.
0
gin_1995
0 / 0 / 0
Регистрация: 13.10.2015
Сообщений: 31
31.10.2015, 23:59  [ТС] 20
VladimirU, ну как-то хочу проверить, потому что это суть задания. На железе можно выдать куда больше чем эти 65536, и я в этом случае должен выдать данное сообщение.
0
31.10.2015, 23:59
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
31.10.2015, 23:59

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

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

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


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

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

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