各位好
1.我在调试ADS1241芯片程序,现在,配置完后,它默认的采集单通道是AIN0.即Multiplexer Control Register是0000 1000,然后将采集结果发送给上位机观察采集数据,经计算采集回来的数据与我给的信号基本相同。
有问题还是其他问题,谢谢!如果需要查看全部程序请通知我,我可以提供。POL硬件拉高*/
main(void)
{
uchar chan=0,n=0;
uchar i;
uchar ACRVal;
// 复位ADS1241
ADS1241SendResetCommand();
// 设置增益1
ADS1241SetGain(0);
//暂时设置一个通道AIN1
ADS1241SetChannel(0x10 | ADS1241_MUXN_AINCOM);//这里如果配置为AIN0,采集数据正常,但改成AIN1就不对。
//选择设置寄存器地址,写入数据
//单极性、采样频率19200Hz、输出数据高位在前、满幅输入为±Vref、数据输出速率7.5Hz
ACRVal = 0x41;
ADS1241WriteRegister(ADS1241_ACR_REGISTER, 1, &ACRVal);
CS=0;
ADS1241SendByte(ADS1241_CMD_SELFCAL);
CS=1;
for(i=0; i<4; i++)
while(DRDY);
{
AD_result=ADS1241ReadData();
/*整理将AD采集结果“AD_result”发给上位机查看结果*/
CS=0;
ADS1241SendByte(ADS1241_CMD_SELFCAL);
CS=1;
for (i=0; i<4; i++)
while (DRDY);
}
}
void ADS1241SendByte(uchar SPI_data)
{
int i;
CS=0;
for (i=0; i<8; i++)
{
if (SPI_data & 0x80)
SDI=1;
else
SDI=0; SCLK=1;
//延迟一点时间
_nop_(); //延迟
// 时钟管脚输出低电平
SCLK = 0;
//延迟一点时间
_nop_(); //延迟
SPI_data <<= 1; }
CS=1;
}
**********
*函数原型: uchar ADS1241ReceiveByte(void)
*功能 : 从spi总线上接受8位数据信号,并将接收到的数据作为一个字节返回
*****************************************************************************
*********/
uchar ADS1241ReceiveByte(void)
{
uchar i;
uchar Result=0;
SCLK = 1;
for (i=0; i<8; i++)
{
SCLK=0;
if(SDO==0)
Result=Result << 1;
else
{
Result=Result<<1;
Result +=1;
}
SCLK=1;
}
return(Result);
}
void ADS1241WriteRegister(uchar StartAddress, uchar NumRegs, uchar * pData)
{
uchar i;
CS=0; // send the command byte
ADS1241SendByte(ADS1241_CMD_WREG | (StartAddress & 0x0f)); // send the command argument
ADS1241SendByte(NumRegs-1); delayus(10);
// send the data bytes
for (i=0; i< NumRegs; i++)
{
ADS1241SendByte(*pData++);
}
CS=1;
}
int ADS1241SendResetCommand(void)
{
uchar i;
ADS1241SendByte(ADS1241_CMD_RESET);//发送复位命令
//延迟一点时间
for(i = 50;i > 0;i–) ;
}
void ADS1241SetGain(uchar gain)
{//选择放大倍数。 0~7
uchar Temp;
Temp=gain;
ADS1241WriteRegister(ADS1241_SETUP_REGISTER, 0x01, &Temp);
}
{
uchar nTemp;
nTemp=MuxCode;
ADS1241WriteRegister(ADS1241_MUX_REGISTER, 0x01, &nTemp);
}
{
int j;
lint Data;
//CS=0;
// 发送命令字节
ADS1241SendByte(ADS1241_CMD_RDATAC);
//ADS1241SendByte(ADS1241_CMD_RDATA);
//延迟一点时间
for(j = 50;j > 0;j–);
CS=0;
// 得到转换结果
Data = ADS1241ReceiveByte();
Data = (Data << 8) | ADS1241ReceiveByte();
Data = (Data << 8) | ADS1241ReceiveByte();
CS=1;
return Data;
}
fandong meng:
自己顶一下,等待大家的帮助
Johnsin Tao:
回复 fandong meng:
Hi
建议你先配置寄存器,然后在读这些配置的寄存器,看数据是否有写进去?
ADS1241,默认的AIN0/AIN1的差分输入通道,所以就算你不写通道,转换出来的也是AIN0/AIN1的数据,而当你写其他通道的时候,可能数据没有被写入。
(建议确认一下相关时序,和上述读寄存器,看数据是否有被写进去)
fandong meng:
回复 Johnsin Tao:
你好,Johnsin
我采用的是AIN0~AIN5,单极性采集,然后AINCM为公共模拟输入端(接地),BUFEN接地,POL通过10K电阻上拉到5V;
我也看了ADS1241默认的是采集AIN0通道,这点应该符合我现在第一通道能采集到数据,请麻烦帮忙确认一下以下三个子程序分别是想AD1241写字节、读字节和写寄存器函数,看是否正确,时序有没有问题。谢谢!
void ADS1241SendByte(uchar SPI_data){ int i; CS=0; for (i=0; i<8; i++) { if (SPI_data & 0x80) SDI=1; else SDI=0; SCLK=1; //延迟一点时间 _nop_(); //延迟 // 时钟管脚输出低电平 SCLK = 0; //延迟一点时间 _nop_(); //延迟 SPI_data <<= 1; } CS=1;}
/***************************************************************************************函数原型: uchar ADS1241ReceiveByte(void)*功能 : 从spi总线上接受8位数据信号,并将接收到的数据作为一个字节返回**************************************************************************************/uchar ADS1241ReceiveByte(void){ uchar i; uchar Result=0; SCLK = 1; for (i=0; i<8; i++) { SCLK=0; if(SDO==0) Result=Result << 1; else { Result=Result<<1; Result +=1; } SCLK=1; } return(Result);}void ADS1241WriteRegister(uchar StartAddress, uchar NumRegs, uchar * pData){ uchar i; CS=0; // send the command byte ADS1241SendByte(ADS1241_CMD_WREG | (StartAddress & 0x0f)); // send the command argument ADS1241SendByte(NumRegs-1); delayus(10); // send the data bytes for (i=0; i< NumRegs; i++) { ADS1241SendByte(*pData++); } CS=1;}
Johnsin Tao:
回复 fandong meng:
Hi
判定时序最好的方法是用示波器直接测试, 然后与datasheet定义的时序做比较(包括那些时间定义).
fandong meng:
回复 Johnsin Tao:
Hi
Johnsin Tao
经过查看手册的时序图,我现在已经能更改ADS1241的采集通道了(主要修改了SendByte函数和ReceiveByte函数、以及SCLK后的延时时间),但是现在有个问题,我设置采集单通道AIN4(任一),外部给定恒流源4~20mA,然后数据输出高16位是稳定的,值也是正确的,但会偶尔出现FFFFFF 而我测试AD芯片该引脚电压在4mA时为0.4003V左右(采样电阻为1‰的100R电阻);
另外还有个问题,在时序图后面的t11,在写SELFCAL命令后,要有最小4个DRDY PERIODS的时间延时,我用的AD外部晶振是2.4576MHz,请问这个时间是多少呢?如何计算,我在手册中没找到。
谢谢!
fandong meng:
回复 Johnsin Tao:
另外,我在主程序进来之后,将CS直接置低电平,在其他程序中,不在对其操作。
在
应用报告ZHCA007–2004 年10 月连接ADS1241 与MSP430 处理器 文件中,有提到:
// Set the gain and multiplexerADS1240SetGain(ADS1240_GAIN_1);ADS1240SetChannel(chan | ADS1240_MUXN_AINCOM);// data rate = 15Hz (4.91MHz, SPEED = 1)ACRVal = SPEED_BIT;ADS1240WriteRegister(ADS1240_ACR_REGISTER, 1, &ACRVal);// do an internal self calADS1240AssertCS(1);ADS1240SendByte(ADS1240_CMD_SELFCAL);ADS1240AssertCS(0);for (i=0; i<4; i++)ADS1240WaitForDataReady(0);
而我对ACR寄存器设置的0X41,
还有这个延时for (i=0; i<4; i++)是如何计算的?我的单片机主时钟是采用的11.0595M晶振,1T模式。
Johnsin Tao:
回复 fandong meng:
Hi
确认一下出现FFFF时的转换时序是否正常(单片机给到ADC的控制时序)?,以及这个过程中供电是否稳定?
t11的定义,可以结合t1的定义来计算。
fandong meng:
回复 Johnsin Tao:
Hi Johnsin Tao
这个过程的供电是稳定的,我测试过。
时序是指单片机发给ADC的SCLK时序吗?
我用的fosc是2.4576MHz,那么主时钟周期tosc=1/fosc=400ns,但DRDY Periods是怎么算的呢?
Johnsin Tao:
回复 fandong meng:
Hi
是的,指的是单片机与ADC所有接口的控制时序。
按照datasheet: http://www.ti.com.cn/cn/lit/ds/symlink/ads1118.pdf 第十四页,
It is reset HIGH when a read operation from the data register is complete.
DRDY goes LOW when a new data word is available in the DOR register.
我认为这个时间没有办法计算,DRDY只是作为ADC输出的标示符,这个时间是ADC内部采样转换并且将数据传到DOR的时间。
fandong meng:
回复 Johnsin Tao:
Hi Johnsin Tao
我测试了一下各个引脚的时序图,在测试DRDY 和DOUT时,在DRDY为低电平期间,发现DOUT有时为高电平、有时为低电平,我分析应该是正常数据;
但有时DOUT却是一直是高电平(参见附件图4),我分析有可能输出的是FFFFFFh。但是我没办法将我在上位机上看到的数据与示波器中看到的波形同步
我将各波形图抓了下来,请参见附件。
现在网路不太好,附件上传不了,晚一会儿我会上传上来,还烦请分析一下。
多谢!