[STM32F0] 求教大神,STM32+AD7705,采集的正确和错误数据交替出现

[复制链接]
2780|7
 楼主| as564335sa 发表于 2018-5-17 16:19 | 显示全部楼层 |阅读模式
我用STM32F072,硬件SPI和AD7705通信,出现一个很奇葩的问题,读AD数据流程是先初始化并设置参数,再读取数据,连续读20次,结果会出现3个错误数据+一个正确数据+3个错误数据+1个正确数据.....有人遇到过吗,好奇葩,调了两天了,如果只初始化一次,主循环只读取数据的话,得到的数据就是错误+正确+错误+正确.........这样。
TIM截图20180517161045.png
TIM截图20180517161056.png

读出的数据

读出的数据

SPI配置

SPI配置
linqing171 发表于 2018-5-17 22:47 | 显示全部楼层
用逻辑分析仪或者示波器抓一下波形,和DataSheet波形进行对比。
Prry 发表于 2018-5-18 08:40 | 显示全部楼层
注意检查是不是有状态寄存器,通过状态寄存器判断转换完成才能读取。
 楼主| as564335sa 发表于 2018-5-18 08:53 | 显示全部楼层
Prry 发表于 2018-5-18 08:40
注意检查是不是有状态寄存器,通过状态寄存器判断转换完成才能读取。

