Reputation: 1
I have been trying to control a simple digital potentiometer, MCP4131-502, through an MSP430G2553. I found a very useful source online that has already done a similar project, here linked, and I've tried to modify it to meet my requirements. However, after several attempts at debugging, I can't get the oscilloscope to show any change on the PW0 pin, and I can't see any change in the resistance. Below is the code I have been uploading to the microcontroller. The development board I am using is the MSP-EXP430G2 Rev1.5 and I only have the jumpers Vcc, test, and rst connected.
enter image description here development board
enter image description here circuit used
enter image description here PW0 and CS lines
enter image description here SCLK and CS lines
enter image description here MOSI and CS lines
Does anyone know what the issue could be? I tried to send in a simple script that would increase and decrease the wiper value to obtain a triangular wave on the PW0 pin but I am not seeing any change in value, it's staying at ground level.
#include <msp430.h>
#include <msp430g2553.h>
// Constants for MCP4131 commands
#define CMD_WRITE_WIPER 0x00
#define CMD_INCREMENT 0x04
#define CMD_DECREMENT 0x08
// Maximum wiper level for the potentiometer
#define MAX_WIPER_LEVEL 127
// Variable to store potentiometer wiper level
unsigned char potLevel;
// Define alternate names for chip select (CS) lines
#define CS_POT1 BIT3 // P1.3 will be used as the chip select line for Potentiometer 1
#define CS_POT2 BIT4 // P1.4 will be used as the chip select line for Potentiometer 2
void clockConfig()
{
// Configure the CPU clock (MCLK) and the Sub-Main Clock (SMCLK)
// Set the DCO (Digitally Controlled Oscillator) to run at 1 MHz
// Using factory-calibrated constants for 1 MHz operation
BCSCTL1 = CALBC1_1MHZ; // Set basic clock system control for 1 MHz --- this is the register that set source basic frequency, set it using a calibration constant
DCOCTL = CALDCO_1MHZ; // Set DCO control register for 1 MHz ---- this is the digital clock register, independent from the the other clocks, set it software
// Set clock dividers for SMCLK and MCLK
// SMCLK = DCO / 2 (500 kHz), MCLK = DCO (1 MHz)
BCSCTL2 = DIVS_3 + DIVM_0; // DIVS_1 sets SMCLK divider to 2, DIVM_0 sets MCLK divider to 1 --- this register sets the dividers for all the clocks, there are different constants in the library for each clock that is how i set dividers for different clocks
}
void pinConfig()
{
// Configure USCI (SPI) pins on Port 1
// Set P1.5, P1.6, and P1.7 for USCI functionality (SPI communication)
P1SEL |= BIT5 + BIT6 + BIT7; // Select USCI functionality for P1.5 (SCLK), P1.6 (MOSI), and P1.7 (MISO) --- these next two registers are the same i think, I just go look at what are each pin functionality and choose them accordingly, here for example i set those three pins to one because they have the sclk, miso and mosi capabilities i don't have to set the dir because as we can see from the datasheet it takes it from the usci which we set later as spi
P1SEL2 |= BIT5 + BIT6 + BIT7; // Set P1.5, P1.6, and P1.7 for USCI (SPI) mode. When P1SEL and P1SEL2 are the same secondary peripheral module function is selected.
// Configure chip select (CS) pins
// Set P1.3 and P1.4 as outputs for chip select lines
P1DIR |= CS_POT1 + CS_POT2; // Set P1.3 and P1.4 as output to control CS lines -- direction registry, I simply set the as outputs, they have many functionalities but since i don't touch p1sel for these bytes they will work as GIOP
// Initialize chip select lines
// Set CS lines high to disable all connected devices
P1OUT |= CS_POT1 + CS_POT2; // Set P1.3 and P1.4 high (inactive state for CS) --- Each bit in each PxOUT register is the value to be output on the corresponding I/O pin when the pin is configured as I/O function, output direction, and the pull-up/down resistor is disabled. Bit = 0: The output is low Bit = 1: The output is high
}
// Configure the USCI module for SPI communication - USCI (universal serial communication interface)
void spiConfig()
{
// Put USCI state machine in reset mode to configure it
UCB0CTL1 = UCSWRST; // Enable software reset to allow configuration -- Enabled. USCI logic held in reset state.
// Configure SPI control register
// UCCKPL = Clock polarity select - high when idle
// UCMSB = MSB first select. Controls the direction of the receive and transmit shift register. Data is transmitted MSB (Most Significant Bit) first
// UCMST = Master mode select -- Set as SPI master
// UCSYNC = Synchronous mode enable. Must be 1 for SPI mode. --- Synchronous mode (SPI)
UCB0CTL0 |= UCCKPL + UCMSB + UCMST + UCSYNC; // Set up 3-wire SPI in master mode with high clock polarity --- each of these are a single bit in the UCB0CTL0 register
// Select clock source for USCI (SCLK), use SMCLK as the clock source
UCB0CTL1 |= UCSSEL_2; // Use SMCLK (500 KHz) --- USCI 0 Clock Source: 2
// Set SPI clock speed (baud rate)
// Baud rate is SMCLK (500 kHz) divided by UCB0BR0 and UCB0BR1
// Setting both UCB0BR0 and UCB0BR1 to 0 gives full SMCLK speed (500 kHz)
UCB0BR0 = 1; // No division, full SMCLK speed ---- The 16-bit value of (UCB0BR0 + UCB0BR1 × 256) forms the pre-scaler value.
UCB0BR1 = 0; // No division, full SMCLK speed ---- I want pre-scaler value to be 1 so UCB0BR0 = 1 and UCB0R1 = 0.
// Release USCI state machine from reset to enable SPI communication
UCB0CTL1 &= ~UCSWRST; // Initialize USCI for SPI communication -- Disabled. USCI reset released for operation.
}
// Drives an MCP4131 digital potentiometer via SPI, arguments:
// csPin: The chip select pin (CS) to enable the desired SPI slave
// dataOut: The wiper level to send to the potentiometer (0-255)
// As of now made for MCP4131, but this chip wont work on my circuit. I will have to place probably an AD5292BRUZ-20-RL7 which doesn't limit as much the input voltage on the potentiometer pin
void setPotValue(unsigned char csPin, unsigned char dataOut)
{
// Enable the selected SPI slave by pulling the corresponding CS pin low
// This selects the device that will communicate over the SPI bus
P1OUT &= ~csPin; // Set the selected CS pin low to enable the slave
// Send the MCP4131 command (0x00 = write wiper command)
UCB0TXBUF = CMD_WRITE_WIPER; // Load the command into the transmit buffer. USCI_Bx Transmit Buffer Register
while (!(IFG2 & UCB0TXIFG)); // Wait for the TX buffer to be ready. IFG2--> SFR Interrupt Flag 2 Register. UCB0TXIFG USCI_B0 transmit interrupt flag. UCB0TXIFG is set when UCB0TXBUF is empty.0b = No interrupt pending, 1b = Interrupt pending
// Send the wiper level (potentiometer value) via SPI
UCB0TXBUF = dataOut; // Load the data (wiper level) into the transmit buffer
while (!(IFG2 & UCB0TXIFG)); // Wait for the TX buffer to be ready. IFG2--> SFR Interrupt Flag 2 Register. UCB0TXIFG USCI_B0 transmit interrupt flag. UCB0TXIFG is set when UCB0TXBUF is empty.0b = No interrupt pending, 1b = Interrupt pending
// Wait for the transmission to complete (ensure all bits are sent)
while (UCB0STAT & UCBUSY); // Wait for SPI bus to become idle. USCI_Bx Status Register. USCI busy. This bit indicates if a transmit or receive operation is in progress. 0b = USCI inactive, 1b = USCI transmitting or receiving
// Disable the SPI slave by pulling the CS pin high
// This deselects the device, ending communication
P1OUT |= csPin; // Set the CS pin high to disable the slave
}
void incrementPotValue(unsigned char csPin)
{
// Enable the selected SPI slave by pulling the corresponding CS pin low
// This selects the device that will communicate over the SPI bus
P1OUT &= ~csPin; // Set the selected CS pin low to enable the slave
// Small delay to allow the device to recognize CS
__delay_cycles(1); // Adjust delay as necessary
// Send the MCP4131 command (0x00 = write wiper command)
UCB0TXBUF = CMD_INCREMENT; // Load the command into the transmit buffer. USCI_Bx Transmit Buffer Register
// Wait for the transmission to complete (ensure all bits are sent)
while (UCB0STAT & UCBUSY); // Wait for SPI bus to become idle. USCI_Bx Status Register. USCI busy. This bit indicates if a transmit or receive operation is in progress. 0b = USCI inactive, 1b = USCI transmitting or receiving
// Disable the SPI slave by pulling the CS pin high
// This deselects the device, ending communication
P1OUT |= csPin; // Set the CS pin high to disable the slave
}
void decrementPotValue(unsigned char csPin)
{
// Enable the selected SPI slave by pulling the corresponding CS pin low
// This selects the device that will communicate over the SPI bus
P1OUT &= ~csPin; // Set the selected CS pin low to enable the slave
// Small delay to allow the device to recognize CS
__delay_cycles(1); // Adjust delay as necessary
// Send the MCP4131 command (0x00 = write wiper command)
UCB0TXBUF = CMD_DECREMENT; // Load the command into the transmit buffer. USCI_Bx Transmit Buffer Register
// Wait for the transmission to complete (ensure all bits are sent)
while (UCB0STAT & UCBUSY); // Wait for SPI bus to become idle. USCI_Bx Status Register. USCI busy. This bit indicates if a transmit or receive operation is in progress. 0b = USCI inactive, 1b = USCI transmitting or receiving
// Disable the SPI slave by pulling the CS pin high
// This deselects the device, ending communication
P1OUT |= csPin; // Set the CS pin high to disable the slave
}
void main(void)
{
// Stop the watchdog timer to prevent the system from resetting
WDTCTL = WDTPW + WDTHOLD;
// Configure the system clock to run at 1 MHz (MCLK) and SMCLK at 500 kHz
clockConfig();
// Configure the necessary pins for SPI and chip select lines
pinConfig();
// Initialize the SPI peripheral (USCI module) for communication
spiConfig();
// Main program loop
while (1)
{
// Gradually increase the wiper value of the first potentiometer (0-126)
for (potLevel = 0; potLevel < MAX_WIPER_LEVEL; potLevel++)
{
incrementPotValue(CS_POT1); // Set potentiometer 1 with increasing values
__delay_cycles(20000); // Introduce a delay to observe the changes
}
// Gradually decrease the wiper value of the first potentiometer (126-0)
for (potLevel = MAX_WIPER_LEVEL; potLevel > 0; potLevel--)
{
decrementPotValue(CS_POT1); // Set potentiometer 1 with decreasing values
__delay_cycles(20000); // Introduce a delay to observe the changes
}
}
}
Upvotes: 0
Views: 39