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

📄 i2c.c

📁 WM8731的驱动程序
💻 C
字号:
/* I2C驱动程序
**
**   由于BF561本身不具有I2C控制器,这里使用GPIO PF1和PF2模拟 
**   
**   用户也可以使用其他GPIO模拟,仅仅需要修改以下两个定义:
**   		#define BIT_SCL				(0x0002)	// scl is PF1
**	    	#define BIT_SDA				(0x0004)	// sda is PF2
**   
**   针对不同的外部设备,从地址是不一样的,需要修改以下定义:
**   		#define SLAVE_ADDR          0x34
**
**   版权所有: 北京亿维东方科技有限公司
**             http://www.emvideo.com.cn
**             2006年6月
**
*/

#include <sys\exception.h>
#include <cdefBF561.h>
#include <ccblkfn.h>
#include <sysreg.h>
#include "wm8731.h"


 
// SPORT0 DMA transmit buffer
//volatile int iTxBuffer1[2];
// SPORT0 DMA receive buffer
//volatile int iRxBuffer1[2];


#define SLAVE_ADDR          0x34
#define BIT_SCL				(0x0002)	// scl is PF1
#define BIT_SDA				(0x0004)	// sda is PF2



// time delay
void delay_us(unsigned long ulTime) {
	unsigned long	i;
	unsigned long	j;
	
	for (i = 0; i < ulTime; i++)
		// pretend 1us
		for (j = 0; j < 100; j++)
			ssync();
			
			
}

// time delay
void delay_us_TEST(unsigned long ulTime) {
	unsigned long	i;
	unsigned long	j;
	
	for (i = 0; i < ulTime; i++)
		// pretend 1us
		for (j = 0; j < 100; j++)
			ssync();
			
			
}
// i2c control
// sda
void set_sda_input(void) {
	*pFIO0_DIR &= ~BIT_SDA;
	*pFIO0_INEN |= BIT_SDA;
	ssync();
}

void set_sda_output(void) {
	*pFIO0_INEN &= ~BIT_SDA;
	*pFIO0_DIR |= BIT_SDA;
	ssync();
}

unsigned char get_sda_value(void) {
	if (*pFIO0_FLAG_D & BIT_SDA)
		return 1;
	else
		return 0;
}

void set_sda_value(unsigned long ulFlag) {
	if (ulFlag)
		*pFIO0_FLAG_S = BIT_SDA;
	else
		*pFIO0_FLAG_C = BIT_SDA;
	ssync();
}

// scl
void set_scl_output(void) {
	*pFIO0_DIR |= BIT_SCL;
	ssync();
}

void set_scl_high(void) {
	*pFIO0_FLAG_S = BIT_SCL;
	ssync();
}

void set_scl_low(void) {
	*pFIO0_FLAG_C = BIT_SCL;
	ssync();
}

// set scl and sda output and high
// note sda should only change its value when scl is low to prevent occasionally generating a start or a stop bit
void set_both_high(void) {
	set_scl_output();
	set_scl_low();
	set_sda_output();
	set_sda_value(1);
	set_scl_high();
}

// sccb write
void sccb_write(unsigned char ucSub_addr, unsigned char ucData) {
	unsigned long	i;
	unsigned char	ucSlave_addr = SLAVE_ADDR;
	unsigned char	ucAck = 1;
	
	// set both high
	set_both_high();
	
	// start
	delay_us(6);
	set_sda_value(0);
	
	delay_us(6);
	set_scl_low();
	
	// send slave address, MSB first
	for (i = 0; i < 8; i++) {
		delay_us(3);
		set_sda_value(ucSlave_addr & (1 << (7 - i)));
	
		delay_us(10);
		set_scl_high();
		
		delay_us(6);
		set_scl_low();		
	}
	
	// read the acknowledge
	delay_us(3);
	set_sda_input();
	
	delay_us(10);
	set_scl_high();
	
	delay_us_TEST(3);
	ucAck = get_sda_value();
	
	delay_us_TEST(3);
	set_scl_low();
	
	delay_us(3);
	set_sda_output();
	
	// send sub address
	for (i = 0; i < 8 ; i++) {
		delay_us(3);
		set_sda_value(ucSub_addr & (1 << (7 - i)));
	
		delay_us(10);
		set_scl_high();   
		
		delay_us(6);
		set_scl_low();   
	}
    ucAck=1;
	// read the acknowledge
	delay_us(3);
	set_sda_input();
	
	delay_us(10);
	set_scl_high();
	
	delay_us(3);
	ucAck = get_sda_value();
	
	delay_us(3);
	set_scl_low();
	
	delay_us(3);
	set_sda_output();
	
	// send ucData
	for (i = 0; i < 8; i++) {			
		delay_us(3);
		set_sda_value(ucData & (1 << (7 - i)));
	
		delay_us(10);
		set_scl_high();   
		
		delay_us(6);
		set_scl_low();   
	}
	ucAck=1;
	// read the acknowledge
	delay_us(3);
	set_sda_input();
	
	delay_us(10);
	set_scl_high();
	
	delay_us(3);
	ucAck = get_sda_value();
	
	delay_us(3);
	set_scl_low();
	
	delay_us(3);
	set_sda_output();
	
	// stop
	set_sda_value(0);
	
	delay_us(10);
	set_scl_high(); 
	
	delay_us(6);
	set_sda_value(1);	
}

