專注電子技術(shù)學(xué)習(xí)與研究
當(dāng)前位置:單片機(jī)教程網(wǎng) >> MCU設(shè)計(jì)實(shí)例 >> 瀏覽文章

基于STM32的PCL6045B開發(fā)體會(huì)

作者:佚名   來源:本站原創(chuàng)   點(diǎn)擊數(shù):  更新時(shí)間:2014年03月02日   【字體:

上兩個(gè)月做了個(gè)關(guān)于尿殘?jiān)男马?xiàng)目,用到了電機(jī)驅(qū)動(dòng)芯片PCL6045BL。這個(gè)系統(tǒng)方案有一個(gè)20余年工作經(jīng)驗(yàn)的老工程師提出來,主要采用的是STM32操作PCL6045,進(jìn)而控制多軸電機(jī)運(yùn)動(dòng)。

于是公司從每個(gè)不同項(xiàng)目組抽選人員組成了一個(gè)團(tuán)隊(duì)。本人負(fù)責(zé)軟件部分,負(fù)責(zé)編寫驅(qū)動(dòng)程序和調(diào)試電路板。
全新項(xiàng)目,有一定挑戰(zhàn)性。經(jīng)過分析,決定采用STM32總線方式(FSMC)驅(qū)動(dòng)PCL6045B。對(duì)比FSMC的四種總線操作時(shí)序和PCL6045B操作時(shí)序。認(rèn)為應(yīng)該選用STM32的PCCARD模式操作。從數(shù)據(jù)庫(kù)中查找了一些文獻(xiàn)資料,就開干起來了。
兩名硬件工程師按我的需求設(shè)計(jì)好硬件電路板。

