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

📄 owiintfunctions.c

📁 达拉斯 1-Wire 主机通信 这份资料展示了如何把 1-Wire 主机通信在应用到一个AVR系统中
💻 C
字号:
// This file has been prepared for Doxygen automatic documentation generation.
/*! \file ********************************************************************
*
* Atmel Corporation
*
* \li File:               OWIIntFunctions.c
* \li Compiler:           IAR EWAAVR 3.20a
* \li Support mail:       avr@atmel.com
*
* \li Supported devices:  All AVRs with UART or USART module. 
*
* \li Application Note:   AVR318 - Dallas 1-Wire(R) master.
*                         
*
* \li Description:        Functions and Interrupt Service Routines that 
*                         handles automated transmission and reception of 0-255 
*                         bits. 
*
*                         $Revision: 1.7 $
*                         $Date: Thursday, August 19, 2004 14:27:18 UTC $
****************************************************************************/

#include "OWIIntFunctions.h"
#include <ioavr.h>
#include "OWIInterruptDriven.h"

OWIflags OWIStatus;
unsigned char *OWIDataBuffer;
unsigned char OWIBufferLength;


/*! \brief  Initialization of the U(S)ART for 1-Wire communication.
 *  
 *  This function configures the U(S)ART for 1-Wire communication.
 *
 *  \note   Parameters are set in "OWIInterruptDriven.h"
 */
void OWI_Init(void)
{
    // Choose single or double UART speed.
    OWI_UART_STATCTRL_REG_A = (OWI_UART_2X << OWI_U2X);
    
    // Enable UART receiver, transmitter and interrupt on receive;
    OWI_UART_STATCTRL_REG_B = (1 << OWI_RXEN) | (1 << OWI_TXEN) | (1 << OWI_RXCIE);

    // Set up asynchronous mode, 8 data bits, no parity, 1 stop bit.
    // (Initial value, can be removed)
    #ifdef URSEL
    OWI_UART_STATCTRL_REG_C = (1 << OWI_URSEL) | (1 << OWI_UCSZ1) | (1 << OWI_UCSZ0);
    #else
    OWI_UART_STATCTRL_REG_C = (1 << OWI_UCSZ1) | (1 << OWI_UCSZ0);
    #endif
    
    // Clear OWI flags.
    OWIStatus.allFlags = FALSE;
}


/*! \brief   Send the Reset signal on 1-Wire bus to receive presence
 *  signal from slave devices.
 * 
 *
 *  This function configures the UART module for transmission of the
 *  Reset signal. The busy flag is TRUE until the 1-Wire driver has 
 *  completed the Reset/Presence sequence. when the busy flag becomes 
 *  FALSE, the presence flag indicates whether a Presence signal was 
 *  received.
 */
void OWI_DetectPresence(void)
{
    // Set OWI busy flag
    OWIStatus.busy = TRUE;
    
    // Set the BAUD Rate to 9600 bps for reset/presence signalling.
    OWI_UART_BAUD_RATE_REG_L = OWI_UBRR_9600;
    
    // Enable UART data register empty interrupt to start the UART
    // transmitter.
    OWI_UART_STATCTRL_REG_B |= (1 << OWI_UDRIE);
}


/*! \brief  Transmit data on the 1-Wire bus. 
 *
 *  This function configures the UART module for transmission of data.
 *  The busy flag is TRUE until transmission is complete.
 *
 *  \param  data        Pointer to the data to be transmitted.
 *  
 *  \param  dataLength  The number of bits to be transmitted.
 */
void OWI_TransmitData(unsigned char * data, unsigned char dataLength)
{
    // Set OWI busy flag
    OWIStatus.busy = TRUE;
    
    // Set the data buffer pointer and data length.
    OWIDataBuffer = data;
    OWIBufferLength = dataLength;
    
    // Enable UART data register empty interrupt to start the UART
    // transmitter.    
    OWI_UART_STATCTRL_REG_B |= (1 << OWI_UDRIE);
}


/*! \brief  Receive data from the 1-Wire bus.
 *
 *  This function configures the UART module for reception of data.
 *  The busy flag is TRUE until reception is complete.
 *
 *  \param  data        A pointer to the location in memory where the 
 *                      received data should be placed
 *
 *  \param  dataLength  The number of bits to receive.
 */
void OWI_ReceiveData(unsigned char * data, unsigned char dataLength)
{
    unsigned char numBytes;

    // Fill buffer with 1's (Write 1 and Read waveforms are similar).
    numBytes = dataLength >> 3;
    if (dataLength & 0x07)
    {
        numBytes++;
    }
    
    while(numBytes)
    {
        data[numBytes - 1] = 0xff;
        numBytes--;
    }

    // Transmit the '1'-filled buffer on the bus to receive data.
    OWI_TransmitData(data, dataLength);
}


/*! \brief  UART Receive Complete Interrupt Service Routine
 *
 *  This ISR takes care of reception and interpretation of signals
 *  from the 1-Wire bus.
 */
