That will hold the LCD in reset. You have to pulse Reset low before beginning communication with the LCD. This can be done with GPIO (best) or a R/C reset circuit.
I got the DHT11 sensors from SunTek today and wrote some C code to read it. This uses TimerA for accurate time measurement, and polling to allow use on any pin. The internal pullup resistor is used, so an external one is not needed.
A six byte array passed to read_dht() will be filled with the start bit, 4 data bytes, and the checksum. Return is 0 for success, or a negative value for failure. This code can run at 1 MHz or higher.
The DHT11 seems to need about 300 ms between readings, less time will result in the sensor sometimes being non-responsive. The fractional bytes are always 0 for the DHT11.
int read_dht(unsigned char *p)
{
// Note: TimerA must be continuous mode (MC_2) at 1 MHz
const unsigned b = BIT4; // I/O bit
const unsigned char *end = p + 6; // End of data buffer
register unsigned char m = 1; // First byte will have only start bit
register unsigned st, et; // Start and end times
//
p[0] = p[1] = p[2] = p[3] = p[4] = p[5] = 0; // Clear data buffer
//
P1OUT &= ~b; // Pull low
P1DIR |= b; // Output
P1REN &= ~b; // Drive low
st = TAR; while((TAR - st) < 18000); // Wait 18 ms
P1REN |= b; // Pull low
P1OUT |= b; // Pull high
P1DIR &= ~b; // Input
//
st = TAR; // Get start time for timeout
while(P1IN & if((TAR - st) > 100) return -1; // Wait while high, return if no response
et = TAR; // Get start time for timeout
do { //
st = et; // Start time of this bit is end time of previous bit
while(!(P1IN & ) if((TAR - st) > 100) return -2; // Wait while low, return if stuck low
while(P1IN & if((TAR - st) > 200) return -3; // Wait while high, return if stuck high
et = TAR; // Get end time
if((et - st) > 110) *p |= m; // If time > 110 us, then it is a one bit
if(!(m >>= 1)) m = 0x80, ++p; // Shift mask, move to next byte when mask is zero
} while(p < end); // Do until array is full
//
p -= 6; // Point to start of buffer
if(p[0] != 1) return -4; // No start bit
if(((p[1] + p[2] + p[3] + p[4]) & 0xFF) != p[5]) return -5; // Bad checksum
//
return 0; // Good read
}
I am a noob and tried to do something similar with the BMP085 and MSP430G2231 when the launchpad was released and never could get I2C to work correctly. Given the flash limitations of that chip, not sure it would have been possible...
Your work inspired me to update ccs, install grace, and get it working! BTW, for any other noobs reading this, you will need to attach pullup resistors to SCL & SDA, jumper the TXD and RXD pins since they seem reversed on the 2553, and remove the jumper for pin 1.6 that connects it to the Launchpads LED2.
Grace seems nice. It is very easy for a noob to get stuck configuring pins, clocks, etc. It was nice to refer back to see what speed you had the UART running at, the pinout for SCL/SDA, etc.
Ok, so the MSP-EXP430F5529 dev board may not provide me with optimal hardware I/O for my greenhouse controller. Basically, I'd want the power/speed of the F5529 without the accelerometer. If I were rebuilding this board, I'd move the LCD SPI over to UCA1 and free up UCB1 for an I2C channel. UCB0 is being used for the RF2500t interface. So...
My solution (for now) is to use a standalone G2553 as an I2C to UART translator. It actually works out well but not my optimal hardware configuration. This project may not be useful for many but some might find bits of the code helpful. The kicker, though, is I configured all of the hardware using Grace. :crazy:
If you have a BMP085, you can open a terminal on your launchpad port and receive temperature and barometric pressure.
/****************************************************************/
/* Greg Whitmore */
/* greg@gwdeveloper.net */
/* www.gwdeveloper.net */
/****************************************************************/
/* released under the "Use at your own risk" license */
/* use it how you want, where you want and have fun */
/* debugging the code. */
/* MSP-EXP430G2553 */
/****************************************************************/
/* includes */
#include
#include
#include
#include "itoa.h"
/* bmp085 defines */
#define BMP085_ADDR 0x77
#define BMP085_CTRL_REG 0xF4
#define BMP085_TEMP_REG 0x2E
#define BMP085_PRESSURE_REG 0x34 // oss =0
//#define BMP085_PRESSURE_REG_OSS1 0x74 // oss =1, longer delays needed 7.5ms
//#define BMP085_PRESSURE_REG_OSS2 0xB4 // oss =2, 13.5ms
//#define BMP085_PRESSURE_REG_OSS3 0xF4 // oss =3, 25.5ms
#define BMP085_MSB_REG 0xF6
#define BMP085_LSB_REG 0xF7
#define BMP085_CONV_REG_XLSB 0xF8
/* prototypes */
// bmp085
void bmp085_cal(void);
unsigned int bmp085_ut(void);
unsigned long bmp085_up(void);
void get_bmp085(void);
// iic
void iic_init(void);
void iic_tx_init(void);
void iic_rx_init(void);
void start_TX(void);
void start_RX(void);
int sendByte_getBytes(unsigned char reg_2_read, int bytes_to_rx);
//uart
void TXString( char* string, int length );
/* variables */
// bmp085
// cal data
int ac1;
int ac2;
int ac3;
unsigned int ac4;
unsigned int ac5;
unsigned int ac6;
int b1;
int b2;
int mb;
int mc;
int md;
// true temp
long ut;
long x1;
long x2;
long b5;
int bmp_temp = 0;
//true pressure
long up;
long x3;
long b3;
unsigned long b4;
long b6;
unsigned long b7;
long p;
long bmp_pres = 0;
// adjusters
long b6Temp;
long x1Temp;
//unsigned int i;
unsigned char temp_buffer[8];
unsigned char pres_buffer[8];
// tx constants
const unsigned char utTxData[] = { BMP085_CTRL_REG, BMP085_TEMP_REG }; // uncomp temp reg
const unsigned char upTxData[] = { BMP085_CTRL_REG, BMP085_PRESSURE_REG }; // oss =0 see bmp085.h
const unsigned char msbData[] = { BMP085_MSB_REG };
// iic
unsigned char *PTxData; // Pointer to TX data
unsigned char TXByteCtr;
unsigned char *PRxData; // Pointer to RX data
unsigned char RXByteCtr;
volatile unsigned char RxBuffer[3]; // Allocate 3 byte of RAM
void main(void)
{
CSL_init(); // Activate Grace-generated configuration
__enable_interrupt(); // Set global interrupt enable
bmp085_cal(); // load calibration data
get_bmp085(); // loop to collect temp & pressure
// and TX via UART
}
// store PROM data into usable variables
void bmp085_cal(void)
{
ac1 = sendByte_getBytes(0xAA, 2);
__delay_cycles(1000);
ac2 = sendByte_getBytes(0xAC, 2);
__delay_cycles(1000);
ac3 = sendByte_getBytes(0xAE, 2);
__delay_cycles(1000);
ac4 = sendByte_getBytes(0xB0, 2);
__delay_cycles(1000);
ac5 = sendByte_getBytes(0xB2, 2);
__delay_cycles(1000);
ac6 = sendByte_getBytes(0xB4, 2);
__delay_cycles(1000);
b1 = sendByte_getBytes(0xB6, 2);
__delay_cycles(1000);
b2 = sendByte_getBytes(0xB8, 2);
__delay_cycles(1000);
mb = sendByte_getBytes(0xBA, 2);
__delay_cycles(1000);
mc = sendByte_getBytes(0xBC, 2);
__delay_cycles(1000);
md = sendByte_getBytes(0xBE, 2);
__delay_cycles(1000);
}
// read uncompensated temperature and return msb & lsb
unsigned int bmp085_ut(void)
{
iic_tx_init();
__delay_cycles(1000);
PTxData = (unsigned char *)utTxData; // send control reg and temp reg
TXByteCtr = 2; // Load TX byte counter
start_TX();
__delay_cycles(200000); // long delay here or it hangs on the valueline mcus
return (sendByte_getBytes(BMP085_MSB_REG, 2));
}
// read uncompensated pressure and return msb, lsb & xlsb
unsigned long bmp085_up(void)
{
iic_tx_init();
__delay_cycles(1000);
PTxData = (unsigned char *)upTxData; // send control reg and temp reg
TXByteCtr = 2; // Load TX byte counter
start_TX();
__delay_cycles(200000); // long delay here or it hangs on the valueline mcus
PTxData = (unsigned char *)msbData; // send msb read register
TXByteCtr = 1;
start_TX();
iic_rx_init(); // set RX interrupt
__delay_cycles(200000); // long delay here or it hangs on the valueline mcus
PRxData = (unsigned char *)RxBuffer; // rx buffer
RXByteCtr = 3; // number of bytes to receive
start_RX();
// returning longs instead of ints to allow 2^16 shifts
// sendByte_getBytes not used here due to long shifts
return ( (( (long)RxBuffer[0] << 16) | ( (long)RxBuffer[1] << 8) | (long)RxBuffer[2]) >> 8);
}
// collect uncompensated temp and pressure
// calculate compensated temp and pressure then transmit via UART
void get_bmp085()
{
while (1){
ut = bmp085_ut();
up = bmp085_up();
// calc true temp
x1 = ((long)ut - ac6) * ac5 >> 15;
x2 = ((long)mc << 11) / (x1 + md);
b5 = x1 + x2;
bmp_temp = (b5 + 8) >> 4;
// itoa function added
itoa(bmp_temp, (char*)temp_buffer); // move integer into char buffer
// calc true pressure
b6 = b5 - 4000;
//x1 = (b2 * (b6 * b6) >> 12) >> 11; // won't work this way on the value line LSR_23 error
b6Temp = b6 * b6;
x1Temp = b2 * b6Temp;
x1Temp = x1Temp >> 12;
x1 = x1Temp >> 11;
x2 = (ac2 * b6) >> 11;
x3 = x1 + x2;
b3 = ((long)ac1 * 4 + x3 + 2) >> 2; // ???? so many 'corrections' on the web this one works though
x1 = ac3 * b6 >> 13;
x2 = (b1 * ((b6 * b6) >> 12)) >> 16;
x3 = ((x1 + x2) + 2) >> 2;
b4 = (ac4 * (unsigned long)(x3 + 32768)) >> 15;
b7 = ((unsigned long)up - b3) * 50000;
if (b7 < 0x80000000)
{ p = (b7 * 2) / b4;}
else {p = (b7 / b4) *2;}
x1 = (p >> 8) * (p >> 8);
x1 = (x1 * 3038) >> 16;
x2 = (-7357 * p) >> 16;
bmp_pres = p + ((x1 + x2 + 3791) >> 4);
// ltoa part of stdlib.h
ltoa(bmp_pres, (char*)pres_buffer);
TXString((char*)temp_buffer, sizeof temp_buffer);
TXString("\r\n", 2);
TXString((char*)pres_buffer, sizeof pres_buffer);
TXString("\r\n", 2);
__delay_cycles(500000);
}
}
void iic_tx_init()
{
UCB0I2CSA = BMP085_ADDR;
UCB0I2CIE |= UCB0TXIE; // Enable TX interrupt
}
void iic_rx_init(void)
{
UCB0I2CIE |= UCB0RXIE; // enable RX interrupt
}
// send 1 byte, return 2 bytes - needs the return expanded for X bytes
int sendByte_getBytes(unsigned char reg_2_read, int bytes_to_rx)
{
// transmit slave address and register to read
iic_tx_init();
__delay_cycles(1000);
PTxData = (unsigned char *)®_2_read; // TX array start address
TXByteCtr = sizeof reg_2_read; // Load TX byte counter
start_TX();
//
// receive requested bytes
iic_rx_init(); // set RX interrupt
__delay_cycles(1000);
PRxData = (unsigned char *)RxBuffer; // rx buffer
RXByteCtr = bytes_to_rx; // number of bytes to receive
start_RX();
//
return ((int)RxBuffer[0] << 8) | (int)RxBuffer[1]; // currently only returning 2 bytes
}
// iic start transmitting
void start_TX(void)
{
UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition
__bis_SR_register(LPM0_bits + GIE); // Enter LPM0, enable interrupts
__no_operation(); // Remain in LPM0 until all data
// is TX'd
while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
}
// iic restart and receive
void start_RX(void)
{
while (UCB0CTL1 & UCTXSTP); // wait for stop
UCB0CTL1 &= ~UCTR; // restart, set as receiver
UCB0CTL1 |= UCTXSTT; // start condition
__bis_SR_register(LPM0_bits + GIE);
while (UCB0CTL1 & UCTXSTP);
}
// interrupt pragma is defined in grace
void iic_TX_isr(void)
{
if (TXByteCtr) // Check TX byte counter
{
UCB0TXBUF = *PTxData++; // Load TX buffer
TXByteCtr--; // Decrement TX byte counter
}
else
{
UCB0CTL1 |= UCTXSTP; // I2C stop condition
IFG2 &= ~UCB0TXIFG; // Clear USCI_B0 TX int flag
}
}
// interrupt pragma is defined in grace
void iic_RX_isr(void)
{
RXByteCtr--; // Decrement RX byte counter
if (RXByteCtr)
{
P1OUT ^= 0x10;
*PRxData++ = UCB0RXBUF; // Move RX data to address PRxData
if (RXByteCtr == 1) // Only one byte left?
UCB0CTL1 |= UCTXSTP; // Generate I2C stop condition
}
else
{
*PRxData = UCB0RXBUF; // Move final RX data to PRxData
}
}
// tx function borrowed from TI's virtual_com_cmds.c
void TXString( char* string, int length )
{
int pointer;
for( pointer = 0; pointer < length; pointer++)
{
volatile int i;
UCA0TXBUF = string[pointer];
while (!(IFG2&UCA0TXIFG)); // USCI_A0 TX buffer ready?
}
}
// timer A isr is simply toggling activity light for now.
// future pwm functions to go here
void timer_A_ISR(void)
{
P1OUT ^= BIT0;
}
Did you grab my i2c code from the i2c-lcd project? If so, look at the i2c explorer I made. Has working i2c write and reads with ability for ack or nack reads.
Additionally, USISRL is never cleared between sending the data, and receiving the ACK/NACK. Accordingly, the function returns the value you had, shifted right once, with the LSB set as the ack or nack.
Try adding
USISRL = 0x00;
Between the tx and rx sections of the i2c_write8 function.
This will empty the USI data holder, so it should return just a 0x01 or 0x00.
As for the 7 bits vs 8 bits, from what I've read of the Arduino i2c library, it simply handles the last bit for you. My i2c and coding is no where as advanced, so you have to choose the full 8bit address.
Oh, and just to make sure, the launchpad and the sensor share a common ground, right?