0 / 0 / 0
Регистрация: 25.09.2024
Сообщений: 5
1

Выдать определенное количество импульсов с заданной частотой

25.09.2024, 16:49. Показов 891. Ответов 19
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Добрый день.
Нужно выдать на ножку Atmega88 определенное количество импульсов (N=125) с заданной частотой (F=440 Гц).
Запрограммировать таймер Timer1 на 440 герц я справился. Подскажите, как попроще (надежнее)
посчитать эти импульсы. Думаю , что через Timer0, но не соображу как.
Пишу на ассемблере.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
25.09.2024, 16:49
Ответы с готовыми решениями:

Аппаратно выдать определенное количество импульсов
Процессор STM32F103. Необходимо чтобы на 4 ножки процессора выдавались пачки импульсов(управление...

Последовательность импульсов с изменяющейся частотой
Здравствуйте:) подскажите, пожалуйста, как сформировать последовательность импульсов (массив из 1...

Создание в LabView Имитации работы генератора импульсов тока с частотой 1кГц
Создать подпрограмму для имитации работы генератора импульсов тока с частотой 1кГц.

Выполнение заданной команды определённое количество раз
мне нужно повторить команду repeat.exe n раз. Но это команда выполняется несколько минут, а мне...

Запуск bat-файла определенное количество раз и определенное количество дней
1 есть .bat файл, который запускает некий скрипт. Требуется настроить его так, что бы запуск...

19
57 / 43 / 14
Регистрация: 12.12.2020
Сообщений: 439
25.09.2024, 18:31 2
Лучший ответ Сообщение было отмечено Ap-o-stol как решение

Решение

Так в таймере1 и считайте. Сработал таймер - счетчик ++ и ногу в инверт. Проверяем значение счетчика. Если больше 250 то все, тушим таймер. Как раз байта одного хватает под перемменую.
0
3 / 3 / 1
Регистрация: 27.02.2014
Сообщений: 101
25.09.2024, 22:15 3
Давно не писал под AVR и возможно есть ошибки - нужно в железе проверять.
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
#include <avr/io.h>
#include <avr/interrupt.h>
 
volatile uint16_t pulse_count = 0; // Счётчик импульсов
#define TARGET_PULSES 125 // Количество импульсов
#define TIMER_PRESCALER 64 // Делитель
#define F_CPU 8000000 // Частота процессора 8 МГц
#define F_TIMER (F_CPU / TIMER_PRESCALER) // Частота таймера
#define PERIOD ((uint16_t)(F_TIMER / 440)) // Количество тиков на 440 Гц
 
void setup() {
    
    DDRB |= (1 << PB0); // Пин B0 на выход
    PORTB &= ~(1 << PB0); // Сброс PB0
 
    // Настройка таймера
    TCCR0A = (1 << WGM01); // Режим CTC
    TCCR0B = (1 << CS01) | (1 << CS00); // Делитель 64
    OCR0A = PERIOD - 1; // Устанавливаем значение для сравнения (284 - 1 = 283)
    TIMSK0 |= (1 << OCIE0A); // Разрешить прерывание по совпадению
 
    sei(); // Разрешаем глобальные прерывания
}
 
ISR(TIMER0_COMPA_vect) {
    if (pulse_count < TARGET_PULSES) {
        PORTB ^= (1 << PB0); // Инвертируем состояние пина B0
        pulse_count++;
    } else {
        // Остановить таймер
        TCCR0A = 0; // Сброс настроек таймера
        TCCR0B = 0; // Отключаем таймер
        PORTB &= ~(1 << PB0); // Выключаем выход
    }
}
 
int main(void) {
    setup();
    
    while (1) {;}
}
Добавлено через 4 минуты
Цитата Сообщение от Ap-o-stol Посмотреть сообщение
Пишу на ассемблере.
Можно скомпилировать и глянуть транслятор в асм и от этого толкнуться
0
57 / 43 / 14
Регистрация: 12.12.2020
Сообщений: 439
25.09.2024, 22:15 4
Частота 440 я так понимаю это 440 импульсов в секунду. Импульс это ногу поднял и ногу опустил. То есть частота инвертирования ног должна быть 880. А pulse_count показывает именно кол-в переключений которых так же должно быть не 125 а 250 (по два переключения на импульс.

И волатиле вроде не нужен - переменная только в прерывании и "живет".
0
3 / 3 / 1
Регистрация: 27.02.2014
Сообщений: 101
25.09.2024, 22:41 5
Цитата Сообщение от Alex1126 Посмотреть сообщение
И волатиле вроде не нужен
На сколько помнится, из прерывания глобальная переменная недоступна без volatile, но могу ошибаться.
Цитата Сообщение от Alex1126 Посмотреть сообщение
Частота 440 я так понимаю это 440 импульсов в секунду......
Тоже не буду спорить, но проверять в железе лень)
Тут скорее сам смысл важнее как дергать лапами в таймере.
А еще нам не сказали какой % заполнения импульс должен быть, но это так, лирическое отступление)
1
57 / 43 / 14
Регистрация: 12.12.2020
Сообщений: 439
25.09.2024, 22:52 6
Цитата Сообщение от aleksandr_l Посмотреть сообщение
На сколько помнится, из прерывания глобальная переменная недоступна без volatile, но могу ошибаться.
не, она явно не про это, она про то что переменная может изменяться не только из главного потока и ее нельзя оптимизировать.
Цитата Сообщение от aleksandr_l Посмотреть сообщение
Тут скорее сам смысл важнее как дергать лапами в таймере.
А еще нам не сказали какой % заполнения импульс должен быть, но это так, лирическое отступление)
это да. Чувствуется какая то недосказанность в задаче
0
3 / 3 / 1
Регистрация: 27.02.2014
Сообщений: 101
25.09.2024, 23:46 7
Цитата Сообщение от Alex1126 Посмотреть сообщение
не, она явно не про это, она про то что переменная может изменяться не только из главного потока и ее нельзя оптимизировать.
Точно до буквы!

