This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSP430G2553 Multiplication and Division with temp. sensor to Double 7-Segment Display, ASM

Other Parts Discussed in Thread: MSP430G2553

Hi, me and a partner are doing a simple project of reading a value off a TMP35G, sending it to msp430g2553 adc10, taking that adc10memory value, and the problem starts here at the conversion and pushing it out to the double 7-seg.

The Physical hookup of the circuit is fine. P2OUT account for both bcd encoders to the double 7_segment displays.

The code works up to us doing the math.

With the ADC10 a value is read from the tmp35g from 0-1023 (0V-3.6V) and thrown in the adc10memory. We take that memory out and throw it into a register to do math to, R14.... and here is where we fail.

The msp430g2553 does not have a hardware multiplier but we must use it because of the class. So the equation to convert it is taking the read value....

'Value' / 1024(steps) x 3.6V (reference value). The new value in Volts is divided by .1mV per degree celsius, otherwise flipping it around the newV x 10 = XX degrees celsius.

Our problem is that the g2553 has only 16bits else known as XXXXh, and when we divide it with the above equation the, say calculated value of 1.8V to 18 degrees celsius loses the 8 when all is said and done.
To make up for some shortfalls of the g2553 we put the multiplication of 3.6 and 10 together to make the initial value to be divided bigger, but 1024 still brings it down to 000X.Yh, and the Y is lost because the MC doesn't have a spot for the Y.

We read horner's method in the TI forums, and it helped.... but it didn't help us figure out how to hold onto that ones digit value.

Any help to explain horner's method, show us how to hold onto the 1s digit value, cleverer math, would be nice.

PS i tried taking the value and then taking the 10s digit value by itself and saving it to a register, and then 1s digit value and saving it to a register, but if the 1s digit goes above 9 it turns into the alphabet so that same method of shifting left until the 1s digit is left, and then shifting it down back to the 1s digit place, and then taking that register, and after shifting the tens digit into its second hex value i would add the 1s digit to that 10s register to get say 1A which I'd send out to p2out. Celsius doesn't go into the alphabet.... -_- 

We were using horner's method if rla-ing and rra-ing and add-ing and sub-ing and we got better, but are still failing in it!

