EV20S & EV01S 5G無線音訊模組I2C介面與STM

lvxfcjf發表於2021-09-09

說明

該模組音訊傳輸使用5G通訊頻率,內部整合雙向資料透傳功能及低音量靜音功能,I2C埠均採用GPIO模擬的方式

STM8程式碼

GPIO初始化

GPIO_Init(I2C_SCL_PORT, (GPIO_Pin_TypeDef)I2C_SCL_PINS, GPIO_MODE_OUT_OD_LOW_FAST); 
GPIO_Init(I2C_SDA_PORT, (GPIO_Pin_TypeDef)I2C_SDA_PINS, GPIO_MODE_OUT_OD_LOW_FAST);

宏定義

#define I2C_SCL_PORT    (GPIOB)#define I2C_SCL_PINS    (GPIO_PIN_4)#define I2C_SDA_PORT    (GPIOB)#define I2C_SDA_PINS    (GPIO_PIN_5)#define SDA2_IN()         {GPIOB->DDR&=~(1<<(5));(GPIOB->DDR|=(0<<(5)));}#define SDA2_OUT()        {GPIOB->DDR&=~(1<<(5));(GPIOB->DDR|=(1<<(5)));}#define SCL2_IN()         {GPIOB->DDR&=~(1<<(4));(GPIOB->DDR|=(0<<(4)));}#define SCL2_OUT()        {GPIOB->DDR&=~(1<<(4));(GPIOB->DDR|=(1<<(4)));}#define READ_SDA2               GPIO_ReadInputPin(I2C_SDA_PORT,I2C_SDA_PINS)#define READ_SCL2               GPIO_ReadInputPin(I2C_SCL_PORT,I2C_SCL_PINS)#define __delay_us(x)           delay_us(x*10)#define i2c_Start()             i2c_Restart()#define ev01s 0x68 #define I2C_TM_SCL_HIGH     1#define I2C_TM_SCL_LOW      3#define I2C_TM_START_HD     24#define I2C_TM_DATA_SU      5#define I2C_TM_SCL_TO_DATA  5   /* SCL low to data valid */#define I2C_TM_STOP_SU      40#define I2C_TM_SCL_TMO      10  /* clock time out */#define de_ack          0#define de_non_ack      1#define I2C_ERROR   (-1)

I2C基礎程式碼