Тогда можно переменную счетчика закинуть в прерывание.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ISR(TIMER0_COMPA_vect) {
 
    static uint16_t pulse_count = 0; // Счётчик импульсов
 
    if (pulse_count < TARGET_PULSES) {
        PORTB ^= (1 << PB0); // Инвертируем состояние пина B0
        pulse_count++;
    } else {
        // Остановить таймер
        TCCR0A = 0; // Сброс настроек таймера
        TCCR0B = 0; // Отключаем таймер
        PORTB &= ~(1 << PB0); // Выключаем выход
 
        pulse_count = 0; // Обнуляем счётчик
    }
}
А потом окажется, что количество импульсов менять нужно будет по ходу пьесы))
Не особо понятно куда конкретно в данном случае лучше запихать.
0
594 / 284 / 42
Регистрация: 22.09.2023
Сообщений: 836
26.09.2024, 09:58 8
Лучший ответ Сообщение было отмечено Ap-o-stol как решение

Решение

Цитата Сообщение от aleksandr_l Посмотреть сообщение
Тогда можно переменную счетчика закинуть в прерывание.
Лучше этого не делать. Потому что "значение статической переменной присваивается при первом вызове функции", а это проверка, которая будет тратить время при каждом вызове прерывания до выключения питания.
Цитата Сообщение от Ap-o-stol Посмотреть сообщение
Запрограммировать таймер Timer1 на 440 герц я справился.
Теперь запрограммируйте его на выдачу импульсов (изучите раздел документации "Output compare units"). И в прерывании таймера считайте количество импульсов. Как только насчитате сколько нужно - выключайте таймер.
1
0 / 0 / 0
Регистрация: 25.09.2024
Сообщений: 5
26.09.2024, 10:53  [ТС] 9
Цитата Сообщение от aleksandr_l Посмотреть сообщение
А еще нам не сказали какой % заполнения импульс должен быть, но это так, лирическое отступление)
-50%.Да в принципе не важно,главное длительность импульса должна быть >50 мкс
Цитата Сообщение от Alex1126 Посмотреть сообщение
То есть частота инвертирования ног должна быть 880.
- Учту, спасибо.
Цитата Сообщение от aleksandr_l Посмотреть сообщение
На сколько помнится, из прерывания глобальная переменная недоступна
- На ассемблере такой проблемы нет - регистр он и есть регистр.
Цитата Сообщение от aleksandr_l Посмотреть сообщение
А потом окажется, что количество импульсов менять нужно будет по ходу пьесы))
- А вот это вернее всего - придется подгонять.
Цитата Сообщение от aleksandr_l Посмотреть сообщение
Тут скорее сам смысл важнее как дергать лапами в таймере.
!!! В точку !!!
Цитата Сообщение от Alex1126 Посмотреть сообщение
Так в таймере1 и считайте. Сработал таймер - счетчик ++ и ногу в инверт. Проверяем значение счетчика. Если больше 250 то все, тушим таймер.
То есть в прерывании отключить прерывание ? Сработает ли ?
Попробую конечно.
0
13 / 12 / 1
Регистрация: 23.01.2019
Сообщений: 69
26.09.2024, 11:19 10
Лучший ответ Сообщение было отмечено Ap-o-stol как решение

Решение

