1. 程式人生 > >關於具有I2C總線的TEA6320的使用

關於具有I2C總線的TEA6320的使用

關閉 發送數據 alt 延時 初始化 spa 查找 地址 數據位

現在先了解一下TEA6320,TEA6320是一個I2C總線控制音響應用的立體聲放大器,,它的I2C協議和音量控制如下:

技術分享圖片

技術分享圖片

技術分享圖片

它的主要代碼:



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,余下的子地址功能寄存器,系統會自動增加,而第三個字節就需要一一寫上全部控制的數據。

這是本人自己查找資料結合自己的思考理解,有需要的同行看了,有發現什麽不對的地方,請指出來,謝謝。

關於具有I2C總線的TEA6320的使用