Bir MC68HC908GP32 mikrodenetleyici kullanarak sinüs sinyali doğru şekilde üretemiyoruz . PWM açıklaması sayfa 349'da başlar. Saat frekansı 2.4MHz iken, ön ölçekleyiciyi kullanarak ve zamanlayıcı modulo'unu 350'ye aşağıdaki gibi ayarlayarak 7 kHz PWM kullandık:
T1SC = 0x60; // Prescaler: Div entre 64
//Counter modulo = 0x015E = 350
T1MODH = 0x01; // High
T1MODL = 0x5E; // Low
PWM çıkışı aşağıdaki RLC filtresi ile filtrelenir ve daha sonra DC bir seri 1 uF kapak kullanılarak çıkarılır. Kesme frekansı PWM'nin 7kHz'in çok altında.
İlk olarak, bir LUT kullanarak denedik, bu örnekler bu site kullanılarak üretildi (100 örnek, genlik = 250). Bu tek bir dönemden oluşur.
int seno[100]={ 125, 133, 141, 148, 156, 164, 171, 178, 185, 192, 198, 205, 211, 216, 221, 226, 231, 235, 238, 241, 244, 246, 248, 249, 250, 250, 250, 249, 248, 246, 244, 241, 238, 235, 231, 226, 221, 216, 211, 205, 198, 192, 185, 178, 171, 164, 156, 148, 141, 133, 125, 117, 109, 102, 94, 86, 79, 72, 65, 58, 52, 45, 39, 34, 29, 24, 19, 15, 12, 9, 6, 4, 2, 1, 0, 0, 0, 1, 2, 4, 6, 9, 12, 15, 19, 24, 29, 34, 39, 45, 52, 58, 65, 72, 79, 86, 94, 102, 109, 117};
Aşağıdaki darbenin genişliği her PWM döngüsünde hesaplanır:
interrupt 4 void rsi_t1ch0 (void)
{
//-- disable interruption flag
T1SC0&=(~0x80);
//-- pwm to '0'
PTB&=0xFD;
//some sensor measures are done here.... 100 out of the 350 cycles are left for this
}
/************************************************************/
/* TIM1 overflow rutine */
/************************************************************/
interrupt 6 void rsi_ov1 (void)
{
T1SC&=(~0x80);
//-- set PWM to 1
PTB|=0x02;
T1CH0H = ((seno[fase])>>8); // high bits
T1CH0L = (seno[fase])&0xFF; // low bits
fase+=1;
if (fase >= 99)
fase=0;
}
void main(void)
{
float temp;
int i;
CONFIG1|=0x01;
DDRB=0xFF; //-- Port B is set as output
PTB=0x00;
//Timer setup
T1SC = 0x60; // Prescaler: Div by 64
T1MODH = 0x01; //Counter modulo
T1MODL = 0x5E;
T1SC0 = 0x50; //Comparator setup
//-- Initial width
T1CH0H = 0x00;
T1CH0L = 0x53;
EnableInterrupts;
T1SC&=~(0x20); //Run timer forever
for(;;);
}
Kapsam içine eklediğinizde, aşağıdaki sinyali alırız. Minimum seviyeye yakın bu tuhaf tepeden kaçınamıyoruz.
Bu tepe noktasını yakınlaştırırken, PWM çıkışının (yukarı) aslında nasıl yanlış olduğunu görebiliriz.
Bu nedenle, bir süre uğraştıktan ve ondan kurtulamadan sonra, her bir numune için değeri sabit kodlamak yerine MCU'daki sinüs sinyalini hesaplamayı denedik. Tüm sayaç kurulumundan hemen önce ana fonksiyona aşağıdaki kodu ekledik:
for(i=0;i<99;i++) {
temp=100*(sin(2*3.14159*i/100)+1);
seno[i]=(int)temp;
}
Ancak sonuçlar sinüsoid gibi görünmüyor:
Saatlerce uğraştıktan sonra hatamızı bulamadık. Biz bir tavsiye için teşekkür ederiz.