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

📄 spidigio.c

📁 avr上的RTOS
💻 C
📖 第 1 页 / 共 2 页
字号:
    u_long bits = 0;    cbi(SPIDIGIO_SOUT_PORT, SPIDIGIO_SOUT_BIT);    /*     * Toggle the input strobe. The shift register will latch     * the current value at the parallel inputs into the shift     * register.     */    sbi(SPIDIGIO_LDI_PORT, SPIDIGIO_LDI_BIT);    delay_us(4);    cbi(SPIDIGIO_LDI_PORT, SPIDIGIO_LDI_BIT);    delay_us(4);    /* Loop for the specified number of bits. */    while (num--) {        /* Shift the resulting value first. */        bits <<= 1;        /*         * The shift register's serial output pin is connected to          * the port input pin. If this input is high, set the least          * significant bit of the resulting value. Otherwise leave          * it zero.         */        if (bit_is_set(SPIDIGIO_SIN_PIN, SPIDIGIO_SIN_BIT)) {            bits |= 1;        }        /*          * This will toggle the clock line, presenting the next bit         * at the shift register's serial output pin.         */        ShiftDigital();    }    return bits;}/*! * \brief Set digital outputs. * * SpiDigitalInit() must have been called by the application before  * calling this function. * * This routine does not check the validity of any parameter. * * \param num  Number of bits to set, typically 8, 16, 24 or 32, which is *             the maximum. The number must not be lower than the number  *             of shift register output bits. * \param bits The bit value to set. Only the number of bits specified are *             used, of which the most significant bit is shifted in first. */void SpiDigitalSet(ureg_t num, u_long bits){    u_long mask;    /* Nothing to do, if the number of bits is zero. */    if (num) {        /*         * Create the bit mask of the most significant bit. Note the UL          * specifier. Most compilers will use integers by default, when          * calculating of the right side. They do not consider the left         * side. In our case this would create unexpected results, if          * integers are 16 bit only.         */        mask = 1UL << (num - 1);        /* Loop for the specified number of bits. */        while (num--) {            /*             * The shift register input is connected to the CPU output.             * If the currently masked bit is set, then set the CPU             * output pin to high level. Otherwise set the output             * pin to low.             */            if (bits & mask) {                /* Set bit instruction. */                sbi(SPIDIGIO_SOUT_PORT, SPIDIGIO_SOUT_BIT);            }             else {                /* Clear bit instruction. */                cbi(SPIDIGIO_SOUT_PORT, SPIDIGIO_SOUT_BIT);            }            /* Let the value get settled. */            delay_us(4);            /* Toggle the shift register clock line. */            ShiftDigital();            /* Left shift the mask by one. */            mask >>= 1;        }        /*         * Toggle the output strobe line. The shift register will latch         * the shifted value and present it at its parallel output pins.         */        cbi(SPIDIGIO_LDO_PORT, SPIDIGIO_LDO_BIT);        delay_us(4);        sbi(SPIDIGIO_LDO_PORT, SPIDIGIO_LDO_BIT);    }}/*! * \brief Return the number of shifts required to get an expected bit  * value at the input. * * When calling this function, it is assumed, that the shift register is  * already filled with the complement of the input bit. * * If the search mode is zero, then the function will return the number  * of shifts until the bit value at the input appears at the output.  * This can be used to detect the total size of the shift register. * * If the search mode is set to one, then the input strobe will be  * toggled before shifting and the function returns the number of shifts  * until the first unmodified bit appears.  This can be used to detect  * the number of inputs. This method requires, that the parallel shift  * register inputs do not change during shifting. If they do change, then * the resulting number will be lower than expected. The routine may be  * called several times to compensate this problem. * * \param num   Total number of shifts, should be 8, 16, 24 or 32. * \param bit   Input bit, either 0 or 1. * \param smode Search mode. * * \return The number of shifts. */static ureg_t CountDigitalShifts(ureg_t num, ureg_t bit, ureg_t smode){    ureg_t i;    ureg_t rc = 0;    /*     * Toggle input strobe if we are searching the last modified bit.     * Input lines are latched on the falling edge.     */    if (smode) {        sbi(SPIDIGIO_LDI_PORT, SPIDIGIO_LDI_BIT);        delay_us(4);        cbi(SPIDIGIO_LDI_PORT, SPIDIGIO_LDI_BIT);    }    /*     * Set the shift register input.     */    if (bit) {        sbi(SPIDIGIO_SOUT_PORT, SPIDIGIO_SOUT_BIT);    } else {        cbi(SPIDIGIO_SOUT_PORT, SPIDIGIO_SOUT_BIT);    }    delay_us(4);    /*     * Do the requested number of shifts and watch the requested bit      * position.     */    for (i = 0; i < num; i++) {        if (bit_is_set(SPIDIGIO_SIN_PIN, SPIDIGIO_SIN_BIT)) {            if (bit) {                if (smode) {                    rc = i + 1;                } else if (rc == 0) {                    rc = i + 1;                }            }        } else {            if (bit == 0) {                if (smode) {                    rc = i + 1;                } else if (rc == 0) {                    rc = i + 1;                }            }        }        ShiftDigital();    }    return rc;}/*! * \brief Initialize the digital I/O shift register interface. * * This routine must be called before using the interface. * * Automatically detects the number of digital inputs and outputs. However, * the method used is limited and may fail on fast changing inputs. The * application should check the result for plausibility. It is save to * call the routine more than once. * * \param inputs  Pointer to an 8-bit value, where the number of  *                detected inputs will be stored. * \param outputs Pointer to an 8-bit value, where the number of  *                detected outputs will be stored. */void SpiDigitalInit(ureg_t * inputs, ureg_t * outputs){    ureg_t total = 0;    ureg_t i;    ureg_t cnt;    /*     * Determine the delay loop count based on the CPU clock.     */    if ((us_loops = (NutGetCpuClock() + 500000UL) / 4000000UL) < 1) {        us_loops = 1;    }    /*     * Set serial data output line direction.     */    sbi(SPIDIGIO_SOUT_DDR, SPIDIGIO_SOUT_BIT);    /*     * Set serial data input line direction and enable pullup.     */    sbi(SPIDIGIO_SIN_PORT, SPIDIGIO_SIN_BIT);    cbi(SPIDIGIO_SIN_DDR, SPIDIGIO_SIN_BIT);    /*     * Clock. Input data is shifted on the falling, output data on the      * rising edge.     */    sbi(SPIDIGIO_SCLK_PORT, SPIDIGIO_SCLK_BIT);    sbi(SPIDIGIO_SCLK_DDR, SPIDIGIO_SCLK_BIT);    /*     * UCN5841 output strobe. Shift register data appears on the output      * pins as long as this line is held high.     */    sbi(SPIDIGIO_LDO_PORT, SPIDIGIO_LDO_BIT);    sbi(SPIDIGIO_LDO_DDR, SPIDIGIO_LDO_BIT);    /*     * SN74HC165 input strobe. Data at input pins is latched in the shift      * register on the falling edge.     */    cbi(SPIDIGIO_LDI_PORT, SPIDIGIO_LDI_BIT);    sbi(SPIDIGIO_LDI_DDR, SPIDIGIO_LDI_BIT);    /*     * Fill the shift register with zeros. Then shift in ones until the      * first appears on the output. This gives us the total size plus one      * of the shift register.     */    CountDigitalShifts(32, 0, 0);    total = CountDigitalShifts(32, 1, 0) - 1;    /*     * Determine the number of inputs. We do this five times for zeros      * and ones and take the maximum count. This way we compensate      * changing inputs while counting.     */    *inputs = 0;    for (i = 0; i < 5; i++) {        if ((cnt = CountDigitalShifts(total, 0, 1)) > *inputs) {            *inputs = cnt;        }        if ((cnt = CountDigitalShifts(total, 1, 1)) > *inputs) {            *inputs = cnt;        }    }    *outputs = total - *inputs;}/*@}*/

⌨️ 快捷键说明

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