MSP432 ADS8341

 

ADS8341

https://www.tij.co.jp/jp/lit/ds/symlink/ads8341.pdf?ts=1623405262771&ref_url=https%253A%252F%252Fwww.tij.co.jp%252Fproduct%252Fjp%252FADS8341%253FkeyMatch%253DADS8341%2526tisearch%253Dsearch-everything

16ビットの4チャンネルADC。

SPIの設定

const eUSCI_SPI_MasterConfig spiMasterConfig2 =

{

        EUSCI_B_SPI_CLOCKSOURCE_SMCLK,             // SMCLK Clock Source

        12000000,                                  // SMCLK = DCO = 12000000

        1200000,                                  // SPICLK = 12000000

        EUSCI_B_SPI_MSB_FIRST,                     // MSB First

        EUSCI_B_SPI_PHASE_DATA_CAPTURED_ONFIRST_CHANGED_ON_NEXT, //up edge

        EUSCI_B_SPI_CLOCKPOLARITY_INACTIVITY_LOW, // Low polarity

        EUSCI_SPI_3PIN

        //EUSCI_SPI_4PIN_UCxSTE_ACTIVE_LOW                          // 3Wire SPI Mode

};

1200000のところは2.4Mまでいけるとデータシートには記載しているが、余裕を見て半分の1.2Mとしている。


タイミングチャートを見ると、MSP432から送りだし、ADS8341がDINの内容を読むときは、立ち上がりのエッジで、送りだすときは、立下りのタイミング・・というしろものだが、EUSCI_B_SPI_PHASE_DATA_CAPTURED_ONFIRST_CHANGED_ON_NEXTでOK。


MSP432は、まずクロックだが、

SPI_transmitData(EUSCI_B2_BASE, control_bits);

と8ビット分を送信すると、8ビット分のクロックを送る。続けて送ってはくれないので、

SPI_transmitData(EUSCI_B2_BASE, 0B00000000);

といったように何かを送信してあげないとクロックを送らない。ADS8341はスタートビットが1でないと反応しないので、0B00000000を送る=クロックを送るになる。

内部クロックモードと外部クロックモードがある。Externalでつかうが、ここではまった点は、コントロールビットを送った後に、1ビットだけ無反応なビットをはさんで16ビット分のデータが送られてくる。つまり、1ビット分だけずれるから、16ビットの最後は25ビット目になり、4バイト目にさしかかる。やり方は二つあって、24ビット分で1周期としておいて、次の設定命令を送る時に、同時に前ビットのLSBの情報が出てくるので読み取る

というのと、

32ビット分をひとまとめとして、処理する方法。読み取りの繰り返し周期がはやい時は全社でよいが、周期が遅い場合は、最後のビットは、時間的に随分前の情報という事になる。


 MAP_GPIO_setOutputLowOnPin(GPIO_PORT_SPI2_CS, GPIO_PIN_SPI2_CS);

 MAP_SPI_transmitData(EUSCI_B2_BASE, control_bits);

 Datatemp[3]=MAP_SPI_receiveData(EUSCI_B2_BASE);

 MAP_SPI_transmitData(EUSCI_B2_BASE, 0B00000000);

 Datatemp[0]=MAP_SPI_receiveData(EUSCI_B2_BASE);

 MAP_SPI_transmitData(EUSCI_B2_BASE, 0B00000000);

 Datatemp[1]=MAP_SPI_receiveData(EUSCI_B2_BASE);

 MAP_SPI_transmitData(EUSCI_B2_BASE, 0B00000000);

 Datatemp[2]=MAP_SPI_receiveData(EUSCI_B2_BASE);

 for (i=0;i<10;i++){}

 MAP_GPIO_setOutputHighOnPin(GPIO_PORT_SPI2_CS, GPIO_PIN_SPI2_CS);


上記の流れで一応読めるが問題が発生。コントロールビットを送っている間もMISOのラインからは、データが送られてくる(ゼロですが・・・)ので、格納する。

ただ、最初だけゼロを2回受け取る・・・・その後は一回で済む。ロジアナでは確認できない・・・そのため、1つ全体にずれてしまって、LSBが最初読み取るときにかえってきてしまう(前のデータ変換の最後)。その後読む、 Datatemp[0]の位置に、コントロールビットを送っている間のデータである0x00が格納されて、 Datatemp[1]の位置にMSBが格納される。このMSBは、コントロールビット終了から1ビットは無反応なので、最初は必ずゼロになる。言葉で書いてもわからんだろうからロジアナの図をみて ほしい。

