muzay 0 Posted June 28, 2013 Share Posted June 28, 2013 hi everyone, thanks to Nate Zimmer Uart example, i could achieve to send string over uart. But i have send ACD values to UART. ADC has 10 bit output. How could i transmit the ADC data? Can i send directly? let say ---------------------------------- value=ADC10MEM; UART_TX(unsigned int value ?); // void UART_TX(int * value) // Define a function which accepts a character pointer to an array { unsigned int i=0; while(value) // Increment through array, look for null pointer (0) at end of string { while ((UCA0STAT & UCBUSY)); // Wait if line TX/RX module is busy with data UCA0TXBUF = value; // Send out element i of tx_data array on UART bus i++; // Increment variable for array address } } ---------------------------- this code gives me always the same uart data independent from the ACD output, probably its not the correct way of reading ADC memories. I am not good at coding by the way, any suggestion would be appreciated, thank you all... Quote Link to post Share on other sites
roadrunner84 466 Posted June 28, 2013 Share Posted June 28, 2013 I think you're reading the ADC correctly, but have you set up the ADC to do the sampling? UART_TX() seems to accept character arrays (ie: strings), but you pass it an integer value. First convert the integer to a character string before passing it to UART_TX() unsigned short value=ADC10MEM; char text[6]; // Longest string is "65536", which takes 6 characters (including the null termination) itoa(value, text, 10); // convert the value to a text string in base 10 numbers UART_TX(text); muzay 1 Quote Link to post Share on other sites
RobG 1,892 Posted June 28, 2013 Share Posted June 28, 2013 #include "msp430g2553.h" unsigned char txData[6] = {0,0,0,0,'\r','\n'}; void binaryToASCII(unsigned int n, unsigned char * digits); void main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop WDT BCSCTL1 = CALBC1_1MHZ; DCOCTL = CALDCO_1MHZ; P1SEL = BIT2; // P1.2 is TXD P1SEL2 = BIT2; UCA0CTL1 |= UCSSEL_2; UCA0BR0 = 104; UCA0BR1 = 0; UCA0MCTL = UCBRS_1; UCA0CTL1 &= ~UCSWRST; ADC10CTL0 = ADC10SHT_2 + ADC10ON + ADC10IE; ADC10CTL1 = INCH_0; // P1.0 analog input ADC10AE0 |= BIT0; CCTL0 = CCIE; // CCR0 interrupt enabled CCR0 = 6400; // sample every 50ms TACTL = TASSEL_2 + MC_1 + ID_3; // SMCLK/8, upmode _bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/ interrupt } #pragma vector=ADC10_VECTOR __interrupt void ADC10_ISR(void) { binaryToASCII(ADC10MEM, txData); char c = 0; while(c < 6) { while (!(IFG2 & UCA0TXIFG)) ; UCA0TXBUF = txData[c]; c++; } } // Timer A0 interrupt service routine #pragma vector = TIMER0_A0_VECTOR __interrupt void Timer_A (void) { ADC10CTL0 |= ENC + ADC10SC; } void binaryToASCII(unsigned int n, unsigned char * digits) { __asm(" clr R14"); __asm(" rla R12"); __asm(" rla R12"); __asm(" rla R12"); __asm(" rla R12"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" mov.b R14, 3(R13)"); __asm(" swpb R14"); __asm(" mov.b R14, 1(R13)"); __asm(" rra R14"); __asm(" rra R14"); __asm(" rra R14"); __asm(" rra R14"); __asm(" mov.b R14, 0(R13)"); __asm(" swpb R14"); __asm(" mov.b R14, 2(R13)"); __asm(" and #0x0F0F, 0(R13)"); __asm(" and #0x0F0F, 2(R13)"); __asm(" add.b #0x30, 3(R13)"); __asm(" tst.b 0(R13)"); __asm(" jnz l1"); __asm(" mov.b #0x20, 0(R13)"); __asm(" tst.b 1(R13)"); __asm(" jnz l2"); __asm(" mov.b #0x20, 1(R13)"); __asm(" tst.b 2(R13)"); __asm(" jnz l3"); __asm(" mov.b #0x20, 2(R13)"); __asm(" jmp l4"); __asm("l1:"); __asm(" add.b #0x30, 0(R13)"); __asm("l2:"); __asm(" add.b #0x30, 1(R13)"); __asm("l3:"); __asm(" add.b #0x30, 2(R13)"); __asm("l4:"); return; } muzay 1 Quote Link to post Share on other sites
roadrunner84 466 Posted June 28, 2013 Share Posted June 28, 2013 From this slab of assembly language I understand that your compiler does not ship the standard function itoa? You could do this in C code as well, you know... void intToAscii(unsigned short num, char* text) { int index = 0; const unsigned short decDigits[5] = {10000, 1000, 100, 10, 1}; if (num == 0) { text[0] = '0'; text[1] = 0; return; } for(int digits = 0; digits < 5; ++digits) { text[index] = '0'; while(num >= decDigits[digits]) { num -= decDigits[digits]; text[index]++; } if ((index != 0) || (text[index] != '0')) // comment this line to pad the string with zeroes index++; } text[index] = 0; } muzay 1 Quote Link to post Share on other sites
RobG 1,892 Posted June 28, 2013 Share Posted June 28, 2013 You know what they say about opinions, do you? Quote Link to post Share on other sites
spirilis 1,265 Posted June 28, 2013 Share Posted June 28, 2013 lol, come to think of it, I feel embarrassed that I didn't know mspgcc had itoa/utoa/ltoa in its libc. Quote Link to post Share on other sites
RobG 1,892 Posted June 28, 2013 Share Posted June 28, 2013 Yes, CCS doesn't have itoa, only ltoa Convert 1024: ltoa - 3,630 clock cycles intToAscii (rr84) - 400 clock cycles (you may want to check your code, I didn't get expected results) binaryToASCII (robg) - 100 clock cycles Convert 15: Itoa - 1,870 intToAscii - 380, no result binaryToASCII - 110 muzay 1 Quote Link to post Share on other sites
muzay 0 Posted June 28, 2013 Author Share Posted June 28, 2013 I think you're reading the ADC correctly, but have you set up the ADC to do the sampling? UART_TX() seems to accept character arrays (ie: strings), but you pass it an integer value. First convert the integer to a character string before passing it to UART_TX() unsigned short value=ADC10MEM; char text[6]; // Longest string is "65536", which takes 6 characters (including the null termination) itoa(value, text, 10); // convert the value to a text string in base 10 numbers UART_TX(text); Thank you, this worked well forme, just instead of itoa, i've used sprintf..i was not sure which ".h" to add to work with itoa... here is my code... //Nate Zimmer UART example // Press button to print hello to terminal #include <msp430g2553.h> // System define for the micro that I am using #include "stdio.h" #define RXD BIT1 //Check your launchpad rev to make sure this is the case. Set jumpers to hardware uart. #define TXD BIT2 // TXD with respect to what your sending to the computer. Sent data will appear on this line #define BUTTON BIT3 unsigned short value; char text[7]; // Longest string is "65536", which takes 6 characters (including the null termination) void UART_TX(char * tx_data); // Function Prototype for TX //void UART_TX(unsigned int * value); // Function Prototype for TX void main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop Watch dog timer BCSCTL1 = CALBC1_1MHZ; // Set DCO to 1 MHz DCOCTL = CALDCO_1MHZ; P1DIR &=~BUTTON; // Ensure button is input (sets a 0 in P1DIR register at location BIT3) P1OUT |= BUTTON; // Enables pullup resistor on button P1REN |= BUTTON; P1SEL = RXD + TXD ; // Select TX and RX functionality for P1.1 & P1.2 P1SEL2 = RXD + TXD ; // UCA0CTL1 |= UCSSEL_2; // Have USCI use System Master Clock: AKA core clk 1MHz UCA0BR0 = 104; // 1MHz 9600, see user manual UCA0BR1 = 0; // UCA0MCTL = UCBRS0; // Modulation UCBRSx = 1 UCA0CTL1 &= ~UCSWRST; // Start USCI state machine // set adc ADC10CTL1 = INCH_5 + ADC10DIV_3 ; // Channel 5, ADC10CLK/4 ADC10CTL0 = SREF_0 + ADC10SHT_3 + ADC10ON + ADC10IE; //Vcc & Vss as reference ADC10AE0 |= BIT5; ADC10CTL0 |= ENC + ADC10SC; // Sampling and conversion start, single measure! while(1) // While 1 is equal to 1 (forever) { if(!((P1IN & BUTTON)==BUTTON)) // Was button pressed? { ADC10CTL0 |= ENC + ADC10SC; //value = ADC10MEM; sprintf(text, "%d\n", ADC10MEM); UART_TX(text); // UART_TX("hellow world"); // send ADC value __delay_cycles(100000); //Debounce button so signal is not sent multiple times } } } void UART_TX(char * tx_data) // Define a function which accepts a character pointer to an array { unsigned int i=0; while(tx_data) // Increment through array, look for null pointer (0) at end of string { while ((UCA0STAT & UCBUSY)); // Wait if line TX/RX module is busy with data UCA0TXBUF = tx_data; // Send out element i of tx_data array on UART bus i++; // Increment variable for array address } } // ADC10 interrupt service routine #pragma vector=ADC10_VECTOR __interrupt void ADC10_ISR(void) { __bic_SR_register_on_exit(CPUOFF); // Clear CPUOFF bit from 0(SR) } Quote Link to post Share on other sites
muzay 0 Posted June 28, 2013 Author Share Posted June 28, 2013 With the code i posted just above (with the help of you ofcourse :thumbup: ) i dunno my sampling frequency and also adc resolution in terms of Voltages...Analog data is 200 Hz maximally. so i need about maximum 1 kHz sampling rate, i think. How can i arrange sampling frequency and ADC resolution for my code? thank you all :wave: Quote Link to post Share on other sites
muzay 0 Posted July 1, 2013 Author Share Posted July 1, 2013 I think you're reading the ADC correctly, but have you set up the ADC to do the sampling? UART_TX() seems to accept character arrays (ie: strings), but you pass it an integer value. First convert the integer to a character string before passing it to UART_TX() unsigned short value=ADC10MEM; char text[6]; // Longest string is "65536", which takes 6 characters (including the null termination) itoa(value, text, 10); // convert the value to a text string in base 10 numbers UART_TX(text); I could not get negative values from ADC with this code, is that because i used unsigned value, what should i do? Quote Link to post Share on other sites
roadrunner84 466 Posted July 1, 2013 Share Posted July 1, 2013 What kind of negative values do you expect? I've only used the ADC in a mode where it takes an analog value between 0 and 2.5 volts and returns to me a numeral representation of this value. You could use signed short if you want, but if the result is only between 0 and 1023 then the effect will be nil. You can scale the value to the desired range, either using a formula or using the map() function that is shipped with Energia. Quote Link to post Share on other sites
muzay 0 Posted July 1, 2013 Author Share Posted July 1, 2013 What kind of negative values do you expect? I've only used the ADC in a mode where it takes an analog value between 0 and 2.5 volts and returns to me a numeral representation of this value. You could use signed short if you want, but if the result is only between 0 and 1023 then the effect will be nil. You can scale the value to the desired range, either using a formula or using the map() function that is shipped with Energia. My analog data that i want to sample is between -2 and 2 volts and launchpad ADC is 10 bits which is bigger than 1 byte! so, should i use "signed long" ? Quote Link to post Share on other sites
RobG 1,892 Posted July 1, 2013 Share Posted July 1, 2013 ADC module can sample positive voltage only, you will have to use op amp if you want to measure negative voltage. Quote Link to post Share on other sites
muzay 0 Posted July 1, 2013 Author Share Posted July 1, 2013 ADC module can sample positive voltage only, you will have to use op amp if you want to measure negative voltage. upsssss! so i need to add a positive voltage, right? Quote Link to post Share on other sites
roadrunner84 466 Posted July 1, 2013 Share Posted July 1, 2013 You'll use an electrical circuit to scale the -2 to +2 volts to 0 to 2.5 volts, then the result will be in the 0 to 1023 range for the 10 bit ADC (0 to 4095 for 12 bit ADC), then scale the 10 bit value any way you like: I want to know wether the voltage is positive (in the 0 to 2 volt range), the scaled voltage will be in the 1.25 to 2.5 volt range, the read value in the 512 to 1023 range. So I can do "value >= 512". I want to scale the value to map in a single signed byte: 0 will become -128, 1023 will become 127: "value / 4 - 128" I want to scale the value to map in a signle signed short: 0 will become -32768, 1023 will become 32767 "value * 32 - 32768" I want to map the value so the number represents tenths of millivolts: 0 will become -20000, 1023 will become 20000 "value * 40000 / 1024 - 20000" etcetera. Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.