This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Tool/software:
Hello everyone,
I am working on a project for my postgraduate studies and I've encountered an issue with part of the code. The goal is to trigger a 12-bit ADC through a comparator (COMP) using an external pin. The values captured by the ADC should be stored in an array and later sent to a CSV file.
However, I am having trouble with triggering the ADC, both via interruption and 'event'. The ADC only executes once and then the entire code stops. Below is the code I am using:
const ADC12 = scripting.addModule("/ti/driverlib/ADC12", {}, false); const ADC121 = ADC12.addInstance(); const Board = scripting.addModule("/ti/driverlib/Board"); const COMP = scripting.addModule("/ti/driverlib/COMP", {}, false); const COMP1 = COMP.addInstance(); const GPIO = scripting.addModule("/ti/driverlib/GPIO", {}, false); const GPIO1 = GPIO.addInstance(); const GPIO2 = GPIO.addInstance(); const GPIO3 = GPIO.addInstance(); const GPIO4 = GPIO.addInstance(); const GPIO5 = GPIO.addInstance(); const OPA = scripting.addModule("/ti/driverlib/OPA", {}, false); const OPA1 = OPA.addInstance(); const SYSCTL = scripting.addModule("/ti/driverlib/SYSCTL"); const VREF = scripting.addModule("/ti/driverlib/VREF"); /** * Write custom configuration values to the imported modules. */ const divider9 = system.clockTree["UDIV"]; divider9.divideValue = 2; const gate7 = system.clockTree["MFCLKGATE"]; gate7.enable = true; const gate8 = system.clockTree["MFPCLKGATE"]; gate8.enable = true; const multiplier2 = system.clockTree["PLL_QDIV"]; multiplier2.multiplyValue = 5; const mux8 = system.clockTree["HSCLKMUX"]; mux8.inputSelect = "HSCLKMUX_SYSPLL0"; const oscillator2 = system.clockTree["SYSOSC"]; oscillator2.enableSYSOSCFCL = true; ADC121.$name = "ADC12_0"; ADC121.adcMem0vref = "VREF"; ADC121.enabledInterrupts = ["DL_ADC12_INTERRUPT_MEM0_RESULT_LOADED"]; ADC121.sampleTime0 = "250 ns"; ADC121.sampleTime1 = "250 ns"; ADC121.adcMem0bcsen = true; ADC121.sampClkSrc = "DL_ADC12_CLOCK_ULPCLK"; ADC121.adcMem0chansel = "DL_ADC12_INPUT_CHAN_13"; ADC121.enableFIFO = true; ADC121.repeatMode = true; ADC121.peripheral.$assign = "ADC0"; Board.InitPriority11 = "/ti/driverlib/PWM"; Board.InitPriority13 = "/ti/driverlib/QEI"; Board.InitPriority14 = "/ti/driverlib/CAPTURE"; Board.InitPriority12 = "/ti/driverlib/COMPARE"; Board.InitPriority5 = "/ti/driverlib/GPIO"; Board.InitPriority1 = "/ti/driverlib/VREF"; Board.InitPriority3 = "/ti/driverlib/COMP"; COMP1.channelEnable = ["POS"]; COMP1.vSource = "DL_COMP_REF_SOURCE_VREF_DAC"; COMP1.controlSelect = "DL_COMP_DAC_CONTROL_SW"; COMP1.enableOutputFilter = true; COMP1.$name = "COMP"; COMP1.outputEnable = true; COMP1.enabledInterrupts = ["DL_COMP_INTERRUPT_OUTPUT_EDGE"]; COMP1.posChannel = "DL_COMP_IPSEL_CHANNEL_1"; COMP1.interruptPriority = "0"; COMP1.peripheral.$assign = "COMP1"; COMP1.peripheral.compPinOut.$assign = "PA3"; COMP1.peripheral.compPinPos1.$assign = "PB24"; COMP1.compPinOutConfig.$name = "ti_driverlib_gpio_GPIOPinGeneric2"; COMP1.compPinPos1Config.$name = "ti_driverlib_gpio_GPIOPinGeneric3"; GPIO1.$name = "GPIO_PB6"; GPIO1.port = "PORTB"; GPIO1.portSegment = "Lower"; GPIO1.associatedPins[0].initialValue = "SET"; GPIO1.associatedPins[0].$name = "USER_PB6"; GPIO1.associatedPins[0].assignedPin = "6"; GPIO1.associatedPins[0].pin.$assign = "PB6"; GPIO2.port = "PORTB"; GPIO2.portSegment = "Lower"; GPIO2.$name = "GPIO_PB7"; GPIO2.associatedPins[0].initialValue = "SET"; GPIO2.associatedPins[0].$name = "USER_PB7"; GPIO2.associatedPins[0].assignedPin = "7"; GPIO2.associatedPins[0].pin.$assign = "PB7"; GPIO3.port = "PORTB"; GPIO3.portSegment = "Lower"; GPIO3.$name = "GPIO_PB8"; GPIO3.associatedPins[0].initialValue = "SET"; GPIO3.associatedPins[0].$name = "USER_PB8"; GPIO3.associatedPins[0].assignedPin = "8"; GPIO4.port = "PORTB"; GPIO4.$name = "GPIO_green"; GPIO4.portSegment = "Upper"; GPIO4.associatedPins[0].initialValue = "SET"; GPIO4.associatedPins[0].$name = "USER_green"; GPIO4.associatedPins[0].launchPadShortcut = "LED2GreenEn"; GPIO5.port = "PORTB"; GPIO5.portSegment = "Upper"; GPIO5.$name = "GPIO_blue"; GPIO5.associatedPins[0].initialValue = "SET"; GPIO5.associatedPins[0].$name = "USER_blue"; GPIO5.associatedPins[0].launchPadShortcut = "LED2BlueEn"; GPIO5.associatedPins[0].pin.$assign = "PB22"; OPA1.$name = "OPA_0"; OPA1.cfg0PSELChannel = "IN0_POS"; OPA1.cfg0MSELChannel = "GND"; OPA1.cfg0Chop = "ADC_AVERAGING"; OPA1.advBW = "HIGH"; OPA1.cfg0NSELChannel = "RBOT"; OPA1.advRRI = true; OPA1.cfg0OutputPin = "ENABLED"; OPA1.peripheral.$assign = "OPA0"; OPA1.peripheral.In0PosPin.$assign = "PA26"; OPA1.peripheral.OutPin.$assign = "PA22"; OPA1.In0PosPinConfig.$name = "ti_driverlib_gpio_GPIOPinGeneric0"; OPA1.OutPinConfig.$name = "ti_driverlib_gpio_GPIOPinGeneric4"; SYSCTL.forceDefaultClkConfig = true; SYSCTL.clockTreeEn = true; VREF.advClockConfigEnable = true; VREF.advClkSrc = "DL_VREF_CLOCK_BUSCLK"; VREF.checkVREFReady = true; VREF.peripheral.$assign = "VREF"; VREF.peripheral.vrefPosPin.$assign = "PA23"; VREF.vrefPosPinConfig.$name = "ti_driverlib_gpio_GPIOPinGeneric1"; Board.peripheral.$suggestSolution = "DEBUGSS"; Board.peripheral.swclkPin.$suggestSolution = "PA20"; Board.peripheral.swdioPin.$suggestSolution = "PA19"; GPIO3.associatedPins[0].pin.$suggestSolution = "PB8"; GPIO4.associatedPins[0].pin.$suggestSolution = "PB27";
#include <stdlib.h> #include <stdint.h> #include <string.h> #include <stdio.h> #include <stdbool.h> #include "ti/driverlib/dl_adc12.h" #include "ti/driverlib/dl_gpio.h" #include "ti_msp_dl_config.h" #include "sys/_stdint.h" #include "ti/driverlib/m0p/dl_core.h" #define COMP_INST_REF_VOLTAGE_mV (3300) #define COMP_INST_DAC8_OUTPUT_VOLTAGE_mV (50) const uint16_t ADC_RESOLUTION = 12; const uint16_t ARRAY_SIZE = 0x01 << ADC_RESOLUTION; volatile bool gCheckADC = false; volatile bool start = false; volatile uint16_t gADCResult = 0; uint8_t dacValue = 0; uint32_t amostras[ARRAY_SIZE]; uint32_t count = 0; uint32_t NUM_AMOSTRAS = 10000; //----------------------------------------------------------------------------------------------------------------------------- // Function to Save Data to CSV: void salvarAmostrasCSV(const char *nomeArquivo, uint32_t amostras[], uint16_t numAmostras) { // Construa o caminho absoluto const char *caminhoAbsoluto = "C:/Users/verga/OneDrive/Desktop/ADC_resultados/julho/amostra.csv"; FILE *file = fopen(caminhoAbsoluto, "w"); if (file == NULL){ printf("Error opening the file.\n"); return; } printf("File opened successfully. Saving data...\n"); fprintf(file, "Valor ADC,Ocorrencias\n"); for(int i = 0; i < ARRAY_SIZE; i++){ fprintf(file, "%d,%d\n", i, amostras[i]); } fclose(file); printf("Data successfully saved to CSV file.\n"); } //----------------------------------------------------------------------------------------------------------------------------- // Function to clear array void limparArray(uint32_t amostras[], uint32_t tamanho) { memset(amostras, 0, tamanho * sizeof(uint32_t)); } //----------------------------------------------------------------------------------------------------------------------------- // Configures the comparator and enables DAC and related interrupts void COMP() { dacValue = (COMP_INST_DAC8_OUTPUT_VOLTAGE_mV * 255) / COMP_INST_REF_VOLTAGE_mV; // Calculate the DAC value based on the configured voltage DL_COMP_setDACCode0(COMP_INST, dacValue); // Configures the comparator DAC DL_COMP_enable(COMP_INST); // Enable the comparator DL_COMP_enableInterrupt(COMP_INST, DL_COMP_INTERRUPT_OUTPUT_EDGE); // Enable comparator interrupts NVIC_EnableIRQ(COMP_INST_INT_IRQN); // Enable interrupt on NVIC //printf("Comparator configured and interrupt enabled. (COMP)\n"); } //----------------------------------------------------------------------------------------------------------------------------- // Delay function in clock cycle void delay_cycles(uint32_t cycles) { while (cycles > 0) { __asm(" nop"); cycles--; } } //----------------------------------------------------------------------------------------------------------------------------- // ADC reading function void readADC() { gADCResult = 0; DL_ADC12_startConversion(ADC12_0_INST); // ADC activation DL_GPIO_setPins((GPIOB), GPIO_PB7_USER_PB7_PIN); // oscilloscope visualization control gADCResult = DL_ADC12_getMemResult(ADC12_0_INST, DL_ADC12_MEM_IDX_0) & 0xFFF; } //----------------------------------------------------------------------------------------------------------------------------- // ADC recording function: void recordADC() { amostras[gADCResult]++; // Increments the occurrence of the ADC value in the array DL_GPIO_clearPins((GPIOB), GPIO_PB7_USER_PB7_PIN); // oscilloscope visualization control DL_GPIO_clearPins((GPIOB), GPIO_PB6_USER_PB6_PIN); // reset do opengamma printf("ADC lido: %d\n", gADCResult); delay_cycles(20); // delay in clock cycles DL_GPIO_setPins((GPIOB), GPIO_PB6_USER_PB6_PIN); // reset do opengamma start = false; gCheckADC = false; } //----------------------------------------------------------------------------------------------------------------------------- // Comparator Interrupt Handler: void GROUP1_IRQHandler(void) { if (DL_COMP_getPendingInterrupt(COMP_INST) == DL_COMP_IIDX_OUTPUT_EDGE) { // Checks whether the interrupt was caused by a rising edge start = true; DL_COMP_clearInterruptStatus(COMP_INST, DL_COMP_INTERRUPT_OUTPUT_EDGE); // Clears comparator interrupt } } //----------------------------------------------------------------------------------------------------------------------------- // Interrupt handler for the ADC void ADC12_0_INST_IRQHandler(void) { if (DL_ADC12_getPendingInterrupt(ADC12_0_INST) == DL_ADC12_IIDX_MEM0_RESULT_LOADED) { gCheckADC = true; DL_ADC12_clearInterruptStatus(ADC12_0_INST, DL_ADC12_INTERRUPT_MEM0_RESULT_LOADED); // Clears ADC interrupt } } //----------------------------------------------------------------------------------------------------------------------------- // Função principal que configura o sistema int main(void) { SYSCFG_DL_init(); NVIC_EnableIRQ(COMP_INST_INT_IRQN); NVIC_EnableIRQ(ADC12_0_INST_INT_IRQN); COMP(); limparArray(amostras, ARRAY_SIZE); printf("Sistema inicializado\n"); while(count < NUM_AMOSTRAS){ while (!start); // Wait for the comparator to interrupt readADC(); recordADC(); count++; printf("count: %d\n", count); } salvarAmostrasCSV("amostras.csv", amostras, ARRAY_SIZE); printf("FIM! \n"); return 0; }
Issue Faced:
If anyone could provide guidance or support on how to resolve this issue, I would greatly appreciate it.
Thank you in advance for your help!
Hi Diego,
When you stop the program with a debugger, where are you in the code? Place a breakpoint at 134 you can catch after the first read and check to make sure the ADC configurations is as expected.
Regards,
Luke
Hello Lucas, before starting
The program gets stuck (in a loop) at line 133, waiting for the 'start' value to return to '1'. before the first pass through while
The first time it is triggered and it enters the functions "readADC" and "recordADC" normally.
When it returns to make a second pass through the 'while' loop, the value of 'start' is '0' and does not return to '1'.
second passed by while
Could there be something wrong that I did in the comparator configuration?
Attached is an image of the comparator configuration screen in CCS Theia.
Thank you very much for the help.
Hi Diego,
The comparator portion doesn't look wrong to me at first glance. What's your input signal? You have a trigger on the rising or falling edge, so what I would expect is anytime you cross the 50mV mark (based on line 13) you should get a trigger on your comparator. You can place a breakpoint in your COMP ISR and then switch your COMPIN+ signal to verify you are getting a trigger on the rising and falling edges.
Regards,
Luke