基于STM32的PCL6045B开发体会

发布者:自在自由最新更新时间:2015-05-11 来源: 51hei关键字:STM32  PCL6045B  开发体会 手机看文章 扫描二维码
随时随地手机看文章
上两个月做了个关于尿残渣的新项目,用到了电机驱动芯片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的情况.[page]
于是我猜想是不是我写入的数据不能改变高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过程中的开发体会。转载请注明出处,有问题欢迎交流。

关键字:STM32  PCL6045B  开发体会 引用地址:基于STM32的PCL6045B开发体会

上一篇:STM32中的tic与toc,用SysTick统计代码段执行时间
下一篇:STM32学习体会

推荐阅读最新更新时间:2024-03-16 14:01

一种基于STM32的心电采集仪设计
  如今,心血管类疾病已经成为威胁人类身体健康的重要疾病之一,而清晰有效的心电图为诊断这类疾病提供了依据,心电采集电路是心电采集仪的关键部分,心电信号属于微弱信号,其频率范围在0.03~100 Hz之间,幅度在0~5 mV之间,同时心电信号还掺杂有大量的干扰信号,因此,设计良好的滤波电路和选择合适的控制器是得到有效心电信号的关键。基于此,本文设计了以STM32为控制核心,AD620和OP07为模拟前端的心电采集仪,本设计简单实用,噪声干扰得到了有效抑制。   1 总体设计方案   心电采集包括模拟采集和数字处理两部分,本设计通过AgCl电极和三导联线心电采集线采集人体心电信号,通过前置放大电路,带通滤波电路,50 Hz双T陷波
[单片机]
一种基于<font color='red'>STM32</font>的心电采集仪设计
STM32中SysTick在3.5固件库中的应用(1)
一、SysTick STM32内核中有一个系统定时器,它是一个24位递减计数器。工作原理是系统时基定时器设定初值并使能后,每经过1个系统时钟周期,计数值就减,当计数值减到0时,系统定时器会重新自动重装初值,并继续下一次计数,同时内部的COUNTFLAG标志位会置位。触发中断。 在很早的固件库中,提供了很多函数,来对SysTick进行设置,但是到了3.5版本的标准固件库中,移除了相关驱动函数,用户必须调用CMSIS 定义的函数,其中CMSIS只提供了一个Systick设置的函数,替代了STM32原来有的所有的驱动函数,这样做的目的,可能是简化Systick 的设置,可是降低了用户对SysTick的可控性。 在CMSIS中提供的函数是
[单片机]
采用STM32 单片机的太阳能LED街灯解决方案
  随着化石类能源的日益减少,以及温室气体的过度排放导致全球变暖问题越来越受到重视,人们一方面在积极开发各类可再生 新能源 ,另一方面也在倡导 节能减排 的绿色环保技术。 太阳能 作为取之不尽、用之不竭的 清洁能源 ,成为众多可再生能源的重要代表;而在照明领域,寿命长、节能、安全、绿色环保、色彩丰富、微型化的 LED 固态照明 也已被公认为世界一种节能环保的重要途径。太阳能-LED街灯同时整合了这两者的优势,利用清洁能源以及高效率的LED实现 绿色照明 。   本文介绍的太阳能-LED街灯方案,能自动检测环境光以控制路灯的工作状态,最大 功率 点追踪(MPPT)保证最大 太阳能电池 板效率,恒电流控制LED,并带有蓄电池状态输出
[单片机]
采用<font color='red'>STM32</font> 单片机的太阳能LED街灯解决方案
stm32 pwm的原理及主要参数的意义
pwm的原理如图 ARR:最值,定时器最值 CCRx:PWM的比较值 CNT:为计数器值 原理就是,CCRx的值和CNT比较大小,通过判断结果来决定输出是高电平还是低电平。 将代码定位到TIM_OC_InitTypeDef类中,然后看注释 uint32_t Pulse; /*! Specifies the pulse value to be loaded into the Capture Compare Register. This parameter can be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF */
[单片机]
STM32开发笔记75: 使用STM32CubeMX点亮一个LED
单片机型号:STM32L053R8T6 今天调试在自己的程序框架下调试RTC始终不成功,只要初始化RTC就进入死机状态。现在重温一下STM32CubeMX的使用方法,看STM32CubeMX生成的程序是否有RTC初始化不成功的问题。本日志从工程的建立讲到点亮一个LED。 1、启动STM32CubeMX,我现在使用的版本是5.2.1。 2、File-New Project,选择相应的芯片类型。 3、双击相应的芯片类型后,进入配置界面。进行SYS配置,选中Debug Serial Wire,由于我习惯于使用FreeRTOS所以在我的项目中Timebase Source都选择定时器。 4、进行RCC设置。 5、
[单片机]
<font color='red'>STM32</font><font color='red'>开发</font>笔记75: 使用STM32CubeMX点亮一个LED
Keil开发STM32更换MCU造成的编译不通过的解决办法
1.更换MCU型号(在Keil从STM32F103ZET6换成STM32F107RCT6) 时出现的编译错误: 这个问题是因为对应处理器内部资源少于启动文件中提及的内部资源,启动文件中某一部分寄存器地址在STM32F107RCT6中没有,才会编译出错。 2.更换启动文件宏定义 由于STM32F103系列的不同型号MCU内部ROM和RAM不同,其地址区间也有些许差异所以需要选择与型号对应的启动文件,并配置对应的宏定义 故首先将startup中加入startup_stm32f10x_cl.s启动文件,然后在“C/C++”配置启动文件:把STM32F10X_HD换成STM32F10X_CL
[单片机]
上拉电阻与下拉电阻的定义及作用
什么是上拉电阻? 将一个不确定信号(高或低电平),通过一个电阻与电源VCC相连,固定在高电平; 什么是下拉电阻? 将一个不确定信号(高或低电平),通过一个电阻与地GND相连,固定在低电平。 图:左边的是上拉电阻示意图,右边的是下拉电阻示意图(无内容无关联) 上拉电阻与下拉电阻用在什么场合? 答:用在数字电路中,存在高低电平的场合。 上拉电阻与下拉电阻怎么接线? 答:上拉电阻:电阻一端接VCC,一端接逻辑电平接入引脚(如单片机引脚) 下拉电阻:电阻一端接GND,一端接逻辑电平接入引脚(如单片机引脚) 上拉电阻与下拉电阻的作用 1、提高输出引脚的驱动能力: 例如,当STM32的CPU引脚输出高电平,但由于后续电路的影响,输出的
[单片机]
上拉电阻与下拉电阻的定义及作用
STM32到CONST的全局变量
程序如下: const int globalConstDat = 12; int globalDat = 11; int main(void) { int localDat = 6; const int localConstDat = 7; USART_Configuration(); //ptint to PC from USART1 printf( &globalConstDat = 0x%p, &globalDat = 0x%prnrn , &globalConstDat, &globalDat); printf( &localDat = 0x%p, &localConstDat = 0x%prn , &localDat
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved