admin 管理员组文章数量: 1086019
【RT
脉冲宽度调制(PWM),全称:Pulse Width Modulation。常用于电机控制,屏幕显示等功能。具体功能网上自行搜索。
开发前准备
- 硬件平台:nxp rt10xx单片机
- IDE: Keil
1.Kconfig 修改和menuconfig配置
在Env环境menuconfig中 RT-Thread Components->Device Drivers 设备驱动默认为n,所以需要开启。
从git下来的drv_pwm.c文件开头宏可知(如果没有,那就自己搭建个这个文件吧),需在Kconfig中添加如下语句,然后在Env环境menuconfig中 Hardware Drivers Config->On-Chip Peripheral Drivers 使能PWM,特别注意下左边配置,BSP_USING_PWM1,由于PWM可用的选择很多PWM1,2,3,4,每个PWM还分很多通道,为了偷懒,也觉得没必要都加上,所以这里只加了PWM1
2.工程添加PWM驱动框架和BSP驱动接口
添加设备驱动的时候笔者发现怎么也找不到pwm.c文件,好家伙官方组件命名怎么又叫 rt_drv_pwm.c 没明白rt命名规范到底是啥规则(全局搜索rt_drv_xxx命名的,也只有它了,希望官方能规范下)
设备驱动框架:rt_drv_pwm.c BSP接口:drv_pwm.c fsl_pwm.c
3.添加或修改drv_pwm.c
笔者查阅了文件,实际没啥要改的
-
定义pwm device
static struct rt_pwm_ops imxrt_drv_ops =
{.control = imxrt_drv_pwm_control
};
-
设备创建注册
imxrt_pwm1_init 实现了外设初始化(注意IO的初始化,笔者统一放到pin_mux.c);rt_device_pwm_register 实现设备驱动注册
int rt_hw_pwm_init(void)
{rt_err_t ret = RT_EOK;// XBARA_Init(XBARA1);// XBARA_SetSignalsConnection(XBARA1,kXBARA1_InputLogicHigh,kXBARA1_OutputFlexpwm1Fault0);// XBARA_SetSignalsConnection(XBARA1,kXBARA1_InputLogicHigh,kXBARA1_OutputFlexpwm1Fault1);// XBARA_SetSignalsConnection(XBARA1,kXBARA1_InputLogicHigh,kXBARA1_OutputFlexpwm1234Fault2);// XBARA_SetSignalsConnection(XBARA1,kXBARA1_InputLogicHigh,kXBARA1_OutputFlexpwm1234Fault3);#ifdef BSP_USING_PWM1static struct rt_device_pwm pwm1_device;if (imxrt_pwm1_init(PWM1) != RT_EOK){LOG_E("init pwm1 failed\n");}ret = rt_device_pwm_register(&pwm1_device, "pwm1", &imxrt_drv_ops, PWM1);if (ret != RT_EOK){LOG_E("%s register failed", "pwm1");}#endif /* BSP_USING_PWM1 */#ifdef BSP_USING_PWM2static struct rt_device_pwm pwm2_device;if (imxrt_pwm2_init(PWM2) != RT_EOK){LOG_E("init pwm2 failed\n");}ret = rt_device_pwm_register(&pwm2_device, "pwm2", &imxrt_drv_ops, PWM2);if (ret != RT_EOK){LOG_E("%s register failed", "pwm2");}
#endif /* BSP_USING_PWM2 */#ifdef BSP_USING_PWM3static struct rt_device_pwm pwm3_device;if (imxrt_pwm3_init(PWM3) != RT_EOK){LOG_E("init pwm3 failed\n");}ret = rt_device_pwm_register(&pwm3_device, "pwm3", &imxrt_drv_ops, PWM3);if (ret != RT_EOK){LOG_E("%s register failed", "pwm3");}#endif /* BSP_USING_PWM3 */#ifdef BSP_USING_PWM4static struct rt_device_pwm pwm4_device;if (imxrt_pwm4_init(PWM4) != RT_EOK){LOG_E("init pwm4 failed\n");}ret = rt_device_pwm_register(&pwm4_device, "pwm4", &imxrt_drv_ops, PWM4);if (ret != RT_EOK){LOG_E("%s register failed", "pwm4");}
#endif /* BSP_USING_PWM4 */#if defined(BSP_USING_QTMR1) || defined(BSP_USING_QTMR2) || defined(BSP_USING_QTMR3) || defined(BSP_USING_QTMR4)if (imxrt_qtmr_init() != RT_EOK){LOG_E(LOG_TAG" init qtmr failed");}
#endif#ifdef BSP_USING_QTMR1static struct rt_device_pwm qtmr1_device;ret = rt_device_pwm_register(&qtmr1_device, "pwm5", &imxrt_drv_qtmr_ops, TMR1);if (ret != RT_EOK){LOG_E("%s register failed", "pwm5");}
#endif /* BSP_USING_QTMR1 */#ifdef BSP_USING_QTMR2static struct rt_device_pwm qtmr2_device;ret = rt_device_pwm_register(&qtmr2_device, "pwm6", &imxrt_drv_qtmr_ops, TMR2);if (ret != RT_EOK){LOG_E("%s register failed", "pwm6");}
#endif /* BSP_USING_QTMR2 */#ifdef BSP_USING_QTMR3static struct rt_device_pwm qtmr3_device;ret = rt_device_pwm_register(&qtmr3_device, "pwm7", &imxrt_drv_qtmr_ops, TMR3);if (ret != RT_EOK){LOG_E("%s register failed", "pwm7");}
#endif /* BSP_USING_QTMR3 */#ifdef BSP_USING_QTMR4static struct rt_device_pwm qtmr4_device;ret = rt_device_pwm_register(&qtmr4_device, "pwm8", &imxrt_drv_qtmr_ops, TMR4);if (ret != RT_EOK){LOG_E("%s register failed", "pwm8");}
#endif /* BSP_USING_QTMR4 */return ret;
}INIT_BOARD_EXPORT(rt_hw_pwm_init);
-
pwm device 相关函数
内容很简单直接贴代码,不用修改啥
static rt_err_t imxrt_drv_pwm_enable(struct rt_device_pwm *device, struct rt_pwm_configuration *configuration, rt_bool_t enable)
{PWM_Type *base;pwm_module_control_t pwm_module_control;base = (PWM_Type *)device->parent.user_data;pwm_module_control = (pwm_module_control_t)(1 << configuration->channel);if (!enable){PWM_StopTimer(base, pwm_module_control);}else{PWM_StartTimer(base, pwm_module_control);}return RT_EOK;
}static rt_err_t imxrt_drv_pwm_get(struct rt_device_pwm *device, struct rt_pwm_configuration *configuration)
{uint8_t get_duty;uint16_t pulseCnt = 0, pwmHighPulse = 0;uint32_t get_frequence;uint32_t pwmClock;PWM_Type *base;pwm_submodule_t pwm_submodule;base = (PWM_Type *)device->parent.user_data;pwm_submodule = (pwm_submodule_t)configuration->channel;/* get frequence */get_frequence = base->SM[pwm_submodule].VAL1;pwmClock = (PWM_SRC_CLK_FREQ / (1U << ((base->SM[pwm_submodule].CTRL & PWM_CTRL_PRSC_MASK) >> PWM_CTRL_PRSC_SHIFT)));get_frequence = pwmClock / get_frequence;/* get dutycycle */pulseCnt = base->SM[pwm_submodule].VAL1;pwmHighPulse = pulseCnt - (base->SM[pwm_submodule].VAL2) * 2;get_duty = pwmHighPulse * 100 / pulseCnt;/* conversion */configuration->period = 1000000000 / get_frequence;configuration->pulse = get_duty * configuration->period / 100;return RT_EOK;
}static rt_err_t imxrt_drv_pwm_set(struct rt_device_pwm *device, struct rt_pwm_configuration *configuration)
{RT_ASSERT(configuration->period > 0);RT_ASSERT(configuration->pulse <= configuration->period);PWM_Type *base;pwm_submodule_t pwm_submodule;pwm_module_control_t pwm_module_control;uint32_t period = 0;uint8_t duty = 0;base = (PWM_Type *)device->parent.user_data;pwm_submodule = (pwm_submodule_t)configuration->channel;pwm_module_control = (pwm_module_control_t)(1 << configuration->channel);duty = configuration->pulse * 100 / configuration->period;Pwm_Signal.dutyCyclePercent = duty;period = (uint32_t)(1000000000 / configuration->period);PWM_SetupPwm(base, pwm_submodule, &Pwm_Signal, 1, kPWM_CenterAligned, period, PWM_SRC_CLK_FREQ);PWM_UpdatePwmDutycycle(base, pwm_submodule, DEFAULT_COMPLEMENTARY_PAIR, kPWM_CenterAligned, duty);PWM_SetPwmLdok(base, pwm_module_control, true);return RT_EOK;
}static rt_err_t imxrt_drv_pwm_control(struct rt_device_pwm *device, int cmd, void *arg)
{struct rt_pwm_configuration *configuration = (struct rt_pwm_configuration *)arg;switch (cmd){case PWM_CMD_ENABLE:return imxrt_drv_pwm_enable(device, configuration, RT_TRUE);case PWM_CMD_DISABLE:return imxrt_drv_pwm_enable(device, configuration, RT_FALSE);case PWM_CMD_SET:return imxrt_drv_pwm_set(device, configuration);case PWM_CMD_GET:return imxrt_drv_pwm_get(device, configuration);default:return RT_EINVAL;}
}static rt_err_t imxrt_drv_pwm_init(PWM_Type *base, pwm_submodule_t pwm_submodule, uint16_t psc, uint32_t fre, uint8_t duty)
{pwm_config_t PwmConfig;uint8_t fault_input;pwm_clock_prescale_t pwm_prescale = (pwm_clock_prescale_t)psc;fault_input = (uint8_t)pwm_submodule;PWM_GetDefaultConfig(&PwmConfig);PwmConfig.prescale = pwm_prescale;PwmConfig.reloadLogic = kPWM_ReloadPwmFullCycle;PwmConfig.pairOperation = kPWM_Independent;PwmConfig.enableDebugMode = true;if (PWM_Init(base, pwm_submodule, &PwmConfig) == kStatus_Fail){LOG_E("init pwm failed \n");return -RT_ERROR;}base->SM[fault_input].DISMAP[0] = 0x00;base->SM[fault_input].DISMAP[1] = 0x00;Pwm_Signal.pwmChannel = DEFAULT_COMPLEMENTARY_PAIR;Pwm_Signal.level = DEFAULT_POLARITY;Pwm_Signal.dutyCyclePercent = duty;PWM_SetupPwm(base, pwm_submodule, &Pwm_Signal, 1, kPWM_CenterAligned, fre, PWM_SRC_CLK_FREQ);PWM_SetPwmLdok(base, pwm_submodule, true);return RT_EOK;
}
4.搭建应用层demo
输出1KHz频率,占空比50的波形
#define PWM_DEV_NAME "pwm1" /* PWM设备名称 */
#define PWM_DEV_CHANNEL 0 /* PWM通道 *//*------------------------------------------------------------------------------------------------------------------
Variables
*/
struct rt_device_pwm *pwm_dev; /* PWM设备句柄 *//*------------------------------------------------------------------------------------------------------------------
Functions
*/
int pwmsample(void)
{rt_uint32_t period;period = 1000000; /*单位ns 周期为:1ms (1KHz)*//* 查找设备 */pwm_dev = (struct rt_device_pwm *)rt_device_find(PWM_DEV_NAME);if (pwm_dev == RT_NULL){rt_kprintf("pwm sample run failed! can't find %s device!\n", PWM_DEV_NAME);return RT_ERROR;}rt_pwm_set(pwm_dev, PWM_DEV_CHANNEL, period, period/2);//rt_device_control(pwm_dev, PWM_CMD_ENABLE, &configuration);rt_pwm_enable(pwm_dev, PWM_DEV_CHANNEL);rt_kprintf("pwm start\r\n");return 0;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(pwmsample, pwm sample);
输入命令pwmsample运行应用,用虚拟示波器测试波形验证结果
本文标签: RT
版权声明:本文标题:【RT 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://roclinux.cn/p/1700299730a386313.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论