SYD8821 IIC模块使用说明

SYD8821是具有全球领先低功耗(RX 2.4mA @-94.5dBm灵敏度,TX 4.3mA @0dBm输出功率)的蓝牙低功耗SOC芯片,在极低电流下实现了优异的射频性能,搭配176kB SRAM,512kB flash,非常适合中高阶可穿戴、智能家居、物联网等低功耗应用具体可咨询:http://www.syd-tek.com/


SYD8821 IIC模块使用说明

   IIC测试必须要一个从机设备,单单SYD8821芯片是不可能实现的了,这里的从机设备采用KX022加速度传感器,SYD8821和KX022传感器的电路连接图如下:

SYD8821 IIC模块使用说明

  一共有六个管脚和GSENSOR连接,分别是;

  两个中断管脚:GPIO19/INT1_GGPIO18/INT2_G
 四个SPI的管脚:GPIO21/G-SDA ,GPIO20/G-SCL,GPIO15/SDO,GPIO17/CS

 这里是用IIC和该传感器连接,所以GPIO15固定拉低,GPIO17固定拉高

   打开工程“\SYD8821\SYD8821_SDK\Source Code\SYD8821\iic”可看到IIC的初始化配置如下:

int main()
{    
    uint8_t iic_buff[32]={0};
    int16_t x,y,z;
    uint16_t i=0;
    float vat=0.0;
    __disable_irq();
    //GPO
    pad_mux_write(LED4, 0);
    pad_mux_write(LED5, 0);
    pad_mux_write(LED6, 0);
    pad_mux_write(LED7, 0);
    gpo_config(LED4,1);
    gpo_config(LED5,1);
    gpo_config(LED6,1);
  gpo_config(LED7,1);
    
    //GPI
    pad_mux_write(KEY1, 0);
    pad_mux_write(KEY2, 0);
    pad_mux_write(KEY3, 0);
    gpi_config(KEY1, PULL_UP);
    gpi_config(KEY2, PULL_UP);
    gpi_config(KEY3, PULL_UP);

  //uart 0
    pad_mux_write(12, 7);
    pad_mux_write(13, 7);
    dbg_init();
    dbg_printf("SYD8821 IIC DEMO\r\n");

  //kx022 gsensor SDA AND CS LOW
    pad_mux_write(15, 0);  
    gpo_config(15,0);                         //固定拉低
    pad_mux_write(17, 0);  
    gpo_config(17,1);                         //固定拉高
    
    // IIC
    pad_mux_write(20, 6); //i2c 1 scl       //管脚选择为IIC功能
    pad_mux_write(21, 6); //i2c 1 sda     // 管脚选择为IIC功能

    /* Masters Init M0*/
    //set i2c clk rate param 0, (48/8)*50K=300k
    i2c_master_set_speed(1, 0);     //设置速度为480K
    i2c_master_enable(1, true);       //使能IIC模块
    i2c_master_enable_int(1, true);    //使能IIC中断 不过这里没有使用中断的功能
    i2c_master_set_address_mode(1, I2C_MASTER_1BYTE_ADDRESS);     //设置地址模式,这里的传感器寄存器地址为1个字节
    NVIC_EnableIRQ(I2CM0_IRQn);    //使能中断
    
    if(kx022_init()) dbg_printf("kx022 init succeed\r\n");     //进行传感器的初始化
    else dbg_printf("kx022 init faild\r\n");

    __enable_irq();
    while(1)
    {
        gpo_toggle(LED4);
        
                /*
        计算公式:加速度 = 读到的原始值 * 8000mG / 65536 / 1000  
        其中的8000mG是这样的:本例程的测量量程是 +-4G  也就是正负4G的范围,这里是在Resolution/Range寄存器里设置的
        那么所能读到的最大数据是65536,也就是说每个数据的刻度是 8000/65536 mg
        */
        gensor_read_xyz(&x, &y, &z);    //读取传感器的值
        vat=(float)x*8000/65536/1000;
        dbg_printf("x : %02x vat: %4.3f i:%d\r\n",x,vat,i);
        vat=(float)y*8000/65536/1000;
        dbg_printf("y : %02x vat: %4.3f i:%d\r\n",y,vat,i);
        vat=(float)z*8000/65536/1000;
        dbg_printf("z : %02x vat: %4.3f i:%d\r\n",z,vat,i);
        delay_ms(500);
        i++;

        delay_ms(1000);
    }        
}

    下面看看kx022_init源码:

