ADS1256时序与代码这次讲清楚!真言一句话+代码足矣

在做东西的过程中,因为HX711的固有问题,选了ADS1256模块,还挺贵的,硬件方面不太懂,直接用成品模块,接上管脚和GPIO就可以用了,就编程准备驱动。

从卖家那拿到的代码,还有网上下的代码,对比芯片手册看了1天和运行,硬是没有跑出来,卖家又骗人卖前说有技术支持卖了后问他们时他们说你自己看,真是气死人了。

国外的代码注释还有些时序上的说明,但很不全,有些代码也找不到了,所以也跑不出来,对照芯片手册很多理解不清,只好憋自己下力气琢磨了。

下面就是琢磨的结果,真传一句话,把从卖家给的资料案例代码进行了改造(原代码时序嵌在函数里面,外部根本没法控制,所以出问题,且没有注释上说明,没法运行),修改后,加了时序注释,非常非常清楚。

真传一句话,假传万言书。

正文:

环境:

开发板:树莓派4B 1.5GHz CPU

IDE:QT Creator 5.0

需要用到wiringPi库的delayMicroseconds函数;QMutex(看波形发现有的波形会被拉长,需要加锁)。

1. 芯片上时序要求

2. 代码  (时序在注释中了)

初始化直接用管脚 RST ,不用软方法。其余读写代码:

#include "oldADS1256.h"
#include "wiringPi.h"
#include <QMutex>


int SCLK = 26; // 串行时钟输入
int DIN  = 27;  // 数据转换结束标志, 低电平有效
int DOUT = 2; // 数据转换结束标志, 低电平有效
int DRDY = 3; // 数据转换结束标志, 低电平有效
int CS   = 24;   // 片选信号, 低电平有效
int RST  = 21;  // 复位信号, 低电平有效

//
void  delaySomeNs(int nCnt)
{
    for(int i = 0; i < nCnt; i++)
    {

    }

    return;
}


void ADS1256_Send8Bit(unsigned char date)
{
	unsigned char i;

	for(i=0;i<8;i++)
	{
        if(date&0x80)          //判断数据是否为高电平,高电平输出为1
        {
            DIN_H;
        }
        else
        {
            DIN_L;
        }
		SCLK_H;               //时钟拉高,为产生下降沿做准备
        delayMicroseconds(1); // t2h, t5
		date<<=1;             //时钟拉低,产生下降沿,数据传输完成
		SCLK_L;
        if(i < 7 )
        {
            delayMicroseconds(1); // t2l, except the last one
        }
	}
}


unsigned char ADS1256_Recive8Bit()
{
	unsigned char i;
	unsigned char date=0;
	for(i=0;i<8;i++)
	{
		SCLK_H;                   //时钟拉高,为产生下降沿做准备
        delayMicroseconds(1);  // t2h, t8
        if(digitalRead(DOUT)==HIGH) //
        {
            date++;                 //读取一个数据
        }
        SCLK_L;
        date = date<<1;
        if(i < 7)
        {
            delayMicroseconds(1); // t2l, except the last one
        }
	}
	return(date);
}


void ADS1256_WriteReg(unsigned char Reg_ID,unsigned char Reg_Date)
{
	ADS1256_Send8Bit(CMD_WREG|Reg_ID);          //送写寄存器命令
    delayMicroseconds(1);  // t2l
	ADS1256_Send8Bit(0X00);                     //只写一个寄存器
    delayMicroseconds(1);  // t2l
	ADS1256_Send8Bit(Reg_Date);                 //寄存器要写的内容
}


void ADS1256_WriteCmd(unsigned char cmd)          //写命令指令
{
	ADS1256_Send8Bit(cmd);
}


//void ADS1256_CfgADC(unsigned char gain,unsigned char drate)   //初始化设置,设置增益以及转换速率
//{
//	ADS1256_WriteCmd(CMD_RESET);                //写复位指令
//    //while(digitalRead(DRDY));
//    ADS1256_WriteReg(REG_STATUS,0XF4);          //写状态,数据传输默认高位在前,启动矫正,禁止使用缓冲
//	ADS1256_WriteCmd(CMD_SELFCAL);              //自校准

//    delayMicroseconds(20);
//	{
//		unsigned char buf[4];
//		/* 状态寄存器定义
//			Bits 7-4 ID3, ID2, ID1, ID0  Factory Programmed Identification Bits (Read Only)

//			Bit 3 ORDER: Data Output Bit Order
//				0 = Most Significant Bit First (default)
//				1 = Least Significant Bit First
//			Input data  is always shifted in most significant byte and bit first. Output data is always shifted out most significant
//			byte first. The ORDER bit only controls the bit order of the output data within the byte.

