i2c.c

来自「zigbee 飞思卡尔 音频传输 基于ucos的所有源码」· C语言 代码 · 共 559 行

C
559
字号







#include "common.h"
#include "i2c.h"
#define debuf 
#undef debuf


void i2c_init(void)
{
	char i;
	//configure the i2c pin
	//set I2C module
	MCF_GPIO_PASPAR = 0x05;
	
	if( (MCF_I2C_I2SR & MCF_I2C_I2SR_IBB) !=0 )
	{
		printf("IBB is set\n");
		MCF_I2C_I2CR = 0x0;
		MCF_I2C_I2CR = 0xa0;
		i = MCF_I2C_I2DR;//dummy read of I2DR
		MCF_I2C_I2SR = 0x0;
		MCF_I2C_I2CR = 0x0;
	}
	
	
	MCF_I2C_I2FDR = 0x1f;  //set a prescaler to configue the i2C clock,
	//configure the FDR carefully ,don't set clock too fast.when set FDR regsiter =0x20 ,the I2C can't work. 
	
	MCF_I2C_I2AR = 0x0;//set slave address as 0
	
	MCF_I2C_I2CR = 1<<7;//enable i2c
	
	MCF_I2C_I2CR |= (0<<6);//set no interrupt mode
	
	printf("fdr=%d\n",MCF_I2C_I2FDR);
	printf("cr=%d\n",MCF_I2C_I2CR);
}


void i2c_generation_start(unsigned char calling_address)
{
	uint32 i =0 ;
	while( (MCF_I2C_I2SR & MCF_I2C_I2SR_IBB) !=0 );//wait until the bus clear
	
	
	MCF_I2C_I2CR |= MCF_I2C_I2CR_MTX;//set transmit mode
	
	MCF_I2C_I2CR |= MCF_I2C_I2CR_MSTA;//set master mode,and generate a start condition

	
	MCF_I2C_I2DR = calling_address;//D0=R/W;
	
	while( (MCF_I2C_I2SR & MCF_I2C_I2SR_IBB) ==0 );//if IBB is clear ,wait until it is set; 
	for(i = 0; i<20000; i++);//delay
}



/*
*is_sub_calling_address:0 -- don't have sub_calling_address ,so don't care  sub_calling_address and sub_address_count
*/
void i2c_event(char *buf,char calling_address,unsigned int *count,char *sub_calling_address,char *sub_address_count,char is_sub_calling_address)
{
		char i = 0;
		MCF_I2C_I2SR &= ~MCF_I2C_I2SR_IIF;//clear IIF
		if( (MCF_I2C_I2CR & MCF_I2C_I2CR_MSTA) ==0)//slave mode
		{
			if( (MCF_I2C_I2SR & MCF_I2C_I2SR_IAL) == 1 )//arbitration lost
			{
				MCF_I2C_I2SR &= ~MCF_I2C_I2SR_IAL;//clear IAL
				if( (MCF_I2C_I2SR & MCF_I2C_I2SR_IAAS) == 0)//IAAS=0
				{
					return;
				}
			} 
			else//not arbitration lost
			{
				if( (MCF_I2C_I2SR & MCF_I2C_I2SR_IAAS) == 0)//IAAS=0
				{
					if( (MCF_I2C_I2CR & MCF_I2C_I2CR_MTX) == 0)// receive mode
					{
						*buf = MCF_I2C_I2DR;
						buf++;
						(*count)--;
						return;
					}
					else// transmit mode
					{
						if( (MCF_I2C_I2SR & MCF_I2C_I2SR_RXAK) == 0) //receive ack
						{
							//i2c_transmit(*buf);//transmit one byte
							MCF_I2C_I2DR = *buf;
							(*count)--;
							buf++;
							return;
						}
						else//no ack
						{
							MCF_I2C_I2CR &= ~MCF_I2C_I2CR_MTX;//set  receive mode
							i = MCF_I2C_I2DR;//dummy read I2DR
							return;
						}
					}
				}
			}
			//IAAS =1
			if( (MCF_I2C_I2SR & MCF_I2C_I2SR_SRW) == 0 )//slave receive mode
			{
				MCF_I2C_I2CR &= ~MCF_I2C_I2CR_MTX;//set  receive mode
				i = MCF_I2C_I2DR;//dummy read I2DR
				return;
			}
			else//slave transmit mode
			{
				MCF_I2C_I2CR |= MCF_I2C_I2CR_MTX;//set  transmit mode
				//i2c_transmit(*buf);//transmit one byte
				MCF_I2C_I2DR = *buf;
				(*count)--;
				buf++;
				return;
			}
		}
		else//master mode
		{
			if( (MCF_I2C_I2CR & MCF_I2C_I2CR_MTX) ==0 )//receive mode
			{
				if(*count == 1)//is last byte
				{
					i2c_generate_stop_signal();
				}
				else//not last byte
				{
					if(*count == 2)//is 2nd last byte to be read
					{
						MCF_I2C_I2CR |= MCF_I2C_I2CR_TXAK;//set TXAK=1	
					}
				}
				*buf = MCF_I2C_I2DR;
				buf++;
				(*count)--;
				return;
			}
			else//transmit mode
			{
				if (*count == 1)//last byte
				{
					(*count)--;
					i2c_generate_stop_signal();
					return;
				}
				else//not last byte
				{
					(*count)--;
					if( (MCF_I2C_I2SR & MCF_I2C_I2SR_RXAK) == 0 )//receive ack
					{
						if( (calling_address & 0x01) == 0)//master write
						{
							//i2c_transmit(*buf);//transmit one byte
							MCF_I2C_I2DR = *buf;
							//(*count)--;
							buf++;
							return;
						}
						else//master receive
						{
							if(is_sub_calling_address == 0)//no sub calling address or have transmit sub calling address
							{
								MCF_I2C_I2CR &= ~MCF_I2C_I2CR_MTX;//set receive mode
								i = MCF_I2C_I2DR;//dummy read from i2DR
								return;
							}
							else//have sub calling address
							{
								//i2c_transmit(*sub_calling_address);//transmit next sub address
								MCF_I2C_I2DR = *sub_calling_address;
								(*sub_address_count)--;
								sub_calling_address++;
								if(*sub_address_count == 0)
									is_sub_calling_address = 0;
								return;
							}
						}
					}
					else//no ack
					{
						i2c_generate_stop_signal();
						return;
					}
				}
			}
		}
}


