查看: 3396|回复: 0

【飞凌RT1052】ADC输入&PWMDAC亮度输出

[复制链接]
  • TA的每日心情
    开心
    2018-4-20 15:04
  • 签到天数: 8 天

    [LV.3]偶尔看看II

    49

    主题

    188

    帖子

    1

    金牌会员

    Rank: 6Rank: 6

    积分
    2947
    最后登录
    2023-7-24
    发表于 2018-11-24 20:28:55 | 显示全部楼层 |阅读模式
    本帖最后由 donatello1996 于 2018-11-24 20:34 编辑

        由于总项目中涉及到ADC采集电压信息,因此必须调通ADC外设,而与ADC相对应的自然就是DAC了,在单片机中,非音频项目的DAC一般都用PWMDAC代替,也就是输出频率高且固定,占空比可变的PWM波,来实现改变LED灯亮度。


    本次两个实验的外设都很好移植,为了节省时间,也因为项目中不需要用到PWM而只作为指示输出用,因此PWM输出的代码直接参考@一代睡神的崛起的帖子,不深究,着重分析ADC外设。


    首先看看ADC的硬件连接,根据原理图可知,SDK默认的ADC引脚是H14(BGA编号),通过一个跳帽接到了一个精密电位器上面,如果是要看出明显效果的话当然不可能用精密电位器,应该选用平常使用的10K普通电位器,这种电位器也有3个接口,中间的接口连接ADC,两边的接口连接VCC和GND,由于板上没有输出VCC的2.54mm引脚,因此从UART2十针接口处取出5V电压:
    40.jpg IMG_20181124_195334R.jpg

    ADC外设选用SDK例程中的polling即循环阻塞采集例程,因为我的项目中ADC采集是循环进行的,为了不让CPU有太大的负担因此使用此例程,并将阻塞采集模式改成非阻塞轮询采集方式,下面再贴代码:
    39.jpg

    ADC初始化函数,直接使用SDK里面的默认参数进行初始化即可:
        /*
        *  config->enableAsynchronousClockOutput = true;
         *  config->enableOverWrite =               false;
           *  config->enableContinuousConversion =    false;
           *  config->enableHighSpeed =               false;
           *  config->enableLowPower =                false;
           *  config->enableLongSample =              false;
           *  config->referenceVoltageSource =        kADC_ReferenceVoltageSourceVref;
           *  config->samplePeriodMode =              kADC_SamplePeriod2or12Clocks;
           *  config->clockSource =                   kADC_ClockSourceAD;
           *  config->clockDriver =                   kADC_ClockDriver1;
           *  config->resolution =                    kADC_Resolution12Bit;
           */


      adc_config_t adcConfigStrcut;
      adc_channel_config_t adcChannelConfigStruct;
      ADC_GetDefaultConfig(&adcConfigStrcut);
      adcConfigStrcut.enableHighSpeed=true;
      ADC_Init(ADC1, &adcConfigStrcut);
      adcChannelConfigStruct.channelNumber = 3;
      adcChannelConfigStruct.enableInterruptOnConversionCompleted = false;


    启用ADC1的通道3,组别0,12位数据,直接使用内部AD时钟不分频,直接使用VREF参考电压,使用高低速模式看不出区别,就用高速模式。连续采集


    模式应该跟多通道有关,遵循官方SDK配置为false,不乱动。复写模式也遵循配置不动。


    采集时改为轮询采集,不占用CPU时间片等待:
    while (1)
    {


                    if(ADC_GetChannelStatusFlags(ADC1,0)==0)
                    {
                            ADC_SetChannelConfig(ADC1,0,&adcChannelConfigStruct);
                            printf("ADC Value: %d\r\n",ADC1->R[0]);
                            QTMER4CH3_PWM_DutySet(14,5000,ADC1->R[0]/40.95);
                    }
            }
    }




    然后是PWM输出代码,直接参考@一代睡神的崛起的代码:


    qtmr_config_t qtimer4pwm_config;


    unsigned char Calcu_2invo(unsigned char time)
    {
        unsigned char i=0,value=1;
       
        if(time>7)time=7;
       
        if(time==0)
            value=1;
        else
        {
            for(i=0;i<time;i++)
            {
                value*=2;
            }
        }
            
        return value;
    }


    void QTMR4_CH3_PWM_Init(unsigned char prisrc,int clk, unsigned char duty)
    {
        unsigned char fredivi=1;
       
        qtmr_primary_count_source_t qtimer_source;
        qtimer_source=(qtmr_primary_count_source_t)prisrc;
       
            //配置GPIO_B1_11为QTIMER3_TIMER1的输出引脚
            IOMUXC_SetPinMux(IOMUXC_GPIO_B1_11_QTIMER4_TIMER3,0);        
            
            //配置IO引脚GPIO_AD_B1_11的功能
            //低转换速度,驱动能力为R0/6,速度为100Mhz,关闭开路功能,使能pull/keepr
            //选择keeper功能,下拉100K Ohm,关闭Hyst
            IOMUXC_SetPinConfig(IOMUXC_GPIO_B1_11_QTIMER4_TIMER3,0x10B0);
       
        fredivi=Calcu_2invo(prisrc-8);
        //初始化QTIMER4
        QTMR_GetDefaultConfig(&qtimer4pwm_config);                  //先设置为默认配置,后面在根据实际情况配置
        qtimer4pwm_config.primarySource=qtimer_source;              //设置第一时钟源
        QTMR_Init(TMR4,kQTMR_Channel_3,&qtimer4pwm_config);         //初始化TIM4通道3
        QTMR_SetupPwm(TMR4,kQTMR_Channel_3,clk,duty,false,CLOCK_GetFreq(kCLOCK_IpgClk)/fredivi); //初始化PWM
        QTMR_StartTimer(TMR4,kQTMR_Channel_3,kQTMR_PriSrcRiseEdge); //通道3在primary时钟源的上升沿计数
    }


    void QTMER4CH3_PWM_DutySet(unsigned char prisrc,int clk, unsigned char duty)
    {
        unsigned char fredivi=1;
        int srcclk,period,hightime,lowtime;
       
        fredivi=Calcu_2invo(prisrc-8);
        srcclk=CLOCK_GetFreq(kCLOCK_IpgClk)/fredivi;
       
        period=(srcclk/clk);                //一个PWM周期需要的计数值
        hightime=(period*duty)/100;         //一个PWM周期中高电平时间(计数值)
        lowtime=period-hightime;            //一个PWM周期中低电平时间(计数值)
       
        TMR4->CHANNEL[kQTMR_Channel_3].CMPLD1=lowtime;
        TMR4->CHANNEL[kQTMR_Channel_3].CMPLD2=hightime;
    }


    看看效果:
    4.gif 41.jpg
    上传工程文件: 工程文件.zip (1.25 MB, 下载次数: 17)
    今天心情不错
    回复

    使用道具 举报

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

    本版积分规则

    关闭

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

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

    GMT+8, 2024-4-20 06:36 , Processed in 0.108322 second(s), 20 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

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