/*
 *  Send (re)start condition
 *    - ensure data is high then issue a start condition
 *    - see also i2c_Start() macro
 */voidi2c_Restart(void){
    SCL_HIGH();                 /* ensure clock is low */
    SDA_HIGH();                 /* ensure data is high */
    __delay_us(10);

    SCL_LOW();                  /* ensure clock is low */
    SDA_HIGH();                 /* ensure data is high */

    __delay_us(I2C_TM_DATA_SU);

    SCL_HIGH();     /* clock pulse high */
    __delay_us(I2C_TM_SCL_HIGH);

    SDA_LOW();                  /* the high->low transition */
    __delay_us(I2C_TM_START_HD);    return;
}/*
 *  Send stop condition
 *    - data low-high while clock high
 */voidi2c_Stop(void){   
    SCL_LOW();
    SDA_LOW();                  /* ensure data is low first */
    __delay_us(I2C_TM_DATA_SU);
    SCL_HIGH();     /* float clock high */
    __delay_us(I2C_TM_STOP_SU);
    SDA_HIGH();                 /* the low->high data transistion */
    
    return;
}/*
 *  Check for an acknowledge
 *    - returns ack or ~ack, or ERROR if a bus error
 */signed chari2c_ReadAcknowledge(void){    unsigned char ack;
    SCL_LOW();                      /* make clock is low */
    __delay_us(I2C_TM_SCL_TO_DATA); /* SCL low to data out valid */
    SDA_HIGH();    if(fg_i2c_ev01s)
    {
        __delay_us(50);//50
    }    else
    {
        __delay_us(5);
    }
    SCL_HIGH();
    __delay_us(I2C_TM_DATA_SU);
    SDA2_IN();  //SDA設定為輸入
    ack = READ_SDA2;                        /* read the acknowledge */
    SDA2_OUT();    return ack;
}/*
 *  Send a byte to the slave
 *    - returns true on error
 */unsigned chari2c_SendByte(unsigned char byte){    signed char i;    for(i=7; i>=0; i--)
    {
    SCL_LOW();                  /* drive clock low */

        if ((byte>>i)&0x01)
    {       /* bit to send */
            SDA_HIGH();
        }        else 
        {
            SDA_LOW();
        }
    
            __delay_us(3);              
        SCL_HIGH();
        __delay_us(I2C_TM_SCL_HIGH);    /* clock high time */
    }    
    return FALSE;
}/*
 *  wait for the clock line to be released by slow slaves
 *    - returns TRUE if SCL was not released after the
 *      time out period.
 *    - returns FALSE if and when SCL released
 */unsigned chari2c_WaitForSCL(void){
    SCL2_IN();    /* SCL_DIR should be input here */
    if(!READ_SCL2)
    {
        __delay_us(I2C_TM_SCL_TMO);        /* if the clock is still low -> bus error */
        if(!READ_SCL2){
            SCL2_OUT();            return TRUE;
        }
    }
    SCL2_OUT();    return FALSE;
}/*
 *  Read a byte from the slave
 *    - returns the byte, or I2C_ERROR if a bus error
 */inti2c_ReadByte(void){    unsigned char i;    unsigned char byte = 0;    unsigned char x;
    SCL_LOW();    if(fg_i2c_ev01s)
    {
        __delay_us(50);//50
    }    for(i=0; i<8; i++)
    {
        SCL_LOW();                  /* drive clock low */
        __delay_us(1);  /* min clock low  period */
        SDA_HIGH();     /* release data line */
        __delay_us(1);
        SCL_HIGH();     /* float clock high */
        __delay_us(1);  /* min clock low  period */
        if(i2c_WaitForSCL())            return I2C_ERROR;
        __delay_us(1);
        byte = byte << 1;       /* read the next bit */
        SDA2_IN();        //x=READ_SDA2&0x01;
                if(READ_SDA2)
                {
                  x=0x01;
                }                else
                {
                  x=0x00;
                }
        SDA2_OUT();
        byte |=x;
    }    return (int)byte;
}/*
 *  send an address and data direction to the slave
 *    - 7-bit address (lsb ignored)
 *    - direction (FALSE = write )
 */unsigned chari2c_SendAddress(unsigned char address, unsigned char rw){    return i2c_SendByte(address | (rw?1:0));
}/*
 *  Opens communication with a device at address. mode
 *  indicates I2C_READ or I2C_WRITE.
 *    - returns TRUE if address is not acknowledged
 */unsigned chari2c_Open(unsigned char address, unsigned char mode){
    i2c_Start();
    i2c_SendAddress(address, mode);    if(i2c_ReadAcknowledge()) 
        return TRUE;    return FALSE;
}/*
 *  Send an (~)acknowledge to the slave
 *    - status of I2C_LAST implies this is the last byte to be sent
 */voidi2c_SendAcknowledge(unsigned char status){
    SCL_LOW();    if ( status & 0x01) {
        SDA_LOW();              /* drive line low -> more to come */
    }else { 
        SDA_HIGH();
    }
    __delay_us(I2C_TM_DATA_SU);
    SCL_HIGH();     /* float clock high */
    __delay_us(3);    return;
}/*
 *  Get a byte from the slave and acknowledges the transfer
 *    - returns true on I2C_ERROR or byte
 */inti2c_GetByte(unsigned char more){    int byte;    if((byte = i2c_ReadByte()) == I2C_ERROR)        return I2C_ERROR;

    i2c_SendAcknowledge(more);    return byte;
}/*
 *  Send a byte to the slave and acknowledges the transfer
 *    - returns I2C_ERROR, ack or ~ack
 */signed chari2c_PutByte(unsigned char data){//  if(i2c_SendByte(data))//      return I2C_ERROR;

    i2c_SendByte(data);    return i2c_ReadAcknowledge();   /* returns ack, ~ack */}void i2c_send_dada(unsigned char A,unsigned char B,unsigned char C){
        disableInterrupts();    unsigned char f=5;    if(fg_i2c_ev01s)
    {
        f=50;
    }
    __delay_us(f);
    i2c_Open(A,0);
    i2c_PutByte(B);
    i2c_PutByte(C);
    i2c_Stop();
        enableInterrupts(); 
}//************************************************//*       I2C check data                         *//************************************************void i2c_read_dada(unsigned char a,unsigned char b,unsigned char c){    unsigned char z=0;    unsigned char y;    unsigned char t;
    t=5;
        disableInterrupts();    if(fg_i2c_ev01s)
    {
        t=50;
    }
    __delay_us(t);
    i2c_Open(a,0);
    i2c_PutByte(b);    if(a==ev01s)
    {
        i2c_Stop();
    }
    __delay_us(t);
    i2c_Open(a,1);    for(;z<c;z++)
    {
        y=de_non_ack;        if((z+1)==c)
        {
            y=de_ack;
        }
        ev01s_rcv_buf[z]=i2c_GetByte(y);
    }
    i2c_Stop(); 
        enableInterrupts();
}

