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.
Hi all,
I'm currently working on a project where I need to set a digital potentiometer. After reading the manual and looking over a few other examples. I've come up with the following code.
//I2C Config
P1SEL |= BIT6 + BIT7; // Assign I2C pins to USCI_B0
P1SEL2|= BIT6 + BIT7; // Assign I2C pins to USCI_B0
P1REN |= BIT6+BIT7; //Enable pull up resistors
//Set Potentiometers
UCB0CTL1 = UCSWRST; //Hold I2C bus during initiation
UCB0CTL0 = UCMODE_3 + UCMST + UCSYNC; //sets I2C mode, master mode, synchronous mode
UCB0CTL1 |= UCSSEL_3; //select SMCLK
UCB0I2CSA = 0x28; //slave address
UCB0CTL1 &= ~UCSWRST; //enable i2c
UCB0CTL1 |= UCTR + UCTXSTT; //set transmit, generate start
while(!(UCB0TXIFG)){;} //wait for transmission to finish
UCB0TXBUF = 0xAF; //send command byte
while(!(UCB0TXIFG)){;} //wait for transmission to finish
UCB0TXBUF = 255; //set pot value
UCB0CTL1 |= UCTXSTP; //generate stop condition
while(!(UCB0TXIFG)){;} //wait for transmission to finish
UCB0CTL1 = UCSWRST; //release I2C bus
Most of what is listed here is from info on the data sheet, found here: http://www.ti.com/lit/ds/symlink/msp430g2553.pdf, and the users guide, found here:http://www.ti.com/lit/ug/slau144i/slau144i.pdf, on pages around 461 and 467.
The data sheet for the digital pot I'm writing to is a DS1803-010: http://datasheets.maxim-ic.com/en/ds/DS1803.pdf
Any help would be greatly appreciated and thank you for your time.
I dont know anything about I2C but I am pretty sure ur program never waited for transmission to finish (logical mistake).
Ryan Wilkerson said:while(!(UCB0TXIFG)){;} //wait for transmission to finish
This is because UCB0TXIFG has a constant value of 0b1000 and !UCB0TXIFG is 0. Thus the contents of while loop never got executed.
UCB0TXIFG is actually a constant while IFG2 is varying. You should actually use this
while (!(IFG2 & UCB0TXIFG)) { ;}
Good luck
UCB0TXIFG is cleared while data in UCB0TXBUF is being pushed to the shift register, it is cleared once the bus is not busy, see pg 471 sec 17.3.4.2.1.
I tried what you suggested, Raju, but it hung up at the first statement. I believe it is because UCB0TXIFG is in the IFG2 register and that operation would always execute as true.
Since the last post, I realized that I forgot to append the R/W bit to the slave address. Since I corrected that I got some reaction out of the UCB0TXIFG bit, although strange, and I changed the while statement to be more explicit. The updated code is as follows:
//I2C Config
P1SEL |= BIT6 + BIT7; // Assign I2C pins to USCI_B0
P1SEL2|= BIT6 + BIT7; // Assign I2C pins to USCI_B0
P1REN |= BIT6+BIT7; //Enable pull up resistors
//Set Potentiometers
UCB0CTL1 = UCSWRST; //Hold I2C bus during initiation
UCB0CTL0 = UCMODE_3 + UCMST + UCSYNC; //sets I2C mode, master mode, synchronous mode
UCB0CTL1 |= UCSSEL_3; //select SMCLK
UCB0I2CSA = 0x50; //slave address(0101000) & write bit(0)
UCB0CTL1 &= ~UCSWRST; //enable i2c
UCB0CTL1 |= UCTR + UCTXSTT; //set transmit, generate start
while(UCB0TXIFG==0){;} //wait for transmission to finish
UCB0TXBUF = 0xAF; //send command byte
while(UCB0TXIFG==0){;} //wait for transmission to finish
UCB0TXBUF = 255; //set pot value
UCB0CTL1 |= UCTXSTP; //generate stop condition
while(UCB0TXIFG==0){;} //wait for transmission to finish
UCB0CTL1 |= UCSWRST; //release I2C bus
According to the manual, I get usual response out of the UCB0TXIFG bit until the second while statement. For some reason as I step through, UCB0TXIFG stays 0 at the line 'UCB0YXBUF = 255;'. Additionally, according to the manual, UCTXSTT should be cleared after the slave address is acknowledged, but it stays set throughout the block. This particular problem persisted with the appended slave address.
Hopefully this provides enough information for a diagnosis.
-Ryan Wilkerson
Hi Ryan,
I don't know much about the I2C stuff yet , I think you should generate a stop condition before second while loop. From the same section of data sheet you mentioned before,,says, If we were transmitting byte by byte you should generate a stop after every byte. Give a try if u find some thing useful.
Regards,
Sri.
For UCTXSTT, this seems to indicate that the start sequence hasn't finished yet. This usually happens if there are no pullups on teh clock and data lines. In this case, the master thinks the slave intentionally holds teh clokc line low before answering, btui in fact, the bus is simply stalled.Ryan Wilkerson said:For some reason as I step through, UCB0TXIFG stays 0 at the line 'UCB0YXBUF = 255;'. Additionally, according to the manual, UCTXSTT should be cleared after the slave address is acknowledged, but it stays set throughout the block.
This also explains why UCTXIFG noever goes high again. It goes high as soon as you set UCTXSTT, as teh TX buffer is double.buffering and you ma yalready fiill it while the slave hasn't been addressed at all. But since the slave addressing doesn't complete, the ocntent of TXBUF isn't moved to the output and TXBUF is still full - and TXIFG won't raise.
Hi all,
i'm doing i2c interface between msp430g2553 and my accelerometer (ADXL345).
Currently i'm trying out the multiple read.
Pin SDO of ADXL345 been tied to logic 1. Therefore the device address is 0x1D. Reset default state is 0xE5 and it should get it back. And i got it right for single-byte read.
Below is my waveform pic and my main program.
Please help. many many thanks. :)
waveform for multiple read but wrong. :(
Main program for single read.
#include <stdio.h>
#include <msp430g2553.h>
#include "MSP430G2553(AddOn).h"
#include "GPIO.h"
#include "UART.h"
#include "i2c.h"
#include "ADXL345.h"
#include "ADXL345(RegMap).h"
#include "L3G4200D.h"
#include "L3G4200D(RegMap).h"
unsigned char readValue;
void main(void) {
StopWatchDog();
CalDCO16MHz();
UARTInit(); //For serial Communication
// i2cFastModeInit(); //I2C - 400kHz
i2cInit(); //I2C - 100kHz
while(1)
{
i2c_start(0x1D); //Perform a I2C Start with the Device Address of ADXL345
i2c_write(0x00); //0x00 register for DEVICE ID (ADXL345 datasheet pg 23)
delay_us(100);
i2c_restart(); //Perform a restart; this can also be a stop and follow by a start
// delay_us(100);
readValue = i2c_read(); //Perform a read. (Expected value is 0xE5)
i2c_stop(); //Stop the I2C
delay_us(300);
// while(1); /*** SET BREAKPOINT HERE***/
}
}
Sorry its been a while since I last looked at I2C so this might not be too helpful. But I notice you didn't quote the following resource which I found invaluable when getting I2C up and running. I see you realised you had to fix the R/W byte at the end of the address. Depending on the data sheet you might have to shift the slave address by 1 bit left before setting the R/W bit.
EDIT: Also you may find that you need external pull up resistors if you are currently relying solely on the internal resistors.
Code Examples:
**Attention** This is a public forum