楼主: nolanpeers

[求助] 飞思卡尔ADC和OLED显示问题

[复制链接]

该用户从未签到

10

主题

32

帖子

0

注册会员

Rank: 2

积分
142
最后登录
2017-7-28
 楼主| 发表于 2015-12-23 16:09:14 | 显示全部楼层
FSL_TICS_ZJJ 发表于 2015-12-22 17:10
你好!
PIT是周期性中断定时器:是一组可以用于产生中断和触发DMA通道的定时器。
LPTMR是低功耗定时器, ...

是不是我可以使用DMA方式?我是AD采集时用DMA还是SPI驱动OLED时在SPI下用DMA来传递数据到SPI?怎么用能建议下吗?非常非常感谢!
回复 支持 反对

使用道具 举报

该用户从未签到

145

主题

4926

帖子

0

金牌会员

Rank: 6Rank: 6

积分
9267
最后登录
1970-1-1
发表于 2015-12-23 17:09:47 | 显示全部楼层
nolanpeers 发表于 2015-12-23 15:57
非常感谢您的耐心回答!我用例子中的PIT例程进行AD采集,可是我的OLED刷新程序还是会影响采样的频率,我用 ...

你PIT和ADC是否用中断了 ?
不用中断肯定会影响的。
回复 支持 反对

使用道具 举报

该用户从未签到

10

主题

32

帖子

0

注册会员

Rank: 2

积分
142
最后登录
2017-7-28
 楼主| 发表于 2015-12-23 17:19:54 | 显示全部楼层
本帖最后由 nolanpeers 于 2015-12-23 17:21 编辑
FSL_TICS_ZJJ 发表于 2015-12-23 17:09
你PIT和ADC是否用中断了 ?
不用中断肯定会影响的。

是在中断中刷新还是在中断中采集?我用的如图中的例子,飞思卡尔官方的例子,这个有中断没有中断我看不懂。我就用了,发现AD采集可以,是1KHz的频率。

使用PIT例子

使用PIT例子
回复 支持 反对

使用道具 举报

该用户从未签到

10

主题

32

帖子

0

注册会员

Rank: 2

积分
142
最后登录
2017-7-28
 楼主| 发表于 2015-12-23 19:53:40 | 显示全部楼层
FSL_TICS_ZJJ 发表于 2015-12-23 17:09
你PIT和ADC是否用中断了 ?
不用中断肯定会影响的。

大神,您有没有PIT或者PDB的中断采集AD的模板程序啊?我实在弄不来。
回复 支持 反对

使用道具 举报

该用户从未签到

10

主题

32

帖子

0

注册会员

Rank: 2

积分
142
最后登录
2017-7-28
 楼主| 发表于 2015-12-23 20:51:36 | 显示全部楼层
FSL_TICS_ZJJ 发表于 2015-12-23 17:09
你PIT和ADC是否用中断了 ?
不用中断肯定会影响的。

如何开启中断,我不会啊,文档看不懂,例子也看不懂,我菜的不行,求大神给个标准例子行不?我在上面改改,消化消化!
回复 支持 反对

使用道具 举报

该用户从未签到

145

主题

4926

帖子

0

金牌会员

Rank: 6Rank: 6

积分
9267
最后登录
1970-1-1
发表于 2015-12-24 11:06:21 | 显示全部楼层
nolanpeers 发表于 2015-12-23 17:19
是在中断中刷新还是在中断中采集?我用的如图中的例子,飞思卡尔官方的例子,这个有中断没有中断我看不懂 ...

楼主你好,
你这个代码是带中断的,其实数据已经在中断中取出来了,你没有必要再在while中调用去取数据,这样浪费时间。
你看,数据已经放到g_AdcValueInt数组了,你可以直接在中断中加一个标志,或者g_AdcTestCallback中加标志。
64.jpg
然后根据标志判断是否是你需要发送到OLED中的数据。

回复 支持 反对

使用道具 举报

该用户从未签到

10

主题

32

帖子

0

注册会员

Rank: 2

积分
142
最后登录
2017-7-28
 楼主| 发表于 2015-12-24 11:23:29 | 显示全部楼层
本帖最后由 nolanpeers 于 2015-12-24 11:25 编辑
FSL_TICS_ZJJ 发表于 2015-12-24 11:06
楼主你好,
你这个代码是带中断的,其实数据已经在中断中取出来了,你没有必要再在while中调用去取数据, ...

带中断了吗?可是官方例子中也没有中断函数的调用。而且给的例子他是在while中取数值的。没看到有中断函数调用么。官方例子如下:

