查看: 18549|回复: 74

[分享] K60实现ADC四通道自动连续采集 无需CPU干预

[复制链接]

该用户从未签到

17

主题

113

帖子

0

注册会员

Rank: 2

积分
130
最后登录
1970-1-1
发表于 2013-10-31 09:31:08 | 显示全部楼层 |阅读模式
 之前有许多朋友询问如何使用K60的ADC实现多个通道的连续自动采集功能。其实就K60而言,他的ADC有ADC0和ADC1,每个ADCx又有A和B两组控制通道,因此最多可以实现4组ADC通道的连续自动采集,而且配合DMA和PDB,无需CPU对采集过程进行干预,我们可以直接读取内存中的转换结果!
本例程同样是基于LPLD的OSKinetis固件库开发的,代码中全部使用库函数进行开发,开发过程无需涉及任何寄存器操作。每步我们都写了详细注释,相信不了解原理的童鞋也能看个大概!


下面我还是简单叙述下实现原理:
Step 1.配置ADC模块,配置A组和B组控制通道均为硬件触发,使能DMA请求。并使能相关输入通道。
Step 2.配置DMA模块,分别用2个DMA通道来控制ADC0和ADC1的DMA传输,并配置DMA源地址为ADC结果寄存器,配置主循环计数2次,因为要分别传输R[A]和R[B]结果寄存器的值。
Step 3.配置PDB模块,使用软件触发或其他外设触发均可,例程中位软件触发。关键步骤是要配置PDB的ADC预触发模式,使能通道0和通道1的预触发,并配置为Back to Back模式,这样才能让ADC的COCO转换完成标志自动触发下一个AD转换!
Step 4.触发PDB工作,坐享其成!

主要代码如下:
[color=white !important]?
            
