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

📄 i2c.c

📁 MP3播放程序
💻 C
字号:

//********************************************************************************************
//
// Title		: MP3测试 - 软I2C驱动程序
// Author		: Ant (gz_ant@126.com)
// Created		: 2005/02/16
// Revised		: 2005/02/19
// Version		: 0.1
// Target MCU	: MEGA16
// Editor Tabs	: 4
//
// 注: 	本代码用于测试STA013硬件及其驱动程序, 并非一个完整的MP3播放器程序.
//		上电后,会循环不停播放一段约2秒的MP3音乐.
//		硬件没有连接RAM缓冲及储存MP3文件的设备, MP3数据是保存在AVR的FLASH中.
//		本代码经测试, 但可能存有Bugs, 若你发现有任何Bug或有任何建议,
//		请来信告知: gz_ant@126.com
////		本代码部分来自"Procyon AVRlib": http://hubbard.engr.scu.edu/embedded/avr/avrlib/release_notes.html
//		特此感谢它的创始人: Pascal Stang !
//
//		感谢在www.21icbbs.com帮助过winsu的朋友, 希望使用者能发扬网络的 "自由,开放" 精神.
//********************************************************************************************

#include <stdio.h>
#include <stdlib.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <avr/twi.h>

#include "type.h"
#include "main.h"
#include "I2C.h"

#define SDA_DirPort			DDRC
#define SDA_OutPort			PORTC
#define SDA_InPort			PINC
#define SDA					1
#define SCK_DirPort			DDRC
#define SCK_OutPort			PORTC
#define SCK					0

#define SDAMask				(1<<SDA)

#define	WriteDeviceAddress		0xA0
#define	ReadDviceAddress		0xA1
#define IIC_TWO_ADDR			0

//定义I2C的延迟参数
#define    DelayX	5			//7.3M=>1;	8.4M=>2.建议5,因为将来的ClockCPU可以是16M


#define    SCL_1    {sbi(SCK_OutPort, SCK);_Nop(DelayX);}
#define    SCL_0    {cbi(SCK_OutPort, SCK);_Nop(DelayX);}
#define    SDA_1    {sbi(SDA_OutPort, SDA);_Nop(DelayX);}
#define    SDA_0    {cbi(SDA_OutPort, SDA);_Nop(DelayX);}

void  _Nop(u8 dly);
void I2C_Ini(void);
void IICStart(void);
void IICStop(void);
u8 IICRecAck(void);
void IICACK(void);
void IICNoAck(void);
void IICSendByte(unsigned char sendbyte);
unsigned char IICReceiveByte(void);


//=======================================================================
void  _Nop(u8 dly)       //延时
{
	while(dly--);
}
//=======================================================================
//初始化端口
void I2C_Ini(void)
{
	sbi(SCK_DirPort,SCK);			//SCK为输出
	sbi(SDA_DirPort,SDA);			//SDA为双向的,先设置为输出
//	sbi(WP_DirPort,WP);				//WP为输出

}
//=======================================================================
//启动总线。根据IIC协议,SCL为1时,SDA从1转变为0。
void IICStart(void)
{
	SCL_0;
	SDA_1;
	SCL_1;
	SDA_0;
	SCL_0;
}
//=======================================================================
//停止IIC总线。根据IIC协议,SCL为1时,SDA从0转变为1。
void IICStop(void)
{
	SCL_0;
	SDA_0;
	SCL_1;
	SDA_1;
	SCL_0;
}
//=======================================================================
//检查应答位,向I2C写数据时,I2C设备(EEPROM)正常接受到数据后在第9周期发出0应答,
//如果不正常接受到数据,则不以0应答而进入待命状态。
//写数据后需检查I2C设备是否有0应答。
u8 IICRecAck(void)
{
	u8 ack;

	SCL_0;
	SDA_0;
	SCL_1;
	
	cbi(SDA_DirPort, SDA);			//设置为输入
	sbi(SDA_OutPort, SDA);			//上拉
	ack=(SDA_InPort & SDAMask);		//读SDA应答位
	sbi(SDA_DirPort, SDA);			//恢复为输出
	
	SCL_0;
	return(ack);
}
//=======================================================================
//对IIC总线产生应答。读I2C设备时,如果下一步还要读则产生0应答。
void IICACK(void)
{
	SDA_0;
	SCL_1;
	SCL_0;
	SDA_1;
}
//=======================================================================
//不对IIC总线产生应答。读I2C设备时,如果下一步不需要读则产生1应答(即不应答)。
void IICNoAck(void)
{
	SDA_1;
	SCL_1;
	SCL_0;
}
//=======================================================================
//向IIC总线写数据。SCL=0时SDA的数据可改变,SCL=1时需保持SDA数据稳定。
void IICSendByte(unsigned char sendbyte)
{
	unsigned char j=8;
	for(;j>0;j--)
	{
		SCL_0;
		
		if(sendbyte&0x80)			SDA_1			//SCL=0时写数据到SDA
		else						SDA_0
		sendbyte<<=1;
		
		SCL_1;
	}
	SCL_0;
}
//=======================================================================
//从IIC总线上读数据。
unsigned char IICReceiveByte(void)
{
	u8 receivebyte=0,i=8;

	cbi(SDA_DirPort, SDA);		//设置SDA为输入
	sbi(SDA_OutPort, SDA);			//上拉
	
	SCL_0;
	while(i--)
	{
		SCL_1;
		receivebyte <<= 1;
		if(SDA_InPort & SDAMask) receivebyte |= 1;
		SCL_0;
	}
	
	sbi(SDA_DirPort, SDA);		//恢复SDA为输出
	return(receivebyte);
}

void ReadIC(u16 addr,u8 ReadLen,u8 *buff)
{
	u8 ERRORCOUNT=10;
	
	addr &= 0x0FFF;
	addr |= 0xA000;
	
	while(ERRORCOUNT--)
	{
		IICStart();
		IICSendByte((addr >> 8) & (~0x01));
		if(IICRecAck()) continue;
		IICSendByte((u8)addr);	
		if(IICRecAck()) continue;
   		
		IICStart();
		IICSendByte((addr >> 8) | 0x01);
		if(IICRecAck()) continue;
		
		while(--ReadLen)
		{
		   	*buff++=IICReceiveByte();
		   	IICACK();
		}
		*buff=IICReceiveByte(); 
		IICNoAck();
		
		break;
	}
	IICStop();	
}
//在指定地址写1Byte的数据。
void WriteICByte(u16 addr, u8 data)
{
	u8 ERRORCOUNT=10;
	
	addr &= 0x0FFF;
	addr |= 0xA000;
	
	while(ERRORCOUNT--)
	{
    	IICStart();
		IICSendByte((addr >> 8) & (~0x01));	
		if(IICRecAck()) continue;
		IICSendByte((u8)addr);
		if(IICRecAck()) continue;
   		IICSendByte(data);
   		IICACK();
   		break;
    }
    IICStop();	   
}
//
void WriteICPage(u16 addr,u8 ReadLen,u8 *buff)
{
	u8 ERRORCOUNT=10;
	
	addr &= 0x0FFF;
	addr |= 0xA000;
	
	while(ERRORCOUNT--)
	{
    	IICStart();
		IICSendByte((addr >> 8) & (~0x01));
		if(IICRecAck()) continue;
		IICSendByte((u8)addr);
		if(IICRecAck()) continue;
		
		while(ReadLen--)
   		{
   			IICSendByte(*buff++);
   			IICACK();
   		}
   		break;
    }
    IICStop();	
}

⌨️ 快捷键说明

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