Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: генератор импульсов на ATmega16
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
neurox
Доброго времени суток. Обращаюсь к вам с такой задачкой:

Необходимо изготовить генератор импульсов на ATmega16. Частота импульсов задается динамически с клавиатуры и отображается на ЖК дисплее.

Что сделал я:

1.Интерфейс я сделал, число отображается и по нажатию кнопок изменяется. (одна кнопка перелистывает единицы, вторая десятки, третья сотни и т.д.)

2.Мега тактируется от внешнего кварца на 10Mhz. На porta дисплей, на portb кнопки.

Что мне не понятно:

1.Думаю для отсчета периода между импульсами разумно использовать 16ти разрядный таймер... да?

2.Можно ли добиться приемлемой точности в моём случае? Мне необходимо генерировать импульсы с частотой в диапазоне от 1Гц до 10000Гц. (Ну или хотя бы до 5000Гц)

3.Как реализовать генерацию импульсов? (В теории кажется понятным а на практике что-то не врубаюсь). Поделитесь опытом, пожалуйста? А если добавите выкладку на С то буду вообще счастлив.
Палыч
1.Да
2.Да
3.Режим СТС. C выводом импульсов на вывод ОС. Посмотрите в DS. Будут вопросы - задавайте.

P.S. Ответил плохо подумавши на второй вопрос... Уточните: точность какая нужна? Плюс/минус 1 Гц во всём диапазоне?
GDI
С 16 битным таймером вы получите только 151Гц максимальную частоту, надо использовать только 10 бит, тогда получится 9765Гц, с точностью установки порядка 9,5Гц. Если поставить кварц 10,48МГц тогда можно получить шаг частоты 10Гц
muravei
Не подойдет? h__p://www.telesys.ru/electronics/projects.php?do=p072
Палыч
Цитата(GDI @ Jan 21 2009, 12:56) *
С 16 битным таймером вы получите только 151Гц максимальную частоту...
Это - ещё почему? В режиме СТС частота на ОС:
Fос= Fclk/(2*N*(1+OCR)), где N=1,8,64,1024; OCR=0...65535; Fclk=10 000 000 Гц
Откуда Вы получили такое ограничение?
GDI
С FastPWM попутал smile.gif
Палыч
Цитата(GDI @ Jan 21 2009, 14:52) *
С FastPWM попутал
Ну, вот...
Другое дело: автор вопроса невнятно сформулировал требования по точности генерируемой частоты... Если желает генерить 10 000 Гц с точностью плюс/минус 0,5 Гц (а, может быть и точнее), то это уже 500ppm, добрая часть из которых, возможно, прийдется на погрешность округления делителя до ближайшего целого. Возможны проблемы с точностью задающего генератора: кроме "точности" изготовления кварца, на частоту задающего генератора будут оказываться и другие воздействия (изменение температуры, напряжения питания и др). Возможно, при проектировании прийдётся очень ответственно отнестись к этой части прибора...
neurox
Цитата(Палыч @ Jan 21 2009, 16:51) *
Уточните: точность какая нужна? Плюс/минус 1 Гц во всём диапазоне?


Желательная точность действительно +/- 1Гц. Возможно ли её при 10 000 Гц достичь? В вычислениях получается уж слишком большая погрешность.. О_о

Получается так... задающая частота 10 МГц... Через prescaler делю её на 1024, получается 9765,625 Гц - это частота с которой будет работать таймер. Далее мне нужно, например, чтобы он махал ногой с частотой 1 Гц. Т.е. я должен вычислить число, с которым будет сравниваться значение таймера и по совпадению инвертировать уровень на ноге. Как мне вычислить это значение?
yarunt
Цитата(neurox @ Jan 21 2009, 12:39) *
Доброго времени суток. Обращаюсь к вам с такой задачкой:

Необходимо изготовить генератор импульсов на ATmega16. Частота импульсов задается динамически с клавиатуры и отображается на ЖК дисплее.

Что сделал я:

1.Интерфейс я сделал, число отображается и по нажатию кнопок изменяется. (одна кнопка перелистывает единицы, вторая десятки, третья сотни и т.д.)