注意:模組對i2C時序有一定要求,具體可參考資料手冊

STM32程式碼

GPIO初始化

void IIC2_Init(void){
    GPIO_InitPara GPIO_InitStructure;
    RCC_AHBPeriphClock_Enable(RCC_AHBPERIPH_GPIOB, ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_PIN_8 | GPIO_PIN_9;
    GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUT;   //推輓輸出
    GPIO_InitStructure.GPIO_Speed = GPIO_SPEED_50MHZ;
    GPIO_InitStructure.GPIO_OType = GPIO_OTYPE_OD;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    GPIO_SetBits(GPIOB, GPIO_PIN_8 | GPIO_PIN_9);
}/*模組接收中斷,外部中斷線初始化*/void ev01s_it_Init(void){
    EXTI_InitPara EXTI_InitStructure;
    GPIO_InitPara GPIO_InitStructure;
    NVIC_InitPara NVIC_InitStructure;

    RCC_APB2PeriphClock_Enable(RCC_APB2PERIPH_CFG, ENABLE);//使能外部中斷時鐘

    GPIO_InitStructure.GPIO_Pin = GPIO_PIN_0;
    GPIO_InitStructure.GPIO_Mode = GPIO_MODE_IN;    //推輓輸出
    GPIO_InitStructure.GPIO_PuPd = GPIO_PUPD_PULLUP;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    
    SYSCFG_EXTILine_Config(EXTI_SOURCE_GPIOB, EXTI_SOURCE_PIN0);    

    EXTI_InitStructure.EXTI_LINE = EXTI_LINE0;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;     //配置中斷模式
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; 
    EXTI_InitStructure.EXTI_LINEEnable = ENABLE;            //使能中斷
    EXTI_Init(&EXTI_InitStructure); 
    
    NVIC_PRIGroup_Enable(NVIC_PRIGROUP_3);

    NVIC_InitStructure.NVIC_IRQ = EXTI0_1_IRQn;
    NVIC_InitStructure.NVIC_IRQPreemptPriority = 2;//優先順序
    NVIC_InitStructure.NVIC_IRQSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQEnable = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

宏定義

//IO方向設定#define SDA2_IN()  {GPIOB->CTLR&=~(3<<(9*2));GPIOB->CTLR|=0<<9*2;}   #define SDA2_OUT() {GPIOB->CTLR&=~(3<<(9*2));GPIOB->CTLR|=1<<9*2;}#define SCL2_IN()  {GPIOB->CTLR&=~(3<<(8*2));GPIOB->CTLR|=0<<8*2;}   #define SCL2_OUT() {GPIOB->CTLR&=~(3<<(8*2));GPIOB->CTLR|=1<<8*2;}//IO操作函式#define IIC2_SCL(x)      (x==0)?GPIO_ResetBits(GPIOB, GPIO_PIN_8):GPIO_SetBits(GPIOB, GPIO_PIN_8)//    PBout(8) //SCL#define IIC2_SDA(x)      (x==0)?GPIO_ResetBits(GPIOB, GPIO_PIN_9):GPIO_SetBits(GPIOB, GPIO_PIN_9)//    PBout(9) //SDA    #define READ_SDA2               GPIO_ReadInputBit(GPIOB,GPIO_PIN_9)//PBin(9) //輸入SDA#define READ_SCL2               GPIO_ReadInputBit(GPIOB,GPIO_PIN_8)//PBin(8) //輸入SCL#define SCL_LOW()           IIC2_SCL(0)#define SCL_HIGH()      IIC2_SCL(1)#define SDA_HIGH()      IIC2_SDA(1)#define SDA_LOW()           IIC2_SDA(0)#define ev01s 0x68 #define I2C_TM_SCL_HIGH     1#define I2C_TM_SCL_LOW      3#define I2C_TM_START_HD     24#define I2C_TM_DATA_SU      5#define I2C_TM_SCL_TO_DATA  5   /* SCL low to data valid */#define I2C_TM_STOP_SU      40#define I2C_TM_SCL_TMO      10  /* clock time out */#define de_ack          0#define de_non_ack      1#define I2C_ERROR   (-1)#define __delay_us(x)   delay_us(x*10)#define i2c_Start()     i2c_Restart()



作者:WangDaS
連結:


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/3486/viewspace-2816809/,如需轉載,請註明出處,否則將追究法律責任。

相關文章