本帖最后由 Justice_Gao 于 2017-7-8 11:00 编辑
今天周末,空下来给大家分享一下MAX32630的ADC采样程序,包括中断式和非中断式。
首先,我们来比较一下STM32F4与MAX32630在ADC方面的区别:
STM32F4:
(1)12位ADC
(2)支持DMA
(3)每个ADC通道自带数据寄存器
(4)最大转换速率2.4MHz
MAX32630:
(1)10位ADC
(2)不支持DMA
(3)每个ADC通道共用一个数据寄存器
(4)最大转换速率8MHz
下面给出非中断式和中断式的ADC采样程序
- /***** Includes *****/
- #include <stdio.h>
- #include <stdint.h>
- #include "mxc_config.h"
- #include "led.h"
- #include "adc.h"
- #include "nhd12832.h"
- #include "board.h"
- #include "max14690.h"
- #include "tmr_utils.h"
- /***** Definitions *****/
- const max14690_cfg_t max14690_cfg2 = {
- .ldo2mv = 3300, /**< 3.3v in mV, connected to VDDB */
- .ldo2mode = MAX14690_LDO_MPC1, /**< Enalbe LDO2 when +5v is present on VBUS */
- .ldo3mv = 3300, /**< 3.3v is L3OUT -- optional */
- .ldo3mode = MAX14690_LDO_ENABLED /**< Enable the LDO. */
- };
- #define CLOCK 23
- /*------------------------------------------------------------
- usÑóê±oˉêy
- ------------------------------------------------------------*/
- void delay_us(uint32_t us)
- {
- uint32_t n;
- while(us--)for(n=0;n<CLOCK;n++);
- }
- /*------------------------------------------------------------
- msÑóê±oˉêy
- ------------------------------------------------------------*/
- void delay_ms(uint32_t ms)
- {
- while(ms--)delay_us(1000);
- }
- /* Change to #undef USE_INTERRUPTS for polling mode */
- #define USE_INTERRUPTS 1
- //#undef USE_INTERRUPTS 注释掉为中断式,不注释则为非中断式
- /***** Globals *****/
- #ifdef USE_INTERRUPTS
- volatile unsigned int adc_done = 0;
- #endif
- /***** Functions *****/
- #ifdef USE_INTERRUPTS
- void AFE_IRQHandler(void)
- {
- ADC_ClearFlags(MXC_F_ADC_INTR_ADC_DONE_IF);
- /* Signal bottom half that data is ready */
- adc_done = 1;
-
- return;
- }
- #endif
- /* ************************************************************************* */
- void ADC0_StartConvert(mxc_adc_chsel_t channel, unsigned int adc_scale, unsigned int bypass)
- {
- uint32_t ctrl_tmp;
- /* Clear the ADC done flag */
- ADC_ClearFlags(MXC_F_ADC_INTR_ADC_DONE_IF);
- MXC_ADC->intr |= MXC_F_ADC_INTR_ADC_DONE_IE;
- /* Insert channel selection */
- ctrl_tmp = MXC_ADC->ctrl;
- ctrl_tmp &= ~(MXC_F_ADC_CTRL_ADC_CHSEL);
- ctrl_tmp |= ((channel << MXC_F_ADC_CTRL_ADC_CHSEL_POS) & MXC_F_ADC_CTRL_ADC_CHSEL);
-
- /* Clear channel configuration */
- ctrl_tmp &= ~(MXC_F_ADC_CTRL_ADC_REFSCL | MXC_F_ADC_CTRL_ADC_SCALE | MXC_F_ADC_CTRL_BUF_BYPASS);
- /* ADC reference scaling must be set for all channels but two*/
- if ((channel != ADC_CH_VDD18) && (channel != ADC_CH_VDD12)) {
- ctrl_tmp |= MXC_F_ADC_CTRL_ADC_REFSCL;
- }
- /* Finalize user-requested channel configuration */
- if (adc_scale || channel > ADC_CH_3) {
- ctrl_tmp |= MXC_F_ADC_CTRL_ADC_SCALE;
- }
- if (bypass) {
- ctrl_tmp |= MXC_F_ADC_CTRL_BUF_BYPASS;
- }
-
- /* Write this configuration */
- MXC_ADC->ctrl = ctrl_tmp;
-
- /* Start conversion */
- MXC_ADC->ctrl |= MXC_F_ADC_CTRL_CPU_ADC_START;
- }
- int main(void)
- {
- uint16_t adc_val[4];
- unsigned int overflow[4];
- uint8_t fmtstr[40];
- /* Initialize ADC */
- ADC_Init();
- MAX14690_Init(&max14690_cfg2);
-
- #ifdef USE_INTERRUPTS
- NVIC_EnableIRQ(AFE_IRQn);
- #endif
-
- while(1) {
- /* Convert channel 0 */
- #ifdef USE_INTERRUPTS
- adc_done = 0;
- ADC0_StartConvert(ADC_CH_0, 0, 1);
- while (!adc_done);
- #else
- ADC_StartConvert(ADC_CH_0, 0, 1);
- #endif
- overflow[0] = (ADC_GetData(&adc_val[0]) == E_OVERFLOW ? 1 : 0);
- /* Delay for 1/4 second before next reading */
- TMR_Delay(MXC_TMR0, MSEC(250));
- }
- }
复制代码
用KEIL开发的小伙伴们需要注意的几个问题是:
(1)//#undef USE_INTERRUPTS 注释掉为中断式,不注释则为非中断式
(2)ADC的参考电压为内部参考电压1.2V
(3)
ADC源代码中断式采样会出现死循环,原因在于ADC_ClearFlags(MXC_F_ADC_INTR_ADC_DONE_IF);这条语句把ADC中断使能也清零了,如图所示,adc_done_ie清零,无法进入中断,程序会一直while (!adc_done);死循环。在源代码的void ADC0_StartConvert(这是我自己定义的函数,源代码中的为void ADC_StartConvert)中,在ADC_ClearFlags(MXC_F_ADC_INTR_ADC_DONE_IF);后加一条语句MXC_ADC->intr |= MXC_F_ADC_INTR_ADC_DONE_IE;,重新使能ADC中断,编译后测试成功
下次我给大家分享一下如何配置ADC通道的电压测量范围,主要有四种测量范围:(1)0~0.6V;(2)0~1.2V;(3)0~3V;(4)0~6V(AIN0和AIN1最大容忍电压为5V)。今天周末,休息一下。。。。。。
求管理员加个精吧,分享这么多不容易呀