2012年8月17日 星期五

ATmega128 串列通信介面 source code

keyword : ATmega128 I2C  (TWI )  SM_bus 2-wire  SPI  UART  interface

1)  source codes  for ATmega128 UART

UARTM128.H
/* Prototypes */
void InitUART0( unsigned char baudrateL,unsigned char baudrateH );
unsigned char ReceiveByte0( void );
void TransmitByte0( unsigned char data );

void InitUART1( unsigned char baudrateL,unsigned char baudrateH );
unsigned char ReceiveByte1( void );
void TransmitByte1( unsigned char data );
 ...
UARTM128.C 
/* Code adapted from Atmel AVR Application Note AVR306
 * Interrupt mode driver for UART.
 */
#include < span>h>
#include < span>h>
#include "uartM128.h"

/* IMPORTANT: these vector numbers are for 8515! If you use other devices
 * you must change them to the different set of numbers.
 *
 * UART_RX_interrupt set to UART, Rx Complete
 * UART_TX_interrupt set to UART Data Register Empty
 */

#pragma interrupt_handler UART0_RX_interrupt:iv_USART0_RX UART0_TX_interrupt:iv_USART0_TX
#pragma interrupt_handler UART1_RX_interrupt:iv_USART1_RX UART1_TX_interrupt:iv_USART1_TX

/* UART Buffer Defines */
#define UART0_RX_BUFFER_SIZE 128 /* 1,2,4,8,16,32,64,128 or 256 bytes */
#define UART0_RX_BUFFER_MASK ( UART0_RX_BUFFER_SIZE - 1 )
#define UART0_TX_BUFFER_SIZE 128 /* 1,2,4,8,16,32,64,128 or 256 bytes */
#define UART0_TX_BUFFER_MASK ( UART0_TX_BUFFER_SIZE - 1 )

#define UART1_RX_BUFFER_SIZE 128 /* 1,2,4,8,16,32,64,128 or 256 bytes */
#define UART1_RX_BUFFER_MASK ( UART1_RX_BUFFER_SIZE - 1 )
#define UART1_TX_BUFFER_SIZE 128 /* 1,2,4,8,16,32,64,128 or 256 bytes */
#define UART1_TX_BUFFER_MASK ( UART1_TX_BUFFER_SIZE - 1 )

#if ( UART0_RX_BUFFER_SIZE & UART0_RX_BUFFER_MASK )
#error RX0 buffer size is not a power of 2
#endif
#if ( UART1_RX_BUFFER_SIZE & UART1_RX_BUFFER_MASK )
#error RX1 buffer size is not a power of 2
#endif

/* Static Variables */
static unsigned char UART0_RxBuf[UART0_RX_BUFFER_SIZE];
static volatile unsigned char UART0_RxHead;
static volatile unsigned char UART0_RxTail;
static unsigned char UART0_TxBuf[UART0_TX_BUFFER_SIZE];
static volatile unsigned char UART0_TxHead;
static volatile unsigned char UART0_TxTail;

