Форум программистов, компьютерный форум, киберфорум
Наши страницы
Микроконтроллеры ATmega AVR
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.63/8: Рейтинг темы: голосов - 8, средняя оценка - 4.63
radist108
1 / 1 / 0
Регистрация: 24.04.2012
Сообщений: 101
1

Не отключается прерывание по таймеру

28.04.2016, 14:27. Просмотров 1545. Ответов 22
Метки нет (Все метки)

Приветствую всех!
Обращаюсь к знатокам за помощью.
Проблема такая. Не отключается прерывание по таймеру. Смысл программы в следующем:
от прерывания по UART запускается таймер. И если не удалось дождаться нужного символа, программа отправляет по UART сообщение об ошибке.
Вот кусок моего кода (МК Atmega2560):

Assembler
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
    .cseg
 
    .org 0x0000     jmp main                // Вектор сброса
    .org 0x0046     jmp RX_reset        // переполнение таймера T3. Сброс при получении неполного сообщения
    .org 0x0066     jmp UART_RX_Interrupt   // Вектор приема данных UART2
 
main:
// ----------------- Иницилизация стека
 
    LDI r16, Low(RAMEND)
    OUT SPL, r16
    LDI r16, High(RAMEND)
    OUT SPH, r16
 
 
// --------------- Присвоение имён переменных
    .def temp=r16   
// -------------- Инициализация UART
 
USORT_Init:                                             
    ldi temp, 0x00                          // Установка скорости обмена 9600
    sts UBRR2H, temp
    ldi temp, 0xCF
    sts UBRR2L, temp
 
    ldi temp, (1<<U2X2)                     // Двойная скорость для асинхронного режима
    sts UCSR2A, temp                        
 
    ldi temp, (1<<TXEN2)|(1<<RXEN2)|(1<<RXCIE2)// Разрешение на передачу, разрешение на приём.
    // Разрешение прерывания по окончанию приема
    sts UCSR2B,temp                         
 
    ldi temp, (1<<UCSZ21)|(1<<UCSZ20)       // Формат: 8 бит, 1 стоп-бит
    sts UCSR2C,temp
 
// ------------- Инициализация таймера T3 (для сброса при получении неполного сообщения)
 
    ldi temp, (0<<CS32)|(1<<CS31)|(1<<CS30) // параметры таймера T3
    sts TCCR3B, temp
 
    SEI     // Разрешение глобальных прерываний (флаг I регистра SREG)
 
// --------------- Начало программы
 
Sleep_1: // пустой цикл
    rjmp Sleep_1
 
// ====================== ОБРАБОТКА ПРИНЯТЫХ КОМАНД ===========================
 
UART_RX_Interrupt:          // Обработчик прерывания приема данных
 
    ldi temp, (0<<CS32)|(1<<CS31)|(1<<CS30) // Запуск таймера
    sts TCCR3B, temp
    ldi temp, (1<<TOIE3)    // флаг разрешения прерывания T3 по переполнению
    sts TIMSK3, temp
    sei // разрешение вложенного прерывания
 
    // здесь находится код программы
 
    reti // Выход из прерывания UART
 
RX_reset:        //Прерывание по таймеру
    cli // запретить прерывания
    ldi temp, (0<<TOIE3)    // отключить прерывание по таймеру T3
    sts TIMSK3, temp
    ldi temp, (0<<CS32)|(0<<CS31)|(0<<CS30) // остановка таймера T3
    sts TCCR3B, temp
 
    ldi temp, 'Q'       // отправка символа об ошибке                      
            
    sts UDR2, temp      // отправляем байт
 
ready:          // цикл ожидания готовности порта        
    lds temp, UCSR2A
    SBRS temp, UDRE2        // Пропуск если регистр данных пуст (если 1 - то готов отправлять данные)
    rjmp ready
    sei // разрешить прерывания
    reti                // Вернуться из обработчика таймера
0
Лучшие ответы (1)
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
28.04.2016, 14:27
Ответы с готовыми решениями:

