So I'm using a code based off the ADCbuf example to read voltages from various sensors and trying to send the data over UART to a terminal program. Can I create a buffer that will populate with which channel goes with which reading? I've tried reducing the buffer size, which works, but I don't want to have such a small buffer that the MCU is constantly sending a data stream over UART. It doesn't seem power efficient to me.
#include <unistd.h> #include <stdint.h> #include <stddef.h> /* Driver Header files */ #include <ti/drivers/GPIO.h> #include <ti/drivers/PIN.h> #include <ti/drivers/UART.h> #include <ti/drivers/ADCBuf.h> // #include <ti/drivers/Watchdog.h> /* Board Header file */ #include "Board.h" #include <ti/drivers/timer/GPTimerCC26XX.h> #include <ti/drivers/Power.h> #include <ti/drivers/power/PowerCC26XX.h> #include <ti/sysbios/BIOS.h> #include <ti/sysbios/knl/Task.h> #include <xdc/runtime/Types.h> /////////////////////////// pin configuration /////////////////////// /* Pin driver handles */ static PIN_Handle muxPinHandle; /* Global memory storage for a PIN_Config table */ static PIN_State muxPinState; /* Global Variables */ unsigned int muxidx = 0; unsigned int muxmod = 0; static int channels = 10; int status = 3; static int ADCFREQ = 100; static int MUXFREQ = 5; PIN_Config muxPinTable[] = { IOID_21 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL | PIN_DRVSTR_MAX, //EN IOID_22 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL | PIN_DRVSTR_MAX, //A3 IOID_23 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL | PIN_DRVSTR_MAX, //A2 IOID_12 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL | PIN_DRVSTR_MAX, //A1 IOID_15 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL | PIN_DRVSTR_MAX, //A0 PIN_TERMINATE }; /////////////////////////// mux task configuration /////////////////////// /* Task data */ //Task_Struct timerTask; //char timerTaskStack[512]; GPTimerCC26XX_Handle hMUXTimer; void timerCallback(GPTimerCC26XX_Handle handle, GPTimerCC26XX_IntMask interruptMask) { // interrupt callback code goes here. Minimize processing in interrupt. GPIO_toggle(Board_GPIO_LED0); muxmod = muxidx % channels; //get remainder of muxidx for switch switch(muxmod) { case 0: PIN_setOutputValue(muxPinHandle, IOID_22, 0); PIN_setOutputValue(muxPinHandle, IOID_23, 0); PIN_setOutputValue(muxPinHandle, IOID_12, 0); PIN_setOutputValue(muxPinHandle, IOID_15, 0); break; case 1: PIN_setOutputValue(muxPinHandle, IOID_22, 0); PIN_setOutputValue(muxPinHandle, IOID_23, 0); PIN_setOutputValue(muxPinHandle, IOID_12, 0); PIN_setOutputValue(muxPinHandle, IOID_15, 1); break; case 2: PIN_setOutputValue(muxPinHandle, IOID_22, 0); PIN_setOutputValue(muxPinHandle, IOID_23, 0); PIN_setOutputValue(muxPinHandle, IOID_12, 1); PIN_setOutputValue(muxPinHandle, IOID_15, 0); break; case 3: PIN_setOutputValue(muxPinHandle, IOID_22, 0); PIN_setOutputValue(muxPinHandle, IOID_23, 0); PIN_setOutputValue(muxPinHandle, IOID_12, 1); PIN_setOutputValue(muxPinHandle, IOID_15, 1); break; case 4: PIN_setOutputValue(muxPinHandle, IOID_22, 0); PIN_setOutputValue(muxPinHandle, IOID_23, 1); PIN_setOutputValue(muxPinHandle, IOID_12, 0); PIN_setOutputValue(muxPinHandle, IOID_15, 0); break; case 5: PIN_setOutputValue(muxPinHandle, IOID_22, 0); PIN_setOutputValue(muxPinHandle, IOID_23, 1); PIN_setOutputValue(muxPinHandle, IOID_12, 0); PIN_setOutputValue(muxPinHandle, IOID_15, 1); break; case 6: PIN_setOutputValue(muxPinHandle, IOID_22, 0); PIN_setOutputValue(muxPinHandle, IOID_23, 1); PIN_setOutputValue(muxPinHandle, IOID_12, 1); PIN_setOutputValue(muxPinHandle, IOID_15, 0); break; case 7: PIN_setOutputValue(muxPinHandle, IOID_22, 0); PIN_setOutputValue(muxPinHandle, IOID_23, 1); PIN_setOutputValue(muxPinHandle, IOID_12, 1); PIN_setOutputValue(muxPinHandle, IOID_15, 1); break; case 8: PIN_setOutputValue(muxPinHandle, IOID_22, 1); PIN_setOutputValue(muxPinHandle, IOID_23, 0); PIN_setOutputValue(muxPinHandle, IOID_12, 0); PIN_setOutputValue(muxPinHandle, IOID_15, 0); break; case 9: PIN_setOutputValue(muxPinHandle, IOID_22, 1); PIN_setOutputValue(muxPinHandle, IOID_23, 0); PIN_setOutputValue(muxPinHandle, IOID_12, 0); PIN_setOutputValue(muxPinHandle, IOID_15, 1); break; case 10: PIN_setOutputValue(muxPinHandle, IOID_22, 1); PIN_setOutputValue(muxPinHandle, IOID_23, 0); PIN_setOutputValue(muxPinHandle, IOID_12, 1); PIN_setOutputValue(muxPinHandle, IOID_15, 0); break; case 11: PIN_setOutputValue(muxPinHandle, IOID_22, 1); PIN_setOutputValue(muxPinHandle, IOID_23, 0); PIN_setOutputValue(muxPinHandle, IOID_12, 1); PIN_setOutputValue(muxPinHandle, IOID_15, 1); break; case 12: PIN_setOutputValue(muxPinHandle, IOID_22, 1); PIN_setOutputValue(muxPinHandle, IOID_23, 1); PIN_setOutputValue(muxPinHandle, IOID_12, 0); PIN_setOutputValue(muxPinHandle, IOID_15, 0); break; case 13: PIN_setOutputValue(muxPinHandle, IOID_22, 1); PIN_setOutputValue(muxPinHandle, IOID_23, 1); PIN_setOutputValue(muxPinHandle, IOID_12, 0); PIN_setOutputValue(muxPinHandle, IOID_15, 1); break; case 14: PIN_setOutputValue(muxPinHandle, IOID_22, 1); PIN_setOutputValue(muxPinHandle, IOID_23, 1); PIN_setOutputValue(muxPinHandle, IOID_12, 1); PIN_setOutputValue(muxPinHandle, IOID_15, 0); break; case 15: PIN_setOutputValue(muxPinHandle, IOID_22, 1); PIN_setOutputValue(muxPinHandle, IOID_23, 1); PIN_setOutputValue(muxPinHandle, IOID_12, 1); PIN_setOutputValue(muxPinHandle, IOID_15, 1); break; } if(muxidx == channels){ muxidx = 0; //reset counter back to zero, if it equals the number of channels } muxidx += 1; // increment counter } /////////////////////////// ADCbuf/UART configuration /////////////////////// #define ADCBUFFERSIZE (5) #define UARTBUFFERSIZE ((20 * ADCBUFFERSIZE) + 24) uint16_t sampleBufferOne[ADCBUFFERSIZE]; uint16_t sampleBufferTwo[ADCBUFFERSIZE]; uint32_t microVoltBuffer[ADCBUFFERSIZE]; uint32_t buffersCompletedCounter = 0; char uartTxBuffer[UARTBUFFERSIZE]; /* Driver handle shared between the task and the callback function */ UART_Handle uart; /* * This function is called whenever an ADC buffer is full. * The content of the buffer is then converted into human-readable format and * sent to the PC via UART. */ void adcBufCallback(ADCBuf_Handle handle, ADCBuf_Conversion *conversion, void *completedADCBuffer, uint32_t completedChannel) { uint_fast16_t i; uint_fast16_t uartTxBufferOffset = 0; /* Adjust raw ADC values and convert them to microvolts */ ADCBuf_adjustRawValues(handle, completedADCBuffer, ADCBUFFERSIZE, completedChannel); ADCBuf_convertAdjustedToMicroVolts(handle, completedChannel, completedADCBuffer, microVoltBuffer, ADCBUFFERSIZE); /* Start with a header message. */ uartTxBufferOffset = snprintf(uartTxBuffer, UARTBUFFERSIZE - uartTxBufferOffset, "\r\nBuffer %u finished.", (unsigned int)buffersCompletedCounter++); /* Write channel number to the UART buffer if there is room. */ if (uartTxBufferOffset < UARTBUFFERSIZE) { uartTxBufferOffset += snprintf(uartTxBuffer + uartTxBufferOffset, UARTBUFFERSIZE - uartTxBufferOffset, "\r\nChannel: "); for (i = 0; i < ADCBUFFERSIZE && uartTxBufferOffset < UARTBUFFERSIZE; i++) { uartTxBufferOffset += snprintf(uartTxBuffer + uartTxBufferOffset, UARTBUFFERSIZE - uartTxBufferOffset, "%u,", (unsigned int)muxmod); } } // /* Write raw adjusted values to the UART buffer if there is room. */ // uartTxBufferOffset += snprintf(uartTxBuffer + uartTxBufferOffset, // UARTBUFFERSIZE - uartTxBufferOffset, "\r\nRaw Buffer: "); // // for (i = 0; i < ADCBUFFERSIZE && uartTxBufferOffset < UARTBUFFERSIZE; i++) { // uartTxBufferOffset += snprintf(uartTxBuffer + uartTxBufferOffset, // UARTBUFFERSIZE - uartTxBufferOffset, "%u,", // *(((uint16_t *)completedADCBuffer) + i)); // } /* Write microvolt values to the UART buffer if there is room. */ if (uartTxBufferOffset < UARTBUFFERSIZE) { uartTxBufferOffset += snprintf(uartTxBuffer + uartTxBufferOffset, UARTBUFFERSIZE - uartTxBufferOffset, "\r\nMicrovolts: "); for (i = 0; i < ADCBUFFERSIZE && uartTxBufferOffset < UARTBUFFERSIZE; i++) { uartTxBufferOffset += snprintf(uartTxBuffer + uartTxBufferOffset, UARTBUFFERSIZE - uartTxBufferOffset, "%u,", (unsigned int)microVoltBuffer[i]); } } /* * Ensure we don't write outside the buffer. * Append a newline after the data. */ if (uartTxBufferOffset < UARTBUFFERSIZE) { uartTxBuffer[uartTxBufferOffset++] = '\n'; } else { uartTxBuffer[UARTBUFFERSIZE-1] = '\n'; } /* Display the data via UART */ UART_write(uart, uartTxBuffer, uartTxBufferOffset); } /* * Callback function to use the UART in callback mode. It does nothing. */ void uartCallback(UART_Handle handle, void *buf, size_t count) { return; } /* * ======== mainThread ======== */ void *mainThread(void *arg0) { /////////////////////////// mux /////////////////////// muxPinHandle = PIN_open(&muxPinState, muxPinTable); if(!muxPinHandle) { /* Error initializing mux output pins */ while(1); } PIN_setOutputValue(muxPinHandle, IOID_21, 1); /////////////////////////// GPIO /////////////////////// /* Call driver init functions */ GPIO_init(); /* Configure the LED pins */ GPIO_setConfig(Board_GPIO_LED0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW); /* Turn on user LED */ GPIO_write(Board_GPIO_LED0, Board_GPIO_LED_ON); /////////////////////////// ADCbuf/ UART /////////////////////// UART_Params uartParams; ADCBuf_Handle adcBuf; ADCBuf_Params adcBufParams; ADCBuf_Conversion continuousConversion; /* Call driver init functions */ ADCBuf_init(); UART_init(); /* Create a UART with data processing off. */ UART_Params_init(&uartParams); uartParams.writeDataMode = UART_DATA_BINARY; uartParams.writeMode = UART_MODE_CALLBACK; uartParams.writeCallback = uartCallback; uartParams.baudRate = 115200; uart = UART_open(Board_UART0, &uartParams); /* Set up an ADCBuf peripheral in ADCBuf_RECURRENCE_MODE_CONTINUOUS */ ADCBuf_Params_init(&adcBufParams); adcBufParams.callbackFxn = adcBufCallback; adcBufParams.recurrenceMode = ADCBuf_RECURRENCE_MODE_CONTINUOUS; adcBufParams.returnMode = ADCBuf_RETURN_MODE_CALLBACK; adcBufParams.samplingFrequency = ADCFREQ; adcBuf = ADCBuf_open(Board_ADCBUF0, &adcBufParams); /* Configure the conversion struct */ continuousConversion.arg = NULL; continuousConversion.adcChannel = Board_ADCBUF0CHANNEL0; continuousConversion.sampleBuffer = sampleBufferOne; continuousConversion.sampleBufferTwo = sampleBufferTwo; continuousConversion.samplesRequestedCount = ADCBUFFERSIZE; if (adcBuf == NULL){ /* ADCBuf failed to open. */ while(1); } /* Start converting. */ status = ADCBuf_convert(adcBuf, &continuousConversion, 1); //if (ADCBuf_convert(adcBuf, &continuousConversion, 1) != // ADCBuf_STATUS_SUCCESS) { /* Did not start conversion process correctly. */ // ADCBuf_close(adcBuf); //} GPTimerCC26XX_Params paramsMUX; GPTimerCC26XX_Params_init(¶msMUX); paramsMUX.width = GPT_CONFIG_32BIT; paramsMUX.mode = GPT_MODE_PERIODIC_UP; paramsMUX.debugStallMode = GPTimerCC26XX_DEBUG_STALL_OFF; hMUXTimer = GPTimerCC26XX_open(CC2640R2_LAUNCHXL_GPTIMER1A, ¶msMUX); //Need timer 0A for ADCbuf if(hMUXTimer == NULL) { Task_exit(); } Types_FreqHz freq; BIOS_getCpuFreq(&freq); //48MHz //GPTimerCC26XX_Value loadVal = freq.lo / 1000; //47999 = 1ms. 1 clock tick = 1/48e6 //GPTimerCC26XX_Value loadVal = 48000000; //48e6 = 1 sec GPTimerCC26XX_Value loadValMUX = 48000000/MUXFREQ; //24e6 = 0.5 sec loadValMUX = loadValMUX - 1; GPTimerCC26XX_setLoadValue(hMUXTimer, loadValMUX); GPTimerCC26XX_registerInterrupt(hMUXTimer, timerCallback, GPT_INT_TIMEOUT); GPTimerCC26XX_start(hMUXTimer); /* Start TI-RTOS */ // BIOS_start(); while(1) { Task_sleep(BIOS_WAIT_FOREVER); } }