打印
[STM32F0]

采集的正确和错误数据交替出现

[复制链接]
498|18
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
stly|  楼主 | 2019-11-10 22:48 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
用STM32F072,硬件SPI和AD7705通信,出现一个很奇葩的问题,读AD数据流程是先初始化并设置参数,再读取数据,连续读20次,结果会出现3个错误数据+一个正确数据+3个错误数据+1个正确数据

使用特权

评论回复
沙发
huanghuac| | 2019-11-10 22:52 | 只看该作者
只初始化一次呢

使用特权

评论回复
板凳
stly|  楼主 | 2019-11-10 22:58 | 只看该作者
如果只初始化一次,主循环只读取数据的话,得到的数据就是错误+正确+错误+正确.

使用特权

评论回复
地板
liuzaiy| | 2019-11-10 23:10 | 只看该作者

还有什么现象?能再详细描述下吗?

使用特权

评论回复
5
stly|  楼主 | 2019-11-10 23:14 | 只看该作者

使用特权

评论回复
6
stly|  楼主 | 2019-11-10 23:14 | 只看该作者

使用特权

评论回复
7
stly|  楼主 | 2019-11-10 23:15 | 只看该作者

使用特权

评论回复
8
stly|  楼主 | 2019-11-10 23:15 | 只看该作者

使用特权

评论回复
9
huanghuac| | 2019-11-10 23:17 | 只看该作者
用逻辑分析仪或者示波器抓一下波形,和DataSheet波形进行对比。

使用特权

评论回复
10
zhuhuis| | 2019-11-10 23:20 | 只看该作者
注意检查是不是有状态寄存器,通过状态寄存器判断转换完成才能读取。

使用特权

评论回复
11
stly|  楼主 | 2019-11-10 23:23 | 只看该作者
读之前判断RDY引脚了

使用特权

评论回复
12
chenho| | 2019-11-10 23:26 | 只看该作者
可以换块电路板实时,排除硬件问题。

使用特权

评论回复
13
huanghuac| | 2019-11-10 23:30 | 只看该作者
既然是SPI读取数据,可以分析一下各个数据之间的位关系是否有规律。

使用特权

评论回复
14
happy_10| | 2019-11-10 23:33 | 只看该作者
#include "BSP.H"
#include "Pin.H"

//lint        --e{750}        Info 750: local macro 'XX' not referenced