Прерывание по таймеру
Здравствуйте! Возможно ли сделать в консольном приложении на Visual Studio так, чтобы во время...

Прерывание по таймеру
Хочу я организовать регулярное действие в моей программе (каждые n секунд делать что-либо)....

STM32L прерывание по таймеру
Добрый день. Начал изучение STM32 на базе STM32T-Dyscovery. Как ИДЕ использую Ecplipse,...

stm32f429 прерывание по таймеру
Всем привет. Не получается включить прерывание по таймеру, или диод не моргает - не знаю в чем...

Прерывание по таймеру на C++ в консоли
Подскажите пожалуйста,как в консольном приложении можно написать прерывание срабатывающее при...

22
Voland_
1725 / 1064 / 104
Регистрация: 04.01.2010
Сообщений: 3,640
28.04.2016, 15:08 2
1. cli и sei <= означает запутаться в прерываниях. В частности, может возникнуть очередь прерываний, которая в свою очередь приведет к переполнению в стеке. Откажитесь от использования вложенных прерываний (хотя, я даже не уверен - возможно ли такое). И не используйте sei и cli в обработчиках прерываний.
2. sts UDR2, temp // отправляем байт <== что за регистр UDR2? вы используете USORT2? я знаю, что есть регистр UDR, не помню ничего про UDR2.
3. Вы объявили прерывание на прием USORT, но не реализовали на передачу, хотя включили его. То есть программа в общем случае может от этого "плохо себя почувствовать". Потому что обработчика вовсе нет.
1
radist108
1 / 1 / 0
Регистрация: 24.04.2012
Сообщений: 101
28.04.2016, 16:57  [ТС] 3
И как Вы посоветуете в моем случае отправлять сообщение, если после начала приема в течении какого то времени не дождались нужного символа?
0
Mirmik
28.04.2016, 18:09
  #4

Не по теме:

ох... такие вещи лучше всё-таки уже на си писать... или даже на с++...

