Форум программистов, компьютерный форум, киберфорум
Наши страницы
Микроконтроллеры 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
Jenykl
12 / 12 / 1
Регистрация: 03.07.2012
Сообщений: 331
18.12.2018, 04:21 41
Доброго времени суток! Такая же ерунда, счетчик считает до 32768, а потом в обратную сторону. Прибор должен был получиться частотомер, но чет как-то только до 32кГц с копейками считает. В МК новичок, может что-то пропустил? Извините за некропост.
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
#define F_CPU 8000000UL // 8MHz частота Atmega8
 
#include <mega8.h> // Библиотека для работы с Atmega8 
#include <lcd.h> // Библиотека для работы с LCD
#include <stdio.h> // Библиотека для ввода/вывода
#include <delay.h> // Библиотека для работы с delay
 
#asm 
   .equ __lcd_port=0x12 // ЖКИ дисплей подключен к порту I/O D
#endasm 
 
unsigned int i = 0, freq = 0; // Объявляем переменные
char lcd_buf[17]; // Массив, в котором будет находиться значение частоты
 
interrupt [EXT_INT1] void ext_int1_isr(void) // Внешнее прерыване INT0 
{
i++; // Увеличиваем на единицу, здесь считается количество входящих импульсов.        
}
 
interrupt [TIM1_COMPA] void timer1_compa_isr(void)// Обработка прерывания по совпадению
{
 freq=i; // Pначение частоты в freq
 i=0; // Обнуляем значение частоты
 TCNT1H=0x00; // Обнуляем счетчик
 TCNT1L=0x00; // Обнуляем счетчик 
}
void main(void) // Основная функция "main", с которой начинается выполнение всей программы
{
//PORTC.0 = ;    
//DDRC.0 = ;
//PORTC.1 = ;    
//DDRC.1 = ;
//PORTC.2 = ;    
//DDRC.2 = ;  
 
PORTD = 0b00001000;
DDRD = 0b00000000;
 
 
//PORTD.3=1; // На порт 2 подключаем встроенный подтягивающий резистор для защиты от помех 
//DDRD.3=0; // Инииализируем порт 2(INT0) как входной
 
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 7,813 kHz
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: On
// Compare B Match Interrupt: Off
TCCR1A=0x00; //Регистр TCCR1A служит для задания режимов работы таймера/счётчика 1 (Normal)
TCCR1B=0x05; 
 
TCNT1H=0x00; // Считаем с нуля
TCNT1L=0x00;
 
ICR1H=0x00;
ICR1L=0x00; 
// Когда досчитали до 7813, то условие выполняется
OCR1A=0x1E85; // Записываем число в регистр сравнения
 
OCR1BH=0x00;
OCR1BL=0x00;
 
 
GICR|=(1<<INT1); // Разрешает внешнее прерывание 1 (т.е INT1)
MCUCR=(1<<ISC11)|(1<<ISC10); // Внешнее прерывание по нарастающему фронту INT1 (логическое изменение из 0 в 1)
GIFR=(1<<INTF1); // Флаг внешнего прерывания 1 
 
TIMSK=(1<<OCIE1A); // Разрешение прерывания по совпадению регистра A с таймером/счетчиком1  
 
#asm("sei") // Глобально разрешаем прерывания 
                 
lcd_init(16); // Инициализация LCD диспеля на 16 символов
 
lcd_gotoxy(2,1); // Со второй позиции на второй строке
lcd_putsf("F =       Hz"); // Выводим надпись с пробелами, между которыми будет значение частоты 
     
while(1) // Бесконечный цикл
    {           
        delay_ms(100); // 
        /*if(freq>31999) // Если частота больше 31999 
        {
        lcd_gotoxy(6,0); // С третьей позиции на первой строке
        lcd_putsf("ERROR"); 
        break; // Останавливаем выполнение цикла while        
        }
        else*/ // Иначе, если частота меньше
        lcd_gotoxy(6,1); // С шестой позиции на второй строке
        sprintf(lcd_buf,"%d",freq); // Записываем в массив lcd_buf freq с помощью sprintf        
        lcd_puts(lcd_buf); // Выводим массив на LCD
    };
}
0
Voland_
1677 / 1022 / 97
Регистрация: 04.01.2010
Сообщений: 3,426
18.12.2018, 09:43 42
объявите переменные
C
1
volatile unsigned int , freq;
но проблема у вас в выводе. Используйте unsigned тип данных для вывода
C
1
sprintf(lcd_buf,"%u",freq);
а лучше вообще что-то типа itoa() использовать, потому что printf'ы очень тяжелые для AVR.
1
COKPOWEHEU
1154 / 817 / 192
Регистрация: 09.09.2017
Сообщений: 3,528
18.12.2018, 09:44 43
Цитата Сообщение от Jenykl Посмотреть сообщение
void main(void)
грубая ошибка: main() имеет тип int и никакой другой.
Цитата Сообщение от Jenykl Посмотреть сообщение
unsigned int i = 0, freq = 0; // Объявляем переменные
нет volatile
Цитата Сообщение от Jenykl Посмотреть сообщение
sprintf(lcd_buf,"%d",freq); // Записываем в массив lcd_buf freq с помощью sprintf
вывод как int, а не как unsigned int. Для беззнакового надо "%u"
Цитата Сообщение от Jenykl Посмотреть сообщение
//PORTD.3=1; // На порт 2 подключаем встроенный подтягивающий резистор для защиты от помех //DDRD.3=0; // Инииализируем порт 2(INT0) как входной // Timer/Counter 1 initialization // Clock source: System Clock // Clock value: 7,813 kHz // Mode: Normal top=FFFFh // OC1A output: Discon. // OC1B output: Discon. // Noise Canceler: Off // Input Capture on Falling Edge
хоть бы мусор за автогенератором прибрали!
Цитата Сообщение от Jenykl Посмотреть сообщение
// Когда досчитали до 7813, то условие выполняется
OCR1A=0x1E85; // Записываем число в регистр сравнения
Что мешало прямо записать OCR1A = 7813; и заодно удалить еще один мусорный комментарий
Цитата Сообщение от Jenykl Посмотреть сообщение
MCUCR=(1<<ISC11)|(1<<ISC10);
А вот это хороший стиль. Вот только боюсь, это "хороший стиль" автогенератора.
1
Jenykl
12 / 12 / 1
Регистрация: 03.07.2012
Сообщений: 331
18.12.2018, 12:03 44
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
грубая ошибка: main() имеет тип int и никакой другой.
CVAVR так сделал, тоже не понимал почему, но работает. Делаю int и ругается сразу. Как бы main уже должен возвращать значение , дописываю return 0; в конце и ошибка. Ладно.

Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
нет volatile
volatile - переменная, которая может изменяться извне? Но почему до этого оно работало? Симулирую в протеусе, может из-за него разницы нет?

Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
хоть бы мусор за автогенератором прибрали!
Оставил на всякий случай)
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Что мешало прямо записать OCR1A = 7813; и заодно удалить еще один мусорный комментарий
Немного обидно, комментарии сам писал. Буду знать.

Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
А вот это хороший стиль. Вот только боюсь, это "хороший стиль" автогенератора.
До этого было в шестнадцатеричной системе написано, но мне так показалось удобнее и сделал так. Автогенератор лишнего выдавал.

