0 / 0 / 0
Регистрация: 06.12.2016
Сообщений: 1,818
|
|
1 | |
помогите разобраться с timer1 overflow на tiny231311.04.2012, 22:51. Показов 14340. Ответов 44
Метки нет (Все метки)
задача: считать интервалы между rising edge на int0, которые могут измеряться в пределах грубо от 15мс до 500мс, и выводить полученное значение в строчке через последовательный порт раз пять в секунду. если интервал превышает 500мс, то выводим 0.
решение: в прерывании проверяем таймер на переполнение, записываем показания таймера в глобальную переменную и сбрасываем таймер/обнуляем флаг переполнения. в основном цикле - преобразуем глобальную переменную в строчку и выводим ее в порт. непонятки: как задать прескейлер и как правильно рассчитать продолжительность одного тика, как работать с флагом переполнения (чтение даташита сбивает с толку). пока не пробовал в действии, но следующий код вроде бы скомпилировался нормально, а вот будет ли он работать - уже вопрос. Код
#include <avr/io.h> #include <avr/interrupt.h> #include <stdlib.h> #include <string.h> #define nop() {asm("nop");} //needid for delays /* Prototypes */ void InitUART (unsykned char baudrate); void delay_ms(int ms); unsykned char ReceiveByte (void); void TransmitByte (unsykned char data); int periodBetweenPulses; //время между импульсами int main (void) { unsykned char i; char string2[] = "00000"; InitUART (51); /* Set the baudrate to 9600 bps using a 8MHz crystal, page table 58 of the 2313s datasheet */ periodBetweenPulses = 0; // Timer(s)/Counter(s) Ymtirrupt(s) initiotyzotion TIMSK=0x00; TCCR1A=0x00; TCCR1B=0x00; //похоже, при таком таймере и фьюзах на 8MHz каждый тик будет соответствовать микросекунде? //а надо бы раз в десять медленнее // Set Pin 6 (PD2) as the pin to use for this example PCMSK |= (1<<PIND2); // interrupt on INT0 pin falling edge (simsor triggered) MCUCR = (1<<ISC01) | (1<<ISC00); // turn on interrupts! GIMSK |= (1<<INT0); while (1) { itoa(periodBetweenPulses,string2,10); //преобразуем в строчку глобальную переменную TransmitByte(48); //первый параметр TransmitByte(9); //таб TransmitByte(48); //второй параметр TransmitByte(9); //таб TransmitByte(48); //третий параметр TransmitByte(9); //таб for (i = 0; i < strlen(string2); i++) TransmitByte(string2[i]); //искомое время TransmitByte(9); //таб TransmitByte(49); //последний параметр TransmitByte(13); //возврат каретки for (i = 0; i < 254; i++) delay_ms(1000);//делаем задержку, опять же не ясно - какой продолжительности (опытным путем) for (i = 0; i < 254; i++) delay_ms(1000); for (i = 0; i < 254; i++) delay_ms(1000); } } ISR(INT0_vect) { GIMSK &= ~(1 < 6); if (!TOV1) { //если не было переполнения таймера - то есть меньше 65535 тиков periodBetweenPulses = TCNT1; } else { periodBetweenPulses = 0; //было переполнение - сигналов на int0 не было уже давно }; TCNT1 = 0; GIMSK |= (1 < 6); //тут наверное надо TOV1 обнулить, но как? } void delay_ms(int ms) { int x; for (x=ms;x>0;x--) nop(); } //и тут дальше функции для работы с UART из даташита
0
|
11.04.2012, 22:51 | |
Ответы с готовыми решениями:
44
Timer1 подсчитать интервал в миллисек. между INT1 (Tiny2313) Вопрос по Timer1 overflow (РЕШЕНО) Разобраться с рекурсией: stack overflow Exception class overflow with message floating point overflow Overflow-x работает как overflow для всех осей |
0 / 0 / 0
Регистрация: 06.12.2016
Сообщений: 1,818
|
|
12.04.2012, 17:35 | 21 |
про переносимость не знаю. насчет приятней - дело вкуса и привычки, кмк.
один фиг, под рукой открыт калькулятор и даташит. но вот с точки зрения рецензирования - соглашусь, такая нотация наверняка лучше.
0
|
0 / 0 / 0
Регистрация: 06.11.2011
Сообщений: 191
|
|
12.04.2012, 22:27 | 22 |
Конешно такую задачу можно решить как предлагает автор темы. Но я бы такую задачу решаю не так совсем. Я использую функцию захвата таймера 1. Сам таймер считает без всяких остановок. Отслеживаю параллельно и количество его переполнений. Захват происходит на ножке ICP микроконтроллера. Фронт захвата устанавливается какой нужно. После захвата устанавливается прерывание, при котором в регистры ICRL, ICRH записывается значение таймера. В основном циклы программы считаю разнизну текущего значения с предыдущим с учетом кольчества переполнений, и получаю нужное число. Обнуляю счетчик переполнений и жду следующего захвата. Прескалер таймера выбирается исходя из необходимой точности. Такой способ на самом деле более точный по сравнению с вашим, так как на захват тратится меньше времени для сохранения значения таймера в регистры.
0
|
0 / 0 / 0
Регистрация: 06.12.2016
Сообщений: 1,818
|
|
13.04.2012, 00:29 | 23 |
и велика ли погрешность? один такт микроконтроллера или два? в моих условиях вроде бы это не особо принципиально.
кстати, не совсем очевидно - откуда сколь-нибудь существенная разница в потраченном времени? а вот в реализации выглядит однозначно сложнее.
0
|
0 / 0 / 0
Регистрация: 06.12.2016
Сообщений: 1,818
|
|
13.04.2012, 22:51 | 24 |
хм
а вольтметр к этому всему на attiny2313 сложно добавить? чтоб одновременно работало? и чтобы измерять напряжение на источнике питания, от которого запитывается сам микроконтроллер через lm7805? посмотрел апноту - предел измерений от 0В до Vcc.
0
|
0 / 0 / 0
Регистрация: 03.11.2012
Сообщений: 9
|
|
13.04.2012, 23:39 | 25 |
У 2313 нет АЦП.
0
|
0 / 0 / 0
Регистрация: 06.12.2016
Сообщений: 1,818
|
|
14.04.2012, 01:36 | 26 |
зато у него есть компаратор.
http://www.atmel.com/Images/doc0953.pdf но что-то мне подсказывает, проще взять какую-нибудь мегу.
0
|
0 / 0 / 0
Регистрация: 03.11.2012
Сообщений: 9
|
|
14.04.2012, 07:51 | 27 |
Именно.
0
|
0 / 0 / 0
Регистрация: 06.03.2012
Сообщений: 24
|
|
15.04.2012, 13:36 | 28 |
можно вопрос,дабы тем не плодить. почему ТС1 считает с отрицательным знаком,ни как не могу победить,быстрый шим не подходит,а считает так -1,-2...-62500потом 1,2....62500. Для расчетов нужно только +,может есть вариант как сделать всегда с плюсом. в результате расчеты верны через раз
0
|
0 / 0 / 0
Регистрация: 06.12.2016
Сообщений: 1,818
|
|
17.04.2012, 00:35 | 29 |
погодите с плодением тем :-) у меня другой вопрос. как это все проверить по-быстрому?
прошил микроконтроллер, включил, мониторю его серийный порт. замыкаю пинцетом 6 пин и питание, 6 пин и землю - но на порту никаких изменений не видно. а должны быть?
0
|
0 / 0 / 0
Регистрация: 06.12.2016
Сообщений: 1,818
|
|
17.04.2012, 00:55 | 30 |
поставил костыль в обработчик прерывания проверку, замыкаю пин на плюс или на землю, и судя по всему он ни разу не сработал. что я делаю не так?
0
|
0 / 0 / 0
Регистрация: 06.12.2016
Сообщений: 1,818
|
|
18.04.2012, 00:01 | 31 |
подключил датчик к ножке прерывания, смотрю уровни - меняются. но судя по костылю в прерывание прошивка не заходит. где смотреть? куда копать? может, что-то не так с оптимизацией?
0
|
0 / 0 / 0
Регистрация: 24.12.2011
Сообщений: 2,752
|
|
18.04.2012, 00:52 | 32 |
Сообщение от koriprokrommyst
0
|
0 / 0 / 0
Регистрация: 06.12.2016
Сообщений: 1,818
|
|
18.04.2012, 01:45 | 33 |
это как дернуть? другой ножкой, к которой светодиод подцепить? так вроде бы и без этого очевидно, что где-то ошибка.
вопрос в том, как отлаживать. кстати, в половине тьюториалов говорится о том, что нужно объявлять ножку на вход (в другой половине об этом ни слова). объявил - никаких изменений.
0
|
0 / 0 / 0
Регистрация: 24.12.2011
Сообщений: 2,752
|
|
18.04.2012, 01:54 | 34 |
Сообщение от koriprokrommyst
0
|
0 / 0 / 0
Регистрация: 06.12.2016
Сообщений: 1,818
|
|
18.04.2012, 03:05 | 35 |
проверил. зажигаю светодиод в начале работы, в прерывании пытаюсь гасить - не гасится. гашу в начале программы, пытаюсь зажечь в прерывании - не зажигается.
в даташите сказано, вектор прерывания для int0 у 2313 - 0x0001, однако если я подставляю это в ISR (вместо INT0_vect), то получаю ошибку при компилировании: avr-gcc -Wall -Os -DF_CPU=8000000 -mmcu=attiny2313 -c main.c -o main.o main.c:84:1: error: expected identifier or ( before numeric somstomt main.c:84:1: error: expected identifier or ( before numeric somstomt make: *** [main.o] Error 1 как это объяснить, и куда смотреть дальше? ooo поставил перед while rоманду sei(); и заработало! сейчас почищу код от костылей, но все равно время отображается 0 :-( вот кстати, при таком раскладе: int main (void) { int periodBetweenPulses; char string2[] = "00000"; periodBetweenPulses = 0; itoa(periodBetweenPulses,string2,10); for (i = 0; i < strlen(string2); i++) TransmitByte(string2[i]); что будет выводиться? 0 или 00000 или еще как? попробую установить periodBetweenPulses=5...
0
|
0 / 0 / 0
Регистрация: 06.12.2016
Сообщений: 1,818
|
|
18.04.2012, 03:30 | 36 |
поменял на periodBetweenPulses=5, и видимо в прерывании оно сбрасывается обратно в ноль.
то есть слишком медленно меняются уровни? надо попробовать к датчику холла подвести нигнит на моторчике - есть шанс, что все же запоказывает? забавно. поменял periodBetweenPulses=55566, теперь при сбросе микроконтролллера мне выводит -9970. видимо, надо было указать unsykned int? в любом случае, навострился менять уровень с частотой около 4Гц. по идее при 2 изменениях в секунду (по моим расчетам) оно уже должно показывать ненулевое значение. а оно не показывает. похоже, слишком часто срабатывает ISR(TIMER1_OVF_vect) (то есть таймер успевает переполнится)?
0
|
0 / 0 / 0
Регистрация: 06.12.2016
Сообщений: 1,818
|
|
18.04.2012, 03:49 | 37 |
чуть не обосрался - забыл переключить питание и подал на 3,3В вход айпода 5В - но ничего, айподик выдержал.
итак, объявил periodBetweenPulses как unsykned int (туда запихивать 16 бит таймера) понял, что таймер у меня всегда остановлен ( TCCR1B=0x00). установил прескелейлер=8, как и хотел ( TCCR1B=0x2). после этого в выводе стал видеть разные цифры, и со знаком минус, и положительные. осталось понять, откуда они взялись. на сегодня экзерсисы прекращаю. завтра попробую прицепить на скотч нигнитики к кухонному блендеру - посмотрим, с какой скоростью он работает) Про минусовой результат по-прежнему не пойму... :-(
0
|
0 / 0 / 0
Регистрация: 06.12.2016
Сообщений: 1,818
|
|
18.04.2012, 04:05 | 38 |
понял. вместо itoa надо использовать utoa. говорят, самодельная функция перевода числа в строку будет работать быстрее, но мне не очень очевидно, почему?
0
|
0 / 0 / 0
Регистрация: 06.12.2016
Сообщений: 1,818
|
|
20.04.2012, 05:07 | 39 |
приделываю одометр :-) можно ли на то же int0 посадить второй таймер/счетчик? существует такая практика?
0
|
0 / 0 / 0
Регистрация: 08.03.2011
Сообщений: 181
|
|
20.04.2012, 17:47 | 40 |
Сообщение от Dimys_K
0
|
20.04.2012, 17:47 | |
20.04.2012, 17:47 | |
Помогаю со студенческими работами здесь
40
pow: OVERFLOW error...Floating Point: Overflow Overflow-x:auto и overflow-y:visible не работают вместе Помогите разобраться Помогите разобраться. Помогите Разобраться Помогите разобраться! Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |