基于STM32单片机的机械手控制系统_第1页
基于STM32单片机的机械手控制系统_第2页
基于STM32单片机的机械手控制系统_第3页
基于STM32单片机的机械手控制系统_第4页
基于STM32单片机的机械手控制系统_第5页
已阅读5页,还剩51页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

基于STM32单片机的机械手控制系统

[4]。C语言也是有逐渐发展的过程,从最开始的B语言一直发展,在70年代由丹尼斯·里奇将B语言进化改为C语言。刚开始C语言运用于AT&T的多用户、UNIX相关操作系统,通过相应的演变过程,UNIX成为一个不需要汇编语言就可以独立运行的系统。随着发展直到80年代初期的时候对C语言进行相应的标准化,在单片机应用程序中逐渐的得到了普及与运用。C语言是编程语言的一种基础,在C语言上发展了很多面向对象化的语言,掌握C语言对于学习其它语言具有很多好处。单片机只能识别机器语言,只能识别二进制数据。采用C语言的编程非常快捷,是最接近人类语言的编程语言,大大的加快了开发的进度,开发完成之后只需要编译软件编译通过就可以生成单片机的执行文件,程序既可以正常的运行。编程软件具有很强大的功能,简洁整齐的编程界面让程序开发变得更加一目了然,当编写程序具有C语言的语法错误的时候,编译器可以报警错误之处,只有改正正确才可以继续编译程序,方便了开发人员对于错误的查找。针对不同硬件使用了两种编程软件,分别为KeiluVision4与天问Block编程软件。首先是建立一个新的工程文件。建立界面如下图的所示的4-1所示。图4-1工程建立图该软件有很多丰富的功能,可以实现程序错误检查、程序编译、文件转化、程序的错误查询等多种功能,让单片机编程变得更加智能简洁。程序编写界面如图所示。图4-2PWM舵机程序编写界面图4-3手柄遥控程序编写界面图4-4W25Q64存储器程序编写界面图4-5红外传感相关程序编写界面对于语音模块,这里使用了天问Block进行编程,该软件不仅可以字符编程,而且还可以图形编程,这样大大的降低了新手编程的难度。下图对语音模块的编程。图4-6语音模块程序编写界面图4-7蜂鸣器程序编写界面在每一次完成部分的程序编写之后都要运行编译下程序,看看程序是否可以顺利的编译通过,点击编译按钮如图中箭头所指。图4-8编译成功界面目标中的文件由LIB创建库文件,然后连接定位.ABS文件,最后转换为单片机可以运行的HEX文件,这个工程可以自动的完成链接功能,让程序开发更加的简单。程序下载界面如图中的4-9所示。图4-9程序下载界面语音模块使用天问Block编程完成后进行最后的编译下载,如下图所示。图4-10天问Block编译下载图4.2机械手控制系统软件设计框图主函数的执行从main开始进入执行,首先需要对传感器或者寄存器进行初始化完成,然后进入到主循环while(1)中执行循环程序。根据采集到的子程序汇总的数据进行逻辑功能输出的判断,同时显示相关的数据信息。当完成所有满足执行条件的子函数调用之后,程序继续从while(1)的开始处开始循环执行。本文基于STM32单片机机械手控制系统的软件设计流程图如图4-11所示。图4-11机械手设计流程图本文设计的手臂旨在实现从左/右、上/下、夹紧/松开物体的操作和控制。机械臂检测到工件从原点水平移动到平面A,然后到达了设定位置,接着机械手实现夹取物品的功能,过2秒时间机械手便可以上升,到达上设定位置,机械手向右进行移动,此时到达了平面B后进行下降的动作,到达低设定位置机械手开始松开,松开时间过2秒钟。松开后再上升左移返回到原点。这便是机械手的自动运行。4.3手动子程序设计本文设计机械手共有6个自由度,下面设计让机械手和它的手臂实现旋转、夹取、松开和移动的手动控制功能。第一部分是控制机械手臂。通过按“L”左方向键来控制底部的电机进行水平后退操作,让机械手臂以底部电机为中心进行逆时针旋转,而右键则可以控制机械手臂进行顺时针旋转。这样便可以让机械手臂实现以底部电机为圆心水平旋转功能,这也就是对机械手臂的第一个轴进行控制。通过按“L”上下方向键来控制第二个舵机进行前后的垂直操作,同样让机械手臂以第二个电机为中心进行前后的旋转,这样便可以实现机械手以第二个电机为中心的垂直旋转功能,同样这也是对机械手臂的第二个轴进行控制。接着,通过“R”上下方向键可以实现机械手臂第三轴的垂直控制,而左右方向键则可以实现对机械手臂第四轴的垂直控制功能。第二部分是控制机械手。通过“1”号按键来控制第五个电机来实现机械手的旋转功能,而“2”号按键来控制第六个电机来实现机械手的夹取,松开功能。另外START按键为待机激活,SELECT可以实现机械手的一键复位功能。MODE切换红绿灯模式,红灯模式下遥感无法使用,再按下MODE为正常情况下红绿灯并存模式,此时遥感可控制1-4轴电机。最后通过机械手与它的手臂来进行配合实现机械手的旋转、夹取、松开和移动的功能。手动流程如4-12,4-13所示。图4-12手动流程图图4-13手柄按键

