微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 硬件电路设计 > TI模拟硬件电路设计 > 关于ADS1118的SPI通信问题以及读取数据问题

关于ADS1118的SPI通信问题以及读取数据问题

时间:10-02 整理:3721RD 点击:

亲们~大家好,我最近在使用一款模数转换芯片ADS1118,现在遇到以下问题,希望可以得到大家的帮助,小弟感激不尽~~

1.ADS1118和单片机(我用的是MSP430F149)通信要使用SPI通信协议,但我现在不清楚如何读取模数转换之后的数字量,比如说怎么使用SPI中断读取数据?仅仅只用在中断函数体中写 “Data = U0RXBUF” 吗?

2.单片机执行程序之后与ADS1118进行通信之后,我在SCLK引脚上检测到了时钟信号,与TI提供的说明书上的波形基本一样,(波形图如下)不知道正不正确,请大家帮忙看看~~

3.但检测 ADS1118 的 DOUT 引脚时却出现这样的波形,不论有没有模拟量输入都是的波形,如下图,这我就费解了...

最后我的硬件连接图如下:

 我将AIN0接正电压,AIN1接地这个连接方式有错误吗?

程序如下(我用的是默认配置,没有修改):(我使用的是IAR Embedded Workbench进行编程的)

#include <msp430x14x.h>

#define CPU_F ((double)8000000)
#define delay_us(x) __delay_cycles((long)(CPU_F*(double)x/1000000.0))
#define delay_ms(x) __delay_cycles((long)(CPU_F*(double)x/1000.0))

#define uchar unsigned char
#define uint unsigned int
#define CS_L P2OUT = 0X00
#define CS_H P2OUT = 0Xff
#define LED_ON P1OUT = 0xff
#define LED_OFF P1OUT = 0x00

char cmd[] = {0x05,0xeb,0x00,0x00},SLV_Data = 0xFF;
uint a = 0,U0TX_BYTE=1;

void SPI_WRITE()
{
uint i;
CS_L;
//while(!U0TX_BYTE);
for(i=0;i<4;i++)
{
TXBUF0 = cmd[i]; // Transmit first character
//while(!U0TX_BYTE);
//U0TX_BYTE = 0;
}
CS_H;
}
int main(void)
{
unsigned int i;

WDTCTL = WDTPW + WDTHOLD; // Stop WDT
P1OUT = 0x000; // Setup P1.0 for LED output
P1DIR |= 0x0ff;
P2DIR |= 0X0FF;
P3SEL = 0x00E; // Setup P3 for SPI mode
P3OUT = 0x020; // Setup P3.4 for Scope trigger and
P3DIR |= 0x030; // P3.5 for slave initialization
U0CTL = CHAR + SYNC + MM + SWRST; // 8-bit, SPI, Master
U0TCTL = SSEL1 + STC; // SMCLK, 3-wire
U0BR0 = 0x002; // SPICLK = SMCLK/2
U0BR1 = 0x000;
U0MCTL = 0x000;
ME1 = USPIE0; // Module enable
U0CTL &= ~SWRST; // SPI enable
IE1 |= URXIE0; // Recieve interrupt enable
_EINT(); // Enable interrupts

P3OUT &= ~0x020; // Toggle P3.5: slave reset
P3OUT |= 0x020;
i = 50000; // Delay
do (i--);
while (i != 0);
CS_L;

while (1)
{
CS_L;
//SPI_WRITE(); // Transmit first character
while ((IFG1 & UTXIFG0) == 0);
TXBUF0 = 0x05; //给ADS1118发送数据
TXBUF0 = 0x8B;
TXBUF0 = 0x00;
TXBUF0 = 0x00;
CS_H;
LPM0; // CPU off
//while(1);
}
} // End Main

#pragma vector = USART0RX_VECTOR
__interrupt void SPI0_rx (void)
{
CS_L;
P1OUT = U0RXBUF;
//P3OUT ^= 0x010; // XOR P3.4 for scope trigger
while ((IFG1 & UTXIFG0) == 0); // USART0 TX buffer ready?
//P1OUT = 0XFF;
TXBUF0 = 0x05;
TXBUF0 = 0xeb;
TXBUF0 = 0x00;
TXBUF0 = 0x00;
CS_H;
}

恳请大家提供帮助与建议,不胜感激,跪谢Orz

你好,

SPI的主设备(单片机)如果不发送数据的话,是不会有clock信号的,所以读取转换结果的时候,可以在单片机端发送0X00或0XFF,这样可以为ADS1118输出数据提供clock信号,不会改变ADS1118的配置寄存器(跟NOP1/0位有关,详见数据手册22页)。单片机端发送0X00或0XFF后,ADS1118返回的数据将会进入RXBUF,如果你的程序是采用SPI中断读取数据的话,那么在中断函数里面写“Data = U0RXBUF” 可以读到转换结果或配置寄存器的值。

