Jump to content

Recommended Posts


I have an LCD working, and I also have an adc working to get voltage from a potentiometer.


I am able to display adc values on the LCD, and they change when I change the value of the pot.


But I am stuck with one thing, I know that it is a 10bit adc, which means it can only get 0x3FF different values of data.

I have a DMM connected to the voltage from the pot, that same voltage is going to the adc on the msp340.

Here are some of the values that I got:

1.5V-------->0x3FD~(F)  -----> Anything below 1.5v is not detected by the adc.

Does anyone know of a way to get the adc to read the full range of the 5v?




Link to post
Share on other sites



AFAIK, MSP max input value for the ADC is Vcc, so I am surprised to see a table with a 5V reading value. You would normally need a resistor divider or something similar to "measure" DC values higher than Vcc.


Another point is that I have normally seen that ADC gives HEX values near 3FF when input voltage is Vcc, but your table seems to be reverse order.


So I would suggest to share  your basic circuit schema and ADC mapping.


Best regards

Link to post
Share on other sites

That makes sense, I did not considered that the msp430 runs on 3.6v. 


And I had my multimeter hooked up wrong, so yes when the voltage reaches 3.6 the value on the LCD is 0x03FF.




One more thing, I am printing hex values to my LCD, and I have been trying to figure out how to display the decimal equivalent.

For example,
If I get 0x0939 I would like to be able to display 2361.
Better yet, it would be awesome to be able to display 2.36



I know that there is a way, but it has been a while since I worked with LCD's.




Link to post
Share on other sites

displaying decimal is straightforward, and there are several ways that are quick. The most appropriate depends on the available hardware.


Presuming that you want something lighter than the standard C output tools (printf and the like declared in the stdio.h header)


Three most common are recursive/stack based decomposition, decompose into an array, or use a table of powers.


The first two require resources that are expensive on a low end MSP430 (need division, modulo, and extra RAM, and build the base ten value from the least significant end. On a higher power processor, they have the advantage of simplicity), so a table of powers it is...


Fisrt, you know the greatest power of ten you need, so the table is easy:


unsigned int powers[]={1,10,100,1000};


Now, we use repeated subtarcation to find the digits. THey come out in high to low sig order, so we can print them as they come. Simplest method prints leading zeroes....

(this is not the most elegant code, but it is, hopefully, clear)



// n contains the value to print. it is destructed in the print process

int i=3;  // most dig digit value

char j;

while (i>=0) { // count off digit weights


   while (n>=powers) {j++; n-=powers;} // count how many times weight can be subrtacted from value

   OUTPUT_CHAR(j); // whatever function you use to send digit char to output device




Simple. functional. minimal code size. A little work with a flag to eliminate the leading zeroes.


Putting the point in requires only an additional test in the outer loop, as it always goes the same place.


The hardest part is converting from the int [0..1023] to the appropriate scaled value, if you are trying to produce the actual voltage measure. Depending on the scale you want, this can be easy or difficult. I try to avoid the need for this scaling if I can, but when I can't, my next choice is fix the scale to the most convenient I can, such as max reading is 10.23V using a voltage divider so I need only put the decimal point in the right place.

Next choice of scale is one where power-of-two division arithmetic does the job, such as max at 5.115V.

If I must use arbitrary scale, it gets interesting. I'll spend a bit of time trying to special case the job before going to mult and division, or, worse, floating point. That is beyond the scope of where I wnt to go now, but I can elaborate with an example from the DS18B20 temp sensor if you need. (produces degC. Conversion to degF is amazingly simple, but unobvious)

Link to post
Share on other sites

If I get the chance, i'll follow up when I get to my home machine. mobile right now..


SDhort (and incomplete) form: the DS18B20 (and similar) have integral ADC and communicate by a 'one wire' interface. You get degC reading as a signed value in 16ths of a degree.


Conversion to degF is nominally *9/5+32. To avoid mult and div by values that arn't powers of 2, a little work goes in. I eventually came to *18/10+32. Eliminate the/10, and go with *18+320 to get degF in tenths. *18 is easy.... *16 is a power of 2, and therefore a left shift. *18 is *16 + *2, so it is shift left 3 times, add orig val, and shift one more time.


The orig is in sixteenths, so shift right 4 times to correct for this to make a whole number.


It is organized a bit differently for optimization and to prevent overflow, but this is the essence. Instead of several hundred or maybe a thousand cycles for mult and div, or, worse, using floating point, the whole process takes about 50 cycles. Could be brough a little lower in assembly, maybe.

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.

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