搜索
bottom↓
回复: 5

关于 MK64 MQX BSP(板级支持包)ADC USART等最最底层的驱动的疑问

[复制链接]

出0入0汤圆

发表于 2016-8-30 10:29:32 | 显示全部楼层 |阅读模式
关于 MK64 MQX  BSP(板级支持包)ADC USART等最最底层的驱动的疑问

最近,新的项目接触飞思卡尔的K64 和 MQX,在ADC\USART等硬件驱动,存在迷惑!

最最底层的硬件初始化(比如I/O口功能的选择、跟据AD通道配置相应的IO功能)我找不到在哪里配置的?

比如,以下为BSP的 initBSP.c(硬件初始化文件),以ADC0为例:

如果我使能ADC0模块  #define BSPCFG_ENABLE_ADC0       1

initbsp就会执行以下的ADC0初始化函数:_io_adc_install("adc0:", (void *) &_bsp_adc0_init);

#if BSPCFG_ENABLE_ADC0
    _io_adc_install("adc0:", (void *) &_bsp_adc0_init);
#endif

分析ADC0的 初始化函数_io_adc_install主要是依据 &_bsp_adc0_init的内容:
内容包括给ADC0S模块分配时钟源、设置时间分频、AD采样速率、中断向量、中断优先级以及ADC0的触发方式等。

typedef struct kadc_install_struct
{
    /* The number of ADC peripheral, use adc_t enum from PSP */
    uint8_t ADC_NUMBER;

    /* The clock source */
    ADC_CLOCK_SOURCE CLOCK_SOURCE;

    /* The clock divisor for ADC */
    ADC_CLOCK_DIV CLOCK_DIV;

    /* ADC high speed control, see ADC_HSC enum */
    ADC_HSC SPEED;

    /* ADC low power control, see ADC_LPC enum */
    ADC_LPC POWER;

    /* The calibration data pointer */
    uint8_t *CALIBRATION_DATA_PTR;

    /* ADC interrupt vector */
    uint32_t ADC_VECTOR;

    /* ADC interrupt vector */
    uint32_t ADC_PRIORITY;

    /* KPDB init structure */
    const KPDB_INIT_STRUCT * PDB_INIT;

} KADC_INIT_STRUCT, * KADC_INIT_STRUCT_PTR;
/////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
const KADC_INIT_STRUCT _bsp_adc0_init = {
    /* The number of ADC peripheral, use adc_t enum from PSP */
    0,
    /* The clock source, selects the best from BUSCLK and BUSCLK/2 */
    ADC_CLK_BUSCLK_ANY,
    /* The clock divisor for ADC. use the fastest one */
    ADC_DIV_ANY,
    /* ADC high speed control, see ADC_HSC enum */
    ADC_HSC_NORMAL,
    /* ADC low power control, see ADC_LPC enum */
    ADC_LPC_NORMAL,
    /* The calibration data pointer */
    NULL,
    /* ADC interrupt vector */
    INT_ADC0,
    /* ADC interrupt vector */
    BSP_ADC0_VECTOR_PRIORITY,
    /* PDB init structure */
    &_bsp_pdb_init
};

但是,但是 这个硬件的初始化都没有涉及到最最底层的,I/O口的功能和AD通道的选择和配置????


再返回来分析一下ADC0的 任务,ADC0任务流使用的通道是:ADC_CHANNEL_DP3_DIFF:
大致的流程:

定义ADC通道和工作方式:
#define     ADC_VALUE_MASK      ((uint32_t)(0xff))
#define     ADC_SAMPLE_FREQ     ((uint32_t)(256))
#define     ADC0_TABLE          {ADC_CHANNEL_DP3_DIFF}////选择ADC通道是ADC_CHANNEL_DP3_DIFF
#define     ADC0_TABLE_LEN      (1)

//define if testing DIFF channel
#define TEST_DIFF_CH

