基于STM32的PCL6045B开发体会
于是公司从每个不同项目组抽选人员组成了一个团队。本人负责软件部分,负责编写驱动程序和调试电路板。
全新项目,有一定挑战性。经过分析,决定采用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) //读寄存器
{
unionudata{
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的情况.
评论