2.Мега тактируется от внешнего кварца на 10Mhz. На porta дисплей, на portb кнопки.

Что мне не понятно:

1.Думаю для отсчета периода между импульсами разумно использовать 16ти разрядный таймер... да?

2.Можно ли добиться приемлемой точности в моём случае? Мне необходимо генерировать импульсы с частотой в диапазоне от 1Гц до 10000Гц. (Ну или хотя бы до 5000Гц)

3.Как реализовать генерацию импульсов? (В теории кажется понятным а на практике что-то не врубаюсь). Поделитесь опытом, пожалуйста? А если добавите выкладку на С то буду вообще счастлив.

А форма импульсов?
swisst
Цитата(neurox @ Jan 22 2009, 09:37) *
Желательная точность действительно +/- 1Гц. Возможно ли её при 10 000 Гц достичь? В вычислениях получается уж слишком большая погрешность.. О_о

Получается так... задающая частота 10 МГц... Через prescaler делю её на 1024, получается 9765,625 Гц - это частота с которой будет работать таймер. Далее мне нужно, например, чтобы он махал ногой с частотой 1 Гц. Т.е. я должен вычислить число, с которым будет сравниваться значение таймера и по совпадению инвертировать уровень на ноге. Как мне вычислить это значение?


точность будет зависить от того, что Вы можете показать на индикаторе. Я получал точность 0,005% для определенной сетки частот - круглые значения, если можно так выразиться.
neurox
Цитата(yarunt @ Jan 22 2009, 15:44) *
А форма импульсов?


прямоугольные
mempfis_
В вашем случае надо использовать как уже сказали выше 16-битный таймер в режиме СТС с инвертированием вывода МК управляемого этим мк. Но нужно определится с его входной тактовой частотой. Используя например 8МГц кварц и 8 делитель можно получить 1МГц. Тогда минимальный возможный период отсчёта составит 1мкс. Значит раз в 1мкс вы сможете инвертировать вывод соотв. период будет в 2 раза больший от 1*2 до 65536*2 мкс (500000 Гц до 7,6 Гц). Чтобы получить мин частоту 1Гц вам надо понизить входную частоту ТС ещё в 8 раз или изменить ТЗ и поднять нижнюю частоту скажем до 10 Гц. Либо другой вариант - ввесести дополнительную переменную и считать её по прерыванию СТС и самостоятельно инвертировать вывод МК тогда вы точно сможете получить 1Гц но у этого метода есть недостаток - вам придётся вводить прерывания СТС, занимать процессор на его обслуживание. Это может привести к плаванию фронта. Первый вариант обеспечит вам стабильную работу независящую от хода исполнения программы вплоть до Fсист/2 так как управление ножкой будет осуществлятся аппаратно без использования прерываний (друг таким способом выводил стабильную тактовую частоту для симки 4МГц при 8МГц системной тактовой частоты).
P.S. не хватает в меге 32-битного таймера для таких случаев smile.gif
neurox
Цитата(swisst @ Jan 22 2009, 15:52) *
точность будет зависить от того, что Вы можете показать на индикаторе. Я получал точность 0,005% для определенной сетки частот - круглые значения, если можно так выразиться.