uint8_t  kx022_init(void)
{
    uint8_t i,st;     
    kx022_write_reg(0x00, 0x24);  
    for(i=0; i<(sizeof(kx022_init_data)); i+=2)
    {
        kx022_write_reg(kx022_init_data[i], kx022_init_data[i+1]);
    }
    kx022_read_reg(KX022_INT_REL, &st);
    kx022_read_reg(KX022_WHO_AM_I_REG, &st);
    
    if(st == 0x14) return 1;
    #ifdef CONFIG_UART_ENABLE
    dbg_printf("WHO I ME: %4X \r\n",st);
    #endif
    return 0;
}

    其中主要调用kx022_read_reg和kx022_write_reg对传感器的寄存器进行初始化,这两个函数的源码如下:

/*
kx022写寄存器函数
参数: uint8_t addr  寄存器地址
             uint8_t value 寄存器数据
注意ID地址不作为传入参数 已经在全部变量定义好了
*/
void kx022_write_reg(uint8_t addr, uint8_t value)
{    
    __align(4) uint8_t val=0;
    val=value;
    i2c_write(1,I2C_ID_KX022,addr,&val,0x01);
}
/*
kx022读寄存器函数
参数: uint8_t addr  寄存器地址
             uint8_t value 读到的内容
注意ID地址不作为传入参数 已经在全部变量定义好了
*/
void kx022_read_reg(uint8_t addr, uint8_t *p_value)
{
    __align(4) uint8_t val=0;
    i2c_read(1,I2C_ID_KX022,addr,&val,0x01);
    *p_value=val;
}

    主要调用i2c_write和i2c_read读进行实际的操作,这里都是操作一个字节!

    当然还有操作多个字节的,比如读取加速度值得gensor_read_xyz函数:

/*
kx022获取加速度传感器三个轴的数据函数
传入参数:uint16_t *p_x X轴数据存储指针
                    uint16_t *p_y y轴数据存储指针
                    uint16_t *p_z z轴数据存储指针
*/
void gensor_read_xyz(int16_t *p_x, int16_t *p_y, int16_t *p_z)
{
//        uint8_t st;
//        uint8_t val[2];
//        int16_t x,y,z;
//            kx022_read_reg(KX022_X_OUTL_REG, &val[0]);
//            kx022_read_reg(KX022_X_OUTL_REG+1, &val[1]);
//            x = (val[0]) | ((int16_t)val[1] << 8);
//            kx022_read_reg(KX022_Y_OUTL_REG, &val[0]);
//            kx022_read_reg(KX022_Y_OUTL_REG+1, &val[1]);
//            y = (val[0]) | ((int16_t)val[1] << 8);
//            kx022_read_reg(KX022_Z_OUTL_REG, &val[0]);
//            kx022_read_reg(KX022_Z_OUTL_REG+1, &val[1]);
//            z = (val[0]) | ((int16_t)val[1] << 8);
//            
//            *p_x=x;
//            *p_y=y;
//            *p_z=z;

        uint8_t st;
        __align(4) uint8_t val[6];
    
        kx022_read_nreg(KX022_X_OUTL_REG, val,6);
        *p_x = (val[0]) | ((int16_t)val[1] << 8);
        *p_y = (val[2]) | ((int16_t)val[3] << 8);
        *p_z = (val[4]) | ((int16_t)val[5] << 8);
}       

     这里一次获取了6个寄存器的值,这里IIC只有32个byte,所以最多一次只能够读取32个字节的数据!


    IIC测试如果没有挂接从机设备,那么时序如下:

SYD8821 IIC模块使用说明

    可以看到从机没有应答,时序停止,挂机从机设备后结果如下:

SYD8821 IIC模块使用说明

    可以看到正确的完整的时序,下面是gensor_read_xyz函数中注释的部分打开的时候的时序图,每次读取一个寄存器的值,知道读完六个寄存器:

SYD8821 IIC模块使用说明

     下面是上面的gensor_read_xyz函数产生的时序:

SYD8821 IIC模块使用说明


这里上传逻辑分析仪数据;https://download.****.net/download/chengdong1314/10304560


这里上传本节博客源代码:https://download.****.net/download/chengdong1314/10304570