///////////////////////////////////////////////////////////////////
// Communications Register (RS:000)
///////////////////////////////////////////////////////////////////
#define DRDY                        0x80U                        // status of the DRDY
#define RS_0                ((uint8_t)0x00)                // (0x00U<<4)        Communications Register, 8 Bits
#define RS_1                ((uint8_t)0x10)                // (0x01U<<4)        Setup Register, 8 Bits
#define RS_2                ((uint8_t)0x20)                // (0x02U<<4)        Clock Register, 8 Bits
#define RS_3                ((uint8_t)0x30)                // (0x03U<<4)        Data Register, 16 Bits
#define RS_4                ((uint8_t)0x40)                // (0x04U<<4)        Test Register, 8 Bits
#define RS_5                ((uint8_t)0x50)                // (0x05U<<4)        No Operation
#define RS_6                ((uint8_t)0x60)                // (0x06U<<4)        Offset Register, 24 Bits
#define RS_7                ((uint8_t)0x70)                // (0x07U<<4)        Gain Register, 24 Bits
#define READ                        0x08U                        // Read/Write Select
#define STBY                         0x04U                        // Standby
#define CH_0                ((uint8_t)0x00)                // 7705: AIN1(+) AIN1(-), 7706: AIN1 COMMON
#define CH_1                ((uint8_t)0x01)                // 7705: AIN2(+) AIN2(-), 7706: AIN2 COMMON
#define CH_2                ((uint8_t)0x02)                // 7705: AIN1(-) AIN1(-), 7706: COMMON COMMON
#define CH_3                ((uint8_t)0x03)                // 7705: AIN1(-) AIN2(-), 7706: AIN3 COMMON
///////////////////////////////////////////////////////////////////
// Setup Register (RS:001)
///////////////////////////////////////////////////////////////////
#define FSYNC                ((uint8_t)0x01)                // Filter Synchronization
#define BUF                        ((uint8_t)0x02)                // Buffer Control
#define        B_U                        ((uint8_t)0x04)                // 0: Bipolar Operation, 1: Unipolar Operation
#define BIPOLAR                 0x00u
#define UNIPOLAR                0x04u
#define MD_0                ((uint8_t)0x00)                // Normal Mode
#define MD_1                ((uint8_t)0x40)                // Self-Calibration
#define MD_2                ((uint8_t)0x80)                // Zero-Scale System Calibration
#define MD_3                ((uint8_t)0xC0)                // Full-Scale System Calibration
#define G_0                        ((uint8_t)0x00)                // Gain = 1                (0x00u<<3)
#define G_1                        ((uint8_t)0x08)                // Gain = 2                (0x01u<<3)
#define G_2                        ((uint8_t)0x10)                // Gain = 4                (0x02u<<3)
#define G_3                        ((uint8_t)0x18)                // Gain = 8                (0x03u<<3)
#define G_4                        ((uint8_t)0x20)                // Gain = 16        (0x04u<<3)
#define G_5                        ((uint8_t)0x28)                // Gain = 32        (0x05u<<3)
#define G_6                        ((uint8_t)0x30)                // Gain = 64        (0x06u<<3)
#define G_7                        ((uint8_t)0x38)                // Gain = 128        (0x07u<<3)
///////////////////////////////////////////////////////////////////
// Clock Register (RS:010)
///////////////////////////////////////////////////////////////////
#define CLKDIS                ((uint8_t)0x10)                // Master Clock Disable Bit
#define CLKDIV                ((uint8_t)0x08)                // Clock Divider Bit
#define CLK                                ((uint8_t)0x04)                // Clock Bit.
#define FS_0_0                ((uint8_t)0x00)                // Code = 391, 19.98@1MHz
#define FS_0_1                ((uint8_t)0x01)                // Code = 312, 25.04@1MHz
#define FS_0_2                ((uint8_t)0x02)                // Code =  78, 100.2@1MHz
#define FS_0_3                ((uint8_t)0x03)                // Code =  39, 200.3@1MHz
#define FS_1_0                ((uint8_t)0x04)                // Code = 384, 50.0 @2.4576MHz
#define FS_1_1                ((uint8_t)0x05)                // Code = 320, 60.0 @2.4576MHz
#define FS_1_2                ((uint8_t)0x06)                // Code =  77, 249.4@2.4576MHz
#define FS_1_3                ((uint8_t)0x07)                // Code =  38, 505.3@2.4576MHz
///////////////////////////////////////////////////////////////////
#define        AD7705_Shift_In()                (uint8_t)bus_SPIxShift(0xFFu)/*TODEL*/        
#define        AD7705_Shift_Out(_cout)        ( void )bus_SPIxShift(_cout)

///////////////////////////////////////////////////////////////////
// AD7705 访问控制接口
///////////////////////////////////////////////////////////////////
static        const        uint8_t        Cfg7705[CS7705_Max][2] =
{
        {
                        BIPOLAR + G_5 + BUF,        // C1H0: pf
                        BIPOLAR + G_4 + BUF,        // C1H1: pr
        },
        {
                        BIPOLAR + G_5 + BUF,        // C2H0: pf
                        BIPOLAR + G_4 + BUF,        // C2H1: pr
        },
        {
                        BIPOLAR + G_5 + BUF,        // C3H0: pf
                        BIPOLAR + G_4 + BUF,        // C3H1: pr
        }
        ,
        {
                        BIPOLAR + G_5 + BUF,        // C4H0: pf
                        BIPOLAR + G_4 + BUF,        // C4H1: pr
        }
        ,
        {
                        BIPOLAR + G_5 + BUF,        // C5H0: pf
                        BIPOLAR + G_4 + BUF,        // C5H1: pr
        }
};

