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

📄 i2c.c

📁 2407DSP开发应用程序实例(有14个常用模块程序)
💻 C
字号:
//I2C串行日历时钟与TMS320LF2407的接口及应用
// 源程序代码:
// 该程序实现对I2C总线日历时钟芯片PCF8583的读写操作 
#include  "register.h"
int wr_data[6],rd_time[4],set_time[4],year_base=0x2003,rd_data[5];
// 系统初始化子程序 
void	sysinit()
{
	asm( " setc INTM ");					// 关闭总中断 
	asm( " clrc SXM ") ;					// 抑制符号扩展 
	asm( " clrc OVM ") ;					// 累加器结果正常溢出 
	asm( " clrc CNF ") ;					// B0被配置为数据空间 
	SCSR1=0X81FE;					// CLKIN=6M,CLKOUT=40M 
	WDCR=0X0E8	;					// 不使能看门狗 
	IMR=0X00;						// 禁止所有中断 
	IFR=0X0FFFF;						// 清除所有的中断标志 
	WSGR=0x0FFFF;					// 不使能所有的等待状态 
}
// 输入输出口初始化子程序 
void	IOINIT()
{
	MCRC=MCRC&0X0F3FF;				// 配置IOPF2和IOPF3为一般的I/O口方式 
	PFDATDIR=PFDATDIR|0X0C0C;			// 配置IOPF2和IOPF3为输出方式,且SCL=SDA=1 
} 
// 软件延时子程序 
void delay(unsigned int x)
{
	int  i;
	for(i=0;i<x;i++)	{i=i;}
}
// 启动I2C总线子程序 
void	START()
	{	
		PFDATDIR=PFDATDIR|0X000C;			// SDA=SCL=1 
		delay(72);								// 软件延时,以使时序匹配 
		PFDATDIR=PFDATDIR&0X0FFF7;		// SDA=0 
		delay(72);								// 软件延时,以使时序匹配 
		PFDATDIR=PFDATDIR&0X0FFFB;			// SCL=0 
		delay(24);								// 软件延时,以使时序匹配 
	}
// 发送字节子程序 
void	TRANSMIT(TRAN)
	int    TRAN;
	{
		int flag,sz;								// 定义需要的局部变量 
		PFDATDIR=PFDATDIR&0X0FFFB;	// SCL=0    
		delay(72);								// 软件延时,以使时序匹配 
		for(flag=0x0080;flag!=0x00;flag=flag>>1)
		{
		sz=TRAN&flag;							// 屏蔽掉不需要的位 
		if(sz==0)	PFDATDIR=PFDATDIR&0X0FFF7;// 如果相应的位为0,则SDA=0 
		else	PFDATDIR=PFDATDIR|0X0008;		// 如果相应的位为1,则SDA=1 
		delay(72);								// 软件延时,以使时序匹配 
		PFDATDIR=PFDATDIR|0X0004;			// SCL=1 
		delay(72);								// 软件延时,以使时序匹配 
		PFDATDIR=PFDATDIR&0X0FFFB;	// SCL=0 
		delay(24);								// 软件延时,以使时序匹配 
		}
}
// 从机(即PCF8583芯片)应答子程序。返回值为0时,代表操作成功;返回值为1时,代表操
// 作失败 
int	SLAVE_ACK()
{
	int    sz,k=0;							// 定义所需要的局部变量 
	PFDATDIR=PFDATDIR|0X0008;			// SDA=1 
	delay(24);								// 软件延时,以使时序匹配 
	PFDATDIR=PFDATDIR&0X0F7FF;		// 设置IOPF3(SDA)为输入 
	delay(24);								// 软件延时,以使时序匹配 
	PFDATDIR=PFDATDIR|0X0004;			// SCL=1 
	delay(24);								// 软件延时,以使时序匹配 
	sz=PFDATDIR&0X0008;					// 检测数据位 
	if(sz==0X0008)  k=1;						// 如果数据位为1,则证明失败,则令k=1 
	else  k=0;  	 						// 如果数据位为0,则证明成功,则保持k=0不变 
	PFDATDIR=PFDATDIR|0X0800;			// 设置IOPF3(SDA)为输出 
	PFDATDIR=PFDATDIR&0X0FF03;		// SCL=SDA=0 
	return(k);
}
// I2C停止子程序 
void    STOP()
	{ 
		PFDATDIR=PFDATDIR&0X0FFF7;		// SDA=0 
		delay(24);
		PFDATDIR=PFDATDIR|0X0004;			// SCL=1 
		delay(24);								// 软件延时,以使时序匹配 
		PFDATDIR=PFDATDIR|0X0008;			// SDA=1 
		delay(24);
	}
