0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

基于CW32F030C8T6的无刷直流电机驱动系统

Mrs_chen_insis 来源:Mrs_chen_insis 作者:Mrs_chen_insis 2022-07-02 14:06 次阅读

基于CW32F030C8T6的无刷直流电机

本项目设计三块板子,(为什么我会这么设计:首先,当时主要是不想把芯片集成上去了!希望主控一块板子,以后也可以玩一些外设什么的,不至于焊接到电机板子上去;其次,我最初是打算做CW32F030C8T6的FOC控制的,我的驱动板也做了FOC的一款,还在测试,需要一段时间再分享,最近学校也比较忙,所以一直耽搁着了,后期会努力做完,这次还是先把基本的BLDC六步换向驱动先完成;最后,我的设计思路大家可以参考,也可以将其全部继承上一块板子,都可以的,完全没问题!)

1、主控板:首先主要是USB供电、经过LDO降压成3.3V,为芯片供电,值得注意的是:该芯片是一个宽电压范围的芯片,可以直接供电5V!其次,通过芯片引脚引出了SWD接口UART接口,方便下载程序和上位机打印数据;最后,板载按键复位电路,添加硬件消抖,保证按键稳定。

2、承接板:该电路主要包括:蜂鸣器电路、LED灯电路、OLED显示电路、按键电路、旋钮电位器电路以及2×17P牛头排母座;起到承接主控板和驱动板的作用。

3、驱动板:该电路主要包括:电源电路驱动电路电流采样电路、霍尔信号电路、反电动势电路、电机接口层电路以及测温层电路;主要起到大功率驱动的作用。

接下来我介绍一下我的硬件部分,软件部分会粘贴部分关键信息,其他请参考UET李芳老师分享的例程!在此,感谢李芳姐姐!!!


硬件部分

选型

电源部分

24VBuck部分

问题1:主电源最低电压是多少?负载电流需要多大?

答:本项目采用57直流无刷电机,其额定电压为:24V(DC);额定电流为:5.9A;空载电流为:0.8A;额定转速为2500RPM;因此,主电源供电部分需大于等于24V,负载电流要大于0.8×3=2.4A以上,留有阈值,选择负载输出电流3A,降压型电路。

poYBAGK_32-AdWIIAAGOJqMX0ZQ156.png

经过上述筛选,我们可以看到,符合条件的有19款,我们按价格升序选择现货商品。进一步观看IC的相关描述,在考虑价格的基础上,还要考虑是否符合我们的要求。

pYYBAGK_33SAFTcTAAGGeFyUAnQ869.png

我这边看到了一款芯龙的Buck芯片,价格也能接受,库存也特别丰富,最主要的是:芯龙是国产芯片!!!不用考虑了,就这款了。

OK,选择好芯片后,进入数据手册读取相关参数

pYYBAGK_33qAbxeGAALPlAvi7Eo907.png

我们可以知道的是:

输入电压范围是:4.5V-40V。 我们输入是24V,完全满足裕量和要求。

输出电压范围是:1.23V-37V。 我们输出是10V-20V,也完全满足裕量和要求。

输出电流是:3A。 我们需要的也是2.4A以上的电路,3A完全满足要求。

开关频率:150KHz。 还可以,这个速度。

pYYBAGK_34KAIHGJAAISr7FJ0x4245.png

我们从描述中可以知道:

1、输入引脚,需要放置一个合适的大容量电容,去消除输入噪声。

2、GND引脚在布局的时候需要考虑到:GND引脚需要放置在肖特基二极管到输出电容地路径的外部,以防止开关电流尖峰感应产生电压噪声。

3、反馈电压是:1.23V.

4、ON/OFF引脚如果悬空,默认低电平。该引脚低电平则芯片工作,若高电平则芯片不工作。

poYBAGK_34eANS8HAAIhfY2IR4k574.png

我们从描述中可以知道:

1、R1采用接近1K欧姆的电阻,使用1%的精度。

2、C1和CFF是可选择的,为了提高稳定性、降低供电噪声。CIN和C1必须靠近放置在引脚1和引脚3。

3、对于输出电压高于10V的情况,CFF电容是需要的,此时的CFF是作为补偿电容使用,与R2并联使用,其值在100pf到33nf之间。CFF的电容值等于(1/(31×1000×R2))。

pYYBAGK_342AWMa5AAE41NiK2hY344.png

