-
Content Count
1,782 -
Joined
-
Last visited
-
Days Won
102
Reputation Activity
-
zeke got a reaction from GeekDoc in Reading the ds18b20 temperature sensor
If you find realterm less than adequate then give this program a try.
It looks a little more refined.
-
zeke got a reaction from Dimiric in Best information for those new to the MSP430?
As you progress in your development of an embedded system based upon the MSP430, you will eventually have to cut your dependency on your dev board. When you do this, you will have to give your system the ability to be programmed.
Whether by JTAG or by Spy-Bi-Wire, you will have to assimilate and understand the information inside this document. Otherwise, you will have a brick coming off the assembly line.
Do want to make a million bricks or a million dollars?
Knowing this information will save you time, money and prevent ulcers!
4. slau320: Programming via the JTAG Interface
This document describes the functions that are required to erase, program, and verify the memory module
of the MSP430
-
zeke got a reaction from lvagasi in Reading the ds18b20 temperature sensor
Okay, I have my code running.
Here's main.c
#include #include "ds18b20.h" #define UART_TXD 0x02 // TXD on P1.1 (Timer0_A.OUT0) #define UART_RXD 0x04 // RXD on P1.2 (Timer0_A.CCI1A) #define UART_TBIT_DIV_2 (16000000 / (9600 * 2)) #define UART_TBIT (16000000 / 9600) #define delayMicroseconds(n) __delay_cycles(n<<4) // The One Wire bus is connected to this pin #define WIRE_PORT 7 //Remember you need a 4.7k pullup resistor here. #define LOW 0 #define HIGH 1 #define INPUT 0 #define OUTPUT 1 #define FALSE 0 #define TRUE 1 //Zeke's mod's int OW_Reset( int Pin ); void OW_WriteByte(int Pin, char d); char OW_ReadByte(int Pin); // Routines written by Peter H Anderson // http://www.phanderson.com/arduino/ds18b20_1.html char digitalRead( char Pin ); void pinMode( int Pin, int Out ); void digitalWrite( int Pin, int Bit ); // Software UART routines void TimerA_UART_init( void ); void TimerA_UART_tx( unsigned char byte ); unsigned int txData; // UART internal variable for TX unsigned char rxBuffer; // Received UART character void main(void) { // int temp = 0; int i; int ROMCode[8]; int ScratchPad[9]; int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract; WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer BCSCTL1 = CALBC1_16MHZ; DCOCTL = CALDCO_16MHZ; P1OUT = UART_RXD; // RXD as IN P1SEL = UART_TXD + UART_RXD; // Timer function for TXD/RXD pins P1DIR = UART_TXD; TimerA_UART_init(); __enable_interrupt(); while ( 1 ) { if ( 1 == OW_Reset( WIRE_PORT ) ) { OW_WriteByte( WIRE_PORT, 0x33 ); // Read ROM Code from DS18B20 for( i=0; i<8; i++ ) { // Read the values inside of the ROMCode array in the debugger window ROMCode[i] = OW_ReadByte( WIRE_PORT ); } } if ( 1 == OW_Reset( WIRE_PORT ) ) { OW_WriteByte( WIRE_PORT, SKIPROM ); // Skip ROM Code matching OW_WriteByte( WIRE_PORT, CONVERTTEMP ); // Read ROM Code from DS18B20 OW_Reset( WIRE_PORT ); OW_WriteByte( WIRE_PORT, SKIPROM ); // Skip ROM Code matching OW_WriteByte( WIRE_PORT, READSCRATCHPAD ); // Read ScratchPad from DS18B20 for( i=0; i<9; i++ ) { // Read the values inside of the ScratchPad array in the debugger window ScratchPad[i] = OW_ReadByte( WIRE_PORT ); } } OW_Reset( WIRE_PORT ); OW_WriteByte( WIRE_PORT, SKIPROM ); // Skip ROM Code matching OW_WriteByte( WIRE_PORT, CONVERTTEMP ); // Read ROM Code from DS18B20 OW_Reset( WIRE_PORT ); OW_WriteByte( WIRE_PORT, SKIPROM ); // Skip ROM Code matching OW_WriteByte( WIRE_PORT, READSCRATCHPAD ); // Read ScratchPad from DS18B20 LowByte = OW_ReadByte( WIRE_PORT ); HighByte = OW_ReadByte( WIRE_PORT ); // Thanks again "Mr. Anderson" for this code TReading = ( HighByte << 8 ) + LowByte; SignBit = TReading & 0x8000; // test most sig bit if ( 1 == SignBit ) // negative { TReading = (TReading ^ 0xffff) + 1; // 2's comp } Tc_100 = ( 6 * TReading ) + TReading / 4; // multiply by (100 * 0.0625) or 6.25 Whole = Tc_100 / 100; // separate off the whole and fractional portions Fract = Tc_100 % 100; // ********************************************************************************************************** // ***** This won't work so I am commenting it out (zeke) ***** // ***** A serial ring buffer and interrupt servicing routines is needed to make this work ***** // ***** // ***** Read the "Whole" and "Fract" values with your debugger ***** // ********************************************************************************************************** // this will print the tempature in an int8 over serial every 1 second. // TimerA_UART_tx( Whole ); // TimerA_UART_tx( Fract ); // ********************************************************************************************************** // insert a breakpoint here and observe the variables in the debugger watch window // ********************************************************************************************************** delayMicroseconds( 1000000 ); } } int OW_Reset( int Pin ) { int presence; delayMicroseconds( 0 ); // delay for 0us digitalWrite( Pin, LOW ); pinMode( Pin, OUTPUT ); delayMicroseconds( 480 ); // delay for 480us pinMode( Pin, INPUT ); delayMicroseconds( 70 ); // delay for 70us if( 0 == digitalRead( WIRE_PORT ) ) { presence = TRUE; // Presense pulse detected } else { presence = FALSE; // ds18b20 is not there } delayMicroseconds( 410 ); // delay for 410us return ( presence ); // return the sampled presence pulse result } // Peter Anderson wrote this void OW_WriteByte( int Pin, char d ) { char n; for(n=8; n!=0; n--) { if ( (d & 0x01) == 1 ) { digitalWrite( Pin, LOW ); pinMode( Pin, OUTPUT ); delayMicroseconds( 5 ); pinMode( Pin, INPUT ); delayMicroseconds( 60 ); } else { digitalWrite( Pin, LOW ); pinMode( Pin, OUTPUT ); delayMicroseconds( 60 ); pinMode( Pin, INPUT ); } d = d >> 1; } } // Peter Anderson wrote this char OW_ReadByte( int pin ) { char d, n, b; for ( n=0; n<8; n++ ) { digitalWrite( pin, LOW ); pinMode( pin, OUTPUT); delayMicroseconds( 5 ); pinMode( pin, INPUT ); delayMicroseconds( 5 ); b = digitalRead( pin ); delayMicroseconds( 50 ); d = (d >> 1) | (b << 7); // shift d to right and insert b in most sig bit position } return(d); } //------------------------------------------------------------------------------ // Arduino like digitalRead, pinMode, and digitalWrite helper functions. //------------------------------------------------------------------------------ char digitalRead( char Pin ) { // Read P1IN and mask it with the 1wPin then shift it to the LSB position return ( (P1IN & (1 << Pin) ) >> Pin ); } void pinMode( int pin, int out ) { if( 1 == out ) { P1DIR |= (1 << pin); } else { P1DIR &= (~(1 << pin)); } } void digitalWrite(int Pin, int Bit) { if ( 1 == ( Bit ) ) { P1OUT |= ( 1 << Pin ); // if the Bit is HIGH then drive the 1wBus HIGH } else { P1OUT &= ( ~(1 << Pin) ); // if the Bit is LOW then drive the 1wBus LOW } } //------------------------------------------------------------------------------ // Function configures Timer_A for full-duplex UART operation //------------------------------------------------------------------------------ void TimerA_UART_init(void) { TACCTL0 = OUT; // Set TXD Idle as Mark = '1' TACCTL1 = SCS + CM1 + CAP + CCIE; // Sync, Neg Edge, Capture, Int TACTL = TASSEL_2 + MC_2; // SMCLK, start in continuous mode } //------------------------------------------------------------------------------ // Outputs one byte using the Timer_A UART //------------------------------------------------------------------------------ void TimerA_UART_tx(unsigned char byte) { while (TACCTL0 & CCIE); // Ensure last char got TX'd TACCR0 = TAR; // Current state of TA counter TACCR0 += UART_TBIT; // One bit time till first bit TACCTL0 = OUTMOD0 + CCIE; // Set TXD on EQU0, Int txData = byte; // Load global variable txData |= 0x100; // Add mark stop bit to TXData txData <<= 1; // Add space start bit } //------------------------------------------------------------------------------ // Timer_A UART - Transmit Interrupt Handler //------------------------------------------------------------------------------ #pragma vector = TIMERA0_VECTOR __interrupt void Timer_A0_ISR(void) { static unsigned char txBitCnt = 10; TACCR0 += UART_TBIT; // Add Offset to CCRx if (txBitCnt == 0) // All bits TXed? { TACCTL0 &= ~CCIE; // All bits TXed, disable interrupt txBitCnt = 10; // Re-load bit counter } else { if (txData & 0x01) { TACCTL0 &= ~OUTMOD2; // TX Mark '1' } else { TACCTL0 |= OUTMOD2; // TX Space '0' } txData >>= 1; txBitCnt--; } } //------------------------------------------------------------------------------ // Timer_A UART - Receive Interrupt Handler //------------------------------------------------------------------------------ #pragma vector = TIMERA1_VECTOR __interrupt void Timer_A1_ISR(void) { static unsigned char rxBitCnt = 8; static unsigned char rxData = 0; switch ( __even_in_range(TAIV, TAIV_TAIFG) ) // Use calculated branching { case TAIV_TACCR1: // TACCR1 CCIFG - UART RX TACCR1 += UART_TBIT; // Add Offset to CCRx if (TACCTL1 & CAP) // Capture mode = start bit edge { TACCTL1 &= ~CAP; // Switch capture to compare mode TACCR1 += UART_TBIT_DIV_2; // Point CCRx to middle of D0 } else { rxData >>= 1; if (TACCTL1 & SCCI) // Get bit waiting in receive latch { rxData |= 0x80; } rxBitCnt--; if (rxBitCnt == 0) // All bits RXed? { rxBuffer = rxData; // Store in global variable rxBitCnt = 8; // Re-load bit counter TACCTL1 |= CAP; // Switch compare to capture mode __bic_SR_register_on_exit(LPM0_bits); // Clear LPM0 bits from 0(SR) } } break; } }
And here's ds18b20.h
#ifndef DS18B20_H_ #define DS18B20_H_ // 'tick' values // Compute these from DalSemi AN126 xls worksheet //int A,B,C,D,E,F,G,H,I,J; #define tA 6 #define tB 64 #define tC 60 #define tD 10 #define tE 9 #define tF 55 #define tG 0 #define tH 480 #define tI 70 #define tJ 410 // 1-Wire ROM Command Codes #define SEARCHROM 0xF0 #define READROM 0x33 #define MATCHROM 0x55 #define SKIPROM 0xCC #define ALARMSEARCH 0xEC // DS18B20 Function Commands #define CONVERTTEMP 0x44 #define WRITESCRATCHPAD 0x4E #define READSCRATCHPAD 0xBE #define COPYSCRATCHPAD 0x48 #define RECALLEE 0xB8 #define READPOWERSUPPLY 0xB4 #endif /*DS18B20_H_*/
Again, make sure you calibrate the DCO for 16MHz if you're using a value line device.
Enjoy!
-
zeke got a reaction from touch in Reading the ds18b20 temperature sensor
Okay, I have my code running.
Here's main.c
#include #include "ds18b20.h" #define UART_TXD 0x02 // TXD on P1.1 (Timer0_A.OUT0) #define UART_RXD 0x04 // RXD on P1.2 (Timer0_A.CCI1A) #define UART_TBIT_DIV_2 (16000000 / (9600 * 2)) #define UART_TBIT (16000000 / 9600) #define delayMicroseconds(n) __delay_cycles(n<<4) // The One Wire bus is connected to this pin #define WIRE_PORT 7 //Remember you need a 4.7k pullup resistor here. #define LOW 0 #define HIGH 1 #define INPUT 0 #define OUTPUT 1 #define FALSE 0 #define TRUE 1 //Zeke's mod's int OW_Reset( int Pin ); void OW_WriteByte(int Pin, char d); char OW_ReadByte(int Pin); // Routines written by Peter H Anderson // http://www.phanderson.com/arduino/ds18b20_1.html char digitalRead( char Pin ); void pinMode( int Pin, int Out ); void digitalWrite( int Pin, int Bit ); // Software UART routines void TimerA_UART_init( void ); void TimerA_UART_tx( unsigned char byte ); unsigned int txData; // UART internal variable for TX unsigned char rxBuffer; // Received UART character void main(void) { // int temp = 0; int i; int ROMCode[8]; int ScratchPad[9]; int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract; WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer BCSCTL1 = CALBC1_16MHZ; DCOCTL = CALDCO_16MHZ; P1OUT = UART_RXD; // RXD as IN P1SEL = UART_TXD + UART_RXD; // Timer function for TXD/RXD pins P1DIR = UART_TXD; TimerA_UART_init(); __enable_interrupt(); while ( 1 ) { if ( 1 == OW_Reset( WIRE_PORT ) ) { OW_WriteByte( WIRE_PORT, 0x33 ); // Read ROM Code from DS18B20 for( i=0; i<8; i++ ) { // Read the values inside of the ROMCode array in the debugger window ROMCode[i] = OW_ReadByte( WIRE_PORT ); } } if ( 1 == OW_Reset( WIRE_PORT ) ) { OW_WriteByte( WIRE_PORT, SKIPROM ); // Skip ROM Code matching OW_WriteByte( WIRE_PORT, CONVERTTEMP ); // Read ROM Code from DS18B20 OW_Reset( WIRE_PORT ); OW_WriteByte( WIRE_PORT, SKIPROM ); // Skip ROM Code matching OW_WriteByte( WIRE_PORT, READSCRATCHPAD ); // Read ScratchPad from DS18B20 for( i=0; i<9; i++ ) { // Read the values inside of the ScratchPad array in the debugger window ScratchPad[i] = OW_ReadByte( WIRE_PORT ); } } OW_Reset( WIRE_PORT ); OW_WriteByte( WIRE_PORT, SKIPROM ); // Skip ROM Code matching OW_WriteByte( WIRE_PORT, CONVERTTEMP ); // Read ROM Code from DS18B20 OW_Reset( WIRE_PORT ); OW_WriteByte( WIRE_PORT, SKIPROM ); // Skip ROM Code matching OW_WriteByte( WIRE_PORT, READSCRATCHPAD ); // Read ScratchPad from DS18B20 LowByte = OW_ReadByte( WIRE_PORT ); HighByte = OW_ReadByte( WIRE_PORT ); // Thanks again "Mr. Anderson" for this code TReading = ( HighByte << 8 ) + LowByte; SignBit = TReading & 0x8000; // test most sig bit if ( 1 == SignBit ) // negative { TReading = (TReading ^ 0xffff) + 1; // 2's comp } Tc_100 = ( 6 * TReading ) + TReading / 4; // multiply by (100 * 0.0625) or 6.25 Whole = Tc_100 / 100; // separate off the whole and fractional portions Fract = Tc_100 % 100; // ********************************************************************************************************** // ***** This won't work so I am commenting it out (zeke) ***** // ***** A serial ring buffer and interrupt servicing routines is needed to make this work ***** // ***** // ***** Read the "Whole" and "Fract" values with your debugger ***** // ********************************************************************************************************** // this will print the tempature in an int8 over serial every 1 second. // TimerA_UART_tx( Whole ); // TimerA_UART_tx( Fract ); // ********************************************************************************************************** // insert a breakpoint here and observe the variables in the debugger watch window // ********************************************************************************************************** delayMicroseconds( 1000000 ); } } int OW_Reset( int Pin ) { int presence; delayMicroseconds( 0 ); // delay for 0us digitalWrite( Pin, LOW ); pinMode( Pin, OUTPUT ); delayMicroseconds( 480 ); // delay for 480us pinMode( Pin, INPUT ); delayMicroseconds( 70 ); // delay for 70us if( 0 == digitalRead( WIRE_PORT ) ) { presence = TRUE; // Presense pulse detected } else { presence = FALSE; // ds18b20 is not there } delayMicroseconds( 410 ); // delay for 410us return ( presence ); // return the sampled presence pulse result } // Peter Anderson wrote this void OW_WriteByte( int Pin, char d ) { char n; for(n=8; n!=0; n--) { if ( (d & 0x01) == 1 ) { digitalWrite( Pin, LOW ); pinMode( Pin, OUTPUT ); delayMicroseconds( 5 ); pinMode( Pin, INPUT ); delayMicroseconds( 60 ); } else { digitalWrite( Pin, LOW ); pinMode( Pin, OUTPUT ); delayMicroseconds( 60 ); pinMode( Pin, INPUT ); } d = d >> 1; } } // Peter Anderson wrote this char OW_ReadByte( int pin ) { char d, n, b; for ( n=0; n<8; n++ ) { digitalWrite( pin, LOW ); pinMode( pin, OUTPUT); delayMicroseconds( 5 ); pinMode( pin, INPUT ); delayMicroseconds( 5 ); b = digitalRead( pin ); delayMicroseconds( 50 ); d = (d >> 1) | (b << 7); // shift d to right and insert b in most sig bit position } return(d); } //------------------------------------------------------------------------------ // Arduino like digitalRead, pinMode, and digitalWrite helper functions. //------------------------------------------------------------------------------ char digitalRead( char Pin ) { // Read P1IN and mask it with the 1wPin then shift it to the LSB position return ( (P1IN & (1 << Pin) ) >> Pin ); } void pinMode( int pin, int out ) { if( 1 == out ) { P1DIR |= (1 << pin); } else { P1DIR &= (~(1 << pin)); } } void digitalWrite(int Pin, int Bit) { if ( 1 == ( Bit ) ) { P1OUT |= ( 1 << Pin ); // if the Bit is HIGH then drive the 1wBus HIGH } else { P1OUT &= ( ~(1 << Pin) ); // if the Bit is LOW then drive the 1wBus LOW } } //------------------------------------------------------------------------------ // Function configures Timer_A for full-duplex UART operation //------------------------------------------------------------------------------ void TimerA_UART_init(void) { TACCTL0 = OUT; // Set TXD Idle as Mark = '1' TACCTL1 = SCS + CM1 + CAP + CCIE; // Sync, Neg Edge, Capture, Int TACTL = TASSEL_2 + MC_2; // SMCLK, start in continuous mode } //------------------------------------------------------------------------------ // Outputs one byte using the Timer_A UART //------------------------------------------------------------------------------ void TimerA_UART_tx(unsigned char byte) { while (TACCTL0 & CCIE); // Ensure last char got TX'd TACCR0 = TAR; // Current state of TA counter TACCR0 += UART_TBIT; // One bit time till first bit TACCTL0 = OUTMOD0 + CCIE; // Set TXD on EQU0, Int txData = byte; // Load global variable txData |= 0x100; // Add mark stop bit to TXData txData <<= 1; // Add space start bit } //------------------------------------------------------------------------------ // Timer_A UART - Transmit Interrupt Handler //------------------------------------------------------------------------------ #pragma vector = TIMERA0_VECTOR __interrupt void Timer_A0_ISR(void) { static unsigned char txBitCnt = 10; TACCR0 += UART_TBIT; // Add Offset to CCRx if (txBitCnt == 0) // All bits TXed? { TACCTL0 &= ~CCIE; // All bits TXed, disable interrupt txBitCnt = 10; // Re-load bit counter } else { if (txData & 0x01) { TACCTL0 &= ~OUTMOD2; // TX Mark '1' } else { TACCTL0 |= OUTMOD2; // TX Space '0' } txData >>= 1; txBitCnt--; } } //------------------------------------------------------------------------------ // Timer_A UART - Receive Interrupt Handler //------------------------------------------------------------------------------ #pragma vector = TIMERA1_VECTOR __interrupt void Timer_A1_ISR(void) { static unsigned char rxBitCnt = 8; static unsigned char rxData = 0; switch ( __even_in_range(TAIV, TAIV_TAIFG) ) // Use calculated branching { case TAIV_TACCR1: // TACCR1 CCIFG - UART RX TACCR1 += UART_TBIT; // Add Offset to CCRx if (TACCTL1 & CAP) // Capture mode = start bit edge { TACCTL1 &= ~CAP; // Switch capture to compare mode TACCR1 += UART_TBIT_DIV_2; // Point CCRx to middle of D0 } else { rxData >>= 1; if (TACCTL1 & SCCI) // Get bit waiting in receive latch { rxData |= 0x80; } rxBitCnt--; if (rxBitCnt == 0) // All bits RXed? { rxBuffer = rxData; // Store in global variable rxBitCnt = 8; // Re-load bit counter TACCTL1 |= CAP; // Switch compare to capture mode __bic_SR_register_on_exit(LPM0_bits); // Clear LPM0 bits from 0(SR) } } break; } }
And here's ds18b20.h
#ifndef DS18B20_H_ #define DS18B20_H_ // 'tick' values // Compute these from DalSemi AN126 xls worksheet //int A,B,C,D,E,F,G,H,I,J; #define tA 6 #define tB 64 #define tC 60 #define tD 10 #define tE 9 #define tF 55 #define tG 0 #define tH 480 #define tI 70 #define tJ 410 // 1-Wire ROM Command Codes #define SEARCHROM 0xF0 #define READROM 0x33 #define MATCHROM 0x55 #define SKIPROM 0xCC #define ALARMSEARCH 0xEC // DS18B20 Function Commands #define CONVERTTEMP 0x44 #define WRITESCRATCHPAD 0x4E #define READSCRATCHPAD 0xBE #define COPYSCRATCHPAD 0x48 #define RECALLEE 0xB8 #define READPOWERSUPPLY 0xB4 #endif /*DS18B20_H_*/
Again, make sure you calibrate the DCO for 16MHz if you're using a value line device.
Enjoy!
-
zeke reacted to touch in Reading DS1821+ Temp Sensor
I've got some DS1820''s myself and have been unable to get them working. I'm going to try a little later tonight, but I know the DS1821 works fine.
Take a look at this:
http://milesburton.com/index.php?title= ... ol_Library
http://www.pjrc.com/teensy/td_libs_OneWire.html
http://www.phanderson.com/arduino/ds18b20_1.html
It really seems like for the DS1820's sensor we need to go about properly addressing it.
Anyways, I'll try to give it a try tonight, it would be nice to get high resolution working too.
-
zeke reacted to touch in Reading tempature from a DS1821+ 1-Wire tempature sensor
Sorry it took so long, been slacking off .
Done: viewtopic.php?f=10&t=452&start=0
-
zeke reacted to touch in Reading DS1821+ Temp Sensor
Here is some code I put together for reading the temp from a DS1281+ Sensor and outputting it over serial.
You will need to flash the missing 16Mhz DCO values to use this, as explained here: viewtopic.php?f=10&p=2954#p2954
#include #define UART_TXD 0x02 // TXD on P1.1 (Timer0_A.OUT0) #define UART_RXD 0x04 // RXD on P1.2 (Timer0_A.CCI1A) #define UART_TBIT_DIV_2 (16000000 / (9600 * 2)) #define UART_TBIT (16000000 / 9600) #define delayMicroseconds(n) __delay_cycles(n<<4) void OneWireOutByte(int _1W_Pin, char d); char OneWireInByte(int _1W_Pin); void OneWireReset(int _1W_Pin); char digitalRead(char pin); void pinMode(int pin, int out); void digitalWrite(int pin, int low); void TimerA_UART_init(void); void TimerA_UART_tx(unsigned char byte); void TimerA_UART_print(char *string); unsigned int txData; // UART internal variable for TX unsigned char rxBuffer; // Received UART character #define LOW 0 #define HIGH 1 #define INPUT 0 #define OUTPUT 1 #define WIRE_PORT 7 //Remember you need a 4.7k pullup resistor here. void main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer BCSCTL1 = CALBC1_16MHZ; DCOCTL = CALDCO_16MHZ; P1OUT = UART_RXD; // RXD as IN P1SEL = UART_TXD + UART_RXD; // Timer function for TXD/RXD pins P1DIR = UART_TXD; __enable_interrupt(); TimerA_UART_init(); for(;{ OneWireReset(WIRE_PORT); OneWireOutByte(WIRE_PORT, 0xEE); // start temp conversion OneWireReset(WIRE_PORT); OneWireOutByte(WIRE_PORT, 0xAA); // read temp //this will print the tempature in an int8 over serial every 1 second. TimerA_UART_tx(OneWireInByte(WIRE_PORT)); delayMicroseconds(1000000); } } void OneWireReset(int Pin) // Send 1Wire Reset { digitalWrite(Pin, LOW); pinMode(Pin, OUTPUT); delayMicroseconds(500); pinMode(Pin, INPUT); delayMicroseconds(500); } void OneWireOutByte(int Pin, char d) { char n; for(n=8; n!=0; n--) { if ((d & 0x01) == 1) { digitalWrite(Pin, LOW); pinMode(Pin, OUTPUT); delayMicroseconds(5); pinMode(Pin, INPUT); delayMicroseconds(60); } else { digitalWrite(Pin, LOW); pinMode(Pin, OUTPUT); delayMicroseconds(60); pinMode(Pin, INPUT); } d=d>>1; } } char OneWireInByte(int Pin) { char d, n, b; for (n=0; n<8; n++) { digitalWrite(Pin, LOW); pinMode(Pin, OUTPUT); delayMicroseconds(5); pinMode(Pin, INPUT); delayMicroseconds(5); b = digitalRead(Pin); delayMicroseconds(50); d = (d >> 1) | (b<<7); // shift d to right and insert b in most sig bit position } return(d); } //------------------------------------------------------------------------------ // Arduino like digitalRead, pinMode, and digitalWrite helper functions. //------------------------------------------------------------------------------ char digitalRead(char pin) { return (P1IN & 1 << pin) >> pin; } void pinMode(int pin, int out){ if(out){ P1DIR |= (1 << pin); } else{ P1DIR &= (~(1 << pin)); } } void digitalWrite(int pin, int low) { if (low){ P1OUT |= ( 1 << pin); }else{ P1OUT &= (~(1 << pin)); } } //------------------------------------------------------------------------------ // Function configures Timer_A for full-duplex UART operation //------------------------------------------------------------------------------ void TimerA_UART_init(void) { TACCTL0 = OUT; // Set TXD Idle as Mark = '1' TACCTL1 = SCS + CM1 + CAP + CCIE; // Sync, Neg Edge, Capture, Int TACTL = TASSEL_2 + MC_2; // SMCLK, start in continuous mode } //------------------------------------------------------------------------------ // Outputs one byte using the Timer_A UART //------------------------------------------------------------------------------ void TimerA_UART_tx(unsigned char byte) { while (TACCTL0 & CCIE); // Ensure last char got TX'd TACCR0 = TAR; // Current state of TA counter TACCR0 += UART_TBIT; // One bit time till first bit TACCTL0 = OUTMOD0 + CCIE; // Set TXD on EQU0, Int txData = byte; // Load global variable txData |= 0x100; // Add mark stop bit to TXData txData <<= 1; // Add space start bit } //------------------------------------------------------------------------------ // Prints a string over using the Timer_A UART //------------------------------------------------------------------------------ void TimerA_UART_print(char *string) { while (*string) { TimerA_UART_tx(*string++); } } //------------------------------------------------------------------------------ // Timer_A UART - Transmit Interrupt Handler //------------------------------------------------------------------------------ #pragma vector = TIMERA0_VECTOR __interrupt void Timer_A0_ISR(void) { static unsigned char txBitCnt = 10; TACCR0 += UART_TBIT; // Add Offset to CCRx if (txBitCnt == 0) { // All bits TXed? TACCTL0 &= ~CCIE; // All bits TXed, disable interrupt txBitCnt = 10; // Re-load bit counter } else { if (txData & 0x01) { TACCTL0 &= ~OUTMOD2; // TX Mark '1' } else { TACCTL0 |= OUTMOD2; // TX Space '0' } txData >>= 1; txBitCnt--; } } //------------------------------------------------------------------------------ // Timer_A UART - Receive Interrupt Handler //------------------------------------------------------------------------------ #pragma vector = TIMERA1_VECTOR __interrupt void Timer_A1_ISR(void) { static unsigned char rxBitCnt = 8; static unsigned char rxData = 0; switch (__even_in_range(TAIV, TAIV_TAIFG)) { // Use calculated branching case TAIV_TACCR1: // TACCR1 CCIFG - UART RX TACCR1 += UART_TBIT; // Add Offset to CCRx if (TACCTL1 & CAP) { // Capture mode = start bit edge TACCTL1 &= ~CAP; // Switch capture to compare mode TACCR1 += UART_TBIT_DIV_2; // Point CCRx to middle of D0 } else { rxData >>= 1; if (TACCTL1 & SCCI) { // Get bit waiting in receive latch rxData |= 0x80; } rxBitCnt--; if (rxBitCnt == 0) { // All bits RXed? rxBuffer = rxData; // Store in global variable rxBitCnt = 8; // Re-load bit counter TACCTL1 |= CAP; // Switch compare to capture mode __bic_SR_register_on_exit(LPM0_bits); // Clear LPM0 bits from 0(SR) } } break; } }
I would like to point a few things that I will improve on this code one day, but don't have the knowledge to do at the moment (this is my first C code I've ever written.). USI could be used to send the temp readout because we don't really have any reason to receieve UART, the timer then could be used for timing of reading the sensor, rather than a delay.
I was also able to get it working in 1wire mode - I did not need to use a transistor, however I did not test programming the DS1821+, as my main goal was to readout the temperature.
You will also need to use something like Realterm that lets you view the serial output as an int8.
There is one question I have that I cannot seem to find an answer too, here or via google. If I wanted to convert the bytes received from OneWireInByte(WIRE_PORT) to an ASCII number format, so that you could view it in putty or whatnot, how would I go about doing that?
Also, a special thanks to zeke as he is the main reason this works, I could have not have gotten it properly working without him figuring out how to flash the 16Mhz DCO values.
-
zeke got a reaction from artifus in Flashing the missing DCO calibration constants
Hi Guys,
I wanted to tack on my calibration code that I successfully used to calibrate my G2231 device.
It's almost exactly like naturetm's code. The only difference is the setDCO() function has a little more fine tuning in it.
Take a look and notice that the setDCO() function is slightly different. I stole the idea from a post aBUGSworstnightmare made on the ti.com website. Here's the link.
//****************************************************************************** // MSP430F20xx Demo - DCO Calibration Constants Programmer // // NOTE: THIS CODE REPLACES THE TI FACTORY-PROGRAMMED DCO CALIBRATION // CONSTANTS LOCATED IN INFOA WITH NEW VALUES. USE ONLY IF THE ORIGINAL // CONSTANTS ACCIDENTALLY GOT CORRUPTED OR ERASED. // // Description: This code re-programs the F2xx DCO calibration constants. // A software FLL mechanism is used to set the DCO based on an external // 32kHz reference clock. After each calibration, the values from the // clock system are read out and stored in a temporary variable. The final // frequency the DCO is set to is 1MHz, and this frequency is also used // during Flash programming of the constants. The program end is indicated // by the blinking LED. // ACLK = LFXT1/8 = 32768/8, MCLK = SMCLK = target DCO // //* External watch crystal installed on XIN XOUT is required for ACLK *// // // MSP430F20xx // --------------- // /|\| XIN|- // | | | 32kHz // --|RST XOUT|- // | | // | P1.0|--> LED // | P1.4|--> SMLCK = target DCO // // A. Dannenberg // Texas Instruments Inc. // May 2007 // Built with CCE Version: 3.2.0 and IAR Embedded Workbench Version: 3.42A //****************************************************************************** //#include "msp430x20x1.h" // do not forget to change this according to the device you're using #include #define DELTA_1MHZ 244 // 244 x 4096Hz = 999.4Hz #define DELTA_8MHZ 1953 // 1953 x 4096Hz = 7.99MHz #define DELTA_12MHZ 2930 // 2930 x 4096Hz = 12.00MHz #define DELTA_16MHZ 3906 // 3906 x 4096Hz = 15.99MHz unsigned char CAL_DATA[8]; // Temp. storage for constants volatile unsigned int i; int j; char *Flash_ptrA; // Segment A pointer void Set_DCO(unsigned int Delta); void main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop WDT BCSCTL3 |= XCAP_3; // Launchpad watch crystals need ~12.5 pF for (i = 0; i < 0xfffe; i++); // Delay for XTAL stabilization P1OUT = 0x00; // Clear P1 output latches P1SEL = 0x10; // P1.4 SMCLK output P1DIR = 0x11; // P1.0,4 output j = 0; // Reset pointer Set_DCO(DELTA_16MHZ); // Set DCO and obtain constants CAL_DATA[j++] = DCOCTL; CAL_DATA[j++] = BCSCTL1; Set_DCO(DELTA_12MHZ); // Set DCO and obtain constants CAL_DATA[j++] = DCOCTL; CAL_DATA[j++] = BCSCTL1; Set_DCO(DELTA_8MHZ); // Set DCO and obtain constants CAL_DATA[j++] = DCOCTL; CAL_DATA[j++] = BCSCTL1; Set_DCO(DELTA_1MHZ); // Set DCO and obtain constants CAL_DATA[j++] = DCOCTL; CAL_DATA[j++] = BCSCTL1; Flash_ptrA = (char *)0x10C0; // Point to beginning of seg A FCTL2 = FWKEY + FSSEL0 + FN1; // MCLK/3 for Flash Timing Generator FCTL1 = FWKEY + ERASE; // Set Erase bit FCTL3 = FWKEY + LOCKA; // Clear LOCK & LOCKA bits *Flash_ptrA = 0x00; // Dummy write to erase Flash seg A FCTL1 = FWKEY + WRT; // Set WRT bit for write operation Flash_ptrA = (char *)0x10F8; // Point to beginning of cal consts for (j = 0; j < 8; j++) *Flash_ptrA++ = CAL_DATA[j]; // re-flash DCO calibration data FCTL1 = FWKEY; // Clear WRT bit FCTL3 = FWKEY + LOCKA + LOCK; // Set LOCK & LOCKA bit while (1) { P1OUT ^= 0x01; // Toggle LED for (i = 0; i < 0x4000; i++); // SW Delay } } void Set_DCO(unsigned int Delta) // Set DCO to selected frequency { unsigned int Compare, Oldcapture = 0; BCSCTL1 |= DIVA_3; // ACLK = LFXT1CLK/8 TACCTL0 = CM_1 + CCIS_1 + CAP; // CAP, ACLK TACTL = TASSEL_2 + MC_2 + TACLR; // SMCLK, cont-mode, clear while (1) { while (!(CCIFG & TACCTL0)); // Wait until capture occured TACCTL0 &= ~CCIFG; // Capture occured, clear flag Compare = TACCR0; // Get current captured SMCLK Compare = Compare - Oldcapture; // SMCLK difference Oldcapture = TACCR0; // Save current captured SMCLK if (Delta == Compare) break; // If equal, leave "while(1)" else if (Delta < Compare) { DCOCTL--; // DCO is too fast, slow it down if (DCOCTL == 0xFF) // Did DCO roll under? if (BCSCTL1 & 0x0f) BCSCTL1--; // Select lower RSEL } else { DCOCTL++; // DCO is too slow, speed it up if (DCOCTL == 0x00) // Did DCO roll over? if ((BCSCTL1 & 0x0f) != 0x0f) BCSCTL1++; // Sel higher RSEL } } TACCTL0 = 0; // Stop TACCR0 TACTL = 0; // Stop Timer_A BCSCTL1 &= ~DIVA_3; // ACLK = LFXT1CLK }
Concerning the mods that were made to the cmd file, I just threw them into the default files because I know that I'm going to forget to made the project edits that are suggested in the first post above.
Just calibrate the g2231 first then use the code after.
-
zeke got a reaction from gatesphere in Using a variable in if statement with msp-gcc
Oops! Sorry about that. I missed that detail.
You have to admit that it seems strange that the brief_pause() doesn't work for you.
Maybe you should insert TAB's instead of spaces inside the brief_pause() function?
static void __inline__ brief_pause(register unsigned int n) { __asm__ __volatile__ ( "1: \n" " dec \t %[n] \n" " jne \t >1b \n" : [n] \t "+r"(n)); }
Read this post to see where I got this idea.
Too bad you're not using CSS because you could use the __delay_cycles(n) intrinsic function here. It doesn't take a variable though. It has to be a hard coded integer value because it is converted by the compiler into code that takes "n" cycles to complete.
Take a chance on the tab insertion option and try the brief_pause() routine again. Somehow it works for many people out there.
-
zeke got a reaction from Rei Vilo in Best information for those new to the MSP430?
If you are new to the MSP430 then you're probably drowning in information right now.
It's true that there are a zillion configurations to make before the 430 will do what you want it do do.
So I'm betting that you are asking yourself "Where do I start?"
I humbly suggest the following TI application notes and books that will get you going in the right direction:
1. slaa294: MSP430 Software Coding Techniques
This application report covers software techniques and topics of interest to all MSP430
programmers. The first part of the document discusses the MSP430 standard
interrupt-based code flow model, recommended for the vast majority of applications.
The next part discusses a handful of techniques that should be considered by any
developer that sets out to develop an MSP430 application. Using these methods can
greatly reduce debug time and/or provide additional robustness in the field. They
include initialization procedures, validation of supply rails before performing
voltage-sensitive operations, and use of special functions. Code examples are
provided.
2. : MSP430 32-kHz Crystal OscillatorsSelection of the right crystal, correct load circuit, and proper board layout are importantfor a stable crystal oscillator. This application report summarizes crystal oscillatorfunction and explains the parameters to select the correct crystal for MSP430ultralow-power operation. In addition, hints and examples for correct board layout aregiven. The document also contains detailed information on the possible oscillator teststo ensure stable oscillator operation in mass production.
3. MSP430 Microcontroller Basics by John H. Davies
The best thing I can say about this book at this time is that it describes well how to make use of the clocking system of the MSP430. This book should be in your personal library or at least on your wishlist.
Once you digest the information above then you will be in good shape for success in working with the msp430.
Have something to add?
Then post up your valuable sources of knowledge.
-
zeke got a reaction from jsolarski in Are MSP430 wake up times clock source dependent?
If you do happen to use a 32kHz crystal, check out TI's App Note slaa322b.
It goes into detail about how a crystal works, what will make it fail and how to design your circuit for optimal operation.
It's a good one to bookmark.
-
zeke got a reaction from vicvelcro in Best information for those new to the MSP430?
If you are new to the MSP430 then you're probably drowning in information right now.
It's true that there are a zillion configurations to make before the 430 will do what you want it do do.
So I'm betting that you are asking yourself "Where do I start?"
I humbly suggest the following TI application notes and books that will get you going in the right direction:
1. slaa294: MSP430 Software Coding Techniques
This application report covers software techniques and topics of interest to all MSP430
programmers. The first part of the document discusses the MSP430 standard
interrupt-based code flow model, recommended for the vast majority of applications.
The next part discusses a handful of techniques that should be considered by any
developer that sets out to develop an MSP430 application. Using these methods can
greatly reduce debug time and/or provide additional robustness in the field. They
include initialization procedures, validation of supply rails before performing
voltage-sensitive operations, and use of special functions. Code examples are
provided.
2. : MSP430 32-kHz Crystal OscillatorsSelection of the right crystal, correct load circuit, and proper board layout are importantfor a stable crystal oscillator. This application report summarizes crystal oscillatorfunction and explains the parameters to select the correct crystal for MSP430ultralow-power operation. In addition, hints and examples for correct board layout aregiven. The document also contains detailed information on the possible oscillator teststo ensure stable oscillator operation in mass production.
3. MSP430 Microcontroller Basics by John H. Davies
The best thing I can say about this book at this time is that it describes well how to make use of the clocking system of the MSP430. This book should be in your personal library or at least on your wishlist.
Once you digest the information above then you will be in good shape for success in working with the msp430.
Have something to add?
Then post up your valuable sources of knowledge.
-
zeke got a reaction from oetroc in Best information for those new to the MSP430?
If you are new to the MSP430 then you're probably drowning in information right now.
It's true that there are a zillion configurations to make before the 430 will do what you want it do do.
So I'm betting that you are asking yourself "Where do I start?"
I humbly suggest the following TI application notes and books that will get you going in the right direction:
1. slaa294: MSP430 Software Coding Techniques
This application report covers software techniques and topics of interest to all MSP430
programmers. The first part of the document discusses the MSP430 standard
interrupt-based code flow model, recommended for the vast majority of applications.
The next part discusses a handful of techniques that should be considered by any
developer that sets out to develop an MSP430 application. Using these methods can
greatly reduce debug time and/or provide additional robustness in the field. They
include initialization procedures, validation of supply rails before performing
voltage-sensitive operations, and use of special functions. Code examples are
provided.
2. : MSP430 32-kHz Crystal OscillatorsSelection of the right crystal, correct load circuit, and proper board layout are importantfor a stable crystal oscillator. This application report summarizes crystal oscillatorfunction and explains the parameters to select the correct crystal for MSP430ultralow-power operation. In addition, hints and examples for correct board layout aregiven. The document also contains detailed information on the possible oscillator teststo ensure stable oscillator operation in mass production.
3. MSP430 Microcontroller Basics by John H. Davies
The best thing I can say about this book at this time is that it describes well how to make use of the clocking system of the MSP430. This book should be in your personal library or at least on your wishlist.
Once you digest the information above then you will be in good shape for success in working with the msp430.
Have something to add?
Then post up your valuable sources of knowledge.
-
zeke reacted to RobG in Another DS1821+ project
I have finally got my DS1821+ and decided to spend some time getting it to work with my LaunchPad.
I have reused my other project's code and setup, but because I am short one pin, I had to remove one digit (I will probably need it later once I get to the point of converting temp to some readable format, maybe reuse latch pin.)
P1.4 is connected directly to data pin of DS1821.
Note: my first approach was to use 2 pins and a transistor, currently I am using only one pin to connect to DS. If you still want to use 2 wire version, here's how to connect it: P1.7 is connected to data pin of the DS, P1.4 is connected to the base of transistor, collector to data pin of DS, emitter to the ground.
New code that uses one wire
#include #define BIT1_3 (BIT1 + BIT2 + BIT3) // all digit bits #define LED_REFRESH 0 #define DS_RESET 1 #define DS_TEST 2 #define DS_READY 3 #define DS_COMM 4 #define READ_TEMP 0xAA #define START_CONV 0xEE #define WIRE_DOWN (P1OUT &= ~BIT4) #define WIRE_UP (P1OUT |= BIT4) #define WIRE_IN (P1IN & BIT4) #define P4_IN (P1DIR &= ~BIT4) #define P4_OUT (P1DIR |= BIT4) unsigned char negative = 0; unsigned char bitSet = 0; unsigned char init = 1; unsigned char mainDelay = 0; unsigned char stepCounter = 0; unsigned char txData = 0; char rxData = 0; unsigned char dataCounter = 0; unsigned int displayData = 0; // data to be displayed unsigned int displayArray[3] = {0x0F, 0x0F, 0x0F}; unsigned char digitCounter = 0; // digit counter unsigned char digit = 0; // single digit to be displayed const unsigned char hex7digit[16] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00,0x00,0x00,0x50,0x79,0x40}; // dec to 7 digit map, E,- const unsigned char digitSelector[3] = {0x02, 0x04, 0x08}; // digit selector map P1.1-P1.3 void handleError(); void setUp(); void convertData(); void backToLED(); void main() { WDTCTL = WDTPW + WDTHOLD; // stop WDT setUp(); _bis_SR_register(LPM0_bits + GIE); // LPM0 with interrupt } // Timer A0 interrupt service routine #pragma vector = TIMERA0_VECTOR __interrupt void Timer_A (void) { if(stepCounter == DS_COMM) { CCR0 = 8; P4_OUT; WIRE_UP; // wire up in case it was pulled down while writing if(init && dataCounter == 8) { // we are done sending Start Convert backToLED(); return; } else if(dataCounter == 16) { // we are done reading temp backToLED(); convertData(); return; } WIRE_DOWN; if(dataCounter < 8) { bitSet = txData & BIT0; if(bitSet) WIRE_UP; txData >>= 1; } else { WIRE_UP; // wire up P4_IN; bitSet = WIRE_IN; rxData >>= 1; if(bitSet) rxData |= BIT7; } dataCounter++; // DS RESET } else if(stepCounter == DS_RESET) { WIRE_UP; // wire up CCR0 = 12; stepCounter++; P4_IN; // DS TEST } else if(stepCounter == DS_TEST) { if(WIRE_IN) { handleError(); } else { CCR0 = 36; stepCounter++; } // DS READY } else if(stepCounter == DS_READY) { if(WIRE_IN) { stepCounter++; } else { handleError(); } // LED_REFRESH } else { digitCounter++; // increase digit counter if(digitCounter == 0x03) digitCounter = 0; // mask, counter range is 0-2 digit = displayArray[digitCounter]; // shift digits right USISRL = hex7digit[digit]; // get segments from the map USICNT |= 8; // start USI mainDelay++; if(mainDelay == 200) { // 1 sec mainDelay = 0; if(init) { txData = START_CONV; } else { txData = READ_TEMP; } stepCounter = DS_RESET; dataCounter = 0; rxData = 0; P4_OUT; WIRE_DOWN; // pull the wire down CCR0 = 48; } } } void convertData() { negative = 0; displayArray[0] = 0; displayArray[1] = 0x0A; displayArray[2] = 0x0A; if(rxData & BIT7) { rxData = -(rxData); negative = 1; } unsigned char d = 0; while(rxData > 0) { displayArray[d] = rxData % 10; rxData /= 10; d++; } if(negative) { if(rxData < 10) { displayArray[1] = 0x0F; } else if(rxData < 100) { displayArray[2] = 0x0F; } } } void handleError() { backToLED(); displayArray[0] = 0x0D; displayArray[1] = 0x0D; displayArray[2] = 0x0E; init = 1; } void backToLED() { CCR0 = 625; init ^= 0x01; stepCounter = LED_REFRESH; } void setUp(void) { BCSCTL1 = CALBC1_1MHZ; DCOCTL = CALDCO_1MHZ; P1DIR |= BIT1_3 + BIT4 + BIT0; // port P1.1-P1.3 used to drive digits, P1.4 to pull wire down P1OUT |= BIT0; // port P1.0 used to latch 74HC595 P1REN |= BIT4; USICTL0 |= USIPE6 + USIPE5 + USIMST + USIOE; // out & clk enable, SPI Master USICTL1 |= USICKPH + USIIE; // counter interrupt, flag remains set USICKCTL = USISSEL_2; // SMCLK USICTL0 &= ~USISWRST; // USI released for operation CCR0 = 625; // approx. 5ms CCTL0 = CCIE; // CCR0 interrupt enabled TACTL = TASSEL_2 + MC_1 + ID_3; // SMCLK/8, upmode } // USI interrupt service routine #pragma vector = USI_VECTOR __interrupt void USI_TXRX (void) { USICTL1 &= ~USIIFG; // clear pending flag P1OUT &= ~BIT1_3; // turn off all digits P1OUT &= ~BIT0; // latch data display (& input for next timer interrupt) P1OUT |= digitSelector[digitCounter]; // turn on digit P1OUT |= BIT0; }
Old code which used 2 pins and transistor
#include #define BIT1_3 (BIT1 + BIT2 + BIT3) // all digit bits #define LED_REFRESH 0 #define DS_RESET 1 #define DS_TEST 2 #define DS_READY 3 #define DS_COMM 4 #define READ_TEMP 0xAA #define START_CONV 0xEE #define WIRE_UP (P1OUT &= ~BIT4) #define WIRE_DOWN (P1OUT |= BIT4) #define WIRE_IN (P1IN & BIT7) unsigned char negative = 0; unsigned char bitSet = 0; unsigned char init = 1; unsigned char mainDelay = 0; unsigned char stepCounter = 0; unsigned char txData = 0; char rxData = 0; unsigned char dataCounter = 0; unsigned int displayData = 0; // data to be displayed unsigned int displayArray[3] = {0x0F, 0x0F, 0x0F}; unsigned char digitCounter = 0; // digit counter unsigned char digit = 0; // single digit to be displayed const unsigned char hex7digit[16] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00,0x00,0x00,0x50,0x79,0x40}; // dec to 7 digit map, E,- const unsigned char digitSelector[3] = {0x02, 0x04, 0x08}; // digit selector map P1.1-P1.3 void handleError(); void setUp(); void convertData(); void backToLED(); void main() { WDTCTL = WDTPW + WDTHOLD; // stop WDT setUp(); _bis_SR_register(LPM0_bits + GIE); // LPM0 with interrupt } // Timer A0 interrupt service routine #pragma vector = TIMERA0_VECTOR __interrupt void Timer_A (void) { if(stepCounter == DS_COMM) { CCR0 = 8; WIRE_UP; // wire up in case it was pulled down while writing if(init && dataCounter == 8) { // we are done sending Start Convert backToLED(); return; } else if(dataCounter == 16) { // we are done reading temp backToLED(); convertData(); return; } if(dataCounter < 8) { WIRE_DOWN; bitSet = txData & BIT0; if(bitSet) WIRE_UP; txData >>= 1; } else { WIRE_DOWN; WIRE_UP; // wire up bitSet = WIRE_IN; rxData >>= 1; if(bitSet) rxData |= BIT7; } dataCounter++; // DS RESET } else if(stepCounter == DS_RESET) { WIRE_UP; // wire up CCR0 = 12; stepCounter++; // DS TEST } else if(stepCounter == DS_TEST) { if(WIRE_IN) { handleError(); } else { CCR0 = 36; stepCounter++; } // DS READY } else if(stepCounter == DS_READY) { if(WIRE_IN) { stepCounter++; } else { handleError(); } // LED_REFRESH } else { digitCounter++; // increase digit counter if(digitCounter == 0x03) digitCounter = 0; // mask, counter range is 0-2 digit = displayArray[digitCounter]; // shift digits right USISRL = hex7digit[digit]; // get segments from the map USICNT |= 8; // start USI mainDelay++; if(mainDelay == 200) { // 1 sec mainDelay = 0; if(init) { txData = START_CONV; } else { txData = READ_TEMP; } stepCounter = DS_RESET; dataCounter = 0; rxData = 0; WIRE_DOWN; // pull the wire down CCR0 = 48; } } } void convertData() { negative = 0; displayArray[0] = 0; displayArray[1] = 0x0A; displayArray[2] = 0x0A; if(rxData & BIT7) { rxData = -(rxData); negative = 1; } unsigned char d = 0; while(rxData > 0) { displayArray[d] = rxData % 10; rxData /= 10; d++; } if(negative) { if(rxData < 10) { displayArray[1] = 0x0F; } else if(rxData < 100) { displayArray[2] = 0x0F; } } } void handleError() { backToLED(); displayArray[0] = 0x0D; displayArray[1] = 0x0D; displayArray[2] = 0x0E; init = 1; } void backToLED() { CCR0 = 625; init ^= 0x01; stepCounter = LED_REFRESH; } void setUp(void) { BCSCTL1 = CALBC1_1MHZ; DCOCTL = CALDCO_1MHZ; P1DIR |= BIT1_3 + BIT4 + BIT0; // port P1.1-P1.3 used to drive digits, P1.4 to pull wire down P1OUT |= BIT0; // port P1.0 used to latch 74HC595 P1REN |= BIT7; // P1.7 resistor enabled P1OUT |= BIT7; // P1.7 pull-up USICTL0 |= USIPE6 + USIPE5 + USIMST + USIOE; // out & clk enable, SPI Master USICTL1 |= USICKPH + USIIE; // counter interrupt, flag remains set USICKCTL = USISSEL_2; // SMCLK USICTL0 &= ~USISWRST; // USI released for operation CCR0 = 625; // approx. 5ms CCTL0 = CCIE; // CCR0 interrupt enabled TACTL = TASSEL_2 + MC_1 + ID_3; // SMCLK/8, upmode } // USI interrupt service routine #pragma vector = USI_VECTOR __interrupt void USI_TXRX (void) { USICTL1 &= ~USIIFG; // clear pending flag P1OUT &= ~BIT1_3; // turn off all digits P1OUT &= ~BIT0; // latch data display (& input for next timer interrupt) P1OUT |= digitSelector[digitCounter]; // turn on digit P1OUT |= BIT0; }
-
zeke got a reaction from Dimiric in Best information for those new to the MSP430?
If you are new to the MSP430 then you're probably drowning in information right now.
It's true that there are a zillion configurations to make before the 430 will do what you want it do do.
So I'm betting that you are asking yourself "Where do I start?"
I humbly suggest the following TI application notes and books that will get you going in the right direction:
1. slaa294: MSP430 Software Coding Techniques
This application report covers software techniques and topics of interest to all MSP430
programmers. The first part of the document discusses the MSP430 standard
interrupt-based code flow model, recommended for the vast majority of applications.
The next part discusses a handful of techniques that should be considered by any
developer that sets out to develop an MSP430 application. Using these methods can
greatly reduce debug time and/or provide additional robustness in the field. They
include initialization procedures, validation of supply rails before performing
voltage-sensitive operations, and use of special functions. Code examples are
provided.
2. : MSP430 32-kHz Crystal OscillatorsSelection of the right crystal, correct load circuit, and proper board layout are importantfor a stable crystal oscillator. This application report summarizes crystal oscillatorfunction and explains the parameters to select the correct crystal for MSP430ultralow-power operation. In addition, hints and examples for correct board layout aregiven. The document also contains detailed information on the possible oscillator teststo ensure stable oscillator operation in mass production.
3. MSP430 Microcontroller Basics by John H. Davies
The best thing I can say about this book at this time is that it describes well how to make use of the clocking system of the MSP430. This book should be in your personal library or at least on your wishlist.
Once you digest the information above then you will be in good shape for success in working with the msp430.
Have something to add?
Then post up your valuable sources of knowledge.
-
zeke got a reaction from GeekDoc in Are MSP430 wake up times clock source dependent?
In this datasheet on page 33, it gives a table of startup times based upon the DCO configuration. The slowest time is 2us when the DCO is set to 1MHz.
What the datasheet doesn't tell you is the startup times for any other configurations - only when MCLK = DCO.
I can tell you that if you use an external crystal (ie 16MHz) then the startup time is completely dependent upon the accuracy of that crystal.
Here's another quote from John H. Davies in MSP430 Microcontroller Basics, page 165:
Crystal Oscillators, LFXT1 and XT2
Crystals are used when an accurate, stable frequency is needed:
-
zeke got a reaction from RobG in Are MSP430 wake up times clock source dependent?
Sorry, it wasn't intended as a snide remark but yeah, it appears that I was an ass last night. :oops:
I could delete my post if you'd like.
It would be good for the original poster to specify the processor that he is working with.
To quote John H. Davies in MSP430 Microcontroller Basics, page 164:
Up to four sources are available for the clock, depending on the family and variant:
Low- or high-frequency crystal oscillator, LFXT1: Available in all devices. It is
usually used with a low-frequency watch crystal (32 KHz) but can also run with a
high-frequency crystal (typically a few MHz) in most devices. An external clock signal
can be used instead of a crystal if it is important to synchronize the MSP430 with other
devices in the system.
High-frequency crystal oscillator, XT2: Similar to LFXT1 except that it is restricted
to high frequencies. It is available in only a few devices and LFXT1 (or VLO) is used
instead if XT2 is missing.
Internal very low-power, low-frequency oscillator, VLO: Available in only the more
recent MSP430F2xx devices. It provides an alternative to LFXT1 when the accuracy of
a crystal is not needed.
Digitally controlled oscillator, DCO: Available in all devices and one of the highlights
of the MSP430. It is basically a highly controllable RC oscillator that starts in less than
1 us in newer devices.
I suspect that the OP is working with a new device (ie: no x1xx or x3xx devices) therefore the answer is one of the four options above. Otherwise I advise the OP to kindly read the datasheet.
-
zeke got a reaction from RobG in Are MSP430 wake up times clock source dependent?
In this datasheet on page 33, it gives a table of startup times based upon the DCO configuration. The slowest time is 2us when the DCO is set to 1MHz.
What the datasheet doesn't tell you is the startup times for any other configurations - only when MCLK = DCO.
I can tell you that if you use an external crystal (ie 16MHz) then the startup time is completely dependent upon the accuracy of that crystal.
Here's another quote from John H. Davies in MSP430 Microcontroller Basics, page 165:
Crystal Oscillators, LFXT1 and XT2
Crystals are used when an accurate, stable frequency is needed:
-
zeke got a reaction from RobG in Are MSP430 wake up times clock source dependent?
In other words, the spec sheet and family user guides are like Wise Guys - they know everything that you want to know but it's sometimes hard to get them to tell you stuff. Especially if you don't phrase your question just right.
It would be good for you to sit down with the Wise Guys in front of you and order a couple of Wobbley Pops and have a long, intense interaction with them. They will then reveal to you all of their golden knowledge and wisdom.
The day after you recover from all your Wobbley Pops, you will develop a superiority complex because all the mysteries of the MSP430 have been revealed to you. You are now the Chosen One. You are now able to program an MSP430 with the shear force of your will and the static electricity generated by your wiggling in your office chair. You can increase the joules with a can of beans
You will read our little forum here and declare your new found super powers with panache and pomp:
"Stand Back everyone! For I am now BITBLASTER! I can solve all your code challenges and program your MSP430 over the internet
"What Mom?!"
"Take out the garbage, Zeke."
"BITBLASTER! MY NAME IS NOW BITBLASTER!"
"Okay Dust Buster, Mache Schnell with the garbage!"
"NOW?!"
"Yes! Do it now Dark Lard of the Laboratory."
"Awe Maaaan! I was just going to blow the protection fuse on that guys micro."
Not to be an ass but read the manual dude! Yes, it's tough reading sometimes but they are full of cool stuff. :mrgreen:
If you don't want to read the manual then read this book first. It's a reeeeealy good book. It tackles the timers and clocks very well. You'll be having fun in no time after that!
Man, we should contact Elsevier and try to get a group discount for the forum members. That's a damn good book.
-
zeke got a reaction from bluehash in Share pics of your workspace setup
Well, since we're all measuring one another :shock: here's my workspace.
Someday, I'll be able to afford walls. The kitties won't be able to sleep on my workbench then! 8-)
Here's the command center. An Ikea Jerker that I got for free off of Kijiji:
Flames happen here. Okay, I measure the amount of magic smoke I let out:
Tiny parts go on and come off on this bench when it's not a crap storage area. I love my Leica microscope. I can see into my skin with it :ugeek: :
-
zeke got a reaction from NatureTM in Poll: What compiler tools do you use?
Bluehash!
I'd like to do a poll to see what compiler tools everyone is using. Can you tweak the forum to allow polls?
Here's what's on my mind.
I use CCS4 and so my code snippets are written in that fashion. I understand that mspgcc is different enough that the code has to be re-written before it will compile.
What tools do you use?
Options:
1. CCS4
2. IAR
3. GCC
4. Rowley
5. Other
What do you think?
-
zeke reacted to nobody in Launchpad Pin1.3 problem
Small warning for those who do not read manuals:
TI produces for us a very good kit at a very competitive price. But no thing is not entirely perfect.
Into this kit is pin P1.3 connected to button S2. OK, no problem. But for debouncing button, RC combination C34/R24 is also attached to P1.3.
And here's the problem. C34/R24 is not detachable. Still not problem to us? Look to the simple sample code:
#include "io430.h" #include "intrinsics.h" const unsigned char FONT[] = { 0x00, 0x06, 0x22, 0x00, 0x6D, 0x00, 0x00, 0x20, 0x39, 0x0F, 0x00, 0x70, 0x08, 0x40, 0x00, 0x52, 0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x48, 0x48, 0x39, 0x48, 0x0F, 0x53, 0x00, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71, 0x6F, 0x76, 0x30, 0x1E, 0x76, 0x38, 0x15, 0x54, 0x3F, 0x73, 0x67, 0x50, 0x6D, 0x78, 0x3E, 0x1C, 0x2A, 0x76, 0x6E, 0x5B, 0x39, 0x64, 0x0F, 0x23, 0x08, 0x20, 0x77, 0x7C, 0x58, 0x5E, 0x79, 0x71, 0x6F, 0x74, 0x04, 0x1E, 0x76, 0x18, 0x15, 0x54, 0x5C, 0x73, 0x67, 0x50, 0x6D, 0x78, 0x3E, 0x1C, 0x2A, 0x76, 0x6E, 0x5B, 0x39, 0x30, 0x0F, 0x40, 0x00 }; // ASCII table [0x20 - 0xFF] /********************************************************************************************/ /* Test - minimalize power consumption of MSP430G2211 */ /* */ /* I use one character from the display LCD-S301C31TR, connected to port 1 */ /* P1.0 = Seg.A1, P1.1 = Seg.B1, P1.2 = Seg.C1, P1.3 = Seg.D1, */ /* P1.4 = Seg.E1, P1.5 = Seg.F1, P1.6 = Seg.G1, P1.7 = COM */ /* */ /* Power consumption is 76uA/3.5V, 65uA/3V, 33uA/1.5V (problem is RC of P1.3) */ /* Without P1.3 power consumption is 3.2uA/3.5V, 2.7uA/3V, 1.35uA/1.5V */ /********************************************************************************************/ int main( void ) { unsigned int i, j; WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer to prevent time out reset BCSCTL3 |= LFXT1S1; // VLOCLK enable (my VLOCLK worked at ~~10kHz) TACCR0 = 50u - 1u; // 10kHz/200Hz = 50 - interrupt every 5msec (200Hz) TACTL |= TASSEL_1 + ID_0 + MC_1; // Timer A clock source select: 1 - ACLK = VLOCLK // Timer A input divider: 0 - /1 // Timer A mode control: 1 - Up to CCR0 TACCTL0 = CCIE; // Capture/compare interrupt enable __enable_interrupt(); //P1DIR = 0xFF; // Set all P1 to output direction // - alternative - P1DIR = 0xFF - BIT3; // Set all P1 to output direction (without P1.3) for(; // Never ending story { for(i=0; i<(128-32); i++) // Browse ASCII table chars [0x20 - 0xFF] { for(j=0; j<100; j++) // Any character displayed 0.5 sec { if(P1IN & BIT7) P1OUT = FONT[i]; else P1OUT = ~FONT[i]; __bis_SR_register(LPM3_bits); // ZZZZZZZZZzzzzzzz.......... // CPU, MCLK, SMCLK, DCO are disabled, ACLK are active } } } } #pragma vector = TIMERA0_VECTOR // Timer A CC0 __interrupt void DELAY(void) { __bic_SR_register_on_exit(LPM3_bits); // WAKE UP, BABY !!! }
OK. The problem is here, what is the solution?
1) Do not use P1.3 (not good, this small cheap chips have a few pins ...)
2) Move your lovely chip out of the Launchpad to Breadboard. Thanks to SpyBiWire you need only four wires ...
3) Simply ignore this problem
4) Modify your Launchpad to fix this issue
Modify. But how?
My suggestion is: break the route from C34/R24 to pin P1.3 of IC1 socket. Remove pinheader J5. Drill two new holes between S2 and J5. Solder a new, six-pin header at location J5. Use two new pins on the pinheader for detachable connection from C34/R24 to button S2. Route S2 to P1.3.
And that is all. End of story.
-
zeke got a reaction from P!-Ro in Flashing the missing DCO calibration constants
Hi Guys,
I wanted to tack on my calibration code that I successfully used to calibrate my G2231 device.
It's almost exactly like naturetm's code. The only difference is the setDCO() function has a little more fine tuning in it.
Take a look and notice that the setDCO() function is slightly different. I stole the idea from a post aBUGSworstnightmare made on the ti.com website. Here's the link.
//****************************************************************************** // MSP430F20xx Demo - DCO Calibration Constants Programmer // // NOTE: THIS CODE REPLACES THE TI FACTORY-PROGRAMMED DCO CALIBRATION // CONSTANTS LOCATED IN INFOA WITH NEW VALUES. USE ONLY IF THE ORIGINAL // CONSTANTS ACCIDENTALLY GOT CORRUPTED OR ERASED. // // Description: This code re-programs the F2xx DCO calibration constants. // A software FLL mechanism is used to set the DCO based on an external // 32kHz reference clock. After each calibration, the values from the // clock system are read out and stored in a temporary variable. The final // frequency the DCO is set to is 1MHz, and this frequency is also used // during Flash programming of the constants. The program end is indicated // by the blinking LED. // ACLK = LFXT1/8 = 32768/8, MCLK = SMCLK = target DCO // //* External watch crystal installed on XIN XOUT is required for ACLK *// // // MSP430F20xx // --------------- // /|\| XIN|- // | | | 32kHz // --|RST XOUT|- // | | // | P1.0|--> LED // | P1.4|--> SMLCK = target DCO // // A. Dannenberg // Texas Instruments Inc. // May 2007 // Built with CCE Version: 3.2.0 and IAR Embedded Workbench Version: 3.42A //****************************************************************************** //#include "msp430x20x1.h" // do not forget to change this according to the device you're using #include #define DELTA_1MHZ 244 // 244 x 4096Hz = 999.4Hz #define DELTA_8MHZ 1953 // 1953 x 4096Hz = 7.99MHz #define DELTA_12MHZ 2930 // 2930 x 4096Hz = 12.00MHz #define DELTA_16MHZ 3906 // 3906 x 4096Hz = 15.99MHz unsigned char CAL_DATA[8]; // Temp. storage for constants volatile unsigned int i; int j; char *Flash_ptrA; // Segment A pointer void Set_DCO(unsigned int Delta); void main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop WDT BCSCTL3 |= XCAP_3; // Launchpad watch crystals need ~12.5 pF for (i = 0; i < 0xfffe; i++); // Delay for XTAL stabilization P1OUT = 0x00; // Clear P1 output latches P1SEL = 0x10; // P1.4 SMCLK output P1DIR = 0x11; // P1.0,4 output j = 0; // Reset pointer Set_DCO(DELTA_16MHZ); // Set DCO and obtain constants CAL_DATA[j++] = DCOCTL; CAL_DATA[j++] = BCSCTL1; Set_DCO(DELTA_12MHZ); // Set DCO and obtain constants CAL_DATA[j++] = DCOCTL; CAL_DATA[j++] = BCSCTL1; Set_DCO(DELTA_8MHZ); // Set DCO and obtain constants CAL_DATA[j++] = DCOCTL; CAL_DATA[j++] = BCSCTL1; Set_DCO(DELTA_1MHZ); // Set DCO and obtain constants CAL_DATA[j++] = DCOCTL; CAL_DATA[j++] = BCSCTL1; Flash_ptrA = (char *)0x10C0; // Point to beginning of seg A FCTL2 = FWKEY + FSSEL0 + FN1; // MCLK/3 for Flash Timing Generator FCTL1 = FWKEY + ERASE; // Set Erase bit FCTL3 = FWKEY + LOCKA; // Clear LOCK & LOCKA bits *Flash_ptrA = 0x00; // Dummy write to erase Flash seg A FCTL1 = FWKEY + WRT; // Set WRT bit for write operation Flash_ptrA = (char *)0x10F8; // Point to beginning of cal consts for (j = 0; j < 8; j++) *Flash_ptrA++ = CAL_DATA[j]; // re-flash DCO calibration data FCTL1 = FWKEY; // Clear WRT bit FCTL3 = FWKEY + LOCKA + LOCK; // Set LOCK & LOCKA bit while (1) { P1OUT ^= 0x01; // Toggle LED for (i = 0; i < 0x4000; i++); // SW Delay } } void Set_DCO(unsigned int Delta) // Set DCO to selected frequency { unsigned int Compare, Oldcapture = 0; BCSCTL1 |= DIVA_3; // ACLK = LFXT1CLK/8 TACCTL0 = CM_1 + CCIS_1 + CAP; // CAP, ACLK TACTL = TASSEL_2 + MC_2 + TACLR; // SMCLK, cont-mode, clear while (1) { while (!(CCIFG & TACCTL0)); // Wait until capture occured TACCTL0 &= ~CCIFG; // Capture occured, clear flag Compare = TACCR0; // Get current captured SMCLK Compare = Compare - Oldcapture; // SMCLK difference Oldcapture = TACCR0; // Save current captured SMCLK if (Delta == Compare) break; // If equal, leave "while(1)" else if (Delta < Compare) { DCOCTL--; // DCO is too fast, slow it down if (DCOCTL == 0xFF) // Did DCO roll under? if (BCSCTL1 & 0x0f) BCSCTL1--; // Select lower RSEL } else { DCOCTL++; // DCO is too slow, speed it up if (DCOCTL == 0x00) // Did DCO roll over? if ((BCSCTL1 & 0x0f) != 0x0f) BCSCTL1++; // Sel higher RSEL } } TACCTL0 = 0; // Stop TACCR0 TACTL = 0; // Stop Timer_A BCSCTL1 &= ~DIVA_3; // ACLK = LFXT1CLK }
Concerning the mods that were made to the cmd file, I just threw them into the default files because I know that I'm going to forget to made the project edits that are suggested in the first post above.
Just calibrate the g2231 first then use the code after.
-
zeke got a reaction from Dee-J_ONUR in 1-Wire Reset Command sample code
Hi Guys,
So, after calibrating the 16Mhz DCO using my code (Here's a link. It's below NatureTM's code), I have a rock solid 16MHz DCO.
Now I can create a reliable 1us delay routine that is required for proper 1-Wire interfacing. Here's an article that shows you the desired waveforms.
By the way, Touch tried porting the Arduino 1-Wire code to the Launchpad without success. The reason why it failed is due to the fact that the Arduino runs at 16MHz and the stock Launchpad board runs at 1MHz.
Here's my code that I used to generate an inverted version of the 1-Wire Reset command on P1.1 of the Launchpad.
//****************************************************************************** // MSP430G2xx1 Demo - Basic Clock, Output Buffered SMCLK, ACLK and MCLK/10 // modified to create a One Wire reset pulse train on P1.1 // // Description: Buffer ACLK on P2.0, default SMCLK(DCO) on P1.4 // // ACLK = LFXT1 = 32768, MCLK = SMCLK = DCO set to 16MHz after calibrating it. // // External watch crystal installed on XIN XOUT is required for ACLK // // MSP430G2xx1 // ----------------- // /|\| XIN|- // | | | 32kHz // --|RST XOUT|- // | | // | P1.4/SMCLK|-->SMCLK = Default DCO // | P1.1|-->MCLK/10 = DCO/10 // | P1.0/ACLK|-->ACLK = 32kHz // // J. Voth // Nine Micron // January 2011 // Built with CCS Version 4.2.1 //****************************************************************************** #include #define delayMicroseconds(n) __delay_cycles(n<<4) void main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop Watchdog Timer BCSCTL1 = CALBC1_16MHZ; // Set range DCOCTL = CALDCO_16MHZ; // Set DCO step + modulation P1DIR |= 0x1F; // P1.0,1,2,3 and P1.4 outputs P1SEL |= 0x11; // P1.0,4 ACLK, SMCLK output while(1) { // drive P1.1 high for ~480us P1OUT |= 0x02; // activate output delayMicroseconds(480); // drive P1.1 high for ~480us P1OUT &= ~0x02; // deactivate output // pulse p1.2 high for 70us P1OUT |= 0x04; // activate P1.2 output delayMicroseconds(70); P1OUT &= ~0x04; // deactivate P1.2 output // Do nothing for the remainder of the time slot delayMicroseconds(410); } }
I modeled it on the Basic Clock Demo program from TI because you can scope the DCO/MCLK frequency on P1.4 as a sanity check. If your DCO isn't calibrated then a scoping of P1.4 will make that plain to you.
I also generate a 70us pulse on P1.2 because that is how long you have to wait until reading the 1-Wire bus for a response.
To properly make use of this code, the 1-Wire bus interface will have to be a two pin version. The addition of a transistor (or FET) will invert the TX signal and thus make everything okay.
Take a look and tell me what you think.
-
zeke got a reaction from jsolarski in delay function
I tried the for() loops and calls to __delay_cycle(n) but nothing was remotely predictable.
I had to calibrate my g2231 before any sort of delay routine was reliable when the DCO was set to anything other than 1MHz.
The O'scope revealed to me that, once calibrated, the __delay_cycle(n) routine was bang on with every number I threw at it.
Yes, I realize that I'm using CCS4 and not mspgcc but I thought that this info would be useful to someone.