اطلاعیه

Collapse
No announcement yet.

کمک درباره کدویژن

Collapse
X
 
  • فیلتر
  • زمان
  • Show
Clear All
new posts

    کمک درباره کدویژن

    سلام دوستان من یه مدار خازن سنج از اینترنت گیر اوردم با برنامه c ولی من c زیاد بلد نیستم اگه میشه بهم بگین تو این برنامه به جای
    #include <avr/interrupt.h>
    #include <avr/io.h>
    #include <avr/eeprom.h>
    چی بنویسم تا کامپایلر ارور نده؟؟
    البته میدونم تو خط اول به جای avr/interrupt.h باید بنویسم mega8.h ولی خطهای بعدی رو نمیدونم چی باید بنویسم.
    برنامه و عکس مدارو میزارم
    ممنون میشم کمکم کنید


    //
    // Title : Capmeter main file
    // Author : Lars Pontoppidan Larsen
    // Date : Jan 2006
    // Version : 1.00
    // Target MCU : Atmel AVR atmega8, atmega48/88/168
    //
    // DESCRIPTION:
    // Capmeter main implementation. See www accessible documentation.
    //
    // Modify init() function to fit either atmega8 or atmega48/88/168 series.
    //
    // DISCLAIMER:
    // The author is in no way responsible for any problems or damage caused by
    // using this code. Use at your own risk.
    //
    // LICENSE:
    // This code is distributed under the GNU Public License
    // which can be found at http://www.gnu.org/licenses/gpl.txt
    //


    #include <avr/interrupt.h>
    #include <avr/io.h>
    #include <avr/eeprom.h>

    #include "lcd.h"

    /* Hardware IO abstraction macros */

    /* AIN0 out also discharges cap */
    #define DISCHARGE_ON DDRD |= (1<<6)
    #define DISCHARGE_OFF DDRD &= ~(1<<6)

    /* Range control */
    #define HIGH_RANGE PORTD |= (1<<5); DDRD |= (1<<5)
    #define LOW_RANGE DDRD &= ~(1<<5); PORTD &= ~(1<<5)
    #define PULLDOWN_RANGE PORTD &= ~(1<<5); DDRD |= (1<<5)

    /* Threshold selection */
    #define ADMUX_LOW 1
    #define ADMUX_MEDIUM 2
    #define ADMUX_HIGH 3

    /* Timer abstraction */
    #define TIMER_VALUE TCNT1
    #define TIMER_START TCCR1B = (1<<CS10)
    #define TIMER_STOP TCCR1B = 0

    /* Led abstraction */
    #define LED_ON PORTD &= ~(1<<4)
    #define LED_OFF PORTD |= (1<<4)

    /* Button abstraction */
    #define BUTTON_PUSHED (!(PIND & (1<<2)))

    char decades[5] = {'p','n','u','m ',' '};

    char lcdbuffer[32];

    unsigned short volatile timer_highword;


    /* Program states: */
    #define STATE_IDLE 0
    #define STATE_LOW_THRESH 1
    #define STATE_HIGH_THRESH 2
    #define STATE_DONE 3
    //#define STATE_BUTTONDOWN 4


    unsigned char volatile measure_state;

    /* The following is the value the analog compare interrupt will set ADMUX: */
    unsigned char volatile set_admux;

    /* The rangemode defines the measurement operation */
    #define RANGE_HIGH_THRESH 1 /* If missing: threshold low */
    #define RANGE_HIGH 2 /* If missing: range low */
    #define RANGE_AUTO 4
    #define RANGE_OVERFLOW 8 /* If set: cap was out of range */
    unsigned char rangemode = RANGE_AUTO;


    /* Constants defining measuring operation: */
    #define EXTRA_DISCHARGE_MS 100 /* Extra discharging that is done even after a threshold is crossed */
    #define LOW_RANGE_TIMEOUT 500 /* At autorange, when to go to high range */
    #define HIGH_RANGE_TIMEOUT 10000 /* When to give up completely */


    /* Menu system */
    #define MENU_SPEED 800 /* ms each menu item is shown */

    #define MENU_ITEMS 6
    char *menu_item[MENU_ITEMS] = {"Range: Auto","Range: Low ","Range: High","Calibrate: Zero","Calibrate: 1 uF","Save calibration"};

    /* Teoretisk beregning af capacitans

    t = tau * ln((V0 - Vinf)/(V - Vinf)

    De forskellige threshold v?rdier, og deres forhold til tau:

    V threshold t fra 0 til x: fra low til x:

    0.88 low tau * 0.1918910 tau * 0.240725 (=K1)
    1.77 medium tau * 0.4326161 tau * 0.554222 (=K2)
    2.65 high tau * 0.7461127

    5.04 top

    R1 = 1.588.000 ohm
    R2 = 1752 ohm

    t = tclocks / fcpu
    tau * K = t
    tau = R*C =>

    C = tau / R = t / (K * R) = tclocks / (K * R * fcpu)

    = tclocks / (0.240725 * 1588000 * 8000000) = tclocks * 3.270e-13 = tclocks * 21430 / 65536 * 1E-12
    = tclocks / (0.554222 * 1588000 * 8000000) = tclocks * 9308 / 65536 * 1E-12

    // // // alternatively
    // // // = tclocks / (0.240725 * 1588000 * 8000000) = tclocks * 5.96856E-13 = tclocks * 53575 / 65536 * 4 * 1E-13
    // // // = tclocks / (0.554222 * 1588000 * 8000000) = tclocks * 5.96856E-13 = tclocks * 46540 / 65536 * 2 * 1E-13
    // // //
    = tclocks / (0.240725 * 1752 * 8000000) = tclocks * 19423 / 65536 * 1E-9
    = tclocks / (0.554222 * 1752 * 8000000) = tclocks * 8437 / 65536 * 1E-9

    */

    /*
    Calibration:

    C = tclocks * Kc / 65536 * 1E-12

    Kc = C * 65536 * 1E12 / tclocks

    = CALIB_CONST / tclocks

    Low range: C = 1uF
    CALIB_CONST = C * 65536e12 = 256000000 (*256)

    High range:
    CALIB_CONST = C * 65536e9 = 65536000

    */

    #define CALIB_LOW 256000000 /* for 1uF reference prescale: >> 8 */
    #define CALIB_HIGH 65536000 /* for 1uF reference */

    /* Calibration values are stored in eeprom in the following format:

    Starting from byte 1: (not 0)
    'C' 'D'
    <data>

    */
    #define EEPROM_HEADER 1
    #define EEPROM_DATA 3


    unsigned short calib[4] = {21430, 9308, 19423, 8437};
    //unsigned short calib[4] = {53575, 46540, 19423, 8437};

    unsigned long calib_offset[4] = {0,0,0,0};

    #define SIZE_OF_CALIB 8
    #define SIZE_OF_CALIBOFFSET 16

    /* This macro fractionally multiplies 16.16 bit with 0.16 bit both unsigned,
    shifting the result two bytes right and returning 16.16 bit.

    Result is 16.16 bit unsigned */


    #define MUL_LONG_SHORT_S2(x,y,result) asm volatile( \
    "clr %C0" "\n\t" \
    "clr %B0" "\n\t" \
    "clr %A0" "\n\t" \
    "mul %A1, %A2" "\n\t" \
    "mov %D0, r1" "\n\t" \
    "mul %A1, %B2" "\n\t" \
    "add %D0, r0" "\n\t" \
    "adc %A0, r1" "\n\t" \
    "adc %B0, %C0" "\n\t" \
    "mul %B1, %A2" "\n\t" \
    "add %D0, r0" "\n\t" \
    "adc %A0, r1" "\n\t" \
    "adc %B0, %C0" "\n\t" \
    "mul %B1, %B2" "\n\t" \
    "add %A0, r0" "\n\t" \
    "adc %B0, r1" "\n\t" \
    "adc %C0, %C0" "\n\t" \
    "mul %C1, %A2" "\n\t" \
    "add %A0, r0" "\n\t" \
    "adc %B0, r1" "\n\t" \
    "brcc L_dl1%=" "\n\t" \
    "inc %C0" "\n\t" \
    "L_dl1%=:" "\n\t" \
    "clr %D0" "\n\t" \
    "mul %C1, %B2" "\n\t" \
    "add %B0, r0" "\n\t" \
    "adc %C0, r1" "\n\t" \
    "brcc L_dl2%=" "\n\t" \
    "inc %D0" "\n\t" \
    "L_dl2%=:" "\n\t" \
    "mul %D1, %A2" "\n\t" \
    "add %B0, r0" "\n\t" \
    "adc %C0, r1" "\n\t" \
    "brcc L_dl3%=" "\n\t" \
    "inc %D0" "\n\t" \
    "L_dl3%=:" "\n\t" \
    "mul %D1, %B2" "\n\t" \
    "add %C0, r0" "\n\t" \
    "adc %D0, r1" "\n\t" \
    "clr r1" "\n\t" \
    : "=&r" (result) \
    : "r" (x), "r" (y) \
    )

    /* Interrupt implementation */
    SIGNAL(SIG_COMPARATOR)
    {
    if (measure_state == STATE_LOW_THRESH) {
    /* We just got low threshold interrupt, start timer and set high threshold */
    TIMER_START;
    ADMUX = set_admux;
    measure_state = STATE_HIGH_THRESH;
    }
    else if(measure_state == STATE_HIGH_THRESH) {
    /* High threshold interrupt, verify it, then stop timer */
    if (ACSR & (1<<ACO)) {
    TIMER_STOP;
    measure_state = STATE_DONE;
    }
    }
    }


    SIGNAL(SIG_OVERFLOW1)
    {
    /* Timer 1 counts the low 16 bits, this interrupt updates the high 16 bits */
    timer_highword++;
    }

    // SIGNAL(SIG_INTERRUPT0)
    // {
    // /* Hardware interrupt 0 is a buttonpush */
    // measure_state = STATE_BUTTONDOWN;
    // }

    /*
    The measure function does the cyclus of a capacitance measurement
    Returned is the number of clocks measured

    The function relies on flags in the global rangemode value
    Input flags:
    RANGE_AUTO
    RANGE_HIGH
    RANGE_HIGH_THRESH

    Output flags:
    RANGE_HIGH (if RANGE_AUTO)
    RANGE_OVERFLOW

    */

    void eeprom_read(void)
    {
    if (eeprom_read_byte((void*)EEPROM_HEADER) != 'C&#039
    return;

    if (eeprom_read_byte((void*)EEPROM_HEADER+1) != 'D&#039
    return;

    eeprom_read_block(calib_offset, (void*)EEPROM_DATA, SIZE_OF_CALIBOFFSET);
    eeprom_read_block(calib, (void*)EEPROM_DATA + SIZE_OF_CALIBOFFSET, SIZE_OF_CALIB);

    }

    void eeprom_write(void)
    {
    eeprom_write_byte((void*)EEPROM_HEADER, 'C'
    eeprom_write_byte((void*)EEPROM_HEADER+1, 'D'

    eeprom_write_block(calib_offset, (void*)EEPROM_DATA, SIZE_OF_CALIBOFFSET);
    eeprom_write_block(calib, (void*)(EEPROM_DATA + SIZE_OF_CALIBOFFSET), SIZE_OF_CALIB);

    }

    long measure(void)
    {
    unsigned short i;

    measure_state = STATE_IDLE;

    /* Discharge cap until below low threshold + some extra */
    ADMUX = ADMUX_LOW;
    PULLDOWN_RANGE; /* Use range signal as pull down */

    while(1) {
    /* Enable comperator and check value */
    DISCHARGE_OFF;
    ms_spin(1);

    /* This value must be checked in every loop */
    if (BUTTON_PUSHED)
    return 0;

    if (!(ACSR & (1<<ACO)))
    break;

    /* Discharge for a while */
    DISCHARGE_ON;
    ms_spin(10);


    }

    DISCHARGE_ON;
    ms_spin(EXTRA_DISCHARGE_MS);

    /* Prepare: reset timer, low range */
    TIMER_STOP;
    TIMER_VALUE = 0;
    timer_highword = 0;

    LOW_RANGE;

    measure_state = STATE_LOW_THRESH;

    /* High or medium threshold */
    if (rangemode & RANGE_HIGH_THRESH)
    set_admux = ADMUX_HIGH;
    else
    set_admux = ADMUX_MEDIUM;

    /* Apply step */
    LED_ON;
    DISCHARGE_OFF;

    if (rangemode & RANGE_AUTO) {

    /* Autorange: See if low range produces something before LOW_RANGE_TIMEOUT ms */
    i = 0;
    while ((measure_state == STATE_LOW_THRESH) && (++i < LOW_RANGE_TIMEOUT)) {
    ms_spin(1);

    /* This value must be checked in every loop */
    if (BUTTON_PUSHED)
    return 0;
    }

    if (i >= LOW_RANGE_TIMEOUT) {
    /* low range timeout, go to high range (better discharge a little first) */
    DISCHARGE_ON;
    ms_spin(EXTRA_DISCHARGE_MS);
    DISCHARGE_OFF;
    HIGH_RANGE;
    rangemode |= RANGE_HIGH;
    }
    else {
    /* low range was ok, set flag accordingly */
    rangemode &= ~RANGE_HIGH;
    }
    }
    else if (rangemode & RANGE_HIGH) {
    HIGH_RANGE;
    }

    /* Wait for completion, timing out after HIGH_RANGE_TIMEOUT */
    i = 0;
    while ((measure_state != STATE_DONE) && (++i < HIGH_RANGE_TIMEOUT)) {
    ms_spin(1);

    /* This value must be checked in every loop */
    if (BUTTON_PUSHED)
    return 0;
    }

    /* Done, discharge cap now */
    LOW_RANGE;
    DISCHARGE_ON;
    LED_OFF;

    if (measure_state != STATE_DONE)
    rangemode |= RANGE_OVERFLOW;
    else
    rangemode &= ~RANGE_OVERFLOW;

    measure_state = STATE_IDLE;

    return ((unsigned long)timer_highword << 16) + TIMER_VALUE;
    }

    /*
    This function deals with value according to the global rangemode flag,
    and shows the result on LCD.

    LCD should preferably be cleared.

    Routine is rather slow
    */

    void calc_and_show(long value)
    {
    unsigned char b;
    unsigned long l;

    if (rangemode & RANGE_AUTO)
    lcd_string("Auto ",0);
    else
    lcd_string("Force",0);

    if (rangemode & RANGE_HIGH)
    lcd_string(" high",16);
    else
    lcd_string(" low ",16);

    if (rangemode & RANGE_OVERFLOW) {
    /* Todo - this smarter */
    lcdbuffer[0] = ' ';
    lcdbuffer[1] = ' ';
    lcdbuffer[2] = ' ';
    lcdbuffer[3] = 'E';
    lcdbuffer[4] = 'r';
    lcdbuffer[5] = 'r';
    lcdbuffer[6] = 'o';
    lcdbuffer[7] = 'r';
    lcdbuffer[8] = ' ';
    lcdbuffer[9] = 0;
    }
    else {
    /* Select calibration value */
    b = rangemode & 3;

    if (calib_offset[b] > value) {
    lcdbuffer[0] = '-';
    value = calib_offset[b] - value;
    }
    else {
    lcdbuffer[0] = ' ';
    value = value - calib_offset[b];
    }

    MUL_LONG_SHORT_S2(value, calib[b], l);

    b = long2ascii(lcdbuffer+1, l);

    /* High range shifts 1E3 */
    if (rangemode & RANGE_HIGH)
    b++;

    lcdbuffer[6] = ' ';
    lcdbuffer[7] = decades[b]; /* range = 1 shifts 1E3 */
    lcdbuffer[8] = 'F';
    lcdbuffer[9] = 0;
    }

    /* Write high threshold in first line, low threshold in second */
    if (rangemode & RANGE_HIGH_THRESH)
    b=7;
    else
    b=23;

    lcd_string(lcdbuffer,b);
    }

    void calibrate_zero(void)
    {
    char oldrange = rangemode;
    unsigned long l;

    rangemode = 0;

    l = measure();
    l = measure();

    calib_offset[rangemode] = l;

    rangemode = RANGE_HIGH_THRESH;

    l = measure();
    l = measure();

    calib_offset[rangemode] = l;

    rangemode = oldrange;

    }

    void calibrate(void)
    {
    char oldrange = rangemode;
    unsigned long value;

    rangemode = 0;
    value = measure();
    value -= calib_offset[rangemode];
    calib[rangemode] = CALIB_LOW / (value>>8) + 1;

    rangemode = RANGE_HIGH_THRESH;
    value = measure();
    value -= calib_offset[rangemode];
    calib[rangemode] = CALIB_LOW / (value>>8) + 1;

    rangemode = RANGE_HIGH;
    value = measure();
    value -= calib_offset[rangemode];
    calib[rangemode] = CALIB_HIGH / value + 1;

    rangemode = RANGE_HIGH | RANGE_HIGH_THRESH;
    value = measure();
    value -= calib_offset[rangemode];
    calib[rangemode] = CALIB_HIGH / value + 1;

    rangemode = oldrange;

    }

    /* Hold-down-button menu implementation: */

    char menu(void)
    {
    unsigned char i;

    lcd_clear();

    for (i=0; i<MENU_ITEMS; i++) {
    lcd_string(menu_item[i],0);
    ms_spin(MENU_SPEED);

    if (!BUTTON_PUSHED)
    break;

    }

    if (i == MENU_ITEMS) {
    /* Just clear display, if user went out of menu */
    lcd_clear();

    /* Wait for release of button */
    while (BUTTON_PUSHED);
    ms_spin(10);

    }
    else {
    /* Flash selected item */
    lcd_clear();
    ms_spin(MENU_SPEED >> 2);
    lcd_string(menu_item[i],0);
    ms_spin(MENU_SPEED >> 1);
    lcd_clear();
    ms_spin(MENU_SPEED >> 2);

    }

    return i;
    }

    void init(void)
    {

    /* Set datadirections */
    DDRD = (1<<4); /* led output, rest input */
    PORTD &= ~(1<<6); /* AIN0 port must be 0 */

    /* Enable button pull up resistor */
    PORTD |= (1<<2);

    /* Setup timer1 to normal operation */
    TCCR1A = 0;
    TCCR1B = 0;
    //TIMSK = (1<<TOIE1); //(mega8)
    TIMSK1 = (1<<TOIE1); //(mega48/88/168)


    /* Setup analog comperator to generate rising edge interrupt */
    ACSR = (1<<ACIS0)|(1<<ACIS1)|(1<<ACIE) ;

    /* Setup analog comperator to use ADMUX */
    ADMUX = ADMUX_LOW;
    //SFIOR |= (1<<ACME);
    ADCSRB |= (1<<ACME);
    DIDR1 |= (1<<AIN1D)|(1<<AIN0D);

    }

    int main(void)
    {
    unsigned long l;

    init();

    lcd_init();

    eeprom_read();

    asm("sei"

    LED_OFF;

    rangemode = RANGE_AUTO;

    while (1) {
    /* Toggle high/low threshold */
    rangemode ^= RANGE_HIGH_THRESH;
    l = measure();
    if (BUTTON_PUSHED) {
    /* Stop any cap. charging */
    LED_OFF;
    LOW_RANGE;
    DISCHARGE_ON;

    /* Menu implementation */
    switch(menu()) {
    case 0: /* auto range */
    rangemode |= RANGE_AUTO;
    break;
    case 1: /* low range */
    rangemode &= ~(RANGE_AUTO | RANGE_HIGH);
    break;
    case 2: /* high range */
    rangemode &= ~RANGE_AUTO;
    rangemode |= RANGE_HIGH;
    break;
    case 3:
    calibrate_zero();
    break;
    case 4:
    calibrate();
    break;
    case 5:
    eeprom_write();
    break;
    }

    }
    else
    calc_and_show(l);
    }
    }

    #2
    پاسخ : کمک درباره کدویژن

    ببخشید که تایپیک بالا رو شلوغش کردم
    اینم فایل برنامه و عکس مدار
    فقط بگید به جای اینا چی بنویسم

    #include <avr/io.h>
    #include <avr/eeprom.h>

    لینک فایل:
    http://www.4shared.com/file/RL0Ddcfs/cap_meter.html

    دیدگاه


      #3
      پاسخ : کمک درباره کدویژن

      کسی نیست کمکم کنه!؟؟

      دیدگاه


        #4
        پاسخ : کمک درباره کدویژن

        با سلام
        این برنامه مربوط به کامپایلر avrgcc میشه و اون مواردی هم که شما بهشون اشاره کردید فایل های سرایند هستند که کامپایلر از اون ها برای کامپایل برنامه استفاده میکنه ونمیشه تنها با معادل نویسی اینها در کدویژن کل برنامه رو داخل کدویژن کامپایل کرد مثلا توی avr gcc روتین زیر :

        SIGNAL(SIG_OVERFLOW1)
        {
        /* Timer 1 counts the low 16 bits, this interrupt updates the high 16 bits */
        timer_highword++;
        }

        همون طور که توضیح داده شده مربوط میشه به روتین وقفه سرریز تایمر 1 ، خوب این توی کدویژن بی معنیه و البته خود کامپایلر gcc به کمک فایل سرایندی #include <avr/interrupt.h> میتونه این روتین رو کامپایل کنه !

        پس اگر میخواهید فقط از برنامه استفاده کنید و فایل هگز مورد نظزرتون هست برنامه رو توی یه کامپایلر gcc مثل winavr یا avrstudio کامپایل کنید و فایل هگزه رو توی میکرو پروگرام کنید .

        اما اگر میخواهید برنامه رو توی کدویژن بازنویسی کنید بگید تا مشخص بشه که منظور تون این بوده تا در این مورد دوستان و بنده کمکتون کنیم.

        دیدگاه


          #5
          پاسخ : کمک درباره کدویژن

          ممنون از راهنمایتون mojtaba_led عزیز.
          من می خوام برنامه رو توی کدویژن بازنویسی کنم. اگه میشه لطف کنین کمکم کنید.

          دیدگاه


            #6
            پاسخ : کمک درباره کدویژن

            راستش الان که برنامه رو دیدم ، دیدم توش از این لاین اسمبلی استفاده شده و من هنوز وقت نشده برم دنبالش ببینم چی به چیه دقیقا .
            پیشنهاد میکنم فعلا از همین برنامه توی avr studio (avr gcc) استفاده کنید چون بازنویسی این برنامه با کدویژن یا هر کامپایلر دیگه ای در درجه اول نیاز به این داره که بدونیم این برنامه دقیقا داره چیکار میکنه تا بشه اون رو باز نویسی کردش .

            فقط تنها کاری که میتونم فعلا براتون انجام بدم معرفی این تاپیک برای آشنایی بیشتر با avr studio (avr gcc) هست :

            آموزش ( avrstudio5 ( AVRGCC

            دیدگاه

            لطفا صبر کنید...
            X