001

            
002

            
003

            
004

            
005

            
006

            
007

            
008

            
009

            
010

            
011

            
012

            
013

            
014

            
015

            
016

            
017

            
018

            
019

            
020

            
021

            
022

            
023

            
024

            
025

            
026

            
027

            
028

            
029

            
030

            
031

            
032

            
033

            
034

            
035

            
036

            
037

            
038

            
039

            
040

            
041

            
042

            
043

            
044

            
045

            
046

            
047

            
048

            
049

            
050

            
051

            
052

            
053

            
054

            
055

            
056

            
057

            
058

            
059

            
060

            
061

            
062

            
063

            
064

            
065

            
066

            
067

            
068

            
069

            
070

            
071

            
072

            
073

            
074

            
075

            
076

            
077

            
078

            
079

            
080

            
081

            
082

            
083

            
084

            
085

            
086

            
087

            
088

            
089

            
090

            
091

            
092

            
093

            
094

            
095

            
096

            
097

            
098

            
099

            
100

            
101

            
102

            
103

            
104

            
                        //**********************************************
            //Step 1.配置ADC0和ADC1的参数
            //ADC0-A
            adc0_init_struct.ADC_Adcx = ADC0;
            adc0_init_struct.ADC_BitMode = SE_12BIT;      //12位精度
            adc0_init_struct.ADC_CalEnable = TRUE;        //使能初始化校验
            adc0_init_struct.ADC_HwAvgSel = HW_4AVG;      //使能4次硬件校准
            adc0_init_struct.ADC_HwTrgCfg = HW_TRGA;      //配置A组为硬件触发
            adc0_init_struct.ADC_DmaEnable = TRUE;        //使能DMA请求
            LPLD_ADC_Init(adc0_init_struct);      //初始化ADC0-A组通道
            //ADC0-B,只需配置不同参数的成员变量
            adc0_init_struct.ADC_HwTrgCfg = HW_TRGB;      //配置B组为硬件触发
            LPLD_ADC_Init(adc0_init_struct);      //初始化ADC0-B组通道
            //使能ADC0的通道DAD1、AD14的引脚复用功能
            LPLD_ADC_Chn_Enable(ADC0, DAD1);
            LPLD_ADC_Chn_Enable(ADC0, AD14);
            //使能ADC0的相关转换通道
            LPLD_ADC_EnableConversion(ADC0, DAD1, 0, FALSE);
            LPLD_ADC_EnableConversion(ADC0, AD14, 1, FALSE);
             
            //ADC1A
            adc1_init_struct.ADC_Adcx = ADC1;
            adc1_init_struct.ADC_BitMode = SE_12BIT;
            adc1_init_struct.ADC_CalEnable = TRUE;
            adc1_init_struct.ADC_HwAvgSel = HW_4AVG;
            adc1_init_struct.ADC_HwTrgCfg = HW_TRGA;
            adc1_init_struct.ADC_DmaEnable = TRUE;
            LPLD_ADC_Init(adc1_init_struct);
            //ADC1B
            adc1_init_struct.ADC_HwTrgCfg = HW_TRGB;
            LPLD_ADC_Init(adc1_init_struct);
            LPLD_ADC_Chn_Enable(ADC1, AD10);
            LPLD_ADC_Chn_Enable(ADC1, AD11);
            LPLD_ADC_EnableConversion(ADC1, AD10, 0, FALSE);
            LPLD_ADC_EnableConversion(ADC1, AD11, 1, FALSE);
               
            //**********************************************
            //Step 2.配置DMA CH0和DMA CH1,分别处理ADC0和ADC1的DMA请求
            //DMA CH0
            dma0_init_struct.DMA_CHx = DMA_CH0;           //使用Ch0通道
            dma0_init_struct.DMA_Req = ADC0_DMAREQ;       //DMA请求源为ADC0
            dma0_init_struct.DMA_MajorLoopCnt = 2;        //主循环计数2次,因为要循环ADC0的AB两组通道
            dma0_init_struct.DMA_MinorByteCnt = 2;        //次循环传输字节计数(由于ADC采样为12位,因此传输2字节)
            dma0_init_struct.DMA_SourceAddr = (uint32)&(ADC0->R[0]);       //源地址:ADC0结果寄存器A地址
            dma0_init_struct.DMA_SourceDataSize = DMA_SRC_16BIT;   //源地址传输数据宽度16位
            dma0_init_struct.DMA_SourceAddrOffset = 4;    //源地址偏移为4个字节,因为ADC0->R寄存为32位宽,A组传输完成后移动到B组
            dma0_init_struct.DMA_LastSourceAddrAdj = -8;  //主循环最后调节地址为-8个字节,因为主循环为2次计数,因此地址偏移了8个字节
            dma0_init_struct.DMA_DestAddr = (uint32)&Result;       //目的地址,即定义的结果保存数组头地址
            dma0_init_struct.DMA_DestDataSize = DMA_DST_16BIT;     //目的地址传输数据宽度16位
            dma0_init_struct.DMA_DestAddrOffset = 2;      //目的地址偏移为2个字节,因为Result为16位变量
            dma0_init_struct.DMA_LastDestAddrAdj = -4;    //目的地址最后调节地址为-4个字节
            dma0_init_struct.DMA_AutoDisableReq = FALSE;   //禁用自动禁用请求,即不受主循环计数计数限制
            //初始化DMA
            LPLD_DMA_Init(dma0_init_struct);
            //使能DMA请求
            LPLD_DMA_EnableReq(DMA_CH0);
             
            //DMA CH1,配置基本相同
            dma1_init_struct.DMA_CHx = DMA_CH1;  
            dma1_init_struct.DMA_Req = ADC1_DMAREQ;      
            dma1_init_struct.DMA_MajorLoopCnt = 2;       
            dma1_init_struct.DMA_MinorByteCnt = 2;
            dma1_init_struct.DMA_SourceAddr = (uint32)&(ADC1->R[0]);      
            dma1_init_struct.DMA_SourceDataSize = DMA_SRC_16BIT; 
            dma1_init_struct.DMA_SourceAddrOffset = 4;
            dma1_init_struct.DMA_LastSourceAddrAdj = -8;
            dma1_init_struct.DMA_DestAddr = (uint32)&Result+4;       //目的地址,由于数组中头2个元素存ADC0的结果,因此要偏移4个字节取第3个元素的地址
            dma1_init_struct.DMA_DestDataSize = DMA_DST_16BIT; 
            dma1_init_struct.DMA_DestAddrOffset = 2;
            dma1_init_struct.DMA_LastDestAddrAdj = -4;
            dma1_init_struct.DMA_AutoDisableReq = FALSE;  
            //初始化DMA
            LPLD_DMA_Init(dma1_init_struct);
            //使能DMA请求
            LPLD_DMA_EnableReq(DMA_CH1);
               
            //**********************************************
            //Step 3.配置PDB,用于触发ADC
            pdb_init_struct.PDB_CounterPeriodMs = 100;    //PDB计数器周期,这个决定了4个通道每采集一次的间隔
            pdb_init_struct.PDB_LoadModeSel = LOADMODE_0;
            pdb_init_struct.PDB_ContinuousModeEnable = TRUE;      //使能连续工作模式,即只需要开始触发一次,以后PDB就会连续工作
            pdb_init_struct.PDB_TriggerInputSourceSel = TRIGGER_SOFTWARE; //软件触发模式,即不需要用其他模块触发PDB工作
            //初始化PDB
            LPLD_PDB_Init(pdb_init_struct);
            //配置PDB预触发功能
            //使能ADC0-A组的预触发功能
            LPLD_PDB_AdcTriggerCfg(ADC0, PRETRIG_EN_A|PRETRIG_DLY_A, 0); 
            //使能ADC0-B组的预触发功能,并使用Back to Back模式
            LPLD_PDB_AdcTriggerCfg(ADC0, PRETRIG_BB_B|PRETRIG_EN_B|PRETRIG_DLY_B, 0);
            //使能ADC1-A组的预触发功能,并使用Back to Back模式
            LPLD_PDB_AdcTriggerCfg(ADC1, PRETRIG_BB_A|PRETRIG_EN_A|PRETRIG_DLY_A, 0);
            //使能ADC1-B组的预触发功能,并使用Back to Back模式
            LPLD_PDB_AdcTriggerCfg(ADC1, PRETRIG_BB_B|PRETRIG_EN_B|PRETRIG_DLY_B, 0);
            //软件触发PDB开始工作
            LPLD_PDB_SoftwareTrigger();
             
            while(1)
            {
              delay();
              printf("ADC0_RA=%d\r\n", Result[0]);
              printf("  ADC0_RB=%d\r\n", Result[1]);
              printf("    ADC1_RA=%d\r\n", Result[2]);
              printf("      ADC1_RB=%d\r\n", Result[3]);
            }
            
            



 
 

