完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
嗨,我正在使用PIC32 MX XLP开发工具包(在DeV板上的MCE:PIC32 MX27 4F256D),并且我需要通过ADC以非常高的速率读取数据,理想地是1 MSPS。根据我对数据表的阅读,这应该是可能的。作为第一步,我试图让ADC以接近1 MSPS的速率读取16个样本,然后产生一个中断。我使用的是12 MHz的转换时钟源,3 TAD的采样。我的系统时钟使用PLL设置为72兆赫。我认为这应该给我一个800 kSPS的吞吐量,但我观察到一个低得多的采样率。当我输入一个1千赫的三角波时,我看到混叠,而且每个周期的样本比我预期的要少得多。我显然错过了一些东西,但我不能确定我做错了什么。我的代码是使用MPLAB和谐来生成的,我使用MPLAB V3.15和XC32 V2.05编译器。我查看了MPLAB中的示例代码作为我的代码的参考。我已经尝试了几种不同的东西,包括外部晶体振荡器和RC振荡器作为时钟源,ADC的不同输入引脚,不同的电压基准,并与时钟设置一起播放,但我一直无法实现更高的采样率。我能够用时钟输出确认系统时钟至少实际上是在72 MHz。我的ADC配置代码如下:这里是我在ADC中断中打印ADC值的代码:有没有其他人遇到类似的问题?我真的很感激任何建议!谢谢!
以上来自于百度翻译 以下为原文 Hi, I'm working with a PIC32MX XLP development kit (MCU on the Dev Board: PIC32MX274F256D) and I need to read data in through the ADC at a very high rate, ideally 1 MSPS. According to my reading of the datasheet this should be possible. As a first step I'm trying to get the ADC to read 16 samples at a rate close to 1 MSPS and then generate an interrupt. I'm using a conversion clock source of 12 MHz and sampling for 3 Tad. My system clock is set to 72 MHz using the PLL. I think this should give me a throughput of 800 KSPS, but I observe a much lower sampling rate. When I input a 1 KHz triangle wave I see aliasing and I get far fewer samples per period than I expect. I'm clearly missing something, but I can't figure out what I'm doing wrong. My code was generated using MPLAB hARMony and I'm using MPLAB v3.15 with the XC32 V2.05 compiler. I looked at the example code in MPLAB as a reference for my code. I've tried several different things including both the external crystal oscillator and RC oscillator as the clock source, different input pins for the ADC, different voltage references and playing around with the clock settings, but I've been unable to achieve a higher sampling rate. I was able to confirm using the clock output that the system clock at least is in fact at 72 MHz. My ADC configuration code is below: void DRV_ADC_Initialize(void) { /* Select Clock Source */ PLIB_ADC_ConversionClockSourceSelect(DRV_ADC_ID_1, ADC_CLOCK_SOURCE_PERIPHERAL_BUS_CLOCK); /* Select Clock Prescaler */ PLIB_ADC_ConversionClockSet(DRV_ADC_ID_1, SYS_CLK_BUS_PERIPHERAL_1, 12000000); /* Select Power Mode */ PLIB_ADC_StopInIdleDisable(DRV_ADC_ID_1); /* Select Voltage Reference */ PLIB_ADC_VoltageReferenceSelect(DRV_ADC_ID_1, ADC_REFERENCE_VDD_TO_AVSS); /* Sampling Selections */ /* Enable Auto Sample Mode */ PLIB_ADC_SampleAutoStartEnable(DRV_ADC_ID_1); /* Sample Acquisition Time (Auto Sample Mode) */ PLIB_ADC_SampleAcquisitionTimeSet(DRV_ADC_ID_1, 3); /* Select Sampling Mode */ PLIB_ADC_SamplingModeSelect(DRV_ADC_ID_1, ADC_SAMPLING_MODE_MUXA); /* Number of Samples Per Interrupt */ PLIB_ADC_SamplesPerInterruptSelect(DRV_ADC_ID_1, ADC_15SAMPLES_PER_INTERRUPT); /* Conversion Selections */ /* Select Trigger Source */ PLIB_ADC_ConversionTriggerSourceSelect(DRV_ADC_ID_1, ADC_CONVERSION_TRIGGER_INTERNAL_COUNT); /* Select Result Format */ PLIB_ADC_ResultFormatSelect(DRV_ADC_ID_1, ADC_RESULT_FORMAT_INTEGER_16BIT); /* Buffer Mode */ PLIB_ADC_ResultBufferModeSelect(DRV_ADC_ID_1, ADC_BUFFER_MODE_ONE_16WORD_BUFFER); /* Channel Selections */ /* MUX A Negative Input Select */ PLIB_ADC_MuxChannel0InputNegativeSelect(DRV_ADC_ID_1, ADC_MUX_A, ADC_INPUT_NEGATIVE_VREF_MINUS); /* MUX A Positive Input Select */ PLIB_ADC_MuxChannel0InputPositiveSelect(DRV_ADC_ID_1, ADC_MUX_A, ADC_INPUT_POSITIVE_AN3); /* Initialize ADC Interrupt */ PLIB_INT_SourceFlagClear(INT_ID_0, INT_SOURCE_ADC_1); PLIB_INT_SourceEnable(INT_ID_0, INT_SOURCE_ADC_1); PLIB_INT_VectorPrioritySet(INT_ID_0, INT_VECTOR_AD1, INT_PRIORITY_LEVEL1); PLIB_INT_VectorSubPrioritySet(INT_ID_0, INT_VECTOR_AD1, INT_SUBPRIORITY_LEVEL0); } Here is my code for printing the ADC values in the ADC interrupt: void __ISR(_ADC_VECTOR, ipl1AUTO) _IntHandlerDrvAdc(void) { /* Clear ADC Interrupt Flag */ for(i = 0; i < 16; i++){ /*printf("ADC Result 1 %u = %ur", i, adc_buffer1);*/ //printf("%ur", ADC1BUF0); adc_buffer1 = DRV_ADC_SamplesRead(i); printf("%ur", adc_buffer1); } PLIB_INT_SourceFlagClear(INT_ID_0, INT_SOURCE_ADC_1); } Has anyone else run into a similar issue? I would really appreciate any suggestions! Thanks! |
|
相关推荐
6个回答
|
|
如果CPU运行在72MHz,采样率为1MSPs,那么处理每一个样本的时间就很短,其中大部分可能仅由中断开销占用。打印字符串会使你的数量级减慢(也就是说,你打印到哪里?)如果它是一个串行端口,你可以计算打印格式字符串需要花费多长时间。更不用说打印字符串,或者在ISR中做任何多余的工作是一个非常糟糕的想法。无论如何,你应该真正地考虑使用DMA来读取ADC,只是为了摆脱中断开销。但是你也需要考虑实际消耗你正在生成的数据。如果你没有时间来处理你正在生成的数据,那么你是否能达到这个神奇的1MSPS标记并不重要。
以上来自于百度翻译 以下为原文 With a CPU running at 72MHz and a sample rate of 1Msps you will have very little time to process each sample, most of which will probably be eaten just by the interrupt overhead. Printing strings will make you orders of magnitudes slower (also, where are you printing to? If it's a serial port you can calculate how long it will take just to print the formatted string). Not to mention that printing strings, or doing any superfluous work in an ISR is a very bad idea anyway. You should really be looking into using DMA for reading the ADC, just to get rid of the interrupt overhead. But you also need to take into account actually consuming the data you're generating. If you don't have time to process the data you're generating, it doesn't matter if you manage to hit that magic 1Msps mark or not. |
|
|
|
非常感谢你的回复。我听到你说的数据处理和使用的DMA和中断开销时间。实际上,我使用DMA实现了相同的代码,将数据直接写入一个大缓冲区(这里有一个很好的示例代码)。不幸的是,当使用上面描述的DMA时,我有相同的精确采样率问题。因此,我返回到只使用ADC来查看问题是否与DMA或ADC有关。当我提到我的文章中的采样率时,我只指在缓冲区之间的16个数据点之间的中断,正如你所说的,我期望在我的数据中有很大的差距,因为在我的例子中需要运行ISR/打印数据的时钟周期。T(再次,只查看在中断之间填充的缓冲区中的16个数据段)。一旦我能用ADC解决这个问题,我将再次按照你的建议来执行DMA。关于如何修复ADC问题有什么建议吗?谢谢!
以上来自于百度翻译 以下为原文 Thanks very much for your response. I hear what you are saying about the data processing and using the DMA and the interrupt overhead time. I actually have implemented the same code using the DMA to write my data directly to a large buffer (there is a good piece of example code for this). Unfortunately, I had the same exact sampling rate issue when using the DMA as described above. Thus, I reverted back to using only the ADC to see if the issue was with the DMA or the ADC. When I refer to sampling rate in my post I'm only referring to the 16 datapoints in the buffer between interrupts, as you state I expect large gaps in my data because of the clock cycles needed to run the ISR/print the data in my case. There is still some issue with the ADC sampling rate that I can't work out (again, looking only at the 16 datapoints that should be in the buffer that is filled between interrupts). Once I can figure out this issue with the ADC I will again implement the DMA as you recommend. Any suggestions on how to fix the ADC issue? Thanks! |
|
|
|
|
|
|
|
谢谢你的建议。但不幸的是,这不是我所面临的问题。我确实理解,我所展示的代码的配置方式将运行效率低下。我现在正在使用ISR的唯一原因是因为我有ADC和DMA的采样率问题,我想知道这个问题是由于ADC还是DMA引起的,所以我尝试了ADC本身,仍然有这个问题(尽管我承认用ON)更难查看采样率。这是我的代码ADC DMA代码。同样,我认为这是配置的方式I应该得到一个800 kSPS采样率来填充每个DMA缓冲器,然后当然是DMA中断运行时的延迟。这是我用ADC DMA尝试的代码版本。我打印了ISR中的缓冲区。通过查看从三角波输入获得的数据,可以清楚地看出ADC在800 kSPS附近没有采样,查看数据点的数量,看起来它甚至可以运行在小于1 kSPS的范围内。不幸的是,我仍然找不到我的错误。如上所述,我并不担心DMA ISR的任何延迟。在我的实际应用中,ISR例程将要短得多,我只在这里打印测试数据。ADC配置:DMA配置:关于我可能在配置中出了什么问题的任何想法?我想我的下一步是尝试手动配置所有寄存器,而不是使用PLIB函数。谢谢!
以上来自于百度翻译 以下为原文 Thanks for the advice. But, unfortunately that's not at all the issue that I'm having. I do understand that the way the code that I've shown is configured it will run inefficiently. The only reason I'm working with the ISR right now is because I had a sampling rate issue with the ADC and the DMA and I wanted to see if the problem was due to the ADC or the DMA so I tried the ADC by itself and still had the issue (though I'll admit its harder to look at the sampling rate with only 16 datapoints). Here is my code ADC DMA code. Again, I think the way this is configure I should get a 800 KSPS sampling rate for filling each DMA buffer and then of course a delay for when the DMA interrupt runs. Here is the version of the code that I tried with the ADC DMA. I printed out the buffer in the ISR. By looking at the data obtained from a triangle wave input it's clear that the ADC is sampling no where near 800 KSPS, looking at the number of data points it looks like it may be running at even less than 1 KSPS. Unfortunately, I still can't locate my error. As above, I'm not worried about any delay from the DMA ISR. In my actual application the ISR routine will be much shorter I'm only printing the data here for testing. ADC Configuration: oid DRV_ADC_Initialize(void) { /* Select Clock Source */ PLIB_ADC_ConversionClockSourceSelect(DRV_ADC_ID_1, ADC_CLOCK_SOURCE_PERIPHERAL_BUS_CLOCK); /* Select Clock Prescaler */ PLIB_ADC_ConversionClockSet(DRV_ADC_ID_1, SYS_CLK_BUS_PERIPHERAL_1, 12000000); /* Select Power Mode */ PLIB_ADC_StopInIdleDisable(DRV_ADC_ID_1); /* Select Voltage Reference */ PLIB_ADC_VoltageReferenceSelect(DRV_ADC_ID_1, ADC_REFERENCE_VDD_TO_AVSS); /* Sampling Selections */ /* Enable Auto Sample Mode */ PLIB_ADC_SampleAutoStartEnable(DRV_ADC_ID_1); /* Sample Acquisition Time (Auto Sample Mode) */ PLIB_ADC_SampleAcquisitionTimeSet(DRV_ADC_ID_1, 3); /* Select Sampling Mode */ PLIB_ADC_SamplingModeSelect(DRV_ADC_ID_1, ADC_SAMPLING_MODE_MUXA); /* Number of Samples Per Interrupt */ PLIB_ADC_SamplesPerInterruptSelect(DRV_ADC_ID_1, ADC_15SAMPLES_PER_INTERRUPT); /* Conversion Selections */ /* Select Trigger Source */ PLIB_ADC_ConversionTriggerSourceSelect(DRV_ADC_ID_1, ADC_CONVERSION_TRIGGER_INTERNAL_COUNT); /* Select Result Format */ PLIB_ADC_ResultFormatSelect(DRV_ADC_ID_1, ADC_RESULT_FORMAT_INTEGER_16BIT); /* Buffer Mode */ PLIB_ADC_ResultBufferModeSelect(DRV_ADC_ID_1, ADC_BUFFER_MODE_ONE_16WORD_BUFFER); /* Channel Selections */ /* MUX A Negative Input Select */ PLIB_ADC_MuxChannel0InputNegativeSelect(DRV_ADC_ID_1, ADC_MUX_A, ADC_INPUT_NEGATIVE_VREF_MINUS); /* MUX A Positive Input Select */ PLIB_ADC_MuxChannel0InputPositiveSelect(DRV_ADC_ID_1, ADC_MUX_A, ADC_INPUT_POSITIVE_AN3); } DMA Configuration: DRV_ADC_Initialize(); //Turn off the LEDs to start //BSP_LEDOff(BSP_LED_GREEN); //BSP_LEDOff(BSP_LED_RED); //BSP_LEDOff(BSP_LED_BLUE); bool appInitialized = true; //Sample code for the ADC/DMA SYS_DMA_ChannelSetup(channelHandle,SYS_DMA_CHANNEL_OP_MODE_AUTO, DMA_TRIGGER_ADC_1); //Set the cell size for the DMA transfer //PLIB_DMA_ChannelXDataSizeSelect ( DMA_ID_0, DMA_CHANNEL_1, DMA_DATA_16 ); /*PLIB_DMA_ChannelXSourceSizeSet(DMA_ID_0, DMA_CHANNEL_0, 1);*/ PLIB_DMA_ChannelXSourceSizeSet(DMA_ID_0, DMA_CHANNEL_0, 2); /*PLIB_DMA_ChannelXDestinationSizeSet(DMA_ID_0, DMA_CHANNEL_0, 256);*/ PLIB_DMA_ChannelXCellSizeSet(DMA_ID_0, DMA_CHANNEL_0, 512); /*PLIB_DMA_ChannelXCellSizeSet(DMA_ID_0, DMA_CHANNEL_0, 1);*/ PLIB_DMA_ChannelXCellSizeSet(DMA_ID_0, DMA_CHANNEL_0, 2); //PLIB_DMA_ChannelXTransferCountSet(DMA_ID_0, DMA_CHANNEL_0, 256); //SYS_DMA_ChannelTransferAdd(channelHandle, (const void*)&ADC1BUF0, 2, &adc_buffer1, 512, 2); SYS_DMA_ChannelTransferAdd(channelHandle, (const void*)&ADC1BUF0, 2, &adc_buffer1,512, 2); PLIB_DMA_ChannelXINTSourceFlagClear(DMA_ID_0, DMA_CHANNEL_0, DMA_INT_DESTINATION_DONE); //PLIB_DMA_ChannelXINTSourceFlagClear(DMA_ID_0, DMA_CHANNEL_0, DMA_INT_DESTINATION_HALF_FULL); //PLIB_DMA_ChannelXINTSourceEnable(DMA_ID_0, DMA_CHANNEL_0, DMA_INT_DESTINATION_HALF_FULL); PLIB_DMA_ChannelXINTSourceEnable(DMA_ID_0, DMA_CHANNEL_0, DMA_INT_DESTINATION_DONE); SYS_DMA_ChannelEnable(channelHandle); /* Enable ADC */ DRV_ADC_Open(); DRV_ADC_Start(); Any thoughts on where I may have gone wrong in the configuration? I think my next step is to try and configure all of the registers manually instead of the using the PLIB functions. Thanks! |
|
|
|
嗨,我尝试配置ADC通过直接编程控制寄存器,基于FRM/数据表/论坛上的一些示例代码,而不是使用PLIB函数。不幸的是,我仍然有相同的问题,我认为是采样率。我仍然使用PLIB函数配置DMA。这里是我的ADC和DMA配置代码:我也尝试使用一个外部VREF+,但这似乎并没有解决这个问题。当我将输入连接到VDD或GND时,ADC响应适当,但是当我输入一个20千赫的三角波时,我的输出中没有任何看起来像三角波的东西。我在DMA中断中打印256字长的DMA缓冲器,以便查看ADC数据,看看它是否工作。我真的不确定我在哪里绊倒。有人有什么建议吗?谢谢!
以上来自于百度翻译 以下为原文 Hi, I tried a configuring the ADC by programming the control registers directly, based on the FRM/datasheet/some sample code on the forum, instead of using the PLIB functions. Unfortunately, I still have the same issue with what I think is the sampling rate. I still configure the DMA using the PLIB functions. Here is my ADC and DMA configuration code: /*******Code to Manually Configure the ADC Registers******/ /* * Configure and enable the ADC * ensure the ADC is off before setting configuration. * If this is really needed, then there is no control with * state of other control registers in ADC peripheral. */ AD1CON1bits.ON = 0; //IEC1xDisable (INT_SOURCE_ADC_1); // (_ADC_IRQ); // Disable ADC Interrupt. AD1CON1 = 0; AD1CON2 = 0; AD1CON3 = 0; AD1CHS = 0; AD1CSSL = 0; /* * AD1PCFG Do not Touch AD1 Pin Configuration register here, * reset default is Analog state. * Digital ports on Port B may already be configured! */ AD1CON1bits.SIDL = 1; //Stop ADC operation in idle mode /* Output integer format | trigger mode auto | enable autosample */ AD1CON1bits.FORM = 0; // 16 bit unsigned integer format. AD1CON1bits.SSRC = 7; // Auto Convert //AD1CON1bits.CLRASAM = 1; // Stop when samples converted. AD1CON1bits.CLRASAM = 0; // Normal operation. Buffer will be overwritten //AD1CON1bits.ASAM = 0; // Not enable Automatic sampling yet. AD1CON1bits.ASAM = 1; // Enable automatic sampling. /* ADC ref external | disable offset test | disable scan mode | perform 1 samples | use dual buffers | use alternate mode */ //AD1CON2bits.VCFG = 4; // Internal voltage reference AVdd, AVss //AD1CON2bits.VCFG = 0; // Internal voltage reference AVdd, AVss AD1CON2bits.VCFG = 1; // External voltage reference Vref+ and Vref- AD1CON2bits.OFFCAL = 0; // Offset calibration disable. AD1CON2bits.CSCNA = 0; // Input Scan //AD1CON2bits.CSCNA = 1; // Do not scan inputs //AD1CON2bits.SMPI = 5; // Number of conversions before Interrupt. AD1CON2bits.SMPI = 1; // Number of conversions before Interrupt. //AD1CON2bits.BUFM = 1; // Two 8-word buffers. AD1CON2bits.BUFM = 0; // One 16-word buffers. //AD1CON2bits.ALTS = 1; // Alternating Mux A and Mux B. AD1CON2bits.ALTS = 0; // Always use MUXA input selection. /* Use ADC internal clock | set sample time. */ //AD1CON3bits.ADRC = 1; // Internal AD RC clock AD1CON3bits.ADRC = 0; // Use the Peripheral bus clock AD1CON3bits.SAMC = 3; // Sample time // ADCS 00000001= TPB * 2 * (ADCS<7:0> + 1) = 4 * TPB= TAD AD1CON3bits.ADCS = 0; /* * Channels to scan with MUX A */ // configure to sample AN0 // use ground as neg ref for A | use AN0 for input A | to sample AN15 by MUX B //AD1CHSbits.CH0NB = 0; /* Channel multiplexer B negative is Vrefl */ //AD1CHSbits.CH0SB = 15; /* Channel multiplexer B positive select AN15 */ AD1CHSbits.CH0NA = 0; /* Channel multiplexer A negative is Vrefl */ AD1CHSbits.CH0SA = 3; /* Channel multiplexer A positive select AN3*/ AD1CON1bits.ON = 1; /* Enable the ADC. */ //AD1CON1bits.ASAM = 1; /**********End ADC Configuration Code***********/ bool appInitialized = true; //Sample code for the ADC/DMA SYS_DMA_ChannelSetup(channelHandle,SYS_DMA_CHANNEL_OP_MODE_AUTO, DMA_TRIGGER_ADC_1); //Set the cell size for the DMA transfer //PLIB_DMA_ChannelXDataSizeSelect ( DMA_ID_0, DMA_CHANNEL_1, DMA_DATA_16 ); /*PLIB_DMA_ChannelXSourceSizeSet(DMA_ID_0, DMA_CHANNEL_0, 1);*/ PLIB_DMA_ChannelXSourceSizeSet(DMA_ID_0, DMA_CHANNEL_0, 2); /*PLIB_DMA_ChannelXDestinationSizeSet(DMA_ID_0, DMA_CHANNEL_0, 256);*/ PLIB_DMA_ChannelXCellSizeSet(DMA_ID_0, DMA_CHANNEL_0, 512); /*PLIB_DMA_ChannelXCellSizeSet(DMA_ID_0, DMA_CHANNEL_0, 1);*/ PLIB_DMA_ChannelXCellSizeSet(DMA_ID_0, DMA_CHANNEL_0, 2); //PLIB_DMA_ChannelXTransferCountSet(DMA_ID_0, DMA_CHANNEL_0, 256); //SYS_DMA_ChannelTransferAdd(channelHandle, (const void*)&ADC1BUF0, 2, &adc_buffer1, 512, 2); SYS_DMA_ChannelTransferAdd(channelHandle, (const void*)&ADC1BUF0, 2, &adc_buffer1,512, 2); PLIB_DMA_ChannelXINTSourceFlagClear(DMA_ID_0, DMA_CHANNEL_0, DMA_INT_DESTINATION_DONE); //PLIB_DMA_ChannelXINTSourceFlagClear(DMA_ID_0, DMA_CHANNEL_0, DMA_INT_DESTINATION_HALF_FULL); //PLIB_DMA_ChannelXINTSourceEnable(DMA_ID_0, DMA_CHANNEL_0, DMA_INT_DESTINATION_HALF_FULL); PLIB_DMA_ChannelXINTSourceEnable(DMA_ID_0, DMA_CHANNEL_0, DMA_INT_DESTINATION_DONE); SYS_DMA_ChannelEnable(channelHandle); /* Enable ADC */ DRV_ADC_Open(); DRV_ADC_Start(); I also tried using an external Vref+, but that didn't seem to solve the issue. The ADC responds appropriately when I connect the input to Vdd or GND, but when I input a 20 KHz triangle wave I don't get anything that looks like a triangle wave at my output. I'm printing the 256 word long DMA buffer in the DMA interrupt in order to look at the ADC data to see if it's working. I'm really not sure where I'm tripping up. Does anyone have any suggestions? Thanks! |
|
|
|
嗨,我能联系技术支持,并得到一些帮助我的问题。毫不奇怪,问题是由于我对DMA缓冲区如何在PIC32 MX设备上工作的误解。我以前使用的是一个DSPIC33 MCU,在那些设备上,我设置两个缓冲器到乒乓之间。每个DMA中断都会交换,缓冲区正在被填充。在PIC32 MX上填充一个缓冲器,但是代码在填充缓冲器的上半部分和下半部分之间进行交换。我需要确保我已经安装了它,并且确保清除适当的中断标志(有两个标志需要清除)。如果我想使用两个缓冲器,我想我需要在每个中断中禁用和重新启用通道(即,我不能使用ChhannLyopuMoDeAuto)。我能够用32 MHz的系统时钟实现1 MSPS采样率,并且ADC转换时钟为16 MHz和TAD=3。下面是我的代码:ADC初始化:应用程序初始化显示DMA初始化:DMA中断:
以上来自于百度翻译 以下为原文 Hi, I was able to contact tech support and get some help with the issue I was having. Not surprisingly the problem was from my misunderstanding of how the DMA buffer works on the PIC32MX devices. I was previously using a dsPIC33 MCU and on those devices I setup two buffers to ping-pong between. Each DMA interrupt would swap, which buffer was being filled. On the PIC32MX one buffer is filled, but the code swaps between filling the first half and the second half of the buffer. I needed to make sure I had it setup this was and also make sure to clear the appropriate interrupt flags are cleared (there are two flags that need to be cleared). If I wanted to use two buffer I think I would need to disable and re-enable the channel at each interrupt (i.e., I could not use CHANNEL_OP_MODE_AUTO). I was able to achieve a 1 MSPS sampling rate with a system clock of 32 MHZ, and ADC conversion clock of 16 MHz and TAD = 3. Below is my code that works: ADC Initialization: void DRV_ADC_Initialize(void) { /* Select Clock Source */ PLIB_ADC_ConversionClockSourceSelect(DRV_ADC_ID_1, ADC_CLOCK_SOURCE_PERIPHERAL_BUS_CLOCK); /* Select Clock Prescaler */ PLIB_ADC_ConversionClockSet(DRV_ADC_ID_1, SYS_CLK_BUS_PERIPHERAL_1, 16000000); /* Select Power Mode */ PLIB_ADC_StopInIdleDisable(DRV_ADC_ID_1); /* Select Voltage Reference */ PLIB_ADC_VoltageReferenceSelect(DRV_ADC_ID_1, ADC_REFERENCE_VDD_TO_AVSS); /* Sampling Selections */ /* Enable Auto Sample Mode */ PLIB_ADC_SampleAutoStartEnable(DRV_ADC_ID_1); /* Sample Acquisition Time (Auto Sample Mode) */ PLIB_ADC_SampleAcquisitionTimeSet(DRV_ADC_ID_1, 3); /* Select Sampling Mode */ PLIB_ADC_SamplingModeSelect(DRV_ADC_ID_1, ADC_SAMPLING_MODE_MUXA); /* Number of Samples Per Interrupt */ PLIB_ADC_SamplesPerInterruptSelect(DRV_ADC_ID_1, ADC_1SAMPLE_PER_INTERRUPT); /* Conversion Selections */ /* Select Trigger Source */ PLIB_ADC_ConversionTriggerSourceSelect(DRV_ADC_ID_1, ADC_CONVERSION_TRIGGER_INTERNAL_COUNT); /* Select Result Format */ PLIB_ADC_ResultFormatSelect(DRV_ADC_ID_1, ADC_RESULT_FORMAT_INTEGER_16BIT); /* Buffer Mode */ PLIB_ADC_ResultBufferModeSelect(DRV_ADC_ID_1, ADC_BUFFER_MODE_ONE_16WORD_BUFFER); /* Channel Selections */ /* MUX A Negative Input Select */ PLIB_ADC_MuxChannel0InputNegativeSelect(DRV_ADC_ID_1, ADC_MUX_A, ADC_INPUT_NEGATIVE_VREF_MINUS); /* MUX A Positive Input Select */ PLIB_ADC_MuxChannel0InputPositiveSelect(DRV_ADC_ID_1, ADC_MUX_A, ADC_INPUT_POSITIVE_AN3); } App initialization showing the DMA initialization: case APP_STATE_INIT: { //Initialize the SPI DRV_SPI0_Initialize(); SPI1CONbits.SMP = 0; //AD1CON1bits.CLRASAM = 0; //Initialize the ADC DRV_ADC_Initialize(); /* Enable ADC */ DRV_ADC_Open(); DRV_ADC_Start(); /*Enable the SPI*/ DRV_SPI_Open(DRV_SPI_INDEX_0, DRV_IO_INTENT_READWRITE); //Turn off the LEDs to start BSP_LEDOff(BSP_LED_GREEN); BSP_LEDOff(BSP_LED_RED); BSP_LEDOff(BSP_LED_BLUE); bool appInitialized = true; //Sample code for the ADC/DMA SYS_DMA_ChannelSetup(channelHandle,SYS_DMA_CHANNEL_OP_MODE_AUTO, DMA_TRIGGER_ADC_1); //With basic mode the channel closes after the first interrupt fires //SYS_DMA_ChannelSetup(channelHandle,SYS_DMA_CHANNEL_OP_MODE_BASIC, DMA_TRIGGER_ADC_1); //Set the cell size for the DMA transfer PLIB_DMA_ChannelXSourceSizeSet(DMA_ID_0, DMA_CHANNEL_0, 2); PLIB_DMA_ChannelXCellSizeSet(DMA_ID_0, DMA_CHANNEL_0, 2048); PLIB_DMA_ChannelXCellSizeSet(DMA_ID_0, DMA_CHANNEL_0, 2); SYS_DMA_ChannelTransferAdd(channelHandle, (const void*)&ADC1BUF0, 2, &adc_buffer1,2048, 2); //Clear the interrupt flags PLIB_DMA_ChannelXINTSourceFlagClear(DMA_ID_0, DMA_CHANNEL_0, DMA_INT_DESTINATION_DONE); PLIB_DMA_ChannelXINTSourceFlagClear(DMA_ID_0, DMA_CHANNEL_0, DMA_INT_DESTINATION_HALF_FULL); //Enable the interrupts PLIB_DMA_ChannelXINTSourceEnable(DMA_ID_0, DMA_CHANNEL_0, DMA_INT_DESTINATION_HALF_FULL); PLIB_DMA_ChannelXINTSourceEnable(DMA_ID_0, DMA_CHANNEL_0, DMA_INT_DESTINATION_DONE); SYS_DMA_ChannelEnable(channelHandle); appData.state = APP_STATE_SERVICE_TASKS; if (appInitialized) { appData.state = APP_STATE_SERVICE_TASKS; } break; } DMA Interrupt: //DMA Interrupt service routine void __ISR(_DMA0_VECTOR, ipl1AUTO) _IntHandlerSysDmaCh0(void) { //Clear the Interrupt Flag PLIB_INT_SourceFlagClear(INT_ID_0, INT_SOURCE_DMA_0); //Sample code from Interrupt.c in the Harmony adc_pot_dma example if (PLIB_DMA_ChannelXINTSourceFlagGet(DMA_ID_0, DMA_CHANNEL_0, DMA_INT_DESTINATION_HALF_FULL)) { //clear the interrupt flag PLIB_DMA_ChannelXINTSourceFlagClear(DMA_ID_0, DMA_CHANNEL_0, DMA_INT_DESTINATION_HALF_FULL); //Set BUFFER_FLAG BUFFER_FLAG = 0; //Test code to print the buffer /*SYS_DMA_ChannelDisable(channelHandle); for(i = 0; i < 512; i++){ printf("%ur", adc_buffer1); } while(1){ ; }*/ } if (PLIB_DMA_ChannelXINTSourceFlagGet(DMA_ID_0, DMA_CHANNEL_0, DMA_INT_DESTINATION_DONE)) { //clear the interrupt flag PLIB_DMA_ChannelXINTSourceFlagClear(DMA_ID_0, DMA_CHANNEL_0, DMA_INT_DESTINATION_DONE); //Set BUFFER_FLAG BUFFER_FLAG = 1; //Test code to print the buffer /*SYS_DMA_ChannelDisable(channelHandle); for(j = 512; j < 1024; j++){ printf("%ur", adc_buffer1[j]); } while(1){ ; }*/ } SYS_DMA_Tasks(sysObj.sysDma, DMA_CHANNEL_0); return; } |
|
|
|
只有小组成员才能发言,加入小组>>
4840 浏览 9 评论
1842 浏览 8 评论
1757 浏览 10 评论
请问是否能把一个ADC值转换成两个字节用来设置PWM占空比?
2968 浏览 3 评论
请问电源和晶体值之间有什么关系吗?PIC在正常条件下运行4MHz需要多少电压?
2072 浏览 5 评论
467浏览 1评论
1120浏览 1评论
305浏览 1评论
PIC Kit3出现目标设备ID(00000000)与预期的设备ID(02c20000)不匹配。是什么原因
373浏览 0评论
268浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-5-7 05:05 , Processed in 0.996038 second(s), Total 82, Slave 65 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号