//			Bit 2 ACAL : Auto-Calibration
//				0 = Auto-Calibration Disabled (default)
//				1 = Auto-Calibration Enabled
//			When Auto-Calibration is enabled, self-calibration begins at the completion of the WREG command that changes
//			the PGA (bits 0-2 of ADCON register), DR (bits 7-0 in the DRATE register) or BUFEN (bit 1 in the STATUS register)
//			values.

//			Bit 1 BUFEN: Analog Input Buffer Enable
//				0 = Buffer Disabled (default)
//				1 = Buffer Enabled

//			Bit 0 DRDY :  Data Ready (Read Only)
//				This bit duplicates the state of the DRDY pin.

//			ACAL=1使能自校准功能。当 PGA,BUFEEN, DRATE改变时会启动自校准
//		*/
//        buf[0] = 0x04;//(0 << 3) | (1 << 2) | (0 << 1);
		
//		/* 高四位0表示AINP接 AIN0,  低四位8表示 AINN 固定接 AINCOM */
//        buf[1] = 0x01;//0x08;                      //通道设置选择
		
//		/*	ADCON: A/D Control Register (Address 02h)
//			Bit 7 Reserved, always 0 (Read Only)
//			Bits 6-5 CLK1, CLK0 : D0/CLKOUT Clock Out Rate Setting
//				00 = Clock Out OFF
//				01 = Clock Out Frequency = fCLKIN (default)
//				10 = Clock Out Frequency = fCLKIN/2
//				11 = Clock Out Frequency = fCLKIN/4
//				When not using CLKOUT, it is recommended that it be turned off. These bits can only be reset using the RESET pin.

//			Bits 4-2 SDCS1, SCDS0: Sensor Detect Current Sources
//				00 = Sensor Detect OFF (default)
//				01 = Sensor Detect Current = 0.5 μ A
//				10 = Sensor Detect Current = 2 μ A
//				11 = Sensor Detect Current = 10μ A
//				The Sensor Detect Current Sources can be activated to verify  the integrity of an external sensor supplying a signal to the
//				ADS1255/6. A shorted sensor produces a very small signal while an open-circuit sensor produces a very large signal.

//			Bits 2-0 PGA2, PGA1, PGA0: Programmable Gain Amplifier Setting
//				000 = 1 (default)
//				001 = 2
//				010 = 4
//				011 = 8
//				100 = 16
//				101 = 32
//				110 = 64
//				111 = 64
//		*/
//        buf[2] = gain;//(0 << 5) | (0 << 3) | (gain << 0);
		
//		buf[3] = drate;	// DRATE_10SPS;	/* 选择数据输出速率 */
//		CS_L;
//        delayMicroseconds(2);
//		ADS1256_Send8Bit(CMD_WREG|0);          //写寄存器
//        ADS1256_Send8Bit(0x03);                //连续写入4个数据
//		ADS1256_Send8Bit(buf[0]);              //设置状态寄存器
//		ADS1256_Send8Bit(buf[1]);              //设置输入通道参数
//		ADS1256_Send8Bit(buf[2]);              //设置ADCON控制寄存器,增益
//		ADS1256_Send8Bit(buf[3]);	             //设置数据速率
//		CS_H;
//        delayMicroseconds(2);
//	}
//    delayMicroseconds(50);
//}

// 20241212, 此为读取通道(差分或单端)的函数。 在此之前,用RESET管脚发个LOW电平去RESET芯片,持续10ms,所有配置用默认的即可;
// 30ksps其实很好,可以快速的取得DRDY,响应还快,不需要调整配置,默认即可;再定时调用此函数读数即可。
// 全部函数都按时序调整正确(见delayMicroseconds函数的表达和后面的注释)并运行取数,波形很好;
// 环境:树莓派4B 1.5GHz(要用cpufrequence库来确定主频)还有wiringPi库的delayMicoseconds基本能准确延时us
long ADS1256_GetAdc(unsigned char channel)
{
    long ret;
    ret = 0;
    while(digitalRead(DRDY));

    QMutex mutex;


    mutex.lock();
    CS_L;
    delayMicroseconds(1);  // t3

	ADS1256_WriteReg(REG_MUX,channel);       // 写入读取的通道
    delayMicroseconds(2);          // t11, 4 tclkin = 0.52us,  2us ensure
    ADS1256_WriteCmd(CMD_SYNC);              //同步A/D转换命令
    delayMicroseconds(5);          // t11,24 tclkin = 3.13us,  5us ensue
    ADS1256_WriteCmd(CMD_WAKEUP);            //完成SYNC并退出待机模式

    delayMicroseconds(2); // t10, 8 tclkin = 1.04us
    CS_H;
    mutex.unlock();

    while(digitalRead(DRDY));
    mutex.lock();
    CS_L;                                    //片选拉低
    delayMicroseconds(1);   // t3
    ADS1256_Send8Bit(CMD_RDATA);             //读取数据命令
	
    delayMicroseconds(8); // t6, 7.68M freq, 0.13us,at least 6.5us, use 8us to ensure
	 
	//连续接收3个数据,高字节在前
    ret = ((long)ADS1256_Recive8Bit() << 16);
    delayMicroseconds(1);  // t2l
    ret +=( (long)ADS1256_Recive8Bit() << 8);
    delayMicroseconds(1);  // t2l
    ret += ADS1256_Recive8Bit() ;

    delaySomeNs(26);                // t9~t10, expect to delay 0.2us
    delayMicroseconds(1);       // t9~t10, 8--10 tclkin, 1.04~1.3us, choose 1.2us
	CS_H;
    mutex.unlock();

//    if(ret & 0x800000)          //
//    {
//        ret |= 0xFFFF000000;
//    }
 		
    return ret;
}