// sccb read
void sccb_read(unsigned char ucSub_addr, unsigned char* pucData) {
	unsigned long	i;
	unsigned char	ucSlave_addr = SLAVE_ADDR;
	unsigned char	ucAck = 1;

	// set both high
	set_both_high();
	
	// start
	delay_us(6);
	set_sda_value(0);
	
	delay_us(6);
	set_scl_low();
	
	// send slave address
	for (i = 0; i < 8; i++) {
		delay_us(3);
		set_sda_value(ucSlave_addr & (1 << (7 - i)));
	
		delay_us(10);
		set_scl_high();
		
		delay_us(6);
		set_scl_low();		
	}
	
	// read the acknowledge
	delay_us(3);
	set_sda_input();
	
	delay_us(10);
	set_scl_high();
	
	delay_us(3);
	ucAck = get_sda_value();
	
	delay_us(3);
	set_scl_low();
	
	delay_us(3);
	set_sda_output();
	
	// send sub address
	for (i = 0; i < 8 ; i++) {
		delay_us(3);
		set_sda_value(ucSub_addr & (1 << (7 - i)));
	
		delay_us(10);
		set_scl_high();   
		
		delay_us(6);
		set_scl_low();   
	}

	// read the acknowledge
	delay_us(3);
	set_sda_input();
	
	delay_us(10);
	set_scl_high();
	
	delay_us(3);
	ucAck = get_sda_value();
	
	delay_us(3);
	set_scl_low();
	
	delay_us(3);
	set_sda_output();

	// re-start
	set_sda_value(1);
	
	delay_us(10);
	set_scl_high();
	
//	delay_us(6);
	delay_us(200);
	set_sda_value(0);
	
//	delay_us(6);
	delay_us(200);
	set_scl_low();	

	ucSlave_addr = SLAVE_ADDR + 1;
	
	// send slave address
	for (i = 0; i < 8; i++) {
		delay_us(3);
		set_sda_value(ucSlave_addr & (1 << (7 - i)));
	
		delay_us(10);
		set_scl_high();
		
		delay_us(6);
		set_scl_low();		
	}
	
	// read the acknowledge
	delay_us(3);
	set_sda_input();
	
	delay_us(10);
	set_scl_high();
	
	delay_us(3);
	ucAck = get_sda_value();
	
	delay_us(3);
	set_scl_low();
	
	// read ucData
	for (i = 0; i < 8; i++) {
		delay_us(13);
		set_scl_high();

		delay_us(3);
		if (get_sda_value())
			*pucData |= (1 << (7-i));
		else
			*pucData &= ~(1 << (7-i));

		delay_us(3);
		set_scl_low();
	}

	// send no-acknowlege
	delay_us(3);
	set_sda_output();
	set_sda_value(1);
	
	delay_us(10);
	set_scl_high();
	
	delay_us(6);
	set_scl_low();

	// stop
	delay_us(3);
	set_sda_value(0);

	delay_us(10);
	set_scl_high(); 
	
	delay_us(6);
	set_sda_value(1);
}

/*
 * write to the WM8731 register space
 */
static int wm8731_write( unsigned int reg,unsigned int value)
{
	unsigned char  data[2];

	/* data is
	 *   D15..D9 WM8731 register offset
	 *   D8...D0 register data
	 */
	data[0] = (reg << 1) | ((value >> 8) & 0x0001);
	data[1] = value & 0x00ff;
    sccb_write(data[0],data[1]);
    
    return 0;

}


  
void wm8731_init(void)   
{   
  
    wm8731_write(WM8731_RESET,0);
    
    wm8731_write(WM8731_PWR, 0);
    
    wm8731_write(WM8731_ACTIVE, 0);
   
   	wm8731_write(WM8731_LOUT1V, 0x057f);
	
	wm8731_write(WM8731_ROUT1V, 0x057f);
	
	wm8731_write(WM8731_LINVOL, 0x019f);
	
	wm8731_write(WM8731_RINVOL, 0x019f);

	wm8731_write(WM8731_APANA, 0x0015);
	
	wm8731_write(WM8731_APDIGI, 0x0000);
	
	wm8731_write(WM8731_SRATE, 0x002C);
	
	wm8731_write(WM8731_IFACE, 0x004a);//24 bits	

    wm8731_write(WM8731_ACTIVE, 1);  
     

}  




⌨️ 快捷键说明

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