This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSP432P401R: Controlling Duty Cycle by using buttons on MSP432P401R Launchpad

Part Number: MSP432P401R

Hi, my goal would be to be able to control the duty cycle value externally. For this I have thought of using the two pushbuttons that the MSP432P401R Launchpad has, that is, the S1 (P1.1) and S2 (P1.4). For this I post two codes: the first one I manage to get a PWM signal with a duty cycle, but I set it in the same program and that doesn't really interest me. Then I tried to it by using the pushbuttons, where one pushbutton allows me to increase my duty cycle by 10% each time I press it and the other one allows me to decrease it by 10% each time I press it, but I have two problems with the code: first, it never enters in the ISR (maybe because the NVIC is wrong) and second, I don't know very well how to deal with the overflow cases as they would be when the duty_cycle exceeds 100%. I thought about setting it to 100%, but what happens when it goes below 0%, if that is possible, since TACCR1 cannot take negative values. .

First code: it works fine, but is not what I really want as I mentioned before:

#include "msp.h"
#include <stdint.h>
#include <stdio.h>

volatile uint8_t contador_ms = 0;
uint8_t duty_cycle = 14; 

void transistors(void){
// TC: P7.6

// Transistor HIGH fase A (PWM)
P7SEL0 |= BIT6; 
P7SEL1 &= ~BIT6;
P7DIR |= BIT6; 
}

void TimerA1_PWM(void){ 
TA1CCR0 = 29; 
TA1CTL |= TASSEL_2 | ID_3 | MC_1 | TACLR; 
TA1CCTL2 |= OUTMOD_6; 
}

void TimerA0(void){
TA0CCR0 = 374;
TA0CTL |= TASSEL_2 | ID_3 | MC_1 | TACLR; 
}

void delay_ms(uint8_t tiempo){
contador_ms = 0;
TA0CTL |= MC_1; // up
TA0CCTL0 |= CCIE; 
while(contador_ms < tiempo);
TA0CTL &= ~MC_3; 
}

void init_interrupciones(void){
NVIC->ICPR[0] |= 0x00000100; 
NVIC->ISER[0] |= 0x00000100; 
__enable_irq(); // Enable global interrupt
}

void main(void)
{
WDT_A->CTL = WDT_A_CTL_PW | WDT_A_CTL_HOLD; // stop watchdog timer
transistors();
init_interrupciones();
TimerA1_PWM();
TimerA0();

while(1){
TA1CCR2 = duty_cycle; // TB HIGH en ON
delay_ms(10); // 10 ms de delay
TA1CCR2 = 0; // TB HIGH en OFF
delay_ms(10); // 10 ms de delay
}
}

void TA0_0_IRQHandler(void){ // Interrupt Timer A0
contador_ms++;
TA0CCTL0 &= ~CCIFG; // Limpiamos la interrupcion
}

Second code:

#include "msp.h"
#include <stdint.h>
#include <stdio.h>

volatile uint8_t contador_ms = 0;
volatile uint8_t duty_cycle = 50; // By setting this value we get approximately 50% Duty Cycle (takes values from 0 to 100).

void pulsadores(void){ // Use pushbuttons S2 (P1.4) and S1 (P1.1) to increase or decrease Duty Cycle by 10% respectively.
P1SEL0 &= ~(BIT4 | BIT1); // I/O
P1SEL1 &= ~(BIT4 | BIT1);
P1DIR &= ~(BIT4 | BIT1); 
P1REN |= (BIT4 | BIT1); // pull up/down
P1OUT |= (BIT4 | BIT1); // Pull-up
P1IES |= (BIT4 | BIT1); 
P1IE |= (BIT4 | BIT1); // interrupt enable
P1IFG &= ~(BIT4 | BIT1); // clear flag
}

void transistors(void){
// TC: P7.6

// Transistor HIGH fase A (PWM)
P7SEL0 |= BIT6; // Set PIN P7.6 (TA1.2) for output on Timer
P7SEL1 &= ~BIT6;
P7DIR |= BIT6; 
}

void TimerA1_PWM(void){ // Timer to control PWM pin
TA1CCR0 = 29; // (30-1) PWM Tperiod: 10 us -> As SMCLK = 3MHz, the counter counts in Up Mode every 1/3MHz = 0.333 us. Therefore, 30 - 0.333us = 10 us
TA1CTL |= TASSEL_2 | ID_3 | MC_1 | TACLR; // SMCLK clock with a frequency of 3 MHz and with a frequency divider of 8, Up Mode
TA1CCTL2 |= OUTMOD_6; // Mode CCR4: Toggle/Set
}

void TimerA0(void){
// for delay
TA0CCR0 = 374; // (375-1) Tperiode PWM: 1 ms
TA0CTL |= TASSEL_2 | ID_3 | MC_1 | TACLR; 
}

void delay_ms(uint8_t tiempo){
contador_ms = 0;
TA0CTL |= MC_1; // up
TA0CCTL0 |= CCIE; 
while(contador_ms < tiempo);
TA0CTL &= ~MC_3; // stop timer
}

void init_interrupciones(void){
NVIC->ICPR[0] |= 0x00000100; 
NVIC->ISER[0] |= 0x00000100; // Registers of 32 bits. enable interrupts on TimerA0_0
__enable_irq(); // Enable global interrupt
}

void main(void)
{
WDT_A->CTL = WDT_A_CTL_PW | WDT_A_CTL_HOLD; // stop watchdog timer
transistors();
init_interrupciones();
NVIC->ISER[1] = 1 << ((PORT1_IRQn) & 31); // Enable Port 1 interrupt on the NVIC
TimerA1_PWM();
TimerA0();

while(1){
TA1CCR2 = (duty_cycle/100)*TA0CCR0; // TB HIGH en ON
delay_ms(10); // 10 ms delay
TA1CCR2 = 0; // TB HIGH en OFF
delay_ms(10); // 10 ms delay
}
}

void TA0_0_IRQHandler(void){ // Interrupt Timer A0
contador_ms++;
TA0CCTL0 &= ~CCIFG; 
}

void PORT1_IRQHandler(void) // Interrupt Port P1
{
if(P1IFG & BIT4){
duty_cycle += 10; // increase in 10% el DC
if(duty_cycle > 100){
duty_cycle = 100; // for avoiding overflow over 100% DC
}
P1IFG &= ~BIT4; 
}
else if(P1IFG & BIT1){
duty_cycle -= 10; // decrease in 10% el DC
P1IFG &= ~BIT1; 
}
}