Цитата Сообщение от Voland_ Посмотреть сообщение
а лучше вообще что-то типа itoa() использовать, потому что printf'ы очень тяжелые для AVR.
Помогло с printf поменять %d на %u и теперь выводит как надо . Но с itoa не прокатило, хоть и менял обозначение переменных вначале.
0
COKPOWEHEU
1154 / 817 / 192
Регистрация: 09.09.2017
Сообщений: 3,528
18.12.2018, 15:18 45
Цитата Сообщение от Jenykl Посмотреть сообщение
Но почему до этого оно работало?
Случайность. Компилятор может закешировать переменную в регистры, тогда изменения в прерывании не будут замечены в основном коде и наоборот. А может и нет - оставить в оперативке. Чтобы такой неопределенности не было, volatile заставляет всегда сохранять в оперативку. После любой операции. В вашем же случае добрая воля компилятора тоже решила, что лучше переменной полежать в оперативке, а не в регистрах. Но его решение может легко измениться при изменении кода.
Цитата Сообщение от Jenykl Посмотреть сообщение
Немного обидно, комментарии сам писал. Буду знать.
Используйте то представление, которое соответствует сути. Если у вас счетчик, лучше десятичное, если набор несвязанных битов - сдвиги и сложения (1<<x | 1<<y), если системная константа, то шестнадцатеричное. Если одного представления недостаточно, стоит добавить комментарий.
Даже в вашем случае число 7813 ни о чем не говорит, поэтому комментарий бесполезен. Вот если в нем расписать откуда это число взялось и для чего нужно - другое дело. А еще лучше если записывать не просто число, а макрос, в котором оно вычисляется из каких-то других, человекочитаемых данных. Помимо прочего это страховка от ошибок
Цитата Сообщение от Jenykl Посмотреть сообщение
До этого было в шестнадцатеричной системе написано, но мне так показалось удобнее и сделал так. Автогенератор лишнего выдавал
В таком случае правильно сделали. Подобные настройки в шестнадцатеричном виде совершенно нечитаемы.
Цитата Сообщение от Jenykl Посмотреть сообщение
Но с itoa не прокатило
Возможно, itoa считает, что ему передают int. Посмотрите на другие функции: utoa, ltoa, ultoa
0
Jenykl
12 / 12 / 1
Регистрация: 03.07.2012
Сообщений: 331
18.12.2018, 16:17 46
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Посмотрите на другие функции: utoa, ltoa, ultoa
А вот в сними не хочет, пишет в cvavr что нет таких. Подключал библиотеку stdlib.h для itoa. А для них какая нужна?
0
COKPOWEHEU
1154 / 817 / 192
Регистрация: 09.09.2017
Сообщений: 3,528
18.12.2018, 16:40 47
по идее, avr_stdlib
но это все нестандартные библиотеки, даже itoa, в современном Си таких нет.
Лучше реализуйте такую самостоятельно или в крайнем случае тот же sprintf
0
Jenykl
12 / 12 / 1
Регистрация: 03.07.2012
Сообщений: 331
18.12.2018, 16:50 48
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Лучше реализуйте такую самостоятельно или в крайнем случае тот же sprintf
Лучше уже оставлю как есть, не тот случае, наверное, чтобы запариваться.
Можно еще тогда пару вопросов? TCNT1H=0x00; TCNT1L=0x00; - их я могу заменить на TCNT1=0? разницы тут нет получается.
И вот эти не до конца понял зачем, без них тоже работает, нужны ли они? или тоже побочные от "автогенератора"
ICR1H=0x00;
ICR1L=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
В других источника видел, что таймер объявляли и без этих регистров.
0
COKPOWEHEU
1154 / 817 / 192
Регистрация: 09.09.2017
Сообщений: 3,528
19.12.2018, 10:00 49
Лучше всего инициализировать все регистры, которые влияют на вашу периферию, даже если нулями: мало ли что там было до начала настройки. В некоторых случаях, обычно при инициализации нулями, это может показаться избыточным, но ведь программа может начаться не только при включении питания, но и вследствие программного сброса, сторожевой собаки, запуска из bootloader'а. А там кто знает какое значение им задали.
Исключение - тот самый bootloader если приходится экономить каждый байт исходного кода, тогда можно рискнуть и оставить регистры настроенными по умолчанию. Но это большая редкость.
А вот те регистры, которые ни на что не повлияют, можно и не инициализировать. Скажем, если UART не используется, настраивать UBRR не нужно. Так же и у вас: если канал B таймера не используется, значение OCR1B безразлично. Если не используется счет до ICR1 и не используется захват таймера, настройка ICR1 тоже не нужна.
Цитата Сообщение от Jenykl Посмотреть сообщение
Можно еще тогда пару вопросов? TCNT1H=0x00; TCNT1L=0x00; - их я могу заменить на TCNT1=0?
Попробуйте - узнаете Некоторые 16-битные регистры объединены в один, позволяют 16-битный доступ, некоторые нет. Скажем, UBRR (UBRRH:UBRRL) представлен только как отдельные регистры и доступа к UBRR нет. Но вот таймеры, если я правильно помню, позволяют 16-битный доступ.
1
Voland_
1677 / 1022 / 97
Регистрация: 04.01.2010
Сообщений: 3,426
19.12.2018, 15:48 50
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Попробуйте - узнаете Некоторые 16-битные регистры объединены в один, позволяют 16-битный доступ, некоторые нет. Скажем, UBRR (UBRRH:UBRRL) представлен только как отдельные регистры и доступа к UBRR нет. Но вот таймеры, если я правильно помню, позволяют 16-битный доступ.
...CVAVR (то есть судя по коду обсуждаем мы именно его) мало того, что поддерживает подобное, он еще и правильно к ним обращается.
1
Jenykl
12 / 12 / 1
Регистрация: 03.07.2012
Сообщений: 331
19.12.2018, 16:25 51
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Попробуйте - узнаете Некоторые 16-битные регистры объединены в один, позволяют 16-битный доступ, некоторые нет. Скажем, UBRR (UBRRH:UBRRL) представлен только как отдельные регистры и доступа к UBRR нет. Но вот таймеры, если я правильно помню, позволяют 16-битный доступ.
Заменял, все нормально работает. Понял, что их нужно для начальной инициализации объявлять (это автогенератор CVAVR сделал), и без них тоже работает)