读之前判断RDY引脚了
小研究 发表于 2018-5-18 11:12 | 显示全部楼层
1 可以换块电路板实时,排除硬件问题。
2 既然是SPI读取数据,可以分析一下各个数据之间的位关系是否有规律。
我是你看不懂的 发表于 2018-5-18 11:51 | 显示全部楼层
我这个用了很久  你参考吧
我是你看不懂的 发表于 2018-5-18 11:52 | 显示全部楼层
  1. #include "BSP.H"
  2. #include "Pin.H"

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

  4. ///////////////////////////////////////////////////////////////////
  5. // Communications Register (RS:000)
  6. ///////////////////////////////////////////////////////////////////
  7. #define DRDY                        0x80U                        // status of the DRDY
  8. #define RS_0                ((uint8_t)0x00)                // (0x00U<<4)        Communications Register, 8 Bits
  9. #define RS_1                ((uint8_t)0x10)                // (0x01U<<4)        Setup Register, 8 Bits
  10. #define RS_2                ((uint8_t)0x20)                // (0x02U<<4)        Clock Register, 8 Bits
  11. #define RS_3                ((uint8_t)0x30)                // (0x03U<<4)        Data Register, 16 Bits
  12. #define RS_4                ((uint8_t)0x40)                // (0x04U<<4)        Test Register, 8 Bits
  13. #define RS_5                ((uint8_t)0x50)                // (0x05U<<4)        No Operation
  14. #define RS_6                ((uint8_t)0x60)                // (0x06U<<4)        Offset Register, 24 Bits
  15. #define RS_7                ((uint8_t)0x70)                // (0x07U<<4)        Gain Register, 24 Bits
  16. #define READ                        0x08U                        // Read/Write Select
  17. #define STBY                         0x04U                        // Standby
  18. #define CH_0                ((uint8_t)0x00)                // 7705: AIN1(+) AIN1(-), 7706: AIN1 COMMON
  19. #define CH_1                ((uint8_t)0x01)                // 7705: AIN2(+) AIN2(-), 7706: AIN2 COMMON
  20. #define CH_2                ((uint8_t)0x02)                // 7705: AIN1(-) AIN1(-), 7706: COMMON COMMON
  21. #define CH_3                ((uint8_t)0x03)                // 7705: AIN1(-) AIN2(-), 7706: AIN3 COMMON
  22. ///////////////////////////////////////////////////////////////////
  23. // Setup Register (RS:001)
  24. ///////////////////////////////////////////////////////////////////
  25. #define FSYNC                ((uint8_t)0x01)                // Filter Synchronization
  26. #define BUF                        ((uint8_t)0x02)                // Buffer Control
  27. #define        B_U                        ((uint8_t)0x04)                // 0: Bipolar Operation, 1: Unipolar Operation
  28. #define BIPOLAR                 0x00u
  29. #define UNIPOLAR                0x04u
  30. #define MD_0                ((uint8_t)0x00)                // Normal Mode
  31. #define MD_1                ((uint8_t)0x40)                // Self-Calibration
  32. #define MD_2                ((uint8_t)0x80)                // Zero-Scale System Calibration
  33. #define MD_3                ((uint8_t)0xC0)                // Full-Scale System Calibration
  34. #define G_0                        ((uint8_t)0x00)                // Gain = 1                (0x00u<<3)
  35. #define G_1                        ((uint8_t)0x08)                // Gain = 2                (0x01u<<3)
  36. #define G_2                        ((uint8_t)0x10)                // Gain = 4                (0x02u<<3)
  37. #define G_3                        ((uint8_t)0x18)                // Gain = 8                (0x03u<<3)
  38. #define G_4                        ((uint8_t)0x20)                // Gain = 16        (0x04u<<3)
  39. #define G_5                        ((uint8_t)0x28)                // Gain = 32        (0x05u<<3)
  40. #define G_6                        ((uint8_t)0x30)                // Gain = 64        (0x06u<<3)
  41. #define G_7                        ((uint8_t)0x38)                // Gain = 128        (0x07u<<3)
  42. ///////////////////////////////////////////////////////////////////
  43. // Clock Register (RS:010)
  44. ///////////////////////////////////////////////////////////////////
  45. #define CLKDIS                ((uint8_t)0x10)                // Master Clock Disable Bit
  46. #define CLKDIV                ((uint8_t)0x08)                // Clock Divider Bit
  47. #define CLK                                ((uint8_t)0x04)                // Clock Bit.
  48. #define FS_0_0                ((uint8_t)0x00)                // Code = 391, 19.98@1MHz
  49. #define FS_0_1                ((uint8_t)0x01)                // Code = 312, 25.04@1MHz
  50. #define FS_0_2                ((uint8_t)0x02)                // Code =  78, 100.2@1MHz
  51. #define FS_0_3                ((uint8_t)0x03)                // Code =  39, 200.3@1MHz
  52. #define FS_1_0                ((uint8_t)0x04)                // Code = 384, 50.0 @2.4576MHz
  53. #define FS_1_1                ((uint8_t)0x05)                // Code = 320, 60.0 @2.4576MHz
  54. #define FS_1_2                ((uint8_t)0x06)                // Code =  77, 249.4@2.4576MHz
  55. #define FS_1_3                ((uint8_t)0x07)                // Code =  38, 505.3@2.4576MHz
  56. ///////////////////////////////////////////////////////////////////
  57. #define        AD7705_Shift_In()                (uint8_t)bus_SPIxShift(0xFFu)/*TODEL*/       
  58. #define        AD7705_Shift_Out(_cout)        ( void )bus_SPIxShift(_cout)

  59. ///////////////////////////////////////////////////////////////////
  60. // AD7705 访问控制接口
  61. ///////////////////////////////////////////////////////////////////
  62. static        const        uint8_t        Cfg7705[CS7705_Max][2] =
  63. {
  64.         {
  65.                         BIPOLAR + G_5 + BUF,        // C1H0: pf
  66.                         BIPOLAR + G_4 + BUF,        // C1H1: pr
  67.         },
  68.         {
  69.                         BIPOLAR + G_5 + BUF,        // C2H0: pf
  70.                         BIPOLAR + G_4 + BUF,        // C2H1: pr
  71.         },
  72.         {
  73.                         BIPOLAR + G_5 + BUF,        // C3H0: pf
  74.                         BIPOLAR + G_4 + BUF,        // C3H1: pr
  75.         }
  76.         ,
  77.         {
  78.                         BIPOLAR + G_5 + BUF,        // C4H0: pf
  79.                         BIPOLAR + G_4 + BUF,        // C4H1: pr
  80.         }
  81.         ,
  82.         {
  83.                         BIPOLAR + G_5 + BUF,        // C5H0: pf
  84.                         BIPOLAR + G_4 + BUF,        // C5H1: pr
  85.         }
  86. };

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

  90.         uint8_t                iRetry;

  91.         for ( iRetry = 10u; iRetry != 0u; --iRetry )
  92.         {
  93.                 uint8_t        ReadyState;
  94.                 Select7705( cs );
  95.                 delay( 1u );
  96.                 AD7705_Shift_Out( RS_0 + READ + xs );
  97.                 ReadyState = AD7705_Shift_In();
  98.                 Select7705( CS7705_none );                        //                DeSelect All
  99.                 if ( 0x00u == ( ReadyState & DRDY ))
  100.                 {
  101.                         Select7705( cs );
  102.                         AD7705_Shift_Out( RS_6 + READ + xs );
  103.                         SetBuf[cs][0 + 6 * xs] = AD7705_Shift_In();
  104.                         SetBuf[cs][1 + 6 * xs] = AD7705_Shift_In();
  105.                         SetBuf[cs][2 + 6 * xs] = AD7705_Shift_In();
  106.                         Select7705( CS7705_none );                //                DeSelect All       
  107.                         delay( 1u );
  108.                         break;        //        done.
  109.                 }
  110.                 delay( 10u );
  111.         }
  112.        
  113.         for ( iRetry = 10u; iRetry != 0u; --iRetry )
  114.         {
  115.                 uint8_t        ReadyState;
  116.                 Select7705( cs );
  117.                 delay( 1u );
  118.                 AD7705_Shift_Out( RS_0 + READ + xs );
  119.                 ReadyState = AD7705_Shift_In();
  120.                 Select7705( CS7705_none );                        //        DeSelect All
  121.                 if ( 0x00u == ( ReadyState & DRDY ))
  122.                 {
  123.                         Select7705( cs );
  124.                         AD7705_Shift_Out( RS_7 + READ + xs );
  125.                         SetBuf[cs][3 + 6 * xs] = AD7705_Shift_In();
  126.                         SetBuf[cs][4 + 6 * xs] = AD7705_Shift_In();
  127.                         SetBuf[cs][5 + 6 * xs] = AD7705_Shift_In();       
  128.                         Select7705( CS7705_none );                        //        DeSelect All       
  129.                         delay( 1u );
  130.                         break;        //        done.
  131.                 }
  132.                 delay( 10u );
  133.         }

  134. }
  135. void        ConfigureWrite( enum enumCS7705 cs, uint8_t xs )
  136. {
  137.                 AD7705_Shift_Out( RS_6 + xs );
  138.                 AD7705_Shift_Out( SetBuf[cs][0 + 6 * xs]  );
  139.                 AD7705_Shift_Out( SetBuf[cs][1 + 6 * xs] );
  140.                 AD7705_Shift_Out( SetBuf[cs][2 + 6 * xs] );
  141.                                
  142.                 AD7705_Shift_Out( RS_7 + xs );
  143.                 AD7705_Shift_Out( SetBuf[cs][3 + 6 * xs]  );
  144.                 AD7705_Shift_Out( SetBuf[cs][4 + 6 * xs] );
  145.                 AD7705_Shift_Out( SetBuf[cs][5 + 6 * xs] );

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

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

  155.         AD7705_Shift_Out( xs + RS_2 );                        // Clock Register, 8 Bits
  156.         AD7705_Shift_Out( CLKDIV + FS_1_0 );        // 50Hz [url=home.php?mod=space&uid=72445]@[/url] 4.9152MHz

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

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

  162.         AD7705_Shift_Out( xs + RS_1 + READ );        //        回读配置
  163.         mode_readback = AD7705_Shift_In();
  164.        
  165.         return        mode_readback;
  166. }

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

  171.         Select7705( cs );
  172.         delay( 1u );
  173.        
  174.         ConfigureWrite( cs, xs );
  175.        
  176.         mode_readback = _Convert7705( mode_set, xs );       
  177.         Select7705( CS7705_none );
  178.         delay( 1u );
  179.         if ( mode_set == mode_readback )
  180.         {
  181.                 return        true;        //        工作正常
  182.         }
  183.         else
  184.         {
  185.                 return        false;        //        工作有问题,没焊?!
  186.         }
  187. }

  188. uint16_t        Readout7705( enum enumCS7705 cs, uint8_t xs )
  189. {
  190.         uint16_t        Result = 0u;
  191.         uint8_t                iRetry;

  192.         for ( iRetry = 20u; iRetry != 0u; --iRetry )
  193.         {
  194.                 uint8_t        ReadyState;
  195.                
  196.                 Select7705( cs );
  197.                 delay( 1u );
  198.                 AD7705_Shift_Out( RS_0 + READ + xs );
  199.                 ReadyState = AD7705_Shift_In();
  200.                 Select7705( CS7705_none );                        //        DeSelect All       
  201.                 if ( 0x00u == ( ReadyState & DRDY ))
  202.                 {        //        is DRDY# ?
  203.                 uint8_t        ResultH, ResultL;
  204.                 Select7705( cs );                        //        DeSelect All       
  205.                 AD7705_Shift_Out( RS_3 + READ + xs );        //        Read.
  206.                 ResultH = AD7705_Shift_In();
  207.                 ResultL = AD7705_Shift_In();
  208.                 Result = ( ResultL + ( ResultH * 0x100u ));
  209.                 Select7705( CS7705_none );                        //        DeSelect All       
  210.                 delay( 1u );
  211.                 break;        //        done.
  212.                  }
  213.                 delay( 20u );
  214.         }

  215.         return        Result;
  216. }

  217. void        Initialize7705( void )
  218. {
  219.         uint8_t        i;

  220.         for ( i = 0u; i < CS7705_Max; ++i )
  221.         {
  222.                 Select7705( i );
  223.                 delay( 1u );
  224.                 // Synchronization.
  225.                 AD7705_Shift_Out( 0xFFu );
  226.                 AD7705_Shift_Out( 0xFFu );
  227.                 AD7705_Shift_Out( 0xFFu );
  228.                 AD7705_Shift_Out( 0xFFu );
  229.                 AD7705_Shift_Out( 0xFFu );
  230.                 AD7705_Shift_Out( 0xFFu );
  231.                 AD7705_Shift_Out( 0xFFu );
  232.                
  233.                 // 启动指定通道的自校准转换
  234.                 _Convert7705( MD_1 + Cfg7705[i][1], 1u );
  235.                 delay( 1u );
  236.                 Select7705( CS7705_none );

  237.         }
  238.         delay( 220u );
  239.         for ( i = 0u; i < CS7705_Max; ++i )
  240.         {
  241.                 ConfigureRead( (enum enumCS7705) i, 1u );
  242.         }
  243.        
  244.         for ( i = 0u; i < CS7705_Max; ++i )
  245.         {
  246.                 Select7705( i );
  247.                 delay( 1u );
  248.                 // 启动指定通道的自校准转换
  249.                 _Convert7705( MD_1 + Cfg7705[i][0], 0u );
  250.                 delay( 1u );
  251.                 Select7705( CS7705_none );
  252.         }

  253.         delay( 220u );
  254.        
  255.         for ( i = 0u; i < CS7705_Max; ++i )
  256.         {
  257.                 ConfigureRead( (enum enumCS7705) i, 0u );
  258.         }

  259. }


 楼主| as564335sa 发表于 2018-5-18 13:46 | 显示全部楼层
解决了,是忘记设置SPI的FIFO了尴尬
您需要登录后才可以回帖 登录 | 注册

本版积分规则

6

主题

252

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部