#pragma vector = OWI_UART_RXC_VECT
__interrupt void UART_RXC_ISR()
{
    static unsigned char bitsReceived = 0;
    static unsigned char receiveBuffer = 0;
    static unsigned char byteIndex = 0;
    unsigned char waveform;
    
    // Check for frame error.
    if (OWI_UART_STATCTRL_REG_A & (1 << OWI_FE))
    {
        // Frame error.
        // Could be caused by a slave connecting to the bus, noice
        // or a short on the bus pulling it low.

        // Read UART DATA REGISTER to clear FE and RXC flags.
        waveform = OWI_UART_DATA_REGISTER;
        
        // Flag error, and clean up.
        OWIStatus.error = TRUE;
        OWIStatus.busy = FALSE;
        OWI_UART_STATCTRL_REG_B &= ~(1 << OWI_UDRIE);
        return;
    }    

    // Read the UART data register to get the waveform for this bit.
    waveform = OWI_UART_DATA_REGISTER;
    
    // If the Baud rate is 9600, check for presence signal.
    if (OWI_UART_BAUD_RATE_REG_L == OWI_UBRR_9600)
    {
        // Set presenceDetected flag if waveform is different from 
        // what was transmitted on the bus.
        OWIStatus.presenceDetected = (waveform != OWI_UART_RESET);

        // Set UART baud rate to 115200 bps.
        OWI_UART_BAUD_RATE_REG_L = OWI_UBRR_115200;

        // Reset bits received counter.
        bitsReceived = 0;

        // Set busy flag to FALSE.
        OWIStatus.busy = FALSE;
    }
    else // Baud rate != 9600.
    {
        // Increase bits received counter.
        bitsReceived++;

        // Right shift receive buffer.
        receiveBuffer >>= 1;

        // Check value of received bit.
        if (waveform == OWI_UART_READ_BIT) // Received 1.
        {
            // Set msb of receive buffer
            receiveBuffer |= 0x80;
        }
        else // Received 0.
        {
            // Do nothing, a 0 has already been shifted in.
        }

        // Was this the last bit?
        if (bitsReceived == OWIBufferLength)
        {
            // Right shift receive buffer to align bits.
            // Only needed when the number of bits is not divisible by 8.
            while(bitsReceived++ & 0x07)  
            {
                receiveBuffer >>= 1;   
            }
            // Insert the received data in the OWI Data buffer.
            OWIDataBuffer[byteIndex] = receiveBuffer;
            
            // Clean up.
            bitsReceived = 0;
            byteIndex = 0;
            OWIStatus.busy = FALSE;
        }
        else // Not the last bit.
        {
            // Is bitsReceived divisible with 8?
            // If so, one byte has been received and the receive buffer
            // must be placed in the big OWI data buffer. 
            if (!(bitsReceived & 0x07))
            {
                // Put the received byte in the data buffer and increment byte index.
                OWIDataBuffer[byteIndex] = receiveBuffer;                
                byteIndex++;
            }
        }
    }    
    return;
}


/*! \brief  UART Data Register Empty Interrupt Service Routine
 *
 *  This ISR is run every time the UART transmit buffer is empty, thus
 *  automating the process of transmitting and receiving bits.
 */
#pragma vector = OWI_UART_UDRE_VECT
__interrupt void UART_UDRE_ISR()
{
    static unsigned char bitsSent = 0;
    static unsigned char transmitBuffer;
    static unsigned char byteIndex = 0;
    
    // If the UART Baud Rate is 9600 bps, send the Reset signal.
    if (OWI_UART_BAUD_RATE_REG_L == OWI_UBRR_9600)
    {
        //Send Reset signal.
        OWI_UART_DATA_REGISTER = OWI_UART_RESET;
        
        // Reset bits sent counter.
        bitsSent = 0;

        // Clear UDRIE flag.
        OWI_UART_STATCTRL_REG_B &= ~(1 << OWI_UDRIE);

        return;
    }
    
    // If this is the first bit in a new transmission, fetch
    // the first byte from the OWI data buffer and reset
    // byte index.
    if (bitsSent == 0)
    {
        byteIndex = 0;
        transmitBuffer = OWIDataBuffer[0];        
    } 
    
    // If this is the last bit in the transmission, clean up.  
    if (bitsSent == OWIBufferLength)
    {
        bitsSent = 0;
        OWI_UART_STATCTRL_REG_B &= ~(1 << OWI_UDRIE);
    }
    else // Not the last bit.
    {
        // Check lsb of the transmit buffer and transmit corresponding
        // waveform on the bus.
        if (transmitBuffer & 0x01)
        {
            OWI_UART_DATA_REGISTER = OWI_UART_WRITE1;
        }
        else
        {
            OWI_UART_DATA_REGISTER = OWI_UART_WRITE0;
        }
        
        // Right shift transmit buffer.
        transmitBuffer >>= 1;
        
        // Increase bits sent counter.
        bitsSent++;

        // If the number of bits sent is divisible by 8, a whole byte has
        // been shifted out. Fetch a new from the OWI data buffer.
        if (!(bitsSent & 0x07))
        {
            byteIndex++;
            transmitBuffer = OWIDataBuffer[byteIndex];
        }
    }
    return;
}

⌨️ 快捷键说明

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