第5章系统调试与测试5.1调试准备在硬件焊接完成之后需要对电路整体进行检查测试,当测试完成确认没有错误之后才会给电路通电,测试的一般步骤如下所示。(1)查看整体电路是否正常,接着查看硬件是否有明显损坏,按照实物实际的连接与原理图中的线路对应,检查器件的引脚周围与原理图上的是否一致。(2)检测实物整体焊接的情况,用万用表测量一下电路输入的阻抗,因为虚焊,漏焊会导致电路出现短路的问题。一旦电源出现了短路的问题,会导致电源的烧毁或者导致单片机系统中的器件烧毁。(3)检查实物元器件的安装情况,这里主要检查具有正负极的元器件,然后再次检查下元件的完整情况,缺少一部分元件会导致实物功能无法实现,严重情况下通电会出现因缺少元件而照成其它元件损毁的情况。(4)硬件电路的调试过程中,第一步需要确定测试点,找好点位进行测试记录。第二步是搭建工作台,选择适合的仪表实现测量,万用表是比较常见的仪器,可以实现测量与检查功能。第三步是确定调试的顺序,电子电路中的信号都是按照一个方向运行,从采集到处理到输出控制顺序依次去测试相关的电子电路。最后一个步骤是完成实物的整体硬件调试,完成程序的下载,观察电路的运行状态。系统调试之前需要对电路进行检测,根据电路原理图与实物进行对照。检查单片机的最小系统,确认引脚功能,按照各个模块的电路图与实际焊接的实物进行对照,检查是否存在导线虚焊或者链接错误的情况,确认无误之后进行短路测量,查看VCC与GND是否处于短路状态。测量各个模块部分的供电电压是否在正常的范围内,可以通过万用表实现电压数值的测量,也可以实现导通状态的测量。在完成硬件电路检测之后,可以进行程序的下载,将HEX单片机可执行文件下载到单片机中,确保程序的正确下载,然后进行通电观察是否正确,当数据或者状态正确时候可以进入最后的调试阶段,通过调试各个步骤检测是否完成系统的设计功能。5.2系统测试程序的编写时按照模块化的功能去实现,通过测试可以看到各个功能模块的工作状态,通过对各个模块的测试可以找出具体模块的错误或者不当之处。在测试时候已经保证了电路的原理是按照电路图的确定,只需要先找软件的问题,这样可以加快各个功能模块的测试与开发进度,将各个功能模块分别写入到单片机进行对应的测试,通过测试现象得出结论。单片机单独测试对于该实物是没有任何意义的,所以接下来的测试都需要配合其它为了实现功能的模块来一起测试,这样才能更好的检测实物功能是否存在问题。最先开始依旧是检测硬件的完整性,确保实现功能的元器件都已安装完毕,接着便可以对要实现的功能来一一测试。首先便是安装部分,共分为5步:(1)首先第一部分便是组装机械手上半部分,该部分需要4个舵机和机械抓以及支架材料组成,组装完毕在每个舵机接口处引出舵机延长线。这部分可实现机械手三到六轴控制。机械手上半部分图如图5-1。图5-1机械手上半部分图(2)其次第二部分就是安装机械手云台支架部分,该部分由2个舵机以及云台支架,大轴承等组成,这里第二部分主要实现机械手一轴与二轴的运动的控制。该部分如图5-2。图5-2机械手云台支架图(3)STM32单片机和存储器焊接在核心板中,核心板与控制板焊接在一起组成32控制板,再将手柄信号接收器安装至32控制板下方,红外感应装置固定至大底板中。图5-3手柄接收器图5-4红外感应模块图5-5焊接芯片图(4)将控制板安装至大底板上,舵机延长线按顺序插入32控制板,红外感应,语音模块,手柄接收器插入32控制板对应位置。图5-6接线入控制板图(5)将整体安装完毕,等待功能测试。图5-7安装完毕图接着便是对主要功能进行测试:(1)外接3A适配器来提供电源,测试红外感应是否能够运行。图5-8适配器图5-9红外感应到物品后的动作(2)测试语音模块。图5-10语音模块接收指令后动作(3)测试手动控制。图5-11手动控制机械手最后这里主要介绍系统的测试结果,从硬件开始进行测试,检查硬件电路的原理与实物是否是一致的,首先是对外部电源能否正常工作的测试,如图5-8,外接电源显示蓝灯亮起,证明在正常工作;接着是对红外感应的测试,物品进入红外感应范围后输出信号,机械手按设定好的程序进行运行,如图5-9,接着是对语音模块来进行测试,当喊出唤醒语音模块的关键词后,语音模块开始工作,接着说出设定好的语音指令关键词,语音模块发出信号,机械手完成了对应的动作,如图5-10,语音指令见附录。最后便是手动控制测试,通过SP2手柄与它的信号接收器来完成对机械手的动作控制,如图5-11。完成这些测试后,得出实物满足了设计需求的功能。