综上所述,我们选型参数为:

CIN:容值为180uf,耐压为大于(24×2=48)V;

C1:容值为10×10^5pf=1uf,耐压为50V;

CFF:容值为1nf,耐压为50V;

R1:阻值为1K欧姆,精度为1%;

R2:阻值为:(1+R2/R1)*1.23=Vout--->R2等于8.76K欧姆。

COUT:容值为180uf,耐压为大于(12×2)=24V;

L1:感值为68uH;

D1:肖特基二极管采用DSK34。

因此24V将压成12V的整体方案为:

pYYBAGK_35SAE2yxAAGAUvbCaGA268.png

12VBuck部分

考虑到霍尔传感器的工作电压是5V,因此需要将12V再Buck变换成5V。本项目采用首鼎的SD8942,至于为什么选择它,因为我买了好多这个物料,库存很多,不能浪费钱。。。而且这个12V将压成5V的方案我也验证过,没什么问题,最主要的是:肖特基二极管都不需要,外围电路很简单。

pYYBAGK_35qAFNH0AALEVamBwsw654.png

我们从描述中可以知道:

1、输入电压范围为:4.5V-16V 我们输入电压是12V,满足要求。

2、开关频率600KHz 开关频率速度快。

3、输出电流:2A 电机空载电流0.8A,2倍裕量,满足要求。

4、不需要肖特基二极管,内部集成 节省成本。

5、芯片效率:96% 效率高。

6、参考电压:0.6V 方便计算回馈电阻阻值。

典型应用中就给出了一个输出5V/2A的基本电路,我们可以直接采用。没什么比较特殊的,主要是电容耐压高点就好,其他的没什么考虑的。因此,最终电路图如下所示:

poYBAGK_36CAZ1cdAAFblqk9xhM862.png

因此电源部分已经整体解决完毕。


驱动硬件部分

我们想开环驱动无刷直流电机的话,需要使用到什么功能?

1、供电电源部分:24V供电机;12V供MOS驱动电路;5V供霍尔驱动电路;以及主控芯片的供电

2、主控芯片:发送6路PWM信号以及3路霍尔传感器的检测信号;

3、MOS驱动电路+三相全桥电路;

4、电位器电路,通过旋钮控制速度;

5、OLED显示功能电路

6、电流采样部分

因此我们不妨从这几个电路进行入手分析,值得注意的是:主控芯片以及供电电源部分我们不再分析,电源在上面已经分析过了,主控芯片则是采用武汉芯源半导体研发的CW32F030C8T6


MOS驱动电路

poYBAGK_37iAUQ3HAAHwQCKzj7s078.png

我们采用的MOS驱动芯片EG3013,为什么选择它?你自己看吧:(上次实验室做实验,需要栅极驱动IC,就买了好多个,最后板子做出来焊接完毕后我才发现,李芳姐用的栅极驱动IC竟然也是这颗物料!)

pYYBAGK_38CABsvyAACysH5hL9A249.png

该芯片的LIN是一个低电平有效的引脚!在程序中,有一个关于AL、BL、CL打开或关闭的GPIO配置,这里就是相反的逻辑!!!所以各位使用的时候根据自己的IC进行修改即可!

FR107是为了加快开通效率的,用肖特基二极管也可以!但是官方用的FR107,这颗物料我在做动量伦的时候也买了的,所以我就按照官方的做就行了。10uF是升压电容,这个阻值是我问屹晶微电子有限公司的一个技术人员,他告诉我,一般用10uf就足够了!这里建议使用封装为1206的,保证功率!我电路中用的0805,我的物料只有0805了....使用起来没什么问题,我验证过了!最后就是上下MOS的驱动信号了,加上电阻和二极管是为了防止寄生电容和回路电感!!!减小振铃现象。加上一个R组成RLC电路,可以吸收寄生参数;而二极管主要是提供一个续流通道。具体可参考视频:https://b23.tv/9a7pe1Q


三相全桥电路

pYYBAGK_4AyAOBoPAABweBh_rb0716.png

此处的NMOS选用的是:

poYBAGK_4BOAW-ZbAAEcK12LPJc134.png

我主要是考虑电压和电流要大一点,RDS小一点,防止发热严重。最后就是考虑价格问题。


电流采样电路

pYYBAGK_4BeAN35DAAATMHPmb-Y682.png

