Микроконтроллеры, АЦП, память и т.д Темы касающиеся микроконтроллеров разных производителей, памяти, АЦП/ЦАП, периферийных модулей... |
05.02.2010, 01:42
|
|
Почётный гражданин KAZUS.RU
Регистрация: 13.12.2004
Сообщений: 3,172
Сказал спасибо: 11
Сказали Спасибо 692 раз(а) в 504 сообщении(ях)
|
Re: ШИМ, синусоида на Мега8?
Может вот так пойдет?
Код:
|
#include ‹inttypes.h›
#include ‹avr/io.h›
#include ‹avr/interrupt.h›
#ifndef F_CPU
#define F_CPU 14745600UL
#endif
// сэмплов на период
#define SPP 32UL
// частота в герцах
#define FREQ 1870UL
// TOP таймера
#define TIMER_TOP ( (F_CPU/(SPP*FREQ)) -1)
uint8_t SinTbl[32] = { 122,146,169,190,208,223,235,242,244,242,235,223,20 8,190,169,146,122,98,75,54,36,21,9,2,0,2,9,21,36,5 4,75,98 };
ISR(TIMER1_OVF_vect)
{
static uint8_t TblIndex = 0;
OCR1BL = SinTbl[TblIndex++];
TblIndex &= 0x1F;
}
int main(void)
{
DDRB |= (1‹‹PB2); // выход для ШИМ PB2 - OC1B
OCR1A = TIMER_TOP; // задаем период
// таймер - Fast PWM, TOP = OCR1A, non-inverting mode
TCCR1A = (0‹‹COM1A1)|(0‹‹COM1A0)|(1‹‹COM1B1)|(0‹‹COM1B0)|(1‹‹WGM11)|(1‹‹WGM10);
TCCR1B = (1‹‹WGM13)|(1‹‹WGM12)|(0‹‹CS12)|(0‹‹CS11)|(1‹‹CS10);
TIMSK = (1‹‹TOIE1);
sei();
while(1)
{
asm volatile("nop");
};
} |
Синусоида больно лохматая при 32 точках выходит...
|
|
|
|
08.02.2010, 12:08
|
|
Временная регистрация
Регистрация: 09.09.2009
Сообщений: 91
Сказал спасибо: 10
Сказали Спасибо 6 раз(а) в 4 сообщении(ях)
|
Re: ШИМ, синусоида на Мега8?
Проверил в железе частота 1871 гц при TCNT1L=49.
Непойму где правда.
|
|
|
|
08.02.2010, 12:37
|
|
Почётный гражданин KAZUS.RU
Регистрация: 13.12.2004
Сообщений: 3,172
Сказал спасибо: 11
Сказали Спасибо 692 раз(а) в 504 сообщении(ях)
|
Re: ШИМ, синусоида на Мега8?
Сообщение от diglook
|
Непойму где правда.
|
А у Вас других прерываний в программе нет? То, что предложил urry может работать только в "тепличных" условиях и очень сильно зависит от времени реакции на прерывание. Если прерывание одно, то это время фиксированное и все хорошо. Если же их несколько, то частота будет плавать. Кроме того частота зависит и от других факторов - версии компилятора, степени оптимизации. Т.е. константу для TCNT1L надо подбирать под свою систему. У Вас вот 49 получилось. Попробуйте вариант из 11 поста - там Ваш же изначальный алгоритм с делителем на 246 реализован, и он не зависит ни от системы, ни от других прерываний, если они конечно не имеют монстрообразных обработчиков.
|
|
|
|
08.02.2010, 13:01
|
|
Временная регистрация
Регистрация: 09.09.2009
Сообщений: 91
Сказал спасибо: 10
Сказали Спасибо 6 раз(а) в 4 сообщении(ях)
|
Re: ШИМ, синусоида на Мега8?
Прерываний пока одно- обработчик синуса, но планируется еще УАРТ.
|
|
|
|
08.02.2010, 13:28
|
|
Гражданин KAZUS.RU
Регистрация: 04.08.2006
Сообщений: 911
Сказал спасибо: 28
Сказали Спасибо 180 раз(а) в 139 сообщении(ях)
|
Re: ШИМ, синусоида на Мега8?
Читаю - порой удивляюсь.
А как вообще, тогда выводить частоту не кратную частоте процессора? Вы задумывались.
Вот я например работаю с FSK. То есть мне надо несколько синусов разной частоты выводить без потери фазы. И частота - никаким боком не бьъётся?
Всё просто - как грабли и не надо путать понятия.
1) Имеется частота сэмплирования (дискретизации). Если выводим быстрый ШИМ то бишь 8 бит, то частота = FPWM = FCLK/256. То есть 14745600/256 = 57600.
2) Создаём таблицу синуса. Чем больше - тем больше точность. Например с шагом 0.5 градуса. Размер 720 байт.
3) Создаём 1 прерывание по переполнению таймера. Там выводим ваш шим.
4) Частота синуса определяется сдвигом фазы в таблице вывода. Например при выводе частоты 1200 Гц получаем:
57600 / 1200 = 48. 360/48 =7.5 градуса. Или если брать по таблице 0.5 градуса 720/48 = 13. Таким образом ошибка составит 0%.
Выведем частоту 2700 к примеру. 57600/2700 = 21.333 = 21. 720/21 = 34.
Результирующая частота составит 2720. Ошибка составит 0,7%
Вывод в прерывании выглидит так
Код:
|
ptrsin += F_OUT_BIT1; // Если выводим "1"
if(ptrsin›&sinus[VOL_SIN-1])ptrsin -= VOL_SIN; // Кольцо по синусу
dpwm = *ptrsin; // Извлечь синус
OCR1A = (uint8_t)dpwm+128; // выводим ШИМ со смещением к центру |
где
int8_t __flash sinus[VOL_SIN];
int8_t __flash static *ptrsin = sinus;
Инициализация
TCCR1A = (1‹‹WGM10)|(1‹‹COM1A1); // режим Fast PWM 8 бит (Ногу на вывод PWM)
TCCR1B = (1‹‹WGM12)|(1‹‹CS10); // режим Fast PWM 8 бит / FCLK
TCNT1 = 0; // Сбросить таймер
OCR1A=0;
_TIFR1 = 0xff; // Сбросить все флаги
_TIMSK1 = (1‹‹TOIE1); // Разрешить прерывание от таймера 1 (вывод синуса)
_TIFR1 = 0xff; // Сбросить все флаги
И всё - 3 строчки.
|
|
|
|
08.02.2010, 15:27
|
|
Временная регистрация
Регистрация: 09.09.2009
Сообщений: 91
Сказал спасибо: 10
Сказали Спасибо 6 раз(а) в 4 сообщении(ях)
|
Re: ШИМ, синусоида на Мега8?
SasaVitebsk, можно подробней прокоментировать обработчик прерывания(несовсем понятна коррекция фазы)?
|
|
|
|
08.02.2010, 17:28
|
|
Почётный гражданин KAZUS.RU
Регистрация: 13.10.2007
Адрес: Беларусь
Сообщений: 8,048
Сказал спасибо: 60
Сказали Спасибо 3,954 раз(а) в 2,309 сообщении(ях)
|
Re: ШИМ, синусоида на Мега8?
Это технология прямого синтeза частоты, она же DDS. Информации море и она прекрасно гуглится. Например
compitech.ru/html.cgi/arhiv/01_07/stat_50.htm
radioradar.net/articles/scientific_technical/dds.html
pda.pro-radio.ru/measure/6873-8/
|
|
|
|
08.02.2010, 17:56
|
|
Прописка
Регистрация: 21.09.2009
Сообщений: 218
Сказал спасибо: 1
Сказали Спасибо 29 раз(а) в 27 сообщении(ях)
|
Re: ШИМ, синусоида на Мега8?
Александр, а так if(ptrsin›&sinus[VOL_SIN-1]) ptrsin = &sinus[0];
не проще? Будет просто сравнение и занесение адреса, никаких вычитаний.
И вместо двух строк
ptrsin += F_OUT_BIT1;
dpwm = *ptrsin;
сделать одну: dpwm = *(ptrsin++);
|
|
|
|
08.02.2010, 18:08
|
|
Почётный гражданин KAZUS.RU
Регистрация: 13.12.2004
Сообщений: 3,172
Сказал спасибо: 11
Сказали Спасибо 692 раз(а) в 504 сообщении(ях)
|
Re: ШИМ, синусоида на Мега8?
Сообщение от =GM=
|
Александр, а так if(ptrsin›&sinus[VOL_SIN-1]) ptrsin = &sinus[0];
не проще?
|
Я не Александр, но попробую ответить за него. Нет, это не проще, так работоспособность вообще нарушится. ptrsin - это накопитель фазы, а F_OUT_BIT1 это константа определяющая частоту сигнала.
Подробно принцип расписан в статье Ридико на телесистемах - http://telesys.ru/electronics/projects.php?do=p035
Если расширить разрядность накопителя, то можно и 0,01Гц получить.
Но DDS требует более качественной фильтрации, по сравнению со случаем когда частота генерируемого сигнала кратна частоте выборок.
|
|
|
|
08.02.2010, 18:25
|
|
Временная регистрация
Регистрация: 09.09.2009
Сообщений: 91
Сказал спасибо: 10
Сказали Спасибо 6 раз(а) в 4 сообщении(ях)
|
Re: ШИМ, синусоида на Мега8?
Цитата:
|
Мужской глаз - самый точный измерительный прибор в мире
|
здесь ВЫ правы! В железе сильно заметна пила(~10%) - увеличится спектр излучения, изменение интегрирующей цепочки(подстроечный резистор, емкость менялась от 0.47 до 1 мкф) приводит только к изменению амплитуды синусоиды, установка фильтров более высокого порядка отвергнута, решили что проще будет ЦАП на R2R(благо свободных портов валом).
Хотя не факт что в паралельном ЦАПе будет красота.
Спасибо всем за участие! ШИМ Тема интересная(для меня точно) - может еще кто что подскажет ?
Последний раз редактировалось diglook; 08.02.2010 в 18:36.
|
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 04:38.
|
|