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

📄 iic.c

📁 2.4G无线音箱的接收程序,采用ATMEGA8单片机和STS公司的无线模块完成
💻 C
字号:
/******************************************************************************
*
* Purpose:      IIC.c
*
* Creator:      Rob Lansbergen
*
* Version:		$Revision: 7 $
*
* File Name:	$Workfile: iic.c $
*
* Author:		Rob Lansbergen
*
* Check in:		$Author: Chong.cheeleong $
*
* The information is provided 揳s is?without any express or implied warranty  
* of any kind, * including warranties of merchantability, noninfringement of   
* intellectual property, or fitness for any particular purpose. In no event sha
* Wireless Sound Solutions and/or its affiliate companies, or its suppliers be 
* liable for any damages whatsoever arising out of the use of or inability to  
* use the information or the materials. Wireless Sound Solutions, its affiliate
* companies, and its suppliers further do not warrant the accuracy or          
* completeness of information, text, graphics, or other items contained within 
* materials. Wireless Sound Solutions, Inc., may make changes to materials, or 
* the products described within, at any time, without notice.                  
* ?007 Wireless Sound Solutions. All rights reserved. Wireless Sound Solutions
* STS and STS-wireless are trademarks of Wireless Sound Solutions.        
******************************************************************************/
#include "pgmspace.h"
#include "defines.h"

#ifndef USE_ATMEL_I2C

unsigned char i2cSlaveAddress = 0x80;

/*
I2C wiring
SCL on SCL_PIN : uC output
SDA on SDA_PIN : uc input
*/

/** on AT128 use extra delay **/
#ifndef MCU_ATMEGA128
	#define FAST_I2C	/* slow version cost 100 Byte */
#endif /* END MCU_ATMEGA128 */

#ifdef FAST_I2C			/* No delay */
	#define i2c_half_delay()
	#define i2c_delay()
#else
	#define i2c_half_delay()
	#define i2c_delay()  {\
	int i=0;\
	while (i !=10) i++;\
	}    ;
/*
#define i2c_half_delay(){
	int i=0;\
	while (i !=10) i++;\
}
#define i2c_delay()  {\
	int i=0;\
	while (i !=20) i++;\
}	 ;
*/
#endif /* END FAST_I2C */


// SET SCL to input instead of Output High
//#define SCL_H()         {I2C_PORT = I2C_PORT |SCL_PIN;}   /* SCL high */
//#define SCL_L()         {I2C_PORT = I2C_PORT & ~SCL_PIN;} /* Pull SCL down */

#define SCL_H()         {I2C_DDR = I2C_DDR & ~SCL_PIN;    I2C_PORT = I2C_PORT & ~SCL_PIN;}  /* SCL high using external pull-up (SDA is input)*/
#define SCL_L()         {I2C_DDR = I2C_DDR | SCL_PIN;     I2C_PORT = I2C_PORT & ~SCL_PIN;}  /* Pull SCL down */

#define SDA_H()         {I2C_DDR = I2C_DDR & ~SDA_PIN;    I2C_PORT = I2C_PORT & ~SDA_PIN;}  /* SDA high using external pull-up (SDA is input)*/
#define SDA_L()         {I2C_DDR = I2C_DDR | SDA_PIN;     I2C_PORT = I2C_PORT & ~SDA_PIN;}  /* Pull SDA down */

unsigned char SDA_IN(void)
{
	if ((I2C_PIN & SDA_PIN) == 0x00) return(0);
	else return(1);
}


void SDA_OUT(unsigned char b)
{
	if (b == 0) {SDA_L();}
	else {SDA_H();}
}

unsigned char i2c_error = 0;                 /* Last error */


/*
 * Makes sure that the bus is in a known condition. Returns 1 on success,
 * 0 if some other device is pulling on the bus.
 */

void i2c_init(void)
{
	SCL_H();
	SDA_H();
	i2c_error = 0;
	return; 
}


/*
 * Generates a start condition on the bus. Returns 0 on success, 1 if some
 * other device is holding the bus.
 */
 
unsigned char i2c_start(void)
{
	SCL_H();        /* EHO: 15-07-2003 in case of repeated start, first scl high */
	i2c_half_delay();
	SDA_L();        /* Pull SDA down... */
	i2c_half_delay();
	SCL_L();        /* ...and then SCL -> start condition. */
	i2c_half_delay();
	return 0;
}


/*
 * Generates a stop condition on the bus. Returns 0 on success, 1 if some
 * other device is holding the bus.
 */

unsigned char i2c_stop(void)
{
	SDA_L();        /* Pull SDA down if it was not down */
	i2c_half_delay();
	SCL_H();        /* Let SCL go up */
	i2c_half_delay();
	SDA_H();        /* ...and then SDA up -> stop condition. */
	i2c_half_delay();
	return (0);
}


/*
 * Clock out one bit.
 * Returns 0 on success, 1 if we lose arbitration.
 */

unsigned char i2c_bit_out(unsigned char bout)
{
	int i = 0;
	SDA_OUT(bout);		/* Put data out on SDA */
	i2c_half_delay();
	SCL_H();			/* Let SCL go up */
	i2c_delay();
	while (i != 1) i++;	/* SCL must be at least 500 ns High */
	SCL_L();			/* Pull SCL back down */
	i2c_delay();
	return 0;			/* OK */
}


/*
 * Clock in one bit.
 */

unsigned char i2c_bit_in(void)
{
	unsigned char bin;
	int i	=	0;
	SDA_H();
	i2c_half_delay();
	SCL_H();			/* Let SCL go up */
	i2c_delay();
	bin = SDA_IN();		/* Read in data */
	while (i !=	1) i++;	/* SCL must be at least 500 ns High */
	i2c_delay();
	SCL_L();			/* Pull SCL back up */
	i2c_delay();
	return bin;			/* Return the sampled bit */
}


/*
 * Send one byte on the bus. No start or stop conditions are generated here,
 * but i2c_error will be set according to the result.
 * Returns 0 on success, 1 if we lose arbitration or if the slave doesn't
 * acknowledge the byte. Check i2c_error for the actual result on error.
 */

unsigned char i2c_byte_out(unsigned char dat)
{
	unsigned char  bit_count;
	bit_count = 8;
	while(bit_count)
	{
		if (dat & 0x80)
		{
			if (i2c_bit_out(1)) return 1;
		}
		else
		{
			if (i2c_bit_out(0)) return 1;
		}
		dat <<= 1;
		bit_count--;
	}
	if (i2c_bit_in())
	{
		i2c_error = I2CERR_NAK;
		return 1;
	}
	return 0;
}


/*
 * Reads one byte in from the slave. Ack must be 1 if this is the last byte
 * to be read during this transfer, 0 otherwise (as per I2C bus specification,
 * the receiving master must acknowledge all but the last byte during a
 * transfer).
 */

unsigned char i2c_byte_in(unsigned char ack)
{
	unsigned char bit_count, byte_in;

	bit_count = 8;
	byte_in = 0;

	while(bit_count)
	{
		byte_in <<= 1;
		if (i2c_bit_in()) byte_in |= 0x01;
		bit_count--;
	}

	i2c_bit_out(ack);
	SDA_H();

	return byte_in;
}



unsigned char I2C_Write_Byte(unsigned char map,	unsigned char data)
{
	return 	(I2C_Write_Buf(map, &data, 1, 0));
}

/* Value is returned And will not damage the Receive buffer  */
/* This is to prevent a byte read can dammage the buffer that was read in I2C_read_buf*/

unsigned char I2C_Read_Byte(unsigned char map)
{
	unsigned char tmp;
	unsigned char result;
		
	/* we do not want to overwrite RX_Data_recv_array[0] */
	tmp = RX_Data_recv_array[0];
	
    I2C_Read_Buf(map, 1);
    
	result = RX_Data_recv_array[0];
	/* set back the old data */
	RX_Data_recv_array[0] = tmp;

    return (result);
}

/* read data is availeble in RX_Data_recv_array */
unsigned char I2C_Read_Buf (unsigned char map, unsigned char rx_count)
{
	if ( I2C_Write_Buf (map, &map, 0, 0))/* second map addres is dummy pointer no data writtten only i2cSlave address and map address*/
	{
		/* If send fails, abort but don't send a stop condition if we lost
		arbitration */

		if (i2c_error != I2CERR_LOST) i2c_stop();
		return 1;
	}

	SDA_H();        /* One of these may be low now, in which case the next */
	SCL_H();        /*   start condition wouldn't be detected so make */
	i2c_delay();    /*   sure that they're up and wait for one delay slot */

	if (i2c_recv(rx_count)) return 1;

	return (i2c_error ? 1 : 0);
}


/*
 * Read in 'count' bytes from slave 'addr'.
 * Returns 0 on success.
 */

unsigned char i2c_recv(unsigned char count)
{
	unsigned char byteptr, byte_in;

	if (i2c_start()) return 1;
	i2c_error = 0;
	byteptr = 0;

	byte_in = i2cSlaveAddress  | 0x01;

	if (i2c_byte_out(byte_in))
	{
		if (i2c_error == I2CERR_NAK) i2c_stop();
		return i2c_error;
	}

	while(count)
	{
		if (--count)
		{
			byte_in = i2c_byte_in(0);
		}
		else
		{
			byte_in = i2c_byte_in(1);   /* No ACK during last byte */
		}
		RX_Data_recv_array[byteptr] = byte_in;
		byteptr++;
	}

	i2c_stop();

	return (i2c_error ? 1 : 0);
}


unsigned char I2C_Write_Buf (unsigned char addr, unsigned char *buf, unsigned char count, unsigned char flash_type)

{
	unsigned char byte_out;
	const unsigned char __flash *fl_buf;
	
	if (flash_type) fl_buf = (const unsigned char __flash *)buf;

	if (i2c_start()) return 1;
	i2c_error = 0;

	byte_out = i2cSlaveAddress & 0xFE;     /* Ensure that it's a write address */
	if (i2c_byte_out(byte_out))
	{
		if (i2c_error == I2CERR_NAK )
		{
			i2c_stop();
			
			putstring("NA ");
			putdec(addr);
			putchar('=');
			if (flash_type) puthex(*fl_buf);
			else 			puthex(*buf);
			putchar('\r');
			
		}
		return i2c_error;
	}
	byte_out = addr;
	count = count+1;                    /* Include map addres to byte count */
	while(count)
	{
		
	     if (Use_I2C_Log_Write == 1)
	     {
			if (count != 1)
			{
				puthex(i2cSlaveAddress);
				putchar('-');
				putdec(addr++);
				putchar('=');
				if (flash_type) puthex(*fl_buf);
				else 			puthex(*buf);
				putstring(" (");
				if (flash_type) putdec(*fl_buf);
				else 			putdec(*buf);
				putstring(")\r");
			}
		}
		
		if (i2c_byte_out(byte_out))
		{
			if (i2c_error == I2CERR_NAK)
			{
				i2c_stop();
			}
			return i2c_error;
		}
		if (flash_type) byte_out = *fl_buf++;
		else 			byte_out = *buf++;
		count--;
	}

	i2c_stop();
	return 0;
}

#endif /* USE_ATMEL_I2C */


⌨️ 快捷键说明

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