このバグを解消できず、対処法として、上のように結果1つずれた形で使っている・・・一応正しい値を返してはくる。

↓はADCの入力にVrefより高い電圧をあえていれて、0xFFFFを返すようにした状態で取得したもの。

 


ADCの関数部分だけを以下に書いておく。

float ADCVread(uint8_t chan){

 uint16_t receivedData;

 static uint8_t control_bits=0;

 static uint8_t Datatemp[4];

 static uint8_t dummy;

 const float Vdacref=1.500;


//Send data  via SPI

/*contorl bit

 BIT 7:Start bit must always be HIGH.

 BIT 6:A2, 5:A1, 4:A0

 single end SGL/DIF HIGH

 A2 A1 A0 CH0 CH1 CH2 CH3

  0  0  0 +IN

  1  0  1     +IN

  0  1  0         +IN

  1  1  0             +IN


 differential  SGL/DIF LOW

 A2 A1 A0 CH0 CH1 CH2 CH3

  0  0  1 +IN -IN

  1  0  1 -IN +IN

  0  1  0         +IN -IN

  1  1  0         -IN +IN

BIT 3 never used:0

BIT 2 SGL/DIF   single end SGL/DIF HIGH,  Differential Channel Control LOW

BIT 1 PD1, 0 PD0

PD1 PD2

  0   0 Power-down between conversions

  1   0 Selects Internal Clock Mode

  0   1 never used

  1   1 Selects External Clock Mode.Power down between conversions

 */

 switch(chan) {

                   case 0: //Channel A

                       control_bits=0B10010111;

                       break;

                   case 1: //Channel B

                       control_bits=0B11010111;

                       break;

                   case 2: //Channel C

                       control_bits=0B10100111;

                       break;

                   case 3: //Channel D

                       control_bits=0B11100111;

                       break;

                   default:

                       control_bits=0B10010111;

               }

  int i;

 /* Transmitting data to slave */


 MAP_GPIO_setOutputLowOnPin(GPIO_PORT_SPI2_CS, GPIO_PIN_SPI2_CS);


 MAP_SPI_transmitData(EUSCI_B2_BASE, control_bits);

 Datatemp[3]=MAP_SPI_receiveData(EUSCI_B2_BASE);


 MAP_SPI_transmitData(EUSCI_B2_BASE, 0B00000000);

 Datatemp[0]=MAP_SPI_receiveData(EUSCI_B2_BASE);


 MAP_SPI_transmitData(EUSCI_B2_BASE, 0B00000000);

 Datatemp[1]=MAP_SPI_receiveData(EUSCI_B2_BASE);


 MAP_SPI_transmitData(EUSCI_B2_BASE, 0B00000000);

 Datatemp[2]=MAP_SPI_receiveData(EUSCI_B2_BASE);


 for (i=0;i<10;i++){}

 MAP_GPIO_setOutputHighOnPin(GPIO_PORT_SPI2_CS, GPIO_PIN_SPI2_CS);


//----1st byte----/

 Datatemp[1]=Datatemp[1] << 1; //shift 1 bit to left

//2nd byte shift 7 bit to right

 dummy=Datatemp[2] >>7;

 // new 1st byte

 Datatemp[1]=Datatemp[1] | dummy;


//----2nd byte----//

 Datatemp[2]=Datatemp[2] <<1; //shift 1 bit to left

//3nd byte shift 7 bit to right

 dummy=Datatemp[3] >>7;

//----new 2nd byt----

 Datatemp[2]=Datatemp[2] | dummy;


 receivedData=Datatemp[1] <<8 | Datatemp[2];

 return Vdacref*receivedData/65536;


//sprintf (OLED_buffer, "%x %x %x %x", Datatemp[0],Datatemp[1],Datatemp[2],Datatemp[3]);

//sprintf (OLED_buffer, "%7.5f", Vdacref*receivedData/65536);

//draw6x8Str(0, 2, OLED_buffer, 1,0);


}

ここまでのMSP432で使ったUARTでPC接続以外をまとめたファイル



コメント

このブログの人気の投稿

Attiny85とAQM0802A(LCD)のI2C接続

ILI9341 240X320 Arduino

Attiny85 FuseRest