Kami tidak dapat menghasilkan sinyal sinus dengan benar menggunakan mikrokontroler MC68HC908GP32 . Deskripsi PWM dimulai di halaman 349. Frekuensi clock adalah 2,4MHz, sementara kami telah menggunakan PWM 7 kHz dengan menggunakan prescaler dan mengatur timer ke 350 sebagai berikut:
T1SC = 0x60; // Prescaler: Div entre 64
//Counter modulo = 0x015E = 350
T1MODH = 0x01; // High
T1MODL = 0x5E; // Low
Output PWM adalah filter oleh filter RLC berikut, dan kemudian DC dihapus menggunakan tutup seri 1uF. Frekuensi cutoff jauh di bawah 7kHz PWM.
Pertama, kami telah mencoba menggunakan LUT, sampel mana yang dihasilkan menggunakan situs ini (100 sampel, amplitudo = 250). Ini terdiri dari satu periode.
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};
Lebar pulsa berikut dihitung setiap siklus PWM:
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(;;);
}
Saat memasukkannya ke dalam ruang lingkup, kami mendapatkan sinyal berikut. Kami tidak dapat menghindari puncak aneh di dekat minimum.
Ketika memperbesar di sekitar puncak itu, kita dapat melihat bagaimana output PWM (naik) sebenarnya salah.
Jadi, setelah bermain-main sebentar dan tidak dapat menghilangkannya, kami telah mencoba menghitung sinyal sinus di MCU, alih-alih mengkodekan nilai untuk setiap sampel. Kami telah menambahkan kode berikut dalam fungsi utama, tepat sebelum semua pengaturan penghitung:
for(i=0;i<99;i++) {
temp=100*(sin(2*3.14159*i/100)+1);
seno[i]=(int)temp;
}
Tetapi hasilnya bahkan tidak terlihat seperti sinusoid:
Setelah berjam-jam berjuang dengan itu, kami belum dapat menemukan kesalahan kami. Kami akan sangat menghargai saran.
sumber
Jawaban:
Di bagian bawah halaman 350 dari lembar data mikrokontroler, disebutkan bahwa menulis nilai kecil ke register nilai timer selama interupsi melimpah dapat menyebabkan interupsi berikutnya dipicu hanya pada iterasi pwm berikutnya, karena timer terus menghitung sementara interupsi rutin sedang dijalankan.
Hal ini dikonfirmasikan oleh fakta bahwa nilai PWM bertahan tinggi untuk satu periode clock PWM keseluruhan + yang terlihat seperti panjang timer (berdasarkan panjang sekitarnya). Nilai yang ditulis ke register panjang timer mungkin mendekati 0 pada saat kesalahan, sehingga cukup layak bahwa penghitung telah melewati nilai yang lebih kecil selama interupsi, dan hanya akan memicu pada siklus berikut.
Ini bisa diperbaiki dengan meningkatkan level minimum sinusoid ke level yang lebih tinggi dari waktu yang diperlukan untuk menjalankan ISR, atau mengubah mekanisme yang digunakan untuk mengatur level baru. Bagian atas halaman 351 menjelaskan bagaimana ini dapat dilakukan.
sumber