AD7797芯片驱动调试

本文详细记录了AD7797拉力传感器在调试过程中遇到的数据读取异常问题。作者通过分析AD采样值的偏差,检查了复位、读写寄存器的时序,并调整了数据读取方式以匹配芯片要求。在初始化、校准和模式设置后,最终解决了读取不到数据的问题,确保了转换和数据读取的正确性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        今天在测试拉力传感器,调校后,发现拉力值还是零。查看AD采样值,结果如图:

先不去分析为啥是零,只看AD采样数据就不对,怎么会偏差这么大,而且有极大值和极小值。

驱动是同事写的,目前已经不负责这个项目了,我只能一点点来看手册调试。

一、AD7797引脚

引脚图,如下图:

注:和通信相关的就是标注的几个引脚,单个芯片(CS可以一直拉低,表示一直选中,不建议这么做)。DOUT/RDY为低表示

转换完成,数据读走或者在数据更新之前为高(数据跟新完后为低)。

时序图:

二、复位

AD7797有上电复位和软件复位。

说的很清楚了,DIN引脚保持至少32个时钟周期,则复位;复位后,经过500us间隔

才能和AD7797通信。

void reset_Ad7797(void)  
{    
    uint8_t i=0;
    SAFE_ATOM_CODE(
        //AD_CS_LOW;
        //80nS
        AD_DIN_HIGH;
        for(i = 0; i < 36; i++)  
        {  
            AD_SCLK_LOW;
            //100ns
            AD_SCLK_HIGH;
            //100ns
        }  
        //AD_CS_HIGH;
        //80nS
        //__NOP();
    )
    //500us
    delay(300);
}

三、读写寄存器

AD7797怎么读写寄存,怎么配置,请看数据手册,这里只讲大概思路。

(数据传输的时候,先传输高字节的高bit)

COMMUNICATION REGISTER

所以有的后续操作,都需要先操作通信寄存器。

CR7写0,可以操作本寄存器;CR6写0,代表后续是写操作;CR6写1,代表后续是读操作;RS2-RS0表示后续操作寄存器地址。

STATUS REGISTER

MODE REGISTER

转换模式有两种:单次转换模式和连续转换模式;转换完后,OUT/RDY为低;

校准模式有三种:内准基准零点校准,系统零点校准和系统满量程校准(系统校准需要硬件支持)。

CONFIGURATION REGISTER

读写时候,按着时序图:

1)写入数据:MCU低电平改变;AD7797高电平读取;

2)读取数据:AD7797电平输出;MCU高电平读取;

测试ID寄存器,发现读取是0x5A,芯片没有焊接错误,只能在时序上看:

 

最后一个Bit在下降沿变低,查看时序图:

最后一个Bit要求上升沿后10ns读取,反应没这么快;下降沿后80ns数据就稳定了,而读取IO需要百ns级,因此

改成下降沿读取,测试成功。

void write_8bit(uint8_t chAddress,uint8_t writedata)  
{    
    U8 i;  
    union{
        uint8_t chCRBD[2];
        struct{
        uint8_t         :2;
        uint8_t Cread   :1;
        uint8_t chRS    :3;
        uint8_t RW      :1;
        uint8_t WEN     :1;
        };
    }tCRBD = {0};
    tCRBD.chCRBD[0] = 0;
    tCRBD.chCRBD[1] = writedata;
    tCRBD.WEN = 0;
    tCRBD.RW  = 0;
    tCRBD.chRS= chAddress;
    SAFE_ATOM_CODE(
        //AD_CS_LOW;
        //80nS
        for(i = 0; i < 16; i++)  
        {  
            AD_SCLK_LOW;
            //100ns
            if(tCRBD.chCRBD[i>>3] & 0x80){
                AD_DIN_HIGH;
            }else{
                AD_DIN_LOW;
            }
            AD_SCLK_HIGH;
            //100ns
            tCRBD.chCRBD[i>>3] = tCRBD.chCRBD[i>>3] << 1;
        }
        //AD_CS_HIGH;
        //80nS
    ) 
    AD_DIN_HIGH;
}