运行结果:

211853hb7lscs8b1q7zaau.png
 
例程下载(回复可见): [拉普兰德K60固件库]例程(DMA PDB ADC)LPLD_DmaPdbAnalogSample.zip (19.4 KB, 下载次数: 96)
回复

使用道具 举报

该用户从未签到

17

主题

113

帖子

0

注册会员

Rank: 2

积分
130
最后登录
1970-1-1
 楼主| 发表于 2013-10-31 09:33:14 | 显示全部楼层

回复:K60实现ADC四通道自动连续采集 无需CPU干预

自己沙发
回复 支持 反对

使用道具 举报

该用户从未签到

0

主题

4

帖子

0

新手上路

Rank: 1

积分
0
最后登录
1970-1-1
发表于 2013-10-31 14:26:49 | 显示全部楼层

回复:K60实现ADC四通道自动连续采集 无需CPU干预

学习了!如此高级的功能确实方便很多!
回复 支持 反对

使用道具 举报

该用户从未签到

4

主题

18

帖子

0

新手上路

Rank: 1

积分
54
最后登录
1970-1-1
发表于 2013-10-31 16:36:29 | 显示全部楼层

RE:K60实现ADC四通道自动连续采集 无需CPU干预

学习了~下载学习lpld的库
回复 支持 反对

使用道具 举报

  • TA的每日心情
    难过
    2021-12-15 16:01
  • 签到天数: 1 天

    连续签到: 1 天

    [LV.1]初来乍到

    305

    主题

    4701

    帖子

    0

    中级会员

    Rank: 3Rank: 3

    积分
    377
    最后登录
    2023-8-16
    发表于 2013-10-31 16:51:02 | 显示全部楼层

    RE:K60实现ADC四通道自动连续采集 无需CPU干预

    谢谢楼主,加分,加精,必须。
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    17

    主题

    113

    帖子

    0

    注册会员

    Rank: 2

    积分
    130
    最后登录
    1970-1-1
     楼主| 发表于 2013-10-31 21:10:47 | 显示全部楼层

    回复:K60实现ADC四通道自动连续采集 无需CPU干预

    回复第 5 楼 于2013-10-31 16:51:02发表:
    谢谢楼主,加分,加精,必须。
     
    谢谢管理员大人的支持,大家有什么需求可以反映,我们尽量用库代码给实现出来。
     
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    0

    主题

    4

    帖子

    0

    新手上路

    Rank: 1

    积分
    0
    最后登录
    1970-1-1
    发表于 2013-11-1 09:44:49 | 显示全部楼层

    回复:K60实现ADC四通道自动连续采集 无需CPU干预

    洋葱大哥又出新资料,力顶
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    3

    主题

    31

    帖子

    0

    新手上路

    Rank: 1

    积分
    44
    最后登录
    1970-1-1
    发表于 2013-11-3 22:43:02 | 显示全部楼层

    RE:K60实现ADC四通道自动连续采集 无需CPU干预

    哈哈~~~
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    3

    主题

    31

    帖子

    0

    新手上路

    Rank: 1

    积分
    44
    最后登录
    1970-1-1
    发表于 2013-11-7 00:13:02 | 显示全部楼层

    RE:K60实现ADC四通道自动连续采集 无需CPU干预

    hao!!!!!!!!!!!!
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    0

    主题

    4

    帖子

    0

    新手上路

    Rank: 1

    积分
    13
    最后登录
    1970-1-1
    发表于 2013-11-9 04:48:48 | 显示全部楼层

    RE:K60实现ADC四通道自动连续采集 无需CPU干预

    thanks!!!!
    回复 支持 反对

    使用道具 举报

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

    本版积分规则

    关闭

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

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

    GMT+8, 2025-7-21 20:54 , Processed in 0.110720 second(s), 29 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

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