第6章总结与展望6.1总结本次设计的基于STM32单片机的机械手控制系统,首先从开始的资料收集开始做起,通过收集相关的内容资料作为参考,确定自己的任务功能之后开始设计整体思路与整体框架。然后进行整体的电路设计,完成整体的原理图。根据原理图实现实物设备的焊接,从而完成实物的整体制作,为下一步的程序调试做准备。在焊接硬件时候遇到了虚焊问题,通过万用表检查电路最后保证了硬件焊接的正确性。通过编写各个模块程序,然后下载到单片机中进行测试,保证每一个功能都可以正常的运行。最后整合成完整的程序,增加逻辑控制实现目标功能。在调试程序的时候遇到显示模块不显示,查找电路时候也没有发现电路焊接有问题,确定是程序的问题,查找显示相关的程序控制,最后发现是程序没有进行显示的初始化设置,修改程序之后问题得到了解决。本次设计在硬件设计与软件设计中都遇到了不同的问题,在细心查找下遇到的问题与困难都很好的解决了。本次完成了整体的目标功能,完成系统包括硬件、软件、整体测试的全部工作,完成了任务目标,实现了课题的需求效果。由于本次设计开发的系统时间有限,在设备进入实际应用中可能存在一些硬件的匹配或者程序的匹配问题,但是随着智能化与物联网话的逐渐发展与技术的更新,基于STM32单片机的机械手控制系统的应用会变得更加的广泛,在实际应用中也会越来越稳定可靠。6.2不足与展望本次设计的机械手系统,通过传感器与电机实现了目标的要求功能,但是在一些结构设计上还有很多的优化,比如机械臂的转动角度,后续如果可以对机械手进行完善,主要的地方还要有主要程序的优化,让机械手控制的更加丝滑,反应的时间更加的迅速,做到精准,在机械结构上进行升级,实现手的样式更加完善,实现类似仿真手的动作控制,同样在材料上也可以升级,让机械手保持更加耐用的同时,材料的价格也可以更加的实惠一些。这些都是日后可以更加精细的研究方向。

参考文献张仔龙,王利强.机械手发展现状与趋势[J].机械研究与应用,2022,35(06):219-225.DOI:10.16576/j.ISSN.1007-4414.2022.06.063.侯进旺.基于单片机的机械手控制系统设计[J].科技通报,2016,32(007):108-112.方龙,陈丹,肖献保.基于单片机的机械手臂控制系统设计[J].广西轻工业,2008,24(008):89-90.李岩,李雪斌,宋家兴.C语言的发展特点及其应用[J].艺术科技,2016,29(09):94.高红红,马保吉,杨恒,李志超.六自由度上料机械手控制系统的设计与测试[J].仪表技术与传感器,2022(01):57-61.王伟,彭细华,周来.一种多自由度教学搬运机械手的控制程序[J].电子技术,2020,49(08):34-35.何英杰,刘娟秀,梁飞.一种移动便捷式心电采集系统的设计[J].电脑知识与技术,2022,18(24):115-118.DOI:10.14004/ki.ckt.2022.1470.张勇.六自由度机械手参数化建模及运动仿真[J].机械管理开发,2023,38(04):4-6.DOI:10.16525/14-1134/th.2023.04.002.折小荣.基于单片机控制的管道施工机械手控制系统研究[J].数字技术与应用,2015,000(009):13.耶晓东.基于单片机的简易机械手的设计[J].微计算机信息,2009,25(014):230-231.沈孝芹,张蔚波,于复生,等.基于单片机控制的气动搬运机械手的研制[J].液压与气动,2008,000(008):14-15.李世强,王霞.工业机械手自动化控制系统设计[J].自动化技术与应用,2022,41(10):1-3+14.徐巍,朱怀志,钟宇超,余成成.基于NSGA-Ⅱ的热压系统上下料机械手结构优化设计[J].现代制造工程,2023(05):65-73.DOI:10.16731/ki.1671-3133.2023.05.010.贾继鹏,赵芳琴.工控技术在机械手控制系统中的应用与分析[J].设备管理与维修,2022,(18):106-107.王一帆,赵琛,袁梦扬,关光.六自由度机械手控制系统设计与仿真[J].数字技术与应用,2022,40(08):194-199.国内机械行业——机械手应用与技术发展概况(上)[J].科技简报,1975(07):12-15.吴云龙,程武山.基于STM32的语音识别机械手智能系统设计[J].单片机与嵌入式系统应用,2020,20(01):37-41.郭栋.基于八轴喷涂机械手臂示教运动控制研究[D].济南大学,2021.DOI:10.27166/ki.gsdcc.2021.000467.蔡展标,许生鸿.舵机机械手控制器设计[J].嘉应学院学报,2018,36(08):45-52.鲁力,杨红军,田龙阳,戢绍庭,陈家林.基于STM32控制的小型机械手的研究[J].武汉轻工大学学报,2022,41(04):59-63.Hernandez-BarrazaLuis,Kalil-KhanAhmed,YeowRayeChen-Hua.Abioinspiredmodularsoftroboticarm[J].EngineeringResearchExpress,2023,5(1).MondiniValeria,KoblerReinmarJosef,SburleaAndreeaIoana,Müller-PutzGernotR.Continuouslow-frequencyEEGdecodingofarmmovementforclosed-loop,naturalcontrolofaroboticarm.[J].Journalofneuralengineering,2020,17(4).AlirezaIzadbakhsh,PayamKheirkhahan.OntheVoltage-basedControlofRobotManipulatorsRevisited[J].InternationalJournalofControl,AutomationandSystems,2018,16(4).AnhTuanVo,ThanhNguyenTruong,HeeJunKang.AModifiedAdaptivePrescribedPerformanceControlMethodforMotionControlProblemsofRoboticManipulators[J].IJMERR,2022,11(12).GirenkoD.S.ZhidkovV.N,KimN.V.AccuracyofNeuralNetworkManipulatorControl[J].RussianEngineeringResearch,2022,42(9):202.

