基于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,降壓型電路。
經過上述篩選,我們可以看到,符合條件的有19款,我們按價格升序、選擇現貨商品。進一步觀看IC的相關描述,在考慮價格的基礎上,還要考慮是否符合我們的要求。
我這邊看到了一款芯龍的Buck芯片,價格也能接受,庫存也特別豐富,最主要的是:芯龍是國產芯片!!!不用考慮了,就這款了。
OK,選擇好芯片后,進入數據手冊讀取相關參數。
我們可以知道的是:
輸入電壓范圍是:4.5V-40V。 我們輸入是24V,完全滿足裕量和要求。
輸出電壓范圍是:1.23V-37V。 我們輸出是10V-20V,也完全滿足裕量和要求。
輸出電流是:3A。 我們需要的也是2.4A以上的電路,3A完全滿足要求。
開關頻率:150KHz。 還可以,這個速度。
我們從描述中可以知道:
1、輸入引腳,需要放置一個合適的大容量電容,去消除輸入噪聲。
2、GND引腳在布局的時候需要考慮到:GND引腳需要放置在肖特基二極管到輸出電容地路徑的外部,以防止開關電流尖峰感應產生電壓噪聲。
3、反饋電壓是:1.23V.
4、ON/OFF引腳如果懸空,默認低電平。該引腳低電平則芯片工作,若高電平則芯片不工作。
我們從描述中可以知道:
1、R1采用接近1K歐姆的電阻,使用1%的精度。
2、C1和CFF是可選擇的,為了提高穩定性、降低供電噪聲。CIN和C1必須靠近放置在引腳1和引腳3。
3、對于輸出電壓高于10V的情況,CFF電容是需要的,此時的CFF是作為補償電容使用,與R2并聯使用,其值在100pf到33nf之間。CFF的電容值等于(1/(31×1000×R2))。
綜上所述,我們選型參數為:
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的整體方案為:
12VBuck部分
考慮到霍爾傳感器的工作電壓是5V,因此需要將12V再Buck變換成5V。本項目采用首鼎的SD8942,至于為什么選擇它,因為我買了好多這個物料,庫存很多,不能浪費錢。。。而且這個12V將壓成5V的方案我也驗證過,沒什么問題,最主要的是:肖特基二極管都不需要,外圍電路很簡單。
我們從描述中可以知道:
1、輸入電壓范圍為:4.5V-16V 我們輸入電壓是12V,滿足要求。
2、開關頻率600KHz 開關頻率速度快。
3、輸出電流:2A 電機空載電流0.8A,2倍裕量,滿足要求。
4、不需要肖特基二極管,內部集成 節省成本。
5、芯片效率:96% 效率高。
6、參考電壓:0.6V 方便計算回饋電阻阻值。
典型應用中就給出了一個輸出5V/2A的基本電路,我們可以直接采用。沒什么比較特殊的,主要是電容耐壓高點就好,其他的沒什么考慮的。因此,最終電路圖如下所示:
因此電源部分已經整體解決完畢。
驅動硬件部分
我們想開環驅動無刷直流電機的話,需要使用到什么功能?
1、供電電源部分:24V供電機;12V供MOS驅動電路;5V供霍爾驅動電路;以及主控芯片的供電
2、主控芯片:發送6路PWM信號以及3路霍爾傳感器的檢測信號;
3、MOS驅動電路+三相全橋電路;
4、電位器電路,通過旋鈕控制速度;
5、OLED顯示功能電路
6、電流采樣部分
因此我們不妨從這幾個電路進行入手分析,值得注意的是:主控芯片以及供電電源部分我們不再分析,電源在上面已經分析過了,主控芯片則是采用武漢芯源半導體研發的CW32F030C8T6;
MOS驅動電路
我們采用的MOS驅動芯片是EG3013,為什么選擇它?你自己看吧:(上次實驗室做實驗,需要柵極驅動IC,就買了好多個,最后板子做出來焊接完畢后我才發現,李芳姐用的柵極驅動IC竟然也是這顆物料!)
該芯片的LIN是一個低電平有效的引腳!在程序中,有一個關于AL、BL、CL打開或關閉的GPIO配置,這里就是相反的邏輯!!!所以各位使用的時候根據自己的IC進行修改即可!
FR107是為了加快開通效率的,用肖特基二極管也可以!但是官方用的FR107,這顆物料我在做動量倫的時候也買了的,所以我就按照官方的做就行了。10uF是升壓電容,這個阻值是我問屹晶微電子有限公司的一個技術人員,他告訴我,一般用10uf就足夠了!這里建議使用封裝為1206的,保證功率!我電路中用的0805,我的物料只有0805了....使用起來沒什么問題,我驗證過了!最后就是上下MOS的驅動信號了,加上電阻和二極管是為了防止寄生電容和回路電感!!!減小振鈴現象。加上一個R組成RLC電路,可以吸收寄生參數;而二極管主要是提供一個續流通道。具體可參考視頻:https://b23.tv/9a7pe1Q
三相全橋電路
此處的NMOS選用的是:
我主要是考慮電壓和電流要大一點,RDS小一點,防止發熱嚴重。最后就是考慮價格問題。
電流采樣電路
型號為:
價格便宜!!!其次其最大能過的電流為:2/0.01=20A!我們平常哪有這么高電壓喲,有個5A、6A的對我這種小白而言,就要關閘了!!!哈哈
霍爾接口電路
其中:C14、C15、C16是濾波作用;R3、R4、R5是為了拉高三個霍爾信號引腳,因為120°的霍爾傳感器不存在111的情況,也是一種保護作用吧!我這里沒選擇5Pin的接口端子是因為我只有3P和2P的物料,不想再買了....
以上的電路,足以跑起開環,下面就是閉環的一些保護功能,比如:電流檢測、電壓保護、溫度保護等等。我就不一一解釋其工作原理了,這個電路圖是李芳老師的書本里面的,書里面描述的更詳細,需要的可以在附件進行下載!我就不在這獻丑了!我這里就簡單展示一下原理圖即可,具體如何工作的書中有所描述。
運放電路
這個運放書中一摸一樣,具體的放大倍數以及工作原理請參考書籍:無刷直流電機控制應用 基于STM8S系列單片機
值得注意的是:這里面關乎到程序的采樣問題,一定要弄明白!我在程序中有寫那些數值是如何算出來的!
這都是一些閉環時加的保護電路,很簡單,相信你可以自己分析。
反電動勢檢測電路
這個電路關乎到無感驅動電機的時候使用。這個數值也是有講究的,請將這個電路對比檢測母線電壓電路,你會發現系數的關系,這個關系需要應用到無感電路中去!
整個電路都沒改動,都是參考:立創開源硬件平臺:Beauty_Light,在此感謝大佬的硬件電路參考設計!!!
軟件部分
有感開環
在開環測試中,最主要的就是需要根據霍爾換向表進行換向操作,只要換向無誤,其他就是改變占空比加減速的問題,因此最為重要的就是真值表,比如李芳姐姐官方的真值表如下所示:
你就需要根據你電機廠商給你的真值表進行相應的改變,這里貼出我電機的真值表:
代表什么意思呢?
比如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文件的參數量,這些參數量是經驗值,需要自己多測試才能找到符合自己電機的參數,我也還在研究中,就不獻丑了。。。這個無感部分的軟件部分,我還在學習中,未來有機會再和大家一起分享吧。
整體設計框圖
-
驅動系統
+關注
關注
3文章
371瀏覽量
26939 -
無刷直流電機
+關注
關注
61文章
689瀏覽量
46158 -
CW32
+關注
關注
1文章
203瀏覽量
641 -
武漢芯源
+關注
關注
1文章
66瀏覽量
255
發布評論請先 登錄
相關推薦
評論