以下为ADC0的初始化(初始化也没有看到有IO和通道选择的部分)??????????
typedef struct
{
    ADC_CLOCK               xAdcClock;              //时钟
    ADC_CLOCK_DIVSION       xAdcClockDivsion;       //时钟分频
    ADC_ADACK               xAdcAck;                //异步时钟输出
    ADC_DIFF                xAdcDiff;               //差分使能
    ADC_LOWPOWER            xAdcLowpower;           //低功耗模式
    ADC_MODE                xAdcMode;               //采样精度
    ADC_LONG_SAMPLE         xAdcLongSample;         //长采样
    ADC_LONG_SAMPLE_TIME    xAdcLongSampleTime;     //长采样时间
    ADC_SPEED               xAdcSpeed;              //转换速度
    ADC_TRIGGER             xAdcTrigger;            //触发方式
    ADC_REFSEL              xAdcRefsel;             //参考电压
    ADC_AVERAGE             xAdcAverage;            //硬件均值
    ADC_AVERAGE_SELECT      xAdcAverageSelect;      //硬件均值采样数量
    ADC_AVERAGE_CONTINUOUS  xAdcAverageContinuous;  //硬件均值连续转换次数
    void                    (*old_isr)(pointer);    //中断服务程序入口
    pointer                 old_isr_data;           //中断服务程序参数
}ADC_PARAMETER;

ADC_PARAMETER   ux_Adc_Parameter;

ADC_StructInit(&ux_Adc_Parameter);//初始化ADC0,ADC0工作模式的初始化

再往下的机制大概就是利用PDB和2个DMA通道配合,分别片选ADC通道和读取ADC的采样结果,
并通过printfK串口打印(其中,这里用到的只有一个ADC通道,但从原理上做了多通道的考虑)

    //配置DMA通道1,利用PDB和DMA原理机制是片选触发不同的ADC通道
    ADC_DMACmd(ADC0, ENABLE);
        
    DMA_PARAMETER   ux_Dma_Parameter;

    DMA_StructInit(&ux_Dma_Parameter);
    ux_Dma_Parameter.xDmaSrcChannel = DMAMUX_SRC_CHANNEL_PDB;
    ux_Dma_Parameter.u32SourceAddress = (uint32_t)&(u32_p_adc0_channel_table[0]);//跟AD通道有关的
    ux_Dma_Parameter.u32DestinationAddress = (uint32_t)&(ADC0_SC1A);
    ux_Dma_Parameter.u16SourceNextValueOffset = sizeof(uint32_t);
    ux_Dma_Parameter.u16DestinationNextValueOffset = 0;
    ux_Dma_Parameter.u8SourceAddressModulo = 0;
    ux_Dma_Parameter.u8DestinationAddressModulo = 0;
    ux_Dma_Parameter.xSourceDataSize = DMA_TRANSFER_SIZE_32_BIT;
    ux_Dma_Parameter.xDestinationDataSize = DMA_TRANSFER_SIZE_32_BIT;
    ux_Dma_Parameter.u32ByteTransferCount = sizeof(uint32_t);
    ux_Dma_Parameter.u32LastSourceAddressAdjustment = -(ADC0_TABLE_LEN * ux_Dma_Parameter.u16SourceNextValueOffset);
    ux_Dma_Parameter.u32LastDestinationAddressAdjustment = 0;
    ux_Dma_Parameter.u16BufferSize = ADC0_TABLE_LEN;
    DMA_Init(DMA_CHANNEL_0, DMAMUX, &ux_Dma_Parameter);
    DMA_Cmd(DMA_CHANNEL_0, DMAMUX, ENABLE);

这里在配置DMA的的源地址的时候出现了跟ADC通道有关的    ux_Dma_Parameter.u32SourceAddress = (uint32_t)&(u32_p_adc0_channel_table[0]);
也就是ADC_CHANNEL_DP3_DIFF
但是也看不到有跟ADC通道的真正的最最底层的配置(ADCIO初始化和真正的ADC通道的选择的部分)
???????????????????????????????????????????????

