Skip to content
cr88192 edited this page Nov 5, 2015 · 1 revision

Simple 3 Phase driver for MSP430. Written for the MSP430G2232, but should work on bigger chips.

Some features don't really work correctly, but alas.

 #include <msp430.h>
 
 typedef unsigned char byte;
 typedef unsigned int uint;
 typedef unsigned long ulong;
 
 #if 0
 const byte sintab[64]= {
 		128, 140, 152, 165, 176, 188, 198, 208,
 		218, 226, 234, 240, 245, 250, 253, 254,
 		255, 254, 253, 250, 245, 240, 234, 226,
 		218, 208, 198, 188, 176, 165, 152, 140,
 		128, 115, 103,  90,  79,  67,  57,  47,
 		 37,  29,  21,  15,  10,   5,   2,   1,
 		  0,   1,   2,   5,  10,  15,  21,  29,
 		 37,  47,  57,  67,  79,  90, 103, 115
 };
 #endif
 
 const byte sintab1_2[64]= {
 		128, 167, 184, 196, 206, 215, 223, 229,
 		235, 240, 244, 247, 250, 252, 254, 255,
 		255, 255, 254, 252, 250, 247, 244, 240,
 		235, 229, 223, 215, 206, 196, 184, 167,
 		128,  88,  71,  59,  49,  40,  32,  26,
 		 20,  15,  11,   8,   5,   3,   1,   0,
 		  0,   0,   1,   3,   5,   8,  11,  15,
 		 20,  26,  32,  40,  49,  59,  71,  88
 };
 
 short phase_cnt;
 short phase_div;
 short phase_pot;
 
 byte phofs[4];
 byte phcnt[4];
 byte phduty[4];
 
 byte phase;
 byte dutysc;			//duty-cycle scale
 byte madutysc;			//master duty-cycle scale
 
 uint vfduty;			//VF duty drop-off
 
 byte phcnt2[2];
 byte phduty2[2];
 
 byte dacm;
 byte vcsense;
 byte vcref;
 byte vcphase;
 
 byte (*func)(byte ph);
 void (*updatePhase)(byte ph);
 void (*updatePhaseB)(byte ph);
 
 
 byte fix_sin8(byte ph)
 {
 	return(sintab1_2[(byte)(ph>>2)]);
 }
 
 byte fix_cos8(byte ph)
 {
 	return(sintab1_2[(byte)((ph+64)>>2)]);
 }
 
 byte fix_sqr8(byte ph)
 {
 	return((byte)(((signed char)ph)>>7));
 }
 
 void updateDutyVfDecay(void)
 {
 	uint i;
 	i=(((ulong)phase_div)*vfduty+128)>>8;
 	if(i>255)i=255;
 	i=((255-i)*madutysc)>>8;
 	dutysc=i;
 }
 
 #if 1
 void updatePhase1(byte ph)
 {
 	int ds;
 	ds=func(phase+phofs[ph]);
 //	ds=(ds*dutysc)>>8;
 	ds=(((ds-128)*dutysc)>>8)+128;
 	phduty[ph]=ds;
 }
 
 void updatePhase1C(byte ph)
 {
 	phduty[ph]=128;
 }
 
 void updatePhase2(byte ph)
 {
 	int ds;
 	ds=func(phase+phofs[ph]);
 	ds=(ds<<1)-256;
 	if(ph&1)ds=-ds;
 	if(ds<0)ds=0;
 	ds=(((unsigned int)ds)*dutysc)>>8;
 //	ds=(((ds-128)*dutysc)>>8)+128;
 	phduty[ph]=ds;
 }
 #endif
 
 void updateVreg(void)
 {
 	int i;
 	if(vcsense<vcref)
 	{
 		i=phduty2[0]-1;
 		if(i<16)i=16;
 		phduty2[0]=i;
 	}else if(vcsense>vcref)
 	{
 		i=phduty2[0]+1;
 		if(i>240)i=240;
 		phduty2[0]=i;
 	}
 }
 
 void updatePin1(byte ph)
 {
 	int i;
 //	i=phcnt[ph]+sintab[(byte)(phase+phofs[ph])];
 	i=phcnt[ph]+phduty[ph];
 	phcnt[ph]=i;
 	if(i&0x100)
 		{ P1OUT|=1<<ph; }
 	else
 		{ P1OUT&=~(1<<ph); }
 }
 
 void updatePin2(byte ph)
 {
 	int i;
 	i=phcnt2[ph]+phduty2[ph];
 	phcnt2[ph]=i;
 	if(i&0x100)
 		{ P2OUT|=1<<ph; }
 	else
 		{ P2OUT&=~(1<<ph); }
 }
 
 void clearPhases(void)
 {
 	phduty[0]=0;	phduty[1]=0;
 	phduty[2]=0;	phduty[3]=0;
 	phduty2[0]=0;	phduty2[1]=0;
 	P1OUT&=~15;
 	P2OUT&=~3;
 }
 
 byte st, lst, nph;
 
 struct phaseMode_s {
 	byte phofs[4];
 	byte (*func)(byte ph);
 	void (*updatePhase)(byte ph);
 	void (*updatePhaseB)(byte ph);
 	byte nph;
 };
 
 const struct phaseMode_s phaseMode[]={
 {	0, 85, 171, 0, fix_sin8,
 	updatePhase1, updatePhase1C, 3},
 {	171, 85, 0, 0, fix_sin8,
 	updatePhase1, updatePhase1C, 3},
 {	0, 85, 171, 0, fix_sqr8,
 	updatePhase1, updatePhase1C, 3},
 {	171, 85, 0, 0, fix_sqr8,
 	updatePhase1, updatePhase1C, 3},
 {	0, 0, 64, 64, fix_sin8,
 	updatePhase2, updatePhase2, 4},
 {	64,	64,	0,	0, fix_sin8,
 	updatePhase2, updatePhase2, 4},
 {	0, 0, 64, 64, fix_sqr8,
 	updatePhase2, updatePhase2, 4},
 {	64,	64,	0,	0, fix_sqr8,
 	updatePhase2, updatePhase2, 4}
 };
 
 void setPhaseMode(byte mode)
 {
 	struct phaseMode_s *phm;
 
 	st=mode;
 	lst=st;
 	phm=(struct phaseMode_s *)(&(phaseMode[st]));
 
 	phofs[0]=phm->phofs[0];
 	phofs[1]=phm->phofs[1];
 	phofs[2]=phm->phofs[2];
 	phofs[3]=phm->phofs[3];
 	func=phm->func;
 	updatePhase=phm->updatePhase;
 	updatePhaseB=phm->updatePhaseB;
 	nph=phm->nph;
 }
 
 void updateMainPhase(void)
 {
 	int i;
 
 	phase=phase+8;
 	phase_cnt=phase_div;
 
 	updateDutyVfDecay();
 
 	updatePhase(0);
 	updatePhase(1);
 	updatePhase(2);
 	updatePhaseB(3);
 
 	i=P2IN;
 	st=(i>>2)&7;
 	if(st!=lst)
 	{
 		lst=st;
 		setPhaseMode(st);
 	}
 }
 
 void updateMainPhase2(void)
 {
 	if(!(vcphase++))
 	{
 		updateVreg();
 	}
 
 	if(phase_cnt<=0)
 	{
 		if(phase_div>1012)
 		{
 			clearPhases();
 			while(phase_div>1012)
 				__bis_SR_register(CPUOFF + GIE);
 			return;
 		}
 
 		updateMainPhase();
 	}
 }
 
 int main(void)
 {
 	BCSCTL1 = CALBC1_16MHZ;
 	DCOCTL = CALDCO_16MHZ;
 
 //	WDTCTL=WDTPW|WDTHOLD;
 
 	WDTCTL = WDT_MDLY_0_5;		//0.5ms at 1MHz (2kHz), 0.03125ms (32kHz) at 16MHz
 //	WDTCTL = WDT_MDLY_0_064;
 	IE1 |= WDTIE;
 
 	//	P1DIR|=0x07;
 	P1DIR|=0x0F;
 	P2DIR|=0x03;
 	P1OUT=0;
 	P2OUT=0;
 
 	P2REN|=0x1C;
 
 //	ADC10CTL0 = SREF_1 + ADC10SHT_2 + ADC10ON + ADC10IE + REF2_5V + REFON;
 	ADC10CTL0 = ADC10SHT_2 + ADC10ON + ADC10IE + REF2_5V + REFON;
 	ADC10CTL1 = INCH_4;
 	ADC10AE0 |= 0x10;
 
 	phase_div=16;
 
 	setPhaseMode(0);
 
 	dutysc=255;
 	madutysc=255;
 	vfduty=192;
 	dacm=0;
 	ADC10CTL0 |= ENC + ADC10SC;
 
 	__bis_SR_register(GIE);
 
 	for(;;)
 	{
 		updatePin1(0);
 		updatePin1(1);
 		updatePin1(2);
 		updatePin1(3);
 
 		updatePin2(0);
 		updatePin2(1);
 
 		updateMainPhase2();
 	}
 	
 //	return 0;
 }
 
 
 #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
 #pragma vector=ADC10_VECTOR
 __interrupt void ADC10_ISR(void)
 #elif defined(__GNUC__)
 void __attribute__ ((interrupt(ADC10_VECTOR))) ADC10_ISR (void)
 #else
 #error Compiler not supported!
 #endif
 {
 	unsigned long i;
 	__bic_SR_register_on_exit(CPUOFF);
 
 #if 1
 	switch(dacm)
 	{
 	case 0:
 		phase_pot=ADC10MEM;
 		i=1023-phase_pot;
 		i=(i*i+512)>>10;
 //		i=(i*i*i)>>20;
 		phase_div=i;
 		dacm=1;
 		break;
 	case 1:
 //		dutysc=ADC10MEM>>2;
 //		madutysc=ADC10MEM>>2;
 		dacm=2;
 		break;
 	case 2:
 		vcsense=ADC10MEM>>2;
 		dacm=3;
 		break;
 	case 3:
 		vcref=ADC10MEM>>2;
 		dacm=0;
 		break;
 	default:
 		dacm=0;
 		break;
 	}
 #endif
 
 //	phase_div=1024-ADC10MEM;
 //	phase_div=16383-(ADC10MEM<<4);
 
 	ADC10CTL1 = (ADC10CTL1&0x0FFF)|((4+dacm)<<12);
 	ADC10AE0 = 0x10<<dacm;
 	ADC10CTL0 |= ENC + ADC10SC;
 }
 
 // Watchdog Timer interrupt service routine
 #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
 #pragma vector=WDT_VECTOR
 __interrupt void watchdog_timer(void)
 #elif defined(__GNUC__)
 void __attribute__ ((interrupt(WDT_VECTOR))) watchdog_timer (void)
 #else
 #error Compiler not supported!
 #endif
 {
 	phase_cnt--;
 }
Clone this wiki locally