Tool/software: Code Composer Studio
Experience Level: Beginner
With the help of responses from my previous forum post, I succeeded in establishing communication between ADC and controller via SPI.
Now, I'm able to read ID register. However, I'm not able to get data values properly.
Data sheet of the ADC - https://www.analog.com/media/en/technical-documentation/data-sheets/AD7177-2.pdf
Able to read ID register properly.
When trying to read Data Register, I get only 16-bit data instead of 32-bit data. I'm reading twice(by giving a read command for each 16-bit). I'm not sure if this is the right way, but if I give only 1 read command and try to read it twice, it is not able to read and is getting struck in the DataGet().
How do I read 32- bit data.
My algorithm is as follows:
1) Configure SPI communication in 16 bit, Mode-3
2) Configured GPIO interrupt for falling edges. Interrupt pin is connected to DOUT
ISR is written in the following way:
1) Disable interrupt and clear flag(to make sure there's no successive interrupt while ISR() is being executed)
2) Read ID register (command word = 0x47)
3) Write to IF mode register to make sure word length - 32 bits (command word = 0x02)
4) Write to data register to read it (comamand word = 0x44)
5) Read it (after 1st read, sending an other 0x44 command and then reading again) . Then, left shifting the MSB's by 16 and bitwise OR with LSB's
6) Enable Interrupt
Results are as follows:
INPUT - OUTPUT
-2.5 V - around 0 (0)
-1.3 V - around 16,000
0 V - around 32,000(2^15)
1.3 V - around 48,000
2.5 V - around 64,000 (2^16)
As per the above readings, I'm inferring that I'm reading only 16-bit value and not 32- bit value.
I'm attaching my code to this post. Please help me get 32-bit values. Am I doing wrong in the configuration or the way I'm reading the values? or is there anything else that I'm missing out? Any leads would highly be appreciated.
#include <stdbool.h> #include <stdint.h> #include "inc/hw_memmap.h" #include "driverlib/gpio.h" #include "driverlib/pin_map.h" #include "driverlib/ssi.h" #include "driverlib/sysctl.h" #include "driverlib/uart.h" #include "utils/uartstdio.h" #include "inc/hw_types.h" #include "inc/hw_ints.h" #include "driverlib/adc.h" #include "driverlib/interrupt.h" #include "driverlib/rom.h" #include "driverlib/rom_map.h" #include "driverlib/fpu.h" #include "driverlib/debug.h" #include "drivers/pinout.h" //***************************************************************************** // //! \addtogroup ssi_examples_list //! <h1>SPI Master (spi_master)</h1> //! //! This example shows how to configure the SSI0 as SPI Master. The code will //! send three characters on the master Tx then polls the receive FIFO until //! 3 characters are received on the master Rx. //! //! This example uses the following peripherals and I/O signals. You must //! review these and change as needed for your own board: //! - SSI0 peripheral //! - GPIO Port A peripheral (for SSI0 pins) //! - SSI0Clk - PA2 //! - SSI0Fss - PA3 //! - SSI0Rx - PA4 //! - SSI0Tx - PA5 //! //! The following UART signals are configured only for displaying console //! messages for this example. These are not required for operation of SSI0. //! - UART0 peripheral //! - GPIO Port A peripheral (for UART0 pins) //! - UART0RX - PA0 //! - UART0TX - PA1 //! //! This example uses the following interrupt handlers. To use this example //! in your own application you must add these interrupt handlers to your //! vector table. //! - None. // //***************************************************************************** //***************************************************************************** // // Number of bytes to send and receive. // //***************************************************************************** #define NUM_SSI_DATA 2 uint32_t g_ui32SysClock,flag=0; uint32_t pui32DataRx[NUM_SSI_DATA]; uint32_t pui32DataRx_1[NUM_SSI_DATA]; uint32_t pui32DataTx_1[NUM_SSI_DATA]; uint32_t ui32Index; uint32_t ID_REGISTER[2], temp; //***************************************************************************** // // This function sets up UART0 to be used for a console to display information // as the example is running. // //***************************************************************************** void ISR(); void ConfigureUART(void) { // // Enable the GPIO Peripheral used by the UART. // ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); // // Enable UART0 // ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0); // // Configure GPIO Pins for UART mode. // ROM_GPIOPinConfigure(GPIO_PA0_U0RX); ROM_GPIOPinConfigure(GPIO_PA1_U0TX); ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1); // // Initialize the UART for console I/O. // UARTStdioConfig(0, 115200, g_ui32SysClock); //UARTprintf("UART configured successfully\n"); } //***************************************************************************** // // Configure SSI0 in master Freescale (SPI) mode. This example will send out // 3 bytes of data, then wait for 3 bytes of data to come in. This will all be // done using the polling method. // //***************************************************************************** void main(void) { /* #if defined(TARGET_IS_TM4C129_RA0) || \ defined(TARGET_IS_TM4C129_RA1) || \ defined(TARGET_IS_TM4C129_RA2) uint32_t ui32SysClock; #endif */ g_ui32SysClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120000000);//Sets the clock Frequency ConfigureUART(); //SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOP); SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0); // PinoutSet(false, false);//enables the GPIO modules and configures the device pins for standard usages GPIOPinConfigure(GPIO_PA2_SSI0CLK); GPIOPinConfigure(GPIO_PA3_SSI0FSS); GPIOPinConfigure(GPIO_PA5_SSI0XDAT1); GPIOPinConfigure(GPIO_PA4_SSI0XDAT0); // The SSI0 peripheral must be enabled for use. // // // Configure the GPIO settings for the SSI pins. This function also gives // control of these pins to the SSI hardware. Consult the data sheet to // see which functions are allocated per pin. // The pins are assigned as follows: // PA5 - SSI0Tx // PA4 - SSI0Rx // PA3 - SSI0Fss // PA2 - SSI0CLK // TODO: change this to select the port/pin you are using. // GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_5 | GPIO_PIN_4 | GPIO_PIN_3 | GPIO_PIN_2); // // Configure and enable the SSI port for SPI master mode. Use SSI0, // system clock supply, idle clock level low and active low clock in // freescale SPI mode, master mode, 1MHz SSI frequency, and 8-bit data. // For SPI mode, you can set the polarity of the SSI clock when the SSI // unit is idle. You can also configure what clock edge you want to // capture data on. Please reference the datasheet for more information on // the different SPI modes. // //#if defined(TARGET_IS_TM4C129_RA0) || \ // defined(TARGET_IS_TM4C129_RA1) || \ // defined(TARGET_IS_TM4C129_RA2) // SSIConfigSetExpClk(SSI0_BASE, g_ui32SysClock, SSI_FRF_MOTO_MODE_3, // SSI_MODE_MASTER, 300000, 16); //#else // SSIConfigSetExpClk(SSI0_BASE, g_ui32SysClock, SSI_FRF_MOTO_MODE_3, // SSI_MODE_MASTER, 300000, 16); //#endif SSIConfigSetExpClk(SSI0_BASE, g_ui32SysClock, SSI_FRF_MOTO_MODE_3, SSI_MODE_MASTER, 300000, 16); // // Enable the SSI0 module. // //SSIAdvModeSet(SSI0_BASE, SSI_ADV_MODE_QUAD_WRITE); SSIAdvModeSet(SSI0_BASE, SSI_ADV_MODE_READ_WRITE); SSIEnable(SSI0_BASE); //SSIDataPut(SSI0_BASE,0x47); while(SSIDataGetNonBlocking(SSI0_BASE, &ID_REGISTER[0])) { } //SSIDataPut(SSI0_BASE,0x8274); // //ox29 -> Fliter Config 1 //Filter - Sinc3 -> Bit word= 1000001001101000 = 0x8268 //Filter - Sinc3 -> Bit word= 1000001001110100 = // while(SSIBusy(SSI0_BASE)) // { // } // for(ui32Index = 0; ui32Index < 2; ui32Index++) // { // // // // // Receive the data using the "blocking" Get function. This function // // will wait until there is data in the receive FIFO before returning. // // // SSIDataGet(SSI0_BASE, &pui32DataRx[ui32Index]); // //UARTprintf("Test print\n"); // // // // Since we are using 8-bit data, mask off the MSB. // // // pui32DataRx[ui32Index] &= 0x000000FF; // // // // // Display the data that SSI0 received. // // // // UARTprintf("Received = "); // // UARTprintf("'%d' ", pui32DataRx[ui32Index]); // while(SSIBusy(SSI0_BASE)) // { // } // // } // while(SSIBusy(SSI0_BASE)) // { // } // // Read any residual data from the SSI port. This makes sure the receive // FIFOs are empty, so we don't read any unwanted junk. This is done hereT\n"); SSIDataPut(SSI0_BASE,0x47);//Command word To read ID register SSIDataGet(SSI0_BASE,ID_REGISTER); SSIDataPut(SSI0_BASE,0x00);//Dummy data SSIDataGet(SSI0_BASE,&ID_REGISTER[0]); UARTprintf("ID: %d \n", ID_REGISTER[0]); SSIDataPut(SSI0_BASE,0x02); //IF Mode register command word SSIDataGet(SSI0_BASE,pui32DataRx);//Dummy read // SysCtlDelay(g_ui32SysClock );//delay GPIOIntRegisterPin(GPIO_PORTP_BASE, GPIO_PIN_0, ISR);// Registering GPIO P0 as interrupt GPIOPinTypeGPIOInput(GPIO_PORTP_BASE, GPIO_PIN_0); GPIOIntTypeSet(GPIO_PORTP_BASE, GPIO_PIN_0, GPIO_FALLING_EDGE); GPIOIntEnable(GPIO_PORTP_BASE, GPIO_PIN_0); IntEnable(INT_GPIOP0); //UARTprintf("Test print\n"); //IntTrigger(INT_GPIOP0); //UARTprintf("Interrupt configured successfully\n"); // // Display indication that the SSI is transmitting data. // //UARTprintf("'%d' ", *temp); //UARTprintf("Sent:\n "); //SSIDataGet(SSI0_BASE, &pui32DataRx[ui32Index]); // // Wait until SSI0 is done transferring all the data in the transmit FIFO. // // // Display indication that the SSI is receiving data. // // UARTprintf("\nInterrupt not occurred\n "); // // Receive 3 bytes of data. // //for(ui32Index = 0; ui32Index < NUM_SSI_DATA; ui32Index++) // { // // Receive the data using the "blocking" Get function. This function // will wait until there is data in the receive FIFO before returning. // //SSIDataGet(SSI0_BASE, &pui32DataRx[0]); // // Since we are using 8-bit data, mask off the MSB. // //pui32DataRx[0] &= 0x0000FFFF; // // Display the data that SSI0 received. // // UARTprintf("'%d' ", pui32DataRx[ui32Index]); // while(SSIBusy(SSI0_BASE)) // { // } // } while(1) { } // // Return no errors // //return(0);*/ } void ISR() { //UARTprintf("Interrupt Occurred\n"); GPIOIntClear(GPIO_PORTP_BASE,GPIO_PIN_0); GPIOIntDisable(GPIO_PORTP_BASE, GPIO_PIN_0); IntDisable(INT_GPIOP0); // SSIDataPut(SSI0_BASE,0x47);//Command word To read ID register // SSIDataGet(SSI0_BASE,ID_REGISTER); // SSIDataPut(SSI0_BASE,0x00);//Dummy data // SSIDataGet(SSI0_BASE,&ID_REGISTER[0]); // UARTprintf("ID: %d \n", ID_REGISTER[0]); //SSIDataGet(SSI0_BASE, &pui32DataRx[ui32Index]); // while(SSIDataGetNonBlocking(SSI0_BASE, &pui32DataRx_1[0])) // { // } // SSIDataPut(SSI0_BASE,0x00); // while(SSIBusy(SSI0_BASE)) // { // } pui32DataRx_1[ui32Index] = 0x00000000; // // SSIDataPut(SSI0_BASE,0x44);//Command word To read register // SSIDataGet(SSI0_BASE,pui32DataRx_1); // dummy data // // Now read the two bytes of the ID // SSIDataPut(SSI0_BASE,0x00);//send dummy data // SSIDataGet(SSI0_BASE,&pui32DataRx_1[0]); // first byte // // while(SSIBusy(SSI0_BASE)) // { // } // while(SSIDataGetNonBlocking(SSI0_BASE, &pui32DataRx_1[ui32Index])) // { // } // SSIDataPut(SSI0_BASE,0x44);//Command word To read register // SSIDataGet(SSI0_BASE,pui32DataRx); // dummy data // // SSIDataPut(SSI0_BASE,0x00);//send dummy data // SSIDataGet(SSI0_BASE,&pui32DataRx[1]); // first byte //UARTprintf("ADC value: 0x%02x%02x\n", pui32DataRx[0], pui32DataRx[1]); for(ui32Index = 0; ui32Index < 2; ui32Index++) { // // Receive the data using the "blocking" Get function. This function // will wait until there is data in the receive FIFO before returning. SSIDataPut(SSI0_BASE,0x44); SSIDataGet(SSI0_BASE, pui32DataRx);//Reading dummy SSIDataPut(SSI0_BASE,0x00);//Writing dummy SSIDataGet(SSI0_BASE, &pui32DataRx[ui32Index]);//Reading the actual value //SSIDataGet(SSI0_BASE, &pui32DataRx[ui32Index]); //SSIDataPut(SSI0_BASE,0x00); //UARTprintf("Test print\n"); // // Since we are using 8-bit data, mask off the MSB. //16-bit //pui32DataRx_1[ui32Index] &= 0x0000FFFF; // // Display the data that SSI0 received. // //UARTprintf("Received = "); // UARTprintf("'%d' \n", pui32DataRx_1[ui32Index]); while(SSIBusy(SSI0_BASE)) { } while(SSIDataGetNonBlocking(SSI0_BASE, &pui32DataRx[ui32Index])) { } //temp = pui32DataRx_1[0]<<16 | pui32DataRx_1[1] ; //pui32DataRx_1[ui32Index] &= 0x0000FFFF; } //temp = pui32DataRx[0] << 24 | pui32DataRx[1] << 16 | pui32DataRx[2] << 8 | pui32DataRx[3]; temp = pui32DataRx[0]<<16 | pui32DataRx[1]; UARTprintf("ADC value = '%d' \n", temp); //UARTprintf("ID: 0x%02x%02x\n", pui32DataRx[0], pui32DataRx[1]); GPIOIntEnable(GPIO_PORTP_BASE, GPIO_PIN_0); IntEnable(INT_GPIOP0); }