⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 radio.c

📁 Contiki是一个开源
💻 C
📖 第 1 页 / 共 4 页
字号:
/*----------------------------------------------------------------------------*//** \brief  This function will return the PANID used by the address filter. * *  \retval Any value from 0 to 0xFFFF. */uint16_tradio_get_pan_id(void){    uint8_t pan_id_15_8 = hal_register_read(RG_PAN_ID_1); /*  Read pan_id_15_8. */    uint8_t pan_id_7_0 = hal_register_read(RG_PAN_ID_0); /*  Read pan_id_7_0. */    uint16_t pan_id = ((uint16_t)(pan_id_15_8 << 8)) | pan_id_7_0;    return pan_id;}/*----------------------------------------------------------------------------*//** \brief  This function will set the PANID used by the address filter. * *  \param  new_pan_id Desired PANID. Can be any value from 0x0000 to 0xFFFF */voidradio_set_pan_id(uint16_t new_pan_id){    uint8_t pan_byte = new_pan_id & 0xFF; /*  Extract new_pan_id_7_0. */    hal_register_write(RG_PAN_ID_0, pan_byte);    pan_byte = (new_pan_id >> 8*1) & 0xFF;  /*  Extract new_pan_id_15_8. */    hal_register_write(RG_PAN_ID_1, pan_byte);}/*----------------------------------------------------------------------------*//** \brief  This function will return the current short address used by the *          address filter. * *  \retval Any value from 0x0000 to 0xFFFF */uint16_tradio_get_short_address(void){    uint8_t short_address_15_8 = hal_register_read(RG_SHORT_ADDR_1); /*  Read short_address_15_8. */    uint8_t short_address_7_0  = hal_register_read(RG_SHORT_ADDR_1); /*  Read short_address_7_0. */    uint16_t short_address = ((uint16_t)(short_address_15_8 << 8)) | short_address_7_0;    return short_address;}/*----------------------------------------------------------------------------*//** \brief  This function will set the short address used by the address filter. * *  \param  new_short_address Short address to be used by the address filter. */voidradio_set_short_address(uint16_t new_short_address){    uint8_t short_address_byte = new_short_address & 0xFF; /*  Extract short_address_7_0. */    hal_register_write(RG_SHORT_ADDR_0, short_address_byte);    short_address_byte = (new_short_address >> 8*1) & 0xFF; /*  Extract short_address_15_8. */    hal_register_write(RG_SHORT_ADDR_1, short_address_byte);}/*----------------------------------------------------------------------------*//** \brief  This function will read the extended address used by the address *          filter. * *  \note In this function a pointer is used to convey the 64-bit result, since *        it is very inefficient to use the stack for this. * *  \return Extended Address, any 64-bit value. */voidradio_get_extended_address(uint8_t *extended_address){    *extended_address++ = hal_register_read(RG_IEEE_ADDR_0);    *extended_address++ = hal_register_read(RG_IEEE_ADDR_1);    *extended_address++ = hal_register_read(RG_IEEE_ADDR_2);    *extended_address++ = hal_register_read(RG_IEEE_ADDR_3);    *extended_address++ = hal_register_read(RG_IEEE_ADDR_4);    *extended_address++ = hal_register_read(RG_IEEE_ADDR_5);    *extended_address++ = hal_register_read(RG_IEEE_ADDR_6);    *extended_address   = hal_register_read(RG_IEEE_ADDR_7);}/*----------------------------------------------------------------------------*//** \brief  This function will set a new extended address to be used by the *          address filter. * *  \param  extended_address Extended address to be used by the address filter. */voidradio_set_extended_address(uint8_t *extended_address){    hal_register_write(RG_IEEE_ADDR_0, *extended_address++);    hal_register_write(RG_IEEE_ADDR_1, *extended_address++);    hal_register_write(RG_IEEE_ADDR_2, *extended_address++);    hal_register_write(RG_IEEE_ADDR_3, *extended_address++);    hal_register_write(RG_IEEE_ADDR_4, *extended_address++);    hal_register_write(RG_IEEE_ADDR_5, *extended_address++);    hal_register_write(RG_IEEE_ADDR_6, *extended_address++);    hal_register_write(RG_IEEE_ADDR_7, *extended_address++);}/*----------------------------------------------------------------------------*//** \brief  This function will configure the CSMA algorithm used by the radio *          transceiver when transmitting data from TX_ARET_ON state. * *  \param  seed0 Lower 8 bits of the seed used for the random number generator *                in the CSMA algorithm. Value range: 0 to 255. *  \param  be_csma_seed1 Is a combined argument of the MIN_BE, MAX_CSMA_RETRIES *                        and SEED1 variables: *                        -# MIN_BE: Bit[7:6] Minimum back-off exponent in the *                           CSMA/CA algorithm. *                        -# MAX_CSMA_RETRIES: Bit[5:3] Number of retries in *                          TX_ARET_ON mode to repeat the CSMA/CA procedures *                          before the ARET procedure gives up. *                        -# SEED1: Bits[2:0] Higher 3 bits of CSMA_SEED, bits[10:8] *                           Seed for the random number generator in the *                           CSMA/CA algorithm. *  \retval RADIO_SUCCESS The CSMA algorithm was configured successfully. *  \retval RADIO_WRONG_STATE This function should not be called in the *                          SLEEP state. */radio_status_tradio_configure_csma(uint8_t seed0, uint8_t be_csma_seed1){    /*Check state.*/    if (radio_is_sleeping() == true){        return RADIO_WRONG_STATE;    }    /*Extract parameters, and configure the CSMA-CA algorithm.*/    uint8_t back_off_exponent = (be_csma_seed1 & 0xC0) >> 6;    uint8_t csma_retries      = (be_csma_seed1 & 0x38) >> 3;    uint8_t seed1             = (be_csma_seed1 & 0x07);    hal_subregister_write(SR_MAX_FRAME_RETRIES, 0); /* AT86RF230 rev A errata. */    hal_subregister_write(SR_MAX_CSMA_RETRIES, csma_retries);    hal_subregister_write(SR_MIN_BE, back_off_exponent);    hal_register_write(RG_CSMA_SEED_0, seed0);    hal_subregister_write(SR_CSMA_SEED_1, seed1);    return RADIO_SUCCESS;}/*----------------------------------------------------------------------------*//**    \brief Calibrate the internal RC oscillator    This function calibrates the internal RC oscillator, based    on the 1 MHz clock supplied by the AT86RF2xx. In order to    verify the calibration result you can program the CKOUT fuse    and monitor the CPU clock on an I/O pin.    \return TRUE if calibrate passed; FALSE if calibrate failed.*/boolcalibrate_rc_osc_clkm(void){        bool success = false;    /*  Use the 1 MHz CLK_M from the AT86RF230. */    uint16_t temp, counter;    uint8_t osccal_saved;    uint8_t tccr2b, tccr1b, tccr1a;    /*  in the following line, 1000000ULL represents the 1MHz input signal */    /*  from the radio.  265 is the number of counts to overflow 8-bit */    /*  timer 2.  32 is the divide by 32 prescaler for timer 1.  F_CPU is */    /*  the main clock frequency. */#define TARGETVAL ((1000000ULL * 256 * 32) / F_CPU)        osccal_saved = OSCCAL;        cli();        radio_set_clock_speed(true, CLKM_1MHz);    /*  Save current values of timer status. */        tccr2b = TCCR2B;        tccr1b = TCCR1B;        tccr1a = TCCR1A;    /*  Stop timers 1 and 2. */    /*  Set timer 1 to normal mode (no CTC, no PWM, just count). */        TCCR2B = 0;        TCCR1B = 0;        TCCR1A = 0;    for (counter = 0; counter < 1000;  counter++){        /*  Delete pending timer 1 and 2 interrupts, and clear the */        /*  counters. */            TIFR1 = 0xFF;            TIFR2 = 0xFF;            TCNT2 = 0;            TCNT1 = 0;        /*  Timer 2 driven from clock divided by 32 */            TCCR2B = (1 << CS21) | (1 << CS20);        /*  Timer 1 driven with external clock */            TCCR1B = (1 << CS12) | (1 << CS11);        /*  Wait for timer 2 to overflow. */        while (!(TIFR2 & (1 << TOV2))){                ;        }        /*  Stop timer 1.  Now, TCNT1 contains the number of CPU cycles */        /*  counted while timer 2 was counting */            TCCR1B = 0;            TCCR2B = 0;            temp = TCNT1;        if (temp < (uint16_t)(0.995 * TARGETVAL)){            /*  Too fast, slow down */                OSCCAL--;        } else if (temp > (uint16_t)(1.005 * TARGETVAL)){            /*  Too slow, speed up */                OSCCAL++;        } else {            /*  We are within +/- 0.5 % of our target frequency, so we're */            /*  done. */                success = true;                break;            }        }        radio_set_clock_speed(true, CLKM_DISABLED);    /*  restore timer status regs */        TCCR2B = tccr2b;        TCCR1B = tccr1b;        TCCR1A = tccr1a;    if (!success){        /*  We failed, therefore restore previous OSCCAL value. */            OSCCAL = osccal_saved;        }        return success;}/*----------------------------------------------------------------------------*//**    \brief Calibrate the internal RC oscillator    This function calibrates the internal RC oscillator, based    on an external 32KHz crystal connected to TIMER2. In order to    verify the calibration result you can program the CKOUT fuse    and monitor the CPU clock on an I/O pin.*/voidcalibrate_rc_osc_32k(void){    /* Calibrate RC Oscillator: The calibration routine is done by clocking TIMER2     * from the external 32kHz crystal while running an internal timer simultaneously.     * The internal timer will be clocked at the same speed as the internal RC     * oscillator, while TIMER2 is running at 32768 Hz. This way it is not necessary     * to use a timed loop, and keep track cycles in timed loop vs. optimization     * and compiler.     */    uint8_t osccal_original = OSCCAL;    volatile uint16_t temp;            /* This is bad practice, but seems to work. */    OSCCAL = 0x80;  //    PRR0 &= ~((1 << PRTIM2)|(1 << PRTIM1)); /*  Enable Timer 1 and 2 */    TIMSK2 = 0x00; /*  Disable Timer/Counter 2 interrupts. */    TIMSK1 = 0x00; /*  Disable Timer/Counter 1 interrupts. */    /* Enable TIMER/COUNTER 2 to be clocked from the external 32kHz clock crystal.     * Then wait for the timer to become stable before doing any calibration.     */    ASSR |= (1 << AS2);    while (ASSR & ((1 << TCN2UB)|(1 << OCR2AUB)|(1 << TCR2AUB)|(1 << TCR2BUB))) { ; }    TCCR2B = 1 << CS20;   /* run timer 2 at divide by 1 (32KHz) */    AVR_ENTER_CRITICAL_REGION();    uint8_t counter = 128;    bool cal_ok = false;    do{        /* wait for timer to be ready for updated config */        TCCR1B = 1 << CS10;        while (ASSR & ((1 << TCN2UB)|(1 << OCR2AUB)|(1 << TCR2AUB)|(1 << TCR2BUB))) { ; }        TCNT2 = 0x80;        TCNT1 = 0;        TIFR2 = 0xFF;        /* Wait for TIMER/COUNTER 2 to overflow. Stop TIMER/COUNTER 1 and 2, and         * read the counter value of TIMER/COUNTER 1. It will now contain the         * number of cpu cycles elapsed within the period.         */        while (!(TIFR2 & (1 << TOV2))){            ;            }        temp = TCNT1;        TCCR1B = 0;#define cal_upper (31250*1.05) // 32812 = 0x802c#define cal_lower (31250*0.95) // 29687 = 0x73f7        /* Iteratively reduce the error to be within limits */        if (temp < cal_lower) {            /* Too slow. Put the hammer down. */            OSCCAL++;        } else if (temp > cal_upper) {            /* Too fast, retard. */            OSCCAL--;        } else {            /* The CPU clock frequency is now within +/- 0.5% of the target value. */            cal_ok = true;        }        counter--;    } while ((counter != 0) && (false == cal_ok));    if (true != cal_ok) {        /* We failed, therefore restore previous OSCCAL value. */        OSCCAL = osccal_original;    }    TCCR2B = 0;    ASSR &= ~(1 << AS2);    /* Disable both timers again to save power. */    //    PRR0 |= (1 << PRTIM2);/* |(1 << PRTIM1); */    AVR_LEAVE_CRITICAL_REGION();}/** @} *//** @} *//*EOF*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -