This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

multiplier IC

i have analoge volts on the pins.

How can you achieve z=x*y with 8051? 2V*(-3V)=-6V for example

Parents
  • 
    /*
    **======================================================================
    **      Get_ADC_Value
    **======================================================================
    **
    **  Return the raw ADC value of the selected ADC channel.
    **
    **  This shall start the conversion, wait for it, and then return
    **  the value.  Since our ADC is 12-bits, we shall mask off the
    **  upper nibble here.
    **
    **----------------------------------------------------------------------
    **
    **  Parameters Passed:      u8 channel
    **  Parameters Returned:    u16 raw adc value
    **  Notes:
    **          If the ADC's EOC fails to assert, then this routine
    **          shall return a 'safe' value and flag the ADC as being
    **          problematic.
    **
    **----------------------------------------------------------------------
    */
    u16 Get_ADC_Value( u8 channel )
    {
        static  u8  time_out_timer; // an atomically accessed data-store
    
        u16         adc;    // ADC is 12 bits, so use a 16-bit storage
    
        bit         eoc;    // the End of Conversion signal
    
        /*------------------------------------------------------------------.
        ;  Start the selected ADC conversion process                        ;
        '------------------------------------------------------------------*/
        Start_ADC( channel );
    
        /*------------------------------------------------------------------.
        ;  Assign a time out period for protection against an infinate loop ;
        '------------------------------------------------------------------*/
        time_out_timer = TO_5mS;
    
        /*------------------------------------------------------------------.
        ;  Start timing the time-out timer (crude, but works)               ;
        '------------------------------------------------------------------*/
        Start_Timer( &time_out_timer );
    
        /*------------------------------------------------------------------.
        ;  Wait for the ADC to complete the conversion.                     ;
        '------------------------------------------------------------------*/
        while( time_out_timer > 0 )
        {
            eoc = Check_End_Of_Convert( );  // ADC reports status, get it
    
            /*--------------------------------------------------------------.
            ;   "Are we there yet?"  If so, then exit the while loop        ;
            '--------------------------------------------------------------*/
            if( eoc != FALSE )
            {
                time_out_timer = 0; // forces while to exit
                timed_out = FALSE;  // declare that we didn't run out of time
            }
            else
            {
                timed_out = TRUE;   // we ran out of time... note it
            }
        }
    
        /*------------------------------------------------------------------.
        ; Keep the time-out timer from stomping on 'retired' data-stores    ;
        ; (Although this has been declared 'static' the out-of-scope data   ;
        ;  needs to be released from the potential of an isr writting to    ;
        ;  the address, and hence, killing some random data-store)          ;
        '------------------------------------------------------------------*/
        Release_Timer( &time_out_timer );
    
        /*------------------------------------------------------------------.
        ;  If we timed out, then the EOC was abnormal.  Return as 'safe'    ;
        ; analog value, and set the corrisponding error flag.               ;
        '------------------------------------------------------------------*/
        if( timed_out != FALSE )
        {
            adc = SAFE_ADC_VALUE;        // Use a 'safe' value
    
            Log_Error( ADC_EOC_ERROR ); // make note of the error
    
            // adc &= ADC_LEADING_MASK; // Could encode an error nibble here
            // adc |= ADC_ERROR_CODE;   // but chose not to due to the
        }                               // possibilitiy of a 16-bit ADC
        else
        {
            adc  = Read_ADC( channel ); // Read it
    
            adc &= ADC_LEADING_MASK;    // clean it up
        }
    
        /*------------------------------------------------------------------.
        ;  The value has been prepared. Return it.                          ;
        '------------------------------------------------------------------*/
        return( adc );
    }
    
    

