上兩個月做了個關于尿殘渣的新項目,用到了電機驅動芯片PCL6045BL。這個系統方案有一個20余年工作經驗的老工程師提出來,主要采用的是STM32操作PCL6045,進而控制多軸電機運動。
于是公司從每個不同項目組抽選人員組成了一個團隊。本人負責軟件部分,負責編寫驅動程序和調試電路板。
全新項目,有一定挑戰性。經過分析,決定采用STM32總線方式(FSMC)驅動PCL6045B。對比FSMC的四種總線操作時序和PCL6045B操作時序。認為應該選用STM32的PCCARD模式操作。從數據庫中查找了一些文獻資料,就開干起來了。
兩名硬件工程師按我的需求設計好硬件電路板。
接下來分成以下幾個步驟進行:
首先就是建立通訊。讓ARM能跟PCL6045B建立起來通訊。
這一步主要就是配置STM32的FSMC為PCCARD模式,配置的過程就是按官方手冊上配置的。先系統初始化配置好STM32的時鐘(不贅述)。然后就是初始化端口,這里需要注意的是,要將跟FSMC相關的端口都設置為特殊功能口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卡模式時序。如下:
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);
}
到這里,就算配置完成。主函數調用。
然后主函數通過控制PCL6045的其中一個口實驗成功,于是就算建立起了通信。
接下來就可以試驗控制PCL6045參數指定數目的脈沖了。
于是,我根據手冊又編寫了如下小測試程序:
p645_wreg(AXS_AU, WPRMD, 0x00000041); //定長運動模式
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);
運行,成功產生脈沖!
正常過程很簡單,但是,實際操作中,特別是第一次摸索的時候,遇到很多棘手的問題。
比如PCL6045 硬件部分IF0 IF1 要接成8086方式。
一開始,我們的硬件電路按如下圖鏈接:
好像也沒什么問題,于是就接著往下調,發現了一個很郁悶的問題,當時把問題描述如下:
#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 軸寄存器的起始地址
幾個地址均已經能夠操作,能控制各個軸電機運動。
STM32通過FSMC與DSP通訊,通過16位傳送數據。
#define outpw( address,data) (*(unsigned short *)(address)=(data));
unsigned int inpw(unsigned int address) //讀寫某一段內存
{
unsigned short data;
data=*(unsigned short*)address;
return data;
}
寫寄存器函數如下:
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]);
// Delay_Us(1); //就算加了延時也無效
outpw (base_addr 3, udt. idata[1]);
// Delay_Us(1); //就算加了延時也無效
outpw (base_addr, rwcom);
}
//讀寄存器函數如下:
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);
}
在設置解碼倍頻時,發現,無論我寫入的是哪個數(00,01,10),都不能改變編碼器讀出的數據,即始終是默認的1倍解碼,即相關寄存器兩個bit是00的情況.
于是我猜想是不是我寫入的數據不能改變高16位,只能改變低16位.
所以我就做了以下測試工作:
現在發現向DSP各軸緩沖區寫入數據時,總是不能寫進去高16位,而低十六位能寫進去。比如,我寫p645_wreg(AXS_AX,WRENV1,0x00000001); //控制脈沖類型。
p645_wreg(AXS_AX,WRENV1,0x00000002);
p645_wreg(AXS_AX,WRENV1,0x00000003);
分別能看到輸出不同類型的脈沖。證明低位操作有效!
但是當我寫做定長測試時,代碼如下
p645_wreg(AXS_AZ, WPRMD, 0x00000041); //定長運動模式
p645_wreg(AXS_AZ, WRMV, 65536L);//這里寫入65535以下的數均能準確控制電機走的步數,超過65535,則會出現電機持續運動而不受控制的異常狀況!
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時我讀取出COUNT1中數據也是沒有規律的。而不超過65535時,則完全正常!
1.當寫入65535時,電機運轉過程讀出數據如下:
Counter1 Counter2
指令 編碼器(這里是默認的1倍,跟我們的編碼器對應上是對的)
0000019662 0000000958
0000039790 0000001937
0000059918 0000002917
0000065535 0000003191
0000065535 0000003191
0000065535 0000003191
0000065535 0000003191
2.當寫入65536及以上時,電機運轉過程讀出數據如下:
Counter1 Counter2
指令 編碼器(這里是默認的1倍,跟我們的編碼器對應上是對的)
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
以上數據均不超過65535
基于上述現象,我做了個程序來測試 讀寫,發現,我寫入的數據到緩沖去時超過0x00ffffff時,讀出來的數據是不對的,只有低24位能讀出來,高8位讀出來的均是0.
寫寄存器函數修改如下:
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);
}
測試代碼如下:
p645_wreg(AXS_AZ,WRENV2,0xffffffff);
data3=inpw (AXS_AZ 2);
data4=inpw (AXS_AZ 3);
讀出的數據只能是data3=65535;data4=255,即最高8位丟失!
當p645_wreg(,,); 寫入的數據是低0x00ffffff以下的數據時,data3;data4讀出來的數據是對的。即寫什么讀出什么。這就是對我現在遇到的問題的詳細敘述。
后來經過一番折騰,經過大量的測量觀察發現。是高16位中的高低字節順序被對調了。郁悶了。于是我與日本方便的工程師交流,他們讓將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
我感覺很奇怪。地址線的不同應該只是地址的不一樣而已,怎么會導致高兩個字節的高低8位對調呢。日本方面說是他們的芯片內部設計是那樣的,而我在日脈手冊上沒有看到任何說明。
之后進一步研究,我的PCL6045控制自如,全部功能順利驗證了一遍。
以上就是我開發PCL6045B過程中的開發體會。轉載請注明出處,有問題歡迎交流。