void i2c_generate_repeat_start(unsigned char calling_address)
{
	uint32 i=0;
	
	MCF_I2C_I2CR |= MCF_I2C_I2CR_MTX;//set transmit mode
	MCF_I2C_I2CR |= MCF_I2C_I2CR_RSTA;//generate a repeat start
	

	MCF_I2C_I2DR = calling_address;
	//while();
	for(i = 0; i<20000; i++);

	
	
	return;
	
}



void i2c_generate_stop_signal(void)
{
	uint32 i = 0;	
	MCF_I2C_I2CR &= ~MCF_I2C_I2CR_MSTA;//generate a stop and select a slave mode
	
	while( (MCF_I2C_I2SR & MCF_I2C_I2SR_IBB) !=0 );//if IBB is set ,wait until it is clear; 
	
	for(i = 0; i<20000; i++);//delay

}





void isl1208_write_byte(unsigned char register_byte,unsigned char data_byte)
{
	//char data[2] = {0};
	unsigned char data[2];
	unsigned char calling_address = 0;
	unsigned char data_count = 0;

	data_count = 2;	//dont include the address of device,but include the register address
	data[0] = register_byte;
	data[1] = data_byte;
	
	//printf("%d\n",data[1]);
	

	//start and write address
	//void i2c_generation_start(char calling_address)
	calling_address = isl1208_address & 0xFE;
	
		printf("start write\n");
//for debug
	#ifdef debuf

	printf("%x\n",MCF_I2C_I2CR);
	#endif
	
	i2c_generation_start(calling_address);//address and write direction
	
	
//for debug
	#ifdef debuf
	printf("%x\n",MCF_I2C_I2CR);
	#endif
	//write register address
	while ( (MCF_I2C_I2SR & MCF_I2C_I2SR_IIF) == 0);//wait IFF
	MCF_I2C_I2SR &= ~MCF_I2C_I2SR_IIF;//clear IIF
	if( (MCF_I2C_I2SR & MCF_I2C_I2SR_RXAK) == 0 )//receive ack
	{
		//for debug
	#ifdef debuf
	printf("%x\n",MCF_I2C_I2CR);
	#endif
		//i2c_transmit(*buf);//transmit one byte
			MCF_I2C_I2DR = data[0];
			//for debug
	//#ifdef debuf
	printf("%x\n",MCF_I2C_I2CR);
	//#endif
	}
	else//no ack
		{
			i2c_generate_stop_signal();
			printf("isl1208 write byte data[0] wrong!\n");
		}
		
	//write data byte
	while ( (MCF_I2C_I2SR & MCF_I2C_I2SR_IIF) == 0);//wait IFF
	MCF_I2C_I2SR &= ~MCF_I2C_I2SR_IIF;//clear IIF
	if( (MCF_I2C_I2SR & MCF_I2C_I2SR_RXAK) == 0 )//receive ack
	{
		//for debug
	#ifdef debuf
	printf("%x\n",MCF_I2C_I2CR);
	#endif
		//i2c_transmit(*buf);//transmit one byte
			MCF_I2C_I2DR = data[1];
	//for debug
	#ifdef debuf
	printf("%x\n",MCF_I2C_I2CR);
	#endif
	}
	else//no ack
		{
			i2c_generate_stop_signal();
			printf("isl1208 write byte data[1] wrong!\n");
		}
	
	//for debug
	#ifdef debuf
	printf("%x\n",MCF_I2C_I2CR);
	#endif
	
	//generat stop
	while ( (MCF_I2C_I2SR & MCF_I2C_I2SR_IIF) == 0);//wait IFF
	MCF_I2C_I2SR &= ~MCF_I2C_I2SR_IIF;//clear IIF
	//for debug
	#ifdef debuf
	printf("%x\n",MCF_I2C_I2CR);
	#endif
	i2c_generate_stop_signal();
	//for debug
	#ifdef debuf
	printf("%x\n",MCF_I2C_I2CR);
	#endif
	return;
	
	
}