型号为:

poYBAGK_4B2ACrRzAADugrz5OiQ200.png

价格便宜!!!其次其最大能过的电流为:2/0.01=20A!我们平常哪有这么高电压哟,有个5A、6A的对我这种小白而言,就要关闸了!!!哈哈


霍尔接口电路

pYYBAGK_4CmAcyi5AAC-VgHqPR4459.png

其中:C14、C15、C16是滤波作用;R3、R4、R5是为了拉高三个霍尔信号引脚,因为120°的霍尔传感器不存在111的情况,也是一种保护作用吧!我这里没选择5Pin的接口端子是因为我只有3P和2P的物料,不想再买了....


以上的电路,足以跑起开环,下面就是闭环的一些保护功能,比如:电流检测、电压保护、温度保护等等。我就不一一解释其工作原理了,这个电路图是李芳老师的书本里面的,书里面描述的更详细,需要的可以在附件进行下载!我就不在这献丑了!我这里就简单展示一下原理图即可,具体如何工作的书中有所描述。


运放电路

pYYBAGK_4DCATtguAAE4SKvjjiQ037.png

这个运放书中一摸一样,具体的放大倍数以及工作原理请参考书籍:无刷直流电机控制应用 基于STM8S系列单片机

值得注意的是:这里面关乎到程序的采样问题,一定要弄明白!我在程序中有写那些数值是如何算出来的!


保护电路

poYBAGK_4DaAaJwtAAHXGxzaX6U766.png

这都是一些闭环时加的保护电路,很简单,相信你可以自己分析。


反电动势检测电路

pYYBAGK_4DyAa4ukAACMYFPLN3Q926.png

这个电路关乎到无感驱动电机的时候使用。这个数值也是有讲究的,请将这个电路对比检测母线电压电路,你会发现系数的关系,这个关系需要应用到无感电路中去!


整个电路都没改动,都是参考:立创开源硬件平台:Beauty_Light,在此感谢大佬的硬件电路参考设计!!!


软件部分

有感开环

在开环测试中,最主要的就是需要根据霍尔换向表进行换向操作,只要换向无误,其他就是改变占空比加减速的问题,因此最为重要的就是真值表,比如李芳姐姐官方的真值表如下所示:

pYYBAGK_4ESAQ3t2AAHnYCgyv2o078.png

你就需要根据你电机厂商给你的真值表进行相应的改变,这里贴出我电机的真值表:

poYBAGK_4EmAfiX2AAEmpTjySSk715.png

代表什么意思呢?

比如HC HB HA = 100时,表示需要导通V相的上桥臂和W相的下桥臂,U相处于关闭状态!其他类比如此,因此只需要改改程序的换向顺序即可让电机完美的跑起来,代码如下所示:

//steP,为当前换相序号,OutPwmValue 输出PWM值,PWM_ON_flag=1时启动PWM输出

void Commutation(unsigned int step,unsigned int OutPwmValue,unsigned int PWM_ON_flag)

{

if(PWM_ON_flag==0) //不启动则关闭输出

{

CW_ATIM->CH1CCRA=0;CW_ATIM->CH2CCRA=0;CW_ATIM->CH3CCRA=0;

ATIM_CtrlPWMOutputs(DISABLE);

PWM_AL_OFF; PWM_BL_OFF; PWM_CL_OFF;

return;

}

//关闭所有下桥臂,防止误触发

PWM_AL_OFF; PWM_BL_OFF; PWM_CL_OFF;

//输出上桥

if(step==0||step==1){ CW_ATIM->CH1CCRA=OutPwmValue;CW_ATIM->CH2CCRA=0;CW_ATIM->CH3CCRA=0; } //0:AB; 1:AC

if(step==2||step==3){ CW_ATIM->CH1CCRA=0;CW_ATIM->CH2CCRA=OutPwmValue;CW_ATIM->CH3CCRA=0; } //2:BC; 3:BA

if(step==4||step==5){ CW_ATIM->CH1CCRA=0;CW_ATIM->CH2CCRA=0;CW_ATIM->CH3CCRA=OutPwmValue; } //3:CA; 4:CB

//输出下桥

if(step==0||step==5){PWM_AL_OFF; PWM_CL_OFF;PWM_BL_ON;} //AB CB ; B下桥导通

else if(step==1||step==2){ PWM_AL_OFF; PWM_BL_OFF; PWM_CL_ON;}//AC BC; C下桥导通

else if(step==3||step==4){ PWM_BL_OFF; PWM_CL_OFF; PWM_AL_ON;}//BA CA; A下桥导通

ATIM_CtrlPWMOutputs(ENABLE); //输出有效

}

