Частота таймера 72 МГц.
Я рассчитываю числа следующим образом:
Ft - частота таймера = 72000000 Hz
Fd - частота дискретизации. Выбираю 240000 Hz
Тогда, число для загрузки в регистр сравнения таймера TOMR0= Ft / Fd = 72000000 / 240000 = 300
Длина таблицы значений синуса N = 64 = 2^6;
Fs - необходимая частота выходного сигнала = 30000 Hz
Значит всю таблицу сигнала необходимо проходить за K прерываний. K = Fd/Fs = 240000 / 30000 = 8
Разрядность аккумулятора фазы Res=32
Тогда, приращение фазы delta = (2^Res) / K = (2^32) / 8 = 536870912
Для индексации элемента в таблице используются старшие 8 бит из аккумулятора фазы. Поэтому сдвигаем вправо на (2^Res) / N = 2^32 / 2^6 = 24
В результате моделирования в Кеиле получил вот такой график
Нажмите для просмотра прикрепленного файлаКод следующий:
Код
#include "LPC23XX.h"
int sinus[64]={512,562,613,662,710,756,800,840,878,
911,941,967,988,1004,1015,1022,1023,1019,1010,996,978,
954,927,895,859,820,778,733,686,638,588,537,486,435,385,
337,290,245,203,164,128,96,69,45,27,13,4,0,1,8,19,35,56,
82,112,145,183,223,267,313,361,410,461,511};
const int array_size=sizeof(sinus)/sizeof(int);
void GPIOResetInit(void);
static unsigned long phase=0;
unsigned int amplituda=1024;
static unsigned long delta=536870912;
/* Timer0 IRQ: Executed periodically */
__irq void Timer0ISR (void) {
DACR = ((sinus[phase>>26]*amplituda)>>4) & 0x0000FFFC;
phase += delta;
T0IR = 0x01; //sbros flaga prerivaniya.Avtomaticheski ne rabotaet
VICVectAddr = 0; /* Acknowledge Interrupt */
return;
}
/******************************************************************************
** Main Function main()
******************************************************************************/
int main (void)
{
GPIOResetInit();
VICIntSelect = 0x00; // all interrupts are IRQs
VICIntEnable = 0x10; // Channel#4 is the Timer0
VICVectAddr4=(unsigned)Timer0ISR;
FIO0DIR=1<<26;
PINSEL1 =1<<21; //vkluchaem DAC
//timer initialization
T0IR=0;
T0CTCR=0;
T0TC=0; //shchetniy register
T0PC=0;
T0PR=0;
T0MR0=300; // register sravnenia tipa OCR
T0MCR=3;
T0TCR=1;
while(1)
{
}
return 0;
}
void GPIOResetInit( void )
{
/* Reset all GPIO pins to default: primary function */
PINSEL0 = 0x00000000;
PINSEL1 = 0x00000000;
PINSEL2 = 0x00000000;
PINSEL3 = 0x00000000;
PINSEL4 = 0x00000000;
PINSEL5 = 0x00000000;
PINSEL6 = 0x00000000;
PINSEL7 = 0x00000000;
PINSEL8 = 0x00000000;
PINSEL9 = 0x00000000;
PINSEL10 = 0x00000000;
SCS |= 0x01;
IODIR0 = 0x00000000;
IODIR1 = 0x20000000;
IOSET0 = 0x00000000;
IOSET1 = 0x00000000;
FIO0DIR = 0x0000000f;
FIO1DIR = 0x20000000;
FIO2DIR = 0x0000000f;
FIO3DIR = 0x00000000;
FIO4DIR = 0x00000000;
FIO0SET = 0x00000000;
FIO1SET = 0x00000000;
FIO2SET = 0x00000000;
FIO3SET = 0x00000000;
FIO4SET = 0x00000000;
return;
};