///////////////////////////////////////////////////////////////////////////////
// Includes
///////////////////////////////////////////////////////////////////////////////

// Standard C Included Files
#include <string.h>
#include <stdio.h>
// SDK Included Files
#include "fsl_debug_console.h"
#include "adc_hw_trigger.h"
#include "fsl_adc16_driver.h"

///////////////////////////////////////////////////////////////////////////////
// Definitions
///////////////////////////////////////////////////////////////////////////////

#define ADC_12BIT_MAXVALUE (0x1000U)
#define RATIO (ADC_12BIT_MAXVALUE/CHART_ROWS)

/*! @brief Define the sparse matrix node for display wave */
#pragma pack(1)
typedef struct sparse_node
{
    struct sparse_node *next; /*!< next node */
    uint8_t value; /*!< the sample index */

} sparse_node_t, *sparse_node_ptr;
#pragma pack()

///////////////////////////////////////////////////////////////////////////////
// Prototypes
///////////////////////////////////////////////////////////////////////////////

extern void init_trigger_source(uint32_t instance);
extern void deinit_trigger_source(uint32_t instance);

#ifdef USE_DAC_OUT_AS_SOURCE
extern void dac_gen_wave(void);
extern void dac_stop_wave(void);
#endif

extern void ADC_TEST_InstallCallback(uint32_t instance, uint32_t chnGroup, void (*callbackFunc)(void) );
extern uint16_t ADC_TEST_GetConvValueRAWInt(uint32_t instance, uint32_t chnGroup);

///////////////////////////////////////////////////////////////////////////////
// Variables
///////////////////////////////////////////////////////////////////////////////

SIM_Type * gSimBase[] = SIM_BASE_PTRS; // SIM base address
static volatile bool gAdcDone = false; // sync object for adc convert result
static sparse_node_ptr gChartHead[CHART_ROWS]; // sparse matrix head
static sparse_node_t gChartNodes[NR_SAMPLES]; // sparse matrix nodes
static uint32_t gFreeNode = 0; // free node slot index for gChartNodes[]
static volatile uint8_t gCurChan = 0;

///////////////////////////////////////////////////////////////////////////////
// Code
///////////////////////////////////////////////////////////////////////////////

/*!
* @brief ADC channel0 callback for fetching sample data.
*/
static void adc_chn0_isr_callback(void)
{
    gCurChan = 0;
    gAdcDone = true;
}

/*!
* @brief ADC channel1 callback for fetching sample data.
*/
static void adc_chn1_isr_callback(void)
{
    gCurChan = 1;
    gAdcDone = true;
}

/*!
* @brief Initialize the ADCx for HW trigger.
*
* @param instance The ADC instance number
*/
static int32_t init_adc(uint32_t instance)
{
#if FSL_FEATURE_ADC16_HAS_CALIBRATION//=1³ÉÁ¢
    adc16_calibration_param_t adcCalibraitionParam;//ÉùÃ÷Ò»¸ö½á¹¹Ìåto configure the ADC16 module calibration
#endif
    adc16_converter_config_t adcUserConfig;//ÅäÖÃADC
    adc16_chn_config_t adcChnConfig;//ÅäÖÃADCͨµÀ

    ADC16_DRV_StructInitUserConfigDefault(&adcUserConfig);//ÅäÖÃADCµÄÉèÖÃ
#if (  defined(FRDM_KL43Z)   /* CPU_MKL43Z256VLH4 */ \
    || defined(TWR_KL43Z48M) /* CPU_MKL43Z256VLH4 */ \
    || defined(FRDM_KL27Z)   /* CPU_MKL27Z64VLH4  */ \
    )
    adcUserConfig.refVoltSrc = kAdc16RefVoltSrcOfValt;//ÉèÖòο¼µçѹÀàÐÍΪ
#endif
    ADC16_DRV_Init(instance, &adcUserConfig);//¿ªÊ¼ADת»»

#if FSL_FEATURE_ADC16_HAS_CALIBRATION  //=1£¬³ÉÁ¢
    // Auto calibraion.
    ADC16_DRV_GetAutoCalibrationParam(instance, &adcCalibraitionParam);
    ADC16_DRV_SetCalibrationParam(instance, &adcCalibraitionParam);
#endif

    // Initialization ADC for
    // 12bit resolution, interrrupt mode, hw trigger enabled.
    // normal convert speed, VREFH/L as reference,
    // disable continuouse convert mode.
    ADC16_DRV_StructInitUserConfigDefault(&adcUserConfig);
    adcUserConfig.hwTriggerEnable = true;
    adcUserConfig.continuousConvEnable = false;
