#夏日挑战赛#【FFH】BearPi_Micro南向开发PWM驱动代码 原创 精华
X丶昕雪
发布于 2022-6-14 23:15
浏览
3收藏
PWM介绍
PWM的频率是指在1秒钟内,信号从高电平到低电平再回到高电平的次数,也是指一秒钟能有多少个周期。占空比是一个脉冲周期内,高电平的时间与整个周期时间的比例。
在一定的频率下,PWM通过不同的占空比得到不同大小的输出模拟电压,通过这种原理实现数字模拟信号转换。
如下图第一个计数周期,当CNT<CCRx时输出低电平;当CNT>=CCRx时输出高电平。周期即是(t2-0)s,占空比是t1/t2.
打开PWM
首先注册一个DevHandle对象,用于存放PWM口驱动相关的配置和操作
static DevHandle MyHandler =NULL;
在驱动代码中添加引用PWM头文件
#include "pwm_if.h"
MyHandler = PwmOpen(uint32_t num);
其中PwmOpen函数内的操作如下:
DevHandle PwmOpen(uint32_t num)
{
struct PwmDev *pwm = PwmGetDevByNum(num); //创建控制器结构体
//判断pwm是否成功启用
(void)OsalSpinLock(&(pwm->lock)); //上锁
//判断pwm->busy是否为繁忙,若为繁忙则解锁退出报错
//判断pwm->method和method->open是否不为空
pwm->busy = true;
(void)OsalSpinUnlock(&(pwm->lock)); //解锁
return (DevHandle)pwm;
}
st=>start: Start
op=>operation: PwmDev *pwm
cond=>condition: pwm!=NULL
op1=>operation: 上锁
cond1=>condition: pwm->busy !=ture
op2=>operation: 解锁、报错
cond2=>condition: pwm->method == NULL 或 pwm->method->open == NULL
cond3=>condition: pwm->method->open(pwm)==0
a=>operation: pwm->busy=true
b=>operation: 解锁
e=>end
st->op->cond
cond(yes)->op1
cond(no)->e
op1->cond1
cond1(no)->op2
cond1(yes)->cond2
cond2(yes)->a
cond2(no)->cond3
cond3(yes)->a
cond3(no)->op2
a->b->e
op2->e
PWM结构体分析
其中PwmDev是核心层控制器结构体
struct PwmDev {
struct IDeviceIoService service;
struct HdfDeviceObject *device;
struct PwmConfig cfg; // 属性结构体,相关定义见下
struct PwmMethod *method; // 钩子函数模板
bool busy; //PWM是否在使用
uint32_t num; // 设备号
OsalSpinlock lock;
void *priv; // 私有数据,一般存储自定义结构体首地址,方便调用
};
对于PwmConfig类型,该类型是结构体用于配置初始化PWM的参数
struct PwmConfig {
uint32_t duty; // 占空时间
uint32_t period; // pwm 周期
uint32_t number; // pwm 连续个数
uint8_t polarity; // 输出的极性
uint8_t status; // 运行状态
};
polarity(PWM输出的极性,有效电平):
Bit | Polarity | meaning |
---|---|---|
0 | PWM_NORMAL_POLARITY | Normal polarity |
1 | PWM_INVERTED_POLARITY | Inverted polarity |
status(运行的状态):
Bit | Status | meaning |
---|---|---|
0 | PWM_DISABLE_STATUS | Disabled |
1 | PWM_ENABLE_STATUS | Enabled |
对于PwmMethod结构体,该结构体包含有
struct PwmMethod {
int32_t (*setConfig)(struct PwmDev *pwm, struct PwmConfig *config);
int32_t (*open)(struct PwmDev *pwm);
int32_t (*close)(struct PwmDev *pwm);
};
以上三个参数都是返回int类型的函数指针
PWM配置
方法一
当我们需要配置pwm时,只需要配置好一个PwmConfig类型的一个结构体,再使用PwmSetConfig函数进行配置
PwmSetConfig(DevHandle handle, struct PwmConfig *config);
方法二
小熊派上有许多PWM配置的具体函数,每一个函数配置一个PWM的配置参数,便于操作,下面列举其中几个:
关闭PWM
PwmClose(DevHandle Handler);
PWM设置周期(自动重装载值)
PwmSetPeriod(DevHandle handle, uint32_t period);
PWM设置占空比
PwmSetDuty(DevHandle handle, uint32_t duty);
PWM输出的极性,有效电平
一个PWM信号的极性,决定了是高占空比的信号输出电平高,还是低占空比信号输出电平高。假设一个信号的占空比为100%,如果为正常极性,则输出电平最大,如果为翻转的极性,则输出电平为0。
PwmSetPolarity(DevHandle handle, uint8_t polarity);
PWM使能
PwmEnable(DevHandle handle);
PWM失能
PwmDisable(DevHandle handle);
驱动代码中启动PWM的配置流程图:
st=>start: PwmOpen
op=>operation: PwmSetPeriod
cond=>operation: PwmSetDuty
cond1=>operation: PwmSetPolarity
cond2=>operation: PwmEnable
e=>end
st->op->cond->cond1->cond2->e
©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
分类
已于2022-6-14 23:16:15修改
赞
9
收藏 3
回复
相关推荐
写得很好,赞一个
大佬,求带!
PWM 不要太重要