Hello,
For some reason, it seems that it is not possible to perform I2C communication and run a PWM at the same time, even if the pins are different. Whenever the PWM starts running, the I2C communication reads an incorrect value and then fails afterwards. Please see attached code. The I2C module is EUSCI_B0, and the PWM is running on Timer A0. Any help would be greatly appreciated!
#include "msp.h"
#include "stdio.h"
#include "driverlib.h"
#define CLKFRQ 3000000
#define SlaveAddress 0x48
#define T 1
#define initTime 5 //
#define BUFSIZE 512
#define PWMCTGT 3000
void i2cTransmitMBStart(char);
char i2cReceiveMBStop();
void initPWM();
void setPWM(float);
const eUSCI_I2C_MasterConfig i2cConfig = {
EUSCI_B_I2C_CLOCKSOURCE_SMCLK, // SMCLK Clock Source
CLKFRQ, // SMCLK = 3MHz
100000, // Desired I2C Clock of 100khz
0, // No byte counter threshold
EUSCI_B_I2C_NO_AUTO_STOP // No Autostop
};
const Timer_A_UpModeConfig upConfig = {
TIMER_A_CLOCKSOURCE_SMCLK,
TIMER_A_CLOCKSOURCE_DIVIDER_64,
T * CLKFRQ / 64,
TIMER_A_TAIE_INTERRUPT_DISABLE,
TIMER_A_CCIE_CCR0_INTERRUPT_ENABLE,
TIMER_A_DO_CLEAR
};
Timer_A_PWMConfig pwmConfig0 = {
TIMER_A_CLOCKSOURCE_SMCLK,
TIMER_A_CLOCKSOURCE_DIVIDER_1,
PWMCTGT,
TIMER_A_CAPTURECOMPARE_REGISTER_1,
TIMER_A_OUTPUTMODE_RESET_SET,
0
};
Timer_A_PWMConfig pwmConfig1 = {
TIMER_A_CLOCKSOURCE_SMCLK,
TIMER_A_CLOCKSOURCE_DIVIDER_1,
PWMCTGT,
TIMER_A_CAPTURECOMPARE_REGISTER_1,
TIMER_A_OUTPUTMODE_RESET_SET,
0 * PWMCTGT
};
int cnt = 0;
float dc = 0.5;
char temps[BUFSIZE];
char sem = 0;
/**
* main.c
*/
void main(void)
{
WDT_A -> CTL = WDT_A_CTL_PW | WDT_A_CTL_HOLD; //stop watchdog timer
CS_setDCOFrequency(CLKFRQ);
CS_initClockSignal(CS_SMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1);
// initialize the I2C master
GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P6, GPIO_PIN4, GPIO_PRIMARY_MODULE_FUNCTION);
GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P6, GPIO_PIN5, GPIO_PRIMARY_MODULE_FUNCTION);
I2C_initMaster(EUSCI_B1_BASE, &i2cConfig);
I2C_setSlaveAddress(EUSCI_B1_BASE, SlaveAddress);
I2C_enableModule(EUSCI_B1_BASE);
// I2C_clearInterruptFlag(EUSCI_B1_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT2 | EUSCI_B_I2C_NAK_INTERRUPT);
// I2C_enableInterrupt(EUSCI_B1_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT2 | EUSCI_B_I2C_NAK_INTERRUPT);
// Interrupt_setPriority(INT_EUSCIB1, 0x20);
// Interrupt_disableInterrupt(INT_EUSCIB1); //initially disabled
// initPWM();
// setPWM(0.0); //no control at first
GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P2, GPIO_PIN4, GPIO_PRIMARY_MODULE_FUNCTION);
Timer_A_generatePWM(TIMER_A0_BASE, &pwmConfig0);
// setup Timer A
CS_setDCOFrequency(CLKFRQ);
CS_initClockSignal(CS_SMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1);
Timer_A_configureUpMode(TIMER_A3_BASE, &upConfig); //configure Timer A using above struct
Timer_A_startCounter(TIMER_A3_BASE, TIMER_A_UP_MODE); //start Timer A
// Interrupt_setPriority(INT_TA3_0, 0x40);
Interrupt_enableInterrupt(INT_TA3_0);
for(; ; ) {}
// return;
}
void TA3_0_IRQHandler() {
// Interrupt_enableInterrupt(INT_EUSCIB1);
if (!sem) { //need to write to temperature register
I2C_setMode(EUSCI_B1_BASE, EUSCI_B_I2C_TRANSMIT_MODE);
I2C_masterSendSingleByte(EUSCI_B1_BASE, 0x00);
printf("Time\tTemp\n");
sem = 1;
}
I2C_setMode(EUSCI_B1_BASE, EUSCI_B_I2C_RECEIVE_MODE);
temps[cnt] = I2C_masterReceiveSingleByte(EUSCI_B1_BASE);
printf("%d\t%d\n", cnt, temps[cnt]);
// Interrupt_disableInterrupt(INT_EUSCIB1);
Timer_A_clearCaptureCompareInterrupt(TIMER_A3_BASE, TIMER_A_CAPTURECOMPARE_REGISTER_0);
cnt++;
if (cnt == initTime) {
// setPWM(dc);
Timer_A_generatePWM(TIMER_A0_BASE, &pwmConfig1);
}
if (cnt == BUFSIZE) {
Interrupt_disableInterrupt(INT_TA3_0);
}
return;
}
void initPWM() {
P2DIR = (P2DIR) | 0x10; //set Pin 2.4 as output
TA0CCR0 = PWMCTGT;
TA0CCTL1 = OUTMOD_7;
TA0CTL = TASSEL__SMCLK | MC__UP | TACLR;
return;
}
void setPWM(float dutyCycle) {
P2SEL0 = (P2SEL0) | 0x10;
P2SEL1 = (P2SEL1 & ~0x10);
TA0CCR1 = dutyCycle * PWMCTGT;
return;
}