附录设计原理图1设计原理图2语音模块语音指令唤醒词:小星小星关键词:前夹取==$DGT:1-7,1!左夹取==$DGT:16-23,1!右夹取==$DGT:8-15,1!左转==#000P2300T1500!右转==#000P0700T1500!居中==#000P1500T1000!爪子张开==#005P1200T1000!爪子闭合==#005P1800T1000!弯曲=={#001P1500T1000!#002P1500T1000!#003P1500T1000!}直立=={#001P1800T1000!#002P2000T1000!#003P2000T1000!}机械手程序#include"z_rcc.h" //配置时钟文件#include"z_gpio.h" //配置IO口文件#include"z_global.h" //存放全局变量#include"z_delay.h" //存放延时函数#include"z_type.h" //存放类型定义#include"z_usart.h" //存放串口功能文件#include"z_timer.h" //存放定时器功能文件#include"z_ps2.h" //存放索尼手柄#include"z_w25q64.h" //存储芯片的操作#include"z_sensor.h" //传感器初始化#include"z_adc.h" //ADC初始化#include<stdio.h> //标准库文件#include<string.h> //标准库文件#include<math.h> //标准库文件#defineMODULE"Jibot1-32"/* 全局变量定义*/inti; //常用的一个临时变量intdo_start_index; //动作组执行起始序号intdo_times; //动作组执行执行次数intgroup_num_start; //动作组执行起始序号intgroup_num_end; //动作组执行终止序号intgroup_num_times; //动作组执行起始变量//u32dj_record_time=1000;//学习时间默认1000u8needSaveFlag=0; //偏差保存标志u32bias_systick_ms_bak=0;//偏差保存标志时间u32action_time=0;u8psx_buf[9]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};//存储手柄的数据 constchar*pre_cmd_set_red[PSX_BUTTON_NUM]={//红灯模式下按键的配置 "<PS2_RED01:#005P0600T2000!^#005PDST!>", //L2 "<PS2_RED02:#005P2400T2000!^#005PDST!>", //R2 "<PS2_RED03:#004P0600T2000!^#004PDST!>", //L1 "<PS2_RED04:#004P2400T2000!^#004PDST!>", //R1 "<PS2_RED05:#002P2400T2000!^#002PDST!>", //RU "<PS2_RED06:#003P2400T2000!^#003PDST!>", //RR "<PS2_RED07:#002P0600T2000!^#002PDST!>", //RD "<PS2_RED08:#003P0600T2000!^#003PDST!>", //RL "<PS2_RED09:$DJR!>", //SE "<PS2_RED10:>", //AL "<PS2_RED11:>", //AR "<PS2_RED12:$DJR!>", //ST "<PS2_RED13:#001P0600T2000!^#001PDST!>", //LU "<PS2_RED14:#000P0600T2000!^#000PDST!>", //LR "<PS2_RED15:#001P2400T2000!^#001PDST!>", //LD "<PS2_RED16:#000P2400T2000!^#000PDST!>", //LL };constchar*pre_cmd_set_grn[PSX_BUTTON_NUM]={//红绿灯模式下按键的配置 "<PS2_RED01:#005P0600T2000!^#005PDST!>", //L2 "<PS2_RED02:#005P2400T2000!^#005PDST!>", //R2 "<PS2_RED03:#004P0600T2000!^#004PDST!>", //L1 "<PS2_RED04:#004P2400T2000!^#004PDST!>", //R1 "<PS2_RED05:#002P2400T2000!^#002PDST!>", //RU "<PS2_RED06:#003P2400T2000!^#003PDST!>", //RR "<PS2_RED07:#002P0600T2000!^#002PDST!>", //RD "<PS2_RED08:#003P0600T2000!^#003PDST!>", //RL "<PS2_RED09:$DJR!>", //SE "<PS2_RED10:>", //AL "<PS2_RED11:>", //AR "<PS2_RED12:$DJR!>", //ST "<PS2_RED13:#001P0600T2000!^#001PDST!>", //LU "<PS2_RED14:#000P0600T2000!^#000PDST!>", //LR "<PS2_RED15:#001P2400T2000!^#001PDST!>", //LD "<PS2_RED16:#000P2400T2000!^#000PDST!>", //LL };/**程序从这里执行 *这个启动代码完成时钟配置使用外部晶振作为STM32的运行时钟并倍频到72M*/intmain(void){ setup_rcc(); //初始化时钟 setup_global(); //初始化全局变量 setup_gpio(); //初始化IO口 setup_nled(); //初始化工作指示灯 setup_beep(); //初始化定时器 setup_djio(); //初始化舵机IO口 setup_w25q64(); //初始化存储器W25Q64 setup_ps2(); //初始化PS2手柄 setup_uart1(); //初始化串口1用于下载动作组 setup_uart3(); //初始化串口3用于底板总线、lora setup_systick(); //初始化滴答时钟,1S增加一次millis()的值 setup_others(); //初始化其他 setup_dj_timer(); //初始化定时器2处理舵机PWM输出 setup_sensor(); //初始化传感器 setup_start(); //初始化启动信号 setup_interrupt();//初始化总中断 while(1){ loop_nled(); //循环执行工作指示灯,500ms跳动一次和声音公用一个IO口这里在声音功能启用的时候就关闭nled loop_uart(); //串口数据接收处理 loop_action(); //动作组批量执行 loop_ps2_data();//循环读取PS2手柄数据 loop_ps2_button();//处理手柄上的按钮 loop_ps2_car(); //处理电机摇杆控制 loop_monitor();//定时保存一些变量 }}///* 初始化函数实现*/voidsetup_rcc(void){//初始化时钟 tb_rcc_init(); //时钟初始化}voidsetup_global(void){//初始化全局变量 tb_global_init(); }voidsetup_gpio(void){//初始化IO口 tb_gpio_init(); }voidsetup_nled(void){//初始化工作指示灯 nled_init(); nled_off(); //工作指示灯关闭}voidsetup_beep(void){//初始化定时器蜂鸣器 beep_init(); beep_off(); //关闭蜂鸣器} voidsetup_djio(void){//初始化舵机IO口 dj_io_init(); } voidsetup_w25q64(void){//初始化存储器W25Q64 spiFlahsOn(1); w25x_init(); //动作组存储芯片初始化 w25x_read((u8*)(&eeprom_info),W25Q64_INFO_ADDR_SAVE_STR,sizeof(eeprom_info));//读取全局变量 if(eeprom_info.version!=VERSION){//判断版本是否是当前版本 eeprom_info.version=VERSION; //复制当前版本 eeprom_info.dj_record_num=0; //学习动作组变量赋值0 } if(eeprom_info.dj_bias_pwm[DJ_NUM]!=FLAG_VERIFY){ for(i=0;i<DJ_NUM;i++){ eeprom_info.dj_bias_pwm[i]=0; } eeprom_info.dj_bias_pwm[DJ_NUM]=FLAG_VERIFY; } for(i=0;i<DJ_NUM;i++){ duoji_doing[i].aim=1500+eeprom_info.dj_bias_pwm[i]; duoji_doing[i].cur=1500+eeprom_info.dj_bias_pwm[i]; duoji_doing[i].inc=0; } spiFlahsOn(0);} voidsetup_adc(void){//初始化ADC采集使用DMA初始化 ADC_init();}voidsetup_ps2(void){//初始化PS2手柄 PSX_init(); }voidsetup_dj_timer(void){//初始化定时器2处理舵机PWM输出 TIM2_Int_Init(20000,71); }voidsetup_uart1(void){//串口1初始化 tb_usart1_init(115200); //串口1打开 uart1_open(); //串口发送测试字符 uart1_send_str((u8*)"uart1checkok!");}//初始化串口2voidsetup_uart2(void){ //串口2初始化 tb_usart2_init(115200); //串口2打开 uart2_open(); //串口发送测试字符 uart2_send_str((u8*)"uart2checkok!");} //初始化串口3voidsetup_uart3(void){ //串口3初始化 tb_usart3_init(115200); //串口3打开 uart3_open(); //串口发送测试字符 uart3_send_str((u8*)"uart3checkok!"); //总线输出复位总线舵机串口3即为总线串口 zx_uart_send_str((u8*)"#255P1500T2000!");} //初始化滴答时钟,1S增加一次millis()的值voidsetup_systick(void){ //系统滴答时钟初始化 SysTick_Int_Init();} //初始化启动信号voidsetup_start(void){ //蜂鸣器LED名叫闪烁示意系统启动 beep_on();nled_on();tb_delay_ms(100);beep_off();nled_off();tb_delay_ms(100); beep_on();nled_on();tb_delay_ms(100);beep_off();nled_off();tb_delay_ms(100); beep_on();nled_on();tb_delay_ms(100);beep_off();nled_off();tb_delay_ms(100);} //初始化其他voidsetup_others(void){ //将偏差带入初始值 for(i=0;i<DJ_NUM;i++){ duoji_doing[i].aim=1500+eeprom_info.dj_bias_pwm[i]; duoji_doing[i].cur=duoji_doing[i].aim; duoji_doing[i].inc=0; } //执行预存命令{G0000#000P1500T1000!#000P1500T1000!} if(eeprom_info.pre_cmd[PRE_CMD_SIZE]==FLAG_VERIFY){ strcpy((char*)uart_receive_buf,(char*)eeprom_info.pre_cmd); if(eeprom_info.pre_cmd[0]=='$'){ parse_cmd(eeprom_info.pre_cmd); }else{ for(i=16;i<strlen((char*)uart_receive_buf);i+=15){ uart_receive_buf[i]='0'; uart_receive_buf[i+1]='0'; uart_receive_buf[i+2]='0'; uart_receive_buf[i+3]='0'; } parse_action(uart_receive_buf); } }}//初始化总中断voidsetup_interrupt(void){ //总中断打开 tb_interrupt_open();} /////* 主循环函数实现*///循环执行工作指示灯,500ms跳动一次voidloop_nled(void){ staticu32time_count=0; staticu8flag=0; if(millis()-time_count>1000){ time_count=millis(); if(flag){ nled_on(); }else{ nled_off(); } flag=~flag; }} //串口数据接收处理voidloop_uart(void){ if(uart1_get_ok){ if(uart1_mode==1){ //命令模式 parse_cmd(uart_receive_buf); }elseif(uart1_mode==2){ //单个舵机调试 parse_action(uart_receive_buf); }elseif(uart1_mode==3){ //多路舵机调试 parse_action(uart_receive_buf); }elseif(uart1_mode==4){ //存储模式 save_action(uart_receive_buf); } uart1_mode=0; uart1_get_ok=0; uart1_open(); } return;} //动作组批量执行voidloop_action(void){ staticlonglongsystick_ms_bak=0; //通过判断舵机是否全部执行完毕并且是执行动作组group_do_ok尚未结束的情况下进入处理 if(group_do_ok==0){ if(millis()-systick_ms_bak>action_time){ systick_ms_bak=millis(); if(group_num_times!=0&&do_times==0){//循环次数不等于0,执行次数现在为0,则执行完毕 group_do_ok=1; uart1_send_str((u8*)"@GroupDone!"); return;//返回跳出本函数 } //调用do_start_index个动作 do_group_once(do_start_index); if(group_num_start<group_num_end){// if(do_start_index==group_num_end){ do_start_index=group_num_start;//赋值起始动作序号到变量中,便于循环使用 if(group_num_times!=0){ do_times--; } return; } do_start_index++; }else{ if(do_start_index==group_num_end){ do_start_index=group_num_start; if(group_num_times!=0){ do_times--; } return; } do_start_index--; } } }else{action_time=10; }}//循环读取PS2手柄数据voidloop_ps2_data(void){ staticu32systick_ms_bak=0; //每20ms处理1次 if(millis()-systick_ms_bak<50){ return; } systick_ms_bak=millis(); //读写手柄数据 psx_write_read(psx_buf); #if0 //测试手柄数据,1为打开0为关闭 sprintf((char*)cmd_return,"0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x\r\n", (int)psx_buf[0],(int)psx_buf[1],(int)psx_buf[2],(int)psx_buf[3], (int)psx_buf[4],(int)psx_buf[5],(int)psx_buf[6],(int)psx_buf[7],(int)psx_buf[8]); uart1_send_str(cmd_return);#endif return;} //处理手柄上的按钮voidloop_ps2_button(void){ staticunsignedcharpsx_button_bak[2]={0}; //对比两次获取的按键值是否相同,相同就不处理,不相同则处理 if((psx_button_bak[0]==psx_buf[3]) &&(psx_button_bak[1]==psx_buf[4])){ }else{ //处理buf3和buf4两个字节,这两个字节存储这手柄16个按键的状态 parse_psx_buf(psx_buf+3,psx_buf[1]); psx_button_bak[0]=psx_buf[3]; psx_button_bak[1]=psx_buf[4]; } return;} ////软件复位函数,调用后单片机自动复位voidsoft_reset(void){ __set_FAULTMASK(1); NVIC_SystemReset();}//处理手柄按键字符,buf为字符数组,mode是指模式主要是红灯和绿灯模式voidparse_psx_buf(unsignedchar*buf,unsignedcharmode){ u8i,pos=0; staticu16bak=0xffff,temp,temp2; temp=(buf[0]<<8)+buf[1]; if(bak!=temp){ temp2=temp; temp&=bak; for(i=0;i<16;i++){//16个按键一次轮询 if((1<<i)&temp){ }else{ if((1<<i)&bak){ //press表示按键按下了 memset(uart_receive_buf,0,sizeof(uart_receive_buf)); if(mode==PS2_LED_RED){ memcpy((char*)uart_receive_buf,(char*)pre_cmd_set_red[i],strlen(pre_cmd_set_red[i])); }elseif(mode==PS2_LED_GRN){ memcpy((char*)uart_receive_buf,(char*)pre_cmd_set_grn[i],strlen(pre_cmd_set_grn[i])); }elsecontinue; //zx_uart_send_str(uart_receive_buf); pos=str_contain_str(uart_receive_buf,(u8*)"^"); if(pos)uart_receive_buf[pos-1]='\0'; if(str_contain_str(uart_receive_buf,(u8*)"$")){ uart1_close(); uart1_get_ok=0; strcpy((char*)cmd_return,(char*)uart_receive_buf+11); strcpy((char*)uart_receive_buf,(char*)cmd_return); uart1_get_ok=1; uart1_open(); uart1_mode=1; }elseif(str_contain_str(uart_receive_buf,(u8*)"#")){ uart1_close(); uart1_get_ok=0; strcpy((char*)cmd_return,(char*)uart_receive_buf+11); strcpy((char*)uart_receive_buf,(char*)cmd_return); uart1_get_ok=1; uart1_open(); uart1_mode=2; } bak=0xffff; }else{//release表示按键松开了 memset(uart_receive_buf,0,sizeof(uart_receive_buf)); if(mode==PS2_LED_RED){ memcpy((char*)uart_receive_buf,(char*)pre_cmd_set_red[i],strlen(pre_cmd_set_red[i])); }elseif(mode==PS2_LED_GRN){ memcpy((char*)uart_receive_buf,(char*)pre_cmd_set_grn[i],strlen(pre_cmd_set_grn[i])); }elsecontinue; pos=str_contain_str(uart_receive_buf,(u8*)"^"); if(pos){ if(str_contain_str(uart_receive_buf+pos,(u8*)"$")){ //uart1_close(); //uart1_get_ok=0; strcpy((char*)cmd_return,(char*)uart_receive_buf+pos); cmd_return[strlen((char*)cmd_return)-1]='\0'; strcpy((char*)uart_receive_buf,(char*)cmd_return); parse_cmd(uart_receive_buf); //uart1_get_ok=1; //uart1_mode=1; }elseif(str_contain_str(uart_receive_buf+pos,(u8*)"#")){ //uart1_close(); //uart1_get_ok=0; strcpy((char*)cmd_return,(char*)uart_receive_buf+pos); cmd_return[strlen((char*)cmd_return)-1]='\0'; strcpy((char*)uart_receive_buf,(char*)cmd_return); parse_action(uart_receive_buf); //uart1_get_ok=1; //uart1_mode=2; } //uart1_send_str(uart_receive_buf); } } } } bak=temp2; beep_on();mdelay(10);beep_off(); } return;}/*//动作组保存函数//只有用<>包含的字符串才能在此函数中进行解析voidsave_action(u8*str){ s32action_index=0; //预存命令处理 spiFlahsOn(1); if(str[1]=='$'&&str[2]=='!'){ eeprom_info.pre_cmd[PRE_CMD_SIZE]=0; rewrite_eeprom(); uart1_send_str((u8*)"@CLEARPRE_CMDOK!"); return; }elseif(str[1]=='$'){ if(sscanf((char*)str,"<$DGT:%d-%d,%d!>",&group_num_start,&group_num_end,&group_num_times)){ if(group_num_start==group_num_end){ w25x_read(eeprom_info.pre_cmd,group_num_start*ACTION_SIZE,ACTION_SIZE); }else{ memset(eeprom_info.pre_cmd,0,sizeof(eeprom_info.pre_cmd)); strcpy((char*)eeprom_info.pre_cmd,(char*)str+1); eeprom_info.pre_cmd[strlen((char*)str)-2]='\0'; } eeprom_info.pre_cmd[PRE_CMD_SIZE]=FLAG_VERIFY; rewrite_eeprom(); //uart1_send_str(eeprom_info.pre_cmd); uart1_send_str((u8*)"@SETPRE_CMDOK!"); } return; } //获取动作的组号如果不正确,或是第6个字符不是#则认为字符串错误 action_index=get_action_index(str); //<G0000#000P1500T1000!> if((action_index==-1)||str[6]!='#'){ uart1_send_str((u8*)"E"); return; } //把尖括号替换成大括号直接存储到存储芯片里面去,则在执行动作组的时候直接拿出来解析就可以了 replace_char(str,'<','{'); replace_char(str,'>','}'); if((action_index*ACTION_SIZE%4096)==0){w25x_erase_sector(action_index*ACTION_SIZE/4096);} w25x_write(str,action_index*ACTION_SIZE,strlen((char*)str)+1);// memset(str,0,sizeof((char*)str));// w25x_read(str,action_index*ACTION_SIZE,ACTION_SIZE);// uart1_send_str(str); //反馈一个A告诉上位机我已经接收到了 uart1_send_str((u8*)"A"); uart3_send_str((u8*)"A"); spiFlahsOn(0); return; }//获取动作组的组号,字符串中有组号返回组号,否则返回-1intget_action_index(u8*str){ u16index=0; //uart_send_str(str); while(*str){ if(*str=='G'){ str++; while((*str!='#')&&(*str!='$')){ index=index*10+*str-'0'; str++; } returnindex; }else{ str++; } } return-1;}//打印存储在芯片里的动作组,从串口1中发送出来$CGP:x-y!这个命令调用voidprint_group(intstart,intend){ spiFlahsOn(1); if(start>end){ int_exchange(&start,&end); } for(;start<=end;start++){ memset(uart_receive_buf,0,sizeof(uart_receive_buf)); w25x_read(uart_receive_buf,start*ACTION_SIZE,ACTION_SIZE); uart1_send_str(uart_receive_buf); uart1_send_str((u8*)"\r\n"); uart3_send_str(uart_receive_buf); uart3_send_str((u8*)"\r\n"); } spiFlahsOn(0);}//两个int变量交换voidint_exchange(int*int1,int*int2){ intint_temp; int_temp=*int1; *int1=*int2; *int2=int_temp;}//获取最大时间intgetMaxTime(u8*str){inti=0,max_time=0,tmp_time=0;while(str[i]){if(str[i]=='T'){tmp_time=(str[i+1]-'0')*1000+(str[i+2]-'0')*100+(str[i+3]-'0')*10+(str[i+4]-'0');if(tmp_time>max_time)max_time=tmp_time;i=i+4;continue;}i++;}returnmax_time;}//执行动作组1次//参数是动作组序号voiddo_group_once(intgroup_num){ spiFlahsOn(1); //将uart_receive_buf清零 memset(uart_receive_buf,0,sizeof(uart_receive_buf)); //从存储芯片中读取第group_num个动作组 w25x_read(uart_receive_buf,group_num*ACTION_SIZE,ACTION_SIZE-1); //获取最大的组时间 action_time=getMaxTime(uart_receive_buf); //把读取出来的动作组传递到parse_action执行 parse_action(uart_receive_buf); spiFlahsOn(0);}//处理#000P1500T1000!类似的字符串voidparse_action(u8*uart_receive_buf){ u16index,time,i=0; intbias; floatpwm; floataim_temp; zx_uart_send_str(uart_receive_buf); if(uart_receive_buf[0]=='#'&&uart_receive_buf[4]=='P'&&uart_receive_buf[5]=='S'&&uart_receive_buf[6]=='C'&&uart_receive_buf[7]=='K'&&uart_receive_buf[12]=='!'){ index=(uart_receive_buf[1]-'0')*100+(uart_receive_buf[2]-'0')*10+(uart_receive_buf[3]-'0'); bias=(uart_receive_buf[9]-'0')*100+(uart_receive_buf[10]-'0')*10+(uart_receive_buf[11]-'0'); if((bias>=-500)&&(bias<=500)&&(index<DJ_NUM)){ if(uart_receive_buf[8]=='+'){ }elseif(uart_receive_buf[8]=='-'){ bias=-bias; } aim_temp=duoji_doing[index].cur-eeprom_info.dj_bias_pwm[index]+bias; eeprom_info.dj_bias_pwm[index]=bi

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论