1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > STC8单片机驱动ADS1256多路AD采集

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

时间:2022-11-28 07:28:19

相关推荐

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

在使用STC8时需要采集多路小电压值,使用LCD1602显示。但是STC8单片机内部只有10和12位精度的ADC,采集毫伏级电压就不够精确。这时可采用外挂高精度ADC实现。常见的有ADS1115、ADS1256、MCP3421以及国产的TM7705等。本方案采用STC8单片机与ADC1256实现多路AD采集。ADS1256是一款低噪声高分辨率的24位ADC,ADS1256数据输出速率最高可为30K采样点/秒(SPS),4路差分与8路单端输入,SPI接口。原理图如下所示:![ADS1256](https://img-/0714142524264.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NDA2NDI1,size_16,color_FFFFFF,t_70#pic_center)## 电路连接使用现成的ADS1256模块,制作一个STC8G1K08单片机最小系统(可以改成STC8H8K64U、STC8A8K64S4A12或者STC8G2K64),在程序中直接定义SPI通信接口以及LCD1602显示接口,相关定义如下:

//SPI通信接口sbit SCK = P1^2;sbit DIN = P1^3;sbit DOUT = P1^4;sbit DRDY = P1^5;sbit CS = P1^6;//LCD1602引脚接口sbit LCD_EN=P1^0;sbit LCD_RW=P1^1;sbit LCD_RS=P1^7;#define LCD_DATAPORT P3

定义好相关端口后开始导入ADS1256头文件:

// QQ:2401553359QQ群:560864628#ifndef __ADS1256_H_#define__ADS1256_H_// define commands #define ADS1256_CMD_WAKEUP 0x00 #define ADS1256_CMD_RDATA 0x01 #define ADS1256_CMD_RDATAC 0x03 #define ADS1256_CMD_SDATAC 0x0f #define ADS1256_CMD_RREG0x10 #define ADS1256_CMD_WREG0x50 #define ADS1256_CMD_SELFCAL 0xf0 #define ADS1256_CMD_SELFOCAL 0xf1 #define ADS1256_CMD_SELFGCAL 0xf2 #define ADS1256_CMD_SYSOCAL 0xf3 #define ADS1256_CMD_SYSGCAL 0xf4 #define ADS1256_CMD_SYNC0xfc #define ADS1256_CMD_STANDBY 0xfd #define ADS1256_CMD_REST 0xfe // define the ADS1256 register values #define ADS1256_STATUS 0x00 #define ADS1256_MUX0x01 #define ADS1256_ADCON 0x02 #define ADS1256_DRATE 0x03 #define ADS1256_IO 0x04 #define ADS1256_OFC0 0x05 #define ADS1256_OFC1 0x06 #define ADS1256_OFC2 0x07 #define ADS1256_FSC0 0x08 #define ADS1256_FSC1 0x09 #define ADS1256_FSC2 0x0A // define multiplexer codes #define ADS1256_MUXP_AIN0 0x00 #define ADS1256_MUXP_AIN1 0x10 #define ADS1256_MUXP_AIN2 0x20 #define ADS1256_MUXP_AIN3 0x30 #define ADS1256_MUXP_AIN4 0x40 #define ADS1256_MUXP_AIN5 0x50 #define ADS1256_MUXP_AIN6 0x60 #define ADS1256_MUXP_AIN7 0x70 #define ADS1256_MUXP_AINCOM 0x80 #define ADS1256_MUXN_AIN0 0x00 #define ADS1256_MUXN_AIN1 0x01 #define ADS1256_MUXN_AIN2 0x02 #define ADS1256_MUXN_AIN3 0x03 #define ADS1256_MUXN_AIN4 0x04 #define ADS1256_MUXN_AIN5 0x05 #define ADS1256_MUXN_AIN6 0x06 #define ADS1256_MUXN_AIN7 0x07 #define ADS1256_MUXN_AINCOM 0x08 // define gain codes #define ADS1256_GAIN_10x00 #define ADS1256_GAIN_20x01 #define ADS1256_GAIN_40x02 #define ADS1256_GAIN_80x03 #define ADS1256_GAIN_160x04 #define ADS1256_GAIN_320x05 #define ADS1256_GAIN_640x06 //#define ADS1256_GAIN_640x07 //define drate codes #define ADS1256_DRATE_30000SPS 0xF0 #define ADS1256_DRATE_15000SPS 0xE0 #define ADS1256_DRATE_7500SPS 0xD0 #define ADS1256_DRATE_3750SPS 0xC0 #define ADS1256_DRATE_2000SPS 0xB0 #define ADS1256_DRATE_1000SPS 0xA1 #define ADS1256_DRATE_500SPS 0x92 #define ADS1256_DRATE_100SPS 0x82 #define ADS1256_DRATE_60SPS0x72 #define ADS1256_DRATE_50SPS0x63 #define ADS1256_DRATE_30SPS0x53 #define ADS1256_DRATE_25SPS0x43 #define ADS1256_DRATE_15SPS0x33 #define ADS1256_DRATE_10SPS0x23 #define ADS1256_DRATE_5SPS0x13 #define ADS1256_DRATE_2_5SPS 0x03signed long ADS1256ReadData(unsigned char channel);void ADS1256_Init(void); //初始化ADS1256void Init_ADS1256_GPIO(void); //#endif

对ADS1256初始化:包括SPI通信初始化,读取AD值等。

// QQ:2401553359QQ群:560864628#include "STC8.H"#include "ADS1256.h"/*端口定义*/ sbit SCK = P1^2;sbit DIN = P1^3;sbit DOUT = P1^4;sbit DRDY = P1^5;sbit CS = P1^6;#define CS_0()CS = 0#define CS_1()CS = 1#define SCK_0()SCK = 0#define SCK_1()SCK = 1#define ADS1256_DIN_0()DIN = 0#define ADS1256_DIN_1()DIN = 1#define ADS1256_DRDY DRDY#define ADS1256_DOUT DOUTvoid delay_ms(u16);//void Init_ADS1256_GPIO(void)//{///********************************************// 提示:写单片机程序配置I/O口时要注意方向,//I/O口配置输出时推荐配置为推挽模式,有些老//的51单片机没有推挽模式,推荐加 1K上拉电阻.// ********************************************///P1M1 =0x00;//P1M0 =0xff; //配置 I O//CS_1();//}static void ADS1256_DelaySCLK(void){unsigned short i;/*取 5 时,实测高电平200ns, 低电平250ns <-- 不稳定取 10 以上,可以正常工作, 低电平400ns 高定400ns <--- 稳定*/for (i = 0; i < 20; i++);}/***********************************************************************************************************函 数 名: SPI_WriteByte*功能说明: 向SPI总线发送8个bit数据。 不带CS控制。*形 参: _data : 数据*返 回 值: 无**********************************************************************************************************/void SPI_WriteByte(unsigned char TxData){unsigned char i;/*ADS1256 要求 SCL高电平和低电平持续时间最小 200ns */for(i = 0; i < 8; i++){if (TxData & 0x80)ADS1256_DIN_1();elseADS1256_DIN_0();SCK_1();//ADS1256_DelaySCLK();TxData <<= 1;SCK_0();/* <---- ADS1256 是在SCK下降沿采样DIN数据, 数据必须维持 50nS *///ADS1256_DelaySCLK();}} /***********************************************************************************************************函 数 名: SPI_ReadByte*功能说明: 从SPI总线接收8个bit数据。 不带CS控制。*形 参: 无*返 回 值: 无**********************************************************************************************************/unsigned char SPI_ReadByte(void){unsigned char i;unsigned char read = 0;//ADS1256_DelaySCLK();/*ADS1256 要求 SCL高电平和低电平持续时间最小 200ns */for (i = 0; i < 8; i++){SCK_1();ADS1256_DelaySCLK();read = read<<1;SCK_0();if (ADS1256_DOUT){read++;}ADS1256_DelaySCLK();}return read;}//-----------------------------------------------------------------////功 能:ADS1256 写数据//入口参数: ///出口参数: ///全局变量: ///备 注: 向ADS1256中地址为regaddr的寄存器写入一个字节databyte//-----------------------------------------------------------------//void ADS1256WREG(unsigned char regaddr,unsigned char databyte){CS_0();while(ADS1256_DRDY);//当ADS1256_DRDY为低时才能写寄存器//向寄存器写入数据地址SPI_WriteByte(ADS1256_CMD_WREG | (regaddr & 0x0F));//写入数据的个数n-1SPI_WriteByte(0x00);//向regaddr地址指向的寄存器写入数据databyteSPI_WriteByte(databyte);CS_1();}//初始化ADS1256void ADS1256_Init(void){//*************自校准****************while(ADS1256_DRDY);CS_0();SPI_WriteByte(ADS1256_CMD_SELFCAL);while(ADS1256_DRDY);CS_1();//**********************************ADS1256WREG(ADS1256_STATUS,0x06);// 高位在前、校准、使用缓冲//ADS1256WREG(ADS1256_STATUS,0x04);// 高位在前、不使用缓冲//ADS1256WREG(ADS1256_MUX,0x08); // 初始化端口A0为‘+’,AINCOM位‘-’ADS1256WREG(ADS1256_ADCON,ADS1256_GAIN_1);// 放大倍数1ADS1256WREG(ADS1256_DRATE,ADS1256_DRATE_10SPS); // 数据5spsADS1256WREG(ADS1256_IO,0x00); //*************自校准****************while(ADS1256_DRDY);CS_0();SPI_WriteByte(ADS1256_CMD_SELFCAL);while(ADS1256_DRDY);CS_1(); //**********************************}//读取AD值signed long ADS1256ReadData(unsigned char channel) {signed long sum=0;char i;unsigned long r=0;while(ADS1256_DRDY);//当ADS1256_DRDY为低时才能写寄存器 ADS1256WREG(ADS1256_MUX,channel);//设置通道CS_0();SPI_WriteByte(ADS1256_CMD_SYNC);//外同步AD信号,启动转换SPI_WriteByte(ADS1256_CMD_WAKEUP);//完成同步并退出待机模式 while(ADS1256_DRDY);SPI_WriteByte(ADS1256_CMD_RDATA);delay_ms(1);for(i=0;i<3;i++){sum = sum << 8;r = SPI_ReadByte(); sum |= r;}CS_1();if (sum>0x7FFFFF) // if MSB=1, {sum -= 0x1000000; // do 2's complement}return sum;}

初始化LCD1602显示,这里定义的是8线并行接口,可以修改为4线串行接口:

sbit LCD_EN=P1^0; //STC8G1K08——20Pinsbit LCD_RW=P1^1;sbit LCD_RS=P1^7;#define LINE1_COLUMN(x) 0x7f+x#define LINE2_COLUMN(x) 0xbf+x#define LCD_DATAPORT P3//端口可改,模式可以改成串行的,减小引脚使用void DelayMs( u16 ms)//延时{u16 i,j;for (i = 0; i < ms; i++)for(j=0;j<115;j++);}void delay_ms(u16 nms){u16 x,y;for(x=nms;x>0;x--)for(y=120;y>0;y--);}void LCD1602_WriteCMD(u8 cmd)//LCD1602写命令函数{LCD_RS=0;LCD_DATAPORT=cmd;delay_ms(1);LCD_EN=1;delay_ms(1);LCD_EN=0;}void LCD1602_WriteData(u8 dat)//LCD1602写数据函数{LCD_RS=1;LCD_DATAPORT=dat;delay_ms(1);LCD_EN=1;delay_ms(1);LCD_EN=0;}void display_char(u8 addr,u8 chr){LCD1602_WriteCMD(addr);LCD1602_WriteData(chr);}void display_num4(u8 addr,u16 num)//显示{u8 qian,bai,shi,ge;qian= num/1000;bai = num/100%10;shi = num/10%10;ge = num%10;//变量分离display_char(addr,qian+'0');//保留两位小数,display_char(addr+1,bai+'0');display_char(addr+2,'.');display_char(addr+3,shi+'0');display_char(addr+4,ge+'0');display_char(LINE1_COLUMN(1),'V');//第一行写字符,VIN:、V、Adisplay_char(LINE1_COLUMN(2),'I');display_char(LINE1_COLUMN(3),'N');display_char(LINE1_COLUMN(4),':');display_char(LINE1_COLUMN(10),'V');display_char(LINE1_COLUMN(16),'A');display_char(LINE2_COLUMN(1),'O');//第二行写字符,OUT:、V、Adisplay_char(LINE2_COLUMN(2),'U');display_char(LINE2_COLUMN(3),'T');display_char(LINE2_COLUMN(4),':');display_char(LINE2_COLUMN(10),'V');display_char(LINE2_COLUMN(16),'A');}void LCD_Init(void){LCD_EN=0;//打开片选LCD_RW=0;//读写控制,1:读// 0:写 这里只写,不读LCD1602_WriteCMD(0x38);LCD1602_WriteCMD(0x0e);LCD1602_WriteCMD(0x06);//地址指针自动加一,且光标加一LCD1602_WriteCMD(0x01);LCD1602_WriteCMD(0x80);}

编写主函数,这里测量单端电压,如果需要测量差分电压的话按照上面ADS1256头文件修改一下就行了。

void main()//ADS126的PGA不是轨到轨运放,采集3.6V以内电压比较好{//如果超过,须加分压电路signedlong Adc;//QQ:2401553359,QQ群:560864628float Volts;P1M0=0X00;P1M1=0X00;//配置GPIO模式,建议用准双向或者推挽模式P3M0=0X00;P3M1=0X00;ADS1256_Init();//ADS1256 参数初始化LCD_Init();while(1)//系数自己用基准电压源校准,电赛那时改动太多了。{Adc = ADS1256ReadData( ADS1256_MUXP_AIN0|ADS1256_MUXN_AINCOM);Volts = (Adc*0.00059270)*0.; // 0.00000059263 为系数,ADC生产出后都有一定的偏差,在此校准。display_num4(LINE1_COLUMN(5),Volts);delay_ms(50);Adc = ADS1256ReadData( ADS1256_MUXP_AIN1|ADS1256_MUXN_AINCOM);Volts = (Adc*0.00059270)*0.915; // 0.00000059263 为系数,ADC生产出后都有一定的偏差,在此校准。display_num4(LINE1_COLUMN(11),Volts);delay_ms(50);Adc = ADS1256ReadData( ADS1256_MUXP_AIN2|ADS1256_MUXN_AINCOM);Volts = (Adc*0.00058136)*1.910; // 0.00000059263 为系数,ADC生产出后都有一定的偏差,在此校准。display_num4(LINE2_COLUMN(5),Volts);delay_ms(50);Adc = ADS1256ReadData( ADS1256_MUXP_AIN3|ADS1256_MUXN_AINCOM);Volts = (Adc*0.00059270)*0.6015; // 0.00000059263 为系数,ADC生产出后都有一定的偏差,在此校准。display_num4(LINE2_COLUMN(11),Volts);DelayMs(50);}}

LCD1602显示效果如下,因为是做电子设计竞赛的,模块比较多,忽略其它模块。

视频链接:/video/BV1fA41177Um

源码链接:/s/1dbJw8ggp9Lcxch8wAfIJ4Q

提取码:lm15

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。