接下來分成以下幾個(gè)步驟進(jìn)行:
首先就是建立通訊。讓ARM能跟PCL6045B建立起來通訊。
這一步主要就是配置STM32的FSMC為PCCARD模式,配置的過程就是按官方手冊(cè)上配置的。先系統(tǒng)初始化配置好STM32的時(shí)鐘(不贅述)。然后就是初始化端口,這里需要注意的是,要將跟FSMC相關(guān)的端口都設(shè)置為特殊功能口AF。如下:
void PCCARD_IO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD RCC_APB2Periph_GPIOE RCC_APB2Periph_GPIOF RCC_APB2Periph_GPIOG,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 GPIO_Pin_2 GPIO_Pin_3 GPIO_Pin_4 GPIO_Pin_12 GPIO_Pin_5;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOF, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 GPIO_Pin_8 GPIO_Pin_9 GPIO_Pin_10 GPIO_Pin_11 GPIO_Pin_12 GPIO_Pin_13 GPIO_Pin_14 GPIO_Pin_15;
GPIO_Init(GPIOE, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14 GPIO_Pin_15 GPIO_Pin_10 GPIO_Pin_9 GPIO_Pin_8 GPIO_Pin_1 GPIO_Pin_0;
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 GPIO_Pin_5;//NOE,NWE引腳
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//cs
GPIO_Init(GPIOG, &GPIO_InitStructure);
}
接下來就是配置FSMC PC卡模式時(shí)序。如下:
void PCCARD_Init(void)
{
FSMC_PCCARDInitTypeDef FSMC_PCCARDInitStructure;
FSMC_NAND_PCCARDTimingInitTypeDef p;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);////
p.FSMC_SetupTime = 0x02;
p.FSMC_WaitSetupTime = 0x04;
p.FSMC_HoldSetupTime = 0x02;
p.FSMC_HiZSetupTime = 0x03;
FSMC_PCCARDInitStructure.FSMC_Waitfeature = FSMC_Waitfeature_Enable ; //使能等待
FSMC_PCCARDInitStructure.FSMC_TCLRSetupTime = 0x10;
FSMC_PCCARDInitStructure.FSMC_TARSetupTime = 0x10;
FSMC_PCCARDInitStructure.FSMC_CommonSpaceTimingStruct = &p;
FSMC_PCCARDInitStructure.FSMC_AttributeSpaceTimingStruct = &p;
FSMC_PCCARDInitStructure.FSMC_IOSpaceTimingStruct = &p;
FSMC_PCCARDInit(&FSMC_PCCARDInitStructure);
FSMC_PCCARDCmd(ENABLE);
}
到這里,就算配置完成。主函數(shù)調(diào)用。
然后主函數(shù)通過控制PCL6045的其中一個(gè)口實(shí)驗(yàn)成功,于是就算建立起了通信。
接下來就可以試驗(yàn)控制PCL6045參數(shù)指定數(shù)目的脈沖了。
于是,我根據(jù)手冊(cè)又編寫了如下小測(cè)試程序:
p645_wreg(AXS_AU, WPRMD, 0x00000041); //定長(zhǎng)運(yùn)動(dòng)模式
p645_wreg(AXS_AU, WRMV, 4012000000);
p645_wreg(AXS_AU, WRFL, 500L);
p645_wreg(AXS_AU, WRFH, 20000L);
p645_wreg(AXS_AU, WRUR, 200L);
p645_wreg(AXS_AU, WRDR, 400L);
p645_wreg(AXS_AU, WRMG, 29L);
p645_wcom(AXS_AU,STAUD);
運(yùn)行,成功產(chǎn)生脈沖!
正常過程很簡(jiǎn)單,但是,實(shí)際操作中,特別是第一次摸索的時(shí)候,遇到很多棘手的問題。
比如PCL6045 硬件部分IF0 IF1 要接成8086方式。
一開始,我們的硬件電路按如下圖鏈接:
好像也沒什么問題,于是就接著往下調(diào),發(fā)現(xiàn)了一個(gè)很郁悶的問題,當(dāng)時(shí)把問題描述如下:
#define AXS_AX ((volatile unsigned int ) 0x90000000)
#define AXS_AY ((volatile unsigned int ) 0x90000004)
#define AXS_AZ ((volatile unsigned int ) 0x9000008)
#define AXS_AU ((volatile unsigned int ) 0x900000c)
其中 AXS_AX、AXS_AY、AXS_AZ、AXS_AU 分別表示 X、Y、Z、U 軸寄存器的起始地址
幾個(gè)地址均已經(jīng)能夠操作,能控制各個(gè)軸電機(jī)運(yùn)動(dòng)。
STM32通過FSMC與DSP通訊,通過16位傳送數(shù)據(jù)。
#define outpw( address,data) (*(unsigned short *)(address)=(data));
unsigned int inpw(unsigned int address) //讀寫某一段內(nèi)存
{
unsigned short data;
data=*(unsigned short*)address;
return data;
}
寫寄存器函數(shù)如下:
void p645_wreg(unsigned int base_addr,unsigned int rwcom,unsigned int data) //向某個(gè)軸的某個(gè)寄存器寫入數(shù)據(jù)
{
union udata{
unsigned int ldata;
unsigned short idata[2];
}udt;
udt.ldata = data;
outpw (base_addr 2, udt. idata[0]);
// Delay_Us(1); //就算加了延時(shí)也無效
outpw (base_addr 3, udt. idata[1]);
// Delay_Us(1); //就算加了延時(shí)也無效
outpw (base_addr, rwcom);
}
//讀寄存器函數(shù)如下:
unsigned long p645_rreg (unsigned int base_addr,unsigned int rrcom) //讀寄存器
{
union udata{
unsigned int ldata;
unsigned short idata[2];
}udt;
outpw(base_addr, rrcom);
// Delay_Us(1);
udt.idata[0] = inpw (base_addr 2);
// Delay_Us(1);
udt.idata[1] = inpw (base_addr 3);
return(udt. ldata);
}
在設(shè)置解碼倍頻時(shí),發(fā)現(xiàn),無論我寫入的是哪個(gè)數(shù)(00,01,10),都不能改變編碼器讀出的數(shù)據(jù),即始終是默認(rèn)的1倍解碼,即相關(guān)寄存器兩個(gè)bit是00的情況.
于是我猜想是不是我寫入的數(shù)據(jù)不能改變高16位,只能改變低16位.
所以我就做了以下測(cè)試工作:
現(xiàn)在發(fā)現(xiàn)向DSP各軸緩沖區(qū)寫入數(shù)據(jù)時(shí),總是不能寫進(jìn)去高16位,而低十六位能寫進(jìn)去。比如,我寫p645_wreg(AXS_AX,WRENV1,0x00000001); //控制脈沖類型。
p645_wreg(AXS_AX,WRENV1,0x00000002);
p645_wreg(AXS_AX,WRENV1,0x00000003);
分別能看到輸出不同類型的脈沖。證明低位操作有效!
但是當(dāng)我寫做定長(zhǎng)測(cè)試時(shí),代碼如下
p645_wreg(AXS_AZ, WPRMD, 0x00000041); //定長(zhǎng)運(yùn)動(dòng)模式
p645_wreg(AXS_AZ, WRMV, 65536L);//這里寫入65535以下的數(shù)均能準(zhǔn)確控制電機(jī)走的步數(shù),超過65535,則會(huì)出現(xiàn)電機(jī)持續(xù)運(yùn)動(dòng)而不受控制的異常狀況!
p645_wreg(AXS_AZ, WRFL, 500L);
p645_wreg(AXS_AZ, WRFH, 2000L);
p645_wreg(AXS_AZ, WRUR, 200L);
p645_wreg(AXS_AZ, WRDR, 400L);
p645_wreg(AXS_AZ, WRMG, 5L);
p645_wcom(AXS_AZ,STAUD);
另外,超過65535時(shí)我讀取出COUNT1中數(shù)據(jù)也是沒有規(guī)律的。而不超過65535時(shí),則完全正常!
1.當(dāng)寫入65535時(shí),電機(jī)運(yùn)轉(zhuǎn)過程讀出數(shù)據(jù)如下:
Counter1 Counter2
指令 編碼器(這里是默認(rèn)的1倍,跟我們的編碼器對(duì)應(yīng)上是對(duì)的)
0000019662 0000000958
0000039790 0000001937
0000059918 0000002917
0000065535 0000003191
0000065535 0000003191
0000065535 0000003191
0000065535 0000003191
2.當(dāng)寫入65536及以上時(shí),電機(jī)運(yùn)轉(zhuǎn)過程讀出數(shù)據(jù)如下:
Counter1 Counter2
指令 編碼器(這里是默認(rèn)的1倍,跟我們的編碼器對(duì)應(yīng)上是對(duì)的)
0000019662 0000000958
0000039790 0000001937
0000059917 0000002917
0000014509 0000003898
0000034637 0000004878
0000054764 0000005857
0000009356 0000006837
0000029484 0000007818
0000049611 0000008797
0000004203 0000009776
0000044458 0000011737
0000064586 0000012718
0000019177 0000013697
0000039305 0000014676
0000059433 0000015657
0000034152 0000017617
0000054279 0000018596
0000008871 0000019577
0000028999 0000020557
0000049126 0000021536
0000003718 0000022516
0000023846 0000023497
0000043973 0000024476
0000018692 0000026436
0000058948 0000028397
0000013539 0000029375
0000033667 0000030355
0000053794 0000031335
以上數(shù)據(jù)均不超過65535
基于上述現(xiàn)象,我做了個(gè)程序來測(cè)試 讀寫,發(fā)現(xiàn),我寫入的數(shù)據(jù)到緩沖去時(shí)超過0x00ffffff時(shí),讀出來的數(shù)據(jù)是不對(duì)的,只有低24位能讀出來,高8位讀出來的均是0.
寫寄存器函數(shù)修改如下:
void p645_wreg(unsigned int base_addr,unsigned int rwcom,unsigned int data)
{
union udata{
unsigned int ldata;
unsigned short idata[2];
}udt;
udt.ldata = data;
outpw (base_addr 2, udt. idata[0]);
outpw (base_addr 3, udt. idata[1]);
//outpw (base_addr, rwcom);
}
測(cè)試代碼如下:
p645_wreg(AXS_AZ,WRENV2,0xffffffff);
data3=inpw (AXS_AZ 2);
data4=inpw (AXS_AZ 3);
讀出的數(shù)據(jù)只能是data3=65535;data4=255,即最高8位丟失!
當(dāng)p645_wreg(,,); 寫入的數(shù)據(jù)是低0x00ffffff以下的數(shù)據(jù)時(shí),data3;data4讀出來的數(shù)據(jù)是對(duì)的。即寫什么讀出什么。這就是對(duì)我現(xiàn)在遇到的問題的詳細(xì)敘述。

后來經(jīng)過一番折騰,經(jīng)過大量的測(cè)量觀察發(fā)現(xiàn)。是高16位中的高低字節(jié)順序被對(duì)調(diào)了。郁悶了。于是我與日本方便的工程師交流,他們讓將STM32的A1~A4與PCL6045的A1~A4相連,(原來是STM32的A0~A3與PCL6045的A1~A4)
于是地址也更改為
#define AXS_AX 0x90000000
#define AXS_AY 0x90000008
#define AXS_AZ 0x90000010
#define AXS_AU 0x90000018
我感覺很奇怪。地址線的不同應(yīng)該只是地址的不一樣而已,怎么會(huì)導(dǎo)致高兩個(gè)字節(jié)的高低8位對(duì)調(diào)呢。日本方面說是他們的芯片內(nèi)部設(shè)計(jì)是那樣的,而我在日脈手冊(cè)上沒有看到任何說明。
之后進(jìn)一步研究,我的PCL6045控制自如,全部功能順利驗(yàn)證了一遍。
以上就是我開發(fā)PCL6045B過程中的開發(fā)體會(huì)。轉(zhuǎn)載請(qǐng)注明出處,有問題歡迎交流。

關(guān)閉窗口

相關(guān)文章