[STC单片机] STC8单片机驱动ADS1256多路AD采集

[复制链接]
6020|5
 楼主| 何程 发表于 2021-7-15 10:45 | 显示全部楼层 |阅读模式
        在使用STC8时需要采集多路小电压值,使用LCD1602显示。但是STC8单片机内部只有10和12位精度的ADC,采集毫伏级电压就不够精确。这时可采用外挂高精度ADC实现。常见的有ADS1115、ADS1256、MCP3421以及国产的TM7705等。本方案采用STC8单片机与ADC1256实现多路AD采集。

        ADS1256是一款低噪声高分辨率的24位ADC,ADS1256数据输出速率最高可为30K采样点/秒(SPS),4路差分与8路单端输入,SPI接口。

      使用现成的ADS1256模块,制作一个STC8G1K08单片机最小系统(可以改成STC8H8K64U、STC8A8K64S4A12或者STC8G2K64),在程序中直接定义SPI通信接口以及LCD1602显示接口,相关定义如下:

  1.         //SPI通信接口
  2.    sbit SCK  = P1^2;
  3.         sbit DIN  = P1^3;
  4.         sbit DOUT = P1^4;
  5.         sbit DRDY = P1^5;
  6.         sbit CS   = P1^6;
  7. //LCD1602引脚接口
  8. sbit LCD_EN=P1^0;
  9. sbit LCD_RW=P1^1;
  10. sbit LCD_RS=P1^7;

  11. #define LCD_DATAPORT P3