uint8_t        SetBuf[CS7705_Max][12];
void        ConfigureRead( enum enumCS7705 cs, uint8_t xs )
{

        uint8_t                iRetry;

        for ( iRetry = 10u; iRetry != 0u; --iRetry )
        {
                uint8_t        ReadyState;
                Select7705( cs );
                delay( 1u );
                AD7705_Shift_Out( RS_0 + READ + xs );
                ReadyState = AD7705_Shift_In();
                Select7705( CS7705_none );                        //                DeSelect All
                if ( 0x00u == ( ReadyState & DRDY ))
                {
                        Select7705( cs );
                        AD7705_Shift_Out( RS_6 + READ + xs );
                        SetBuf[cs][0 + 6 * xs] = AD7705_Shift_In();
                        SetBuf[cs][1 + 6 * xs] = AD7705_Shift_In();
                        SetBuf[cs][2 + 6 * xs] = AD7705_Shift_In();
                        Select7705( CS7705_none );                //                DeSelect All        
                        delay( 1u );
                        break;        //        done.
                }
                delay( 10u );
        }
        
        for ( iRetry = 10u; iRetry != 0u; --iRetry )
        {
                uint8_t        ReadyState;
                Select7705( cs );
                delay( 1u );
                AD7705_Shift_Out( RS_0 + READ + xs );
                ReadyState = AD7705_Shift_In();
                Select7705( CS7705_none );                        //        DeSelect All
                if ( 0x00u == ( ReadyState & DRDY ))
                {
                        Select7705( cs );
                        AD7705_Shift_Out( RS_7 + READ + xs );
                        SetBuf[cs][3 + 6 * xs] = AD7705_Shift_In();
                        SetBuf[cs][4 + 6 * xs] = AD7705_Shift_In();
                        SetBuf[cs][5 + 6 * xs] = AD7705_Shift_In();        
                        Select7705( CS7705_none );                        //        DeSelect All        
                        delay( 1u );
                        break;        //        done.
                }
                delay( 10u );
        }

}
void        ConfigureWrite( enum enumCS7705 cs, uint8_t xs )
{
                AD7705_Shift_Out( RS_6 + xs );
                AD7705_Shift_Out( SetBuf[cs][0 + 6 * xs]  );
                AD7705_Shift_Out( SetBuf[cs][1 + 6 * xs] );
                AD7705_Shift_Out( SetBuf[cs][2 + 6 * xs] );
                                
                AD7705_Shift_Out( RS_7 + xs );
                AD7705_Shift_Out( SetBuf[cs][3 + 6 * xs]  );
                AD7705_Shift_Out( SetBuf[cs][4 + 6 * xs] );
                AD7705_Shift_Out( SetBuf[cs][5 + 6 * xs] );

}
/**
*        对指定的通道进行转换。回读配置供主程序判断7705是否工作正常。
*/
static        uint8_t        _Convert7705( uint8_t mode_set, uint8_t xs )
{
        uint8_t        mode_readback;

        AD7705_Shift_Out( xs + RS_1 );                        // 切换到指定的采样通道
        AD7705_Shift_Out( mode_set );                        // 以指定的配置进行采样

        AD7705_Shift_Out( xs + RS_2 );                        // Clock Register, 8 Bits
        AD7705_Shift_Out( CLKDIV + FS_1_0 );        // 50Hz @ 4.9152MHz

        AD7705_Shift_Out( xs + RS_4 );                        // Test Register, 8 Bits
        AD7705_Shift_Out( 0x00u );                                // Default: 0x00

        AD7705_Shift_Out( xs + RS_3 + READ );        //        读取数据以复位 DRDY#
        (void)AD7705_Shift_In();
        (void)AD7705_Shift_In();

        AD7705_Shift_Out( xs + RS_1 + READ );        //        回读配置
        mode_readback = AD7705_Shift_In();
        
        return        mode_readback;
}

