Перейти к содержанию

Генератор Atmega


Рекомендуемые сообщения

Потребовался генератор прямоугольных импульсов (меандра) с регулировкой частоты в диапазоне от 1Гц до 100кГц (T = 1s...10us) задание частоты и вывод на дисплей 16х2. Регулировка осуществляется кнопками. В общем для этой цели использую режим CTC  (Clear-To-Compare) таймер 1 (16 бит, 65535 тактов) при частоте ядра 8МГц и при двух установочных коэффициентах деления (1:1) и (1:256) можно варьировать в данном диапазоне. Вопрос состоит в следующем: как перейти из значения регистра OCR1A  к частоте сигнала? На данном этапе хотелось бы видеть реальную частоту на жки + как-то переключаться между коэффициентами деления (switch?), функция (set_freq()). В общем прошу помочь и отнестись с пониманием). Программирование со скрипом идёт. Код прилагаю. Спасибо.


#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <stdio.h>
#include "main.h"
#include "lcd.h"

#define F_CPU 8000000UL
char lcd_buffer[16];								// массив для вывода на жк
						
unsigned int freq = 50000;							// значение частоты
unsigned int prescaler;								// делитель
  
void tc1_init()
{
	TCCR1A |= (1<<COM1A0) | (1<<COM1B0);			// переключение OC1A
	TIMSK |= (1<<TOIE1);							// разрешить прерывание по переполнению
	TCNT1 = 0;										// инициализация счётчика
}

void io_init()
{
	DDRB = 0x00;									// кнопки на PB с внешней подтяжкой
	DDRD = 0x20;									// генерация сигнала на PD5
}

void set_freq()										// настройка частоты
{
	freq = (F_CPU/(2*prescaler*freq))-1;
	OCR1A = freq;
	
	if (..)
	
		switch (prescaler)
		{
			case 1:		TCCR1B |= (1<<WGM12) | (1<<CS10); break;	// 1:1
			case 256:	TCCR1B |= (1<<WGM12) | (1<<CS12); break;	// 1:256
		}
}

void wave_adj()								// регулировка частоты
{
	if(~PINB & (1<<0))						// PB0 log 0 уменьшение частоты
	{
		freq +=10;
		_delay_ms(250);
		//if (temp >= 65534)	temp = 20000;
	}
	if(~PINB & (1<<1))						// PB1 log 0 увеличение частоты
	{
		freq -=10;
		_delay_ms(250);
		//if (temp == 0) temp = 20000;
	}
}

ISR(TIMER1_OVF_vect)
{
	PORTD ^= (1<<5);						// переключение логического уровня 
}

int main(void)
{	
	port_init();
	io_init();
	tc1_init();
	lcd_init();								// инициализация жки
	lcd_load();								// полоса загрузки black-bar
	lcd_clear();							// очистка экрана
	set_freq();
	sei();									// разрешить прерывание глобально
	
	while (1)
	{
		set_pos(0,0);
		string_lcd("SETTING FREQ = ");
		
		set_pos(0,1);
		sprintf(lcd_buffer, "= %u Hz", freq);
		string_lcd(lcd_buffer);
		
		wave_adj();
	}
}









 

Ссылка на комментарий
Поделиться на другие сайты

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

Может, проще реализовать алгоритм DDS, там задаётся сразу ччастота линейо в коде и шаг по частоте постоянный, в отличие от подхода в лоб через регистр OCR. Но алгоритм придется реализовать программно что наложит ограничение на максимальную частоту(впрочем, если тактовая будет порядка 20Мгц, написав критическую часть на ассемблере наверно можно будет обеспечить до 100кГц...). Если взять платку DDS китайского производства, контроллеру останется только залить туда значение частоты и фазы(актуально для многоканального генератора) а дальше всё аппаратно о милигерц вплоть до десятков мегагерц.

Суть DDS такова: Берём значение частоты и накапливаем его в сумматоре со скоростью максимальной частоты - т.е. в вашем случае с частотой 200 кГц. Переполнение суммматора будет являться сигналом для переключения сигнала на выходе. Максимальный код частоты(например значение 0xFFFF) будет сразу же переводить к переполнению сумматора переключать выход и выдавать 100кГц меандр, значение кода 0x0001 - с частотой 100К/65536(в случае 16-битного сумматора) = 1.5Гц... Основная проблема - уместить код сумматора и переключения выхода в интервал между прерываниями... при такте 20Мгц и прерываниям 200кГц у нас на всё про всё будет всего 100 тактов, которые надо потратить на вход/выход с прерывания, сохранение контекста, сам алгоритм сумматора и чтобы ещё вашему коду вывода на индикатор и опроса клавиатуры досталось. Это в принципе реально, но надо вспомнить ассемблер и выделить пару регистров под код частоты и пару на сумматор, которые будут использоваться эксклюзивно в прерывании.

и да, поскольку заметную долю времени контролер будет исполнять код прерывания, необходимо будет откорректировать значение константы тактовой частоты контроллера, чтобы DELAY работали правильно. Если к примеру прерывание займет 50% времени, тогда надо сказать компилятору что у нас контроллер дескать 10Мгц-овый, а не 20-ти и тогда все задержки на подсчете тактов станут правильными. И ещё один ньюанс - если в коде будет встречаться запрет прерывания или используются другие прерывания то в выходном сигнале может появиться значительный фазовый шум... Это может оказаться критичным для некоторых применений такого генератора.

Изменено пользователем Alexeyslav

Учение - изучение правил. Опыт - изучение исключений.

Ссылка на комментарий
Поделиться на другие сайты

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

Присоединяйтесь к обсуждению

Вы публикуете как гость. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...