对ADS1256初始化:包括SPI通信初始化,读取AD值等。

  1. // QQ:2401553359     QQ群:560864628
  2. #include "STC8.H"
  3. #include "ADS1256.h"
  4.         /*端口定义*/

  5.         sbit SCK  = P1^2;
  6.         sbit DIN  = P1^3;
  7.         sbit DOUT = P1^4;
  8.         sbit DRDY = P1^5;
  9.         sbit CS   = P1^6;

  10.         #define CS_0()                CS = 0
  11.         #define CS_1()                CS = 1
  12.         #define SCK_0()                SCK = 0
  13.         #define SCK_1()                SCK = 1

  14.         #define ADS1256_DIN_0()        DIN = 0
  15.         #define ADS1256_DIN_1()        DIN = 1

  16.         #define ADS1256_DRDY   DRDY
  17.         #define ADS1256_DOUT   DOUT

  18. void delay_ms(u16);

  19. //void Init_ADS1256_GPIO(void)
  20. //{
  21. //        /********************************************
  22. //                 提示:写单片机程序配置I/O口时要注意方向,
  23. //                I/O口配置输出时推荐配置为推挽模式,有些老
  24. //                的51单片机没有推挽模式,推荐加 1K上拉电阻.
  25. //         ********************************************/
  26. //        P1M1 =0x00;
  27. //        P1M0 =0xff; //配置 I O
  28. //        CS_1();
  29. //}



  30. static void ADS1256_DelaySCLK(void)
  31. {
  32.         unsigned short i;

  33.         /*
  34.                 取 5 时,实测高电平200ns, 低电平250ns <-- 不稳定
  35.                 取 10 以上,可以正常工作, 低电平400ns 高定400ns <--- 稳定
  36.         */
  37.         for (i = 0; i < 20; i++);
  38. }
  39. /*
  40. *********************************************************************************************************
  41. *        函 数 名: SPI_WriteByte
  42. *        功能说明: 向SPI总线发送8个bit数据。 不带CS控制。
  43. *        形    参: _data : 数据
  44. *        返 回 值: 无
  45. *********************************************************************************************************
  46. */
  47. void SPI_WriteByte(unsigned char TxData)
  48. {
  49.         unsigned char i;
  50.         /* ADS1256 要求 SCL高电平和低电平持续时间最小 200ns  */
  51.         for(i = 0; i < 8; i++)
  52.         {
  53.                 if (TxData & 0x80)
  54.                         ADS1256_DIN_1();
  55.                 else
  56.                         ADS1256_DIN_0();
  57.                
  58.                 SCK_1();
  59.                 //ADS1256_DelaySCLK();
  60.                 TxData <<= 1;
  61.                 SCK_0();                        /* <----  ADS1256 是在SCK下降沿采样DIN数据, 数据必须维持 50nS */
  62.                 //ADS1256_DelaySCLK();
  63.         }
  64.        
  65. }

  66. /*
  67. *********************************************************************************************************
  68. *        函 数 名: SPI_ReadByte
  69. *        功能说明: 从SPI总线接收8个bit数据。 不带CS控制。
  70. *        形    参: 无
  71. *        返 回 值: 无
  72. *********************************************************************************************************
  73. */
  74. unsigned char SPI_ReadByte(void)
  75. {
  76.         unsigned char i;
  77.         unsigned char read = 0;

  78.         //ADS1256_DelaySCLK();

  79.         /* ADS1256 要求 SCL高电平和低电平持续时间最小 200ns  */
  80.         for (i = 0; i < 8; i++)
  81.         {
  82.                 SCK_1();
  83.                 ADS1256_DelaySCLK();
  84.                 read = read<<1;
  85.                 SCK_0();
  86.                 if (ADS1256_DOUT)
  87.                 {
  88.                         read++;
  89.                 }
  90.                 ADS1256_DelaySCLK();
  91.         }
  92.         return read;
  93. }

  94. //-----------------------------------------------------------------//
  95. //        功    能:ADS1256 写数据
  96. //        入口参数: /
  97. //        出口参数: /
  98. //        全局变量: /
  99. //        备    注: 向ADS1256中地址为regaddr的寄存器写入一个字节databyte
  100. //-----------------------------------------------------------------//
  101. void ADS1256WREG(unsigned char regaddr,unsigned char databyte)
  102. {
  103.    
  104.         CS_0();
  105.         while(ADS1256_DRDY);//当ADS1256_DRDY为低时才能写寄存器
  106.         //向寄存器写入数据地址
  107.     SPI_WriteByte(ADS1256_CMD_WREG | (regaddr & 0x0F));
  108.     //写入数据的个数n-1
  109.     SPI_WriteByte(0x00);
  110.     //向regaddr地址指向的寄存器写入数据databyte
  111.     SPI_WriteByte(databyte);
  112.         CS_1();
  113. }


  114. //初始化ADS1256
  115. void ADS1256_Init(void)
  116. {

  117.         //*************自校准****************
  118.    while(ADS1256_DRDY);
  119.         CS_0();
  120.         SPI_WriteByte(ADS1256_CMD_SELFCAL);
  121.         while(ADS1256_DRDY);
  122.         CS_1();
  123.         //**********************************

  124.         ADS1256WREG(ADS1256_STATUS,0x06);               // 高位在前、校准、使用缓冲
  125. //        ADS1256WREG(ADS1256_STATUS,0x04);               // 高位在前、不使用缓冲
  126. //        ADS1256WREG(ADS1256_MUX,0x08);                  // 初始化端口A0为‘+’,AINCOM位‘-’
  127.         ADS1256WREG(ADS1256_ADCON,ADS1256_GAIN_1);      // 放大倍数1
  128.         ADS1256WREG(ADS1256_DRATE,ADS1256_DRATE_10SPS); // 数据5sps
  129.         ADS1256WREG(ADS1256_IO,0x00);  
  130.                      
  131.         //*************自校准****************
  132.         while(ADS1256_DRDY);
  133.         CS_0();
  134.         SPI_WriteByte(ADS1256_CMD_SELFCAL);
  135.         while(ADS1256_DRDY);
  136.         CS_1();
  137.         //**********************************

  138. }


  139. //读取AD值
  140. signed long ADS1256ReadData(unsigned char channel)  
  141. {
  142.   signed long sum=0;
  143.         char i;
  144.         unsigned long r=0;
  145.        
  146.         while(ADS1256_DRDY);//当ADS1256_DRDY为低时才能写寄存器
  147.         ADS1256WREG(ADS1256_MUX,channel);                //设置通道
  148.         CS_0();
  149.         SPI_WriteByte(ADS1256_CMD_SYNC);//外同步AD信号,启动转换
  150.         SPI_WriteByte(ADS1256_CMD_WAKEUP);//完成同步并退出待机模式          
  151.         while(ADS1256_DRDY);       
  152.         SPI_WriteByte(ADS1256_CMD_RDATA);
  153.         delay_ms(1);
  154.        
  155.         for(i=0;i<3;i++)
  156.     {
  157.             sum = sum << 8;
  158.                 r = SPI_ReadByte();  
  159.                   sum |= r;
  160.         }       

  161.         CS_1();

  162.         if (sum>0x7FFFFF)           // if MSB=1,
  163.         {
  164.                 sum -= 0x1000000;       // do 2's complement
  165.         }

  166.     return sum;
  167. }