void write_16bit(uint8_t chAddress,uint16_t writedata)  
{    
    U8 i;  
    union{
        uint8_t chCRBD[3];
        struct{
        uint8_t         :2;
        uint8_t Cread   :1;
        uint8_t chRS    :3;
        uint8_t RW      :1;
        uint8_t WEN     :1;
        };
    }tCRBD = {0};
    tCRBD.chCRBD[0] = 0;
    tCRBD.chCRBD[1] = (writedata>>8) & 0x00FF;
    tCRBD.chCRBD[2] = writedata & 0x00FF;
    tCRBD.WEN = 0;
    tCRBD.RW  = 0;
    tCRBD.chRS= chAddress;
    SAFE_ATOM_CODE(
        //AD_CS_LOW;
        //80nS
        for(i = 0; i < 24; i++)  
        {  
            AD_SCLK_LOW;
            //100ns
            if(tCRBD.chCRBD[i>>3] & 0x80){
                AD_DIN_HIGH;
            }else{
                AD_DIN_LOW;
            }
            AD_SCLK_HIGH;
            //100ns
            tCRBD.chCRBD[i>>3] = tCRBD.chCRBD[i>>3] << 1;
        }
        //AD_CS_HIGH;
        //80nS
    ) 
    AD_DIN_HIGH;
}

void write_24bit(uint8_t chAddress,uint32_t writedata)  
{    
    U8 i;  
    union{
        uint8_t chCRBD[4];
        struct{
        uint8_t         :2;
        uint8_t Cread   :1;
        uint8_t chRS    :3;
        uint8_t RW      :1;
        uint8_t WEN     :1;
        };
    }tCRBD = {0};
    tCRBD.chCRBD[0] = 0;
    tCRBD.chCRBD[1] = (writedata>>16) & 0x000000FF;
    tCRBD.chCRBD[2] = (writedata>>8)  & 0x000000FF;
    tCRBD.chCRBD[3] = writedata & 0x000000FF;
    tCRBD.WEN = 0;
    tCRBD.RW  = 0;
    tCRBD.chRS= chAddress;
    SAFE_ATOM_CODE(
        //AD_CS_LOW;
        //80nS
        for(i = 0; i < 32; i++)  
        {  
            AD_SCLK_LOW;
            //100ns
            if(tCRBD.chCRBD[i>>3] & 0x80){
                AD_DIN_HIGH;
            }else{
                AD_DIN_LOW;
            }
            AD_SCLK_HIGH;
            //100ns
            tCRBD.chCRBD[i>>3] = tCRBD.chCRBD[i>>3] << 1;
        }
        //AD_CS_HIGH;
        //80nS
    ) 
    AD_DIN_HIGH;
}
uint8_t read_8bit(uint8_t chAddress)  
{     
    uint8_t readdata = 0;  
    uint8_t i;  
    union{
        uint8_t chCRBD;
        struct{
        uint8_t         :2;
        uint8_t Cread   :1;
        uint8_t chRS    :3;
        uint8_t RW      :1;
        uint8_t WEN     :1;
        };
    }tCRBD = {0};
    tCRBD.chCRBD= 0;
    tCRBD.WEN = 0;
    tCRBD.RW  = 1;
    tCRBD.chRS= chAddress;
    SAFE_ATOM_CODE(
        //AD_CS_LOW;
        //80nS
        for(i = 0; i < 8; i++)  
        {  
            AD_SCLK_LOW;
            //100ns
            if(tCRBD.chCRBD & 0x80){
                AD_DIN_HIGH;
            }else{
                AD_DIN_LOW;
            }
            AD_SCLK_HIGH;
            //100ns
            tCRBD.chCRBD = tCRBD.chCRBD<<1;
        }
        AD_DIN_HIGH;
        for(i = 0; i < 8; i++)  
        {  
            AD_SCLK_LOW;
            //100ns
            readdata = readdata << 1;
            if(AD_DOUT){
                readdata += 1;
            }
            AD_SCLK_HIGH;
            //100ns
        }
        //AD_CS_HIGH;
        //80nS
    ) 
    return readdata;
}