bool        Convert7705( enum enumCS7705 cs, uint8_t xs )
{
        const uint8_t mode_set = MD_0 + Cfg7705[cs][xs];
        uint8_t        mode_readback;

        Select7705( cs );
        delay( 1u );
        
        ConfigureWrite( cs, xs );
        
        mode_readback = _Convert7705( mode_set, xs );        
        Select7705( CS7705_none );
        delay( 1u );
        if ( mode_set == mode_readback )
        {
                return        true;        //        工作正常
        }
        else
        {
                return        false;        //        工作有问题,没焊?!
        }
}

uint16_t        Readout7705( enum enumCS7705 cs, uint8_t xs )
{
        uint16_t        Result = 0u;
        uint8_t                iRetry;

        for ( iRetry = 20u; iRetry != 0u; --iRetry )
        {
                uint8_t        ReadyState;
               
                Select7705( cs );
                delay( 1u );
                AD7705_Shift_Out( RS_0 + READ + xs );
                ReadyState = AD7705_Shift_In();
                Select7705( CS7705_none );                        //        DeSelect All        
                if ( 0x00u == ( ReadyState & DRDY ))
                {        //        is DRDY# ?
                uint8_t        ResultH, ResultL;
                Select7705( cs );                        //        DeSelect All        
                AD7705_Shift_Out( RS_3 + READ + xs );        //        Read.
                ResultH = AD7705_Shift_In();
                ResultL = AD7705_Shift_In();
                Result = ( ResultL + ( ResultH * 0x100u ));
                Select7705( CS7705_none );                        //        DeSelect All        
                delay( 1u );
                break;        //        done.
                 }
                delay( 20u );
        }

        return        Result;
}

void        Initialize7705( void )
{
        uint8_t        i;

        for ( i = 0u; i < CS7705_Max; ++i )
        {
                Select7705( i );
                delay( 1u );
                // Synchronization.
                AD7705_Shift_Out( 0xFFu );
                AD7705_Shift_Out( 0xFFu );
                AD7705_Shift_Out( 0xFFu );
                AD7705_Shift_Out( 0xFFu );
                AD7705_Shift_Out( 0xFFu );
                AD7705_Shift_Out( 0xFFu );
                AD7705_Shift_Out( 0xFFu );
               
                // 启动指定通道的自校准转换
                _Convert7705( MD_1 + Cfg7705[1], 1u );
                delay( 1u );
                Select7705( CS7705_none );

        }
        delay( 220u );
        for ( i = 0u; i < CS7705_Max; ++i )
        {
                ConfigureRead( (enum enumCS7705) i, 1u );
        }
        
        for ( i = 0u; i < CS7705_Max; ++i )
        {
                Select7705( i );
                delay( 1u );
                // 启动指定通道的自校准转换
                _Convert7705( MD_1 + Cfg7705[0], 0u );
                delay( 1u );
                Select7705( CS7705_none );
        }

        delay( 220u );
        
        for ( i = 0u; i < CS7705_Max; ++i )
        {
                ConfigureRead( (enum enumCS7705) i, 0u );
        }

}


使用特权

评论回复
15
stly|  楼主 | 2019-11-10 23:36 | 只看该作者
解决了,是忘记设置SPI的FIFO了尴尬

使用特权

评论回复
16
characteristic| | 2019-11-11 19:24 | 只看该作者
是保持时间的问题么

使用特权

评论回复
17
paotangsan| | 2019-12-9 16:18 | 只看该作者
缓冲做的不太好吧

使用特权

评论回复
18
renzheshengui| | 2019-12-9 16:22 | 只看该作者
恭喜楼主解决问题

使用特权

评论回复
19
wakayi| | 2019-12-9 16:27 | 只看该作者
长知识了 呵呵呵

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

433

主题

7058

帖子

0

粉丝