编写主函数,这里测量单端电压,如果需要测量差分电压的话按照上面ADS1256头文件修改一下就行了。
  1. void main()//ADS126的PGA不是轨到轨运放,采集3.6V以内电压比较好
  2. {             //如果超过,须加分压电路
  3.         signed        long Adc;//QQ:2401553359,QQ群:560864628
  4.         float  Volts;
  5.         P1M0=0X00;P1M1=0X00;//配置GPIO模式,建议用准双向或者推挽模式
  6.   P3M0=0X00;P3M1=0X00;
  7.   ADS1256_Init();                        //ADS1256 参数初始化
  8.         LCD_Init();
  9.         while(1)//系数自己用基准电压源校准,电赛那时改动太多了。
  10.         {
  11.                 Adc = ADS1256ReadData( ADS1256_MUXP_AIN0|ADS1256_MUXN_AINCOM);       
  12.                 Volts = (Adc*0.00059270)*0.2010; // 0.00000059263 为系数,ADC生产出后都有一定的偏差,在此校准。
  13.                 display_num4(LINE1_COLUMN(5),Volts);
  14.                 delay_ms(50);
  15.                
  16.                 Adc = ADS1256ReadData( ADS1256_MUXP_AIN1|ADS1256_MUXN_AINCOM);       
  17.                 Volts = (Adc*0.00059270)*0.915; // 0.00000059263 为系数,ADC生产出后都有一定的偏差,在此校准。
  18.                 display_num4(LINE1_COLUMN(11),Volts);
  19.                 delay_ms(50);
  20.                
  21.                 Adc = ADS1256ReadData( ADS1256_MUXP_AIN2|ADS1256_MUXN_AINCOM);       
  22.                 Volts = (Adc*0.00058136)*1.910; // 0.00000059263 为系数,ADC生产出后都有一定的偏差,在此校准。
  23.                 display_num4(LINE2_COLUMN(5),Volts);
  24.                 delay_ms(50);
  25.                
  26.           Adc = ADS1256ReadData( ADS1256_MUXP_AIN3|ADS1256_MUXN_AINCOM);       
  27.                 Volts = (Adc*0.00059270)*0.6015; // 0.00000059263 为系数,ADC生产出后都有一定的偏差,在此校准。
  28.                 display_num4(LINE2_COLUMN(11),Volts);
  29.                 DelayMs(50);
  30.         }
  31. }
LCD1602显示效果如下,因为是做电子设计竞赛的,模块比较多,忽略其它模块。

视频链接:https://www.bilibili.com/video/BV1fA41177Um

源码链接:https://pan.baidu.com/s/1dbJw8ggp9Lcxch8wAfIJ4Q

提取码:lm15









ahui1105 发表于 2021-7-16 14:20 | 显示全部楼层
换锦锐CA51F003T3

评论

还没用过,程序兼容STC的吗?  发表于 2021-7-16 22:40
Mentalin 发表于 2022-3-26 12:57 | 显示全部楼层
大佬呀,STC8 与 ADS1256 直接连接无法读取电压数据,这两个之间需要加什么转换电路吗?
 楼主| 何程 发表于 2022-4-2 13:45 | 显示全部楼层
Mentalin 发表于 2022-3-26 12:57
大佬呀,STC8 与 ADS1256 直接连接无法读取电压数据,这两个之间需要加什么转换电路吗? ...

不用加,看看时钟频率对不对
单模先声 发表于 2022-4-6 16:19 | 显示全部楼层

锦锐有硬件乘法器吗
您需要登录后才可以回帖 登录 | 注册

本版积分规则

4

主题

44

帖子

1

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