值得注意的是,不同电机使用时还需要改这个换向顺序,根据你自身电机导通的顺序而定!

//const unsigned char STEP_TAB[6]={1,3,2,5,0,4};//{4,0,5,2,3,1};//

//自己电机顺序

const unsigned char STEP_TAB[6]={4,0,5,2,3,1};//{4,0,5,2,3,1};//


有感闭环

闭环例程相对而言,复杂一点点,不过李芳老师讲的很仔细,相信大家理解起来也不是很困难!该例程主要用到了状态机进行电机的控制作用,主要分为:电机起步检测状态、开始PID状态、运行PID状态、停止状态、错误状态、错误溢出状态。代码如下:

/******************** 核心函数:状态机 *********************/

switch(MOTORSTATE)//状态机

{

case STATESTARTCHECK: //起步检查阶段,判断按键PB5是否按下,按下启动,进入这个函数,否则不进入无法启动电机

EnDirCheck(); //判断PB5是否按下

MotorStartCheck();//是否成功启动电机,是的话进入下一个状态MOTORSTATE=STATESTARTPID;

break;

case STATESTARTPID:

MotorStartPID();//电机启动成功,初始化PID并计算PID,再进入下一个状态MOTORSTATE=STATERUNPID;

break;

case STATERUNPID:

MotorRunPID();//运行PID计算

EnDirCheck();

break;

case STATESTOP:

MotorStop();//停止电机函数

break;

case STATEERROR:

sprintf(temp_buff," ERROR Happen! "); //输出显示故障发生

sprintf(temp_buff1," CODE is: %d ",ErrorCode); //显示故障发生错误代码

OLED_ShowStr(0,0,temp_buff,2);

OLED_ShowStr(0,4,temp_buff1,2);

MotorError();//停止电机运行,并进入错误溢出MotorErrorOver状态机

break;

case STATEERROROVER:

MotorErrorOver();

break;

}

值得注意的是:该例程代码还用了切换界面的函数,又学到了一点,哈哈!也就是通过按键PB4进行OLED的菜单切换,确实很棒!


想要理解该例程,就需要将control.c文件读懂!这样理解起来没什么问题。

#include "control.h"

extern unsigned char save_flag;

extern void Flash_Save(void);

void MotorStartCheck(void)

{

if(MOTORSTATE==STATEERROR)return;

if(SetSpeed>0&&startflag==1)

{

MOTORSTATE=STATESTARTPID;

Dir=dirflag;

}

}

void MotorStartPID(void)

{

if(MOTORSTATE==STATEERROR)

return;

PID_init();

PIDcompute(MINSPEED,0);

HALL_MOTOR_START();

TargS1=SetSpeed;

MOTORSTATE=STATERUNPID;

}

void MotorRunPID(void)

{

if(MOTORSTATE==STATEERROR)return;

if(SetSpeed==0||startflag==0) //给出停止信号

{

MOTORSTATE=STATESTOP;

}

TargS1=SetSpeed;

if(TimeCountPID>=20)//计算实时速度并时行PID运算

{

TimeCountPID=0;

RealS1=HALLcountTemp*500/MPolePairs;//HALLcount*100*60/6/POLEPAIRS;

PIDcompute(TargS1,RealS1);

}

}

void MotorStop(void)

{

if(MOTORSTATE==STATEERROR)return;

Motor_Start_F=0;

MOTOR_STOP0();

if(RealS==0)

{

MOTORSTATE=STATESTARTCHECK; //停下来后才切换流程

}

}

void MotorError(void)

{

MOTOR_STOP0();//停止电机

Motor_Start_F=0;//电机启停标志位至0

MOTORSTATE=STATEERROROVER;//进入错误溢出状态机中

}

void MotorErrorOver(void)