// 字节写子程序,即向I2C器件写1个字节的数据,入口为地址BYTE_ADDR和需要写入的
// 字节
// 内容T_DATA。返回值为0时,代表操作成功;返回值为1时,代表操作失败 
int	BYTE_WR(BYTE_ADDR,T_DATA)
int	BYTE_ADDR,T_DATA;
	{
		int  k;
		START();								// 启动I2C总线 
		TRANSMIT(0X0A0);						// 送写控制字 
		k=SLAVE_ACK();						// 从机(即PCF8583芯片)应答 
		if(k==0)	 TRANSMIT(BYTE_ADDR);		// 送出地址 
		 k=SLAVE_ACK();				// 从机(即PCF8583芯片)应答 
		if(k==0)	TRANSMIT(T_DATA);			// 送出需要保存的数据 
		k=SLAVE_ACK();				// 从机(即PCF8583芯片)应答 
		if(k==0)	STOP();						// 设置停止状态 
		return(k);
	}
// 接收一个字节子程序,出口为接收到的数据R_DATA 
int  RECEIVE()	
	{
	int  R_DATA=0,sz,i;
	PFDATDIR=PFDATDIR&0X0F7FF;		// 设置IOPF3(SDA)为输入 
	PFDATDIR=PFDATDIR&0X0FFFB;			// SCL=0 
	delay(72);								// 软件延时,以使时序匹配  
	for(i=0;i<8;i++)	{
	R_DATA=R_DATA<<1;					// R_DATA左移一位 
	PFDATDIR=PFDATDIR|0X0004;			// SCL=1 
	delay(72);								// 软件延时,以使时序匹配   
	sz=PFDATDIR&0X0008;					// 取得相应的数据位 
	if(sz==0)	 R_DATA=R_DATA&0XFFFE;		// 如果数据位为0,则R_DATA最低位清0 
	else  R_DATA=R_DATA|0x0001;			// 如果数据位为1,则R_DATA最低位置1 
	PFDATDIR=PFDATDIR&0X0FFFB;	// SCL=0 
	delay(24);								// 软件延时,以使时序匹配  
	}
	PFDATDIR=PFDATDIR|0X0800;			// 设置IOPF3(SDA)为输出 
	return(R_DATA);						// 返回接收的字节 
}
// 主机无应答信号子程序 
void	NO_ACK()
	{
		PFDATDIR=PFDATDIR|0X0004;			// SCL=1 
		delay(24);								// 软件延时,以使时序匹配 
		PFDATDIR=PFDATDIR&0X0FFFB;			// SCL=0 
	}
// 主机应答子程序 
void	MASTER_ACK()
	{
		PFDATDIR=PFDATDIR&0X0FFFB;	// SCL=0 
		PFDATDIR=PFDATDIR&0X0FFF7;		// SDA=0 
		PFDATDIR=PFDATDIR|0X0004;			// SCL=1 
		delay(24);								// 软件延时,以使时序匹配 
		PFDATDIR=PFDATDIR&0X0FFFB;	// SCL=0 
	}