//-----------------------------------------------------------------------------
// End Of File
//-----------------------------------------------------------------------------
#ifndef __ADS1256_H_
#define	__ADS1256_H_


// 定义命令,可见数据手册P34
#define CMD_WAKEUP   0x00  // Completes SYNC and Exits Standby Mode 0000  0000 (00h)		完成SYNC并退出待机状态
#define CMD_RDATA    0x01  // Read Data 0000  0001 (01h)		读取数据
#define CMD_RDATAC   0x03  // Read Data Continuously 0000   0011 (03h)		连续读取数据
#define CMD_SDATAC   0x0f  // Stop Read Data Continuously 0000   1111 (0Fh)		停止连续读取数据
#define CMD_RREG     0x10  // Read from REG rrr 0001 rrrr (1xh)		从REG读取
#define CMD_WREG     0x50	 // Write to REG rrr 0101 rrrr (5xh)			写到REG
#define CMD_SELFCAL  0xf0  	// Offset and Gain Self-Calibration 1111    0000 (F0h)		偏移和增益自校准
#define CMD_SELFOCAL 0xf1 // Offset Self-Calibration 1111    0001 (F1h)		偏移自校准
#define CMD_SELFGCAL 0xf2  	// Gain Self-Calibration 1111    0010 (F2h)			增益自校准
#define CMD_SYSOCAL  0xf3 	// System Offset Calibration 1111   0011 (F3h)		系统偏移校准
#define CMD_SYSGCAL  0xf4 	// System Gain Calibration 1111    0100 (F4h)			系统增益校准
#define CMD_SYNC     0xfc 	// Synchronize the A/D Conversion 1111   1100 (FCh)		同步A/D转换
#define CMD_STANDBY  0xfd 	// Begin Standby Mode 1111   1101 (FDh)		开始待机模式
#define CMD_RESET    0xfe  	// Reset to Power-Up Values 1111   1110 (FEh)		重置为开机值
 
// 定义ADS1256的内部寄存器,可见数据手册P30
#define REG_STATUS       0x00   // x1H		状态寄存器
#define REG_MUX          0x01   // 01H		输入多路复用器控制寄存器
#define REG_ADCON        0x02   // 20H		A/D控制寄存器
#define REG_DRATE        0x03   // F0H		A/D数据速率
#define REG_IO           0x04   // E0H		GPIO控制寄存器
#define REG_OFC0         0x05   // xxH		偏移校准字节0,最低有效字节
#define REG_OFC1         0x06   // xxH		偏移校准字节1
#define REG_OFC2         0x07   // xxH		偏移校准字节2,最高有效字节
#define REG_FSC0         0x08   // xxH		满量程校准字节0,最低有效字节
#define REG_FSC1         0x09   // xxH		满量程校准字节1
#define REG_FSC2         0x0A   // xxH		满量程校准字节2,最高有效字节
 
 
// 定义多路复用代号
#define MUXP_AIN0   0x00 
#define MUXP_AIN1   0x10 
#define MUXP_AIN2   0x20 
#define MUXP_AIN3   0x30 
#define MUXP_AIN4   0x40 
#define MUXP_AIN5   0x50 
#define MUXP_AIN6   0x60 
#define MUXP_AIN7   0x70 
#define MUXP_AINCOM 0x80 
 
