MSP432 MAX5144 via SPI
ArduinoやSTM32ですでに以前テストはしている。その時と同じくISL21080CIH315Z-TK(基準電圧1.5V)を用意して基準電圧として利用した。
ここまでで、ADCやSSD1306のOLEDやスイッチのテストをしてきているので、OLEDに設定電圧にちゃんと出力されているかを計測して表示するまでの記録。
SPIの設定→ピンのアサイン→SPIモードのEnable→実際の送信という流れ。
* MAX 5144 DAC
* ------------------
* |1 REF GND 10 |
* 2,3 and 4 |2 CS VCC 9 |
* pull up w |3 SCLK RFB 8 |
* 1k |4 DIN INV 7 |
* Vcc--10k-- |5 CLR OUT 6 |
CLRの端子を10KでVccと接続。ここを接続しないで実験していて半日以上無駄にした・・・。
【SPIの設定】
/* SPI Master Configuration Parameter */
const eUSCI_SPI_MasterConfig spiMasterConfig =
{
EUSCI_B_SPI_CLOCKSOURCE_SMC
LK, // SMCLK Clock Source
32000, // SMCLK = DCO = 3MHZ 3000000
32000, // SPICLK = 500khz 500000
EUSCI_B_SPI_MSB_FIRST, // MSB First
//EUSCI_B_SPI_PHASE_DATA_CHANGED_ONFIRST_CAPTURED_ON_NEXT,
EUSCI_B_SPI_PHASE_DATA_CAPTURED_ONFIRST_CHANGED_ON_NEXT,
//EUSCI_B_SPI_CLOCKPOLARITY_INACTIVITY_HIGH, // High polarity
EUSCI_B_SPI_CLOCKPOLARITY_INACTIVITY_LOW, // Low polarity
EUSCI_B_SPI_3PIN // 3Wire SPI Mode
};
→めちゃくちゃハマったところ。以前も経験があったのだが、SPI速度が問題。特にMSP432のボードは、ブレッドボードまでジャンパーワイヤで接続する事もあり、最初MAX5144の出力電圧が、起動時の値から変化しなかった。配線が間違っているのか・・・どこかプログラムが間違ったのか・・と膨大な時間を費やしたが、配線は間違いなく、どこかの配線がノイズを受ける。ワイヤーを手で触ると設定した値になったり、USBケーブルを触ると動いたりと・・・よってまず低速でテストは開始する事を強く進める。
CLRに5Vを与えるのを忘れていたからで、与えてからは12MHzとかで余裕で動く。
本題。” EUSCI_B”って何? Bって言うだけあって_Aってのもむろんある。https://www.ti.com/lit/ug/slau424f/slau424f.pdf?ts=1622269247786&ref_url=https%253A%252F%252Fwww.google.com%252F
見て。
eUSCI_A モジュールに4つまで使えて、①自動のボーレート検出機能をもつUART、②IrDA ③SPI (16 Mbpsまで)に割り当て可能。eUSCI_B モジュールも4つまであり、こちらは①I2C と②SPI (16 Mbpsまで)に使うことができる。
EUSCI_B_SPI_PHASE_DATA_CAPTURED_ONFIRST_CHANGED_ON_NEXT:
MAX5144のタイミングダイヤログを見るとSCLKが下から上に変化するエッジのタイミングにDINの状態を読んで信号を読み取る仕様。MSP432のDriverLib、このあたりのネーミングがいけてない。
EUSCI_B_SPI_PHASE_DATA_CAPTURED_ONFIRST_CHANGED_ON_NEXT
この訳をどう解釈するか、phase dataで切れて、capturedは修飾語でphase dataにかかる、on first changed は最初に変化する
最初に変化する点で補足あれた位相データと解釈するのか?あああ~~~~
”最初に変化するところで、キャプチャーして次のところは変化するだけ”と解釈してみた。
”クロックの最初の立ち上がりでキャプチャーしますよ”。
一応このタイミングダイヤログの場合は、
EUSCI_B_SPI_PHASE_DATA_CAPTURED_ONFIRST_CHANGED_ON_NEXT
EUSCI_B_SPI_CLOCKPOLARITY_INACTIVITY_LOW
の組み合わせが正解。EUSCI_B_SPI_PHASE_DATA_CAPTURED_ONFIRST_CHANGED_ON_NEXTは
CHOL=1を意味する。
【ピンアサイン】
/* Selecting P1.5 P1.6 and P1.7 in SPI mode */
MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1,
GPIO_PIN5 | GPIO_PIN6 | GPIO_PIN7, GPIO_PRIMARY_MODULE_FUNCTION);
/* Configuring SPI in 3wire master mode */
MAP_SPI_initMaster(EUSCI_B0_BASE, &spiMasterConfig);
/* Selecting P3.0 as SPI CS pin */
MAP_GPIO_setAsOutputPin(GPIO_PORT_P3, GPIO_PIN0);
MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P3, GPIO_PIN0);
/* Enable SPI module */
MAP_SPI_enableModule(EUSCI_B0_BASE);
ここでは、 P3.0 をCSピンをして使った。それ以外の部分は、Bを使う限りは同じ設定になるんで、そのまま。
【実際の書き込み】
void DACVset(float Vsetadc){
static uint16_t DataInt=0;
static uint8_t Datatemp1=0;
static uint8_t Datatemp2=0;
const float Vdacref=1.500;
//Send data to DAC MAX5144 via SPI
DataInt=(uint16_t)(Vsetadc/Vdacref*16384);
DataInt=DataInt <<2;
Datatemp1=DataInt >> 8;
Datatemp2=DataInt & 0xFF;
/* Transmitting data to slave */
MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P3, GPIO_PIN0);
/* Polling to see if the TX buffer is ready */
//while (!(SPI_getInterruptStatus(EUSCI_B0_BASE,EUSCI_B_SPI_TRANSMIT_INTERRUPT)));
MAP_SPI_transmitData(EUSCI_B0_BASE, Datatemp1);
/* Polling to see if the TX buffer is ready */
//while (!(SPI_getInterruptStatus(EUSCI_B0_BASE,EUSCI_B_SPI_TRANSMIT_INTERRUPT)));
MAP_SPI_transmitData(EUSCI_B0_BASE, Datatemp2);
MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P3, GPIO_PIN0);
これも、ArduinoやSTM32の時と同じ、CSピンを下げておいて、送付する。
送付前に、書き込み可能かwhile (!(SPI_getInterruptStatus(EUSCI_B0_BASE,EUSCI_B_SPI_TRANSMIT_INTERRUPT)));
で見ているが、コメントアウトしていても動いている。
8ビットづつの送付になるので、2ビットシフトする操作をしてから上位と下位バイトに分けて2回送付。
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* --/COPYRIGHT--*/
/******************************************************************************
* MSP432 Empty Project
*
* Description: An empty project that uses DriverLib
*
* MSP432P401
* ------------------
* /|\| |
* | | |
* --|RST |
* | MOSIP/1.6 |------->
* | P1.7 |MISO
* CLK |P1.5 CLK |
* | CS/P3.0|------->
* | SDA/P6.4|------->
// | SCK/P6.5|------->
* | |
*
* Author:
*******************************************************************************/
/* DriverLib Includes */
#include <ti/devices/msp432p4xx/driverlib/driverlib.h>
/* Standard Includes */
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include "ssd1306_lib.h"
char printNum[80];
static uint16_t resultsBuffer[5];
void DACVset(float Vsetadc);
/* SPI Master Configuration Parameter */
const eUSCI_SPI_MasterConfig spiMasterConfig =
{
EUSCI_B_SPI_CLOCKSOURCE_SMCLK, // SMCLK Clock Source
32000, // SMCLK = DCO = 3MHZ 3000000
32000, // SPICLK = 500khz 500000
EUSCI_B_SPI_MSB_FIRST, // MSB First
//EUSCI_B_SPI_PHASE_DATA_CHANGED_ONFIRST_CAPTURED_ON_NEXT,
EUSCI_B_SPI_PHASE_DATA_CAPTURED_ONFIRST_CHANGED_ON_NEXT,
//EUSCI_B_SPI_CLOCKPOLARITY_INACTIVITY_HIGH, // High polarity
EUSCI_B_SPI_CLOCKPOLARITY_INACTIVITY_LOW, // Low polarity
EUSCI_B_SPI_3PIN // 3Wire SPI Mode
};
/* Statics */
//static volatile uint8_t RXData = 0;
//static uint8_t TXData = 0;
//DAC variables
static float Vset=1.4000;
uint16_t j;
int main(void)
{
/* Stop Watchdog */
MAP_WDT_A_holdTimer();
/**************************************************************************/
/*OLED SSD1306 via I2C*/
/**************************************************************************/
/* Initialization of SSD1306 OLED*/
ssd1306Init();
fillDisplay (0x00);
/**************************************************************************/
/*ADC*/
/**************************************************************************/
/* Setting reference voltage to 2.5 and enabling reference */
MAP_REF_A_setReferenceVoltage(REF_A_VREF2_5V);
MAP_REF_A_enableReferenceVoltage();
/* Initializing ADC (MCLK/1/1) */
MAP_ADC14_enableModule();
MAP_ADC14_initModule(ADC_CLOCKSOURCE_MCLK, ADC_PREDIVIDER_1, ADC_DIVIDER_1,0);
/* Configuring GPIOs for Analog In */
MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5,
GPIO_PIN5 | GPIO_PIN4 | GPIO_PIN2 | GPIO_PIN1 | GPIO_PIN0,
GPIO_TERTIARY_MODULE_FUNCTION);
/* Configuring ADC Memory (ADC_MEM0 - ADC_MEM7 (A0 - A7) with no repeat)
* with internal 2.5v reference */
MAP_ADC14_configureMultiSequenceMode(ADC_MEM0, ADC_MEM7, false);
MAP_ADC14_configureConversionMemory(ADC_MEM0,
ADC_VREFPOS_INTBUF_VREFNEG_VSS,
ADC_INPUT_A0, false);//5.5
MAP_ADC14_configureConversionMemory(ADC_MEM1,
ADC_VREFPOS_INTBUF_VREFNEG_VSS,
ADC_INPUT_A1, false);//5.4
MAP_ADC14_configureConversionMemory(ADC_MEM3,
ADC_VREFPOS_INTBUF_VREFNEG_VSS,
ADC_INPUT_A3, false);//5.2
MAP_ADC14_configureConversionMemory(ADC_MEM4,
ADC_VREFPOS_INTBUF_VREFNEG_VSS,
ADC_INPUT_A4, false);//5.1
MAP_ADC14_configureConversionMemory(ADC_MEM5,
ADC_VREFPOS_INTBUF_VREFNEG_VSS,
ADC_INPUT_A5, false);//5.0
/* Enabling the interrupt when a conversion on channel 7 (end of sequence)
* is complete and enabling conversions */
MAP_ADC14_enableInterrupt(ADC_INT5);
/* Enabling Interrupts */
MAP_Interrupt_enableInterrupt(INT_ADC14);
MAP_Interrupt_enableMaster();
/* Setting up the sample timer to automatically step through the sequence
* convert.
*/
MAP_ADC14_enableSampleTimer(ADC_AUTOMATIC_ITERATION);
/* the start of the sample */
MAP_ADC14_enableConversion();
/**************************************************************************/
/*SPI*/
/**************************************************************************/
/* Setting DCO to 12MHz */
// CS_setDCOCenteredFrequency(CS_DCO_FREQUENCY_12);
/* Selecting P1.5 P1.6 and P1.7 in SPI mode */
MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1,
GPIO_PIN5 | GPIO_PIN6 | GPIO_PIN7, GPIO_PRIMARY_MODULE_FUNCTION);
/* Configuring SPI in 3wire master mode */
MAP_SPI_initMaster(EUSCI_B0_BASE, &spiMasterConfig);
/* Selecting P3.0 as SPI CS pin */
MAP_GPIO_setAsOutputPin(GPIO_PORT_P3, GPIO_PIN0);
MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P3, GPIO_PIN0);
/* Enable SPI module */
MAP_SPI_enableModule(EUSCI_B0_BASE);
float Vadc[5];
uint16_t i;
while(1)
{
DACVset(Vset);
// MAP_PCM_gotoLPM0();
MAP_ADC14_toggleConversionTrigger();
for (i=0;i<5;++i){
Vadc[i]=2.5*resultsBuffer[i]/ 16384;
}
sprintf (printNum, "%6.4f", Vadc[0]);
draw6x8Str(0, 0, printNum, 1,0);
}
}
void ADC14_IRQHandler(void)
{
uint64_t status;
status = MAP_ADC14_getEnabledInterruptStatus();
MAP_ADC14_clearInterruptFlag(status);
if(status & ADC_INT5)
{
MAP_ADC14_getMultiSequenceResult(resultsBuffer);
}
}
void DACVset(float Vsetadc){
static uint16_t DataInt=0;
static uint8_t Datatemp1=0;
static uint8_t Datatemp2=0;
const float Vdacref=1.500;
//Send data to DAC MAX5144 via SPI
DataInt=(uint16_t)(Vsetadc/Vdacref*16384);
DataInt=DataInt <<2;
Datatemp1=DataInt >> 8;
Datatemp2=DataInt & 0xFF;
/* Transmitting data to slave */
MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P3, GPIO_PIN0);
/* Polling to see if the TX buffer is ready */
//while (!(SPI_getInterruptStatus(EUSCI_B0_BASE,EUSCI_B_SPI_TRANSMIT_INTERRUPT)));
MAP_SPI_transmitData(EUSCI_B0_BASE, Datatemp1);
/* Polling to see if the TX buffer is ready */
//while (!(SPI_getInterruptStatus(EUSCI_B0_BASE,EUSCI_B_SPI_TRANSMIT_INTERRUPT)));
MAP_SPI_transmitData(EUSCI_B0_BASE, Datatemp2);
MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P3, GPIO_PIN0);
for (j=0; j<500; j++); //some delay
/**************************************************************************/
}
コメント
コメントを投稿