Недоступна генерация синуса выше 83 Гц (ATMega48)
Добавлено: Пт ноя 07, 2014 13:44:30
Добрый день форумчане, написал код для Atmega 48 трехфазного частотника
Листинг
Я новичок, не пинайте сильно, что в данном коде не так?
Попытка выставить любую частоту выше 83 заканчивается одним и тем же, работой на частоте 50 Гц.
компилятор CodevisionAVR, проверяю в протеусе.
Код естественно будет доработан плюшками, но пока хоть разобраться с частотой, она регулируется только в диапазоне 0-83 Гц
Попытка производить вычисления в теле прерывания таймера 1 приводит вообще к околесице, к тому же самому только в 30 Гц.
в синусе 256 значений, для целого числа сдвига фаз.
потолком является величина 2-значная.
Регистр OCR1A как и таймер 1 16 битный.
Число 8000000/(256*freq) в любом случае меньше 2 байт.
Процедура деления выполняется нацело, т.е. без плавающей точки, т.е. те же 100 Гц будут в регистре OCR1A числом 138 или же OCR1AH=0x01 OCR1AL=0x38, при попытке прописать эти значения в лоб, то же самое происходит что при вычислении (естественно вычисление закоменчивается при этом).
Что за затык может быть такой искусственный?
Листинг
Код: Выделить всё
volatile char i;
volatile unsigned char b_sin; // Индекс фазы B в таблице синуса
volatile unsigned char c_sin; // Индекс фазы C в таблице синуса
volatile unsigned char temp_a; // временное хранение значения фазы A
volatile unsigned char temp_b; // временное хранение значения фазы B
volatile unsigned char temp_c; // временное хранение значения фазы C
volatile unsigned int freq_inv=31250; // задает период прерывания
volatile unsigned int freq=83; // задает частоту
volatile unsigned char amp_sin = 255; // амплитуда синуса. 255 это максимум.
#include <mega48.h>
#include <delay.h>
#include <stdio.h>
#include <sin256.h>
interrupt [EXT_INT0] void ext_int0_isr(void)
{
}
interrupt [EXT_INT1] void ext_int1_isr(void)
{
}
interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
ADCSRB = sin[i];
temp_a=((unsigned int)amp_sin*(unsigned int)sin[i])>>8;
OCR0A = temp_a;
b_sin=i+85;
ADCSRB = sin[b_sin];
temp_b=((unsigned int)amp_sin*(unsigned int)sin[b_sin])>>8;
OCR0B = temp_b;
c_sin=i+170;
ADCSRB = sin[c_sin];
temp_c=((unsigned int)amp_sin*(unsigned int)sin[c_sin])>>8;
OCR2A = temp_c;
i++;
if (i>255) i=0;
b_sin++;
if (b_sin>255) b_sin=0;
c_sin++;
if (c_sin>255) c_sin=0;
}
void main(void)
{
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
PORTD=0x0C;
DDRD=0x00;
TCCR0A=0xA3;
TCCR0B=0x01;
TCNT0=0x00;
ASSR=0x00;
TCCR2A=0x83;
TCCR2B=0x01;
TCNT2=0x00;
DDRD|=(1<<5)|(1<<6); // PD5 PD6 выходы ШИМ Таймер0
DDRB|=(1<<3); // PB3 выход ШИМ Таймер2
OCR1AH = ((unsigned int)freq_inv/(unsigned int)freq)>>8;
OCR1AL = ((unsigned int)freq_inv/(unsigned int)freq);
OCR1BH=0x00;
OCR1BL=0x00;
TCCR1A = 0x00;
TCCR1B = 0x09;
EICRA=0x00;
EIMSK=0x00;
PCICR=0x00;
TIMSK0=0x00;
TIMSK1=0x02;
TIMSK2=0x00;
UCSR0A=0x00;
UCSR0B=0x08;
UCSR0C=0x06;
UBRR0H=0x00;
UBRR0L=0x0C;
ACSR=0x80;
ADCSRB=0x00;
// Global enable interrupts
#asm("sei")
while (1)
{
}
}Я новичок, не пинайте сильно, что в данном коде не так?
Попытка выставить любую частоту выше 83 заканчивается одним и тем же, работой на частоте 50 Гц.
компилятор CodevisionAVR, проверяю в протеусе.
Код естественно будет доработан плюшками, но пока хоть разобраться с частотой, она регулируется только в диапазоне 0-83 Гц
Попытка производить вычисления в теле прерывания таймера 1 приводит вообще к околесице, к тому же самому только в 30 Гц.
в синусе 256 значений, для целого числа сдвига фаз.
потолком является величина 2-значная.
Регистр OCR1A как и таймер 1 16 битный.
Число 8000000/(256*freq) в любом случае меньше 2 байт.
Процедура деления выполняется нацело, т.е. без плавающей точки, т.е. те же 100 Гц будут в регистре OCR1A числом 138 или же OCR1AH=0x01 OCR1AL=0x38, при попытке прописать эти значения в лоб, то же самое происходит что при вычислении (естественно вычисление закоменчивается при этом).
Что за затык может быть такой искусственный?