/////////////////////////////////////////////////////////
//以下是配置DMA通道1 通过DMA读取ADC的打样结果
   ux_Dma_Parameter.xDmaSrcChannel = DMAMUX_SRC_CHANNEL_ADC0;
    ux_Dma_Parameter.u32SourceAddress = (uint32_t)&(ADC0_RA);
    ux_Dma_Parameter.u32DestinationAddress = (uint32_t)&(ux_adc0_value.u16_p_all_value[0]);
    ux_Dma_Parameter.u16SourceNextValueOffset = 0;
    ux_Dma_Parameter.u16DestinationNextValueOffset = sizeof(uint16_t);
    ux_Dma_Parameter.u8SourceAddressModulo = 0;
    ux_Dma_Parameter.u8DestinationAddressModulo = 0;
    ux_Dma_Parameter.xSourceDataSize = DMA_TRANSFER_SIZE_16_BIT;
    ux_Dma_Parameter.xDestinationDataSize = DMA_TRANSFER_SIZE_16_BIT;
    ux_Dma_Parameter.u32ByteTransferCount = sizeof(uint16_t);
    ux_Dma_Parameter.u32LastSourceAddressAdjustment = 0;
    ux_Dma_Parameter.u32LastDestinationAddressAdjustment = -((ADC0_TABLE_LEN*(ADC_VALUE_MASK + 1)) * ux_Dma_Parameter.u16DestinationNextValueOffset);
    ux_Dma_Parameter.u16BufferSize = ADC0_TABLE_LEN*(ADC_VALUE_MASK + 1);
    DMA_Init(DMA_CHANNEL_1, DMAMUX, &ux_Dma_Parameter);
    DMA_Cmd(DMA_CHANNEL_1, DMAMUX, ENABLE);
   
///////////////到最后面就是取数据串口打印................

到整个过程下来,我都没有找到,也是让我迷惑的地方。。。。。。。最最底层的IO和 ADC通道的选择和配置的那部分硬件的初始化。



以下是 ADC0任务的DEMO代码:

谢谢大家!

#include <mqx.h>
#include <bsp.h>
#include "adc16.h"
#include "dma.h"
#include "app_dma.h"

#define     ADC_VALUE_MASK      ((uint32_t)(0xff))
#define     ADC_SAMPLE_FREQ     ((uint32_t)(256))
#define     ADC0_TABLE          {ADC_CHANNEL_DP3_DIFF}
#define     ADC0_TABLE_LEN      (1)

//define if testing DIFF channel
#define TEST_DIFF_CH

typedef union
{
    struct
    {
        uint16_t  u16_channel[ADC0_TABLE_LEN];
    }ux_p_each_value[ADC_VALUE_MASK + 1];
    uint16_t  u16_p_all_value[ADC0_TABLE_LEN*(ADC_VALUE_MASK + 1)];
} ADC0_VALUE;

uint32_t          u32_p_adc0_channel_table[ADC0_TABLE_LEN] = ADC0_TABLE;
ADC0_VALUE      ux_adc0_value;

uint32_t cnt = 0;

/* Task IDs */
#define MAIN_TASK 5

/* Function prototypes */
extern void main_task(uint32_t);

const TASK_TEMPLATE_STRUCT MQX_template_list[] =
{
    /* Task Index,  Function,  Stack,  Priority,    Name,       Attributes,             Param,  Time Slice */
    {MAIN_TASK,     main_task, 2048,      8,        "Main",     MQX_AUTO_START_TASK,    0,      0           },
    {0}
};