примеры значений: 1hz, 283hz, 1000hz, 8582hz
Палыч
Цитата(neurox @ Jan 22 2009, 10:37) *
Желательная точность действительно +/- 1Гц. Возможно ли её при 10 000 Гц достичь? В вычислениях получается уж слишком большая погрешность.. О_о
Достичь можно, и погрешность, скорее всего, будет небольшой...
Цитата(neurox @ Jan 22 2009, 10:37) *
... Через prescaler делю её на 1024, получается 9765,625 Гц ......... Как мне вычислить это значение?
Для того, чтобы погрешность округления делителя до ближайшего целого была минимальна, необходимо, чтобы деление в прескалере было бы минимальным. Исходя из этого идеально использовать пределитель равнй единице. Но, для всего диапазона единица пределителя неподходит - иначе значение OCR выходит за 16 бит. Весь диапазон необходимо разбить на несколько частей - в каждом поддиапазоне своё значение пределителя.
Как определить пределитель и значение OCR? Если заглянуть в DS, то легко найти формулу определения частоты на ноге ОС в режиме СТС. Несложными преобразованиями получаем:
OCR= Fclk/(Foc*2*N)-1
В этой формуле Fclk- частота задающего генератора; Foc- частота, которую необходимо получить на выходе; N- значение пределителя; OCR- значение, которое необходимо поместить в регистр для получения нужной частоты на выходе. Вспомним что N - имеет значение степени двойки и что деление на 2 (или степень двойки) - это сдвиг вправо. Попробуем вычислить OCR при этом подбирая значение пределителя такое - чтобы результат помещался в 16 бит.
1. Делим Fclk на Foc (обозначим результат как Х). Результат надо получить типа unsigned long (надеюсь, программируете на Си)
2. Проверяем насколько Х превышает размер 17 (!) бит. Именно 17 бит, т.к. осталось ещё деление на 2, но мы прибережем его (деление) для округления до ближайшего целого. rolleyes.gif
Если Х помещается в 17 бит - то пределитель = 1, и Y=X
иначе, если Х помещается в 20 бит - то делитель = 8, и Y=X>>3
иначе, если Х помещается в 23 бита - то делитель = 64, и Y=X>>6
иначе, если Х помещается в 25 бит - то делитель = 256, и Y=X>>8
иначе делитель = 1024, и Y=X>>10
3. Делим на 2 с округлением до ближайшего целого и вычитаем единицу Z=(Y+1)>>1 - 1 (это и будет вычисленное значение для OCR)
Ну, вот... Для заданной частоты генерации импульсов определили пределитель и значение OCR
neurox
memphis_, внутренний RC подойдет для этой цели? Т.З. можно поменять... отсутствие частот от 1 до 10 Герц не критично.
mempfis_
Цитата
Получается так... задающая частота 10 МГц... Через prescaler делю её на 1024, получается 9765,625 Гц - это частота с которой будет работать таймер. Далее мне нужно, например, чтобы он махал ногой с частотой 1 Гц. Т.е. я должен вычислить число, с которым будет сравниваться значение таймера и по совпадению инвертировать уровень на ноге. Как мне вычислить это значение?


Fсист - системная тактовая частота,
Кдел - коэф. деления предделителя
Fтс=Fсист/Кдел - тактовая частота ТС
Fуст - необходимая частота
Fтс/Fуст=Кпер (Кпер - коэф. пересчёта в режиме СТС)
N=Кпер/2=Fтс/(2*Fуст)=Fсист/(2*Кдел*Fуст) - число заносимое в регистр сравнения для заданной частоты

N=Fсист/(2*Кдел*Fуст)
N=10000000/(2*512*1)=9765,625
N=9765 - занеся такое число в регист сравнения при 10МГц и Кдел=512 получите 1,000064 Гц на выходе

Цитата(neurox @ Jan 22 2009, 11:22) *
memphis_, внутренний RC подойдет для этой цели? Т.З. можно поменять... отсутствие частот от 1 до 10 Герц не критично.

