哈哈,看见编辑推荐了,怎么说也得回应一下,现在放出MCU控制代码
/*---------------------------------------------------------------------------------------------------------*/
/* */
/* Copyright(c) 2017 Nuvoton Technology Corp. All rights reserved. */
/* */
/*---------------------------------------------------------------------------------------------------------*/
//***********************************************************************************************************
// Nuvoton Technoledge Corp.
// Website: http://www.nuvoton.com
// E-Mail : MicroC-8bit@nuvoton.com
// Date : Apr/29/2017
//***********************************************************************************************************
//***********************************************************************************************************
// File Function: N76E003 I2C master mode demo code, the Slave address = 0xA4
//
// ____________ _____________
// | | SDA | |
// | |<-------->| |
// | | | |
// |N76E003(M) | | N76E003(S) |
// |(I2C_Master)| | (I2C_Slave) |
// | | SCL | |
// | |--------->| |
// |____________| |_____________|
//
// The protocol of I2C is same the "24LC64"
//***********************************************************************************************************
#include "N76E003.h"
#include "Common.h"
#include "Delay.h"
#include "SFR_Macro.h"
#include "Function_define.h"
#define u8 unsigned char
#define u16 unsigned int
#define u32 unsigned long
#define V_Up P17
#define V_Down P00
#define I2C_CLOCK 13
#define TLV320_ADD 0x34
#define Vol 120//0-127的一个数字,=0为静音
#define VOL_ADJ_CON 40000
u8 volume = Vol;
u8 MUTE=1;
//========================================================================================================
void Init_I2C(void)
{
/* Set I2C clock rate */
I2CLK = I2C_CLOCK;
/* Enable I2C */
set_I2CEN;
}
//========================================================================================================
void I2C_Error(void)
{
// P3 = I2STAT;
// P3 = ERROR_CODE;
while (1);
}
//========================================================================================================
void I2C_W_DATA(UINT8 REG_ADD , UINT8 u8DAT)
{
/* Step1 */
set_STA; /* 发送Start位信号 */
clr_SI;
while (!SI); //检测总线,这里是主控单从芯片,单发送,其实可以不需要这个检测,
if (I2STAT != 0x08) I2C_Error(); //不过原官方代码有这个,也不影响,就留着了。
/* Step2 */
clr_STA; //STA=0
I2DAT = TLV320_ADD; //发送芯片IIC地址
clr_SI;
while (!SI); //检测ACK
if (I2STAT != 0x18) I2C_Error();
/* Step3 */
REG_ADD<<=1; //TLV320AC23寄存器地址用的是D15-D9,因此,官方文档地址在这里必须左移一位。
I2DAT = REG_ADD; //发送寄存器地址
clr_SI;
while (!SI); //检查ACK
if (I2STAT != 0x28) I2C_Error();
/* Step4 */
I2DAT = u8DAT; //发送目的数据
clr_SI;
while (!SI); //检查ACK
if (I2STAT != 0x28) I2C_Error();
/* Step5 */
set_STO;
clr_SI;
while (STO); /* 等待总线拉高*/
}
void MUTE_ISR (void) interrupt 0
{
u8 i;
IE0=0;
for(i=0;i<1000;i++){if(P30!=0)return;} //加个电容抗抖的话,这里软件抗抖可以不要
MUTE++;
MUTE&=0x01;
I2C_W_DATA(0x02,(0X80+volume*MUTE)); //MUTE=0 or 1 volume*MUTE=volume or 0,等于0就直接实现静音.
I2C_W_DATA(0x03,(0X80+volume*MUTE));
}
/*音量下降按钮中断,软件抗抖,抗抖完成后是一个瞬动(下降一个dB),
然后检测按钮是不是继续按着,如果是,进入循环连续调整(俗称连发)*/
void Volume_Down_ISR (void) interrupt 7
{
u8 ADJ;
u16 i;
PIF=0;
for(i=0;i<1000;i++){if(V_Down!=0)return;} //软件抗抖
if(volume>0)volume--; //瞬动一次,立刻调整输出
I2C_W_DATA(0x02,(0X80+volume));
I2C_W_DATA(0x03,(0X80+volume));
while(V_Down==0) //连发扳机检测,VOL_ADJ_CON是连发时间间隔计数。
{
ADJ=0;
for(i=0;i<VOL_ADJ_CON;i++)
{
if(V_Down!=0){ADJ=1;return;}
}
if(ADJ==0)
{
if(volume>0)volume--;
I2C_W_DATA(0x02,(0X80+volume)); //连发控制输出
I2C_W_DATA(0x03,(0X80+volume));
}
}
}
void Volume_Up_ISR (void) interrupt 2
{
u8 ADJ;
u16 i;
IE1=0;
for(i=0;i<500;i++){if(V_Up!=0)return;} //软件抗抖
if(volume<127)volume++; //瞬动一次,立刻调整输出
I2C_W_DATA(0x02,(0X80+volume));
I2C_W_DATA(0x03,(0X80+volume));
while(V_Up==0) //连发扳机检测,VOL_ADJ_CON是连发时间间隔计数。
{
ADJ=0;
for(i=0;i<VOL_ADJ_CON;i++)
{
if(V_Up!=0){ADJ=1;return;}
}
if(ADJ==0)
{
if(volume<127)volume++;
I2C_W_DATA(0x02,(0X80+volume)); //连发控制输出
I2C_W_DATA(0x03,(0X80+volume));
}
}
}
//========================================================================================================
void main(void)
{
Set_All_GPIO_Quasi_Mode; //全部用弱上拉模式,这样,可以节省3个按钮上拉电阻,IIC总线也可以用就简单点偷懒了。
//P00_Quasi_Mode;
//Enable_INT_Port0; //管脚切换到00组,这里是P00
PINEN=0X01;
PICON=0X04;
//Enable_BIT0_FallEdge_Trig; //管脚中断边沿中断,下降沿
while(P30==0);
set_EPI;
TCON=0X05;
set_EX0;
set_EX1;
EA =1;
Init_I2C();
//I2C_Process(0x0F,0x00); //寄存器复位控制
I2C_W_DATA(0x00,0x17); //线路L 音量、静音
I2C_W_DATA(0x01,0x17); //线路R 音量、静音
/*这里没做断电音量自动保存,要实现也很简单,每次音量改变中断完成后,用FLASH单元,代替EEPROM数据,用SPI自编程实现,
考虑到片内FLASH擦写寿命(10W)还可以用连续单元,顺序检测第一个FF单元,并进行编程,一个一个的写下去,直到一页全部写满,
到该页内没有FF单元,才进行一次页擦除,然后就又可以继续保存音量数据了。*/
I2C_W_DATA(0x02,(0X80+volume)); //耳机L音量同时更新、零电压更新、音量控制
I2C_W_DATA(0x03,(0X80+volume)); //耳机L音量同时更新、零电压更新、音量控制
I2C_W_DATA(0x04,0x18); //音频路径控制
I2C_W_DATA(0x05,0x00); //DAC 控制 软静音、过采样、高通
I2C_W_DATA(0x06,0x07); //电源控制,ADC、line输入 MIC关闭,其余全部开启
I2C_W_DATA(0x07,0x3E); //主从、数据格式控制 88.2
I2C_W_DATA(0x08,0x20); //过采样控制 44.1
I2C_W_DATA(0x09,0x01); //数字界面激活控制
while (1)
{
UINT16 tmp;
for (tmp=0;tmp<2000;tmp++){;}
}
/* =================== */
}
|