Цитата Сообщение от Voland_ Посмотреть сообщение
...CVAVR (то есть судя по коду обсуждаем мы именно его) мало того, что поддерживает подобное, он еще и правильно к ним обращается.
Премного благодарен вам обоим, что ответили на мои немного туповатые вопросы) Смотрел информацию по поводу таймеров и попробовал сделать немного проще с 8-битным таймером с прерываниями, прибор так же считает частоту до 65к с копейками.

Хотел сделать вывод на экран ошибки, мол, оно вышло за предел 65000, но ничего годного не вышло. Так как если подать частоту на вход INT0, например 66000, то оно начнет считать сначала, то есть там будет частота 1500 к примеру и сообщение об ошибке не выдаст, т.к. значение то не больше 65 000)))

Этот вопрос не по теме: а нужно ли подключать какие-нибудь резисторы на вход INT0 или диоды, что-нибудь, или хватит просто подавать импульсы на голую ножку?)))
0
COKPOWEHEU
1154 / 817 / 192
Регистрация: 09.09.2017
Сообщений: 3,528
20.12.2018, 10:32 52
Цитата Сообщение от Jenykl Посмотреть сообщение
Заменял, все нормально работает.
Значит можно пользоваться Только помните, что в некоторых случаях такой код не будет переносим на другие компиляторы: gcc, iar. Впрочем, диалекты контроллерного Си в любом случае несовместимы, так что если нужна переносимость, все равно придется городить слой совместимости. В хороших библиотеках так и делают.
Цитата Сообщение от Jenykl Посмотреть сообщение
Этот вопрос не по теме: а нужно ли подключать какие-нибудь резисторы на вход INT0 или диоды, что-нибудь, или хватит просто подавать импульсы на голую ножку?)))
Слишком расплывчатое описание задачи.
Если вы хотите вызывать прерывания кнопкой, просто замыкая вывод на землю (вообще-то это нужно разве что для выхода из сна), то надо либо ставить внешний резистор до питания, либо включать внутренний.
Если в качестве источника прерывания выступает другая микросхема, что бывает чаще, все зависит от нее. Обычно выходы микросхем TTL-совместимые, то есть внешний резистор можно не ставить
1
20.12.2018, 10:32
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
20.12.2018, 10:32

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

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

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


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

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

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