数据读取的时序可以参考数据手册23页DATA RETRIEVAL章节。你可以将你写入的配置寄存器值读出,校验一下是否正确,这可以顺便确认一下通信时序是否正确。

能否将SPI的SCLK , SDO, SDI, CS这几个引脚的时序在示波器上同时抓出来?单独一个引脚的时序难于分析。

AIN0接正电压,AIN1接地这个连接方式是否合理需要根据配置寄存器里面的MUX[2:0], PGA[2:0]这几个位而定,你的正电压是给的是多少V?

首先十分感谢Martin先生的热心帮助,现在情况是这样的,我更换了主控制器,现在使用的是Launchpad msp430G2553,也换了ADS1118,SPI的SCLK , SDO, SDI, CS这几个引脚的时序如下:

                                                                   图1 SCLK时序图

                                                                    图2 SDO时序图

                                                             图3 SDI时序图

                                                                      图4 CS时序图

在抓出的这4幅图里面,我发现 SDI  的波形有些奇怪,我配置的 MUX[2:0] = 100  即 AINP = AIN0,AINN is GND;PGA[2:0] = 010  即 FS = 正负2.048V,在实际硬件连接里我 AIN0 接 +3.5V,那按此配置的话,应该从ADS1118接收到的数据是7FFFH才对啊,那为什么会出现 SDI  那样的波形?

我的程序如下:(由于使用的是TI工程师给的G2553与ADS1118的模块程序,有些不懂的地方已用红字写出,还望指教~~)

#include <msp430g2553.h>

/*
 * ======== Grace related includes ========
 */
//#include <ti/mcu/msp430/csl/CSL.h>


/*
 *  ======== Function Calls ========
 */

void uart_txc(char c);
void uart_txstr(char *c);
/* "hex2asc" Converts a 32-bit integer n into an ASCII string.

digs is the maximum number of digits to display.  Conversion is controlled
by mode, as follows:

- mode = 0: Leading zeroes are not printed.  The string may be
  less than digs digits long.
- mode = 1: Spaces are printed in place of leading zeroes.  The
  string will be digs digits long.
- mode = 2: Leading zeroes are printed.  The string will be digs
  digits long.

If the number is zero, at least one zero is printed in all modes.

This routine works by converting n to an 8-byte BCD number and calling
hex2asc.  No division by 10 is performed.
*/

int hex2asc(void *n, int digs, int mode, char *s);

void ADS_Config(void);
void ADS_Read(int data[]);
void Send_Result(int *data);
void Port_Config(void);
signed int WriteSPI(unsigned int config, int mode);
void delay(void);

#define h2a(d) ((d>9)?(d+'A'-10):(d+'0'))
#define LITTLEENDIAN 1

/*
 *  ======== main ========
 */
int main(int argc, char *argv[])
{
    int i = 0;
    CSL_init();                     // Activate Grace-generated configuration
   
    // >>>>> Fill-in user code here <<<<<

    // Initialize TC data array

    signed int data[6];

    // Port configuration
    Port_Config();

    // Set ADS1118 configuration
    ADS_Config();
    while (1)
    {
     // Read the data from both input pairs
     ADS_Read(data);


     // Transmit the data out the UART
     Send_Result(data);
        P1OUT = (data[0] >> (i))& 0x0001;
        i++;
        if(i == 16)  i = 0;
    }


    return (0);
}

void Port_Config(void)
{
 // Set P1.0, P1.3, P1.4, P2.1, P2.2, P2.4, P2.5, P2.6 and P2.7 low

 P1OUT = 0x00;
 P2OUT = 0x01 ;
}


/*
 * Initial configuration routine.  A header file could be created, but the configuration is really rather simple.
 * In this case a 16-bit value representing the register contents is set to variable temp
 */
void ADS_Config(void)
{
 int i;

 unsigned int temp;

 // Set the configuration to AIN0/AIN1, FS=+/-1.024, SS, DR=128sps, PULLUP on DOUT
 //temp = 0x78A;
        temp = 0x458A;

 // Set CS low and write configuration
 P2OUT &= ~BIT0;


 // Write the configuration
 WriteSPI(temp,0);

 // Set CS high to end transaction
 P2OUT |= BIT0;
}

 