0
pyzhman
1158 / 513 / 76
Регистрация: 15.05.2012
Сообщений: 2,929
28.04.2016, 19:40 5
отправлять сообщение можно по истечении таймаута, который стартует в начале приема. Таймаут можно организовать на том же таймере.
0
radist108
1 / 1 / 0
Регистрация: 24.04.2012
Сообщений: 101
28.04.2016, 19:52  [ТС] 6
Дело в том, что сообщение не нужно посылать по каждому прерыванию по UART. Оно отправляется по тайм-ауту, если в приятой пачке символов нет контрольного знака
0
pyzhman
1158 / 513 / 76
Регистрация: 15.05.2012
Сообщений: 2,929
29.04.2016, 06:37 7
Я и написал:
Цитата Сообщение от pyzhman Посмотреть сообщение
отправлять сообщение можно по истечении таймаута
0
radist108
1 / 1 / 0
Регистрация: 24.04.2012
Сообщений: 101
29.04.2016, 07:14  [ТС] 8
У меня этот счетчик запускается с момента получения первого сообщения. Но потом его не отключить никак. Точнее прерывание по нему
0
pyzhman
1158 / 513 / 76
Регистрация: 15.05.2012
Сообщений: 2,929
29.04.2016, 09:03 9
У вас он на самом деле отключается (проверил самолично), но не выходит из него. Смотрим даташит:
Assembler
1
2
3
4
5
6
7
USORT_Transmit:
; Wait for empty transmit buffer
sbis UCSRnA,UDREn
rjmp USORT_Transmit
; Put data (r16) into buffer, sends the data
out UDRn,r16
ret
т.е. сначала проверяем, а потом засылаем. Но это, так скажем, тактическая ошибка. А стратегическая, надо полагать, кроется в настройках уарта на передачу. Смотреть Voland_ 3.
Да, и уберите sei перед reti, последняя сама разрешает прерывания. И вложенные прерывания - это как надо угореть, чтоб их обрабатывать.
1
radist108
1 / 1 / 0
Регистрация: 24.04.2012
Сообщений: 101
29.04.2016, 09:04  [ТС] 10
Затем нужно отключить таймер. А он не отключается (
0
pyzhman
1158 / 513 / 76
Регистрация: 15.05.2012
Сообщений: 2,929
29.04.2016, 09:19 11
Assembler
1
2
3
4
ldi temp, (0<<TOIE3)* * // отключить прерывание по таймеру T3
sts TIMSK3, temp
ldi temp, (0<<CS32)|(0<<CS31)|(0<<CS30) // остановка таймера T3
sts TCCR3B, temp
Отключается и запретом прерывания, и отключением тактирования. Встает намертво, уж поверьте.
На каком основании утверждаете, что не отключается?

Добавлено через 3 минуты
Может быть вы имеете ввиду, что не выходит из обработчика прерывания? В этом случае надо смотреть узел передачи по уарту (у вас ожидание отправки сидит в обработчике по переполнению, что, вообще говоря, не есть гут).
0
Voland_
1725 / 1064 / 104
Регистрация: 04.01.2010
Сообщений: 3,640
29.04.2016, 09:33 12
Цитата Сообщение от radist108 Посмотреть сообщение
он не отключается
С чего вы решили? Он-то выключается. Просто не забывайте, что когда вы включаете таймер, его значение не сбрасывается. То есть рано или поздно прерывание таки сработает после какого-то принятого байта.
1
radist108
1 / 1 / 0
Регистрация: 24.04.2012
Сообщений: 101
29.04.2016, 09:35  [ТС] 13
Стоит и обнулить счетчик тоже?
0
Voland_
1725 / 1064 / 104
Регистрация: 04.01.2010
Сообщений: 3,640
29.04.2016, 09:39 14
Цитата Сообщение от radist108 Посмотреть сообщение
Стоит и обнулить счетчик тоже?
я ж не знаю что вы преследуете. Но если нужно сбрасывать - то сбрасывайте конечно. ЗЫ: если вы хотите принять пакет за определенное время - то счетчик надо сбрасывать после принятия заголовка. Если вы ловите межсимвольный интервал - то нужно обнулять счетчик по приему каждого байта.
0
radist108
1 / 1 / 0
Регистрация: 24.04.2012
Сообщений: 101
29.04.2016, 09:53  [ТС] 15
Мне бы сейчас хотя бы ту часть кода написать, которая отправляет символ с задержкой после прерывания по приему с UART.
0
pyzhman
1158 / 513 / 76
Регистрация: 15.05.2012
Сообщений: 2,929
29.04.2016, 09:59 16
Почему не хотите вынести отправку байта за пределы обработчика прерывания по переполнению?
1
radist108
1 / 1 / 0
Регистрация: 24.04.2012
Сообщений: 101
29.04.2016, 10:02  [ТС] 17
Цитата Сообщение от pyzhman Посмотреть сообщение
Почему не хотите вынести отправку байта за пределы обработчика прерывания по переполнению?
С радостью сделаю всё, чтобы программа заработала!
А как это сделать? Закрыть прерывание по переполнению а потом? Как после reti в обработчике переполнения я перейду к отправке символа? У меня сразу в основной пустой цикл переход произойдет.
0
pyzhman
1158 / 513 / 76
Регистрация: 15.05.2012
Сообщений: 2,929
29.04.2016, 10:04 18
Взведите при переполнении флаг. А в теле по этому флагу отправляйте байт.
0
Voland_
1725 / 1064 / 104
Регистрация: 04.01.2010
Сообщений: 3,640
29.04.2016, 10:06 19
Лучший ответ Сообщение было отмечено radist108 как решение

Решение

Цитата Сообщение от radist108 Посмотреть сообщение
А как это сделать? Закрыть прерывание по переполнению а потом?
флаги. В главном потоке (пустом вашем цикле) вы постоянно следите за каким-то флагом или в памяти, или в регистре. А флаг выставляете в прерывании по переполнению. Когда выставляется флаг - вы отправляете свое сообщение и сразу его сбрасываете.

ЗЫ: это обычная практика, так правильно. Но в вашем случае я не вижу в этом смысла.
1
radist108
1 / 1 / 0
Регистрация: 24.04.2012
Сообщений: 101
29.04.2016, 13:28  [ТС] 20
Вот заработавший вариант!
Assembler
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
.cseg
 
.org 0x0000     jmp main                // Вектор сброса
 
.org 0x0046     jmp Time_out        // переполнение таймера T3. Сброс при получении неполного сообщения
.org 0x0066     jmp UART_RX_Interrupt   // Вектор приема данных UART2
 
 
// ----------------- Иницилизация стека
 
LDI r16, Low(RAMEND)
OUT SPL, r16
LDI r16, High(RAMEND)
OUT SPH, r16
 
main:
// --------------- Присвоение имён переменных
 
.def temp=r16
.def byte_0=r17 // открывающая скобка (0x5B)
.def byte_1=r18 
.def byte_2=r19 
 
// -------------- Инициализация UART
 
USORT_Init:                                             
    ldi temp, 0x00                          // Установка скорости обмена 9600
    sts UBRR2H, temp
    ldi temp, 0xCF
    sts UBRR2L, temp
 
    ldi temp, (1<<U2X2)                     // Двойная скорость для асинхронного режима
    sts UCSR2A, temp                        
 
    ldi temp, (1<<TXEN2)|(1<<RXEN2)|(1<<RXCIE2)
    sts UCSR2B,temp                         
 
    ldi temp, (1<<UCSZ21)|(1<<UCSZ20)       // Формат: 8 бит, 1 стоп-бит
    sts UCSR2C,temp
 
SEI     // Разрешение глобальных прерываний (флаг I регистра SREG)
CLT // очищаем флаг T
// --------------- Начало программы
 
 
 
    
 
    rjmp sleep_1
 
 
Sleep_1:
 
BRTS error_send // Перейти если флаг T установлен
rjmp Sleep_1
 
error_send:
// отправляем сообщение об ошибке
 
uart_snt:
    lds temp, UCSR2A
    SBRS temp, UDRE2    ; Пропуск если нет флага готовности,
    ; если 1 - то готов отправлять данные
    RJMP    uart_snt ; ждем готовности - флага UDRE
 
    ldi temp, 'Q'
    sts UDR2, temp  ; шлем байт в UDR
 
    ldi temp, (0<<TOIE3) // отключить прерывание по таймеру T3
    sts TIMSK3, temp
    ldi temp, (0<<CS32)|(0<<CS31)|(0<<CS30) // остановка таймера T3
    sts TCCR3B, temp
 
    CLT // очищаем флаг T
 
rjmp Sleep_1
 
// ====================== ОБРАБОТКА ПРИНЯТЫХ КОМАНД ===========================
 
UART_RX_Interrupt:          // Обработчик прерывания приема данных
    
uart_rcv:
    lds temp, UCSR2A
    SBRS temp, UDRE2    ; Пропуск если нет флага готовности,
    RJMP uart_rcv   ; вращаясь в цикле
    lds temp, UDR2  ; байт пришел - забираем.
 
ldi temp, (1<<CS32)|(0<<CS31)|(1<<CS30) // старт таймера 011
sts TCCR3B, temp
ldi temp, (1<<TOIE3)    // флаг разрешения прерывания T3 по переполнению
sts TIMSK3, temp
 
reti
 
Time_out:        //Таймаут ожидания скобки
    SET // устанавливаем флаг T 
 
    reti
0
29.04.2016, 13:28
Answers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
29.04.2016, 13:28

Прерывание по таймеру раз в пол-секунды
Использую CVAVR. Необходимо получить прерывание по таймеру 1 точно раз в пол-секунды. Стоящий у...

Timer 1. Прерывание по таймеру = +- 1шаг. Как избавиться?
Есть такая проблемка. При возникновении прерывания запись в порт возникает с разницей в +- 1-н...

Индукционная панель Neff T44T33N0/01, не отключается по таймеру, и выводит индикатор "e 9"
Добрый день коллеги. Индукционная панель Neff. Модель E-nr.: T44T33N0/01 FD:9009 00042 ...


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

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

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