// 字节读子程序,即从I2C器件读出1个字节的数据,入口为需要读出的地址BYTE_ADDR,
// 出口为读出的数据R_DATA,通过C语言的参数传递功能实现。返回值为0X0FFFF时,
// 表示操作失败;
// 否则操作成功 
int	BYTE_RD(int  BYTE_ADDR)
	{
		int	k,R_DATA;
		START();								// 启动I2C总线 
		TRANSMIT(0XA0);						// 送出写控制字,以写入地址字节 
		k=SLAVE_ACK( );						// 从机(即PCF8583芯片)应答 
		if(k==0)	TRANSMIT(BYTE_ADDR);// 送出需要读出数据的地址 
		k=SLAVE_ACK();						// 从机(即PCF8583芯片)应答 
		if(k==0)  {
		START( );								// 启动I2C总线 
		TRANSMIT(0XA1);
	}									// 送出读控制字 
	k=SLAVE_ACK();						// 从机(即PCF8583芯片)应答 
	if(k==0)
	{
		R_DATA=RECEIVE();					// 接收PCF8583发出的数据 
		NO_ACK();							// 主机不作应答 
		STOP();								// 设置停止状态 
	}
	if(k==0)  return(R_DATA);					// 返回一个读出的数据 
	else   return(0X0FFFF);					// 如果整个读过程有误,则返回0X0FFFF 
}
// 连续写子程序,入口为需要写的起始地址ADDR,存储需要写入数据的数组的首地址
// ARRY,需要写入的数据的个数N 
int	CON_WR(ADDR,ARRAY,N)
int   ADDR,*ARRAY,N;
{
		int	k;
		START();								// 启动I2C总线 
		TRANSMIT(0X0A0);						// 送写控制字 
		k=SLAVE_ACK();						// 从机(即PCF8583芯片)应答 
		if(k==0)	 TRANSMIT(ADDR);			// 送出要写数据的起始地址 
		k=SLAVE_ACK();				// 从机(即PCF8583芯片)应答 
		if(k==0)	 
		{
			for(;N>0;N--,ARRAY++)
			{ 
				
				TRANSMIT(*ARRAY&0x00FF);					// 送出需要保存的数据的低八位,保存在数组ARRAY中 
				k=SLAVE_ACK();						// 从机(即PCF8583芯片)应答,地址自动加1 
				if(k==1)	break;
			}
		}
		STOP();								// 设置停止状态 
		return(k);
}
// 连续读子程序,入口为需要读的起始地址ADDR,存储读出数据的数组首地址ARRY,需
// 要读出的数据的个数N 
int	CON_RD(ADDR,ARRAY,N)
int   ADDR,*ARRAY,N;
{
	int	k,R_DATA;         
	START();								// 启动I2C总线 
	TRANSMIT(0XA0);						// 送出写控制字,以写入地址字节 
	k=SLAVE_ACK();						// 从机(即PCF8583芯片)应答 
	if(k==0)	TRANSMIT(ADDR);				// 送出需要读出数据的地址 
	k=SLAVE_ACK();						// 从机(即PCF8583芯片)应答 
	if(k==0)	
	{
		START();								// 启动I2C总线 
		TRANSMIT(0XA1);
	}									// 送出读控制字 
	k=SLAVE_ACK();						// 从机(即PCF8583芯片)应答 
	if(k==0)
	{
		for(;N>1;N--,ARRAY++)
		{
			R_DATA=RECEIVE();					// 接收PCF8583发出的数据 
			*ARRAY=R_DATA&0x00FF;						// 读出的数据存入数组 
			MASTER_ACK();						// 主机应答,地址自动加1   
		}
		R_DATA=RECEIVE();					// 接收PCF8583发出的数据        
		*ARRAY=R_DATA&0x00FF;						// 读出的数据存入数组 
		NO_ACK();							// 主机不作应答 
		STOP();								// 设置停止状态 
	}
	return(k);								// k=0时表示操作成功,k=1时表示操作失败 
}  
 //
void time_WR()
{
	wr_data[0]=0x0;								//ms
	wr_data[1]=set_time[3]&0x00ff;			//second
	wr_data[2]=(set_time[3]&0xff00)>>8;		//minute
	wr_data[3]=set_time[2]&0x00ff;			//hour;
	wr_data[4]=((set_time[0]&0x03)<<6)|(set_time[1]&0x003f);	//year/date
	wr_data[5]=((set_time[2]&0x0700)>>3)|((set_time[1]&0x1f00)>>8);	//week/month
	CON_WR(0x01,wr_data,6);
} 
//**********从8583中读时间子程序------------------**********/
void time_rd()							
{
	CON_RD(0x02,rd_data,5); 
	rd_time[0]=year_base+((rd_data[3]&0x00C0)>>6);//year
	rd_time[1]=((rd_data[4]&0x001f)<<8)|(rd_data[3]&0x003f);	//month,date
	rd_time[2]=((rd_data[4]&0x00e0)<<3)|rd_data[2];	//week.hour
	rd_time[3]=(rd_data[1]<<8)|rd_data[0];		//minute,second
	
}
// 主程序 
main()
{
int       k;
int       R_DATA;
	sysinit();								// 系统初始化 
	IOINIT();								// 输入输出口初始化 
	set_time[0]=0x2003;/*2003年*/
	set_time[1]=0x1231;/*12月31日*/
	set_time[2]=0x0523;/*星期五23时*/
	set_time[3]=0x5930;/*59分30秒*/ 
	time_WR();
//	k=BYTE_WR(0x00,0x00);			/* 设置PCF8583的控制状态寄存器,其地址为0x00,值0x00 
//代表的意义请参考相关资料,若k==0,则证明写入成功;若 k==1,则证明写入失败  */
//	R_DATA=BYTE_RD(0x00);		/*读出地址单元0X00的值,如果读出值为0X0FFFF,则表示
// 读出值有误,其地址为0x05,值0xD8代表的意义请参考相关资料,若k==0,则证明写入成功;,若k==1则证明写入失败                       
// 读出地址单元0X05的值,如果读出值为0X0FFFF,则表示
// 读出值有误*/ 
	while(1)
	{
		time_rd();
		asm(" nop"); 
	}
}  

//  直接返回中断服务子程序           
void interrupt nothing() 
{
	return;
}

⌨️ 快捷键说明

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