Hi all, my aim is to control a driver of a brushless motor by using 6 pins that come directly from 6 pins of my microcontroller (MSP432P401R), where 3 of them act as normal GPIO and represent the lower transistors (BA, BB, BC) and the other pins have the special function of PWM (TA,TB,TC) and share the same timer and port as well (P2.4, P2.5 and P2.6) respectively. The program is based on a FSM of 6 states and in each state there are 2 pins that stay HIGH and the rest stay LOW as it could be seen in the image above. The sequence is the one that appears in the image and when it arrives to the 6th state it starts over going to the 1rst state and so on. To sum up, TA, TB and TC are controlled using PWM and duty cycle is applied on them to take control of the speed of the motor and BA,BB and BC are normal GPIOs that could be HIGH or LOW depending on the state. My main problem is that I don't know how to switch between TA, TB and TC by applying PWM on one pin and disabling the PWM applied on another pin in the state before, like for example what happens then you reach the 3rd state and you should stop applying PWM to TA and start applying it on TB (hope it's clear). The code I wrote for this is the following one, but I know it has problems and if someone could help me understand what should I do and how to do it in a properly way, I would be really grateful!
#include "msp.h"
#define PWM 0x70 // 0111 0000
#define GPIO 0xE0 // 1110 0000
uint8_t estado = 0;
void inicializaciones(void){
/* TA: P2.4; TB: P2.5; TC: P2.6
* BA: P3.5; BB: P3.6; BC: P3.7
*/
// Pins Transistors HIGH (PWM)
P2->SEL0 |= PWM; // Configuramos los pines P2.4 (TA0.1), P2.5 (TA0.2) y P2.6 (TA0.3)
P2->SEL1 &= ~PWM;
P2->DIR |= PWM; // Para poner TA0.1, TA0.2 y TA0.3
// Pins Transistors LOW (GPIO)
P3->SEL0 &= ~GPIO;
P3->SEL1 &= ~GPIO;
P3->DIR |= GPIO; // output
}
void TimerA0(void){ // Timer para controlar los 3 pines PWM
TIMER_A0->CCTL[0] = TIMER_A_CCTLN_CCIE; // TACCR0 interrupt enabled
TIMER_A0->CCR[0] = 32767; // Periodo del PWM
TIMER_A0->CTL = TIMER_A_CTL_TASSEL_1 | TIMER_A_CTL_MC__UP; // Reloj ACLK (ACLK = TACLK = 32768H), Up Mode
}
void main(void)
{
WDT_A->CTL = WDT_A_CTL_PW | WDT_A_CTL_HOLD; // stop watchdog timer
inicializaciones();
__enable_irq(); // Enable global interrupt
TimerA0();
while(1){
switch(estado){
case 0: { // TA y BB HIGH
TIMER_A0->CCTL[1] = TIMER_A_CCTLN_OUTMOD_3 |TIMER_A_CCTLN_CCIE; // TACCR1 interrupt enabled; ModoCCR1: Set/Reset
P3->OUT |= (GPIO & ~(BIT7 | BIT5)); // 0100 0000, P3.6 (BB) HIGH
estado++;
}
case 1: { // TA y BC HIGH
P3->OUT |= (GPIO & ~(BIT6 | BIT5)); // 1000 0000, P3.7 (BC) HIGH
estado++;
}
case 2: { // TB y BC HIGH
TIMER_A0->CCTL[2] = TIMER_A_CCTLN_OUTMOD_3 |TIMER_A_CCTLN_CCIE; // TACCR2 interrupt enabled; ModoCCR1: Set/Reset
estado++;
}
case 3: { // BA y TB HIGH
P3->OUT |= (GPIO & ~(BIT7 | BIT6)); // 0010 0000, P3.5 (BA) HIGH
estado++;
}
case 4: { // BA y TC HIGH
TIMER_A0->CCTL[3] = TIMER_A_CCTLN_OUTMOD_3 |TIMER_A_CCTLN_CCIE; // TACCR3 interrupt enabled; ModoCCR1: Set/Reset
estado++;
}
case 5: { // BB y TC HIGH
P3->OUT |= (GPIO & ~(BIT7 | BIT5)); // 0100 0000, P3.6 (BB) HIGH
estado = 0;
}
}
}
}
void TA0_N_IRQHandler(void)
{
if(TIMER_A0->CCTL[1]&TIMER_A_CCTLN_CCIFG)
{
TIMER_A0->CCTL[1] &= ~TIMER_A_CCTLN_CCIFG;
TIMER_A0->CCR[1] = 8191; // f(ACLK)/4 = 8192Hz
}
if(TIMER_A0->CCTL[2]&TIMER_A_CCTLN_CCIFG)
{
TIMER_A0->CCTL[2] &= ~TIMER_A_CCTLN_CCIFG;
TIMER_A0->CCR[1] = 0; // Reset TA0.1
TIMER_A0->CCR[2] = 8191; // f(ACLK)/4 = 8192Hz
}
if(TIMER_A0->CCTL[3]&TIMER_A_CCTLN_CCIFG)
{
TIMER_A0->CCTL[3] &= ~TIMER_A_CCTLN_CCIFG;
TIMER_A0->CCR[2] = 0; // Reset TA0.2
TIMER_A0->CCR[3] = 8191; // f(ACLK)/4 = 8192Hz
}
if(TIMER_A0->CTL&TIMER_A_CTL_IFG)
{
// Clear timer overflow flag
TIMER_A0->CTL &= ~TIMER_A_CTL_IFG;
}
}
#include "msp.h"
#define PWM 0x70 // 0111 0000
#define GPIO 0xE0 // 1110 0000
uint8_t estado = 0;
void inicializaciones(void){
/* TA: P2.4; TB: P2.5; TC: P2.6
* BA: P3.5; BB: P3.6; BC: P3.7
*/
// Pins Transistors HIGH (PWM)
P2->SEL0 |= PWM; // Configuramos los pines P2.4 (TA0.1), P2.5 (TA0.2) y P2.6 (TA0.3)
P2->SEL1 &= ~PWM;
P2->DIR |= PWM; // Para poner TA0.1, TA0.2 y TA0.3
// Pins Transistors LOW (GPIO)
P3->SEL0 &= ~GPIO;
P3->SEL1 &= ~GPIO;
P3->DIR |= GPIO; // output
}
void TimerA0(void){ // Timer para controlar los 3 pines PWM
TIMER_A0->CCTL[0] = TIMER_A_CCTLN_CCIE; // TACCR0 interrupt enabled
TIMER_A0->CCR[0] = 32767; // Periodo del PWM
TIMER_A0->CTL = TIMER_A_CTL_TASSEL_1 | TIMER_A_CTL_MC__UP; // Reloj ACLK (ACLK = TACLK = 32768H), Up Mode
}
void main(void)
{
WDT_A->CTL = WDT_A_CTL_PW | WDT_A_CTL_HOLD; // stop watchdog timer
inicializaciones();
__enable_irq(); // Enable global interrupt
TimerA0();
while(1){
switch(estado){
case 0: { // TA y BB HIGH
TIMER_A0->CCTL[1] = TIMER_A_CCTLN_OUTMOD_3 |TIMER_A_CCTLN_CCIE; // TACCR1 interrupt enabled; ModoCCR1: Set/Reset
P3->OUT |= (GPIO & ~(BIT7 | BIT5)); // 0100 0000, P3.6 (BB) HIGH
estado++;
}
case 1: { // TA y BC HIGH
P3->OUT |= (GPIO & ~(BIT6 | BIT5)); // 1000 0000, P3.7 (BC) HIGH
estado++;
}
case 2: { // TB y BC HIGH
TIMER_A0->CCTL[2] = TIMER_A_CCTLN_OUTMOD_3 |TIMER_A_CCTLN_CCIE; // TACCR2 interrupt enabled; ModoCCR1: Set/Reset
estado++;
}
case 3: { // BA y TB HIGH
P3->OUT |= (GPIO & ~(BIT7 | BIT6)); // 0010 0000, P3.5 (BA) HIGH
estado++;
}
case 4: { // BA y TC HIGH
TIMER_A0->CCTL[3] = TIMER_A_CCTLN_OUTMOD_3 |TIMER_A_CCTLN_CCIE; // TACCR3 interrupt enabled; ModoCCR1: Set/Reset
estado++;
}
case 5: { // BB y TC HIGH
P3->OUT |= (GPIO & ~(BIT7 | BIT5)); // 0100 0000, P3.6 (BB) HIGH
estado = 0;
}
}
}
}
void TA0_N_IRQHandler(void)
{
if(TIMER_A0->CCTL[1]&TIMER_A_CCTLN_CCIFG)
{
TIMER_A0->CCTL[1] &= ~TIMER_A_CCTLN_CCIFG;
TIMER_A0->CCR[1] = 8191; // f(ACLK)/4 = 8192Hz
}
if(TIMER_A0->CCTL[2]&TIMER_A_CCTLN_CCIFG)
{
TIMER_A0->CCTL[2] &= ~TIMER_A_CCTLN_CCIFG;
TIMER_A0->CCR[1] = 0; // Reset TA0.1
TIMER_A0->CCR[2] = 8191; // f(ACLK)/4 = 8192Hz
}
if(TIMER_A0->CCTL[3]&TIMER_A_CCTLN_CCIFG)
{
TIMER_A0->CCTL[3] &= ~TIMER_A_CCTLN_CCIFG;
TIMER_A0->CCR[2] = 0; // Reset TA0.2
TIMER_A0->CCR[3] = 8191; // f(ACLK)/4 = 8192Hz
}
if(TIMER_A0->CTL&TIMER_A_CTL_IFG)
{
// Clear timer overflow flag
TIMER_A0->CTL &= ~TIMER_A_CTL_IFG;
}
}