SylixOS的imx1050平台PWM捕获驱动

  • 概述
    本文档是对IMXRT1050平台上的SylixOS PWM波的产生和捕获功能的详细分析。代码在IMXRT1050的板级支持包的“bsp_rt1050/SylixOs/driver/pwm/”目录下的pwm.c文件中,该文件会依赖于bsp_rt1050/SylixOs/driver/lib目录,这个目录是NXP官方提供的库文件。
    本文档描述的应用场景是这样的:PWM需要根据用户自己设置的参数,达到控制输出波形的频率和精确的周期个数,以达到控制3D打印机的目的。
  • PWM波的输出
    IMXRT1050包含4个PWM模块,每个子模块有3路,PWM_A/PWM_B/PWM_X, 如图 2.1所示。暂时只关心PWM_A/PWM_B。
  • 图 2.1 PWM子模块
    可以想象PWM只要确定一个上升沿和一个下降沿的时刻就能确定一个周期,从而可以确定一个频率的波形。因此需要用到一个定时器和几个比较器。如图 2.2所示显示的是中心对齐的波形产生示意图。设置VAL2和VAL3寄存器,作为比较器的值,当计数器的值匹配VAL2,PWM_A会产生一个上升边沿,当计数器的值匹配VAL3,PWM_A会产生一个下降沿,这样循环下去,PWM_A就会产生一连串波形。PWM_B同样如此。


    图 2.2 PWM波形产生

    1. PWM的捕获
      PWM同样可以设置为输入捕获功能。电路图如图 3.1所示。输入有两路,由INP_SEL控制。第一路直接输入捕获到电路,并可设置在输入波形的上升沿/下降沿/双边沿触发中断,在中断中可以关闭PWM用来实现控制输出波形周期数,第二路输入波形先经过一个8bit计数器,计数器记录输入波形双边沿个数,存储在EDGCNT里。可以设置期望比较值EDGCPM。比较器comparator比较EDGCNT和EDGCPM的值,当匹配时,reset边沿计数器的值,同时进入捕获电路。并可产生中断。第二路将很好的减少中断的次数,提高PWM的性能。捕获电路Circuit 0 Capture和Circuit 1 Capture将会交替工作。使能Arming Logic 将使捕获电路开始工作。

      图 3.1输入捕获功能逻辑
    2. 代码编写
      4.1 编码思路
      PWM_A作为输出,PWM_B作为捕获输入。应用程序传两个参数,分别指定PWM_A输出波形的频率、PWM_B应该捕获的周期数。当PWM_B捕获到指定周期数,会触发中断处理函数,中断处理函数关闭PWM_A的输出波,这样就达到了控制输出周期的个数的目的。同时需要实现同步功能,即在中断函数中需要post一个信号量,告知pend的一方已经产生了指定个数的周期,并关闭了PWM_A。
      综上所述,应该实现一下几个函数:
      ? pwmConfig配置PWM输出功能
      ?
      pwmCaptureInputConfig 配置捕获功能
      ? pwmIsr 中断处理函数
      ? PWM_StopTimer 停止PWM输出功能
      ? PWM_StartTimer 打开PWM 输出功能
      除了中断处理函数,其他函数都可以挂在字符驱动函数
      pwmIoctl中。
      4.2 代码分析
      4.2.1 初始化部分
      程序清单 4.1
      /
      为pwm0创建同步信号量
      /

      _G_pwm[kPWM_Module_0].PWMC_CapSem = API_SemaphoreBCreate("pwm_sync",LW_FALSE,LW_OPTION_OBJECT_GLOBAL,LW_NULL);

    if(LW_OBJECT_HANDLE_INVALID == _G_pwm[kPWM_Module_0].PWMC_CapSem)
    {
    PWM_DEBUG("Pwm API_SemaphoreBCreate Failed\n");
    return (PX_ERROR);
    }

    /*
        初始化PWM0中断,用于pwm捕获
    */

    PwmIRQ = PWM1_0_IRQn;
    API_InterVectorSetPriority(BSP_IRQ_TO_VECTOR(PwmIRQ), LW_INTER_PRIO_LOWEST);
    API_InterVectorConnect(BSP_IRQ_TO_VECTOR(PwmIRQ),(PINT_SVR_ROUTINE)__pwmIsr0,NULL,"pwm_isr0"); / 注册中断服务函数 /
    API_InterVectorEnable(BSP_IRQ_TO_VECTOR(PwmIRQ));
    4.2.2 __pwmIoctl

    程序清单 4.2
    static INT pwmIoctl (PLW_FD_ENTRY pFdEntry, INT iCmd, LONG lArg)
    {
    INT iRet;
    INT iIrq;
    PPWM_USER_CONFIG pPwmUserConfig;
    PPWM_DUTY_CONFIG pPwmDutyConfig;
    INT iModuleCtr;
    PPWM_CAPTURE_CONFIG pCapParaCfg;
    __PPWM_CONTROLER pPwmDev = (__PPWM_CONTROLER)pFdEntry->FDENTRY_pdevhdrHdr;

    switch (iCmd) {
    case PWM_MODE_SET:  /*  PWM 模式设置 */
        pPwmUserConfig = (__PPWM_USER_CONFIG)lArg;
    
        if(LW_NULL == pPwmUserConfig)
        {
            return  (PX_ERROR);
        }
    
        iRet = __pwmConfig(pPwmDev->PWMC_pBase, pPwmUserConfig);
        break;
    case PWM_STOP_SET:    /*  停止 PWM  */
        iModuleCtr     = (INT)lArg;
        if (iModuleCtr > kPWM_Control_Module_3 ||
            iModuleCtr < kPWM_Control_Module_0)
        {
            PWM_DEBUG("larg error\r\n");
            return PX_ERROR;
        }
    
        PWM_StopTimer(pPwmDev->PWMC_pBase, iModuleCtr);
        iRet = ERROR_NONE;
        break;
    
    case PWM_START_SET:     /*  打开 PWM  */
        iModuleCtr     = (INT)lArg;
    
        if (iModuleCtr > kPWM_Control_Module_3 ||
            iModuleCtr < kPWM_Control_Module_0)
        {
            PWM_DEBUG("larg error\r\n");
            return PX_ERROR;
        }
    
        PWM_StartTimer(pPwmDev->PWMC_pBase, iModuleCtr);
        iRet = ERROR_NONE;
        break;
    case PWM_INCAPT_SET:   /*  捕获输入 */
        pCapParaCfg = (__PPWM_CAPTURE_CONFIG)lArg;
        iRet = __pwmCaptureInputConfig(pPwmDev->PWMC_pBase,pCapParaCfg);
        break;
    case PWM_CAPT_WAITE: /*用于捕获同步*/
        iRet = API_SemaphoreBPend(_G_pwm[kPWM_Module_0].PWMC_CapSem,LW_OPTION_WAIT_INFINITE);
        break;
    default:
        return  (PX_ERROR);
    }
    
    return  (iRet);

    }
    4.3 捕获配部分
    程序清单 4.3
    static INT __pwmCaptureInputConfig (PWM_Type *pBase, __PPWM_CAPTURE_CONFIG pPwmCaptureConfig)
    {
    uint32_t irq;
    uint32_t status = 0;

    PWM_SetupInputCapture(pBase, pPwmCaptureConfig->subModule, pPwmCaptureConfig->pwmChannel, pPwmCaptureConfig->inputCaptureParams);
    status = PWM_GetStatusFlags(pBase, pPwmCaptureConfig->subModule);

    /*
        先清中断
    */
    if(status & (PWM_STS_CFB0_MASK))
    {
        //bspDebugMsg("PWM_ClearStatusFlags>>>>>>\n");
        PWM_ClearStatusFlags(pBase,pPwmCaptureConfig->subModule,status & (PWM_STS_CFB0_MASK));
    }
    
    /*
        中断的开启必须要在PWM_SetupInputCapture 配置之后,否则可能会出现配置没有完成就进入中断
    */
    irq = PWM_GetEnabledInterrupts(pBase, kPWM_Module_0);
    PWM_EnableInterrupts(pBase, kPWM_Module_0, (uint32_t)(irq | PWM_INTEN_CB0IE(1) |PWM_INTEN_CB1IE(1)));
    /*
        使配置生效
    */
    PWM_SetPwmLdok(pBase, 1 << kPWM_Module_0, LW_TRUE);
    
    return (ERROR_NONE);

    }

    4.4 中断部分
    程序清单 4.4
    static irqreturn_t __pwmIsr0(PVOID pvArg, ULONG ulVector)
    {
    uint32_t status = 0;

    status = PWM_GetStatusFlags(_G_pwm[kPWM_Module_0].PWMC_pBase, kPWM_Module_0);
    
    if(status & PWM_STS_CFB0_MASK) //clear int
    {
    PWM_ClearStatusFlags(_G_pwm[kPWM_Module_0].PWMC_pBase, kPWM_Module_0,status & PWM_STS_CFB0_MASK);
        PWM_StopTimer(_G_pwm[kPWM_Module_0].PWMC_pBase,1 << kPWM_Module_0);
    }
    
    if(status & PWM_STS_CFB1_MASK) //clear int
    {
    PWM_ClearStatusFlags(_G_pwm[kPWM_Module_0].PWMC_pBase, kPWM_Module_0,status & PWM_STS_CFB1_MASK);
        PWM_StopTimer(_G_pwm[kPWM_Module_0].PWMC_pBase,1 << kPWM_Module_0);
        //_DebugFormat(__PRINTMESSAGE_LEVEL, "2");
    }
    
    API_SemaphoreBPost(_G_pwm[kPWM_Module_0].PWMC_CapSem);
    
    return  (LW_IRQ_HANDLED);

    }

    原文地址:http://blog.51cto.com/12142768/2116105

    时间: 2025-02-01 15:59:24

    SylixOS的imx1050平台PWM捕获驱动的相关文章

    SylixOS基于Nuc970平台的SD驱动移植

    1. 适用范围 本文档为实现Nuc970平台的SD驱动总结,提供一些SylixOS SD驱动移植方法的参考. 2. 原理概述 2.1 控制器类型 SD控制器有两种类型,分为SD标准控制器(SDHCI)和SD非标准控制器. SylixOS Base代码中实现了SDHCI的驱动,但Nuc970的SD控制器是非标准控制器,其功能都需要在BSP中单独实现. 2.2  命令.应答.数据 SD传输过程中会有命令.应答和数据三个概念存在. 命令和应答都是在CMD线上传输的,数据在DAT线上进行传输. 2.2.

    SylixOS在x86平台的快速构建

    1.适用范围 本文档适用于使用RealEvo-IDE集成开发环境在x86平台快速构建SylixOS运行环境. 2.前提准备 在开发机上正确安装RealEvo-IDE集成开发环境. 一台正常的x86平台目标机(建议使用Intel处理器,包含显示器或者串口等输出设备和键盘等输入设备). 如果需要U盘安装则需要一个大于32M的空白U盘. 3.制作x86 bsp启动镜像 3.1准备base工程 3.1.1打开RealEvo-IDE 双击图标,打开RealEvo-IDE软件,如图 31所示选择建立工程的工

    Arduino控制16路PWM舵机驱动板(PCA9685)

    最近买了块16路PWM舵机驱动板,测试后做个总结. 舵机原理网上资料很多就不详细介绍了,一般以9g舵机为例,一个20ms的周期内通过0.5ms到2.5ms的脉冲宽度控制舵机角度. 板子为16通道12bit PWM舵机驱动,用2个引脚通过I2C就可以驱动16个舵机. 修改例子为可以通过串口设置舵机角度 1 #include <Wire.h> 2 #include <Adafruit_PWMServoDriver.h> 3 4 //默认地址 0x40 5 Adafruit_PWMSer

    SylixOS iMX6平台I2C总线驱动

    原理概述 I2C总线驱动概述 I2C总线驱动是I2C适配器的软件实现,提供I2C适配器与从设备间完成数据通信的能力,比如起始,停止,应答信号和MasterXfer的实现函数.驱动程序包含初始化I2C总线控制器__i2cHwInit函数,操作函数集(总线传输__i2cTransfer函数,总线控制__i2cMasterCtl函数). Imx6ul控制器的硬件描述 imx6ul处理器内部集成了一个I2C控制器,通过五个寄存器来进行控制. I2Cx_IADR I2C地址寄存器 I2Cx_IFDR I2

    SylixOS下基于NUC970的NAND驱动

    开发环境 开发环境 宿主机: Windows7 64bits 系统 开发板: 安米MDK972 软件环境: RealEvo-IDE3.0 NAND Flash: S34ML02G100TF100 S34ML02G100TF100芯片参数 Density:2 Gbit Input / Output Bus Width: 8-bits Page Size:2112 (2048 + 64) bytes; 64 bytes is spare area Block Size: 64 Pages;128k

    高通LCD的pwm背光驱动

    发生异常的现象: msm8953 lcd在快速亮灭的情况下背光概率性休眠不灭:测量高通pwm,发现正常的时候pwm的管脚LCM_BL_PWM为低电平,失败的时候为高电平: 根据原理图: mpp是什么? mpp是基于电源pmic的管脚,也叫做多功能管脚:MPP的全称是Multi Purpose Pin:可以做电源.gpio.ADC.PWM.SINK等功能. 背光的控制方式: LCD控制IC支持动态背光控制功能(CABC)通过解析图像的直方图动态改变输出PWM的占空比从而动态调节LCD的背光,在不改

    MTK MT6735平台调试Camera驱动记录

    Camera驱动相关文件: 1.ProjectConfig.mk   配置相关信息,定义主副摄像头.和其他信息 2.kd_imgsensor.h     定义Sensor_id 的信息文件, kernel和vendor下都需要有一份 3.kd_camera_hw.c  kd_camera_hw.h  控制Camera上下电,宏在kd_camera_hw.h中定义 4.kd_sensorlist.h    sensorlist.cpp  这两个文件中定义添加Sensor模组,两个文件中的顺序必须一

    使用wireshark在windows平台下捕获HTTP协议数据包中的帐号密码信息

    1.打开wireshark软件,从Interface List中选择相应的网卡,例如我的PC机上是“本地连接”,然后选择”Start”启动抓包程序. 2.打开学校主页,输入账号和密码登录校内邮箱. 3.终止抓包程序. 4.在过滤器一栏Filter填写http.request.method==post过滤表达式,获取通过post方式发送的账户密码信息,一行一行查看封包列表,可以看到在16进制数据模块可以看到username&password.

    各个平台camera驱动编写注意事项

    各个平台camera驱动编写注意事项 camera驱动开发 1)另外注意,在imx6平台中,4.1.15kernel版本的代码,mxc的mxc_v4l2_capture.c camera主控制器和ov5642.c的sensor驱动之间,通过v4l2-int-device.h和v4l2-int-device.c中的master和slave注册attach连接的方式来关联,关联后,master(camera isp主控制器)通过ioctl来控制slave(sensor).master和slave只有