Hi,
I'm trying to control a brushed DC motor. The board has a drive circuit that takes a pwm and a direction signal. I've tried to configure the three phase timer to only use outputs v, v(neg) and timer TA1 to control the motor. I've managed to set up the timer so I get a pwm out. The problem is that I can not change the duty cycle of the pwm (TA1 register).
When I step through the code I see that I can not seem to change ICTB2 register. I want to set it to 0x01 but it remains on the value 0x9F.
void pwm_initPWM(void){
void
{
//Disable IRQ
asm("FCLR I"); //TODO Fixa macro
//==========================================
// Set PRCR register
//According to datasheet, you need to use move to set this register - use temp variable?
temp = ictb2;temp &= 0x01;ictb2 = temp;
temp = ictb2;
temp &= 0x01;
ictb2 = temp;
//Trigger interrupt every time b2 underflows.
// Set PRCR register - WR disable
prcr = 0x02;
// Configure 3-phase timer
//PRC1 in PRCR should be set before
invc0 = 0x1C;
// Bit 0-1 - 00
// Bit 2 - Three phase timers enable = 1
// Bit 3 - Enable output = 1
// Bit 4 - Simulataneous Conduction protection = 1
// Bit 5 - SC detection (Read only) = 0
// Bit 6 - Pwm mode = 0 (Triangle)
// Bit 7 - Software trigger ? =test setting to 0
invc1 = 0x50;
// Bit 0 - When to reload = 0 (only when tb2 reloads)
// Bit 1 - Three phase mode = 0
// Bit 2 - Dead time counter clk source = 0 (f1=24M)
// Bit 3 - Carrier wave detection flag = 0(Read Only)
// Bit 4 - Active level control bit = 1 (active high output)
// Bit 5 - Dead time disable = 0 (Enable)
// Bit 6 - Dead time trigger = 1
// Bit 7 - 0
prcr = 0x00;
// TB2 Settings
tb2sc = 0x00;
//Bit 0 - Set reload options for B2 timer = 0 (PWMCON = 0)
//Which should be used?
idb0 = 0x3B;
// Bit 2 - Enable V shift registers = 0 (Active)
// Bit 6 and 7 = 0
idb1 = 0x37;
// Bit 3 - Enable V^ shift registers = 0 (Active)
// Configure Timer TA1 and TB2
ta1mr = 0x12;
//Bit 0-1 - Timer mode = 10 (One shot)
//Bit 4 - Trigger Select = 1 (Three phase)
tb2mr = 0x00;
//Bit 0-1 - Operating mode bit = 00
//Bit 2-5 - MR0-3 = 0000
//Bit 6-7 - CLK select = 00 (f1=24MHz)
trgsr = 0x01 ;
//Bit 0-1 - Trigger on V-phase = 01(?)
// Configure pwm counter timer TB2
tb2 = 750;
//PWM Freq = f1 / (tb2*2) = 24 /1500 = 16kHZ
tb2ic = 0x07;
// Timer B2 interrupt priority level 7
//===========================================
// Dead time counter
//TODO: kolla med Magnus vad som kan varavettigt
vettigt
//Simultaneous conduction protection is enabled
dtt = 10;
//Dead time counter 10x41,6 ns approx 400 ns; //TODO: Check
// PWM Register
ta1 = pwm_pwmValue;
//PWM
// Output settings
//Disable register protect
iobc = 0x00;
//Bit 7 - Three phase output pin setting = 0 (use port p7
//Enable register protect
// Pin setting
p7_2s = 0x02;
// V
p7_3s = 0x02;
// V(Negative phase)s
pd7_2 = 1;pd7_3 = 1;
pd7_2 = 1;
pd7_3 = 1;
//Enable IRQ
asm("FSET I"); //TODO Use macro
// Start timer B2
// (TA1 is started automatically)
tabsr = 0x82;
//Bit 1 - Set A1 Counter to sample input
//Bit 7 - Set TB2S bit to 1 to start timer
}void pwm_setPWM(int pwm){if (pwm == 0 || pwm_pwmEn == 0){if(pwm_pwmEn == 1){pwm_disablePWM();}}if (pwm >= 0){//PORT_POWER_PHASE = 1; //TODO remove comment}else{//PORT_POWER_PHASE = 0;pwm = -pwm;}if (pwm > PWM_MAX) //TODO Set PWM_MAX as parameterpwm = PWM_MAX;else if(pwm < -PWM_MAX){pwm = -PWM_MAX;}pwm_pwmValue = pwm;}//IRQ function
}
if (pwm == 0 || pwm_pwmEn == 0){
if(pwm_pwmEn == 1){pwm_disablePWM();}}
pwm_disablePWM();
if (pwm >= 0){
//PORT_POWER_PHASE = 1; //TODO remove comment
else{
//PORT_POWER_PHASE = 0;
pwm = -pwm;
if (pwm > PWM_MAX) //TODO Set PWM_MAX as parameter
pwm = PWM_MAX;
else if(pwm < -PWM_MAX){pwm = -PWM_MAX;}pwm_pwmValue = pwm;}
pwm = -PWM_MAX;
pwm_pwmValue = pwm;
//IRQ function
Hi again,
I have managed to work out a way to set the duty cycle on the PWM. It worked when I changed to three phase mode 1 and set the duty cycle with ta1 and ta11.
The problem with setting ictb2 is still present. If I set it to 0x01 i get timer B (carrier signal) interrupts every 9'th pwm cycle. Why would this be? Could there be some prescaler I have forgotten? The code I pasted last is still true. I guess it could be something in the pll setting but the rest of the application seems to work.
I'm happy for any suggestions and ideas.
Best Regards,
Ola
Hey,
When initialization of the ICTB2, according to the datasheet on page 249, the 'MOV' function is required.
Therefore ICTB2 should be initialized as so:
mov BYTE PTR [ictb2], 0x01;
Furthermore, on the same page of the data sheet figure 17.6:
"when the INV00 bit in the INVC0 register is set to 1, the first interrupt is generating if the timer B2 underflows n-1 times. Subsequent interrupts are generated every n times the timer B2 underflows (n = setting value of the ICTB2 counter)"
With this it should trigger the interrupt right away when the program starts and then should be triggered appropriately from then on out. Other than that, everything seems to be initialized properly and should be reacting appropriately.
Hope this helps out,
Anthony