/*TASK*-----------------------------------------------------
**
** Task Name    : main_task
** Comments     :
**
*END*-----------------------------------------------------*/
void main_task
   (
      uint32_t initial_data
   )
{
#ifdef TEST_DIFF_CH
    short buf[ADC0_TABLE_LEN*(ADC_VALUE_MASK + 1)];
#endif
   
    ADC_PARAMETER   ux_Adc_Parameter;
   
    ADC_StructInit(&ux_Adc_Parameter);
    /* Before calibration, set hardware average to maximum and set ADC clock to be less than or equal to 4MHz,
    using external reference VREFH = VDDA */
    //ux_Adc_Parameter.xAdcAck               = ADC_ADACK_ENABLE;
    ux_Adc_Parameter.xAdcClock              = ADC_CLOCK_BUSCLK;
    ux_Adc_Parameter.xAdcClockDivsion       = ADC_CLOCK_DIVSION_8;
    ux_Adc_Parameter.xAdcMode               = ADC_MODE_16_BIT;
    ux_Adc_Parameter.xAdcLongSample         = ADC_LONG_SAMPLE_ENABLE;
    ux_Adc_Parameter.xAdcLongSampleTime     = ADC_LONG_SAMPLE_TIME_6ADCK;
    /* Select internal reference */
    ux_Adc_Parameter.xAdcRefsel             = ADC_REFSEL_INTERNAL;
    /* Set ADC speed and low power mode to select ADACK value */
    ux_Adc_Parameter.xAdcSpeed              = ADC_SPEED_HIGH;

    /* hardware average enable */
    ux_Adc_Parameter.xAdcAverage            = ADC_AVERAGE_ENABLE;
    ux_Adc_Parameter.xAdcAverageContinuous  = ADC_AVERAGE_CONTINUOUS_1;
    ux_Adc_Parameter.xAdcAverageSelect      = ADC_AVERAGE_SELECT_32;

    ADC_Init(ADC0, &ux_Adc_Parameter);
    ADC_Cal(ADC0);

    /* hardware average enable */
    //ux_Adc_Parameter.xAdcAverage            = ADC_AVERAGE_DISABLE;
    ux_Adc_Parameter.xAdcAverageSelect      = ADC_AVERAGE_SELECT_4;
    ADC_Init(ADC0, &ux_Adc_Parameter);
   
    ADC_DMACmd(ADC0, ENABLE);
        
    DMA_PARAMETER   ux_Dma_Parameter;

    DMA_StructInit(&ux_Dma_Parameter);
    ux_Dma_Parameter.xDmaSrcChannel = DMAMUX_SRC_CHANNEL_PDB;
    ux_Dma_Parameter.u32SourceAddress = (uint32_t)&(u32_p_adc0_channel_table[0]);
    ux_Dma_Parameter.u32DestinationAddress = (uint32_t)&(ADC0_SC1A);
    ux_Dma_Parameter.u16SourceNextValueOffset = sizeof(uint32_t);
    ux_Dma_Parameter.u16DestinationNextValueOffset = 0;
    ux_Dma_Parameter.u8SourceAddressModulo = 0;
    ux_Dma_Parameter.u8DestinationAddressModulo = 0;
    ux_Dma_Parameter.xSourceDataSize = DMA_TRANSFER_SIZE_32_BIT;
    ux_Dma_Parameter.xDestinationDataSize = DMA_TRANSFER_SIZE_32_BIT;
    ux_Dma_Parameter.u32ByteTransferCount = sizeof(uint32_t);
    ux_Dma_Parameter.u32LastSourceAddressAdjustment = -(ADC0_TABLE_LEN * ux_Dma_Parameter.u16SourceNextValueOffset);
    ux_Dma_Parameter.u32LastDestinationAddressAdjustment = 0;
    ux_Dma_Parameter.u16BufferSize = ADC0_TABLE_LEN;
    DMA_Init(DMA_CHANNEL_0, DMAMUX, &ux_Dma_Parameter);
    DMA_Cmd(DMA_CHANNEL_0, DMAMUX, ENABLE);
   
    ux_Dma_Parameter.xDmaSrcChannel = DMAMUX_SRC_CHANNEL_ADC0;
    ux_Dma_Parameter.u32SourceAddress = (uint32_t)&(ADC0_RA);
    ux_Dma_Parameter.u32DestinationAddress = (uint32_t)&(ux_adc0_value.u16_p_all_value[0]);
    ux_Dma_Parameter.u16SourceNextValueOffset = 0;
    ux_Dma_Parameter.u16DestinationNextValueOffset = sizeof(uint16_t);
    ux_Dma_Parameter.u8SourceAddressModulo = 0;
    ux_Dma_Parameter.u8DestinationAddressModulo = 0;
    ux_Dma_Parameter.xSourceDataSize = DMA_TRANSFER_SIZE_16_BIT;
    ux_Dma_Parameter.xDestinationDataSize = DMA_TRANSFER_SIZE_16_BIT;
    ux_Dma_Parameter.u32ByteTransferCount = sizeof(uint16_t);
    ux_Dma_Parameter.u32LastSourceAddressAdjustment = 0;
    ux_Dma_Parameter.u32LastDestinationAddressAdjustment = -((ADC0_TABLE_LEN*(ADC_VALUE_MASK + 1)) * ux_Dma_Parameter.u16DestinationNextValueOffset);
    ux_Dma_Parameter.u16BufferSize = ADC0_TABLE_LEN*(ADC_VALUE_MASK + 1);
    DMA_Init(DMA_CHANNEL_1, DMAMUX, &ux_Dma_Parameter);
    DMA_Cmd(DMA_CHANNEL_1, DMAMUX, ENABLE);
   
    DMA_EnableRequest(DMAMUX, DMA_CHANNEL_0);
    DMA_EnableRequest(DMAMUX, DMA_CHANNEL_1);
   
   
    SIM_SCGC6 |= SIM_SCGC6_PDB_MASK;

    PDB_SC_REG(PDB0_BASE_PTR) |= PDB_SC_PDBEN_MASK ;
    PDB_SC_REG(PDB0_BASE_PTR) |= PDB_SC_TRGSEL(0xf) | PDB_SC_CONT_MASK;
    PDB_MOD_REG(PDB0_BASE_PTR) = BSP_BUS_CLOCK / 50 / ADC_SAMPLE_FREQ;
    PDB_IDLY_REG(PDB0_BASE_PTR) = 0;
    PDB_SC_REG(PDB0_BASE_PTR) |= PDB_SC_LDOK_MASK;
    PDB_SC_REG(PDB0_BASE_PTR) |= PDB_SC_DMAEN_MASK;
    PDB_SC_REG(PDB0_BASE_PTR) |= PDB_SC_SWTRIG_MASK;
   
   
    while(1)
    {
        for(long int i = 0; i < 8000000; i ++);
        ADC_DMACmd(ADC0, DISABLE);
        
        for(cnt = 0; cnt < ADC0_TABLE_LEN*(ADC_VALUE_MASK + 1); cnt++)
        {
#ifdef TEST_DIFF_CH
            //when ADC operate in differential mode, converted 16bit value is in 2's complement value
            if((ux_adc0_value.u16_p_all_value[cnt])&0x8000)
                buf[cnt] = -(~(ux_adc0_value.u16_p_all_value[cnt])+1);
            else
                buf[cnt] = ux_adc0_value.u16_p_all_value[cnt];
            printf("%d\n", buf[cnt]);
#else
            printf("%d\n", ux_adc0_value.u16_p_all_value[cnt]);
#endif
        }
        ADC_DMACmd(ADC0, ENABLE);
        
        _time_delay(100);
    }   
    //_task_block();
}  