static unsigned char UART1_RxBuf[UART1_RX_BUFFER_SIZE];
static volatile unsigned char UART1_RxHead;
static volatile unsigned char UART1_RxTail;
static unsigned char UART1_TxBuf[UART1_TX_BUFFER_SIZE];
static volatile unsigned char UART1_TxHead;
static volatile unsigned char UART1_TxTail;
/* initialize UART */
void InitUART0( unsigned char baudrateL,unsigned char baudrateH )
 {
 unsigned char x;
 UBRR0H = baudrateH;
    UBRR0L = baudrateL; /* set the baud rate */

 /* enable UART receiver and transmitter, and
 receive interrupt */
 UCSR0B = ( (1<<RXCIE0) | (1<EN0) | (1< /* flush receive buffer */
 UART0_RxTail = x;
 UART0_RxHead = x;
 UART0_TxTail = x;
 UART0_TxHead = x;
 }
void InitUART1( unsigned char baudrateL,unsigned char baudrateH )
{      unsigned char x;
      UBRR1H = baudrateH;
      UBRR1H = baudrateL;
    
      UCSR1B = ( (1< (1< = x;
 UART1_RxHead = x;
 UART1_TxTail = x;
 UART1_TxHead = x;
}
/* interrupt handlers */
void UART0_RX_interrupt( void )
{
 unsigned char data;
 unsigned char tmphead;
 data = UDR0; /* read the received data */
 /* calculate buffer index */
 tmphead = ( UART0_RxHead + 1 ) & UART0_RX_BUFFER_MASK;
 UART0_RxHead = tmphead; /* store new index */
 if ( tmphead == UART0_RxTail )
  {
  /* ERROR! Receive buffer overflow */
  }
 UART0_RxBuf[tmphead] = data; /* store received data in buffer */
}

void UART0_TX_interrupt( void )
{
 unsigned char tmptail;

 /* check if all data is transmitted */
 if ( UART0_TxHead != UART0_TxTail )
  {
  /* calculate buffer index */
  tmptail = ( UART0_TxTail + 1 ) & UART0_TX_BUFFER_MASK;
  UART0_TxTail = tmptail; /* store new index */
  UDR0 = UART0_TxBuf[tmptail]; /* start transmition */
  }
 else
  {
  UCSR0B &= ~(1<<UDRIE0); /* disable UDRE interrupt */
  }
 }

/* Read and write functions */
unsigned char ReceiveByte0( void )
 {
 unsigned char tmptail;

 while ( UART0_RxHead == UART0_RxTail ) /* wait for incomming data */
  ;
 tmptail = ( UART0_RxTail + 1 ) & UART0_RX_BUFFER_MASK;/* calculate buffer index */
 UART0_RxTail = tmptail; /* store new index */
 return UART0_RxBuf[tmptail]; /* return data */
 }

void TransmitByte0( unsigned char data )
 {
 unsigned char tmphead;
 /* calculate buffer index */
 tmphead = ( UART0_TxHead + 1 ) & UART0_TX_BUFFER_MASK; 
  /* wait for free space in buffer */

 while ( tmphead == UART0_TxTail )
  ;
 UART0_TxBuf[tmphead] = data; /* store data in buffer */
 UART0_TxHead = tmphead; /* store new index */
 UCSR0B |= (1< }

unsigned char DataInReceiveBuffer0( void )
 {
 return ( UART0_RxHead != UART0_RxTail ); 
  /* return 0 (FALSE) if the receive buffer is empty */
 }
/* interrupt handlers1*/
void UART1_RX_interrupt( void )
{
 unsigned char data;
 unsigned char tmphead;
 data = UDR1; /* read the received data */
 /* calculate buffer index */
 tmphead = ( UART1_RxHead + 1 ) & UART1_RX_BUFFER_MASK;
 UART1_RxHead = tmphead; /* store new index */
 if ( tmphead == UART1_RxTail )
  {
  /* ERROR! Receive buffer overflow */
  }
 UART1_RxBuf[tmphead] = data; /* store received data in buffer */
}

void UART1_TX_interrupt( void )
{
 unsigned char tmptail;

 /* check if all data is transmitted */
 if ( UART1_TxHead != UART1_TxTail )
  {
  /* calculate buffer index */
  tmptail = ( UART1_TxTail + 1 ) & UART1_TX_BUFFER_MASK;
  UART1_TxTail = tmptail; /* store new index */
  UDR1 = UART1_TxBuf[tmptail]; /* start transmition */
  }
 else
  {
  UCSR1B &= ~(1< terrupt */
  }
 }

/* Read and write functions */
unsigned char ReceiveByte1( void ) {
 unsigned char tmptail;

 while ( UART1_RxHead == UART1_RxTail ) /* wait for incomming data */
  ;
 tmptail = ( UART1_RxTail + 1 ) & UART1_RX_BUFFER_MASK;/* calculate buffer index */
 UART1_RxTail = tmptail; /* store new index */
 return UART1_RxBuf[tmptail]; /* return data */ }

void TransmitByte1( unsigned char data )
 {
 unsigned char tmphead;
 /* calculate buffer index */
 tmphead = ( UART1_TxHead + 1 ) & UART1_TX_BUFFER_MASK; 
  /* wait for free space in buffer */

 while ( tmphead == UART1_TxTail )
  ;
 UART0_TxBuf[tmphead] = data; /* store data in buffer */
 UART1_TxHead = tmphead; /* store new index */
 UCSR1B |= (1< enable UDRE interrupt */
 }

unsigned char DataInReceiveBuffer1( void )
 {
 return ( UART1_RxHead != UART1_RxTail ); 
  /* return 0 (FALSE) if the receive buffer is empty */
 }
/* main - a simple test program*/
void main( void )
 {
 InitUART0( 51,0 ); /*set the baudrate to 9600 bps using a 4MHz crystal*/
         InitUART1( 51,0 ); 
 _SEI();            /* enable interrupts => enable UART interrupts */
 while ( 1 )        /* forever */
  {
                  /*echo the received character*/
TransmitByte0( ReceiveByte0() );
 
                 /* echo the received character */                
                 TransmitByte0( ReceiveByte0() ); 
  }
 }

 ...
 
2)source codes for ATmega128 SPI
 
SPI.h
/*
**  Header file : spi.h
*/
#if defined(_AVR)
/* SPI header for AVR */
#ifndef  __SPI__H
#define  __SPI__H

/*
**  Constants for SpiInit()
*/
#define     SPI_DATA_ORDER_MSB_FIRST    0x00
#define     SPI_DATA_ORDER_LSB_FIRST    0x40
#define     SPI_CLOCK_POLARITY          0x08     
#define     SPI_CLOCK_PHASE             0x04     
#define     SPI_CLOCK_RATE_DIV4         0x00
#define     SPI_CLOCK_RATE_DIV16        0x01
#define     SPI_CLOCK_RATE_DIV64        0x02
#define     SPI_CLOCK_RATE_DIV128       0x03

void SpiInit(unsigned char);
void SpiWriteByte(unsigned char);
unsigned char SpiReadByte(void);
unsigned char SpiReadDataReg(void);

#endif

/*
**  End of Header file
*/
#endif
 
SPI.c
 
/*
** Purpose:    SPI init, read & write routines without interrupt.
**              These routines works only as an SPI Master.
**
**  Version:    1.0.0, 29:th of July 1999
**
**  Author:     Lars Wictorsson
**              LAWICEL / SWEDEN
**              http://www.lawicel.com   lars@lawicel.com**
**  History:    1999-07-29  Created
*/

#include 
#include "spi.h"

/*
**  SpiInit() initializes the SPI as a master, enable it
**  and set it up as requested by parameter Controlregister.
**  See "spi.h" for availible parameter values, they could
**  be ORed together. See AVR SPI documentation for more 
**  detailed information.
*/
void SpiInit(unsigned char ControlRegister)
{
    DDRB  |= 0xB0;                         // Set SCK, MOSI & SS as outputs
    PORTB &= 0x5F;                         // clear bits MOSI, & SCK

    SPCR = ControlRegister + SPE + MSTR;   // Write to control register.
}

/*
**  SpiWriteByte() writes a byte to the SPI and waits until
**  it has been transmitted. This function doesn't
**  return any value back.
*/
void SpiWriteByte(unsigned char byte)
{
    SPDR = byte;
    while (!(SPSR & 0x80));
    byte = SPDR;
}

/*
**  SpiReadByte() first writes a byte (a dummy, since
**  that byte is to generate clock signals to "poll" home**  the byte from the slave. The function returns the
**  received byte.
*/
unsigned char SpiReadByte(void)
{
    SPDR = 0x00;
    while (!(SPSR & 0x80));
    return SPDR;
}

/*
**  SpiReadDataReg() reads the last byte in the SPI register
**  without any clock signals generated. Could be used
**  as reading the last byte received.
*/
unsigned char SpiReadDataReg(void)
{
    return SPDR;
}

 ...
 
3)source codes for ATmega128 I2C
 
I2C.h
// ***************     I2C driver V 1.0    ***************
// ***           Written By P. Fletcher-Jones          ***
// ***                Written on 06/6/01      ***
// ***                 Last MOD 15/11/01      ***
// ***       Compiled using ImageCraft C Comiler       ***
// *******************************************************


// ****************************** //
// *** I2C Hardware Interface *** //
// ****************************** //

#define SDA BIT1
#define SCL BIT0

#define I2C_PORT PORTD
#define I2C_DIR  DDRD
#define I2C_IN  PIND

void Init_I2C(void);
void I2C_Start (void);
void I2C_Stop (void);
void I2C_Clock (void);
unsigned char I2C_Ackn(void);
void Write_I2C_Control (unsigned char,unsigned char,unsigned char);
void Write_I2C_Byte(unsigned char);
unsigned char Read_I2C_Byte(void);

 ...
 
I2C.C
// ***************   I2C driver Demo V 1.0   *************
// ***           Written By P. Fletcher-Jones          ***
// ***                Written on 16/11/01      ***
// ***                 Last MOD 21/11/01      ***
// *******************************************************
// ***************     I2C driver V 1.0    ***************
// ***           Written By P. Fletcher-Jones          ***
// ***                Written on 16/11/01      ***
// ***                 Last MOD 21/11/01      ***
// ***       Compiled using ImageCraft C Comiler       ***
// *******************************************************

#include 
#include < span>>
#include 

#include "I2C.h"


// ******************************************** //
// *** This routine will setup the I2C Port *** //
// ******************************************** //

void Init_I2C(void)
{
 SETBIT(I2C_DIR,SCL);      // Set SCL to output 
 SETBIT(I2C_DIR,SDA );    // Set SDA to output
 
 SETBIT(I2C_PORT,SCL);    // Set SCL high
 SETBIT(I2C_PORT,SDA );    // Set SDA high
}



// ************************************************ //
// *** This routine will send the I2C Start Bit *** //
// ************************************************ //

void I2C_Start (void)
{
 SETBIT(I2C_PORT,SCL);  // Set SCL High
 SETBIT(I2C_PORT,SDA);  // Set SDA High
 
 SETBIT(I2C_DIR,SDA);    // Set SDA to output 
 CLEARBIT(I2C_PORT,SDA); // Clear SDA
}


// *********************************************** //
// *** This routine will send the I2C Stop Bit *** //
// *********************************************** //

void I2C_Stop (void)
{
 
 SETBIT(I2C_DIR,SDA);       // Set SDA to output
 
 CLEARBIT(I2C_PORT,SDA);    // Clear SDA
 CLEARBIT(I2C_PORT,SCL);    // Clear SCL
 
 SETBIT(I2C_PORT,SCL);     // Set SCL High
 SETBIT(I2C_PORT,SDA);     // Set SDA High
}


// ************************************************** //
// *** This routine will send the I2C clock pulse *** //// ************************************************** //

void I2C_Clock (void)
{
 SETBIT(I2C_PORT,SCL);    // Set SCL high
 NOP();      // Small Delay
 CLEARBIT(I2C_PORT,SCL);   // Set SCL low
}


// ******************************************************** //
// *** This routine will write a byte to the I2C device *** //
// ******************************************************** //
void Write_I2C_Byte(unsigned char byte)
{
 unsigned char i;

 SETBIT(I2C_DIR,SDA);      // Set SDA to output 
 CLEARBIT(I2C_PORT,SCL);
  
 for (i = 0; i < 8; i++){     // Loop for our 8 bits
 
 // Set or Clear SDA pin
  if((byte & 0x80) == 0x80) SETBIT(I2C_PORT, SDA); // Set I2C SDA PIN
  else CLEARBIT(I2C_PORT,SDA);       // Clear I2C SDA PIN
  
  SETBIT(I2C_PORT,SCL);   // Set SCL High, Clock data

  byte = byte << 1;   // Shift data in buffer right one
 
     CLEARBIT(I2C_PORT,SCL);   // Clear SCL
 }

 
 while(I2C_Ackn() );    // Check for acknowledge from I2C device }


// ********************************************************* //
// *** This routine will read a byte from the I2C device *** //
// ********************************************************* //

unsigned char Read_I2C_Byte(void)
{ 
 unsigned char i,buff = 0;
 
 for (i = 0; i < 8; i++){
 
  buff = buff << 1;
  
   CLEARBIT(I2C_DIR,SDA);       // Set SDA to input
  
  SETBIT(I2C_PORT,SCL);       // Set SCL High,Clock bit out
 
  // Read data on SDA pin
  if ( CHECKBIT( I2C_IN,SDA ) ) buff = buff | 0x01; 
  
  CLEARBIT(I2C_PORT,SCL);       // Clear SCL  
        }

 // *** No ACK *** //
  I2C_Clock();        // Clock I2C bit
 
 return buff;        // Return our I2C byte
}


// *********************************************************************** //
// *** This routine returns a 0 if the I2C device sends an acknowledge *** //
// *********************************************************************** //

unsigned char I2C_Ackn(void)
{
 unsigned char Ackn = 0;     // Temp RAM for Ackn flag
 
 CLEARBIT(I2C_PORT,SCL);
 CLEARBIT(I2C_DIR,SDA);        // Set SDA to input 
 
 SETBIT(I2C_PORT,SCL);      // Clock the ACK bit
 if ( CHECKBIT( I2C_IN,SDA ) ) Ackn = 1;  // Check the ACK bit on SDA 
 
 CLEARBIT(I2C_PORT,SCL);       // Clear the clock

 return Ackn;       // Return our ACK bit
} 


// ***************************************************** //
// *** This routine will write the I2C device code,  *** //
// *** set the device chip select bits,           *** //
// *** and set or clear the I2C R/W bit     *** //
// ***************************************************** //

void Write_I2C_Control(unsigned char D_Code,unsigned char H_ADD,unsigned char RW)
{

 // *** Send the I2C device Control code *** //

 CLEARBIT(I2C_PORT,SCL);                  // Clear SCL clock 
 if( (D_Code & 0x08) == 0x08) SETBIT(I2C_PORT, SDA); // Set I2C SDA PIN
 else CLEARBIT(I2C_PORT,SDA);      // Clear I2C SDA PIN
 I2C_Clock();   // Clock I2C bit
 
 if( (D_Code & 0x04) == 0x04) SETBIT(I2C_PORT, SDA); // Set I2C SDA PIN
 else CLEARBIT(I2C_PORT,SDA);      // Clear I2C SDA PIN
 I2C_Clock();   // Clock I2C bit
 
 if( (D_Code & 0x02) == 0x02) SETBIT(I2C_PORT, SDA); // Set I2C SDA PIN
 else CLEARBIT(I2C_PORT,SDA);      // Clear I2C SDA PIN

 I2C_Clock();   // Clock I2C bit
  if( (D_Code & 0x01) == 0x01) SETBIT(I2C_PORT, SDA); // Set I2C SDA PIN
 else CLEARBIT(I2C_PORT,SDA);      // Clear I2C SDA PIN

 I2C_Clock();   // Clock I2C bit

 
 // *** Send the I2C Control byte chip selects bits *** //

 if( (H_ADD & 0x04) == 0x04) SETBIT(I2C_PORT, SDA); // Set I2C SDA PIN
 else CLEARBIT(I2C_PORT,SDA);      // Clear I2C SDA PIN
 I2C_Clock();   // Clock I2C bit
  if( (H_ADD & 0x02) == 0x02) SETBIT(I2C_PORT, SDA); // Set I2C SDA PIN
 else CLEARBIT(I2C_PORT,SDA);      // Clear I2C SDA PIN

 I2C_Clock();   // Clock I2C bit
 
 if( (H_ADD & 0x01) == 0x01) SETBIT(I2C_PORT, SDA); // Set I2C SDA PIN
 else CLEARBIT(I2C_PORT,SDA);      // Clear I2C SDA PIN
 I2C_Clock();   // Clock I2C bit
 
 // *** Set or Clear the read / write bit for I2C control *** //
 
 if(RW) SETBIT(I2C_PORT,SDA);               // Set I2C SDA PIN
 else CLEARBIT(I2C_PORT,SDA);        // Clear I2C SDA PIN
 
 I2C_Clock();   // Clock I2C bit
 
 while(I2C_Ackn() );  // Check for acknowledge from I2C device
}


void EEPROM_Write(unsigned char, unsigned char, unsigned char);
unsigned char EEPROM_Read(unsigned char, unsigned char);


// **************************************************************** //
// ***                     Init_I2C();       *** //
// *** This routine will setup the I2C port direction registers *** //
// **************************************************************** //

// ***************************************************************** //// ***                     I2C_Start();               *** //
// *** This routine will set the I2C start condition on the bus, *** //
// *** All commands must be preceded by a START condition    *** //
// ***************************************************************** //

// ***************************************************************** //
// ***                     I2C_Stop();               *** //
// *** This routine will set the I2C stop condition on the bus,  *** //
// *** All commands must end with a STOP condition            *** //
// ***************************************************************** //

// *********************************************************************** //
// ***                Write_I2C_Control(0x0A,0,0);               *** //
// *** This routine will write the I2C device code, the device address *** //
// *** setup on the hardware pins A0,A1 & A2, and also the W/R bit     *** //
// *** So for an external EEPROM, such as the 24LC04B you would need   *** //
// *** a device code of 1010 (0x0A),                      *** //
// *** hardware address 0 (if pins A0,A1 & A2 are left unconnected,    *** //
// *** and the last parameter is R/W. Write is active low      *** //
// *********************************************************************** //

// *********************************************************************** //
// ***                          I2C_Ackn();          *** //
// *** This routine will clock the ACK bit from the I2C slave device   *** //
// *** it will return TRUE for a fail, and FALSE for a correct ACK bit *** //
// *********************************************************************** //

// ************************************************************** //// ***                     Write_I2C_Byte();      *** //
// *** This routine will clock a byte to the slave I2C device *** //
// ************************************************************** //

// ************************************************************************** //
// ***                       Read_I2C_Byte();               *** //
// *** This routine will read and return a byte from the I2C slave device *** //
// ************************************************************************** //



// *********************************************************************** //
// ***                 Example of using Imagecraft I2C driver          *** //
// ***              to write to an external 8 bit address EEPROM       *** //
// *** H_ADD is the hardware address set on the device A0,A1 & A2 pins *** //
// *** M_ADD is the devices internal memory address                    *** //
// *** Data is user data to be writen            *** //
// *********************************************************************** //

void EEPROM_Write(unsigned char H_ADD, unsigned char M_ADD, unsigned char Data)
{
 I2C_Start();          // Set I2C start condition
 Write_I2C_Control(0x0A,H_ADD,0);    // Send the EEPROM control Byte

 Write_I2C_Byte(M_ADD);      // Send the EEPROM internal Address
  
 Write_I2C_Byte(Data);      // Send the EEPROM Data
 
 I2C_Stop();         // Set I2C Stop condition
}


// *********************************************************************** //
// ***              Example of using Imagecraft I2C driver             *** //
// ***            to Read an external 8 bit address EEPROM             *** //
// *** H_ADD is the hardware address set on the device A0,A1 & A2 pins *** //
// *** M_ADD is the devices internal memory address                    *** //
// *** Data is user data to be writen            *** //
// *********************************************************************** //

unsigned char EEPROM_Read(unsigned char H_ADD, unsigned char M_ADD)
{
 unsigned char Temp;    // Temp RAM for EEPROM Read
 
 I2C_Start();        // Set I2C start condition

 Write_I2C_Control(0x0A,H_ADD,0);  // Send the EEPROM control Byte
       // Dummy write to set address

 Write_I2C_Byte(M_ADD);    // Send the EEPROM internal Address
 
 I2C_Start();        // Set I2C start condition
 
 Write_I2C_Control(0x0A,H_ADD,1);  // Send the EEPROM control Byte
 
 Temp = Read_I2C_Byte();   // Read data from EEPROM
 
 I2C_Stop();       // Set I2C Stop condition

 return Temp;     // Return data from EEPROM
}










void main (void)
{
 unsigned long c;     // Temp Ram used for write delay
 
 DDRB = 0xFF;         // Set Port B to Outputs

 Init_I2C();         // Setup the hardware port

 EEPROM_Write(0xa2,1,0xAA);   // Write to device 0, memory address 1, Data 0xAA   
 
 for(c=0;c<1000;c++);    // Delay for EEPROM Write
 
 PORTB = EEPROM_Read(0xa3,1);   // Read device 0, memory address 1
} ...
 
 
http://www.codeforge.com/read/183736/I2C.h__html
 

CodeForge.com

Free Open Source Codes Forge and Sharing http://www.codeforge.com/

沒有留言:

張貼留言

注意:只有此網誌的成員可以留言。