Help wanted.

  • Jared sarff said:

    We were using horner's method if rla-ing and rra-ing and add-ing and sub-ing and we got better, but are still failing in it!

    Help wanted.

     Hi this is an home work and class job than engeener , you have to grasp how character and binary are different in both assembly or C.

     You are using C so you don't have access of floating point you need so you have to scale your number calculus to integer, 16bit are not enough so you must extend to 32 bit long.. It is very simple and it is done from beginning of automatic binary calculator.

     This was where digital revolution started:

    http://en.wikipedia.org/wiki/Konrad_Zuse

     A lot of time and knowledge grown from early time ...

     Help is how to acquire background and learn how to solve.

  • I looked at the link and read about Zuse a bit, but that didn't help nudge me in a helpful direction.
    I am using assembly, and as far as I know the msp430g2553 only has 16 bits. I can't tradeout for another microcontroller because the class 'demands' the G2553.
  • Is using assembly a requirement? Why?
  • Jared sarff said:
    I looked at the link and read about Zuse a bit, but that didn't help nudge me in a helpful direction.

     If you wish a ready solution it cannot help at all, it was just to point what where able to do electromechanical calculator (programmable too) a lot of time ago before electronic revolution, so algoritm are know at that time and multiple bit/byte extension of result are not a problem.

     I wish you think about how to solve problem, you are in a class and If I got my pupils do a similar they get at oral test to explain all till they learn!!

     It is basic knowledge, I think it is not question to use floating point, but you can multiply number and think about, so in the past I never used EXPEN$$$IVE and power hungry floating point unit .

     If you do some scaling of your number and use good number than decimals are difficult to crunch to microcontroller then you get a fast clean code.

    Jared sarff said:
    I am using assembly, and as far as I know the msp430g2553 only has 16 bits. I can't tradeout for another microcontroller because the class 'demands' the G2553

     I never proposed to use a museal machine but to think how old discipline is so all about integer number was known.. Just learn about:

    this is a first reference
    en.wikipedia.org/.../Binary_number

    and this for long division and how to manage..

    en.wikipedia.org/.../Division_algorithm

    but this is the worst way you are in base 2 not 10 and ... division is slow.. so scaling the good coefficient between prime numbers is the best...

     Sorry no ready to use code. I am experienced programmer approaching 40 yr coding, this require just write down code but I don't wish bypass teaching rule.

  • Jared sarff said:

    PS i tried taking the value and then taking the 10s digit value by itself and saving it to a register, and then 1s digit value and saving it to a register, but if the 1s digit goes above 9 it turns into the alphabet so that same method of shifting left until the 1s digit is left, and then shifting it down back to the 1s digit place, and then taking that register, and after shifting the tens digit into its second hex value i would add the 1s digit to that 10s register to get say 1A which I'd send out to p2out. Celsius doesn't go into the alphabet.... -_- 

     Repeat hint..

    learn how to convert between bases and how different are number letter ASCII and binary values of them.

     This reveal me you don't have knowledge of how number and character work.

     a character is some of 'a' 'b' 'c', '0' '1' '2'... or wichever alphabet you use..

     Binary number is a value...

     Binary value of 0 is 0 binary of 0x5a is 90

    Binary value of character '1' is 49 or 0x31 not 1

     so.. start display letter and number , display just a single figure from binary 0 to 9.. then learn how to convert and do number display. It is not required have division, you can use other trick.

    try this link if can help you learn more form partecipation to a teaching blog.

    http://www.coder-tronics.com/

  • // start with ADC10 reading in R14
            MOV     &ADC10MEM,R14
            RLA     R14
            RLA     R14
            MOV     R14,R15
            RLA     R14
            RLA     R14
            RLA     R14
            ADD     R15,R14
            ADD     #0x0200,R14
            AND     #0xFC00,R14
            SWPB    R14
            RRA     R14
            RRA     R14
    // end up with degrees C in R14

  • old_cow_yellow said:
    // start with ADC10 reading in R14 MOV &ADC10MEM,R14

     Uhm. I was asking me why OCY posted this code, it readed and it is ok.

    old_cow_yellow said:
    // end up with degrees C in R14

     Right conversion applied are the needed by case, but why provide ready to use code?

    ok this is cryptic enough with all scaling done as an experienced programmer ca apply, it was like I suggested but not commented so it is a great puzzle.

      OCY I like a lot, great exercise and yes this is great integer number theory art.

     OCY, you suggested hacker level code in classroom, so get your place punished too, Jared sarff at Oral examination so please explain how this code work or better comment it! ;)

     It is working as a charm so don't try mess about and start your new job, as you can see 16 bit are enough.

  • Thanks for the comments.
    That code actually come out straight from Jared sarff's mouth. I only added a little rounding. I intentionally turned off the "optimizer" so that it is easier to understand. It could have been smaller and faster.
  • old_cow_yellow said:
    Thanks for the comments.

    OCY, year after year is a pleasure read you.

    old_cow_yellow said:
    That code actually come out straight from Jared sarff's mouth.

     Uh, I am too old  and got distracted? Yes but from I just seen about Horners polynomial optimization, I missed code. Sorry OCY where it was happened? :D

    old_cow_yellow said:
    I only added a little rounding.

     Just little little ...

    old_cow_yellow said:
    I intentionally turned off the "optimizer" so that it is easier to understand. It could have been smaller and faster

     Uhm.. so you wish also remove AND or adjust to deep polynomial? I think this is enough to and using this code expose to an high risk when has to be explained.

     Tony.. don't be worst more, wait after explanation. I see you wish cut code from ;)

     So now we have at output of code a binary number ranging from 0 to 63 representing temperature.. how can this be converted to bcd to save our poor student are in the pain of foreign mathematical language?

    example temperature = 36 (decimal)

    trivial one take two variables (register) and set to zero

    R10    R11

    0          0

    add ten to first and 1 to second

    R10    R11

    10        1

    is R10 greater than  temperature?

    (Yes ended, )No continue

    add ten to first and 1 to second

    R10    R11

    20        2

    is R10 greater than  temperature?

    (Yes ended,) No continue

    R10    R11

    30        3

    is R10 greater than  temperature?

    (Yes ended,) No continue

    R10    R11

    40        4

    is R10 greater than temperature?

    Yes ended,(No continue)

     it is ended so now it need be adjusted

    Subtract 10 from R10 and 1 from R11

    subtract R10 from temperature, this is your unit of temprature

    R11 is contain tens figure of temperature

    R11= 3

    Temp= 36-30=>6

     this if understood also solve problem of bcd, use of bcd decoder is not a so clever idea, just port b was enough to display temperature but.. this is another question and problem was that.

    Tony and OCY too no hack code for now please. ;)


    (Yes ended, )No continue

  • The Celsius formula is: ADC10MEM * 423 / 1024 - 278

    if you reorder it for a less rounding down error and overflow chance: (ADC10MEM - 673) * 423 / 1024
    (if you need decimal point, probably should be -67)*529/128 and then add the decimal point in the dec-to-ascii routine)

    How to do the *423:
    msp430x2xx can only double itself math, RLA is actually ADD reg15,reg15 but as that still is only a single word instruction it's the same thing

    423= 110100111b
    So we need: *256 + *128 + *32 + *4 + *2 + *1

    [code not optimized for this exact calculation, but so you can use any values for other routines]

            mov.w  &ADCMEM10,R15 ; enter with value in R15 and return the result in R15
            sub.w  #673,R15    
            mov.w  R15,R14       ; *1 now done
            rla.w  R15           ; *2
            add.w  R15,R14       ; + *2 now done
            rla.w  R15           ; *4
            add.w  R15,R14       ; + *4 now done
            rla.w  R15           ; *8
            rla.w  R15           ; *16
            rla.w  R15           ; *32
            add.w  R15,R14       ; + *32 now done
            rla.w  R15           ; *64
            rla.w  R15           ; *128
            add.w  R15,R14       ; + *128 now done
            rla.w  R15           ; *256
            add.w  R15,R14       ; + *256 now done (so *423 is now done)
            
            swpb   R14           ; /256 now done
            mov.b  R14,R15       ; .b also removes the reminder that was at the top
            rra.w  R15           ; as we know the msb is 0, rra instead of rrc is better
            rra.w  R15           ; /1024 now done, result in R15
            

  • Tony Philipsson said:

    The formula is: ADC10MEM * 423 / 1024 - 278

    if you reorder it for a more integer friendly: (ADC10MEM - 673) * 423 / 1024

     Oh no Tony doubly punished too...

     You posted commented code also.. and what are the number you used? For what is 278? and it is double len than OCY one.

     Original was asking for multiply by 36 and OCY perform then scaling by 1024 so OCY was perfect on these numbers, result is in Celsius?

     I see you don't hacked RRA.W RRA.B too ;)

     From there more than was needed is hacked.. TONY you are a bad pupils suggesting more hard to understand  code.

  • It's not a hack, it's the only way to do it with limited math instructions the msp430x2xx have.
    and C does this same way for you behind closed doors.
  • Tony Philipsson said:
    It's not a hack, it's the only way to do it with limited math instructions the msp430x2xx have.

     Uh no, OCY was more short and as it said some more instruction can be removed..

    Tony Philipsson said:
    and C does this same way for you behind closed doors

     Uh.. not really.. see this..

    register int x,y;

    register char temperature;

    x=ADCMEM10;

    y=x<<=2;

    y+=x<<=3;

    y+=0x200;

    y/=0x100;

    temperature = (byte)y>>=2;

    it generate code very close to OCY one, yes you can write y=x*36; but this I think it call multiplication is less faster than...

     So take care about hacking, Tony did you see how to remove AND of OCY and BIC on your code?

    Edit Some shift where reversed.. so new code is as << first two not >> as I erroneously wrote...

  • > So take care about hacking
    No sure where you going with this, should I hack (optimization tricks) though it makes it less understandable?
    Like I said my routine is so you can understand how multiplications is just additions with the power of 2 values.
    And divisions should always be made with a single power of 2 value, adjust the multiplication value instead to get the 0.xxx value

    Also to easy to make changes for other values that may come up on other programs.

  • Tony Philipsson said:
    No sure where you going with this, should I hack (optimization tricks) though is makes it less understandable?

     Not really, that is same code of OCY but on C perspective, so it multiply by 4 then save and add result multiply by 32.. it add 512 to shift result then do a division by 256 so compiler use swb too and finally divide more by for so division by 1024 is complete...

     About hack I was referring about and clearing high byte, this can be saved using one time RRA.W then RRA.B it qutomatically clear high byte so result is in integer form...

     Yes C code appear near unreadable, that is integer optimized to perform scaling as from assembler perspective, I am using c as assembler so when I wish fast execution I do these tricks on C than in asm. I seen over time compiler is more clever than me, just need be guided to avoid some slow way.

  • Tony Philipsson said:
    swpb R14 ; /256 now done mov.b R14,R15 ; .b also removes the reminder that was at the top rra.w R15 ; as we know the msb is 0, rra instead of rrc is better rra.w R15 ; /1024 now done, result in R15

     Hey Tony, this is politically incorrect, I remember there was a BIC #0ff00,R15...

            swpb   R14           ; /256 now done
    ;;;; useless        mov.b  R14,R15       ; .b also removes the reminder that was at the top
            rra.b  R14           ; as we know the msb is 0, rra instead of rrc is better ----  this clear MSB so result is also scaled to
            rra.w  R14           ; /1024 now done, result in R14 
    

     Tony.. Hack is an art of lessening code and time.

     Here some amusing code:

    http://en.wikipedia.org/wiki/International_Obfuscated_C_Code_Contest

  • It's not useless as I wanted the result to use the same register as incoming and the transfer to that register also acts as the bic.w 0xff00
    and top of that is also a single word instruction and the bic.w is not.
    And what if you only want to /256? as I said this is a generic function.

    rra.b , what if the msbit in that byte is set?,
    it will trail down as if we are working on signed chars but we are working on unsigned, as I take it adc10mem is always unsigned.
    and the resulting Celsius is unsigned too?
    using rrc.b will work and will give the bonus of 17bit calculations.

            add.w  R15,R14       ; + *256 now done (so *423 done, overflow is OK if /512 or higher later)
            swpb   R14           ; /256 now done
            rrc.b  R14           ; c will be cleared/set from the add.w instruction above as it
                                 ; actually work correctly as the 17bit. As such the optimal division is /512
    

    And why do you call things hack?, using undocumented ops on the 6502 is a hack.
    These are optimizing's and actual instruction length have to be locked at to see what uses less and run fastest.

  • So with just slight little less conversion accuracy *212/512

            mov.w  &ADCMEM10,R12 ; enter with value in R12 and return the result in R12
            sub.w  #673,R12      ; or do -278 last 
            rla.w  R12           ; *2
            rla.w  R12           ; *4
            mov.w  R12,R14       ; set *4 now done
            rla.w  R12           ; *8
            rla.w  R12           ; *16
            add.w  R12,R14       ; + *16 now done
            rla.w  R12           ; *32
            rla.w  R12           ; *64
            add.w  R12,R14       ; + *64 now done
            rla.w  R12           ; *128
            add.w  R12,R14       ; + *128 now done (17bit math OK)
            swpb   R14           ; /256 now done
            rrc.b  R14           ; /512 now done, with 17bit math
            mov.b  R14,R12       ; optional, just so R12 in and R12 out 
    

  • Tony Philipsson said:

    So with just slight little less conversion accuracy *212/512

    
    

     Tony, yes you are good student and I appreciate also your reduction of polynomial strength by approximation at expense of granularity and quantization, but forever this is a problem, we got question from student of I suppose undergraduate not an engineer that must have these knowledge, I fear these pupils got no more than hint of cut and paste code leaving them just happy to avoided understand how things work.. and I bet we never see here with same name if they got not interested in argument and happy to learn about.

    So I discourage this also if we amused in a so quite OT meetings.

    Again software tricks on the past I/we developed a lot to do task with limited resources, OCY I felt is also coming from old computing era and we used punched card and tape too, we punched also by hand, today these are some things old nostalgic take in his knowledge. We have now MSP is more powerful than mainframe of old era but what is missed is ability to use. We used also integer conversion instead of floating point, so a simple uP with just add and subtract was able to do scaling with just shift and rotate. On some processor multiply and divide where present but still slow and integer Horner was forever the best solution.

     On last year I wrote a lot of  c program simulating all hardware of old computer and it run part on a Linux PC and  TI processor, other  part on an FPGA, Floppy controller never read write magnetics but a file on an external media where image of old device reside..

     To do these embedded rework complete knowledge of theory is the base and today school over the world is just dropping to arduino community of hobby happy to solve undergraduate job for free leaving student to an odd perception of jobs and not least never learned how to solve problems.

     This I think has to be a professional forum where industry person get here to exchange experience about MSP usage or solve strange behaviour of devices. If student are welcome never forget they MUST do homework. So I appreciate OCY but try limit solution in these cases, it is not an help than a damage to learning.

     Forever to address these problem a special area was necessary on forum, so C learning and Programming or school questions but they have to stay away from professional forum.

     This is not the vision of internal TI and mixing these argument forever is burdening forum.

     

  • So, you guys are great. I haven't been able to read the comments this weekend but I was notified in email how many there were. Before I even got to read these me and my partner 'finished' our program, not totally sure it works fine as the counting gets finicky here and there, but it counts down to 10'C Degrees (9ish is the lowest it can go as the TMP35 range is from 10'C-125'C, so at 9'c it starts to flip out and jump to 11 or 10 before dropping back down) and we got it to count up to 35'C with a hair dryer -aimed at only the tmp35 and not the rest of the circuit.

    We will look into the solutions of what some of you posted, and if we can understand it we may swap it out for a part of our code. Overall being said here is the code we wrote after studying Horner's Method. Before any tips from here.


    .cdecls C,LIST,"msp430g2553.h" ; cdecls tells assembler to allow
    ; the c header file

    ;------------------------------------------------------------------------------
    ; Initialize MSP430
    ;------------------------------------------------------------------------------

    .text ; program start
    .global _main ; define entry point

    _main mov.w #0280h,SP ; initialize stack pointer
    mov.w #WDTPW+WDTHOLD,&WDTCTL ; stop watchdog timer

    ;------------------------------------------------------------------------------

    mov.w #ADC10SHT_2+ADC10ON+ADC10IE+REFON,&ADC10CTL0

    mov.w #INCH_0,&ADC10CTL1 ; input channel 0

    ;------------------------------------------------------------------------------
    ; Select and configure inputs and outputs
    ;------------------------------------------------------------------------------

    bis.b #BIT0,&ADC10AE0 ; P1.0 as analog input A0
    mov.b #00h,P2SEL
    mov.b #0FFh,&P2DIR ; P2.0-7 output

    ;------------------------------------------------------------------------------

    Mainloop bis.w #ENC+ADC10SC,&ADC10CTL0 ; initiate conversion
    bis.w #CPUOFF+GIE,SR ; turn off CPU (enter low power mode 0)
    ; and enable interrupts - wait in low
    ; power mode until ADC sample is complete
    mov.w ADC10MEM,R12
    mov.w R12,R13
    rla.w R13 ;multiply by 3.6x10 = 36
    rla.w R13
    mov.w R13,R14 ;we guessed our reference voltage 3.6V at the time of writing this
    rla.w R13 ;this was before putting REFON in the circuit, so we should probably
    rla.w R13 ;change this?
    rla.w R13
    ; rla.w R13
    add.w R14,R13 ;end multiply by 36



    mov.w R13,R8
    rra.w R13 ;divide memory by 2
    rra.w R13 ;divide by 4
    rra.w R13 ;divide by 8
    rra.w R13 ;divide by 16
    rra.w R13 ;divide by 32
    rra.w R13 ;divide by 64
    rra.w R13 ;divide by 128, I got 001Bh here
    ; rra.w R13 ;divide by 256
    ; rra.w R13 ;divide by 512
    ; rra.w R13 ;divide by 1024
    ; rra.w R13 ;i got a 0001.Bh = 27, so I wanted to keep that 1B

    mov.w R13,R14
    rra.w R14 ;shift R14 to 0001 in this block of 4 right shifts
    rra.w R14 ;Getting 10's digit alone in R14
    rra.w R14 ;
    rra.w R14 ;

    rla.w R14 ;shift R134 to 0010 in this block of 4 left shifts
    rla.w R14 ;We now have our 10's digit.
    rla.w R14 ;
    rla.w R14 ;

    mov.w #0010h,R10 ;starting to get the 1's digit alone from the 10's digit
    mixed1s clrz
    cmp.w R10,R13 ;if R13 is less then decimal 10 (R10) then..
    jlo onealone ;jmp to onealone
    sub.w R10,R13 ;else subtract 16 decimal from the circuit until
    jmp mixed1s ;there is less then 16.

    onealone mov.w #000Ah,R10 ;R10 = 10 in decimal
    cmp.w R10,R13 ;
    jl THEN ;If R13 is less then 10 jmp to THEN...
    sub.w #000Ah,R13 ;Else subtract 10 from R13 and...
    add.w #0010h,R14 ;Add 1 to 10's digit
    THEN add.w R13,R14 ;Add what is or what is left in R13 to R14

    mov.w R14,R15
    OUT1 mov.w R15,P2OUT ;

    clrz ;Following block up to cmp is just a stall so we can see the 7-seg better
    mov.w #0FFFFh,R6
    TIMER dec.w R6
    cmp.w #0000h,R6

    jne TIMER

    jmp Mainloop ; start the sample process again

    ;------------------------------------------------------------------------------
    ; The interrupt service routine for the ADC10 interrupt
    ;------------------------------------------------------------------------------


    ADC10_ISR bic.w #CPUOFF,0(SP) ; when the ADC conversion is complete
    reti ; exit low power mode and resume processing

    ;------------------------------------------------------------------------------
    ; Interrupt Vectors
    ;------------------------------------------------------------------------------

    .sect ".reset" ; MSP430 RESET Vector
    .short _main
    .sect ".int05" ; ADC10 Vector
    .short ADC10_ISR

    .end

    Any critique of this code?
  • Using Assembly is not a requirement but as we started in assembly and I never learned C (yet! I will, just probably not while this class is running).
    We could use C or Assembly and stay away from Arduino.
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    // start with ADC10 reading in R14
            MOV     &ADC10MEM,R14
            RLA     R14
            RLA     R14
            MOV     R14,R15
            RLA     R14
            RLA     R14
            RLA     R14
            ADD     R15,R14
            ADD     #0x0200,R14
            AND     #0xFC00,R14
            SWPB    R14
            RRA     R14
            RRA     R14
    // end up with degrees C in R14

    I have up to *36 in our code and then the add by 0200 and fc00 and swpb flew over my head. We (partner and I) looked at swpb on Saturday before reading this today and all he said was, it makes big indian into little indian and reverse. (Not to lie i have learned very little about big and little endian?, i think that's its real name before doing a google search).

    I have seen things like #0x0200 but don't understand them yet. I know what # means, but why a 0x0200, or any general 0x or 0xYYYY number?I can guess that 0200 is 16^2x2 = 512 and fc00 = 61440+3072 = 64512 both base 10, but don't understand why you did that.

    So r14 is *36 then we.... add? and add? (is it more multiplying or just actually adding a certain number), we take our answer after that and flip it and divide by 4.

  • Jared sarff said:
    I have up to *36 in our code and then

     Ok, I seen it from, so you grasped first part till add of 512, why? So good also code must be understood also as mathematical and physics theory to solve and explain problems.

     Get back, you have a temperature sensor give temperature in term of 10mV/°C so for example 25°C result in 250mV.

    You have a 10 bit ADC resolution is in term of FS/2^nbit so 3.6/1024 -> each step measure 3.5mV so it can be a better idea t use internal calibrated reference of 1.5V where FS is around 150°C and greater resolution used on ADC, this case resolution go down to 1.5/1024 ->> 1.46mV, less approximation on quantization, is this Ok?

    When you use 3.6 as reference than example of 25°C set ADC near 71 (rounding of 71.11)

    multiply by 36 -> 2556

     What is wrong? Why Tony proposed a completely different scaling factor than yours was proposed by OCY?

     SWPB swap bytes on a word, so clearing the MSB you can simply get division by 256 in just one instruction...

     Don't care about endian big or little is not important swapping bytes on a word forever divide by 256 (0x100) if you clear the MSB part.

     dividing two more time by 2 this is the 1024 division in just three instruction...

     Byte instruction when applied to a register clean MSB then if register is reused MSB is zeroed.

     But now it is your time, what is wrong in your calculus? Are correct multiply by 36? or 360 or is better use another coefficient? V mV Full Scale voltage Temperature constants of sensor are on same coherent?

     Write formulae, post here for check then I suggest you change to 1.5V Vref than use VCC.

     Edit: Corrected some mistype and added two word

  • Jared sarff said:
    Any critique of this code?

      It seems you are on the right way of learning and experiment than ask for work done, I seen more perplexity on display first post than here, please just clean digit decoding from text I used or just comment.

     Style come from time but get clean when start.

     Other way are more efficient but this case it is enough, few cycle complete in few uS and no problem for a temperature, when you need low power you can use an LCD than LED.

     About decoder, just only after all is ok think about remove it, multiplexing is the better way to use just MSP430 and nothing more than an inverter or one more bit of another port is enough to direct drive. All can be done in just 8 9 bit, MSP or MSP and two MOS driving display one at a time.

     Apply KISS: All has to be done one thing at time, test it and only when it work for sure try add another part.

  • So here is my new code. How do you link stuff so it looks more original instead of funny looking?

    main.asm

    Well, anyways... a different group suggested they used the math of adc10mem*115/1024+10.
    .115 is because the tmp35 is 125 to 10'C so 125-10=115, 1024 for the steps, and 10 because the tmp doesn't start at 0'C but at 10'C.

    Furthermore, since I have changed what the reference voltage is (1.5V instead of 3.6) I have changed the starting equation to be *15 instead of *36. My new equation is simply adc10mem*15/1024+10. This suits the requirement the other group pointed out and my added in new reference voltage.
    The added 10'C at the end I think helped me clarify that

    -When in my original equation i was doing the whole math and ending up with 1.Bh, thus dropping the B since it doesn't fit on the 16bit register, i ended up with just 1'C. This was actually 11'C since I didn't add that automatic 'it starts at' 10'C.

    --This is still wrong because there is no way my house is at 11'C.

    -I will see how my new equation goes, and if it doesn't work I will consider looking at other options.
    On a different note:

    -I see now that swpb makes 0089h into 8900h and could again switch it back to 0089h.
    -I however did not understand how it divided by 256. I couldn't get it to work. (i only tried about 5 times or less though so maybe a little more trial and error and I could have understood it).

    -I added in an alarm that will go off if the temperature range isn't 20-24'C. As of now it just blinks the green led.

  • Trans2TempC from the formula:
    oC = ((x/1024)*1500mV)-986mV)*1/3.55mV
    Simplified: ADC10MEM*423/1024-278

    Swpb is a shortcut to do >>8 (and that is the same thing as /256)

    but as msp only have a >>1 instructions you would have to do clrc, rrc, rra,rra,rra,rra,rra,rra,rra
    with swpb you do have to ignore/eliminate the upper 8bit as it did a swap and not a right-shift-8
  • Using a temperature probe I we were getting the room as 24-25'C, but our board was reading 18-19'C. This means I am now only off on Hex to BCD conversion. 18 --> 16+8 = 24'C.
    I know to get the 10s digit i would x/10, but I don't know how to do a modulus 10 to get the 1's digit.
    Once I got the 10's digit and 1's digit in their separate registers i would shift the 10's digit over to the 10s place and then add the 1's digit to equal correct bcd numbers only temperature.
    I am having trouble with the hex to bcd conversion, heh. I find it sad, its like an equation on the tip of my tongue but I can't code it out correctly.
  •            clr.b   &1st_digit
               jmp compare
    keepsub    sub.b   #10,&temperature
               inc.b   &1st_digit
    compare    cmp.b   #10,&temperature
               jhs keepsub
               mov.b   &temperature,&2nd_digit

    You have to do a CMPSUB, if for example 35C, you can subtract 10 three times and you're left with 5

    Does the result have to be stored as a BCD byte?
    e.g a nibble in each byte can be from 0-9 for max 99 = 0x99 (yes visually bcd shows correctly if you view them as hex)
    The msp430 does have some DADD instructions I never used, as bcd is so 1970's

    	  
    	       clr.b   &bcd
               jmp compare
    keepsub    sub.b   #10,&temperature
               dadd.b  #10,&bcd
    compare    cmp.b   #10,&temperature
               jhs keepsub
               add.b   &temperature,&bcd
  • A fellow student said that the ADC10MEM comes out as integer instead of hex, but code composer just shows it as hex for ccs sake. True?
  • This is the circuit we have, two bcd to 7-segment displays from P2OUT P2.0-P2.7. We have 4 white LEDs in one of the bcd decoder circuits just for troubleshooting from before. The TMP35G us to the left of the MSP430G2 and capacitors are placed in the board to help with debouncing or so. Figured I should produce the circuit sometime.

  • > comes out as integer instead of hex, but code composer just shows it as hex
    Internally everything is binary,
    debuggers like to show it as hex as that way a byte is always two characters. (aligns nicely in columns)
    So binary, hex and decimals is all the same.
    bcd it a little odd that is uses nibbles (4bits) , A hex nibble can store 0-F but a bcd nibble maxes out at 9 so it only goes to 0-9

  • Yep, I know hex, binary, and bcd just fine so no need to worry about me jumbling them up.

    So I had something like it but it didn't work, so I took your code and filled in the blanks but added one extra line.

    			clr.w	R15
    			jmp		compare
    keepsub		sub.b	#10,R13
    			dadd.b	#10,R15
    			sub.b	#01,R15
    compare		cmp.b	#10,R13
    			jhs		keepsub
    			add.b	R13,R15

    the dadd added 10 to R15 plus 1 for a total of 11, which ended up giving the bcd funky icons as it went above 9 in the 1's unit. So I just subtracted 1 every time too.

    The code runs fine now but the TMP isn't as sensitive as the temperature probe we have so its a little flippy, like right now its jumping between 20-21 repeatably when the sensor says its 19.2, but that's okay. It doesn't heat up as fast either. Cheers and thanks for helping.

    We are on to our last project of traffic lights at an intersection next to the campus. Partner likes timers and whatnot so he says he's having fun writing it while I corrected this one. I had to add in a little more multiplying so that the starting temperatures were more inline, here's the finished project.

    			.cdecls C,LIST,"msp430g2553.h"    ; cdecls tells assembler to allow
                                                  ; the c header file
    ;------------------------------------------------------------------------------
    ;   Initialize MSP430
    ;------------------------------------------------------------------------------
                .text								; program start
                .global _main						; define entry point
    
    _main       mov.w   #0280h,SP					; initialize stack pointer
                mov.w   #WDTPW+WDTHOLD,&WDTCTL		; stop watchdog timer
    ;------------------------------------------------------------------------------
                mov.w   #ADC10SHT_2+ADC10ON+ADC10IE+REFON,&ADC10CTL0
                mov.w   #INCH_0,&ADC10CTL1          ; input channel 0
    ;------------------------------------------------------------------------------
    ;   Select and configure inputs and outputs
    ;------------------------------------------------------------------------------
                bis.b   #BIT0,&ADC10AE0             ; P1.0 as analog input A0
                mov.b	#00h,P2SEL					;allows P2.6-7 to work correctly
                mov.b   #0FFh,&P2DIR                ; P2.0-7 output
    			bis.b	#40h,&P1DIR					;make  P1.6 output
    
    Mainloop    bis.w   #ENC+ADC10SC,&ADC10CTL0		; initiate conversion
                bis.w   #CPUOFF+GIE,SR				; turn off CPU (enter low power mode 0)
    												; and enable interrupts - wait in low
    												; power mode until ADC sample is complete
    			mov.w	ADC10MEM,R12
    			mov.w	R12,R13
    			rla.w	R13							;*2
    			mov.w	r13,r12
    			rla.w	R13							;*4
    			mov.w	r13,r8
    			rla.w	R13							;*8
    			add.w	r12,r13						;*8+*2=*10
    			mov.w	r13,r12
    			rla.w	r13							;*16
    			mov.w	r13,r14						;
    			rla.w	r13							;*32
    			rla.w	r13							;*64
    			rla.w	r13							;128
    			add.w	r8,r13						;128+4= *132
    			add.w	r12,r13						;128+10= *142
    			mov.w	R13,R8						;reference point
    			rra.w	R13							;/2
    			rra.w	R13							;/4
    			rra.w	R13							;/8
    			rra.w	R13							;/16
    			rra.w	R13							;/32
    			rra.w	R13							;/64
    			rra.w	R13							;/128
    			rra.w	R13							;/256
    			rra.w	R13							;/512
    			rra.w	R13							;/1024
    			add.w	#000Ah,R13					;TMP starts at 10'C, so add 1 to 10's digit
    
    			clr.w	R15							;following block takes the hex number in R13 and
    			jmp		compare						;converts it into a bcd format for the bcd encoder chips.
    keepsub		sub.b	#10,R13
    			dadd.b	#10,R15
    			sub.b	#01,R15
    compare		cmp.b	#10,R13
    			jhs		keepsub
    			add.b	R13,R15						;temperature in 'C, finished product to be shipped to P2OUT
    
    			mov.w	R15,P2OUT					;following block engages alarm if temperature isn't in range 20-24'C
    			clrz
    			cmp.w	#0x0025,R15
    			jl		notabove
    			mov.b	#40h,P1OUT
    			jmp		duplicate
    notabove	clrz
    			cmp.w	#0x0020,R15
    			jge		justright
    duplicate	mov.b	#40h,P1OUT
    
    			clrz								;Following block cmp is a delay to see the 7-seg better
    			mov.w	#0FFFFh,R6
    TIMER2		dec.w	R6
    			cmp.w	#0000h,R6
    			jne		TIMER2
    
    justright	mov.b	#00h,P1OUT
    
    			clrz								;Following block cmp is a delay to see the 7-seg better
    			mov.w	#0FFFFh,R6
    TIMER		dec.w	R6
    			cmp.w	#0000h,R6
    			jne		TIMER
    
                jmp     Mainloop                     ; start the sample process again
    ;------------------------------------------------------------------------------
    ;  The interrupt service routine for the ADC10 interrupt
    ;------------------------------------------------------------------------------
    ADC10_ISR   bic.w   #CPUOFF,0(SP)                 ; when the ADC conversion is complete
    			reti                                  ; exit low power mode and resume
                                                      ; processing
    ;------------------------------------------------------------------------------
    ;   Interrupt Vectors
    ;------------------------------------------------------------------------------
                .sect   ".reset"                      ; MSP430 RESET Vector
                .short  _main
                .sect   ".int05"                      ; ADC10 Vector
                .short  ADC10_ISR
                .end
    

  • "as far as I know the msp430g2553 only has 16 bits"
    The G2553 has 4096 bits ram. How you handle and interpret them is up to you.
    That one CPU instruction can only handle at most 16 bits simultaneously is not a limitation to only use 16 bits.
    With the long datatype the compiler offers direct support of 32 bit numbers, And the GCC long long type provides 64 bit integer support.
    I'm sure you will have no problems doing what the compiler does, and more.

    On the PC-XT (a 16 bit machine as well, and only 4,77MHz), I once wrote math code (in Modula2) to handle 32 digit (not bit) decimal numbers. Could have scaled it to 64 or more digits easily.

**Attention** This is a public forum