char isl1208_read_byte(unsigned char register_byte)
{
	uint32 i = 0;
	unsigned char data = 0;
	unsigned char calling_address = 0;
	unsigned char data_count = 0;
	
	data_count = 1;	//don't include the address of device,but include the register address
	data = register_byte;
	
	//start and write address
	//void i2c_generation_start(char calling_address)
	calling_address = isl1208_address & 0xFE;
	//for debug
	#ifdef debuf
	printf("%x\n",MCF_I2C_I2CR);
	#endif
	
	MCF_I2C_I2CR &= ~MCF_I2C_I2CR_TXAK;//set TXAK=0	

	
	i2c_generation_start(calling_address);//address and write direction
	
	//for debug
	#ifdef debuf
	printf("%x\n",MCF_I2C_I2CR);
	#endif
	//write register address
	while ( (MCF_I2C_I2SR & MCF_I2C_I2SR_IIF) == 0);//wait IFF
	MCF_I2C_I2SR &= ~MCF_I2C_I2SR_IIF;//clear IIF
	if( (MCF_I2C_I2SR & MCF_I2C_I2SR_RXAK) == 0 )//receive ack
	{
		//for debug
	#ifdef debuf
	printf("%x\n",MCF_I2C_I2CR);
	#endif
		//i2c_transmit(*buf);//transmit one byte
			MCF_I2C_I2DR = data;
			//for debug
	#ifdef debuf
	printf("%x\n",MCF_I2C_I2CR);
	#endif
	}
	else//no ack
		{
			i2c_generate_stop_signal();
			printf("read byte wrong!\n");
		}
		
	
	
	//repeat start and device address
	calling_address = isl1208_address|0x1;//set read direction
	///for debug
	#ifdef debuf
	printf("%x\n",MCF_I2C_I2CR);
	#endif
	while ( (MCF_I2C_I2SR & MCF_I2C_I2SR_IIF) == 0);//wait IFF
	MCF_I2C_I2SR &= ~MCF_I2C_I2SR_IIF;//clear IIF
	//for debug
	#ifdef debuf
	printf("%x\n",MCF_I2C_I2CR);
	#endif
		
	
	i2c_generate_repeat_start(calling_address);
	//for debug
	//printf("address=%d",calling_address);
	
	MCF_I2C_I2CR |= MCF_I2C_I2CR_TXAK;//set TXAK=1
	//for debug
	#ifdef debuf
	printf("%x\n",MCF_I2C_I2CR);
	#endif
		
	MCF_I2C_I2CR &= ~MCF_I2C_I2CR_MTX;//set receive mode
	
	//for debug
	#ifdef debuf
	printf("%x\n",MCF_I2C_I2CR);
	#endif
	data = MCF_I2C_I2DR;//dummy read from i2DR
	//printf("data=%d",data);
	for(i = 0; i < 20000;i++);
	//MCF_I2C_I2DR;
	
	
	//read a data
	///for debug
	#ifdef debuf
	printf("%x\n",MCF_I2C_I2CR);
	#endif
	while ( (MCF_I2C_I2SR & MCF_I2C_I2SR_IIF) == 0);//wait IFF
	MCF_I2C_I2SR &= ~MCF_I2C_I2SR_IIF;//clear IIF
	//for debug
	#ifdef debuf
	printf("%x\n",MCF_I2C_I2CR);
	#endif
	data = MCF_I2C_I2DR;
	//printf("\ndata1=%d\n",data);
	//for debug
	#ifdef debuf
	printf("%x\n",MCF_I2C_I2CR);
	#endif
	//printf("data_f=%d",data);
	//MCF_I2C_I2CR |= MCF_I2C_I2CR_TXAK;//set TXAK=1	

	
	while ( (MCF_I2C_I2SR & MCF_I2C_I2SR_IIF) == 0);//wait IFF
	MCF_I2C_I2SR &= ~MCF_I2C_I2SR_IIF;//clear IIF
	i2c_generate_stop_signal();//generate stop 
	//for debug
	#ifdef debuf
	printf("%x\n",MCF_I2C_I2CR);
	#endif
	

	
	
	
	
	
	return data;
}





/*****************************************************************
*ucos-ii test task for FlexCAN
*******************************************************************/
OS_STK	AppTaskI2cIsl1208Stk[256];
void  AppTaskI2cIsl1208 (void * pdata)
{
	unsigned char i = 0;
	unsigned char data = 0;
	
	i2c_init();//init the i2c
	
	//void isl1208_write_byte(char register_byte,char data_byte)
	//set WRTC,XTOSCB,ARST
	isl1208_write_byte(0x07,0x90);//set sr register
	printf("write sr= \n");
	i = isl1208_read_byte(0x07);
	printf("%d\n",i);
	
	printf("start write INT register\n");
	isl1208_write_byte(0x08,0x10);//set INT register  ,forbiden the int and output frequency
	printf("write int = ");
	i = isl1208_read_byte(0x08);
	printf("%d\n",i);
	
	isl1208_write_byte(isl1208_rtc_sc,0x01);
	isl1208_write_byte(isl1208_rtc_mn,0x02);
	isl1208_write_byte(isl1208_rtc_hr,0x93);//set 24hours
	isl1208_write_byte(isl1208_rtc_dt,0x04);
	isl1208_write_byte(isl1208_rtc_mo,0x05);
	isl1208_write_byte(isl1208_rtc_yr,0x06);
	isl1208_write_byte(isl1208_rtc_dw,0x06);
	
	while (1)
	{
		//char isl1208_read_byte(char register_byte)
		data = isl1208_read_byte(6);
		printf("星期");
		printf("%d: ",data+1);
		
		data = isl1208_read_byte(5);
		printf("公元");
		if(data<10)
			printf("200%d: ",data);
		else
			printf("20%d:",data);
		
		data = isl1208_read_byte(4);
		printf("%d:",data);
		printf("月");
		
		data = isl1208_read_byte(3);
		printf("%d",(data&0xF0)>>4);
		printf("%d:",(data&0x0f));
		printf("日:");
		
		data = isl1208_read_byte(2);
		if((data&0x80) ==0)//12 hours format
			{
				if((data&0x20)==0)
				{
					
					printf("%d",(data&0xF0)>>4);
					printf("%d",(data&0x0f));
				}
				else
				{
					data = ((data&0x10)>>4)*10 + (data&0x0f) + 12;
					printf("%d",data);
				}
			}
		else//24 hours format
		{
			printf("%d",(data&0x30)>>4);
			printf("%d",(data&0x0f));
		}
		printf("时(24小时制)");
	
		data = isl1208_read_byte(1);
		printf("%d",(data&0xF0)>>4);
		printf("%d",(data&0x0f));
		printf("分");
		
		data = isl1208_read_byte(0);
		printf("%d",(data&0xF0)>>4);
		printf("%d",(data&0x0f));
		printf("秒");
		
		printf("\n");
		
		
		OSTimeDly(60);
		
	}
}

⌨️ 快捷键说明

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