工具与软件:
您好!
我将尝试实施 ADC 比较器中断、以便在测量的电压高于0.11V 时红色 LED 亮起、并在低于0.11V (约为136/4096 * 3.3V)时熄灭。 下面是我的代码。 我怀疑 InitADC 和 ADC0Seq2Handler 中的中断条件/配置有问题。 我已经正确地更新了 startup_ccs.c 中的矢量表
现在、PE3正在收集电压数据、我已确认它工作正常。 怎么了?
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.
工具与软件:
您好!
我将尝试实施 ADC 比较器中断、以便在测量的电压高于0.11V 时红色 LED 亮起、并在低于0.11V (约为136/4096 * 3.3V)时熄灭。 下面是我的代码。 我怀疑 InitADC 和 ADC0Seq2Handler 中的中断条件/配置有问题。 我已经正确地更新了 startup_ccs.c 中的矢量表
#define ADC_SEQUENCER3_LENGTH 1 #define ADC_SEQUENCER2_LENGTH 4 #define ADC_SEQUENCER1_LENGTH 4 #define ADC_SEQUENCER0_LENGTH 8 #define VOLTAGE_PRIORITY 0 #define VOLTAGE_CALIBRATION_FACTOR 1.008 uint32_t VoltBuf[ADC_SEQUENCER2_LENGTH]; // SS2 has the size of 4 samples uint32_t voltage; int32_t VoltIntegerPart; int32_t VoltFractionPart; void ADC0Seq2Handler(void){ IntMasterDisable(); uint32_t ulStatus = ADCIntStatus(ADC0_BASE, 2, true); uint32_t comparatorStatus = ADCComparatorIntStatus(ADC0_BASE); ADCIntClear(ADC0_BASE,2); if (comparatorStatus & (1 << 0)) { GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, GPIO_PIN_2); ADCComparatorIntClear(ADC0_BASE, 0); } if (comparatorStatus & (1 << 1)) { GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0); ADCComparatorIntClear(ADC0_BASE, 1); } IntMasterEnable(); } void InitADC(void){ SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3); // Configure PE3 as an ADC input SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); // Enable the ADC0 peripheral ADCHardwareOversampleConfigure(ADC0_BASE,32); // Set the auto average to 64 // Configure sequence 2 for voltage measurement on AIN0 (PE) ADCSequenceDisable(ADC0_BASE, 2); // Disable sequence 2 ADCSequenceConfigure(ADC0_BASE, 2, ADC_TRIGGER_PROCESSOR, VOLTAGE_PRIORITY); // Configure sequence 2 ADCSequenceStepConfigure(ADC0_BASE, 2, 0, ADC_CTL_CH0); ADCSequenceStepConfigure(ADC0_BASE, 2, 1, ADC_CTL_CH0); ADCSequenceStepConfigure(ADC0_BASE, 2, 2, ADC_CTL_CH0); ADCSequenceStepConfigure(ADC0_BASE, 2, 3, ADC_CTL_CH0 | ADC_CTL_IE | ADC_CTL_END); // Set up the last step and start an interrupt when the conversion is over ADCSequenceEnable(ADC0_BASE, 2); // Enable the sequence again ADCIntEnable(ADC0_BASE,0); ADCIntClear(ADC0_BASE, 2); // Clear the interrupt flag // Configure the ADC comparator ADCComparatorConfigure(ADC0_BASE, 1, ADC_COMP_TRIG_NONE | ADC_COMP_INT_HIGH_HALWAYS); ////////////////////////////////////////////////////////////////////////////////// could be wrong ADCComparatorRegionSet(ADC0_BASE, 0, 136, 4095); // Set the comparator region (136 corresponds to 0.11V) ADCComparatorReset(ADC0_BASE, 0, true, true); // Reset the comparator ADCComparatorIntEnable(ADC0_BASE, 0); // Enable the comparator interrupt ADCComparatorConfigure(ADC0_BASE, 2, ADC_COMP_TRIG_NONE | ADC_COMP_INT_LOW_HALWAYS ); ////////////////////////////////////////////////////////////////////////////////// could be wrong ADCComparatorRegionSet(ADC0_BASE, 1, 0, 136); // Set the comparator region (136 corresponds to 0.11V) ADCComparatorReset(ADC0_BASE, 1, true, true); // Reset the comparator ADCComparatorIntEnable(ADC0_BASE, 1); // Enable the comparator interrupt IntEnable(INT_ADC0SS2); // Enable the ADC sequence 2 interrupt in the NVIC IntMasterEnable(); } void InitGPIO(void) { // Enable the GPIO port for the LED (PF2) SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1); // Configure PF2 as an output GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, 0); // Initialize the LED to be off } void main(void) { SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); // System clock: 16*12.5/2.5 = 80MHz (MAX) InitADC(); InitGPIO(); while(1){} }
顺便说一下、第44行应该是 ADCIntEnable (ADC0_BASE、2)
实际上、这杀死了我拥有的其余主要功能。
假设您要将 AIN0传递给比较器0进行比较、您将编写如下内容。
ADCSequenceStepConfigure (ADC0_BASE、2、0、ADC_CTL_CH0 | ADC_CTL_CMP0);//将 CH0分配至步骤0并将该通道路由到比较器0。
在代码中、我看到使用比较器1和比较器2来检查边界时、没有向任何比较器分配任何通道。 请记住 、与每个比较器单元关联、您可以设置上下键合值。 请参阅以下说明。 无需使用两个不同的比较器单元来设置上限和下限。 您似乎打算使用两个不同的比较器单元来设置两个不同的限值。 在另一种情况下,您只需将通道(例如 CH0)分配给比较器(例如 ADC_CTL_CMP0) 并设置 ADC_CTL_CMP0比较器的下限和上限。
感谢您的答复。 更新后的代码如下所示。 它仍然不工作,我不知道什么是错的。 我一直在遵循这里显示的示例代码: https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/313435/tiva-digital-comparator-problem
但他们的示例似乎没有内部温度传感器读数、我的示例中没有、我不知道我的设置的哪个部分是错误的。 顺便说一下、如果我运行以下代码、可以在终端上得到正确的输出。 只有 ADC 中断不起作用。
#define ADC_SEQUENCER3_LENGTH 1 #define ADC_SEQUENCER2_LENGTH 4 #define ADC_SEQUENCER1_LENGTH 4 #define ADC_SEQUENCER0_LENGTH 8 #define VOLTAGE_CALIBRATION_FACTOR 1.008 int ulTemp_ValueC; uint32_t TempBuf[ADC_SEQUENCER3_LENGTH]; // SS3 has the size of 1 sample uint32_t VoltBuf[ADC_SEQUENCER2_LENGTH]; // SS2 has the size of 4 samples int tempC; int tempF; uint32_t voltage; int32_t VoltIntegerPart; int32_t VoltFractionPart; void InitUART(void){ // Initialize the UART. SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0); GPIOPinConfigure(GPIO_PA0_U0RX); GPIOPinConfigure(GPIO_PA1_U0TX); GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1); UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC); UARTStdioConfig(0, 115200, 16000000); } void InitADC(void){ SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3); // Configure PE3 as an ADC input SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); // Enable the ADC0 peripheral ADCHardwareOversampleConfigure(ADC0_BASE,32); // Set the auto average to 64 // Configure sequence 3 for internal temperature sensor ADCSequenceDisable(ADC0_BASE, 3); // Disable sequence 3 ADCSequenceStepConfigure(ADC0_BASE, 3, 0, ADC_CTL_TS | ADC_CTL_IE | ADC_CTL_END); // Set up the last step and start an interrupt when the conversion is over ADCSequenceEnable(ADC0_BASE, 3); // Enable the sequence again ADCSequenceConfigure(ADC0_BASE, 3, ADC_TRIGGER_PROCESSOR, 1); // Configure sequence 3, Priority must be 1 or 0 if ADC_TRIGGER_ALWAYS is used by another sequence ADCIntClear(ADC0_BASE, 3); // Clear the interrupt flag // Configure sequence 2 for voltage measurement on AIN0 (PE) ADCSequenceDisable(ADC0_BASE, 2); // Disable sequence 2 ADCSequenceStepConfigure(ADC0_BASE, 2, 0, ADC_CTL_CH0 | ADC_CTL_CMP0); ADCSequenceStepConfigure(ADC0_BASE, 2, 1, ADC_CTL_CH0); ADCSequenceStepConfigure(ADC0_BASE, 2, 2, ADC_CTL_CH0); ADCSequenceStepConfigure(ADC0_BASE, 2, 3, ADC_CTL_CH0 | ADC_CTL_IE | ADC_CTL_END); // Set up the last step and start an interrupt when the conversion is over ADCSequenceEnable(ADC0_BASE, 2); // Enable the sequence again ADCSequenceConfigure(ADC0_BASE, 2, ADC_TRIGGER_ALWAYS, 3); // Configure sequence 2 IntPrioritySet(INT_ADC0SS2, 0); // ADCIntEnable(ADC0_BASE, 2); ADCIntEnableEx(ADC0_BASE, ADC_INT_DCON_SS2); ADCIntClear(ADC0_BASE, 2); // Clear the interrupt flag // Configure the ADC comparator ADCComparatorConfigure(ADC0_BASE, 0, ADC_COMP_INT_MID_ONCE); ADCComparatorRegionSet(ADC0_BASE, 0, 136, 4095); // Set the comparator region (136 corresponds to 0.11V) ADCComparatorReset(ADC0_BASE, 0, true, true); // Reset the comparator ADCComparatorIntEnable(ADC0_BASE, 2); // Enable the comparator interrupt IntEnable(INT_ADC0SS2); // Enable the ADC sequence 2 interrupt in the NVIC IntMasterEnable(); } void InitGPIO(void) { // Enable the GPIO port for the LED (PF2) SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1); // Configure PF2 as an output GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, 0); // Initialize the LED to be off } int GetInternalTemp(void){ ADCProcessorTrigger(ADC0_BASE, 3); // Trigger the ADC conversion process. while(!ADCIntStatus(ADC0_BASE, 3, false)) {} // Wait for the interrupt flag to get set ADCIntClear(ADC0_BASE, 3); // Clear the interrupt flag ADCSequenceDataGet(ADC0_BASE, 3, TempBuf); // Get the actual data samples from ADC0 sequencer 3 // Convert the value to temperature // TEMP = 147.5 - ((75 * (VREFP - VREFN) * ADCVALUE) / 4096) // 3.3V * 10 * 75 = 2475 //13.3.6 of the TM4C123GH6PM datasheet ulTemp_ValueC = (1475 -((2475 * TempBuf[0])) / 4096)/10; return ulTemp_ValueC; } uint32_t GetVoltage(void){ uint32_t ulADC0Value[1]; ADCProcessorTrigger(ADC0_BASE, 2); // Trigger the ADC conversion process while(!ADCIntStatus(ADC0_BASE, 2, false)) {} // Wait for the interrupt flag to get set ADCIntClear(ADC0_BASE, 2); // Clear the interrupt flag ADCSequenceDataGet(ADC0_BASE, 2, VoltBuf); // Get the actual data samples from ADC0 sequencer 2 ulADC0Value[0] = (VoltBuf[0] + VoltBuf[1] + VoltBuf[2] + VoltBuf[3] + 2)/4; return ulADC0Value[0]; } void IntToFloat(uint32_t intV){ float fVoltage; fVoltage = (intV * 3.3)/4096 * VOLTAGE_CALIBRATION_FACTOR; VoltIntegerPart = (int32_t) fVoltage; VoltFractionPart = (int32_t) (fVoltage * 1000.0f); VoltFractionPart = VoltFractionPart - (VoltIntegerPart * 1000); if (VoltFractionPart < 0){ VoltFractionPart *= -1; } } void ADC0Seq2Handler(void){ // IntMasterDisable(); // uint32_t ulStatus = ADCIntStatus(ADC0_BASE, 2, true); // uint32_t comparatorStatus = ADCComparatorIntStatus(ADC0_BASE); uint32_t status; status = ADCComparatorIntStatus(ADC0_BASE); ADCComparatorIntClear(ADC0_BASE, status); if ((ADCSequenceDataGet(ADC0_BASE, 2, VoltBuf) >= 136) & status) { GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, GPIO_PIN_1); } if ((ADCSequenceDataGet(ADC0_BASE, 2, VoltBuf) < 136) & status) { GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, 0); } } void main(void) { SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); // System clock: 16*12.5/2.5 = 80MHz (MAX) InitGPIO(); //// change later InitADC(); InitUART(); while(1){ tempC = GetInternalTemp(); tempF = (1.8 * ulTemp_ValueC) + 32; // Celsius to Fahrenheit voltage = GetVoltage(); IntToFloat(voltage); UARTprintf("Voltage = %3d.%03dV\n", VoltIntegerPart, VoltFractionPart); UARTprintf("Temperature = %3d°C / %3d°F\n", tempC, tempF); SysCtlDelay(SysCtlClockGet() / 3); // Delay for about 2 seconds } }
Scott、您好!
此问题是否已得到解决? 我现在将结束该主题。 如果您有任何更新、您可以再次写入此帖子、该主题将使其状态更改为"已打开"。