Цитата Сообщение от Ap-o-stol Посмотреть сообщение
То есть в прерывании отключить прерывание ? Сработает ли ?
Попробую конечно.
440Гц, предполагаю, что что то музыкальное выводится на ножку.
Можно порсто отключить ногу в TCCR1A. Или вам переключать ноты нужно?
1
0 / 0 / 0
Регистрация: 25.09.2024
Сообщений: 5
26.09.2024, 12:31  [ТС] 11
Можно просто отключить ногу в TCCR1A.
Отличный вариант! Спасибо.
0
57 / 43 / 14
Регистрация: 12.12.2020
Сообщений: 439
26.09.2024, 19:11 12
Цитата Сообщение от Ap-o-stol Посмотреть сообщение
То есть в прерывании отключить прерывание ? Сработает ли ?
а почему не должно? вы отключаете возникновение прерывание выполнение кода в прерывании продолжится
0
629 / 386 / 73
Регистрация: 21.09.2008
Сообщений: 1,317
27.09.2024, 10:55 13
Цитата Сообщение от Alex1126 Посмотреть сообщение
вы отключаете возникновение прерывание выполнение кода в прерывании продолжится
В архитектуре AVR при входе в обработчик прерывания дальнейшие прерывания автоматически заблокированы , вложенные прерывания исключены (пожалуй, только сигнал RESET невозможно заблокировать). Отсюда проистекает требование к обработчику прерывания как можно быстрее отработать причину своего вызова и отдать управление.
Например, это может повлиять на точный отсчёт времени таймером, как это реализоано в платформе Arduino для AVR (функция millis()).
Можете написать пример сохранения значения SREG из обработчика в ячейку памяти, а вывести значение этой ячеки в консоль уже после выхода из обработчика, чтобы убедиться лично в моих сказаниях.
0
0 / 0 / 0
Регистрация: 25.09.2024
Сообщений: 5
27.09.2024, 11:56  [ТС] 14
Цитата Сообщение от sharpey Посмотреть сообщение
В архитектуре AVR при входе в обработчик прерывания дальнейшие прерывания автоматически заблокированы
Да, но флаги других прерываний (если наступили) устанавливаются, по выходу из прерывания общий запрет снимается и диспетчер прерываний запускает другие прерывания согласно иерархии.
0
57 / 43 / 14
Регистрация: 12.12.2020
Сообщений: 439
27.09.2024, 12:42 15
Да, все правильно. При входе в прерывание глобально прерывания запрещаются, но прерывание конкретное можно выключить.
И да, флаги прерывания устанавливаются и при выходе из одного прерывания можно сразу улететь на другое (вроде не сразу, вроде одна команда отработает, но точно не помню).
0
629 / 386 / 73
Регистрация: 21.09.2008
Сообщений: 1,317
28.09.2024, 17:59 16
Цитата Сообщение от Ap-o-stol Посмотреть сообщение
диспетчер прерываний запускает другие прерывания согласно иерархии
Это как понимать применительно к AVR?
0
0 / 0 / 0
Регистрация: 25.09.2024
Сообщений: 5
30.09.2024, 12:57  [ТС] 17
Если есть система приоритетов - есть иерархия и есть кусок микропрограммного кода который это отслеживает - чем не диспетчер ?
0
57 / 43 / 14
Регистрация: 12.12.2020
Сообщений: 439
30.09.2024, 17:07 18
Цитата Сообщение от sharpey Посмотреть сообщение
Это как понимать применительно к AVR?
так и понимать. Если во время обработки прерывания установились флаги нескольких прерываний, то при выходе из прерывания программа уходит на следующее, то что выше в иерархии прерываний.
0
629 / 386 / 73
Регистрация: 21.09.2008
Сообщений: 1,317
01.10.2024, 11:05 19
Цитата Сообщение от Alex1126 Посмотреть сообщение
при выходе из прерывания программа уходит на следующее, то что выше в иерархии прерываний
В AVR порядок приоритета прерывания заложен в таблице векторов прерываний: чем меньше адрес в таблице, тем выше приоритет прерывания. Например, в ATmega328P/164РА/324РА/644РА/1284Р внешнее прерывание INT0 более приоритетно, чем INT1, PCINT0, PCINT1, PCINT2, WDT и так далее. Выше INT0 только немаскируеое RESET - у неё наивысший приоритет.
0
57 / 43 / 14
Регистрация: 12.12.2020
Сообщений: 439
01.10.2024, 16:47 20
Ну я про то же самое и говорил просто без подробностей
0
01.10.2024, 16:47
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
01.10.2024, 16:47
Помогаю со студенческими работами здесь

По нажатию кнопки выдать последовательность прямоугольных импульсов скважностью 3 (ATmega16, ASM)
По нажатию кнопки SW1 подключенной к выводу PD2 начать выдавать последовательность прямоугольных...

Вставить в массив определенный элемент определенное количество раз на определенное место
Задачка такая: вставить в массив определенный элемент определенное количество раз на определенное...

Как считать определённое количество цифр заданного числа (считать число до заданной цифры)?
как считать число 12345 до символа 5? То есть 1234 присвоить другой переменной?.:wall:

Генерация звука с заданной частотой
Нужно написать простенькую программу для проигрывания звука с какой-то частотой, n - мсек. Если...

Амплитудный спектр заданной последовательности импульсов
Здравствуйте. Я студент заочник (ЗУ). На семестр дали курсовую по РТЦиС. Тема: Расчет электрических...


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru