欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

关于具有I2C总线的TEA6320的使用

程序员文章站 2023-10-26 17:24:28
现在先了解一下TEA6320,TEA6320是一个I2C总线控制音响应用的立体声放大器,,它的I2C协议和音量控制如下: 它的主要代码: 下面屏蔽的那几段代码会影响到I2C的接收,发送 怎么对TEA6320的理解呢,详看TEA6320的协议,MAD(从地址)是第一个字节,SAD(子地址)是第二个字节 ......

 

现在先了解一下tea6320,tea6320是一个i2c总线控制音响应用的立体声放大器,,它的i2c协议和音量控制如下:

 

关于具有I2C总线的TEA6320的使用

关于具有I2C总线的TEA6320的使用 

 

关于具有I2C总线的TEA6320的使用 

 

它的主要代码:


void delay1ms(unsigned int delay ) //1ms延时
{
    unsigned int j;
    for(;delay>0;delay--)
    for(j=0;j<125;j++);
}

void init()                 ///总线初始化 将总线都拉高一释放总线  发送启动信号前,要先初始化总线。即总线检测到总线空闲才开始发送启动信号
{
    sda=1;
    _nop_();
    scl=1;
    _nop_();
}

void inituart(void)
{
    tmod = 0x20;                     //将timer1设置为mode2以产生波特率
    scon = 0x50;                    //串口工作方式2
    th1 = 0xfd;                        //波特率9600
    tl1 = th1;
    pcon = 0x00;                    //将smod设置为0
    tr1 = 1;                        //开启定时器1
    ea=1;                           //开启总中断
    es=1;                           //开启串口中断
}

void senddata(uchar dat)             //发送数据
{
    acc = dat;
    cy=p;
    tb8=~cy;
    sbuf=acc;
    while(!ti);
    ti = 0;                             //软件复位      
}
            
void i2c_start()
{
    sda=1;           //起始信号
    _nop_();
    scl=1;
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    sda=0;  
    _nop_();
    _nop_();
    _nop_();            
    _nop_();           
    _nop_();

}
void i2c_stop()
{
    sda=0;           //停止信号
    _nop_();
    scl=1;
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    sda=1;
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();
}
void ack()   //应答信号
{
        sda=0;
        _nop_();
        scl=1;
        _nop_();
        scl=0;
        _nop_();
//    sda = 1;
//    scl = 1;
//    _nop_();
//    while(sda==1);
//    scl = 0;
}