Reply
  • 
    /*
    **======================================================================
    **      Get_ADC_Value
    **======================================================================
    **
    **  Return the raw ADC value of the selected ADC channel.
    **
    **  This shall start the conversion, wait for it, and then return
    **  the value.  Since our ADC is 12-bits, we shall mask off the
    **  upper nibble here.
    **
    **----------------------------------------------------------------------
    **
    **  Parameters Passed:      u8 channel
    **  Parameters Returned:    u16 raw adc value
    **  Notes:
    **          If the ADC's EOC fails to assert, then this routine
    **          shall return a 'safe' value and flag the ADC as being
    **          problematic.
    **
    **----------------------------------------------------------------------
    */
    u16 Get_ADC_Value( u8 channel )
    {
        static  u8  time_out_timer; // an atomically accessed data-store
    
        u16         adc;    // ADC is 12 bits, so use a 16-bit storage
    
        bit         eoc;    // the End of Conversion signal
    
        /*------------------------------------------------------------------.
        ;  Start the selected ADC conversion process                        ;
        '------------------------------------------------------------------*/
        Start_ADC( channel );
    
        /*------------------------------------------------------------------.
        ;  Assign a time out period for protection against an infinate loop ;
        '------------------------------------------------------------------*/
        time_out_timer = TO_5mS;
    
        /*------------------------------------------------------------------.
        ;  Start timing the time-out timer (crude, but works)               ;
        '------------------------------------------------------------------*/
        Start_Timer( &time_out_timer );
    
        /*------------------------------------------------------------------.
        ;  Wait for the ADC to complete the conversion.                     ;
        '------------------------------------------------------------------*/
        while( time_out_timer > 0 )
        {
            eoc = Check_End_Of_Convert( );  // ADC reports status, get it
    
            /*--------------------------------------------------------------.
            ;   "Are we there yet?"  If so, then exit the while loop        ;
            '--------------------------------------------------------------*/
            if( eoc != FALSE )
            {
                time_out_timer = 0; // forces while to exit
                timed_out = FALSE;  // declare that we didn't run out of time
            }
            else
            {
                timed_out = TRUE;   // we ran out of time... note it
            }
        }
    
        /*------------------------------------------------------------------.
        ; Keep the time-out timer from stomping on 'retired' data-stores    ;
        ; (Although this has been declared 'static' the out-of-scope data   ;
        ;  needs to be released from the potential of an isr writting to    ;
        ;  the address, and hence, killing some random data-store)          ;
        '------------------------------------------------------------------*/
        Release_Timer( &time_out_timer );
    
        /*------------------------------------------------------------------.
        ;  If we timed out, then the EOC was abnormal.  Return as 'safe'    ;
        ; analog value, and set the corrisponding error flag.               ;
        '------------------------------------------------------------------*/
        if( timed_out != FALSE )
        {
            adc = SAFE_ADC_VALUE;        // Use a 'safe' value
    
            Log_Error( ADC_EOC_ERROR ); // make note of the error
    
            // adc &= ADC_LEADING_MASK; // Could encode an error nibble here
            // adc |= ADC_ERROR_CODE;   // but chose not to due to the
        }                               // possibilitiy of a 16-bit ADC
        else
        {
            adc  = Read_ADC( channel ); // Read it
    
            adc &= ADC_LEADING_MASK;    // clean it up
        }
    
        /*------------------------------------------------------------------.
        ;  The value has been prepared. Return it.                          ;
        '------------------------------------------------------------------*/
        return( adc );
    }
    
    

