Part Number: LAUNCHXL-CC2640R2
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);
}
}