Other Parts Discussed in Thread: TM4C123GH6PM, DRV8801
器件型号: TM4C123GH6PM
主题中讨论的其他器件: DRV8801
您好:
我的定制 TM4C123GH6PM 板出现了一些(很少)的问题读数、因此我创建了一个简单的程序来隔离将在 Tiva-c tm4c123 评估板上运行的问题。
1.其中一个频道有一个不可解释的偏倚
2.通道间的串扰很小,一个影响到另一个。
问题仍然存在并且可以观察到。 发生的情况是、如果我将一个通道悬空并对另 一个通道施加 3V3、一个通道读取 3V3、另一个通道(悬空)读取 2v9、反之亦然。 在实际电路板上、没有 ADC 引脚悬空、有一个 33nf 电容器接地、电压来自 10K 电阻器。 (DRV8801 的 VPROPI 引脚)
这几乎就像过时数据停留在 ADC FIFO 中、即 ADC 的采样/保持一样。 是否有解决此问题的方法? 这在之前的论坛中讨论过、但没有在相同的设置下讨论。
也许我可以使用单个序列、从 ch3 从 ch2 采样一个? 也许我可以将一个引脚分配给 ADC0、将另一个引脚分配给 ADC1? 在试错之前、我想在这个论坛上提问。
其他发现结果:a. ADC 速度越快、交叉耦合越多。 B.单独使用 ADC0 和 ADC1 不会消除交叉耦合 C。我们实际上同时对两个通道进行采样、这将是一次又一次的中断、一个具有优先级 1、另一个具有优先级 2 — 我们可能会在 ADC 通道上引入相移。
此致、
c.
以下是我的完整代码:
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "inc/hw_gpio.h"
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "driverlib/fpu.h"
#include "driverlib/timer.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "driverlib/adc.h"
#include "utils/uartstdio.h"
#include "utils/ustdlib.h"
#define RED_LED GPIO_PIN_1 // PF1
#define GREEN_LED GPIO_PIN_3 // PF3
#define EMA_ALPHA 15.0f
#define EMA_DIV 16.0
#define ADC_MULTIPLIER 0.000805664;
uint32_t ui32SysClkFreq;
char loginfo_buffer[128];
uint32_t adc_fifo_left_load[4];
uint32_t adc_fifo_right_load[4];
volatile uint32_t adc_ch1;
volatile uint32_t adc_ch2;
volatile float ch1 = 0.0f;
volatile float ch2 = 0.0f;
volatile float avg_ch1 = 0.0f;
volatile float avg_ch2 = 0.0f;
void ADC0SS1IntHandler(void) {
MAP_ADCIntClear(ADC0_BASE, 1);
MAP_ADCSequenceDataGet(ADC0_BASE, 1, adc_fifo_right_load);
adc_ch2 = ( adc_fifo_right_load[0] + adc_fifo_right_load[1] + adc_fifo_right_load[2] + adc_fifo_right_load[3] ) / 4;
ch2 = adc_ch2 * ADC_MULTIPLIER;
avg_ch2 = ( (EMA_ALPHA * avg_ch2) + ch2 ) / EMA_DIV;
}
void ADC0SS2IntHandler(void) {
MAP_ADCIntClear(ADC0_BASE, 2);
MAP_ADCSequenceDataGet(ADC0_BASE, 2, adc_fifo_left_load);
adc_ch1 = ( adc_fifo_left_load[0] + adc_fifo_left_load[1] + adc_fifo_left_load[2] + adc_fifo_left_load[3] ) / 4;
ch1 = adc_ch1 * ADC_MULTIPLIER;
avg_ch1 = ( (EMA_ALPHA * avg_ch1) + ch1 ) / EMA_DIV;
}
void init_serial(void) {
MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
MAP_GPIOPinConfigure(GPIO_PA0_U0RX);
MAP_GPIOPinConfigure(GPIO_PA1_U0TX);
MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
MAP_UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);
MAP_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
UARTStdioConfig(0, 115200, 16000000);
}
void init_gpio(void) {
MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
MAP_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, RED_LED);
MAP_GPIOPadConfigSet(GPIO_PORTF_BASE, RED_LED, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD);
MAP_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GREEN_LED);
MAP_GPIOPadConfigSet(GPIO_PORTF_BASE, GREEN_LED, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD);
}
int main(void) {
MAP_FPUEnable();
MAP_FPULazyStackingEnable();
MAP_SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_20MHZ | SYSCTL_OSC_MAIN);
ui32SysClkFreq = MAP_SysCtlClockGet();
init_gpio();
MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); // enable ADC0
while(!SysCtlPeripheralReady(SYSCTL_PERIPH_ADC0));
MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_0 | GPIO_PIN_1); // PE0, PE1
MAP_ADCReferenceSet(ADC0_BASE, ADC_REF_INT); // Use internal reference VDDA = 3V3
MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER2); // timer2 enable
MAP_ADCSequenceConfigure(ADC0_BASE, 1, ADC_TRIGGER_TIMER, 1); // set adc trigger for sequence 1 pri 1
MAP_ADCSequenceConfigure(ADC0_BASE, 2, ADC_TRIGGER_TIMER, 2); // set adc trigger for sequence 2 pri 2
MAP_ADCSequenceStepConfigure(ADC0_BASE, 1, 0, ADC_CTL_CH2); // sequence 1 step configuration
MAP_ADCSequenceStepConfigure(ADC0_BASE, 1, 1, ADC_CTL_CH2);
MAP_ADCSequenceStepConfigure(ADC0_BASE, 1, 2, ADC_CTL_CH2);
MAP_ADCSequenceStepConfigure(ADC0_BASE, 1, 3, ADC_CTL_CH2 | ADC_CTL_IE | ADC_CTL_END);
MAP_ADCSequenceStepConfigure(ADC0_BASE, 2, 0, ADC_CTL_CH3); // sequence 2 step configuration
MAP_ADCSequenceStepConfigure(ADC0_BASE, 2, 1, ADC_CTL_CH3);
MAP_ADCSequenceStepConfigure(ADC0_BASE, 2, 2, ADC_CTL_CH3);
MAP_ADCSequenceStepConfigure(ADC0_BASE, 2, 3, ADC_CTL_CH3 | ADC_CTL_IE | ADC_CTL_END);
MAP_ADCSequenceEnable(ADC0_BASE, 1); // enable sequence 1
MAP_ADCSequenceEnable(ADC0_BASE, 2); // enable sequence 2
MAP_ADCIntClear(ADC0_BASE, 1); // interrupt clear sequence 1
MAP_ADCIntClear(ADC0_BASE, 2); // interrupt clear sequence 2
ADCIntRegister(ADC0_BASE, 1, ADC0SS1IntHandler); // register interrupt SS1
ADCIntRegister(ADC0_BASE, 2, ADC0SS2IntHandler); // register interrupt SS2
MAP_ADCIntEnable(ADC0_BASE, 1); // adc interrupt int enable
MAP_IntEnable(INT_ADC0SS1); // enable nvic interrupt
MAP_ADCIntEnable(ADC0_BASE, 2); // adc interrupt int enable
MAP_IntEnable(INT_ADC0SS2); // enable nvic interrupt
MAP_TimerConfigure(TIMER2_BASE, TIMER_CFG_A_PERIODIC); // configure timer as periodic
MAP_TimerLoadSet(TIMER2_BASE, TIMER_A, ui32SysClkFreq / 16000); // sampling at 16khz default
MAP_TimerControlTrigger(TIMER2_BASE, TIMER_A, true); // enable the ADC trigger output for Timer A
init_serial();
MAP_IntMasterEnable();
MAP_TimerEnable(TIMER2_BASE, TIMER_A); // always running, trigger is g_ADC_SAMPLING
uint8_t len = sprintf(loginfo_buffer, "SYSINIT");
UARTprintf(loginfo_buffer, len);
while(true) {
len = sprintf(loginfo_buffer, "%f %f\n", avg_ch1, avg_ch2);
UARTprintf(loginfo_buffer, len);
MAP_SysCtlDelay(100000);
}
}