Children
  • 
    /*
    **======================================================================
    **      main
    **======================================================================
    **
    **  This answers the question "How can you achieve z=x*y with 8051?"
    **  found in the origional contract.
    **
    **  Contract: http://www.keil.com/forum/docs/thread12890.asp
    **
    **  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    **
    **  This shall "infinately" read in two analog voltage values, then
    **  multiply them together, and with that result control a heat-lamp
    **  to keep the french-fries from becoming solid blocks of Crisco.
    **
    **----------------------------------------------------------------------
    **
    **  Parameters Passed:      <none>
    **  Parameters Returned:    <none>
    **  Notes:
    **          This requires a time-base isr, and other 'implied' functions
    **
    **----------------------------------------------------------------------
    */
    void main( void )
    {
        /*------------------------------------------------------------------.
        ;
        '------------------------------------------------------------------*/
        u16     raw_x;      // get the un-scaled ADC values
        u16     raw_y;
    
        s16     x;          // for the scaled values
        s16     y;
    
        s32     result_z;   // our result ... (2^12)x(2^12) = 16,777,216 < 2^32
    
        /*------------------------------------------------------------------.
        ;  Power-up                                                         ;
        '------------------------------------------------------------------*/
        Disable_Interrupts( );  // just in case
        Init_Port_IO( );        // 'safest' port levels
        Init_Debug( );          // initialize the error/debug stuff
    
        /*------------------------------------------------------------------.
        ;  Initialize the time-base                                         ;
        '------------------------------------------------------------------*/
        Init_Time_Base( );      // configure it
        Enable_Time_Base( );    // enable it
    
        /*------------------------------------------------------------------.
        ;  Clear any 'pending' interrupts and then enable the master.       ;
        '------------------------------------------------------------------*/
        Enable_All_Interrupts( );
    
        /*------------------------------------------------------------------.
        ;  Simple forever loop which reads, multiplies, and outputs         ;
        '------------------------------------------------------------------*/
        while( FOREVER )
        {
            /*--------------------------------------------------------------.
            ;  Read in the ADC values                                       ;
            '--------------------------------------------------------------*/
            raw_x = Get_ADC_Value( CHANNEL_0 );
            raw_y = Get_ADC_Value( CHANNEL_1 );
    
            /*--------------------------------------------------------------.
            ;  Scale the values per the system requirements                 ;
            '--------------------------------------------------------------*/
            x = Scale_ADC( raw_x );
            y = Scale_ADC( raw_y );
    
            /*--------------------------------------------------------------.
            ;  Multiply the two readings, and feed that into our output...  ;
            '--------------------------------------------------------------*/
            result_z = x * y;                   // the complex math
    
            /*--------------------------------------------------------------.
            ; The output is a signed 32-bit PWM channel operating with a    ;
            ; base frequency of 50kHz, and this is used to control the      ;
            ; french-fry heat lamps, and simultaneously killing the flies   ;
            ; buzzing about with the intense Infra-Red lamps.  Those little ;
            ; black dots in your fry container are not 'zesty' spices.      ;
            '--------------------------------------------------------------*/
            Update_PWM_Out( CHANNEL_A, result_z );
        }
    
    }
    
    
    
    /*===========================================================================
    *       END OF MODULE ( Keil_Forum_Example.C )
    ===========================================================================*/
    
    

    I did not include all of the functions, but you can figure it out from there.

    Also I have not compiled this code because it will only show a bunch of errors and complain how it should not work. I hate that. So I never actually compile or link programs. This way I also avoid that debugging thing too. It takes too much time anyway.

    --Cpt. Vince Foster
    2nd Cannon Place
    Fort Marcy Park, VA

  • now I am sure he will get an a on his test

    uh... thanks erik.

    After posting it, I quickly spotted an error. (not that there is only one).

    It turns out that I didn't allocate 'timed_out' and then I didn't initialize it prior to the while( time_out_timer > 0 ) loop. So if time_out_timer was 0, then timed_out is un-assigned, thus the if( timed_out != FALSE ) test becomes an invalid test. The system fails, millions are lost, and as a result of the failure, a Mr. Boro Berak (this OP) is hired to replace me while the crayon on his diploma is still drying.

    Mr. Berak will quickly hire erik malund and he shall ask some fairly simple questions...

    which '8051'
    which language (C, Pascal, assembler)
    which a/d (internal/external)
    what supply voltages do you have
    what precision do you need
    what resolution do you need
    what fluency do you have in programming
    what experience do you have in analog design

    --Cpt. Vince Foster
    2nd Cannon Place
    Fort Marcy Park, VA

  • Maybe not: that's a pretty distinctive style, and any decent teacher would instantly spot whether or not it is typical of the student's own work...