/* EOF */

出0入0汤圆

发表于 2016-8-30 10:49:35 | 显示全部楼层
这个比较偏门,估计用的不多,

出0入0汤圆

发表于 2016-9-20 00:20:34 | 显示全部楼层
io的配置在bsp下的一个gpio初始化.c文件里,里面基本所有的io功能初始化都在那个里边,在各个功能模块里会调用到这里。

出0入0汤圆

 楼主| 发表于 2016-9-24 16:37:52 | 显示全部楼层
lantian0099 发表于 2016-9-20 00:20
io的配置在bsp下的一个gpio初始化.c文件里,里面基本所有的io功能初始化都在那个里边,在各个功能模块里会 ...

谢谢!问题已解决。

出0入8汤圆

发表于 2016-9-24 16:40:54 | 显示全部楼层
粤H广宁 发表于 2016-9-24 16:37
谢谢!问题已解决。

给个建议:
问题如果解决的话,可以将解决方案描述一下,
有始有终,让后来人也可以学习一下。

出0入0汤圆

 楼主| 发表于 2016-9-27 20:34:23 | 显示全部楼层
security 发表于 2016-9-24 16:40
给个建议:
问题如果解决的话,可以将解决方案描述一下,
有始有终,让后来人也可以学习一下。 ...

嗯 嗯
第一:是自己刚开始用MK64这颗芯片,也是第一次用飞思卡尔的芯片,由于时间比较急 自己看DATASHEET 不够耐心和详细!
关于 IO口配置和AD通道的选择使能,在细心看完后才领悟到。所以。。。对于自己来说 以后是需要改正的地方。。。。

第二:鉴于这个主题是这样理解的:
在这个主题的对AD采样的案例的操作方式是没用使用MQX里面的ADC的驱动的,而是采样直接操作的方式----------
本主题用到了2个DMA通道
由PDB 定时触发第一个DMA通道,在这个DMA通道里面实现ADC通道的切换!
再由ADC触发另外一个DMA通道,在这个DMA通道里面实现了ADC数据的读取。
--------------从而实现整个ADC的采样过程的通道切换和AD植的读取,都是通过DMA方式去实现。

以上是我的理解的描述,有理解不到位的地方,希望朋友们指出! 谢谢!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-20 20:20

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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