uint16_t read_16bit(uint8_t chAddress)  
{     
    uint16_t readdata = 0;  
    uint8_t  i;  
    union{
        uint8_t chCRBD;
        struct{
        uint8_t         :2;
        uint8_t Cread   :1;
        uint8_t chRS    :3;
        uint8_t RW      :1;
        uint8_t WEN     :1;
        };
    }tCRBD = {0};
    tCRBD.chCRBD= 0;
    tCRBD.WEN = 0;
    tCRBD.RW  = 1;
    tCRBD.chRS= chAddress;
    SAFE_ATOM_CODE(
        //AD_CS_LOW;
        //80nS
        for(i = 0; i < 8; i++)  
        {  
            AD_SCLK_LOW;
            //100ns
            if(tCRBD.chCRBD & 0x80){
                AD_DIN_HIGH;
            }else{
                AD_DIN_LOW;
            }

            AD_SCLK_HIGH;
            //100ns
            tCRBD.chCRBD = tCRBD.chCRBD<<1;
        }
        AD_DIN_HIGH;
        for(i = 0; i < 16; i++)  
        {  
            AD_SCLK_LOW;
            //100ns
            readdata = readdata << 1;
            if(AD_DOUT){
                readdata += 1;
            }
            AD_SCLK_HIGH;
            //100ns
        }
        //AD_CS_HIGH;
        //80nS
    )
    return readdata;
}

uint32_t read_24bit(uint8_t chAddress)  
{     
    uint32_t readdata = 0;  
    uint8_t  i;  
    union{
        uint8_t chCRBD;
        struct{
        uint8_t         :2;
        uint8_t Cread   :1;
        uint8_t chRS    :3;
        uint8_t RW      :1;
        uint8_t WEN     :1;
        };
    }tCRBD = {0};
    tCRBD.chCRBD= 0;
    tCRBD.WEN = 0;
    tCRBD.RW  = 1;
    tCRBD.chRS= chAddress;
    SAFE_ATOM_CODE(
        //AD_CS_LOW;
        //80nS
        for(i = 0; i < 8; i++)  
        {  
            AD_SCLK_LOW;
            //100ns
            if(tCRBD.chCRBD & 0x80){
                AD_DIN_HIGH;
            }else{
                AD_DIN_LOW;
            }
            AD_SCLK_HIGH;
            //100ns
            tCRBD.chCRBD = tCRBD.chCRBD<<1;
        }
        AD_DIN_HIGH;
        for(i = 0; i < 24; i++)  
        {  
            AD_SCLK_LOW;
            //100ns
            readdata = readdata << 1;
            if(AD_DOUT){
                readdata += 1;
            }
            AD_SCLK_HIGH;
            //100ns
        }
        //AD_CS_HIGH;
        //80nS
    )
    return readdata;
}

四、读取数据

1、初始化

void Init_ad7797(void)
{
	unsigned char id = 0;
    unsigned int  con= 0;
    //复位
    reset_Ad7797();
    //读取复位状态
    while(1){
        if(0x08 == (read_8bit(AD7797_SR) & 0x08)){
            break;
        }
    }
    //校准
    sys_calibration();
    //读取ID
    while(1){
        if(0x5B == read_8bit(AD7797_IDR)){
            break;
        }
    }
    //设置模式
    Ad7797_Ini();
}

校准:

void sys_calibration(void)    
{  
    //内部零点校准
    write_16bit(AD7797_MR,0x8009);
    while(0x00 != (read_8bit(AD7797_SR) & 0x80));
    //系统零点校准
    //write_16bit(AD7797_MR,0xC009);
    //系统满量程校准
    //write_16bit(AD7797_MR,0xE009);
} 

设置模式:

void Ad7797_Ini(void)     
{     	
//	write_16bit(AD7797_MR,0x0710);

//    while(1){
//        if(0x0710 == read_16bit(AD7797_MR)){
//            break;
//        }
//    }

    while(1){
        write_16bit(AD7797_MR,0x200A);
        if(0x200A == read_16bit(AD7797_MR)){
            break;
        }
    }
}

读取数据流程:

单词模式:

write_16bit(AD7797_MR,0x200A);//启动转换(每次转换完成后,都要从新启动)

等待转换完成,DOUT/RDY引脚边变低

读取数据:

read_24bit(AD7797_DR)

连续模式:

write_16bit(AD7797_MR,0x000A);//配置模式(启动一次就行)

 

等待转换完成,DOUT/RDY引脚边变低

读取数据:

read_24bit(AD7797_DR)

 

采样数据:

2021.04.30

昨天把CS一直使能的驱动调试没有问题了,同事说不建议这样用,还是要启用CS,于是今天又把CS使能了,但是发现一个奇怪的问题,

就是AD一直读取不到数据,查看是读取不到DOUT/RDY拉低,肯定不是驱动函数的事,只能从时序着手了。查看单词读取时序:

启动转换后,等待转换期间,CS要保持低电平,修改逻辑后,测试OK。

 

下图是连续转换模式,需要CS一直使能:

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值