#if (  defined(FRDM_KL43Z)   /* CPU_MKL43Z256VLH4 */ \
    || defined(TWR_KL43Z48M) /* CPU_MKL43Z256VLH4 */ \
    || defined(FRDM_KL27Z)   /* CPU_MKL27Z64VLH4  */ \
    )
    adcUserConfig.refVoltSrc = kAdc16RefVoltSrcOfValt;
#endif
    ADC16_DRV_Init(instance, &adcUserConfig);

    // Install Callback function into ISR
    ADC_TEST_InstallCallback(instance, 0U, adc_chn0_isr_callback);
    ADC_TEST_InstallCallback(instance, 1U, adc_chn1_isr_callback);

    adcChnConfig.chnIdx = (adc16_chn_t)ADC_INPUT_CHAN;//ÉèÖÃADCÊäÈëͨµÀ
#if FSL_FEATURE_ADC16_HAS_DIFF_MODE//=1³ÉÁ¢
    adcChnConfig.diffConvEnable = false;  //½ûÖ¹²î·ÖÊäÈë
#endif /* FSL_FEATURE_ADC16_HAS_DIFF_MODE */
    adcChnConfig.convCompletedIntEnable = true;//ÔÊÐíÖжÏ

    // Configure channel0
    ADC16_DRV_ConfigConvChn(instance, 0U, &adcChnConfig);

    // Configure channel1, which is used in PDB trigger case
    ADC16_DRV_ConfigConvChn(instance, 1U, &adcChnConfig);

    return 0;
}

/*!
* @brief Reset the sparse matrix
*/
void sparse_reset(void)
{
    memset(gChartHead, 0, sizeof(gChartHead));
    memset(gChartNodes, 0, sizeof(gChartNodes));
    gFreeNode = 0;
}

/*!
* @brief insert a node into the sparse matrix
*
* @param index The amplitude index
* @param value The sample count value
*/
void sparse_insert(uint32_t index, uint8_t value)
{
    sparse_node_ptr p = gChartHead[index];

    assert(gFreeNode < NR_SAMPLES);

    if (!p)
    {
        gChartHead[index] = &gChartNodes[gFreeNode++];
        gChartHead[index]->value = value;
    }
    else
    {
        while (p->next != NULL)
        {
            p = p->next;
        }
        p->next = &gChartNodes[gFreeNode++];
        p->next->value = value;
    }
}

/*!
* @brief Main demo function
*/
int main(void)
{
    uint8_t cnt;
    int32_t row;

    // init the hardware board
    hardware_init();

    PRINTF("\r\nadc_hw_trigger demo running...\r\n\r\n");

#ifdef USE_DAC_OUT_AS_SOURCE
    // use DAC to generate the sine wave
    dac_gen_wave();
#else
    // If no DAC can be use, then a function generator should
    // be used to generate a signal wave, and connect to ADC input
#endif

    // initialize the ADC
    if (init_adc(ADC_INST))
    {
        PRINTF("Failed to do the ADC init\n");
        return -1;
    }

    // setup the HW trigger source
    init_trigger_source(ADC_INST);

    // init the print chart array
    sparse_reset();

    for (cnt = 0; cnt < NR_SAMPLES; cnt++)
    {
        uint16_t result;
        double tmpRatio;

        while (gAdcDone != true)
        {
            ;
        }

        result = ADC16_DRV_GetConvValueRAW(ADC_INST, (uint32_t)gCurChan);
        gAdcDone = false;

        // insert the sample data into the sparse matrix
        tmpRatio = (double)result / RATIO;
        row = (int32_t)tmpRatio;
        if (row >= CHART_ROWS)
        {
            row = CHART_ROWS - 1;
        }
        // fill one samples into sparse matrix
        sparse_insert(row, cnt);
    }

    // print the chart
    for (row = CHART_ROWS - 1; row >= 0; row --)
    {
        sparse_node_ptr p = gChartHead[row];
        uint32_t last = 0;

        while (p)
        {
            for (; last < p->value; last++)
            {
                PRINTF(" ");
            }
            PRINTF("*");
            p = p->next;
            last++;
        }
        PRINTF("\r\n");
    }

    // disable the adc0
    ADC16_DRV_Deinit(ADC_INST);
    // disable hw trigger source
    deinit_trigger_source(ADC_INST);
#ifdef USE_DAC_OUT_AS_SOURCE
    // disable dac source
    dac_stop_wave();
#endif

    while(1)
    {}
}


