📄 i2c.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 + -