Jump to content
43oh

Recommended Posts

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...

 

 

 

Link to post
Share on other sites

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);
Link to post
Share on other sites


#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;

}

 

 

Link to post
Share on other sites

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;
}
Link to post
Share on other sites

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

Link to post
Share on other sites

 

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)
}
Link to post
Share on other sites

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:

Link to post
Share on other sites

 

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?

Link to post
Share on other sites

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.

Link to post
Share on other sites

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" ? 

Link to post
Share on other sites

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.

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...