在循环中中取得数值

在循环中中取得数值
回复 支持 反对

使用道具 举报

该用户从未签到

145

主题

4926

帖子

0

金牌会员

Rank: 6Rank: 6

积分
9267
最后登录
1970-1-1
发表于 2015-12-24 12:39:56 | 显示全部楼层
nolanpeers 发表于 2015-12-24 11:23
带中断了吗?可是官方例子中也没有中断函数的调用。而且给的例子他是在while中取数值的。没看到有中断函数 ...

楼主是想用PIT中断对吧。
那么就需要使能PIT中断, pit_trigger.c中void init_trigger_source(uint32_t adcInstance)
    pit_user_config_t pitUserInit = {
        .isInterruptEnabled = true,
        .periodUs = freqUs,
    };
然后添加PIT中断服务函数,void PIT0_IRQHandler(void),比如        PIT_TFLG0 |= PIT_TFLG_TIF_MASK;
在函数中做清除PIT中断标志。
这样就不需要你在while中做调用ADC的函数了。
你先照着做下,如果还是不行,我会帮你调试添加个。


回复 支持 反对

使用道具 举报

该用户从未签到

10

主题

32

帖子

0

注册会员

Rank: 2

积分
142
最后登录
2017-7-28
 楼主| 发表于 2015-12-25 10:17:36 | 显示全部楼层
本帖最后由 nolanpeers 于 2015-12-25 10:38 编辑
FSL_TICS_ZJJ 发表于 2015-12-24 11:06
楼主你好,
你这个代码是带中断的,其实数据已经在中断中取出来了,你没有必要再在while中调用去取数据, ...

大神,我使用的是C:\Freescale\KSDK_1.2.0\examples\frdmk22f\demo_apps\adc_hw_trigger\pit\mdk:这个例子main函数只粘贴了部分,为何我在中断中将x2和x1的差值赋给数组a的操作不行?main函数中打印不出来,而且中断也停不了。如果不进行数组操作,采集和显示处于正常状态,数组打印出来都是空的,虽然采集和显示可以正常,不过我感觉是巧合,其实那里还是有错误的,就是我发现不了。g_AdcValueInt[instance][chnGroup] 这个值我该如何调取?绿色字体部分是我想采集10000个点后,停止AD中断采集所采取的方法,是不是很low,我不知道如何关断,所以就这么弄,不知道对不对,反正是停下来了,不过我从示波器里观察下来好像count等于10000时有那么一段时间是没停止采集,还要再过一会,采集才停止。我想知道正确的方法和步骤。谢谢!



uint32_t    a[10000];

main
{
    for (cnt = 0; cnt <10000; cnt++)
    {
        while (gAdcDone != true)
           {;}
        j++
        if(f)
        {
                x1=((float)(0xffff&x2)*0.0503)/1000;
                 draw_num(c,x1); ///*     OLED显示   */
                c--;
                if(c==0)
                        c=127;
        }
       if(stop)
        {
                cnt=10000;
        }

                                                
       gAdcDone = false;
    }
    // disable the adc0
    ADC16_DRV_Deinit(ADC_INST);
    // disable hw trigger source
    deinit_trigger_source(ADC_INST);

    for(i=0;i<10000;i++)
        printf("%-10.5lf",DEV_1st);
}


/* User-defined ADC ISR. */
static void ADC_TEST_IRQHandler(uint32_t instance)
{
    uint32_t chnGroup=0,x1=0,x2=0;
        
    g_AdcValueInt[instance][chnGroup] = ADC16_DRV_GetConvValueRAW(instance, chnGroup);
    x2=g_AdcValueInt[instance][chnGroup];
    a[count]=x2-x1;       
     if(count%16==0)
        {
                f=1;
                x2= g_AdcValueInt[instance][chnGroup];//用于OLED显示
        }
         
    GPIO_DRV_TogglePinOutput(test);//检测反转频率的信号    x1=x2;     
    count++;
     if(count==10000)
          {
                 stop=1;
                 
          }

}





回复 支持 反对

使用道具 举报

  • TA的每日心情
    难过
    2024-3-21 15:13
  • 签到天数: 41 天

    连续签到: 1 天

    [LV.5]常住居民I

    32

    主题

    1820

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    1785
    最后登录
    2024-3-21
    发表于 2015-12-25 14:24:37 | 显示全部楼层
    学习方法,看看大家的回复,说的不错!下次俺们就不怕了!呵呵!
    好多年没来了
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /3 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2025-7-23 13:59 , Processed in 0.106670 second(s), 30 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表