void ADS_Read(int data[])
{
 unsigned int j, temp;

 // Set the configuration to AIN0/AIN1, FS=+/-1.024, SS, DR=128sps, PULLUP on DOUT
 //temp = 0x78A;
        temp = 0x458A;

 // Set CS low and write configuration
 P2OUT &= ~BIT0;

 // First the data is captured by writing to each device to take start a conversion for A0-A1
 WriteSPI(temp,1);

 // Set CS high to end transaction
 P2OUT |= BIT0;

/*
* Now we pause slightly before reading the data, or it is possible to either poll the DOUT/DRDY or enable an interrupt
* where the DOUT/DRDY transition from high to low triggers a read.  In this case it is kept quite simple with a delay
*/

 delay();  // May be needed depending on method

 // When we read the data we restart the conversion with new mux channel A1  (此处不明白为什么要重新选择另外一个通道开启转换,难道不能只对一个通道的电压值进行转换吗?本函数以下的语句可以去掉吗?)

 //temp = 0x378A;
        temp = 0x558A;

 // Set CS low and write configuration
 P2OUT &= ~BIT0;

 // Read the earlier conversion result and set to the new configuration
 data[0] = WriteSPI(temp,1);

 delay();  // May be needed depending on method

 // Read second channel data
 data[1]=WriteSPI(temp,0);

 // Set CS high to end transaction
 P2OUT |= BIT0;


}


signed int WriteSPI(unsigned int config, int mode)
{
 signed int msb;
 unsigned int temp;
 char dummy;

 temp = config;

 if (mode==1) temp = config | 0x8000; // if mode is set to 1, this command should initiate a conversion

/*
 * The process of communication chosen is to always send the configuration and read it back
 * this results in a four byte transaction.  The configuration is 16-bit (or 2 bytes) and is transmitted twice.
 *
 */
 while(!(UC0IFG&UCB0TXIFG));  // Make sure buffer is clear

 /*
  *  First time configuration is written
  */

 UCB0TXBUF = (temp >> 8 );  // Write MSB of Config
 while(!(UC0IFG&UCB0RXIFG));
 msb=UCB0RXBUF;     // Read MSB of Result

 while(!(UC0IFG&UCB0TXIFG));

 UCB0TXBUF= (temp & 0xff);  // Write LSB of Config
 while(!(UC0IFG&UCB0RXIFG));
 msb = (msb << 8) | UCB0RXBUF ;   //Read LSB of Result

 /*
  * Second time configuration is written, although data could be sent as NOP in either transmission, just simplified in this case
  */

 while(!(UC0IFG&UCB0TXIFG));
 UCB0TXBUF = (temp >> 8 );  // Write MSB of Config

 while(!(UC0IFG&UCB0RXIFG));
 dummy=UCB0RXBUF;    // Read MSB of Config

 /*
  * One advantage of reading the config data is that DOUT/DRDY is forced high which makes it possible to either poll the state or set an interrupt
  */
 while(!(UC0IFG&UCB0TXIFG));
 UCB0TXBUF= (temp & 0xff);  // Write LSB of Config

 while(!(UC0IFG&UCB0RXIFG));
 dummy=UCB0RXBUF;    //Read LSB of Config


 return msb;
}

 


/*
 * Following code relates to formatting the data for transmission on UART
 */

void Send_Result(int *data)
{
 unsigned int i;
 int intval = 0;
 char char_array[5];

 // Poke out data
 uart_txstr("TEMPS:");
 uart_txc('\r');
 uart_txc('\n');
 for (i=0; i<2; i++)
 {
  intval = data[i];
  hex2asc(&intval, 4, 2, char_array);
  uart_txstr(char_array);
  uart_txc('\r');
  uart_txc('\n');
 }
}

 

 

int hex2asc(void *npos, int digs, int mode, char *s)
{
 int i,zero;
 char dig;
 char *spos=s;
 char *n=(char *)npos;

 zero=1;
#if LITTLEENDIAN
 n+=(digs-1)>>1;
#else
 n+=(16-digs)>>1;
#endif
 for (i=digs-1;i>=0;--i) {
  if (i&1) {
   dig=(*(char *)n>>4)&15;
  } else {
   dig=*(char *)n&15;
#if LITTLEENDIAN
   --n;
#else
   ++n;
#endif
  }
  if (zero&&dig)
   zero=0;
  if (zero) {
   switch(mode) {
   case 1:
    *spos++=' ';
    break;
   case 2:
    *spos++='0';
    break;
   default:
    break;
   }
  } else
   *spos++=h2a(dig);
 }
 if (zero&&mode==1)
  *(spos-1)='0';
 else if (zero&&mode==0)
  *spos++='0';
 *spos=0;
 return spos-s;
}
void uart_txc(char c)
{
 while (!((UC0IFG&UCA0TXIFG)));
 UCA0TXBUF=c;

}

void uart_txstr(char *c)
{
 while (*c) uart_txc(*(c++));
}

void delay(void)
{
 unsigned int k;

 for (k = 8000; k = 0; k--) __no_operation();

}

你现在这个好使了吗?我也用的是149.好用的话能不能发一份给我。行不。邮箱1003287885@qq.com

149的好使了吗?可以发我一份吗?谢谢!540362098@qq.com

149好了吗?能发我一份吗?非常感谢!501883466@qq.com

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top