Лучше используйте внешний кварц. Внутренний RC-генератор врятли подойдёт. Его нужно калибровать, параметры могут плавать от температуры. Но можете проверить опытным путём.
Палыч
Цитата(neurox @ Jan 22 2009, 11:22) *
внутренний RC подойдет для этой цели?
При использовании внутреннего RC - о точности речи тогда не ведите вообще...
neurox
Палыч, mempfis_ спасибо! blink.gif сижу вникаю...
Палыч
В продолжение к написанному выще
Чтобы не нагружать МК проверками: во сколько бит влезает результат деления Fclk/Foc, можно просчитать заранее (типа на бумажке, поскольку Fclk - вроде извесна) для разных Foc и определить диапазоны Foc и соотвествующие им значения пределителя. Тогда вместо "если Х помещается" будет "если Foc в диапазоне (т.е. Foc > Значение)"
GDI
Можно еще каскадно соединить 2 таймера. Т.е. один таймер(Т1) работает как управляемый прескалер и выдает частоту на порт, затем, эта ножка порта аппаратно(проводником) соединяется со входом внешнего тактирования асинхронного таймера Т0, таким образом можно расширить разрядность до 24 бит.
Палыч
Цитата(GDI @ Jan 22 2009, 14:01) *
таким образом можно расширить разрядность до 24 бит.
Ну, это Вы чего-то напутали...
Если А - это делитель одного таймера (8-ми разрядного), В - делитель другого (16-ти разрядного), то общий делитель будет С=A*B, а не С=A*2^16+B как это было бы в случае двадцатичетырёхбитного таймера. Для решения задачи автора вопроса достаточно 16-ти битного таймера с пределителем, и городить ещё что-то не имеет смысла
Maik-vs
Здесь читали?
Палыч
Цитата(Maik-vs @ Jan 22 2009, 14:22) *
Здесь читали?
Проекты Леонида Ивановича - все очень качественные и для начинающих разработчиков его работы - образец для подражания, но в данном случае автору вопроса нужны прямоугольные импульсы в меньшем диапазоне и с более грубым шагом. Можно сделать этот проект - гораздо проще, чем у Леонида Ивановича...
GDI
Цитата
Ну, это Вы чего-то напутали...
Если А - это делитель одного таймера (8-ми разрядного), В - делитель другого (16-ти разрядного), то общий делитель будет С=A*B, а не С=A*2^16+B как это было бы в случае двадцатичетырёхбитного таймера.
А подскажите, как каскадируют двоичные счетчики?
Палыч
Цитата(GDI @ Jan 22 2009, 15:23) *
А подскажите, как каскадируют двоичные счетчики?
Двоичными счетчиками исходную частоту делят на 2^N, где N - номер выхода счетчика. С помощью таймера в AVR исходную частоту можно разделить на 2*Х, где Х - шестнадцатибитовое число (любое, а не только степень двойки).
MrYuran
Цитата(Палыч @ Jan 22 2009, 14:20) *
Если А - это делитель одного таймера (8-ми разрядного), В - делитель другого (16-ти разрядного), то общий делитель будет С=A*B

А вот интересно, какую разрядность имеет произведение 8р на 16р? Разве не 24?
Палыч
Цитата(MrYuran @ Jan 22 2009, 15:47) *
А вот интересно, какую разрядность имеет произведение 8р на 16р? Разве не 24?
А вот, попробуйте представить (записать) все двадцатичетырёхразрядные числа в виде произведения двух чисел - одного 8-ми, а второго 16-ти разрядных.
GDI
Цитата
А вот, попробуйте представить (записать) все двадцатичетырёхразрядные числа в виде произведения двух чисел - одного 8-ми, а второго 16-ти разрядных.
А если представить(а так оно и есть) что на вход 8битного таймера-счетчика поступает частота деленная на 2^16(максимальное значение 16битного таймера)? Мы опустим возможность получения некоторых промежуточных значений несколькими комбинациями обоих таймеров - нам ни к чему лишние сложности.
Другое дело, что меняя период первого таймера мы на выходе второго будем получать частоту первого таймера деленную пополам, т.к. второй таймер нам даст минимальное деление на 2, т.о. мы не получим чистые 24 бита, будет только 23, но это все равно лучше чем 16 с программным последующим делением, т.к. решение будет аппаратное и не будет большого дрожания фазы.
Может мы из-за бита спорим? smile.gif
Палыч
Цитата(GDI @ Jan 22 2009, 16:25) *
... но это все равно лучше чем 16 с программным последующим делением, т.к. решение будет аппаратное и не будет большого дрожания фазы.
А, кто тут говорил о программном делении? Для решения этой задачи (генерации меандра с частотой от 1 до 10000 Гц) достаточно аппаратных средств шестнадцатиразрядного таймера. Конечно, значения, которые заносятся в регистры таймера, для конкретной выходной частоты необходимо программно расчитывать. Но без этого не обойтись при любом построении генератора с задаваемой (изменяющейся) частотой с шагом 1 Гц, спроектированного на МК.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.