void i2c_sendbyte(unsigned char dat)  //发送数据
{ 
unsigned char temp; unsigned char i; scl=0; _nop_(); _nop_(); _nop_(); _nop_(); for(i=0;i<8;i++) //要发送的数据长度为8位 { temp=dat; if(temp<<i&0x80) sda=1; //判断发送位 else sda=0; _nop_(); scl=1; //置时钟线为高,通知从机开始接受数据位 _nop_(); _nop_(); _nop_(); //保证时钟高电平周期大于4us ` _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); scl=0; //拉低scl,为下次数据传输做好准备 _nop_(); _nop_(); } sda=1; //释放sda总线,接下来由从设备控制,比如从设备接收完数据后,在scl为高时,拉低sda作为应答信号 _nop_(); _nop_(); _nop_(); _nop_(); } main() { inituart(); init(); while(1) { cs=1; a10=0; a11=0; a12=0; a13=0; a14=0; oe=0; /*.....enable变低,总线开始接受数据.....*/ ale=0; bb=0; ii=p0; aa=0xff; v24=0; if(ii==0x8f) // 5个按钮不动作,关的状态 { delay1ms(50); if(ii==0x8f) { bb=0xf9; p0=bb; aa=0x11; delay1ms(200); cs=1; a10=1; a11=0; a12=0; a13=0; a14=0; we=0; delay1ms(500); } } if(ii==0x8e) { delay1ms(50); if(ii==0x8e) { bb=0xf1; p0=bb; aa=0x11; delay1ms(200); cs=1; a10=1; a11=0; a12=0; a13=0; a14=0; we=0; delay1ms(500); senddata(0xaa); i2c_start(); i2c_sendbyte(0x80); //mad,第一个字节 ack(); i2c_sendbyte(0x00); //sad,第二个字节 ack(); i2c_sendbyte(0x2c); //响度 +20db ack(); i2c_sendbyte(0x3f); //前右 响度0db ack(); i2c_sendbyte(0x3f); //前左 响度0db ack(); i2c_sendbyte(0x3f); //后右 响度0db ack(); i2c_sendbyte(0x3f); //后左 响度0db ack(); i2c_sendbyte(0x10); //低音 响度+15db ack(); i2c_sendbyte(0x10); //高音 响度+15db ack(); i2c_sendbyte(0x7f); //声道选择 直接静音关闭,选通ial和iar ack(); i2c_stop(); delay1ms(5000); i2c_start(); i2c_sendbyte(0x80); //mad ack(); i2c_sendbyte(0x00); //sad ack(); i2c_sendbyte(0x2c); //响度 +20db ack(); i2c_sendbyte(0x3f); //前右 响度0db ack(); i2c_sendbyte(0x3f); //前左 响度0db ack(); i2c_sendbyte(0x3f); //后右 响度0db ack(); i2c_sendbyte(0x3f); //后左 响度0db ack(); i2c_sendbyte(0x10); //低音 响度+15db ack(); i2c_sendbyte(0x10); //高音 响度+15db ack(); i2c_sendbyte(0xff); //声道选择 直接静音,选通ial和iar ack(); i2c_stop(); senddata(0x55); } } if(ii==0x8d) //4脚按钮动作处于开的状态 { delay1ms(50); if(ii==0x8d) { bb=0xe9; p0=bb; aa=0x11; delay1ms(200); cs=1; a10=1; a11=0; a12=0; a13=0; a14=0; we=0; delay1ms(500); senddata(0xaa); i2c_start(); i2c_sendbyte(0x80); //mad ack(); i2c_sendbyte(0x00); //sad ack(); i2c_sendbyte(0x2c); //响度 +20db ack(); i2c_sendbyte(0x3f); //前右 响度0db ack(); i2c_sendbyte(0x3f); //前左 响度0db ack(); i2c_sendbyte(0x3f); //后右 响度0db ack(); i2c_sendbyte(0x3f); //后左 响度0db ack(); i2c_sendbyte(0x10); //低音 响度+15db ack(); i2c_sendbyte(0x10); //高音 响度+15db ack(); i2c_sendbyte(0x7e); //声道选择 直接静音关闭,选通ibl和ibr ack(); i2c_stop(); delay1ms(5000); i2c_start(); i2c_sendbyte(0x80); //mad ack(); i2c_sendbyte(0x00); //sad ack(); i2c_sendbyte(0x2c); //响度 +20db ack(); i2c_sendbyte(0x3f); //前右 响度0db ack(); i2c_sendbyte(0x3f); //前左 响度0db ack(); i2c_sendbyte(0x3f); //后右 响度0db ack(); i2c_sendbyte(0x3f); //后左 响度0db ack(); i2c_sendbyte(0x10); //低音 响度+15db ack(); i2c_sendbyte(0x10); //高音 响度+15db ack(); i2c_sendbyte(0xfe); //声道选择 直接静音 ack(); i2c_stop(); senddata(0x55); } } if(ii==0x8b) //8脚按钮动作处于开的状态 { delay1ms(50); if(ii==0x8b) { bb=0xd9; p0=bb; aa=0x11; delay1ms(200); cs=1; a10=1; a11=0; a12=0; a13=0; a14=0; we=0; delay1ms(500); senddata(0xaa); i2c_start(); i2c_sendbyte(0x80); //mad ack(); i2c_sendbyte(0x00); //sad ack(); i2c_sendbyte(0x2c); //响度 +20db ack(); i2c_sendbyte(0x3f); //前右 响度0db ack(); i2c_sendbyte(0x3f); //前左 响度0db ack(); i2c_sendbyte(0x3f); //后右 响度0db ack(); i2c_sendbyte(0x3f); //后左 响度0db ack(); i2c_sendbyte(0x10); //低音 响度+15db ack(); i2c_sendbyte(0x10); //高音 响度+15db ack(); i2c_sendbyte(0x7d); //声道选择 直接静音关闭,选通icl和icr ack(); i2c_stop(); delay1ms(5000); i2c_start(); i2c_sendbyte(0x80); //mad ack(); i2c_sendbyte(0x00); //sad ack(); i2c_sendbyte(0x2c); //响度 +20db ack(); i2c_sendbyte(0x3f); //前右 响度0db ack(); i2c_sendbyte(0x3f); //前左 响度0db ack(); i2c_sendbyte(0x3f); //后右 响度0db ack(); i2c_sendbyte(0x3f); //后左 响度0db ack(); i2c_sendbyte(0x10); //低音 响度+15db ack(); i2c_sendbyte(0x10); //高音 响度+15db ack(); i2c_sendbyte(0xfd); //声道选择 直接静音,选通icl和icr ack(); i2c_stop(); senddata(0x55); } } if(ii==0x87) //8脚按钮动作处于开的状态 { delay1ms(50); if(ii==0x87) { bb=0xb9; p0=bb; aa=0x11; delay1ms(200); cs=1; a10=1; a11=0; a12=0; a13=0; a14=0; we=0; delay1ms(500); senddata(0xaa); i2c_start(); i2c_sendbyte(0x80); //mad ack(); i2c_sendbyte(0x00); //sad ack(); i2c_sendbyte(0x2c); //响度 +20db ack(); i2c_sendbyte(0x3f); //前右 响度0db ack(); i2c_sendbyte(0x3f); //前左 响度0db ack(); i2c_sendbyte(0x3f); //后右 响度0db ack(); i2c_sendbyte(0x3f); //后左 响度0db ack(); i2c_sendbyte(0x10); //低音 响度+15db ack(); i2c_sendbyte(0x10); //高音 响度+15db ack(); i2c_sendbyte(0x7d); //声道选择 直接静音关闭,选通icl和icr ack(); i2c_stop(); delay1ms(5000); i2c_start(); i2c_sendbyte(0x80); //mad ack(); i2c_sendbyte(0x00); //sad ack(); i2c_sendbyte(0x2c); //响度 +20db ack(); i2c_sendbyte(0x3f); //前右 响度0db ack(); i2c_sendbyte(0x3f); //前左 响度0db ack(); i2c_sendbyte(0x3f); //后右 响度0db ack(); i2c_sendbyte(0x3f); //后左 响度0db ack(); i2c_sendbyte(0x10); //低音 响度+15db ack(); i2c_sendbyte(0x10); //高音 响度+15db ack(); i2c_sendbyte(0xfd); //声道选择 直接静音,选通icl和icr ack(); i2c_stop(); senddata(0x55); } } if(ii==0x0f) { delay1ms(50); if(ii==0x0f) { bb=0x79; p0=bb; aa=0x11; delay1ms(200); cs=1; a10=1; a11=0; a12=0; a13=0; a14=0; we=0; delay1ms(500); } } senddata(bb); delay1ms(500); if(aa==0xff) { p0=0x89; cs=1; a10=1; a11=0; a12=0; a13=0; a14=0; we=0; delay1ms(500); } senddata(aa); delay1ms(500); } }

其中i2c的应答代码
void ack()   //应答信号
{
        sda=0;
        _nop_();
        scl=1;
        _nop_();
        scl=0;
        _nop_();
//    sda = 1;
//    scl = 1;
//    _nop_();
//    while(sda==1);
//    scl = 0;
}

 下面屏蔽的那几段代码会影响到i2c的接收,发送

怎么对tea6320的理解呢,详看tea6320的协议,mad(从地址)是第一个字节,sad(子地址)是第二个字节,第三个字节就是i2c真正要传输的数据,协议上说超过1个字节,数据将被发送,自动增加显著子地址,即tea6320在写入数据超过1个字节的时候,子地址能自动递增,所以,子地址只需取列表第一个音量/响度的控制寄存器0x00,余下的子地址功能寄存器,系统会自动增加,而第三个字节就需要一一写上全部控制的数据。

这是本人自己查找资料结合自己的思考理解,有需要的同行看了,有发现什么不对的地方,请指出来,谢谢。