#define MUXN_AIN0   0x00 
#define MUXN_AIN1   0x01 
#define MUXN_AIN2   0x02 
#define MUXN_AIN3   0x03 
#define MUXN_AIN4   0x04 
#define MUXN_AIN5   0x05 
#define MUXN_AIN6   0x06 
#define MUXN_AIN7   0x07 
#define MUXN_AINCOM 0x08   
 
 
// 定义增益代号
#define PGA_1            0x00
#define PGA_2            0x01
#define PGA_4            0x02
#define PGA_8            0x03
#define PGA_16           0x04
#define PGA_32           0x05
#define PGA_64           0x06
//#define ADS1256_GAIN_64     0x07 
 
 
//定义转换速率代号
#define DATARATE_30K         0xF0
#define DATARATE_15K         0xE0
#define DATARATE_7_5K        0xD0
#define DATARATE_3_7_5K      0xC0
#define DATARATE_2K          0xB0
#define DATARATE_1K          0xA0
#define DATARATE_500         0x92
#define DATARATE_100         0x82
#define DATARATE_60        	 0x72
#define DATARATE_50        	 0x63
#define DATARATE_30        	 0x53
#define DATARATE_25        	 0x43
#define DATARATE_15        	 0x33
#define DATARATE_10        	 0x23
#define DATARATE_5        	 0x13
#define DATARATE_2_5     			0x02


//-----------------------------------------------------------------
// I/O口定义
//-----------------------------------------------------------------
extern int SCLK; // 串行时钟输入
extern int DIN;  // 数据转换结束标志, 低电平有效
extern int DOUT; // 数据转换结束标志, 低电平有效
extern int DRDY; // 数据转换结束标志, 低电平有效
extern int CS;   // 片选信号, 低电平有效
extern int RST;  // 复位信号, 低电平有效

//sbit SCLK=P1^0;							// 串行时钟输入
//sbit DIN=P1^1;							// 数据转换结束标志, 低电平有效
//sbit DOUT=P1^2;							// 数据转换结束标志, 低电平有效
//sbit DRDY=P1^3;							// 数据转换结束标志, 低电平有效
//sbit CS=P1^4;								// 片选信号, 低电平有效
//sbit RST=P1^5;							// 复位信号, 低电平有效


#define RST_L  (digitalWrite(RST,LOW))
#define RST_H  (digitalWrite(RST,HIGH))
#define CS_L  (digitalWrite(CS,LOW))
#define CS_H  (digitalWrite(CS,HIGH))
#define DRDY_L  (digitalWrite(DRDY,LOW))
#define DRDY_H  (digitalWrite(DRDY,HIGH))
#define DOUT_L  (digitalWrite(DOUT,LOW))
#define DOUT_H  (digitalWrite(DOUT,HIGH))
#define DIN_L  (digitalWrite(DIN,LOW))
#define DIN_H  (digitalWrite(DIN,HIGH))
#define SCLK_L  (digitalWrite(SCLK,LOW))
#define SCLK_H  (digitalWrite(SCLK,HIGH))


//-----------------------------------------------------------------
// 外部函数声明
//-----------------------------------------------------------------
extern void ADS1256_Send8Bit(unsigned char date);
extern unsigned char ADS1256_Recive8Bit(void);
extern void ADS1256_WriteReg(unsigned char Reg_ID,unsigned char Reg_Date);
extern void ADS1256_WriteCmd(unsigned char cmd);
// extern signed long ADS1256_ReadData(unsigned char channel);
// extern void ADS1256_Init(void);
//extern void ADS1256_CfgADC(unsigned char gain,unsigned char drate);
extern long ADS1256_GetAdc(unsigned char channel);
extern void  delayNs(int nCnt);

// extern unsigned char ADS1256_ReadChipID(void);
// extern void ADS1256_SetChannal(unsigned char ch);
// extern void ADS1256_SetDiffChannal(unsigned char ch);
// extern int ADS1256_ReadData(void);
// extern int ADS1256_ReadAdc(unsigned char ch);
// extern unsigned char ADS1256_ReadReg(unsigned char Reg_ID);
// extern void ADS1256_WaitDRDY(void);


// extern void ADS1256_StartScan(unsigned char ucScanMode);
// extern void ADS1256_StartScan_1(void);
// extern void ADS1256_StopScan(void);
// extern int ADS1256_GetAdc(unsigned char ch);
// extern void ADS1256_ISR(void);
// extern void ADS1256_CfgADC(unsigned char gain, unsigned char drate);
// extern void ADS1256_ResetHard(void);



// signed long ADS1256ReadData(unsigned char channel);
// void ADS1256_Init(void);   //初始化ADS1256
// void Init_ADS1256_GPIO(void); //

#endif

要点:

1. 时序不由函数内部控制,函数内部如sendbit只保证这段时序,整体时序由外部调用的来按时序要求进行控制;将SCLK的时序控制了,上升沿到最后一个下降沿截止满足要求,后续相邻的时延由外部调用函数按时序控制;

2. t9和t10,有点矛盾,8--10个tclkin,不是很好控制,用波形凑吧。

3. tclkin是ADS1256上用的1/晶振频率,7.68M,所以tclkin=0.13us。 tdata是采样速率,这个时间比较长,一般达不到。

实测数据能很轻松拿到,注意时序就没啥问题,其余的内容参照寄存器、命令很简单了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值