{

unsigned char times=0;

times=0;

LEDOFF();

TimeCountTemp=0;

while(TimeCountTemp<200);//延时200ms

while(1) //发生故障,则故障指示灯闪烁。需重启

{

if(times

{

if(TimeCountTemp<200)

{

LEDON();

}

else if(TimeCountTemp<=400)//LED flashing

{

LEDOFF();

}

else if(TimeCountTemp>400)

{

if(times

{

times++;

TimeCountTemp=0;

if(times>=ErrorCode);

else LEDOFF();

}

}

}

else if(TimeCountTemp<500);

else {times=0;TimeCountTemp=0;}

}

}

void WaitStart(void)

{

if(SetSpeed==0)MOTORSTATE=STATESTARTCHECK;

}

void EnDirCheck(void)

{

unsigned int dd;

static unsigned char key_dir=0,key_en=0;

if(MOTORSTATE==STATEERROR)return;

if(GPIO_ReadPin(EN_GPIO_PORT,EN_GPIO_PIN)==GPIO_Pin_SET)key_en=0; //使能判断

else if(key_en==0)

{

for(dd=0;dd<500;dd++); //消抖

if(GPIO_ReadPin(EN_GPIO_PORT,EN_GPIO_PIN)==GPIO_Pin_RESET)

{

startflag=1-startflag;

if(startflag==0)

GPIO_WritePin(LEDSTSTO_GPIO_PORT,LEDSTSTO_GPIO_PIN,GPIO_Pin_SET); //启停指示灯灭

else

GPIO_WritePin(LEDSTSTO_GPIO_PORT,LEDSTSTO_GPIO_PIN,GPIO_Pin_RESET); //启停指示灯灭

key_en=1;

}

}

// if(GPIO_ReadPin(DR_GPIO_PORT,DR_GPIO_PIN)==GPIO_Pin_SET)key_dir=0; //方向判断

// else if(key_dir==0)

// {

// for(dd=0;dd<500;dd++); //消抖

// if(GPIO_ReadPin(DR_GPIO_PORT,DR_GPIO_PIN)==GPIO_Pin_RESET)

// {

// dirflag=1-dirflag;

// if(dirflag==0)

// GPIO_WritePin(LEDDIR_GPIO_PORT,LEDDIR_GPIO_PIN,GPIO_Pin_RESET); //方向指示灯亮

// else

// GPIO_WritePin(LEDDIR_GPIO_PORT,LEDDIR_GPIO_PIN,GPIO_Pin_SET); //方向指示灯亮

// if(dirflag!=Dir)

// MOTORSTATE=STATESTOP;

// key_dir=1;

// }

// }

}

该函数主要是一些变量的赋值,状态机的切换,以及PID的运算功能函数!

我这里对于采样部分、过流、过压保护部分进行了详细的注释,大家可以看看。

#include "compu.h"

/******************** 对电机速度进行获取 *********************/

void SampleSpeed(void)

{

//根据电位器的值,计算设定速度,注意最大速度和最小速度的定义

unsigned int tem=0;

unsigned int st=0;

/******************** 读取ADC采取到的旋钮开关值 *********************/

st=SampleData[3];

/******************** 如果读取到的旋钮值小于旋钮最小值-10的话,则停止电机运行,给定目标速度为0 *********************/

if(st

SetSpeed=0;

/******************** 如果小于等于最小值,啥也不做 *********************/

else if(st<=NMINVD);

/******************** 如果小于最大值的话,那就代表希望电机运行起来 *********************/

else if(st<=NMAXVD)

{

tem=MINSPEED+KKN*(st-NMINVD);//根据旋钮值,给定目标值!

SetSpeed=tem;

}

/******************** 如果旋钮值大于最大的旋钮值,那速度给定最大速度 *********************/

else SetSpeed=MAXSPEED;

}

/******************** 对电压电流进行采集 *********************/

void SampleVI(void)

{

float t;

//定义电流故障计数周期变量、电流故障计数周期变量

static unsigned char IErCount=0,VErCount=0;

/******************** 下面是对采样电流进行措施分析 *********************/

if(SampleData[2]<=DIin)//如果采样到的电流值小于偏置值,将母线平均电流赋值给0

CanshuI=0;

else //否则是采样到的电流值大于偏置值

{

t=(SampleData[2]-DIin); //采样量减去偏置量,求取变化量

//t表示ADC采样的原始值,最大为4096;

//相对应的ADC=t时,电压量为x,而ADC=4096时对应的电压量为3.3V(这里因为是单位原因,电流是ma,所以电压*1000了的)

//因此x=t/4096*3300,这个是电压值,要求电流,根据欧姆定律,U/R即可,4.3是运放的放大倍数!

t=t*1.61;// /t=t/4096*3300/4.3/0.1; //0.1欧

CanshuI=t;

}

/******************** 过流保护,如果电流大于8A,则启动保护,停止电机运行! *********************/

if(CanshuI>=ISH*1000&&ErrorCode==0) //过流保护

{

IErCount++;//电流过流错误计数变量递增,如果大于设定的最大误差变量,则给定错误代码,停止电机

if(IErCount>=NumErr)

{ErrorCode=4;}//过流保护的故障代码是:4

}

else IErCount=0;

/******************** 下面是对采样母线电压进行措施分析 *********************/

t =SampleData[0];//读取采样到的母线电压

//t表示ADC采样的原始值,最大为4096;

//相对应的ADC=t时,电压量为x,而ADC=4096时对应的电压量为3.3V

//因此x=t/4096*3.3,这个是电压值

t=t/4096*3.3/RV1*(RV1+RV2);

CanshuV=t*10; //采集母线电压放大10倍

/******************** 过压保护,如果电压大于40V,则启动保护,停止电机运行! *********************/

if(CanshuV>=VSH*10&&ErrorCode==0) //过压判断

{

VErCount++;

if(VErCount>=NumErr)

{ErrorCode=6;}//过压保护的故障代码是:6

}

else VErCount=0;

}

其他.c文件这里就不再分析,相信大家能够看懂。


无感开环

该例程去除了霍尔换向的繁琐操作,采用反电动势过零点进行位置检测。

该例程中ADC的功能较为复杂,需要大家多花时间分析,无感控制是大趋势,非常建议大家多研究研究

void ADC_Configuration(void)

{

ADC_InitTypeDef ADC_InitStruct;

DMA_InitTypeDef DMA_InitStruct = {0};

__RCC_GPIOA_CLK_ENABLE();

__RCC_GPIOB_CLK_ENABLE();

__RCC_ADC_CLK_ENABLE();

//配置ADC测试IO口

PA00_ANALOG_ENABLE() ; //PA00 (AIN0) U相反电动势

PA01_ANALOG_ENABLE() ; //PA01 (AIN1) V相反电动势

PA03_ANALOG_ENABLE() ; //PA03 (AIN3) 母线电压

PA05_ANALOG_ENABLE() ; //PA05 (AIN5) W相反电动势

PA06_ANALOG_ENABLE() ; //PA06 (AIN6) 电流

PB00_ANALOG_ENABLE() ; //PB00 (AIN8) 电位器

ADC_InitStruct.ADC_AccEn = ADC_AccDisable;//不需要累加器

ADC_InitStruct.ADC_Align = ADC_AlignRight;//右对齐

ADC_InitStruct.ADC_ClkDiv = ADC_Clk_Div8; // ADCCLK=16MHz

ADC_InitStruct.ADC_DMAEn = ADC_DmaEnable;//使能DMA

ADC_InitStruct.ADC_InBufEn = ADC_BufDisable;//失能缓冲

ADC_InitStruct.ADC_OpMode = ADC_SingleChOneMode;//单次转换模式

ADC_InitStruct.ADC_SampleTime = ADC_SampTime10Clk;//采样频率

ADC_InitStruct.ADC_TsEn = ADC_TsDisable;//内置温度传感器失能

ADC_InitStruct.ADC_VrefSel = ADC_Vref_VDDA;//参考电压 选用VDDA

ADC_Init(&ADC_InitStruct);

CW_ADC->CR1_f.CHMUX = 0; // AN0

ADC_Enable();

// 使用4路DMA通道:CH1、CH2、CH3、 CH4

// CH1 将ADC单次单通道的采样结果传入RAM(ADC_ResultBuff[6])

// CH2 将ADC的CR1寄存器的配置值从RAM(ADC_CR1Array)传入寄存器

// CH3 将ADC的START寄存器的配置值从RAM(ADC_Start)传入寄存器

// CH1、CH2、CH3由ADC硬件触发

// CH4由ATIM硬件触发,启动ADC

//开启DMA时钟

__RCC_DMA_CLK_ENABLE();

DMA_InitStruct.DMA_DstAddress = (uint32_t)&SampleData[0]; // 目标地址

DMA_InitStruct.DMA_DstInc = DMA_DstAddress_Increase; // 目标地址递增

DMA_InitStruct.DMA_Mode = DMA_MODE_BLOCK; // BLOCK传输模式

DMA_InitStruct.DMA_SrcAddress = (uint32_t)&CW_ADC->RESULT0; // 源地址: ADC的结果寄存器

DMA_InitStruct.DMA_SrcInc = DMA_SrcAddress_Fix; // 源地址固定

DMA_InitStruct.DMA_TransferCnt = 0x6; // DMA传输次数

DMA_InitStruct.DMA_TransferWidth = DMA_TRANSFER_WIDTH_16BIT; // 数据位宽16bit

DMA_InitStruct.HardTrigSource = DMA_HardTrig_ADC_TRANSCOMPLETE; // ADC转换完成硬触发

DMA_InitStruct.TrigMode = DMA_HardTrig; // 硬触发模式

DMA_Init(CW_DMACHANNEL1, &DMA_InitStruct);

DMA_Cmd(CW_DMACHANNEL1, ENABLE);

DMA_InitStruct.DMA_DstAddress = (uint32_t)&CW_ADC->CR1; // 目标地址

DMA_InitStruct.DMA_DstInc = DMA_DstAddress_Fix; // 目标地址固定

DMA_InitStruct.DMA_Mode = DMA_MODE_BLOCK; // BLOCK传输模式

DMA_InitStruct.DMA_SrcAddress = (uint32_t)&ADC_CR1Array[0]; // 源地址

DMA_InitStruct.DMA_SrcInc = DMA_SrcAddress_Increase; // 源地址递增

DMA_InitStruct.DMA_TransferCnt = 0x5; // DMA传输次数

DMA_InitStruct.DMA_TransferWidth = DMA_TRANSFER_WIDTH_8BIT; // 数据位宽8bit

DMA_InitStruct.HardTrigSource = DMA_HardTrig_ADC_TRANSCOMPLETE; // ADC转换完成硬触发

DMA_InitStruct.TrigMode = DMA_HardTrig; // 硬触发模式

DMA_Init(CW_DMACHANNEL2, &DMA_InitStruct);

DMA_Cmd(CW_DMACHANNEL2, ENABLE);

DMA_InitStruct.DMA_DstAddress = (uint32_t)&CW_ADC->START; // 目标地址

DMA_InitStruct.DMA_DstInc = DMA_DstAddress_Fix; // 目标地址固定

DMA_InitStruct.DMA_Mode = DMA_MODE_BLOCK; // BLOCK传输模式

DMA_InitStruct.DMA_SrcAddress = (uint32_t)&ADC_Start; // 源地址

DMA_InitStruct.DMA_SrcInc = DMA_SrcAddress_Fix; // 源地址固定

DMA_InitStruct.DMA_TransferCnt = 0x5; // DMA传输次数

DMA_InitStruct.DMA_TransferWidth = DMA_TRANSFER_WIDTH_8BIT; // 数据位宽8bit

DMA_InitStruct.HardTrigSource = DMA_HardTrig_ADC_TRANSCOMPLETE; // ADC转换完成硬触发

DMA_InitStruct.TrigMode = DMA_HardTrig; // 硬触发模式

DMA_Init(CW_DMACHANNEL3, &DMA_InitStruct);

DMA_Cmd(CW_DMACHANNEL3, ENABLE);

DMA_InitStruct.DMA_DstAddress = (uint32_t)&CW_ADC->START; // 目标地址

DMA_InitStruct.DMA_DstInc = DMA_DstAddress_Fix; // 目标地址固定

DMA_InitStruct.DMA_Mode = DMA_MODE_BLOCK; // BLOCK传输模式

DMA_InitStruct.DMA_SrcAddress = (uint32_t)&ADC_Start; // 源地址

DMA_InitStruct.DMA_SrcInc = DMA_SrcAddress_Fix; // 源地址固定

DMA_InitStruct.DMA_TransferCnt = 0x1; // DMA传输次数

DMA_InitStruct.DMA_TransferWidth = DMA_TRANSFER_WIDTH_8BIT; // 数据位宽8bit

DMA_InitStruct.HardTrigSource = DMA_HardTrig_ATIM_CH1A2A3A4; // ATIM硬件触发

DMA_InitStruct.TrigMode = DMA_HardTrig; // 硬触发模式

DMA_Init(CW_DMACHANNEL4, &DMA_InitStruct);

DMA_Cmd(CW_DMACHANNEL4, ENABLE);

//开启DMA中断,也就是ADC检测完毕后通过DMA传输后,会产生一个中断,在中断中再重新配置ADC

DMA_ITConfig(CW_DMACHANNEL1, DMA_IT_TC, ENABLE);

//失能中断后配置好中断在使能!

__disable_irq();

NVIC_EnableIRQ(DMACH1_IRQn);

__enable_irq();

}

该例程中需要详细分析MOTORCONTROL.c文件内容,这个是无感换向的核心部分!


无感闭环

该例程中主要在无感开环的基础上增加了PID和过流过压保护功能!也是在MOTORCONTROL.c文件中!

如果大家电机跑不起来,可以修改:QDPwm的值、也可以配置sensorlessP.c文件的参数量,这些参数量是经验值,需要自己多测试才能找到符合自己电机的参数,我也还在研究中,就不献丑了。。。这个无感部分的软件部分,我还在学习中,未来有机会再和大家一起分享吧。


整体设计框图

poYBAGK_4faAax_OAAVXcGrnuyE935.png
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 驱动系统
    +关注

    关注

    3

    文章

    340

    浏览量

    26702
  • 无刷直流电机

    关注

    60

    文章

    654

    浏览量

    45553
  • CW32
    +关注

    关注

    1

    文章

    113

    浏览量

    224
  • 武汉芯源
    +关注

    关注

    1

    文章

    57

    浏览量

    143
收藏 人收藏

    评论

    相关推荐

    直流电机直流电机驱动器有区别吗?

    直流电机直流电机驱动器有区别吗?
    发表于 09-02 10:32

    直流电机直流电机的特性与区别

    ,需要定期维护更换刷子。  尽管有诸多劣势,但直流电机有一显著优势:成本。由于控制直流电机相对简单,因此还广泛用于系统成本是主要
    发表于 01-28 10:07

    四轴飞行器直流电机驱动控制设计的实现

    直流电机直流电机驱动控制系统包括驱动电路和
    发表于 10-08 15:13

    直流电机的工作原理和驱动原理

    基于 F2812DSP 直流电机驱动电路 PCB 板制作电调及软件测试心得体会(一)
    发表于 05-27 13:09

    什么是直流电机(BLDC)以及它的应用

    ,而无直流电机驱动桥则需要 6 只功率管)。图1所示为其中一种小功率三相、星形连接、单副磁对极的
    发表于 07-04 07:00

    直流电机与有直流电机的对比

    ,寿命更长。直流是基于交流调速原理基础上制造出来的,性能方面既有直流电机的启动转矩大,转速稳定调速方便,又有交流电机的结构简单没有易损件
    发表于 03-16 16:08

    请问怎样去设计直流电机

    直流电机驱动原理是什么?直流电机的硬件该如
    发表于 05-07 06:31

    直流电机的matlab仿真

    直流电机的matlab仿真 机电技术 2 0 1 1 年8
    发表于 07-05 06:28

    直流电机的matlab仿真

    直流电机的matlab仿真.pdf60机电技术2011 年 8
    发表于 07-05 06:38

    用简易桥驱动直流电机

    用简易桥驱动直流电机.pdf应用40用简易桥驱动
    发表于 07-05 07:59

    直流电机直流电机的优缺点比较

    直流电机的优点有哪些?缺点又有哪些?直流电机的优点有哪些?缺点又有哪些?
    发表于 07-20 06:38

    直流电机驱动方法有哪些

    直流电机(BLDC)具有哪些特点?直流电机是如何进行工作的?
    发表于 08-11 07:48

    直流电机是如何进行换向的

    什么是直流电机直流电机是由哪些部分组成的?
    发表于 08-17 07:51

    直流电机

    直流电机方波驱动,SPWM,SVPWM,FOC之间的区别和优缺点
    发表于 12-02 09:29

    基于武汉芯源CW32F030C8T6直流无刷电机评估开发板的介绍

    基础应用。CW32F030C8T6基于ARM公司Cortex-M0+内核,最高主频64MHZ,64K字节FLASH,8K字节RAM,采用LQFP48封装,是一款高性价比的国产MCU。基****于CW32F030C8T6
    发表于 07-19 17:09