Initial commit

This commit is contained in:
Bogdan Kolbov 2019-07-29 08:17:46 +03:00
commit bbde15f9bf
108 changed files with 37036 additions and 0 deletions

283
.cproject Normal file
View File

@ -0,0 +1,283 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
<storageModule moduleId="org.eclipse.cdt.core.settings">
<cconfiguration id="ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.1605704765">
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.1605704765" moduleId="org.eclipse.cdt.core.settings" name="Debug">
<macros>
<stringMacro name="__CM4_REV" type="VALUE_TEXT" value="0"/>
</macros>
<externalSettings/>
<extensions>
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="${cross_rm} -rf" description="" errorParsers="org.eclipse.cdt.core.GASErrorParser;org.eclipse.cdt.core.GmakeErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.CWDLocator;org.eclipse.cdt.core.GCCErrorParser" id="ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.1605704765" name="Debug" parent="ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug" postannouncebuildStep="" postbuildStep="" preannouncebuildStep="" prebuildStep="">
<folderInfo id="ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.1605704765." name="/" resourcePath="">
<toolChain errorParsers="" id="ilg.gnuarmeclipse.managedbuild.cross.toolchain.elf.debug.1854751117" name="Cross ARM GCC" nonInternalBuilderId="ilg.gnuarmeclipse.managedbuild.cross.builder" superClass="ilg.gnuarmeclipse.managedbuild.cross.toolchain.elf.debug">
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.level.235990940" name="Optimization Level" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.level" useByScannerDiscovery="true" value="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.level.size" valueType="enumerated"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.messagelength.525011748" name="Message length (-fmessage-length=0)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.messagelength" useByScannerDiscovery="true" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.signedchar.652051416" name="'char' is signed (-fsigned-char)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.signedchar" useByScannerDiscovery="true" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.functionsections.2120457832" name="Function sections (-ffunction-sections)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.functionsections" useByScannerDiscovery="true" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.datasections.1183840552" name="Data sections (-fdata-sections)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.datasections" useByScannerDiscovery="true" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.debugging.level.299777029" name="Debug level" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.debugging.level" useByScannerDiscovery="true" value="ilg.gnuarmeclipse.managedbuild.cross.option.debugging.level.max" valueType="enumerated"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.debugging.format.657485291" name="Debug format" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.debugging.format" useByScannerDiscovery="true"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.toolchain.name.742151801" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.toolchain.name" useByScannerDiscovery="false" value="Sourcery CodeBench Lite for ARM EABI" valueType="string"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.architecture.134296343" name="Architecture" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.architecture" useByScannerDiscovery="false" value="ilg.gnuarmeclipse.managedbuild.cross.option.architecture.arm" valueType="enumerated"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.family.1304847864" name="ARM family" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.family" useByScannerDiscovery="false" value="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.mcpu.cortex-m4" valueType="enumerated"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.instructionset.18878311" name="Instruction set" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.instructionset" useByScannerDiscovery="false" value="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.instructionset.thumb" valueType="enumerated"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.prefix.528820877" name="Prefix" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.prefix" useByScannerDiscovery="false" value="arm-none-eabi-" valueType="string"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.c.1965477367" name="C compiler" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.c" useByScannerDiscovery="false" value="gcc" valueType="string"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.cpp.1689765874" name="C++ compiler" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.cpp" useByScannerDiscovery="false" value="g++" valueType="string"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.ar.1897114813" name="Archiver" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.ar" useByScannerDiscovery="false" value="ar" valueType="string"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.objcopy.1347693698" name="Hex/Bin converter" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.objcopy" useByScannerDiscovery="false" value="objcopy" valueType="string"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.objdump.119866392" name="Listing generator" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.objdump" useByScannerDiscovery="false" value="objdump" valueType="string"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.size.225381161" name="Size command" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.size" useByScannerDiscovery="false" value="size" valueType="string"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.make.129845409" name="Build command" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.make" useByScannerDiscovery="false" value="cs-make" valueType="string"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.rm.645767312" name="Remove command" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.rm" useByScannerDiscovery="false" value="cs-rm" valueType="string"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.addtools.createflash.46031997" name="Create flash image" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.addtools.createflash" useByScannerDiscovery="false" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.addtools.printsize.934798819" name="Print size" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.addtools.printsize" useByScannerDiscovery="false" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.fpu.unit.1709970612" name="FPU Type" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.fpu.unit" useByScannerDiscovery="true" value="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.fpu.unit.fpv4spd16" valueType="enumerated"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.fpu.abi.447103466" name="Float ABI" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.fpu.abi" useByScannerDiscovery="true" value="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.fpu.abi.hard" valueType="enumerated"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.target.other.441844501" name="Other target flags" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.target.other" useByScannerDiscovery="true" value="" valueType="string"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.toolchain.id.1159771958" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.toolchain.id" useByScannerDiscovery="false" value="730666677" valueType="string"/>
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="ilg.gnuarmeclipse.managedbuild.cross.targetPlatform.1111832768" isAbstract="false" osList="all" superClass="ilg.gnuarmeclipse.managedbuild.cross.targetPlatform"/>
<builder buildPath="${ProjName}/Debug" errorParsers="org.eclipse.cdt.core.GmakeErrorParser;org.eclipse.cdt.core.CWDLocator" id="ilg.gnuarmeclipse.managedbuild.cross.builder.1846842658" keepEnvironmentInBuildfile="false" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="ilg.gnuarmeclipse.managedbuild.cross.builder"/>
<tool command="${cross_prefix}${cross_c}${cross_suffix}" commandLinePattern="${COMMAND} ${cross_toolchain_flags} ${FLAGS} -c ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}" errorParsers="org.eclipse.cdt.core.GASErrorParser;org.eclipse.cdt.core.GCCErrorParser" id="ilg.gnuarmeclipse.managedbuild.cross.tool.assembler.1135800266" name="Cross ARM GNU Assembler" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.assembler">
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.assembler.usepreprocessor.401541642" name="Use preprocessor" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.assembler.usepreprocessor" useByScannerDiscovery="false" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.assembler.asmlisting.993021628" name="Generate assembler listing (-Wa,-adhlns=&quot;$@.lst&quot;)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.assembler.asmlisting" useByScannerDiscovery="false" value="true" valueType="boolean"/>
<inputType id="ilg.gnuarmeclipse.managedbuild.cross.tool.assembler.input.614857886" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.assembler.input"/>
</tool>
<tool command="${cross_prefix}${cross_c}${cross_suffix}" commandLinePattern="${COMMAND} ${cross_toolchain_flags} ${FLAGS} -c ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}" errorParsers="org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.GCCErrorParser" id="ilg.gnuarmeclipse.managedbuild.cross.tool.c.compiler.1173441847" name="Cross ARM C Compiler" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.c.compiler">
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.include.paths.862213974" name="Include paths (-I)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.include.paths" useByScannerDiscovery="false" valueType="includePath">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/Vinclude}&quot;"/>
</option>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.asmlisting.1665590179" name="Generate assembler listing (-Wa,-adhlns=&quot;$@.lst&quot;)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.asmlisting" useByScannerDiscovery="false" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.defs.1155328255" name="Defined symbols (-D)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.defs" useByScannerDiscovery="false"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.std.1685330845" name="Language standard" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.std" useByScannerDiscovery="true" value="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.std.gnu11" valueType="enumerated"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.savetemps.961642540" name="Save temporary files (--save-temps Use with caution!)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.savetemps" useByScannerDiscovery="false" value="false" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.include.files.582164422" name="Include files (-include)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.include.files" useByScannerDiscovery="false"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.other.1165832177" name="Other compiler flags" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.other" useByScannerDiscovery="true" value="-fsingle-precision-constant" valueType="string"/>
<inputType id="ilg.gnuarmeclipse.managedbuild.cross.tool.c.compiler.input.2065717434" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.c.compiler.input"/>
</tool>
<tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.cpp.compiler.1157053913" name="Cross ARM C++ Compiler" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.cpp.compiler"/>
<tool command="${cross_prefix}${cross_c}${cross_suffix}" commandLinePattern="${COMMAND} ${cross_toolchain_flags} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}" errorParsers="" id="ilg.gnuarmeclipse.managedbuild.cross.tool.c.linker.1599914735" name="Cross ARM C Linker" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.c.linker">
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.gcsections.1597911657" name="Remove unused sections (-Xlinker --gc-sections)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.gcsections" useByScannerDiscovery="false" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.scriptfile.2036328640" name="Script files (-T)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.scriptfile" useByScannerDiscovery="false" valueType="stringList">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/cmd/build.ld}&quot;"/>
</option>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.nodeflibs.1760740393" name="Do not use default libraries (-nodefaultlibs)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.nodeflibs" useByScannerDiscovery="false" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.nostdlibs.109724705" name="No startup or default libs (-nostdlib)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.nostdlibs" useByScannerDiscovery="false" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.flags.1121633783" name="Linker flags (-Xlinker [option])" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.flags" useByScannerDiscovery="false" valueType="stringList">
<listOptionValue builtIn="false" value="-L&quot;${workspace_loc:/${ProjName}/cmd/}&quot;"/>
</option>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.libs.1870399126" name="Libraries (-l)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.libs" useByScannerDiscovery="false"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.paths.2019339927" name="Library search path (-L)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.paths" useByScannerDiscovery="false" valueType="libPaths">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/lib}&quot;"/>
</option>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.otherobjs.1640812717" name="Other objects" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.otherobjs" useByScannerDiscovery="false" valueType="userObjs">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/lib/libc.a}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/lib/libgcc.a}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/lib/libm.a}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/lib/libCANOpen_drv.a}&quot;"/>
</option>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.other.1870052095" name="Other linker flags" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.other" useByScannerDiscovery="false" value="" valueType="string"/>
<inputType id="ilg.gnuarmeclipse.managedbuild.cross.tool.c.linker.input.661667903" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.c.linker.input">
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
</inputType>
</tool>
<tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.cpp.linker.675986085" name="Cross ARM C++ Linker" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.cpp.linker">
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.cpp.linker.gcsections.1571586785" name="Remove unused sections (-Xlinker --gc-sections)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.cpp.linker.gcsections" value="true" valueType="boolean"/>
</tool>
<tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.archiver.2093549256" name="Cross ARM GNU Archiver" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.archiver"/>
<tool command="${cross_prefix}${cross_objcopy}${cross_suffix}" commandLinePattern="${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT}" errorParsers="" id="ilg.gnuarmeclipse.managedbuild.cross.tool.createflash.1548863923" name="Cross ARM GNU Create Flash Image" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.createflash">
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.createflash.choice.1388885304" name="Output file format (-O)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.createflash.choice" useByScannerDiscovery="false" value="ilg.gnuarmeclipse.managedbuild.cross.option.createflash.choice.srec" valueType="enumerated"/>
</tool>
<tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.createlisting.757444280" name="Cross ARM GNU Create Listing" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.createlisting">
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.createlisting.source.1854964062" name="Display source (--source|-S)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.createlisting.source" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.createlisting.allheaders.1182181489" name="Display all headers (--all-headers|-x)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.createlisting.allheaders" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.createlisting.demangle.2011876984" name="Demangle names (--demangle|-C)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.createlisting.demangle" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.createlisting.linenumbers.1025685360" name="Display line numbers (--line-numbers|-l)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.createlisting.linenumbers" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.createlisting.wide.1836553439" name="Wide lines (--wide|-w)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.createlisting.wide" value="true" valueType="boolean"/>
</tool>
<tool command="${cross_prefix}${cross_size}${cross_suffix}" commandLinePattern="${COMMAND} ${FLAGS}" errorParsers="" id="ilg.gnuarmeclipse.managedbuild.cross.tool.printsize.2125940164" name="Cross ARM GNU Print Size" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.printsize">
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.printsize.format.1774335776" name="Size format" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.printsize.format" useByScannerDiscovery="false"/>
</tool>
</toolChain>
</folderInfo>
<fileInfo id="ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.1605704765.2018936083" name="V_PWM_Module.c" rcbsApplicability="disable" resourcePath="Vsrc/V_PWM_Module.c" toolsToInvoke="ilg.gnuarmeclipse.managedbuild.cross.tool.c.compiler.1173441847.1551872100">
<tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.c.compiler.1173441847.1551872100" name="Cross ARM C Compiler" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.c.compiler.1173441847">
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.other.627528704" name="Other compiler flags" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.other" useByScannerDiscovery="true" value="-fsingle-precision-constant" valueType="string"/>
<inputType id="ilg.gnuarmeclipse.managedbuild.cross.tool.c.compiler.input.881201789" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.c.compiler.input"/>
</tool>
</fileInfo>
<folderInfo id="ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.1605704765.1805741637" name="/" resourcePath="asm">
<toolChain id="ilg.gnuarmeclipse.managedbuild.cross.toolchain.elf.debug.2004030594" name="Cross ARM GCC" superClass="ilg.gnuarmeclipse.managedbuild.cross.toolchain.elf.debug" unusedChildren="">
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.level.235990940.1469338465" name="Optimization Level" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.level.235990940"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.messagelength.525011748.557746189" name="Message length (-fmessage-length=0)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.messagelength.525011748"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.signedchar.652051416.1829109825" name="'char' is signed (-fsigned-char)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.signedchar.652051416"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.functionsections.2120457832.965682008" name="Function sections (-ffunction-sections)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.functionsections.2120457832"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.datasections.1183840552.1069986439" name="Data sections (-fdata-sections)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.datasections.1183840552"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.debugging.level.299777029.174791892" name="Debug level" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.debugging.level.299777029"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.debugging.format.657485291.778908462" name="Debug format" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.debugging.format.657485291"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.toolchain.name.742151801.1539427334" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.toolchain.name.742151801"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.architecture.134296343.2019577032" name="Architecture" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.architecture.134296343"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.family.1304847864.1307159765" name="ARM family" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.family.1304847864"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.instructionset.18878311.1891767763" name="Instruction set" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.instructionset.18878311"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.prefix.528820877.77349213" name="Prefix" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.prefix.528820877"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.c.1965477367.952176845" name="C compiler" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.c.1965477367"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.cpp.1689765874.600565162" name="C++ compiler" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.cpp.1689765874"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.ar.1897114813.609252004" name="Archiver" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.ar.1897114813"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.objcopy.1347693698.1419574728" name="Hex/Bin converter" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.objcopy.1347693698"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.objdump.119866392.756056290" name="Listing generator" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.objdump.119866392"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.size.225381161.2122232321" name="Size command" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.size.225381161"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.make.129845409.1510147539" name="Build command" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.make.129845409"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.rm.645767312.2133610331" name="Remove command" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.rm.645767312"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.addtools.createflash.46031997.2062049049" name="Create flash image" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.addtools.createflash.46031997"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.addtools.printsize.934798819.306247066" name="Print size" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.addtools.printsize.934798819"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.fpu.unit.1709970612.1626686790" name="FPU Type" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.fpu.unit.1709970612"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.fpu.abi.447103466.1557166818" name="Float ABI" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.fpu.abi.447103466"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.target.other.441844501.261835020" name="Other target flags" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.target.other.441844501"/>
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="ilg.gnuarmeclipse.managedbuild.cross.targetPlatform" isAbstract="false" osList="all" superClass="ilg.gnuarmeclipse.managedbuild.cross.targetPlatform"/>
<tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.assembler.25739545" name="Cross ARM GNU Assembler" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.assembler.1135800266">
<inputType id="ilg.gnuarmeclipse.managedbuild.cross.tool.assembler.input.321302863" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.assembler.input"/>
</tool>
<tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.c.compiler.1763788421" name="Cross ARM C Compiler" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.c.compiler.1173441847">
<inputType id="ilg.gnuarmeclipse.managedbuild.cross.tool.c.compiler.input.196061140" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.c.compiler.input"/>
</tool>
<tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.cpp.compiler.1416432073" name="Cross ARM C++ Compiler" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.cpp.compiler.1157053913"/>
<tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.c.linker.211819828" name="Cross ARM C Linker" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.c.linker.1599914735"/>
<tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.cpp.linker.1653887405" name="Cross ARM C++ Linker" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.cpp.linker.675986085"/>
<tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.archiver.1102438131" name="Cross ARM GNU Archiver" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.archiver.2093549256"/>
<tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.createflash.1436636726" name="Cross ARM GNU Create Flash Image" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.createflash.1548863923"/>
<tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.createlisting.161810835" name="Cross ARM GNU Create Listing" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.createlisting.757444280"/>
<tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.printsize.1247230212" name="Cross ARM GNU Print Size" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.printsize.2125940164"/>
</toolChain>
</folderInfo>
<fileInfo id="ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.1605704765.395663209" name="DSP.h" rcbsApplicability="disable" resourcePath="Vinclude/DSP.h" toolsToInvoke=""/>
<sourceEntries>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="Vinclude"/>
<entry excluding="dummy_V_CANtoRS.c" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="Vsrc"/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="asm"/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="include"/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="src"/>
</sourceEntries>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
<storageModule moduleId="ilg.gnuarmeclipse.managedbuild.packs"/>
</cconfiguration>
<cconfiguration id="ilg.gnuarmeclipse.managedbuild.cross.config.elf.release.1990299353">
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="ilg.gnuarmeclipse.managedbuild.cross.config.elf.release.1990299353" moduleId="org.eclipse.cdt.core.settings" name="Release">
<macros>
<stringMacro name="__CM4_REV" type="VALUE_TEXT" value="0"/>
</macros>
<externalSettings/>
<extensions>
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="${cross_rm} -rf" description="" id="ilg.gnuarmeclipse.managedbuild.cross.config.elf.release.1990299353" name="Release" parent="ilg.gnuarmeclipse.managedbuild.cross.config.elf.release">
<folderInfo id="ilg.gnuarmeclipse.managedbuild.cross.config.elf.release.1990299353." name="/" resourcePath="">
<toolChain id="ilg.gnuarmeclipse.managedbuild.cross.toolchain.elf.release.1610871238" name="Cross ARM GCC" superClass="ilg.gnuarmeclipse.managedbuild.cross.toolchain.elf.release">
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.level.1079499004" name="Optimization Level" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.level" value="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.level.size" valueType="enumerated"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.messagelength.594182684" name="Message length (-fmessage-length=0)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.messagelength" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.signedchar.1552505082" name="'char' is signed (-fsigned-char)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.signedchar" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.functionsections.735855855" name="Function sections (-ffunction-sections)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.functionsections" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.datasections.86415979" name="Data sections (-fdata-sections)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.datasections" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.debugging.level.2021760111" name="Debug level" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.debugging.level"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.debugging.format.351498377" name="Debug format" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.debugging.format"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.toolchain.name.497684385" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.toolchain.name" value="Sourcery CodeBench Lite for ARM EABI" valueType="string"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.architecture.250366655" name="Architecture" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.architecture" value="ilg.gnuarmeclipse.managedbuild.cross.option.architecture.arm" valueType="enumerated"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.family.1173945392" name="ARM family" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.family" value="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.mcpu.cortex-m3" valueType="enumerated"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.instructionset.1147412555" name="Instruction set" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.instructionset" value="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.instructionset.thumb" valueType="enumerated"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.prefix.1570641349" name="Prefix" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.prefix" value="arm-none-eabi-" valueType="string"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.c.1307835816" name="C compiler" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.c" value="gcc" valueType="string"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.cpp.91224007" name="C++ compiler" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.cpp" value="g++" valueType="string"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.ar.1084724426" name="Archiver" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.ar" value="ar" valueType="string"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.objcopy.1409245586" name="Hex/Bin converter" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.objcopy" value="objcopy" valueType="string"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.objdump.2050016684" name="Listing generator" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.objdump" value="objdump" valueType="string"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.size.859835010" name="Size command" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.size" value="size" valueType="string"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.make.1197053146" name="Build command" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.make" value="cs-make" valueType="string"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.rm.979100724" name="Remove command" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.rm" value="cs-rm" valueType="string"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.addtools.createflash.272216713" name="Create flash image" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.addtools.createflash" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.addtools.printsize.142465801" name="Print size" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.addtools.printsize" value="true" valueType="boolean"/>
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="ilg.gnuarmeclipse.managedbuild.cross.targetPlatform.1268345674" isAbstract="false" osList="all" superClass="ilg.gnuarmeclipse.managedbuild.cross.targetPlatform"/>
<builder buildPath="${ProjName}/Release" id="ilg.gnuarmeclipse.managedbuild.cross.builder.1883166023" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" superClass="ilg.gnuarmeclipse.managedbuild.cross.builder"/>
<tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.assembler.840458930" name="Cross ARM GNU Assembler" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.assembler">
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.assembler.usepreprocessor.1428722614" name="Use preprocessor" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.assembler.usepreprocessor" value="true" valueType="boolean"/>
<inputType id="ilg.gnuarmeclipse.managedbuild.cross.tool.assembler.input.1235062357" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.assembler.input"/>
</tool>
<tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.c.compiler.1949731196" name="Cross ARM C Compiler" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.c.compiler">
<inputType id="ilg.gnuarmeclipse.managedbuild.cross.tool.c.compiler.input.376308926" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.c.compiler.input"/>
</tool>
<tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.cpp.compiler.734894093" name="Cross ARM C++ Compiler" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.cpp.compiler"/>
<tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.c.linker.1586695678" name="Cross ARM C Linker" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.c.linker">
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.gcsections.1559834360" name="Remove unused sections (-Xlinker --gc-sections)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.gcsections" value="true" valueType="boolean"/>
<inputType id="ilg.gnuarmeclipse.managedbuild.cross.tool.c.linker.input.1104494889" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.c.linker.input">
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
</inputType>
</tool>
<tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.cpp.linker.664076807" name="Cross ARM C++ Linker" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.cpp.linker">
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.cpp.linker.gcsections.1964261640" name="Remove unused sections (-Xlinker --gc-sections)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.cpp.linker.gcsections" value="true" valueType="boolean"/>
</tool>
<tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.archiver.719386581" name="Cross ARM GNU Archiver" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.archiver"/>
<tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.createflash.392351902" name="Cross ARM GNU Create Flash Image" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.createflash"/>
<tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.createlisting.1061078679" name="Cross ARM GNU Create Listing" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.createlisting">
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.createlisting.source.2019512155" name="Display source (--source|-S)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.createlisting.source" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.createlisting.allheaders.1555433963" name="Display all headers (--all-headers|-x)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.createlisting.allheaders" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.createlisting.demangle.1566356270" name="Demangle names (--demangle|-C)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.createlisting.demangle" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.createlisting.linenumbers.1535886807" name="Display line numbers (--line-numbers|-l)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.createlisting.linenumbers" value="true" valueType="boolean"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.createlisting.wide.744750058" name="Wide lines (--wide|-w)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.createlisting.wide" value="true" valueType="boolean"/>
</tool>
<tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.printsize.598242677" name="Cross ARM GNU Print Size" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.printsize">
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.printsize.format.1832178998" name="Size format" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.printsize.format"/>
</tool>
</toolChain>
</folderInfo>
<sourceEntries>
<entry excluding="Vinclude|include|src|Vsrc|include/Peripherals|asm/niiet.S|include/UART_API|include/Peripherals/UART_API/PrimeCell_gen_sw|include/Peripherals/eADC/stellaris (do not include)" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="Vinclude"/>
<entry excluding="dummy_V_CANtoRS.c" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="Vsrc"/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="include"/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="src"/>
</sourceEntries>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
</cconfiguration>
</storageModule>
<storageModule moduleId="scannerConfiguration">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
<scannerConfigBuildInfo instanceId="ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.1605704765;ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.1605704765.;ilg.gnuarmeclipse.managedbuild.cross.tool.c.compiler.1173441847;ilg.gnuarmeclipse.managedbuild.cross.tool.c.compiler.input.2065717434">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
<scannerConfigBuildInfo instanceId="ilg.gnuarmeclipse.managedbuild.cross.config.elf.release.1990299353;ilg.gnuarmeclipse.managedbuild.cross.config.elf.release.1990299353.;ilg.gnuarmeclipse.managedbuild.cross.tool.c.compiler.1949731196;ilg.gnuarmeclipse.managedbuild.cross.tool.c.compiler.input.376308926">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
<storageModule moduleId="refreshScope" versionNumber="2">
<configuration configurationName="Debug"/>
<configuration configurationName="Release"/>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<project id="Example_LED_blinking.null.308845348" name="Example_LED_blinking"/>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
</cproject>

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/Debug/

32
.project Normal file
View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>MCD_035</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
<triggers>clean,full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.cdt.core.cnature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
</natures>
<variableList>
<variable>
<name>copy_PARENT</name>
<value>$%7BPARENT-3-PROJECT_LOC%7D/ProjectsGit/motorcontroldemo</value>
</variable>
</variableList>
</projectDescription>

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project>
<configuration id="ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.1605704765" name="Debug">
<extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="520753781973748679" id="ilg.gnuarmeclipse.managedbuild.cross.GCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT ARM Cross GCC Built-in Compiler Settings " parameter="${COMMAND} ${FLAGS} ${cross_toolchain_flags} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
</extension>
</configuration>
<configuration id="ilg.gnuarmeclipse.managedbuild.cross.config.elf.release.1990299353" name="Release">
<extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="480357847621646132" id="ilg.gnuarmeclipse.managedbuild.cross.GCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT ARM Cross GCC Built-in Compiler Settings " parameter="${COMMAND} ${FLAGS} ${cross_toolchain_flags} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
</extension>
</configuration>
</project>

View File

@ -0,0 +1,67 @@
eclipse.preferences.version=1
org.eclipse.cdt.codan.checkers.errnoreturn=Warning
org.eclipse.cdt.codan.checkers.errnoreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},implicit\=>false}
org.eclipse.cdt.codan.checkers.errreturnvalue=Error
org.eclipse.cdt.codan.checkers.errreturnvalue.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
org.eclipse.cdt.codan.checkers.noreturn=Error
org.eclipse.cdt.codan.checkers.noreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},implicit\=>false}
org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation=Error
org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem=Error
org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem=Warning
org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem=Error
org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem=-Warning
org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},no_break_comment\=>"no break",last_case_param\=>false,empty_case_param\=>false}
org.eclipse.cdt.codan.internal.checkers.CatchByReference=Warning
org.eclipse.cdt.codan.internal.checkers.CatchByReference.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},unknown\=>false,exceptions\=>()}
org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem=Error
org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization=Warning
org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},skip\=>true}
org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem=Error
org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem=Error
org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
org.eclipse.cdt.codan.internal.checkers.InvalidArguments=Error
org.eclipse.cdt.codan.internal.checkers.InvalidArguments.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem=Error
org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem=Error
org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem=Error
org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem=Error
org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker=-Info
org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},pattern\=>"^[a-z]",macro\=>true,exceptions\=>()}
org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem=Warning
org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
org.eclipse.cdt.codan.internal.checkers.OverloadProblem=Error
org.eclipse.cdt.codan.internal.checkers.OverloadProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem=Error
org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem=Error
org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem=-Warning
org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem=-Warning
org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem=Warning
org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true,exceptions\=>()}
org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem=-Warning
org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},paramNot\=>false}
org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem=Warning
org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},else\=>false,afterelse\=>false}
org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem=Error
org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem=Warning
org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true}
org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem=Warning
org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true}
org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem=Warning
org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true,exceptions\=>("@(\#)","$Id")}
org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem=Error
org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}

View File

@ -0,0 +1,11 @@
eclipse.preferences.version=1
environment/buildEnvironmentInclude/ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.1605704765/CPATH/delimiter=;
environment/buildEnvironmentInclude/ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.1605704765/CPATH/operation=remove
environment/buildEnvironmentInclude/ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.1605704765/C_INCLUDE_PATH/delimiter=;
environment/buildEnvironmentInclude/ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.1605704765/C_INCLUDE_PATH/operation=remove
environment/buildEnvironmentInclude/ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.1605704765/append=true
environment/buildEnvironmentInclude/ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.1605704765/appendContributed=true
environment/buildEnvironmentLibrary/ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.1605704765/LIBRARY_PATH/delimiter=;
environment/buildEnvironmentLibrary/ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.1605704765/LIBRARY_PATH/operation=remove
environment/buildEnvironmentLibrary/ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.1605704765/append=true
environment/buildEnvironmentLibrary/ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.1605704765/appendContributed=true

203
LICENSE.txt Normal file
View File

@ -0,0 +1,203 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

18
README.md Normal file
View File

@ -0,0 +1,18 @@
Данный репозиторий включает в себя полноценный работоспособный проект для задач управления двигателем на базе микроконтроллеров серии 1921ВК035 фирмы АО «НИИЭТ». Помимо исходного кода проекта, репозиторий содержит специализированное программное обеспечение, позволяющее производить разработку, отладку и исследование систем управления через интерфейс CAN с протоколом верхнего уровня CANopen. Начинать знакомство с данным ПО следует с файла ```Описание структуры ПО MotorControlDemo.pdf```, находящегося в разделе [Downloads](https://bitbucket.org/niietcm4/motorcontroldemo/downloads/) репозитория [MotorControlDemo](https://bitbucket.org/niietcm4/motorcontroldemo/).
Состав репозитория:
- MotorControlDemo проект с исходными кодами - реализует различные структуры управления электродвигателями различных типов, в том числе с обратными связями по току, скорости, положению. ПО поддерживает обработку следующих датчиков положения/скорости ротора: датчики Холла, инкрементальный энкодер. Реализована коммуникация по интерфейсу CAN по протоколу верхнего уровня CANopen. ПО микроконтроллера разработано в
бесплатной среде разработки [VectorIDE (Eclipse+GCC+OpenOCD)](http://motorcontrol.ru/production/soft/vector-ide/).
- COODEdit4 NIIET edition - редактор словарей CANopen, далее COODEdit (CanOpen Object Dictionary Editor) программный продукт, позволяющий осуществлять редактирование словарей объектов для CANopen-совместимых устройств с драйвером данной реализации в графическом виде. Подробнее с возможностями программы можно ознакомиться в руководстве пользователя - см. файл ```COODEdit user manual.pdf``` в разделе [Downloads](https://bitbucket.org/niietcm4/motorcontroldemo/downloads/) репозитория [MotorControlDemo](https://bitbucket.org/niietcm4/motorcontroldemo/).
- UniCON - управляющий интерфейс пользователя, набор программных средств, позволяющих осуществлять мониторинг (в том числе снятие осциллограмм переходных процессов) и настройку CANopen-совместимых устройств посредством персонального компьютера. UniCON при помощи переходника CAN-USB или USB-UART конвертора взаимодействует через CANopen с ПО микроконтроллера и обеспечивает интерфейс пользователя.
Подробнее с возможностями программы можно ознакомиться в руководстве пользователя - см. файл ```UniCON руководство пользователя.pdf``` в разделе [Downloads](https://bitbucket.org/niietcm4/motorcontroldemo/downloads/) репозитория [MotorControlDemo](https://bitbucket.org/niietcm4/motorcontroldemo/).
С вопросами и предложениями можно обращаться:
- motorcontrol@niiet.ru
- [тема](http://forum.niiet.ru/viewtopic.php?f=37&t=536) на интернет-форуме АО «НИИЭТ»
- интернет-форум ООО «НПФ ВЕКТОР» http://motorcontrol.ru/forum/
*Если вы нашли ошибку в программном обеспечении или документации просьба по возможности оповестить об этом разработчиков любым удобным способом.*

View File

@ -0,0 +1,68 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file CANBlockTransferInterface.h
\brief Áëî÷íàÿ ïåðåäà÷à äàííûõ äëÿ CANopen
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 2.0 25/03/2016
\defgroup CANOpen_drv Äðàéâåð CANOpen
@{
*/
#ifndef CANBLOCKTRANS_INTERFACE_H
#define CANBLOCKTRANS_INTERFACE_H
#ifdef __cplusplus
extern "C"
{
#endif
#include "DSP.h"
#define CANBT_INTERFACE_FREE 0
#define CANBT_INTERFACE_BUSY 0x8000
#define CANBT_INTERFACE_FLASH_PROG 1
#define CANBT_INTERFACE_DATALOG1 2
#define CANBT_INTERFACE_DATALOG2 3 // èñïîëüçóåòñÿ äëÿ 32-áèòíîãî äàòàëîããåðà
struct SCanBTInterface{
Uint16 alreadyInit; //ïðèçíàê ïåðâîãî âûçîâà äèñêåòíîãî àâòîìàòà.
Uint16 state_shadow;//Òåíåâîå ñîñòîÿíèå.
Uint16 state_prev; //Ïðåäûäóùåå ñîñÿíèå (íà îäèí òàêò)
Uint16 E; //Ôëàã ïåðâîãî âõîæäåíèÿ.
Uint32 time_prev;
Uint64 state_time; //âðåìÿ íàõîæäåíèÿ â òåêóùåì ñîñòîÿíèè, â òèêàõ ïðîöà. Äëÿ 150Ìãö ìàêñèìàëüíîå âðåìÿ îêîëî 4òûñ. ëåò :)
Uint16 BlockTransferCommand;
void (*ms_calc)(volatile struct SCanBTInterface* p, Uint32 time, TCo_OdVars* co_ptr);
void (*slow_calc)(volatile struct SCanBTInterface* p);
};
typedef volatile struct SCanBTInterface TCanBTInterface;
#define T_CANBT_INTERFACE_DEFAULTS {0,CANBT_INTERFACE_FREE,0xFF,1,\
0,0,0,\
SMCanBTInterface_ms,\
SMCanBTInterface_slow}
void SMCanBTInterface_ms(volatile struct SCanBTInterface* p, Uint32 time, TCo_OdVars* co_ptr);
void SMCanBTInterface_slow(volatile struct SCanBTInterface* p);
//êîëáýêè äëß 2700.00
void callback_BTcmd(Uint16 par, Uint16 tag_CANnum);
#ifdef __cplusplus
}
#endif
#endif

170
Vinclude/CANOpen_drv.h Normal file
View File

@ -0,0 +1,170 @@
/*!
Copyright 2017 АО "НИИЭТ" и ООО "НПФ ВЕКТОР"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file CANOpen_drv.h
\brief Драйвер CANOpen
\author ООО "НПФ Вектор". http://motorcontrol.ru
\version v 3.19 2019_03_06
\defgroup CANOpen_drv Драйвер CANOpen
@{
*/
#ifndef CAN_OPEN_DRV_H
#define CAN_OPEN_DRV_H
#ifdef __cplusplus
extern "C" {
#endif
//********************************************************************************************
//
//!Включатель CAN 1
#define CAN_1_ENABLE
//********************************************************************************************
//!Включатель CAN 2
//#define CAN_2_ENABLE
//********************************************************************************************
/*
* Функции инициализации драйвера для CAN1 и CAN2
* Драйвер использует работу с пользовательской памятью (интерфейс с которой определяется функциями co_UserMemoryRead и co_UserMemoryWrite -
* см. файл CANOpenUDfuncs.c), поэтому к моменту начала работы с драйвером пользователь должен ГАРАНТИРОВАТЬ,
* что драйвер пользовательской памяти проинициализирован.
*/
extern Uint16 co1_Init(TCo_OdVars* ppc);//В случае если инициализациЯ не удалась функциЯ возвращает 0, иначе 1.
extern Uint16 co2_Init(TCo_OdVars* ppc);//В случае если инициализациЯ не удалась функциЯ возвращают 0, иначе 1.
//ФункциЯ переинициализации CAN без восстановлениЯ параметров из пользовательской памяти (может быть использована лишь длЯ ПОВТОРНОЙ инициализации)
extern Uint16 co_ReInit(TCo_OdVars* ppc);//В случае если инициализациЯ не удалась функциЯ возвращают 0, иначе 1.
extern void propReset (void);
//Прототипы функций
extern void co_UserMemoryRead (const T_UserMemoryContext *p);
extern void co_UserMemoryWrite (const T_UserMemoryContext *p);
#ifdef CAN_1_ENABLE
extern void co_CAN1GpioInit();
extern void co_CAN1INTEnable();
extern void co_CAN1INTDisable();
#endif
#ifdef CAN_2_ENABLE
extern void co_CAN2GpioInit();
extern void co_CAN2INTDisable();
extern void co_CAN2INTEnable();
#endif
//!функция драйвера CANOpen вызываемая в прерывании 1 мс таймера, тактирующего работу драйвера
extern void co_1ms_calc(TCo_OdVars*);
//!функция обработчика драйвера CANOpen в фоновой программе
extern void co_background_calc(TCo_OdVars*);
//!Функция восстановления значений параметров словаря объектов по умолчанию
/*!
Результатом работы функции является восстановление параметров указанного
типа и диапазона
type - 1 rw-параметры
2 rwp-параметры
3 rwps-параметры
range - 1 восстановление индексов 1000h-1FFFh
2,3,4,5
Функция по времени выполнения относится к длиным (вызывать следует в фоне) */
extern void co_ODexpositor_instaurationDefault(TCo_OdVars* ppc, Uint16 type, Uint16 range);
//!Функция сохранения значений параметров словаря объектов в ЭнОЗУ
/*!Результатом работы функции является сохранение параметров указанного
типа и диапазона
type - 1 rw-параметры
2 rwp-параметры
3 rwps-параметры
range - 1 восстановление индексов 1000h-1FFFh
2,3,4,5
Функция по времени выполнения относится к длиным (вызывать следует в фоне).*/
extern void co_ODexpositor_paramConservation(TCo_OdVars* ppc, Uint16 type, Uint16 range);
//!Функция восстановления значений параметров словаря объектов из ЭнОЗУ
/*! Результатом работы функции является восстановление параметров указанного
типа и диапазона
type - 1 rw-параметры
2 rwp-параметры
3 rwps-параметры
range - 1 восстановление индексов 1000h-1FFFh
2,3,4,5
Внимание!!!Восстановление параметров 2-го и 3-го типов возможно если
переменная co_protectBit = 0. Если co_protectBit = 1 , то функция ничего
не "делает".
Если восстановление параметров заданного типа и диапазона произошло
неудачно(контрольная сумма не сошлась), то восстановление заданного
типа и диапазона повторяется.Если после трех попыток восстановление
не завершилось успехом, то выполняется восстановление параметров заданного
типа и диапазона по умолчанию.
Функция по времени выполнения относится к длиным (вызывать следует в фоне).*/
extern void co_ODexpositor_paramInstauration(TCo_OdVars* ppc, Uint16 type, Uint16 range);
// функции сервиса NMT
// драйвер может выступать NMT мастером, либо быть NMT слэйвом
//! функция для отправки NMT (нужна только для NMT мастера)
void co_sendNMT(TCo_OdVars* ppc, Uint16 nmtCommand, Uint16 nmtNODE_ID);
//!функция ПОЛЬЗОВАТЕЛя для отправки SDO запросов на чтение параметров сервера
extern void co_SDOrequestRead(TCo_OdVars*);
//!функция ПОЛЬЗОВАТЕЛя для отправки SDO запросов на запись параметров сервера
extern void co_SDOrequestWrite(TCo_OdVars*);
extern void Z_co_receiveSDOrequest(TCo_OdVars*, TZCanMsg*);
extern void co_CANToExtInterface_Send(TZCanMsg* MSG, Uint16 tag_CANnum);
/*!ФункциЯ возвращает адрес переменной по переданным индексу
и подындексу. Если "свЯзаннаЯ" переменнаЯ 32-х разрЯднаЯ, то
возвращаетсЯ указатель на старшую часть.
ВНИМАНИЕ!!!Если запрошенного индекса и подиндекса не существует, то
функциЯ возвращает 0 (это нужно обЯзательно отслеживать). */
extern Uint16 * co_getAddr(TCo_OdVars* ppc, Uint32 ind_subind);
// Функция получения информации об объекте с заданным адресом.
// Возвращает 0, если объект не найден.
extern Uint16 co_getObjectInfo(
TCo_OdVars* ppc, // указатель на структуру используемого модуля CANopen
Uint32 ind_subind, // биты 16-31 - индекс, биты 0-7 - подындекс объекта
TObjectInfo* pObjectInfo // указатель на структуру, куда будет помещена информация об объекте
);
extern void co_RPDO1_Callback(Uint16 nodeID, Uint16 tag_CANnum);
extern void co_RPDO2_Callback(Uint16 nodeID, Uint16 tag_CANnum);
extern void co_RPDO3_Callback(Uint16 nodeID, Uint16 tag_CANnum);
extern void co_RPDO4_Callback(Uint16 nodeID, Uint16 tag_CANnum);
extern void co_RPDO5_Callback(Uint16 nodeID, Uint16 tag_CANnum);
extern void co_RPDO6_Callback(Uint16 nodeID, Uint16 tag_CANnum);
extern void co_RPDO7_Callback(Uint16 nodeID, Uint16 tag_CANnum);
extern void co_RPDO8_Callback(Uint16 nodeID, Uint16 tag_CANnum);
//функции ПОЛЬЗОВАТЕЛя, инициирующие передачу, или прием блока данных посредством
//сервиса блочной передачи
extern void CANBlockTransferInitTX(TCo_OdVars* ppc, Uint16 size, Uint16* source_ptr);
extern void CANBlockTransferInitRX(TCo_OdVars* ppc, Uint16 size, Uint16* dest_ptr);
#ifdef __cplusplus
}
#endif
#endif
/*@}*/

83
Vinclude/DRV_INTERFACE.h Normal file
View File

@ -0,0 +1,83 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file DRV_INTERFACE.h
\brief ×åðåç äàííûå ìîäóëü îáåñïå÷èâàåòñß ðàáîòà ñ áàíêîì àâàðèé (÷òåíèå, î÷èñòêà).
//Ïðåäïîëàãàåòñß, ÷òî ìîäóëü ìîæåò ðàñøèðßòü ôóíêöèîíàëüíîñòü (ñêà÷èâàòü êàèå-òî äðóãèå äàííûå)...
//ÏÐÈÌÅ×ÀÍÈÅ äëÿ ïðîãðàììèñòà:
1.äëÿ êîìàíä ðàáîòàþùèõ ïî ñåòè ñ àâòîìàòèçèðîâàííûìè ñèñòåìàìè (Þíèêîí,, ïóëüòû è ò.ä.) ïîñëå âûïîëíåíèÿ êîìàíäû ïîëå ans_data äîëæíî áûòü óñòàíîâëåíî çíà÷åíèåì çàïðîñà:
p->ans_data = temp;
÷òî ñîîáùèò âíåøíåé ñèñòåìå, ÷òî çàïðîñ îáðàáîòàí.  ýòîì ñëó÷àå ïîëå p->ans_data îáíóëÿåòñÿ âíåøíåé àâòîìàòèçèðîâàííîé ñèñòåìîé ïîñëå ñáîðà èíôîðìàöèè ñ ïîëåé
p->data_Low
p->data_High
2.äëÿ âíóòðåííèõ âûçîâîâ ïîëå p->ans_data òðîãàòü íå íóæíî
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 2.1 2017_07_24
*/
// ïðèìåð èñïîëüçîâàíèß â ìîäóëå main
#ifndef DRV_INTERFACE_H
#define DRV_INTERFACE_H
#ifdef __cplusplus
extern "C"
{
#endif
#define DRV_INTERFACE_RESET_TIME 10 //âûäåðæêà â ñåê ïåðåä îáíóëåíèåì ïàðàìåòðà Ans_Data
//!çàïðîñ íà ÷òåíèå àâàðèè
#define DATA_REQUEST_READ_FAULT 1
//!çàïðîñ íà çàïèñü àâàðèè
#define DATA_REQUEST_WRITE_FAULT 2
//!çàïðîñ íà çàïèñü ðàáî÷åãî âðåìåíè
#define DATA_REQUEST_WRITE_WORK_TIME 3
//!çàïðîñ íà ÷òåíèå ðàáî÷åãî âðåìåíè
#define DATA_REQUEST_READ_WORK_TIME 4
#define DATA_REQUEST_WRITE_OPER_TIME 5
//!çàïðîñ íà ÷òåíèå âðåìåíè âî âêëþ÷åííîì ñîñòîßíèè
#define DATA_REQUEST_READ_OPER_TIME 6
//!î÷èñòêà âñåãî
#define DATA_REQUEST_CLEAR_ALL 10
struct SDrvInterface
{
long req_data;
long ans_data;
long data_High;
long data_Low;
long INTERFACE_time_sec;//!<
long INTERFACE_delta_time_sec;//!<
void (*calc)(struct SDrvInterface*);
};
typedef struct SDrvInterface TDrvInterface;
#define DRV_INTERFACE_DEFAULTS {0,0,0,0,\
0,0,\
DRV_INTERFACE_Calc,\
}
void DRV_INTERFACE_Calc(TDrvInterface*);
#ifdef __cplusplus
}
#endif
#endif

68
Vinclude/DSP.h Normal file
View File

@ -0,0 +1,68 @@
/******************************************************************************
* @file DSP.h
* @brief Файл подключения заголовочных файлов периферии и объявления системных констант
* @version v1.0
* @date 11 декабря 2015
*
* @note
* ООО "НПФ Вектор", все права защищены. Наш сайт: http://motorcontrol.ru
*
* @par
* ООО "НПФ Вектор" распространяет это программное обеспечение в демонстрационных
* целях, и оно может распространяться свободно.
*
* @par
* Данное программное обеспечение распространяется "как есть", и Вы,
* его пользователь, принимаете на себя все риски, связанные с его использованием.
* ООО "НПФ Вектор" не несет никакой ответственности за возможные убытки,
* связанные с его использованием.
*
******************************************************************************/
#ifndef VINCLUDE_DSP_H_
#define VINCLUDE_DSP_H_
#define __CM4_REV 0x0001 //в K1921VK01T.h есть объявление __CM4F_REV, но в core_cm4.h проверяется именно __CM4_REV. Если не объявлено там объявляется нулем и больше нигде, вроде, не используется эта константа
#define __CHECK_DEVICE_DEFINES
#include <stdint.h>
#include "K1921VK035.h"
#include "core_cm4.h" /* Cortex-M4 processor and core peripherals */
#include <string.h> //для memcpy
#include "EPwm_defines.h"
typedef char int8;
typedef unsigned char Uint8;
typedef unsigned short int Uint16;
typedef unsigned int Uint32;
typedef short int int16;
typedef int int32;
typedef unsigned long long Uint64;
typedef long long int64;
//Указатели на секцию памяти fastcode, где лежат функции для копирования из флеша в оперативку.
//Определены в файле компоновки памяти.
extern int __fastcode_ram_start;
extern int __fastcode_ram_end;
extern int __fastcode_flash_start;
extern int __isr_vector_flash_start;
extern int __isr_vector_ram_start;
extern int __isr_vector_ram_end;
//! Запрет прерываний
#define DINT __disable_irq()
//! Разрешение прерываний
#define EINT __enable_irq()
#define IRQ_PRIORITY_TZ 1
#define IRQ_PRIORITY_ADC 2
#define IRQ_PRIORITY_10K 3
#define IRQ_PRIORITY_CAP 4
#define IRQ_PRIORITY_CAN 5
#define IRQ_PRIORITY_1K 6
#define IRQ_PRIORITY_EQEP 6
#endif /* VINCLUDE_DSP_H_ */

183
Vinclude/EPwm_defines.h Normal file
View File

@ -0,0 +1,183 @@
/******************************************************************************
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
* @file EPwm_defines.h
* @brief Ôàéë îáúÿâëåíèÿ ñèñòåìíûõ êîíñòàíò äëÿ ðàáîòû ñ ØÈÌ ìîäóëÿìè
* @author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
* @version v1.0
* @date 11 äåêàáðÿ 2015
******************************************************************************/
#ifndef EPWM_DEFINES_H
#define EPWM_DEFINES_H
#ifdef __cplusplus
extern "C" {
#endif
// TBCTL (Time-Base Control)
// CTRMODE bits
#define TB_COUNT_UP 0x0
#define TB_COUNT_DOWN 0x1
#define TB_COUNT_UPDOWN 0x2
#define TB_FREEZE 0x3
// PHSEN bit
#define TB_DISABLE 0x0
#define TB_ENABLE 0x1
// PRDLD bit
#define TB_SHADOW 0x0
#define TB_IMMEDIATE 0x1
// SYNCOSEL bits
#define TB_SYNC_IN 0x0
#define TB_CTR_ZERO 0x1
#define TB_CTR_CMPB 0x2
#define TB_SYNC_DISABLE 0x3
// HSPCLKDIV and CLKDIV bits
#define TB_DIV1 0x0
#define TB_DIV2 0x1
#define TB_DIV4 0x2
// PHSDIR bit
#define TB_DOWN 0x0
#define TB_UP 0x1
// CMPCTL (Compare Control)
// LOADAMODE and LOADBMODE bits
#define CC_CTR_ZERO 0x0
#define CC_CTR_PRD 0x1
#define CC_CTR_ZERO_PRD 0x2
#define CC_LD_DISABLE 0x3
// SHDWAMODE and SHDWBMODE bits
#define CC_SHADOW 0x0
#define CC_IMMEDIATE 0x1
// AQCTLA and AQCTLB (Action Qualifier Control)
// ZRO, PRD, CAU, CAD, CBU, CBD bits
#define AQ_NO_ACTION 0x0
#define AQ_CLEAR 0x1
#define AQ_SET 0x2
#define AQ_TOGGLE 0x3
// DBCTL (Dead-Band Control)
// OUT MODE bits
#define DB_DISABLE 0x0
#define DBA_ENABLE 0x1
#define DBB_ENABLE 0x2
#define DB_FULL_ENABLE 0x3
// POLSEL bits
#define DB_ACTV_HI 0x0
#define DB_ACTV_LOC 0x1
#define DB_ACTV_HIC 0x2
#define DB_ACTV_LO 0x3
// IN MODE
#define DBA_ALL 0x0
#define DBB_RED_DBA_FED 0x1
#define DBA_RED_DBB_FED 0x2
#define DBB_ALL 0x3
// CHPCTL (chopper control)
// CHPEN bit
#define CHP_DISABLE 0x0
#define CHP_ENABLE 0x1
// CHPFREQ bits
#define CHP_DIV1 0x0
#define CHP_DIV2 0x1
#define CHP_DIV3 0x2
#define CHP_DIV4 0x3
#define CHP_DIV5 0x4
#define CHP_DIV6 0x5
#define CHP_DIV7 0x6
#define CHP_DIV8 0x7
// CHPDUTY bits
#define CHP1_8TH 0x0
#define CHP2_8TH 0x1
#define CHP3_8TH 0x2
#define CHP4_8TH 0x3
#define CHP5_8TH 0x4
#define CHP6_8TH 0x5
#define CHP7_8TH 0x6
// TZSEL (Trip Zone Select)
//==========================
// CBCn and OSHTn bits
#define TZ_DISABLE 0x0
#define TZ_ENABLE 0x1
// TZCTL (Trip Zone Control)
//==========================
// TZA and TZB bits
#define TZ_HIZ 0x0
#define TZ_FORCE_HI 0x1
#define TZ_FORCE_LO 0x2
#define TZ_NO_CHANGE 0x3
// ETSEL (Event Trigger Select)
//=============================
#define ET_CTR_ZERO 0x1
#define ET_CTR_PRD 0x2
#define ET_CTRU_CMPA 0x4
#define ET_CTRD_CMPA 0x5
#define ET_CTRU_CMPB 0x6
#define ET_CTRD_CMPB 0x7
// ETPS (Event Trigger Pre-scale)
//===============================
// INTPRD, SOCAPRD, SOCBPRD bits
#define ET_DISABLE 0x0
#define ET_1ST 0x1
#define ET_2ND 0x2
#define ET_3RD 0x3
//--------------------------------
// HRPWM (High Resolution PWM)
//================================
// HRCNFG
#define HR_Disable 0x0
#define HR_REP 0x1
#define HR_FEP 0x2
#define HR_BEP 0x3
#define HR_CMP 0x0
#define HR_PHS 0x1
#define HR_CTR_ZERO 0x0
#define HR_CTR_PRD 0x1
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif

196
Vinclude/Global_time.h Normal file
View File

@ -0,0 +1,196 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file Global_time.h
\brief Ìîäóëü ðàáîòû ñî âðåìåíåì
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 1.1 2010_02_24
*/
#ifndef GLOBAL_TIME_H
#define GLOBAL_TIME_H
#ifdef __cplusplus
extern "C"
{
#endif
#include "DSP.h"
#define GLOBAL_TIME_CALC_FREQ 10 //!<êÃö ÷àñòîòà âûçîâà ôóíêöèè calc
//#define USE_ABSOLUTE_TIME_CLOCK //ðàñêîìåíòèðîâàòü åñëè èñïîëüçóþòñß ÷àñû ðåàëüíîãî âðåìåíè
#define GLOBAL_TIME_SPI_START_ADDR 6500 //!<íà÷àëüíûé àäðåñ â SPI
#define GLOBAL_TIME_POWER_ON_TIME_ADDR GLOBAL_TIME_SPI_START_ADDR
#define GLOBAL_TIME_OPERATIONAL_TIME_ADDR GLOBAL_TIME_SPI_START_ADDR + 4
//!Àáñîëþòíîå âðåìß
struct SABSOLUTE_TIME
{
int16 second;
int16 minute;
int16 hour;
int16 day;
int16 year;
};
typedef volatile struct SABSOLUTE_TIME ABSOLUTE_TIME;
//!Îòíîñèòåëüíàß äàòà
typedef struct
{
int16 millisecond;
int16 second;
int16 minute;
int32 hour;
}RELATIVE_DATE;
//!Îòíîñèòåëüíîå âðåìß
struct SRELATIVE_TIME
{
int ON;
Uint32 tic_isr;
Uint32 millisecond_counter;
Uint32 second_counter;
int16 delta_millisecond;
int16 delta_second;
RELATIVE_DATE relative_date;
};
typedef volatile struct SRELATIVE_TIME RELATIVE_TIME;
/*! \class TGlobalTime
\brief Ìîäóëü ðàáîòû ñî âðåìåíåì.
Êëàññ \a TGlobalTime, îñíîâàííûé íà ñòðóêòóðå SGlobalTime, ñîäåðæèò ìåòîäû
äëß ðàáîòû ñî âðåìåíåì.Îòñ÷èòûâàåò âðåìß â:\n
äëß îòñ÷åòà âðåìåíè ðàáîòû è ò.ä.:\n
ìèëèñåêóíäû: 0-999\n
ñåêóíäû: 0-59\n
ìèíóòû: 0-59\n
÷àñû: 0-23\n
äíè: 0-364\n
ãîäà: 0-ïðèìåðíî äî 160 ëåò\n
äëß îòñ÷åòà äåëüò (ïðèðàùåíèé âðåìåíè):\n
ìèëèñåêóíäû: 0-0xFFFFFFFF - ñîîòâåòñòâóåò ïðèìåðíî 1.5 ìåñßöàì\n
ñåêóíäû: 0-0xFFFFFFFF - ñîîòâåòñòâóåò ïðèìåðíî 160 ãîäàì\n
Åñòü ñïåöèàëüíûé ñïîñîá, ïîçâîëßþùèé îòñ÷èòûâàòü âûäåðæêè âðåìåíè ñ òî÷íîñòüþ
äî ìèëëèñåêóíä â ïåðûâàíèè ØÈÌ. Èñïîëüçóåòñß ïåðåìåííàß delta_millisecond,
êîòîðàß âîçâîäèòñß â åäèíèöó êàæäóþ ìèëëèñåêóíäó è íà ñëåäóþùåì ïåðèîäå ØÈÌ
ñáðàñûâàåòñß. Òîãäà ìîæíî â íåîáõîäèìûé ñ÷åò÷èê äîáàâèòü counter+=delta_millisecond è
ïîëó÷èòü â counter ñ÷åò÷èê ìèëëèñåêóíä. Àíàëîãè÷íî delta_second.
ÏÐÈÌÅ×ÀÍÈÅ: 1. ìîäóëü íå òðåáóåò èíèöèàëèçàöèè
2. àâòîìàòè÷åñêè ïåðåíàñòðàèâàåòñß ïðè èçìåíåíèè íåñóùåé ÷àñòîòû
ÄËß ÊÎÐÐÅÊÒÍÎÉ ÐÀÁÎÒÛ ÌÎÄÓËß ÏÎËÜÇÎÂÀÒÅËÜ ÄÎËÆÅÍ:
1. â ìàêðîñå GLOBAL_TIME_CALC_FREQ ïðàâèëüíî óêàçàòü íåñóùóþ ÷àñòîòó âûçîâà ôóíêöèè ðàñ÷åòà.
Ñëåäóåò îòìåòèòü, ÷òî çíà÷åíèå GLOBAL_TIME_CALC_FREQ öåëî÷èñëåííîå, ïîýòîìó
ìîäóëü êîððåêòíî ðàáîòàåò òîëüêî ïðè öåëûõ çíà÷åíèßõ íåñóùåé ÷àñòîòû (â êÃö).
Íåäîñòàòîê ñâßçàí ñ êîíêðåòíîé ðåàëèçàöèåé ìîäóëß.
*/
//! ñì. TGlobalTime
struct SGlobalTime
{
RELATIVE_TIME relative_time1;//!îòíîñèòåëüíîå âðåìß 1
RELATIVE_TIME relative_time2;//!îòíîñèòåëüíîå âðåìß 2
ABSOLUTE_TIME absolute_time;//!àáñîëþòíîå âðåìß
int16 time_type;//!÷àñû ðåàëüíîãî âðåìåíè (1 - åñòü)
int32 PowerOn_time; //!<Îáùåå âðåìß íàðàáîòêè
int32 PowerOn_time_min; //!<Îáùåå âðåìß íàðàáîòêè â ìèíóòàõ
int32 operational_time; //!<Îáùåå âðåìß âêëþ÷åííîãî ñîñòîßíèß
int32 operational_time_min; //!<Îáùåå âðåìß âêëþ÷åííîãî ñîñòîßíèß â ìèíóòàõ
int16 WtiteSPI_flag;
int32 PrevWriteSPIHour;
void (*init)(volatile struct SGlobalTime*);
void (*calc)(volatile struct SGlobalTime*);
void (*ms_calc)(volatile struct SGlobalTime*);
void (*slow_calc)(volatile struct SGlobalTime*);
void (*read_PowerOn_time)(volatile struct SGlobalTime*);
void (*write_PowerOn_time)(volatile struct SGlobalTime*);
void (*read_oper_time) (volatile struct SGlobalTime*);
void (*write_oper_time)(volatile struct SGlobalTime*);
};
typedef volatile struct SGlobalTime TGlobalTime;
//!Èíèöàëèçàòîð îòíîñèòåëüíîé äàòû.
#define RELATIVE_DATE_DEFAULTS {0,0,0,0}
//!Èíèöèàëèçàòîð îòíîñèòåëüíîãî âðåìåíè.
#define RELATIVE_TIME_DEFAULTS {0,\
0,0,0,0,0,\
RELATIVE_DATE_DEFAULTS,\
}
//!Èíèöèàëèçàòîð àáñîëþòíîãî âðåìåíè.
#define ABSOLUTE_TIME_DEFAULTS {0,0,0,0,0}
//!Èíèöèàëèçàòîð TGlobalTime.
#define GLOBAL_TIME_DEFAULTS { RELATIVE_TIME_DEFAULTS,\
RELATIVE_TIME_DEFAULTS,\
ABSOLUTE_TIME_DEFAULTS,\
1,0,0,0,0,0,0,\
GlobalTime_init,\
GlobalTime_calc,\
GlobalTime_ms_calc,\
GlobalTime_slow_calc,\
GlobalTime_read_PowerOn_time, \
GlobalTime_write_PowerOn_time, \
GlobalTime_read_oper_time, \
GlobalTime_write_oper_time,\
}
//! \memberof TGlobalTime
void GlobalTime_init(TGlobalTime*);
//! \memberof TGlobalTime
void GlobalTime_calc(TGlobalTime*);
//! \memberof TGlobalTime
void GlobalTime_ms_calc(TGlobalTime*);
//! \memberof TGlobalTime
void GlobalTime_slow_calc(TGlobalTime*);
//! \memberof TGlobalTime
void GlobalTime_REL_TIME_calc(RELATIVE_TIME *p);
//! \memberof TGlobalTime
void GlobalTime_read_PowerOn_time(TGlobalTime*);
//! \memberof TGlobalTime
void GlobalTime_write_PowerOn_time(TGlobalTime*);
//! \memberof TGlobalTime
void GlobalTime_read_oper_time(TGlobalTime*);
//! \memberof TGlobalTime
void GlobalTime_write_oper_time(TGlobalTime*);
#ifdef __cplusplus
}
#endif
#endif
/*@}*/

96
Vinclude/SM_CmdLogic.h Normal file
View File

@ -0,0 +1,96 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file SMCmdLogic.h
\brief Îáðàáîòêà êîìàíä è çàäàíèé, ïîñòóïàþùèõ èç ðàçëè÷íûõ èñòî÷íèêîâ. (ñì. TSM_CmdLogic)
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 2.0 25/03/2016
\defgroup SMCmdLogic Îáðàáîòêà êîìàíä è çàäàíèé, ïîñòóïàþùèõ èç ðàçëè÷íûõ èñòî÷íèêîâ. (ñì. TSM_CmdLogic)
@{
*/
#ifndef SM_CmdLogicH
#define SM_CmdLogicH
#include "V_common.h"
#ifdef __cplusplus
extern "C"
{
#endif
//! Ñèñòåìà îñòàíîâëåíà, ãîòîâà ê çàïóñêó (ÃÎÒÎÂ)
#define CMD_LOGIC_TURNED_OFF 0x0
//! Ñîñòîÿíèå ÐÀÁÎÒÀ
#define CMD_LOGIC_TURNED_ON 0x2
/*! \class TSM_CmdLogic
\brief Îáðàáîòêà êîìàíä è çàäàíèé, ïîñòóïàþùèõ èç ðàçëè÷íûõ èñòî÷íèêîâ.
Êëàññ \a TSM_CmdLogic, îñíîâàííûé íà ñòðóêòóðå SSMCmdLogic, ñëóæèò äëÿ îáðàáîòêè êîìàíä
îïåðàòèâíîãî óïðàâëåíèÿ è çàäàíèÿ ñêîðîñòè. Êîìàíäû ìîãóò ïîñòóïàòü êàê ïî CANOpen,
òàê è ïî äðóãèì ïðîòîêîëàì (ModBus). Ñîäåðæèò äèñêðåòíûé àâòîìàò, êîòîðûé ïåðåêëþ÷àåò
ñèñòåìó ìåæäó ñîñòîÿíèÿìè ÐÀÁÎÒÀ è ÎÑÒÀÍÎÂ (ÃÎÒÎÂ).
*/
//! ñì. TSM_CmdLogic
struct SSM_CmdLogic
{
int state;//!<Cîñòîÿíèå
int state_prev;//!<Ïðåäûäóùåå ñîñòîÿíèå
int E;//!<Ôëàã ïåðâîãî âõîæäåíèÿ
TCmd cmd_by_level_prev;//!<Ïðåäûäóùåå ñîñòîÿíèå êîìàíäíîãî ñëîâà
int ReRunCounter;//!< Ñ÷åò÷èê âðåìåíè ñ ìîìåíòà ïðåäûäóùåãî çàïóñêà ñèñòåìû
int StartButtonPrev;
int StartButton;
int StopButtonPrev;
int StopButton;
void (*init)(volatile struct SSM_CmdLogic*);//!< Pointer to the init funcion
void (*slow_calc)(volatile struct SSM_CmdLogic*);//!< Pointer to the calc funtion
void (*ms_calc)(volatile struct SSM_CmdLogic*); //!< Pointer to the calc funtion
};
typedef volatile struct SSM_CmdLogic TSM_CmdLogic;
//! Èíèöèàëèçàòð ïî óìîë÷àíèþ
#define SM_CMD_LOGIC_DEFAULTS {0,0,0,{0},0,0,0,0,0,\
SM_CmdLogicInit,\
SM_CmdLogicSlow_Calc,\
SM_CmdLogicms_Calc}
//! \memberof TSM_CmdLogic
void SM_CmdLogicInit(TSM_CmdLogic*);
//! \memberof TSM_CmdLogic
void SM_CmdLogicSlow_Calc(TSM_CmdLogic*);
//! \memberof TSM_CmdLogic
void SM_CmdLogicms_Calc(TSM_CmdLogic*);
#ifdef __cplusplus
}
#endif
#endif
/*@}*/

94
Vinclude/SM_Ctrl.h Normal file
View File

@ -0,0 +1,94 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file SMCtrl.h
\brief Îñíîâíîé ÄÀ ïåðåêëþ÷åíèÿ ñèñòåì óïðàâëåíèÿ (ñì. TSM_Ctrl)
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 2.0 25/03/2016
\defgroup SMCtrl Îñíîâíîé ÄÀ ïåðåêëþ÷åíèÿ ñèñòåì óïðàâëåíèÿ (ñì. TSM_Ctrl)
@{
*/
#ifndef SM_Ctrl_H
#define SM_Ctrl_H
#ifdef __cplusplus
extern "C"
{
#endif
/*! \class TSM_Ctrl
\brief Îñíîâíîé ÄÀ ïåðåêëþ÷åíèÿ ñèñòåì óïðàâëåíèÿ
Êëàññ \a TSM_Ctrl, îñíîâàííûé íà ñòðóêòóðå SSMCtrl, ñîäåðæèò
îñíîâíîé äèñêðåòíûé àâòîìàò ïåðåêëþ÷åíèÿ ñèñòåì óïðàâåëíèÿ.  êàæäîì èç
ñîñòîÿíèé äàííîãî àâòîìàòà ðåàëèçîâàíà òà èëè èíàÿ ñòðóêòóðà óïðàâëåíèÿ.
Ñòðóêòóðà ñîáèðàåòñÿ èç ãîòîâûõ áëîêîâ. Îáû÷íî èñïîëüçóåñÿ ìîäóëü ØÈÌ,
ôàçíûå è êîîðäèíàòíûå ïðåîáðàçîâàíèÿ, ÀÖÏ, ÇÈ è ò.ï. Ñòðóêòóðû óïðàâëåíèÿ ìîãóò áûòü:
ñêàëÿðíîå óïðàâëåíèå, çàìêíóòàÿ ïî òîêó ñèñòåìà óïðàâëåíèÿ, âåêòîðíîå óïðàâëåíèå è ò.ï.
 run_mode çàäàåòñÿ íîìåð æåëàåìîé ñòðóêòóðû óïðàâëåíèÿ.
*/
//! ñì. TSM_Ctrl
struct SSM_Ctrl
{
long ctrl_counter;//!<Ñ÷åò÷èê âðåìåíè íàõîæäåíèÿ â îäíîì ñîñòîÿíèè
long run_mode;//!Çàäàííûé ðåæèì ðàáîòû (çàäàííîå ñîñòîÿíèå). Âåêòîðíîå óïðàâëåíèå, ñêàëÿðíîå, ïîñòîÿííûé òîê è ò.ï.
int state;//!<Ñîñòîÿíèå äèñêðåòíîãî àâòîìàòà - îíî æå òåêóùàÿ ñòðóêòóðà óïðàâëåíèÿ.
int state_prev;//!<Ïðåäûäóùåå ñîñòîÿíèå
int E;//!<Ôëàã ïåðâîãî âõîæäåíèÿ.
long AnglePrev;//!< Ïðåäûäóùåå çíà÷åíèå óãëà äëÿ ðåæèìà àâòîíàñòðîéêè ÄÏÐ
long AngleDemo;//!< Óãîë äëÿ äåìî-ðåæèìà êîíòóðà ïîëîæåíèÿ
void (*init)(struct SSM_Ctrl*); //!< Pointer to the init funcion
void (*slow_calc)(struct SSM_Ctrl*);//!< Pointer to the calc funtion
void (*fast_calc)(struct SSM_Ctrl*); //!< Pointer to the calc funtion
void (*ms_calc)(struct SSM_Ctrl*); //!< Pointer to the calc funtion
} ;
typedef struct SSM_Ctrl TSM_Ctrl;
//!Èíèöèàëèçàòîð ïî óìîë÷àíèþ
#define SM_CTRL_DEFAULTS {0,0,0,0,0,0,0,\
SM_Ctrl_Init,\
SM_Ctrl_Slow_Calc,\
SM_Ctrl_Fast_Calc,\
SM_Ctrl_ms_Calc,\
}
//! \memberof TSM_Ctrl
void SM_Ctrl_Init(TSM_Ctrl*);
//! \memberof TSM_Ctrl
void SM_Ctrl_Slow_Calc(TSM_Ctrl*);
//! \memberof TSM_Ctrl
void SM_Ctrl_Fast_Calc(TSM_Ctrl*);
//! \memberof TSM_Ctrl
void SM_Ctrl_ms_Calc(TSM_Ctrl*);
#ifdef __cplusplus
}
#endif
#endif
/*@}*/

93
Vinclude/SM_Net.h Normal file
View File

@ -0,0 +1,93 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file SMNet.h
\brief Ìîäóëü îáùåãî íàçíà÷åíèÿ äëÿ ðàáîòû ñ ñåòüþ. (ñì. TSM_Net)
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 2.0 25/03/2016
\defgroup SMNet Ìîäóëü îáùåãî íàçíà÷åíèÿ äëÿ ðàáîòû ñ ñåòüþ. (ñì. TSM_Net)
@{
*/
#ifndef SM_Net_H
#define SM_Net_H
#ifdef __cplusplus
extern "C"
{
#endif
#define DRV_STATUS_INIT 0x0
#define DRV_STATUS_READY 0x1
#define DRV_STATUS_RUNNING 0x2
#define DRV_STATUS_FAULT 0x3
#define DRV_STATUS_TESTING 0x4
#define DRV_STATUS_STOPPED 0x5
#define DRV_STATUS_AUTO_SET 0x6
#define DRV_STATUS_ALARM 0x8
/*! \class TSM_Net
\brief Ìîäóëü îáùåãî íàçíà÷åíèÿ äëÿ ðàáîòû ñ ñåòüþ.
Êëàññ \a TSM_Net, îñíîâàííûé íà ñòðóêòóðå SSMNet, ñîäåðæèò
ìåòîäû îáùåãî íàçíà÷åíèÿ äëÿ ðàáîòû ñ ðàçëè÷íûìè ñåòåâûìè èíòåðôåéñàìè.
Âûçîâ ôóíêöèé ðàñ÷åòà êîíêðåòíûõ ñåòåâûõ ìîäóëåé, ðàáîòà ñ ìàñøòàáèðóþùèìè êîýôôèöèåíòàìè è ò.ï.
*/
//! ñì. TSM_Net
struct SSM_Net
{
int state; //!<Ñîñòîÿíèå
int state_prev;//!<Ñîñòîÿíèå ïðåäûäóùåå
int E;//!<Ôëàã ïåðâîãî âõîæäåíèÿ
void (*init)(struct SSM_Net*); /* Pointer to the init funcion */
void (*slow_calc)(struct SSM_Net*); /* Pointer to the calc funtion */
void (*ms_calc)(struct SSM_Net*); /* Pointer to the calc funtion */
void (*fast_calc)(struct SSM_Net*); /* Pointer to the calc funtion */
} ;
typedef struct SSM_Net TSM_Net;
//!èíèöèàëèçàòîð ïî óìîë÷àíèþ
#define SM_NET_DEFAULTS {0,0,0,\
SM_Net_Init,\
SM_Net_Slow_Calc,\
SM_Net_ms_Calc,\
SM_Net_fast_Calc,\
}
//! \memberof TSM_Net
void SM_Net_Init(TSM_Net*);
//! \memberof TSM_Net
void SM_Net_Slow_Calc(TSM_Net*);
//! \memberof TSM_Net
void SM_Net_ms_Calc(TSM_Net*);
//! \memberof TSM_Net
void SM_Net_fast_Calc(TSM_Net*);
#ifdef __cplusplus
}
#endif
#endif
/*@}*/

128
Vinclude/SM_Protect.h Normal file
View File

@ -0,0 +1,128 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file SMProtect.h
\brief Ìîäóëü çàùèò. (ñì. TSM_Protect)
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 2.0 25/03/2016
\defgroup SMProtect Ìîäóëü çàùèò. (ñì. TSM_Protect)
@{
*/
#ifndef SM_Protect_H
#define SM_Protect_H
#ifdef __cplusplus
extern "C"
{
#endif
#include "build.h"
//! Ìîäóëü àùèò âûêëþ÷åí
#define PROT_OFF 0
//! Ìîäóëü çàùèò âêëþ÷åí
#define PROT_ON_OK 1
//! Ìîäóëü çàùèò â ñîñòîÿíèè àâàðèè (ñðàáîòàëà çàùèòà)
#define PROT_FAIL 2
//Ìàêðîñ ïðèåìà àïïàðàòíîé àâàðèè èíâåðòîðà: åñëè íîëü, òî àâàðèÿ
#define DRV_FAULT (GPIOA->DATA & (1 << 7))
/*! \class TSM_Protect
\brief Ìîäóëü çàùèò.
Êëàññ \a TSM_Protect, îñíîâàííûé íà ñòðóêòóðå SSMProtect,
îáðàáàòûâàåò âñå âîçìîæíûå àâàðèéíûå ñèòóàöèè è âîçâîäèò ñîîòâåòñòâóþùèé ýòîé
àâàðèè áèò â îäíîì èç ñëîâ bit_fault 1-2. äàëåå ïðîèñõîäèò îáðàáîòêà ýòèõ ñëîâ, è,
åñëè ýòà àâàðèÿ íå çàìàñêèðîâàíà, ïðîèñõîäèò îñòàíîâ ïðèâîäà.
*/
//! ñì. TSM_Protect
struct SSM_Protect
{
Uint16 state;//!< Ñîñòîÿíèå
Uint16 state_prev;//!< Ñîñòîÿíèå ïðåäûäóùåå
Uint16 readDrvSts; //!<Ôëàã çàïðîñà ÷òåíèÿ ñòàòóñà drv8301
Uint16 clearDrvFault; //!<Ôëàã çàïðîñà ñáðîñà àâàðèè drv8301
Uint16 bit_fault1;//!<Ñëîâî àâàðèé 1
Uint16 bit_fault2;//!<Ñëîâî àâàðèé 2
Uint16 masked_bit_fault1;//!<Ñëîâî àâàðèé ïîñëå ìàñêèðîâàíèÿ
Uint16 masked_bit_fault2;//!<Ñëîâî àâàðèé ïîñëå ìàñêèðîâàíèÿ
Uint16 mask_fault1;//!<Ìàñêà àâàðèé 1
Uint16 mask_fault2;//!<Ìàñêà àâàðèé 2
Uint16 bit_fault_written1;
Uint16 bit_fault_written2;
long Imax_protect; //!<Óñòàâêà ìàêñèìàëüíî-òîêîâîé çàùèòû
long Umax_protect; //!<Óñòàâêà çàùèòû max íàïðÿæåíèÿ íà ÇÏÒ
long Umin_protect;//!<Óñòàâêà çàùèòû min íàïðÿæåíèÿ íà ÇÏÒ
long speed_max;//!<Óñòàâêà ìàêñèìàëüíîé ñêîðîñòè
long T_max;
int E;//!<Ôëàã ïåðâîãî âõîæäåíèÿ
Uint16 Main_ErrorCode;//!< //ëèñòàþùèéñÿ êîä àâàðèè
Uint32 Main_Flags;//!< //Ôëàã àâàðèéíîé áëîêèðîâêè áëîêà
Uint16 powered_okCounter;//!< Ñ÷åò÷èê äëÿ îæèäàíèÿ âêëþ÷åíÿ ìîäóëÿ çàùèò ïîñëå èíåöèàëèçàöèè
void (*init)(struct SSM_Protect*); /* Pointer to the init funcion */
void (*slow_calc)(struct SSM_Protect*); /* Pointer to the calc funtion */
void (*fast_calc)(struct SSM_Protect*); /* Pointer to the calc funtion */
void (*ms_calc)(struct SSM_Protect*); /* Pointer to the calc funtion */
} ;
typedef struct SSM_Protect TSM_Protect;
//!Èíèöèàëèçàòîð ïî óìîë÷àíèþ
#define SM_PROTECT_DEFAULTS {0,0,\
0,0,\
0,0,\
0,0,\
0,0,\
0,0,\
0,0,0,0,0,\
0,0,0,0,\
SM_Protect_Init,\
SM_Protect_Slow_Calc,\
SM_Protect_Fast_Calc,\
SM_Protect_ms_Calc,\
}
//! \memberof TSM_Protect
void SM_Protect_Init(TSM_Protect*);
//! \memberof TSM_Protect
void SM_Protect_Slow_Calc(TSM_Protect*);
//! \memberof TSM_Protect
void SM_Protect_Fast_Calc(TSM_Protect*);
//! \memberof TSM_Protect
void SM_Protect_ms_Calc(TSM_Protect*);
#ifdef __cplusplus
}
#endif
#endif
/*@}*/

90
Vinclude/SM_Sys.h Normal file
View File

@ -0,0 +1,90 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file SMSys.h
\brief Ìîäóëü-îáåðòêà äëÿ ðàñ÷åòà îñòàëüíûõ ìîäóëåé. (ñì. TSM_Sys)
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 2.0 25/03/2016
\defgroup SMSys Ìîäóëü-îáåðòêà äëÿ ðàñ÷åòà îñòàëüíûõ ìîäóëåé. (ñì. TSM_Sys)
@{
*/
#ifndef SM_Sys_H
#define SM_Sys_H
#ifdef __cplusplus
extern "C"
{
#endif
//! Ñèñòåìà â èíèöèàëèçàöèè
#define SYS_INIT 0
//! Ñèñòåìà ïðîèíèöèàëèçèðîâàíà
#define SYS_READY 1
/*! \class TSM_Sys
\brief Ìîäóëü-îáåðòêà äëÿ ðàñ÷åòà îñòàëüíûõ ìîäóëåé.
Êëàññ \a TSM_Sys, îñíîâàííûé íà ñòðóêòóðå SSMSys, ÿâëÿåòñÿ ìîäóëåì,
âíóòðè ìåòîäîâ êîòîðîãî ïðîèñõîäèò âûçîâ áîëüøèíñòâà îñòàëüíûõ. Íàïðèìåð,
ôóíêöèÿ áûñòðîãî ðàñ÷åòà äàííîãî ìîäóëÿ âûçûâàåò ôóíêöèè áûñòðîãî ðàñ÷åòà
îñòàëüíûõ ìîäóëåé. Êðîìå òîãî, â èíèöèàëèçàöèè äàííîãî ìîäóëÿ íàñòðàèâàþòñÿ ïðåðûâàíèÿ
êîíòðîëëåðà.
*/
//! ñì. TSM_Sys
struct SSM_Sys
{
int state;//!< Ñîñòîÿíèå
int state_prev;//!< Ñîñòîÿíèå ïðåäûäóùåå
int E;//!<Ôëàã ïåðâîãî âõîæäåíèÿ
void (*init)(struct SSM_Sys*); /* Pointer to the init funcion */
void (*slow_calc)(struct SSM_Sys*); /* Pointer to the calc funtion */
void (*fast_calc)(struct SSM_Sys*); /* Pointer to the calc funtion */
void (*ms_calc)(struct SSM_Sys*); /* Pointer to the calc funtion */
} ;
typedef struct SSM_Sys TSM_Sys;
//!Èíèöèàëèçàòîð ïî óìîë÷àíèþ
#define SM_Sys_DEFAULTS {0,0,0,\
SM_Sys_Init,\
SM_Sys_Slow_Calc,\
SM_Sys_Fast_Calc,\
SM_Sys_ms_Calc,\
}
//! \memberof TSM_Sys
void SM_Sys_Init(TSM_Sys*);
//! \memberof TSM_Sys
void SM_Sys_Slow_Calc(TSM_Sys*);
//! \memberof TSM_Sys
void SM_Sys_Fast_Calc(TSM_Sys*);
//! \memberof TSM_Sys
void SM_Sys_ms_Calc(TSM_Sys*);
#ifdef __cplusplus
}
#endif
#endif
/*@}*/

72
Vinclude/V_AutoOffset.h Normal file
View File

@ -0,0 +1,72 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file V_AutoOffset.h (IQ version)
\brief Àâòîìàòè÷åñêèé ðàñ÷åò ñìåùåíèÿ äëÿ ÀÖÏ
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 2.0 25/03/2016
Äàííîå ïðîãðàììíîå îáåñïå÷åíèå ðàñïðîñòðàíÿåòñÿ "êàê åñòü", è Âû,
åãî ïîëüçîâàòåëü, ïðèíèìàåòå íà ñåáÿ âñå ðèñêè, ñâÿçàííûå ñ åãî èñïîëüçîâàíèåì.
ÎÎÎ "ÍÏÔ Âåêòîð" íå íåñåò íèêàêîé îòâåòñòâåííîñòè çà âîçìîæíûå óáûòêè,
ñâÿçàííûå ñ åãî èñïîëüçîâàíèåì.
*/
#ifndef V_AUTO_OFFSET_H
#define V_AUTO_OFFSET_H
#ifdef __cplusplus
extern "C"
{
#endif
#include "DSP.h"
struct SAutoOffset
{
_iq FilterK;//!< Êîýôôèöèåíò ôèëüòðà (òåìï èçìåíåíèÿ ñìåùåíèÿ)
int32 IA_int; //!< Èíòåãðàòîð äëÿ òîêà ôàçû A
int32 IB_int; //!< Èíòåãðàòîð äëÿ òîêà ôàçû B
int32 IC_int; //!< Èíòåãðàòîð äëÿ òîêà ôàçû C
int Enabled; //!< Âêëþ÷åíî/âûêëþ÷åíî
void (*init)(volatile struct SAutoOffset *);
void (*ms_calc)(volatile struct SAutoOffset *);
void (*slow_calc)(volatile struct SAutoOffset *);
};
typedef volatile struct SAutoOffset TAutoOffset;
#define AUTO_OFFSET_DEFAULTS {\
_IQ(0.0001),\
0,0,0,\
0,\
AutoOffset_init,\
AutoOffset_calc,\
AutoOffset_slow_calc}
void AutoOffset_init(TAutoOffset *);
void AutoOffset_calc(TAutoOffset *);
void AutoOffset_slow_calc(TAutoOffset *);
#ifdef __cplusplus
}
#endif
#endif

110
Vinclude/V_CANtoRS.h Normal file
View File

@ -0,0 +1,110 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file v_CANtoRS.h
\brief Ïðåîáðàçîâàòåëü ïîñûëîê CAN â RS/USB è îáðàòíî. Ðàáîòàåò
ñîâìåñòíî ñ äðàéâåðîì CANOpen
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 3.0 08/08/2017
*/
#ifndef V_CAN_TO_RS_H
#define V_CAN_TO_RS_H
#ifdef __cplusplus
extern "C" {
#endif
#define CANTORS_BUFSIZE 20
#define CANTORS_TRANSM_TIME_OUT 10
#define CANTORS_READ_DATA_MAX_LEN 10
#define CANTORS_HEART_COUNTER_MAX 1000
#define CANTORS_ACTIVE 0x1
#define CANTOUSB_ACTIVE 0x2
#include "DSP.h"
#include "CANOpen_drv.h"
struct SCANtoRS {
Uint16 lastActiveConnection; // Îïðåäåëÿåò, êàêîé èíòåðôåéñ áûë àêòèâåí â ïîñëåäíèé ðàç - USB èëè RS
Uint8 tempBuf[13]; // Âðåìåííûé áóôåð äëÿ äàííûõ
Uint16 test_dbg; //äëÿ îòëàäêè
Uint16 APIpacketMode;
int16 HeartBeatGo;//ïðîïóñòèòå ñåðäöåáèåíèå!
Uint16 callback_go; //ôëàã äëÿ âûçîâà callback
Uint16 TransmBusy; //ôëàã çàíÿòîñòè ïåðåäàò÷èêà
Uint16 PacketInWait; //ôëàã åñëè åñòü ÷òî-òî â áóôåðå îòïðàâêè
Uint16 HeartCounter; //ñ÷åò÷èê äëÿ îòïðàâêè HeartBeat
Uint16 TransmBusyTimeCount; //ñ÷åò÷èê òàéìàóòà çàíÿòîñòè ïåðåäàò÷èêà
Uint16 ReadPackDataCounter; //ñ÷åò÷èê äàííûõ â ïàêåòå
Uint16 ReadCRCCounter; //ñ÷åò÷èê äàííûõ â ïàêåòå
Uint16 SendTimeoutCounter;
Uint16 all_len; //transmit buf len
Uint16 tr_counter; //transmit counter
Uint16 MessDrop1;
Uint16 MessDrop2;
Uint16 MessDrop3;
Uint16 CounterWrongCRC;
Uint16 CounterRes;
Uint16 CounterSended;
void (*init)(volatile struct SCANtoRS *); /* Pointer to the init function */
void (*calc)(volatile struct SCANtoRS *); /* Pointer to the calc function */
void (*receive)(volatile struct SCANtoRS *);
Uint16 (*write)(TZCanMsg* MSG,volatile struct SCANtoRS *);
void (*callback)(TCo_OdVars* ppc, TZCanMsg* p);
unsigned char buf_out[CANTORS_BUFSIZE];
Uint16 temp_buf[CANTORS_BUFSIZE];
TZCanMsg MSG;
TZCanMsg bufMSG;
Uint16 ReadPackData[CANTORS_BUFSIZE]; //áóôåð äëÿ API ïîñûëêè
Uint16 ReadCRC[2]; //áóôåð äëÿ ÑRC
Uint16 TempData[10];
Uint16* nodeID;
UART_TypeDef *UART;//!Óêàçàòåëü íà èñïîëüçóåìûé ìîäóëü UART
};
typedef volatile struct SCANtoRS TCANtoRS;
void CANtoRS_init(TCANtoRS*);
void CANtoRS_calc(TCANtoRS*);
void CANtoRS_Receive(TCANtoRS*);
Uint16 CANtoRS_SendP(Uint16* Data, int16 len,TCANtoRS *p);
Uint16 CANtoRS_Write(TZCanMsg* MSG,TCANtoRS *p);
Uint16 CANtoRS_WriteHelper(TZCanMsg* MSG,TCANtoRS *p);
void CANtoRS_HeartBeat(TCANtoRS *p);
Uint16 CANtoRS_C_CRC(TCANtoRS *p,Uint16 *Data,Uint16 len);
void CANtoRS_Analysis(TCANtoRS*);
//åñëè äîáàâëÿåì â ñòðóêóðó ïåðåìåííûå òî äîáàâëÿåì çíà÷åíèÿ ïî óìîë÷àíèþ
#define CAN_TO_RS_DEFAULTS { .init = CANtoRS_init,\
.calc = CANtoRS_calc,\
.receive = CANtoRS_Receive,\
.write = CANtoRS_WriteHelper}
#ifdef __cplusplus
}
#endif
#endif

101
Vinclude/V_CurPar.h Normal file
View File

@ -0,0 +1,101 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file V_CurPar.h
\brief Ðàñ÷åò íàáëþäàåìûõ òåêóùèõ ïàðàìåòðîâ (ñì. TCurPar)
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 2.0 25/03/2016
\defgroup V_CurPar Ðàñ÷åò íàáëþäàåìûõ òåêóùèõ ïàðàìåòðîâ (ñì. TCurPar)
@{
*/
#ifndef V_CURPAR_H
#define V_CURPAR_H
#include "filter.h"
#ifdef __cplusplus
extern "C" {
#endif
/*! \class TCurPar
\brief Ðàñ÷åò íàáëþäàåìûõ òåêóùèõ ïàðàìåòðîâ
Êëàññ \a TCurPar, îñíîâàííûé íà ñòðóêòóðå SCurPar, ñîäåðæèò
ðÿä ðàçðîçíåííûõ âû÷èñëåíèé äëÿ îòîáðàæåíèÿ òåêóùèõ ïàðàìåòðîâ ïðèâîäà.
Íàïðèìåð, ðàñ÷åò äåéñòâóþùèõ òîêîâ ôàç, òåêóùåé ìîùíîñòè è ò.ï.
*/
//! ñì. TCurPar
struct SCurPar{
long speed; //!< Òåêóùàÿ ÷àñòîòà âðàùåíèÿ
long power; //!< Òåêóùàÿ ìîùíîñòü
long Is; //!< Òåêóùàÿ òîê ñòàòîðà àìïëèòóäíûé ìãíîâåííûé
long ThetaRefCurr; //!< Çàäàííîå óãëîâîå ïîëîæåíèå
long ThetaCurr; //!< Òåêóùåå óãëîâîå ïîëîæåíèå
long IsRef; //!< Òîê ñòàòîðà çàäàííûé
long Ialpha; //!< Òîê ïî îñè àëüôà
long Ibeta; //!< Òîê ïî îñè áåòòà
long Ualpha; //!< Íàïðÿæåíèå ïî îñè àëüôà
long Ubeta; //!< Íàïðÿæåíèå ïî îñè áåòòà
long PowerK; //!< Ñëóæåáíûé ïàðàìåòð äëÿ ìàñøòàáèðîâàíèÿ ìîùíîñòè
TFilter fPower; //!< Ôèëüòð ìîùíîñòè
void (*init)(volatile struct SCurPar*);//!< ïðîöåäóðà èíèöèàëèçàöèè
void (*calc)(volatile struct SCurPar*);//!<ðàñ÷åò
void (*slow_calc)(volatile struct SCurPar*);//!<ìåäëåííûé ðàñ÷åò
};
typedef volatile struct SCurPar TCurPar;
//!èíèöèàëèçàòîð ïî-óìîë÷àíèþ
#define TCUR_PAR_DEFAULTS \
{\
0,0,0,0,0,\
0,0,0,\
0,0,0,\
FILTER_DEFAULTS,\
&CurPar_init, \
&CurPar_calc, \
&CurPar_slow_calc, \
}
//! \memberof TCurPar
void CurPar_init(TCurPar*);
//! \memberof TCurPar
void CurPar_calc(TCurPar*);
//! \memberof TCurPar
void CurPar_slow_calc(TCurPar*);
#ifdef __cplusplus
}
#endif // extern "C"
#endif // V_UF_H
/*@}*/

226
Vinclude/V_DPR_eCAP.h Normal file
View File

@ -0,0 +1,226 @@
/*!
Copyright 2017 АО "НИИЭТ" и ООО "НПФ ВЕКТОР"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file V_DPR_eCAP.h
\brief Модуль расчёта скорости и положения по трём датчикам на элементах Холла.
\author ООО "НПФ Вектор". http://motorcontrol.ru
\version v 2.0 25/03/2016
*/
#ifndef V_DPR_ECAP_H
#define V_DPR_ECAP_H
#ifdef __cplusplus
extern "C"
{
#endif
struct SDPReCAPFLG1_BITS // bits
{
Uint16 AngleMode:
1; // 0 Режим расчета угла: 0 - 6 секторов, 1 - интерполяция
Uint16 SpeedMode:
1; // 1 Режим расчета скорости: 0 - по каждому датчику, 1 - по каждой метке
Uint16 Dir:
1; // 2 Направление движения: 0 - по часовой, 1 - против.
Uint16 PrevDir:
1; // 3 Направление движения: 0 - по часовой, 1 - против.
Uint16 CAPnumber:
2; // 4-5 Номер eCAP, по которому было предыдущее прерывание.
Uint16 ZeroFLG:
1; // 6 Флаг обнуления скорости
Uint16 SpeedMinFLG:
1; // 7
Uint16 firstlaunch1:1; //!< 1 FLAG: первое попадание в прерывание eCAP1.
Uint16 firstlaunch2:1; //!< 2 FLAG: первое попадание в прерывание eCAP2.
Uint16 firstlaunch3:1; //!< 3 FLAG: первое попадание в прерывание eCAP3.
Uint16 rsvd:
5; // 8-15 reserved;
};
union SDPReCAP_FLG1
{
Uint16 all;
struct SDPReCAPFLG1_BITS bit;
};
struct SDPReCAP
{
int16 enabled;
int16 initialized;
int16 HallCode; //Текущий код положения по датчикам Холла
Uint32 Ts; // Период для расчёта интерполированного угла
Uint32 Tspeed; // Период для расчёт скорости
Uint32 TsNom; // Период, соответсвующий номинальной скорости
Uint32 TsNomMilsec; // Период, соответсвующий номинальной скорости при тактировании 1 мс
Uint32 PrevTs; // Предыдущая величина периода для расчёта угла.
_iq speed; // Расчитанная скорость
_iq speedMIN; // Уставка минимальной скорости
_iq speedMinREF; // Скорость, соответствующая уставке для обнуления скорости
_iq Angle; // Расчитанный интерполированный угол
_iq Angle6; // Расчитанный декодированный угол
_iq AnglePrev; // Расчитанный декодированный угол предыдущий
Uint32 cnt; // Счётчик числа прерываний с момента пуска (дальше 2 не считает).
Uint32 cnt2; // Счётчик прерываний смомента реверса.
Uint32 milsec; // Время в мс с момента прихода прошлой метки
Uint32 milsecFIX; // Переститанная уставка для обнуления скорости
Uint32 milsecREF; // Уставка для обнуления скорости
Uint32 milsecPrevREF; // Предыдущее значение уставки для обнуления скорости
Uint32 PrevTspeed; // Предыдущая величина периода для расчёта скорости
Uint32 PrevTspeed1; // Предыдущая величина периода для расчёта скорости по датчику А.
Uint32 PrevTspeed11;
Uint32 PrevTspeed2; // Предыдущая величина периода для расчёта скорости по датчику B.
Uint32 PrevTspeed22;
Uint32 PrevTspeed3; // Предыдущая величина периода для расчёта скорости по датчику C.
Uint32 PrevTspeed33;
int16 CAPCalcEna1;
int16 CAPCalcEna2;
int16 CAPCalcEna3;
int16 CAP_WrongEdgeCnt;
int16 CAP_WrongEdgeCnt1;
int16 CAP_WrongEdgeCnt2;
int16 CAP_WrongEdgeCnt3;
int16 CAP_WrongEdgeCntPrev;
Uint16 WrongCodeCounter;
Uint16 WrongCodeCounterPerSec;
Uint16 WrongCodeCounterLimitPerSec;
int32 AngleOffset;
int16 ErrorLevel;
int16 ErrorLevelCounter;
int16 ErrorLevelTimeCounterBig;
int16 ErrorLevelTimeCounter;
int16 SensorFault;
Uint16 UserDirection;//пользовательская инверсия направления
float SimulatorOmega2IQ_factor;
union SDPReCAP_FLG1 DPReCAP_FLG1;
void (*Init)(volatile struct SDPReCAP*);
void (*AngleCalc)(volatile struct SDPReCAP*);
void (*Angle6Calc)(volatile struct SDPReCAP*);
void (*AngleErrorCalc)(volatile struct SDPReCAP*);
void (*SpeedCalc)(volatile struct SDPReCAP*);
void (*CAP1Calc)(volatile struct SDPReCAP*);
void (*CAP2Calc)(volatile struct SDPReCAP*);
void (*CAP3Calc)(volatile struct SDPReCAP*);
void (*HelpCalc)(volatile struct SDPReCAP*);
void (*slow_calc)(volatile struct SDPReCAP*);
void (*ms_calc)(volatile struct SDPReCAP*);
void (*calc_10k)(volatile struct SDPReCAP*);
};
typedef volatile struct SDPReCAP TDPReCAP;
/******************************************************************************
Инициализация структуры по умолчанию
******************************************************************************/
#define DPRECAP_DEFAULTS \
{\
0,0,0,0,0,0,0,0,0, \
0,0,0,0,0, \
0,0,0,0,0,0, \
0,0,0,0,0,0,0,\
0,0,0,\
0,0,0,0,0,\
0,0,0,0,\
0,0,0,0,0,0,\
0,0,\
&DPReCAP_Init, \
&DPReCAP_AngleCalc, \
&DPReCAP_Angle6Calc, \
&DPReCAP_AngleErrorCalc, \
&DPReCAP_SpeedCalc, \
&DPReCAP_CAP1Calc, \
&DPReCAP_CAP2Calc, \
&DPReCAP_CAP3Calc, \
&DPReCAP_HelpCalc, \
&DPReCAP_SlowCalc, \
&DPReCAP_msCalc, \
&DPReCAP_calc_10k\
}
/******************************************************************************
Процедура инициализации.
******************************************************************************/
void DPReCAP_Init(TDPReCAP*);
/******************************************************************************
Процедура расчёта угла.
******************************************************************************/
void DPReCAP_Angle6Calc(TDPReCAP*);
/******************************************************************************
Процедура вычисления факта ошибочного изменения угла.
******************************************************************************/
void DPReCAP_AngleErrorCalc(TDPReCAP*);
/******************************************************************************
Процедура расчёта интерполированного угла.
******************************************************************************/
void DPReCAP_AngleCalc(TDPReCAP*);
/******************************************************************************
Процедура расчёта скорости.
******************************************************************************/
void DPReCAP_SpeedCalc(TDPReCAP*);
/******************************************************************************
Расчёт прерывания 1
******************************************************************************/
void DPReCAP_CAP1Calc(TDPReCAP*);
/******************************************************************************
Расчёт прерывания 2
******************************************************************************/
void DPReCAP_CAP2Calc(TDPReCAP*);
/******************************************************************************
Расчёт прерывания 3
******************************************************************************/
void DPReCAP_CAP3Calc(TDPReCAP*);
/******************************************************************************
Вспомогательные расчёт, общий для всех прерываний
******************************************************************************/
void DPReCAP_HelpCalc(TDPReCAP*);
/******************************************************************************
Вспомогательные расчёт в фоне
******************************************************************************/
void DPReCAP_SlowCalc(TDPReCAP*);
/******************************************************************************
Миллисекундный расчет
******************************************************************************/
void DPReCAP_msCalc(TDPReCAP*);
void DPReCAP_calc_10k(TDPReCAP* p);
#ifdef __cplusplus
}
#endif // extern "C"
#endif // V_DPR_ECAP_H

337
Vinclude/V_IQmath.h Normal file
View File

@ -0,0 +1,337 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file V_IQmath.h
\brief Áèáëèîòåêà ôóíêöèé öåëî÷èñëåííîé ìàòåìàòèêè
\author ÎÎÎ "ÍÏÔ Âåêòîð". Âñå ïðàâà çàùèùåíû. http://motorcontrol.ru
\version v 2.0 25/03/2016
\defgroup V_IQmath Áèáëèîòåêà ôóíêöèé öåëî÷èñëåííîé ìàòåìàòèêè
\addtogroup V_IQmath
@{*/
#ifndef V_IQ_MATH_H
#define V_IQ_MATH_H
#ifdef __cplusplus
extern "C" {
#endif
#include "DSP.h"
static const int32 fix16_max = 0x7FFFFFFF; /*!< the maximum value of int32 */
static const int32 fix16_min = 0x80000000; /*!< the minimum value of int32 */
static const int32 fix16_overflow = 0x80000000; /*!< the value used to indicate overflows when FIXMATH_NO_OVERFLOW is not specified */
static const int32 fix16_pi = 205887;
static const int32 fix16_e = 178145;
static const int32 fix16_one = 0x00010000;
#define _PI 3.1415926535f
typedef int32 _iq;
//Ïðåîáðàçîâàíèå äàííûõ â ôîðìàòå ñ ïëàâàþùåé òî÷êîé â öåëî÷èñëåííûå ôîðìàòû îò IQ1 äî IQ30.
#define _IQ30(A) (long) ((A) * 1073741824.0f)
#define _IQ29(A) (long) ((A) * 536870912.0f)
#define _IQ28(A) (long) ((A) * 268435456.0f)
#define _IQ27(A) (long) ((A) * 134217728.0f)
#define _IQ26(A) (long) ((A) * 67108864.0f)
#define _IQ25(A) (long) ((A) * 33554432.0f)
#define _IQ24(A) (long) ((A) * 16777216.0f)
#define _IQ23(A) (long) ((A) * 8388608.0f)
#define _IQ22(A) (long) ((A) * 4194304.0f)
#define _IQ21(A) (long) ((A) * 2097152.0f)
#define _IQ20(A) (long) ((A) * 1048576.0f)
#define _IQ19(A) (long) ((A) * 524288.0f)
#define _IQ18(A) (long) ((A) * 262144.0f)
#define _IQ17(A) (long) ((A) * 131072.0f)
#define _IQ16(A) (long) ((A) * 65536.0f)
#define _IQ15(A) (long) ((A) * 32768.0f)
#define _IQ14(A) (long) ((A) * 16384.0f)
#define _IQ13(A) (long) ((A) * 8192.0f)
#define _IQ12(A) (long) ((A) * 4096.0f)
#define _IQ11(A) (long) ((A) * 2048.0f)
#define _IQ10(A) (long) ((A) * 1024.0f)
#define _IQ9(A) (long) ((A) * 512.0f)
#define _IQ8(A) (long) ((A) * 256.0f)
#define _IQ7(A) (long) ((A) * 128.0f)
#define _IQ6(A) (long) ((A) * 64.0f)
#define _IQ5(A) (long) ((A) * 32.0f)
#define _IQ4(A) (long) ((A) * 16.0f)
#define _IQ3(A) (long) ((A) * 8.0f)
#define _IQ2(A) (long) ((A) * 4.0f)
#define _IQ1(A) (long) ((A) * 2.0f)
//ïî óìîë÷àíèþ ôîðìàò IQ24
#define _IQ(A) _IQ24(A)
#define _IQmpy(A,B) _IQ24mpy(A,B)
#define _IQmpyI32(A,B) _IQ24mpyI32(A,B)
#define _IQdiv(A,B) _IQ24div(A,B)
#define _IQsqrt(A) _IQ24sqrt(A)
#define _IQsinPU(A) _IQ24sinPU(A)
#define _IQcosPU(A) _IQ24cosPU(A)
#define _IQsin(A) _IQ24sin(A)
#define _IQcos(A) _IQ24cos(A)
#define _IQtanPU(A) _IQ24tanPU(A)
#define _IQatan2PU(A,B) _IQ24atan2PU(A,B)
#define _IQmag(A,B) _IQ24mag(A,B)
#define _IQtoF(A) _IQ24toF(A)
int32 _IQ24sinPU(int32 inAngle);
int32 _IQ24atan2PU(int32 inY , int32 inX);
int32 _IQ24sinPU_accurate(int32 inAngle);
int32 _IQ24sqrt(int32 inValue);
int32 _IQ16div(int32 a, int32 b);
int32 _IQ24div(int32 a, int32 b);
int32 _IQ21div(int32 a, int32 b);
int32 _IQ10div(int32 a, int32 b);
int32 _IQ24mag(int32 a, int32 b);
//! Ïðåîáðàçóåò èç öåëî÷èñëåííîãî 8.24 â ôîðìàò float
//! \memberof V_IQmath
#if defined (__GNUC__)
__attribute__((always_inline))
#elif defined (__CMCPPARM__)
__STATIC_INLINE
#endif
inline float _IQ24toF(int32_t a) {
return (float)(a)*(1.0/16777216.0f);
}
//! \memberof V_IQmath
#if defined (__GNUC__)
__attribute__((always_inline))
#elif defined (__CMCPPARM__)
__STATIC_INLINE
#endif
inline float _IQ21toF(int32_t a) {
return (float)(a)*(1.0/2097152.0f);
}
//! \memberof V_IQmath
#if defined (__GNUC__)
__attribute__((always_inline))
#elif defined (__CMCPPARM__)
__STATIC_INLINE
#endif
inline float _IQ12toF(int32_t a) {
return (float)(a)*(1.0/4096.0f);
}
//! Ïðåîáðàçóåò èç öåëî÷èñëåííîãî 22.10 â ôîðìàò float
//! \memberof V_IQmath
#if defined (__GNUC__)
__attribute__((always_inline))
#elif defined (__CMCPPARM__)
__STATIC_INLINE
#endif
inline float _IQ10toF(int32_t a) {
return (float)(a)*(1.0/1024.0f);
}
//! Ïðåîáðàçóåò èç öåëî÷èñëåííîãî 26.6 â ôîðìàò float
//! \memberof V_IQmath
#if defined (__GNUC__)
__attribute__((always_inline))
#elif defined (__CMCPPARM__)
__STATIC_INLINE
#endif
inline float _IQ6toF(int32_t a) {
return (float)(a)*(1.0/64.0f);
}
//! Óìíîæåíèå äâóõ ÷èñåë â ôîðìàòå 8.24
//! \memberof V_IQmath
#if defined (__GNUC__)
__attribute__((always_inline))
#elif defined (__CMCPPARM__)
__STATIC_INLINE
#endif
inline int32 _IQ24mpy(int32 inArg0, int32 inArg1) {
return (int32)(((int64_t)inArg0 * inArg1)>> 24);
}
//! \memberof V_IQmath
#if defined (__GNUC__)
__attribute__((always_inline))
#elif defined (__CMCPPARM__)
__STATIC_INLINE
#endif
inline int32 _IQ18mpy(int32 inArg0, int32 inArg1) {
return (int32)(((int64_t)inArg0 * inArg1)>> 18);
}
//! \memberof V_IQmath
#if defined (__GNUC__)
__attribute__((always_inline))
#elif defined (__CMCPPARM__)
__STATIC_INLINE
#endif
inline int32 _IQ20mpy(int32 inArg0, int32 inArg1) {
return (int32)(((int64_t)inArg0 * inArg1)>> 20);
}
//! Óìíîæåíèå äâóõ ÷èñåë â ôîðìàòå 32.0
//! \memberof V_IQmath
#if defined (__GNUC__)
__attribute__((always_inline))
#elif defined (__CMCPPARM__)
__STATIC_INLINE
#endif
inline int32 _IQ24mpyI32(int32 inArg0, int32 inArg1) {
return (inArg0 * inArg1);
}
//! Óìíîæåíèå äâóõ ÷èñåë â ôîðìàòå 16.16
//! \memberof V_IQmath
#if defined (__GNUC__)
__attribute__((always_inline))
#elif defined (__CMCPPARM__)
__STATIC_INLINE
#endif
inline int32 _IQ16mpy(int32 inArg0, int32 inArg1) {
int64_t product = (int64_t)inArg0 * inArg1;
int32 result = product >> 16;
// result += (product & 0x8000) >> 15; //Íåïîíòÿíî äëÿ ÷åãî. Íàïèñàíî äëÿ îêðóãëåíèÿ
return result;
}
//! Óìíîæåíèå äâóõ ÷èñåë â ôîðìàòå 28.4
//! \memberof V_IQmath
#if defined (__GNUC__)
__attribute__((always_inline))
#elif defined (__CMCPPARM__)
__STATIC_INLINE
#endif
inline int32 _IQ4mpy(int32 inArg0, int32 inArg1) {
return (int32)(((int64_t)inArg0 * inArg1)>> 4);
}
//! Ôóíêöèÿ êîñèíóñà, âûçûâàåò ôóíêöèþ ñèíóñà
//! \memberof V_IQmath
#if defined (__GNUC__)
__attribute__((always_inline))
#elif defined (__CMCPPARM__)
__STATIC_INLINE
#endif
inline int32 _IQ24cosPU(int32 inAngle) {
return _IQ24sinPU(inAngle + _IQ24(0.25));
}
//! \memberof V_IQmath
#if defined (__GNUC__)
__attribute__((always_inline))
#elif defined (__CMCPPARM__)
__STATIC_INLINE
#endif
inline int32 _IQ18sinPU(int32 inAngle) {
return _IQ24sinPU(inAngle<<6)>>6;
}
//! \memberof V_IQmath
#if defined (__GNUC__)
__attribute__((always_inline))
#elif defined (__CMCPPARM__)
__STATIC_INLINE
#endif
inline int32 _IQ18cosPU(int32 inAngle) {
return _IQ24sinPU((inAngle<<6) + _IQ24(0.25))>>6;
}
//! Ôóíêöèÿ òàíãåíñà, âûçûâàåò ôóíêöèè ñèíóñà è êîñèíóñà.
//! \memberof V_IQmath
#if defined (__GNUC__)
__attribute__((always_inline))
#elif defined (__CMCPPARM__)
__STATIC_INLINE
#endif
inline int32 _IQ24tanPU(int32 inAngle) {
return _IQ24div(_IQ24sinPU(inAngle), _IQ24sinPU(inAngle));
}
#if defined (__GNUC__)
__attribute__((always_inline))
#elif defined (__CMCPPARM__)
__STATIC_INLINE
#endif
inline int32 _IQ16toIQ(int32 a){
return (a << 8);
}
#if defined (__GNUC__)
__attribute__((always_inline))
#elif defined (__CMCPPARM__)
__STATIC_INLINE
#endif
inline int32 _IQ24cos(int32 x){
x = _IQmpy(x, _IQ(0.15915494309189533576));
return _IQsinPU(x + _IQ24(0.25));
}
#if defined (__GNUC__)
__attribute__((always_inline))
#elif defined (__CMCPPARM__)
__STATIC_INLINE
#endif
inline int32 _IQ24sin(int32 x){
x = _IQmpy(x, _IQ(0.15915494309189533576));
return _IQsinPU(x);
}
#if defined (__GNUC__)
__attribute__((always_inline))
#elif defined (__CMCPPARM__)
__STATIC_INLINE
#endif
inline int32 _IQabs(int32 x){
if (x<0)
return -x;
return x;
}
#ifdef __CMCPPARM__
#define fabs(x) fabsf(x)
#endif /* __CMCPPARM__ */
#ifdef __cplusplus
}
#endif
#endif
/*@}*/

90
Vinclude/V_MBVarsConv.h Normal file
View File

@ -0,0 +1,90 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file v_MBVarsConv.h
\brief Ìîäóëü ïðåîáðàçîâàíèÿ äàííûõ Modbus
\author ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
\version v.1.1. 02/03/2017
\addtogroup v_ModBus
@{
*/
#ifndef V_MBVARSCONV_H
#define V_MBVARSCONV_H
#ifdef __cplusplus
extern "C" {
#endif
#include "DSP.h"
/*! \class TMBVarsConv
\brief Ìîäóëü ïðåîáðàçîâàíèÿ äàííûõ Modbus
Êëàññ \a TMBVarsConv, îñíîâàííûé íà ñòðóêòóðå SMBVarsConv, ïðåäíàçíà÷åí
äëÿ ïðåîáðàçîâàíèÿ äàííûõ èç ôîðìàòà 16 ðàçðÿäîâ Modbus â ôîðìàò ñèñòåìû óïðàâëåíèÿ (IQ 24).
*/
struct SMBVars{
int Command;
int CommandPrev;
int speed_ref;
int CurIs;
int CurSpeed;
int Main_ErrorCode;
int Umax_protect;
};
//!ñì. TMBVarsConv MBVars
#define SMBVARS_DEFAULTS {0,0,0,0,0,0}
struct SMBVarsConv{
struct SMBVars Vars;
Uint16 NeedForSave;
void (*init)(volatile struct SMBVarsConv*);
void (*calc)(volatile struct SMBVarsConv*);
void (*slow_calc)(volatile struct SMBVarsConv*);
};
typedef volatile struct SMBVarsConv TMBVarsConv;
//!Èíèöèàëèçàòîð ïî óìîë÷àíèþ
#define MBVARSCONV_DEFAULTS { SMBVARS_DEFAULTS,\
0,\
MBVarsConv_init,\
MBVarsConv_calc,\
MBVarsConv_slow_calc\
}
//! \memberof TMBVarsConv
void MBVarsConv_init(TMBVarsConv *p);
//! \memberof TMBVarsConv
void MBVarsConv_calc(TMBVarsConv *p);
//! \memberof TMBVarsConv
void MBVarsConv_slow_calc(TMBVarsConv *p);
#ifdef __cplusplus
}
#endif
#endif
/*@}*/

126
Vinclude/V_ModBus.h Normal file
View File

@ -0,0 +1,126 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file V_ModBus.h
\brief Äðàéâåð ModBus (ñì. TModBus)
\author Alecksey Anuchin
\version v 1.1 24/03/2017
\defgroup V_ModBus Äðàéâåð ModBus (ñì. TModBus)
@{
*/
#ifndef V_MODBUS_H
#define V_MODBUS_H
#ifdef __cplusplus
extern "C" {
#endif
#include "mbod.h"
#define MODBUS_MAX_RX_COUNT 10
/*! \class TModBus
\brief Äðàéâåð ModBus
Êëàññ \a TModBus, îñíîâàííûé íà ñòðóêòóðå SModBus, îáðàáàòûâàåò
âõîäÿùèå ïîñûëêè ïî RS-485 êàê ïîñûëêè ModBus (RTU). */
//! ñì. TModBus
//! Ñòðóêòóðà modbus äëÿ õðàíåíèÿ âíóòðåííèõ äàííûõ
typedef struct {volatile Uint16 In[MODBUS_MAX_RX_COUNT];//!<Ìàññèâ äëÿ ïðèíÿòèÿ äàííûõ
volatile Uint16 InCount;//!<Ñ÷åò÷èê äëÿ ìàññèâà ïðèíÿòûõ äàííûõ
volatile MB_Record /*const*/ *Addr;//!<Óêàçàòåëü íà ñëîâàðü
volatile Uint16 TimeOut;//!<Òåêóùèé òàéìàóò, êîòîðûé íàäî âûäåðæèâàòü
volatile Uint16 TimeOut1_5;//!<Ðàññ÷èòàííûé òàéìàóò 1,5 äëèíû ïåðåäàííîãî áàéòà
volatile Uint16 TimeOut2_5;//!<Ðàññ÷èòàííûé òàéìàóò 2,5 äëèíû ïåðåäàííîãî áàéòà
volatile Uint16 ToSend;//!<Äàííûå äëÿ îòïðàâêè
volatile Uint16 NumOfHRs;//!<Êîëè÷åñòâî Holding Registers
volatile Uint16 MiddleOfHRs;//!<Ñåðåäèíà Holding Registers
volatile Uint16 InitialStepOfHRs;//!<Øàã Holding Registers
volatile Uint16 NumOfIRs;//!<Êîëè÷åñòâî Input Registers
volatile Uint16 MiddleOfIRs;//!<Ñåðåäèíà Input Registers
volatile Uint16 InitialStepOfIRs;//!<Øàã Input Registers
volatile Uint16 NumOfCs;//!<Êîëè÷åñòâî Coils
volatile Uint16 MiddleOfCs;//!<Ñåðåäèíà Coils
volatile Uint16 InitialStepOfCs;//!<Øàã Coils
volatile Uint16 NumOfDIs;//!<Êîëè÷åñòâî Discrete Inputs
volatile Uint16 MiddleOfDIs;//!<Ñåðåäèíà Discrete Inputs
volatile Uint16 InitialStepOfDIs;//!<Øàã Discrete Inputs
volatile Uint16 RxCRC;//!<Ïðèíèìàåìàÿ êîíòðîëüíàÿ ñóììà
volatile Uint16 TxCRC;//!<Ïåðåäàâàåìàÿ êîíòðîëüíàÿ ñóììà
volatile Uint16 MagicNumber;//!<Ýì...
volatile int16 TxState;//!<Ñîñòîÿíèå ïåðåäà÷è
volatile Uint16 temp;//!<
volatile int16 RecievedCounter;//!<Ñ÷åò÷èê äëÿ îòñ÷èûâàíèÿ òàéìàóòà ïî ïðèåìó
UART_TypeDef *UART;//!Óêàçàòåëü íà èñïîëüçóåìûé ìîäóëü UART
} MODBUS_INT;
#define MODBUS_INT_DEFAULTS {{0},0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\
0xFFFF,0xFFFF, 0xA001,-1, 0,0, \
}
struct SModBus{Uint32 BaudRate;//!<Ñêîðîñòü ðàáîòû ïî RS
Uint16 ExecutionFreq;//!< ×àñòîòà òàêòèðîâàíèÿ ìîäóëÿ
Uint16 RSNodeID; //!< Íîìåð óçëà â ñåòè
Uint16 Enabled; //!< Ðàçðåøåíèå èçìåíåíèÿ ïàðàìåòðîâ ïðèâîäà ÷åðåç ModBus
Uint16 Refresh; //!< Ôëàã èçìåíåíèÿ ïàðàìåòðîâ ïî Modbus
int16 error;
int16 errorCode;
int16 AutoRestart;
int16 clear_error;
Uint16 received_data;
Uint16 GPIOsValue;
Uint16 isOnline;//!< Â ñåòè ìû èëè íåò (èäóò ëè ïàêåòû)
Uint32 OfflineCounter;//!< Ñ÷åò÷èê èíêðåìåíòèðóåòñÿ ñ ÷àñòîòîé âûçîâà ïðîöåäóðû ModBus_Execute è îáíóëÿåòñÿ, åñëè â ñåòè åñòü ïàêåòû
Uint32 OfflineCounterMax;//!< Òàéìàóò îòñóòñòâèÿ ïàêåòîâ â ñåòè (â åäèíèöàõ ñ÷¸òà OfflineCounter)
Uint16 ReceiveByteCounter;//!< Ñ÷åò÷èê ïðèíÿòûõ áàéò
Uint16 ReceivePacketCounter;//!< Ñ÷åò÷èê ïðèíÿòûõ ïîñûëîê
MODBUS_INT MBInternals;//!< Ñëóæåáíûå ïåðåìåííûå äëÿ ðàáîòû äðàéâåðà (íå äëÿ ïîëüçîâàòåëÿ)
void (*Init)(volatile struct SModBus*);
void (*Execute)(volatile struct SModBus*);
};
typedef volatile struct SModBus TModBus;
#define MODBUS_DEFAULTS {9600,10000, 0x01, 1, 0,\
0,0,0,0,0,0,0,0,0,0,0,\
MODBUS_INT_DEFAULTS,\
ModBus_Init, \
ModBus_Execute,\
}
//! \memberof TModBus
void ModBus_Init(TModBus *p);
//! \memberof TModBus
void ModBus_Execute(TModBus *p);
//! \memberof TModBus
int16 ModBus_FindVocAddr(TModBus *p,volatile MB_Record Table[], Uint16 TableSize, int16 Type, Uint16 Index, int16 NumOfIndexs, int16 Mid, int16 Step);
#ifdef __cplusplus
}
#endif
#endif
/*@}*/

173
Vinclude/V_PWM_Module.h Normal file
View File

@ -0,0 +1,173 @@
/*!
Copyright 2017 АО "НИИЭТ" и ООО "НПФ ВЕКТОР"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file V_PWM_Module.h
\brief Модуль реализации векторной ШИМ (см. TPWM_Module)
\author ООО "НПФ Вектор". http://motorcontrol.ru
\version v 2.0 25/03/2016
\defgroup V_PWM_Module Модуль реализации векторной ШИМ (см. TPWM_Module)
@{*/
#ifndef _V_PWM_Module_
#define _V_PWM_Module_
#ifdef __cplusplus
extern "C"
{
#endif
#define _1_SQRT3 _IQ(0.5773503)
#define _2_SQRT3 _IQ(1.1547005)
//! Ограничения частоты ШИМ (кГц) min
#define PWM_FREQ_MIN _IQ10(2)
//! Ограничения частоты ШИМ (кГц) max
#define PWM_FREQ_MAX _IQ10(100.0)
//!Векторная 6-ти секторная ШИМ
#define PWM_TYPE_6SECT_NO_SV 0
//!Синусоидальная ШИМ
#define PWM_TYPE_SIN_PWM 1
//!Векторная 12-ти секторная ШИМ
#define PWM_TYPE_12SECT_NO_SV 2
//!ШИМ методом вычисления фазных потенциалов
#define PWM_TYPE_FLY_12SECT 3
//!ШИМ для управления ДПТ
#define PWM_TYPE_DC_DRIVE 4
//!ШИМ для управления SRM
#define PWM_TYPE_SRD 5
//! Ограничения величины "мёртвого времени", мкс, min
#define DEAD_BAND_MIN _IQ(0)
//! Ограничения величины "мёртвого времени", мкс, max
#define DEAD_BAND_MAX _IQ(10)
//! Ограничения величины "минимальной скважности", мкс, min
#define GAMMA_LIMIT_MIN _IQ(0)
//! Ограничения величины "минимальной скважности", мкс, max
#define GAMMA_LIMIT_MAX _IQ(10)
// Константы загрузки регистров AQCTL# и AQCSFRC (ePWM)
// (определяют настройку событий для выходов ШИМ)
#define AQ_EPWM_DISABLE 0x0000 //!< все события запрещены
//! Флаг разрешения внутренней привязки ШИМ-выходов
#define ENABLE_PULLUP 0
//!что делать при аппаратной аварии с ножками
#define TZ_STATE TZ_HIZ
/*! \class TPWM_Module
\brief Модуль реализации ШИМ
Класс \a TPWM_Module, основанный на структуре SPWM_Module, реализует
векторную и скалярную широтно-импульсную модуляцию для управления
шестиключевым инвертором. Имеет настройки мертвого времени,
частоты, коррекцию в зависимости от напряжения ЗПТ,
компенсацию мертвого времени.
Задание напряжения происходит по двум перпендикулярным осям альфа и бетта.
При этом ось альфа сонаправлена с осью А трехфазной системы координат. Для задания нового напряжения нужно
поместить задание в UalphaRef, UbetaRef и вызвать update. В зависимости от того,
какой тип ШИМ выбран в настройках (настраивается пользователем в переменной PWM_type),
функция PWM_Module_Update вызовет нужную функцию, реализующую требуемый тип ШИМ.
В результате этого на трех фазах инвертора в среднем за период ШИМ будет реализован
такой вектор напряжения, который задан в UalphaRef, UbetaRef. Чтобы создать переменное
синусоидальное напряжение, требуется вращать вектор задания внешней по отношению к модулю ШИМ программой.
*/
//! см. TPWM_Module
struct SPWM_Module {
int16 Enabled; //!< Флаг для чтения - включен ШИМ или выключен.
int32 UalphaRef; //!<Задание по оси асьфа (задается)
int32 UbetaRef; //!<Задание по оси бетта (задается)
int32 UPhARef; //!<Задание по фазе A (задается)
int32 UPhBRef; //!<Задание по фазе B (задается)
int32 UPhCRef; //!<Задание по фазе c (задается)
int32 k_pwm; //!< Период таймера ШИМ, для чтения.
int32 U_mag; //!< Текущая амплитуда напряжения, для чтения.
int32 U_lim; //!< Ограничение вектора напряжения, задается
int32 GammaA; //!< Скважность фазы А в размерности таймера ШИМ, для чтения.
int32 GammaB; //!< Скважность фазы B в размерности таймера ШИМ, для чтения.
int32 GammaC; //!< Скважность фазы C в размерности таймера ШИМ, для чтения.
int16 PWM_type; //!< Тип ШИМ. Принимает значения констант с префиквом PWM_TYPE_. Задается.
int16 PWM_typeOld; //!< Предыдущее значения типа ШИМ, служебная переменная.
int16 sector; //!< Текущий сектор в векторном типе ШИМ. Для чтения.
int32 UalphaNorm; //!< Нормированное задание, служебная переменная.
int32 UbetaNorm; //!< Нормированное задание, служебная переменная.
int32 UdCorTmp; //!<Служебная переменная для корректировки выходного напряжения в зависимости от напряжения ЗПТ
int32 UdCompK; //!< Коэффициент корректировки выходного напряжения инвертора в зависимости от изменения напряжения ЗПТ от номинального. Задается.
int32 UdCompEnable; //!< Разрешение корректировки выходного напряжения инвертора в зависимости от изменения напряжения ЗПТ от номинального. Задается.
int16 ULimitation; //!< флаг о том, что идет ограничение напряжения - выходное напряжение меньше заданного. Для чтения.
_iq Frequency; //!< Частота ШИМ в кГц. Формат 22.10! Задается.
_iq FreqPrev; //!< Предудущая частота ШИМ, служебная переменная.
int32 DeadBand; //!< величина "мёртвого времени", мкс, задается.
int32 MinGammaLimit; //!< минимальная скважность на ключе, задается.
int PDP_Fault; //!< Флаг о том, что моудлем ШИМ зафиксирована аппаратная авария от инвертора. Для чтения. По ней необходима реакция модуля защит!
int ChargingMode; //!< Режем заряда будстрепных конденсаторов. Должен выставляться в еденицу на время 2-10 мс внешней программой перед запуском ШИМ.
void (*init)(volatile struct SPWM_Module*); /* Pointer to the init function */
void (*update)(volatile struct SPWM_Module*); /* Pointer to the update function */
void (*slow_calc)(volatile struct SPWM_Module*);
void (*On)(volatile struct SPWM_Module*); //!< процедура включения (разрешения) ШИМ-выходов
void (*Off)(volatile struct SPWM_Module*); //!< процедура отключения (запрещения) ШИМ-выходов
};
typedef volatile struct SPWM_Module TPWM_Module;
//! Инициализатор по-умолчанию.
#define PWM_Module_DEFAULTS {\
0,0,0, \
0,0,0, \
0, \
0, \
_IQ(0.866),0, \
0,0,\
0,0,\
0,\
0,0,0,0,0,0,0x1400,0,0,0,0,0,\
PWM_Module_Init, \
PWM_Module_Update, \
PWM_Module_SlowCalc, \
PWM_Module_On, \
PWM_Module_Off, \
}
//! \memberof TPWM_Module
void PWM_Module_Init(TPWM_Module *);
//! \memberof TPWM_Module
void PWM_Module_Update(TPWM_Module *);
//! \memberof TPWM_Module
void PWM_Module_SlowCalc(TPWM_Module *);
//! \memberof TPWM_Module
void PWM_Module_On(TPWM_Module *);
//! \memberof TPWM_Module
void PWM_Module_Off(TPWM_Module *);
//векторные функции из библиотеки
void PWM_Module_No_SV_Update(TPWM_Module *);
#ifdef __cplusplus
}
#endif
#endif
/*@}*/

251
Vinclude/V_QEP.h Normal file
View File

@ -0,0 +1,251 @@
/*!
Copyright 2017 АО "НИИЭТ" и ООО "НПФ ВЕКТОР"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file V_QEP.h
\brief Модуль оценки скорости и положения при помощи eQEP (см. TposspeedEqep)
\author ООО "НПФ Вектор". Все права защищены. http://motorcontrol.ru
\version v 2.0 25/03/2016
\defgroup V_QEP Модуль оценки скорости и положения при помощи eQEP (см. TposspeedEqep)
\addtogroup V_QEP
@{*/
#include "V_IQmath.h"
#include "filter.h"
#ifndef V_POSSPEED_EQEP_H
#define V_POSSPEED_EQEP_H
#ifdef __cplusplus
extern "C" {
#endif
struct SPOSSPEEDCTL_BITS { // bits
Uint16 InitType:
2; // 0:1 INPUT: режим инициализации положения при пуске:
// 0 - всё выставляется вручную
// 1 - выставляем вектор тока, далее пуск в векторном режиме(исходное положение - 0 электрических градусов);
// 2 - пуск в векторном режиме(исходное положение - последнее сохранённое)
Uint16 index_en:
1; // 2 INPUT: наличие репера
// 0 - репер отсутствует
// 1 - репер подключён;
Uint16 dir:
1; // 3 INPUT: направление движения(в случае неправильного направления);
// 0 - (по умолчанию)прямое включение;
// 1 - инверсия;
Uint16 CmdInit:
1; // 4 INPUT: для режима инициализации
Uint16 Min_clk:
4; // 5:8 INPUT: минимальное число меток для захвата на низкой скорости - НЕ МЕНяТЬ!!!!!
// Min_clk=2 - 4 метки
// 3 - 8 меток - по умолчанию
// 4 - 16 меток
// 5 - 32 метки
// 6 - 64 метки
// 7 - 128 меток
// 8 - 256 меток
// 9 - 512 меток
// 10 - 1024 метки
Uint16 rsvd:
7; // 9:15 reserved;
};
union SPOSSPEED_CTL {
Uint16 all;
struct SPOSSPEEDCTL_BITS bit;
};
struct SPOSSPEEDFLG1_BITS { // bits
Uint16 UTO_tmp:
1; // 0 TEMPORARY FLAG: флаг time-out;
Uint16 PCO_tmp:
1; // 1 TEMPORARY FLAG: флаг положительного переполнения счётчика;
Uint16 PCU_tmp:
1; // 2 TEMPORARY FLAG: флаг отрицательного переполнения счётчика;
Uint16 UPPS_tmp:
4; // 3:6 TEMPORARY: значение текущего кванта перемещения для захвата;
Uint16 CCPS_tmp:
3; // 7:9 TEMPORARY: значение текущего коэффициента деления;
Uint16 first_launch:
2; // 10:11 FLAG: инициализация первого запуска;
Uint16 accuracy:
2; // 12:13 FLAG: флаг переключения алгоритмов;
Uint16 first_theta:
1; // 14 FLAG: флаг первого расчёта углового преращения;
Uint16 transit:
1; // 15 FLAG: флаг перехода на алгоритм высоких скоростей;
};
union SPOSSPEED_FLG1 {
Uint16 all;
struct SPOSSPEEDFLG1_BITS bit;
};
struct SPOSSPEEDFLG2_BITS { // bits
Uint16 pos_ident:
1; // 0 FLAG: флаг точной идентификации абсолютного положения ротора;
Uint16 UTO_tmp2:
1; // 1 TEMPORARY FLAG: флаг time-out;
Uint16 PCO_tmp2:
1; // 2 TEMPORARY FLAG: флаг положительного переполнения счётчика;
Uint16 PCU_tmp2:
1; // 3
Uint16 lost_UTO:
1; // 4
Uint16 Dir_prev:
1; // 5
Uint16 Cdef:
1; // 6
Uint16 Delay_flux:
1; // 7
Uint16 first_index:
1; // 8
Uint16 rsvd:
8; // 9:15 reserved;
};
union SPOSSPEED_FLG2 {
Uint16 all;
struct SPOSSPEEDFLG2_BITS bit;
};
/*! \class TposspeedEqep
\brief Модуль обработки квадратурного декодера (ДПР типа "энкодер")
Класс \a TposspeedEqep, основанный на структуре SposspeedEqep,
является модулем для определения углового положения и скорости ротора
двигателя по данным от квадратурного энкодера. Для работы с датчиком
используется периферийный модуль процессора EQEP. Положение вала theta_elec определяется
по аппаратному счетчику QPOSCNT, который увеличивает и уменьшает
свое значение автоматически при вращении вала. После включения процессора
абсолютное угловое положение вала не может быть оперелено, пока не произойдет
событие индексации (сработает реперная метка). Модуль возводит флаг Posspeed_FLG2.bit.pos_ident,
как только это происходит. До этого момента значение углового положения не валидное и не должно использоваться
системой управления. Для калибровки датчика положения (смещения нулевого положения)
используется переменная AngleOffset.
Для вычисления скорости speed_elec используется аппаратный счетчик QCPRD,
который измеряет время между заданным количеством меток датчика. Для обеспечения приемлемой
точности на высоких и низких скоростях "заданное" количество меток переключается на ходу при помощи
делителя UPPS. Так как скорость на малых скоростях вращения пульсирует,
имеется инерционный фильтр скорости первого порядка, значение которого,
speed.output, может быть выведено пользователю.
*/
//! см. TposspeedEqep
struct SposspeedEqep {
Uint32 resol; //!<INPUT: разрешение датчика в метках/оборот;
float resol_inv; //!<обратная величина к разрешению датчика resol
Uint16 pole_pairs; //!<INPUT: число пар полюсов;
Uint16 SpeedCalcType; //!< Тип расчета скорости вращения: 0 - аппаратно, 1 - программно по углу.
float speed_nom; //!<INPUT: номинальная скорость в об/мин;
_iq speed_elec; //!<OUTPUT: электрическая скорость в Q24(относительные единицы)
_iq theta_elec; //!<OUTPUT: электрический угол в Q24(относительные единицы)
float k_low; //!<PARAMETER;
Uint32 Poscnt_res; //!<Механическ.угол в метках;
Uint16 Poscnt_res16; //!<Механическ.угол в метках 16ти разрядный для осца;
Uint32 Poscnt_resPrev; //!<Механическ.угол в метках предыдущее значение;
int16 MoveK; //!<TEMPORARY;
_iq theta_mech; //!<Механический угол;
_iq prevThetaMech; //!<Механический угол предыдущее значение;
_iq theta_el_tmp; //!<TEMPORARY: электрический угол;
Uint16 speed_calc_skip; //!<пропуск расчета скорости, флаг
_iq speedK; //!<TEMPORARY: делитель частоты, тактирующей таймер захвата;
union { /*!< Status interrupt */
Uint16 Qcprdlat16_tmp; //!<TEMPORARY: копия защёлки времени;
Uint32 Qcprdlat_tmp; //!<TEMPORARY: копия защёлки времени;
}; //!<Для наблюдения в юниконе
union { /*!< Status interrupt */
uint16_t QEPSTS; /*!< QEPSTS : type used for word access */
_QEP_QEPSTS_bits QEPSTS_bit; /*!< QEPSTS_bit: structure used for bit access */
}; //!<Для наблюдения в юниконе
Uint16 DirPrev;
_iq speed_tmpIQ; //!<TEMPORARY;
TFilter speed_filter; //!<Фильтр скорости
Uint16 skip_counter;//!< Счетчик пропуска расчета скорости после смены UPPS
union SPOSSPEED_CTL Posspeed_CTL;
union SPOSSPEED_FLG1 Posspeed_FLG1;
union SPOSSPEED_FLG2 Posspeed_FLG2;
Uint16 GPIOsValue;//!< Текущее значение ножек GPIO модуля QEP
Uint16 Index_eventFlag;
Uint16 UPPS_forWatch;//!< Текущее значение UPPS
_iq AngleOffset;//!< Смещение электрического угла в градусах
int16 RevolutionCounter; // Количество механических оборотов;
int16 Poscnt_resContinouosInt8;//!<Механическ.угол в метках c учетом кол-ва оборотов (переменная 8 разрядов отсекается)
int16 Poscnt_resContinouosInt;//!<Механическ.угол в метках c учетом кол-ва оборотов (переменная 16 разрядов)
long Poscnt_resContinouosLong;//!<Механическ.угол в метках c учетом кол-ва оборотов (переменная 32 разрядов)
_iq theta_mechContinouos; //!<Механический угол в градусах абсолютный;
_iq theta_elecContinouos; //!<Электрический угол в градусах абсолютный;
long speed_elec_temp; //Скорость нефильтрованная
long theta_start; //внутренняя перременная: Начальный угол
long theta_finish;//внутренняя перременная: Конечный угол
long d_fi;//внутренняя перременная: разница в угле
long KThetaToSpeed; //внутренняя перременная: коэф. пересчета произв. угла в скорость
void (*init)(volatile struct SposspeedEqep*);
void (*calc)(volatile struct SposspeedEqep*);
void (*slow_calc)(volatile struct SposspeedEqep*);
void (*index)(volatile struct SposspeedEqep*);
};
typedef volatile struct SposspeedEqep TposspeedEqep;
//! Инициализатор по-умолчанию.
#define POSSPEED_DEFAULTS {0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0, 0,{0},{0},0,0,FILTER_DEFAULTS,0,\
0,0x0790,0,0,0,0,0,0,0,0,0,0,0,\
0,0,0,0,0,\
TposspeedEqep_init,\
TposspeedEqep_Calc,\
TposspeedEqep_SlowCalc,\
TposspeedEqep_IndexEvent,\
}
//! \memberof TposspeedEqep
void TposspeedEqep_init(TposspeedEqep*);
//! \memberof TposspeedEqep
void TposspeedEqep_Calc(TposspeedEqep*);
//! \memberof TposspeedEqep
void TposspeedEqep_SlowCalc(TposspeedEqep*);
//! \memberof TposspeedEqep
void TposspeedEqep_IndexEvent(TposspeedEqep*);
#ifdef __cplusplus
}
#endif
#endif
/*@}*/

83
Vinclude/V_RTC_Clock.h Normal file
View File

@ -0,0 +1,83 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file V_RTC_Clock.h
\brief Ìîäóëü ðàáîòû ñ ÷àñàìè ðåàëüíîãî âðåìåíè
\author ÎÎÎ "ÍÏÔ Âåêòîð". Âñå ïðàâà çàùèùåíû. http://motorcontrol.ru
\version v 2.0 25/03/2016
\defgroup V_rmp_ctrl Çàäàò÷èê èíòåíñèâíîñòè (ñì. TRMPCtrl)
@{
*/
#ifndef V_RTC_CLOCK_H_
#define V_RTC_CLOCK_H_
#define RTC_SLAVE_ADDRESS 0x68 // Äëÿ RTC DS1340 àäðåñ 1101 000b = 0x68 (õîòÿ â ðóêîâîäñòâå îíè åãî êàê áû äîïîëíÿþò íóë¸ì
// è ïîëó÷àþò 1101 0000b = 0xD0)
#define RTC_WRITE_ERROR 1
#define RTC_READ_ERROR 2
#define RTC_TIMEOUT_ERROR 3
#define RTC_TIMEOUT 1000 // Êîëè÷åñòâî îæèäàíèÿ øèíû
#define RTC_SECOND_WAITING_TIMEOUT 10000 // Âðåìÿ, â òå÷åíèå êîòîðîãî äîëæíà ñìåíèòüñÿ ñåêóíäà (çàäàåòñÿ â ìñ). Åñëè íå ìåíÿåòñÿ, çíà÷èò ÷àñû íå ðàáîòàþò.
struct SRTCClock{
Uint16 ms; // Íà âñÿêèé
Uint16 msInDay; // Ìèëèïèñþëè ñ íà÷àëà ñóòîê
Uint16 error; // Êîä îøèáêè
Uint16 tryCounter; // Ñ÷åò÷èê îæèäàíèé øèíû
Uint16 second;
Uint16 minute;
Uint16 hour;
Uint16 DOW; // DayOfWeek - äåíü íåäåëè (ïóñòü áóäåò, ÷òî, æàëêî ÷òî ëè?)
Uint16 day; // Date - ýòî ÷èñëî ìåñÿöà
Uint16 month;
Uint16 year;
Uint32 packed_time; // Âðåìÿ, óïàêîâàííîå â ñëîâî
Uint32 timeToSet; // Âðåìÿ, êîòîðîå íóæíî óñòàíîâèòü íà ÷àñàõ, óïàêîâàííîå â ñëîâî
Uint16 setTimeFlag;
Uint16 readTimeFlag;
Uint16 secondPrev;
Uint16 stoppedCounter;
Uint16 ClockOk;
void (*init)(volatile struct SRTCClock*); // Èíèöèàëèçàöèÿ
void (*read)(volatile struct SRTCClock*); // Ïðî÷èòàòü âðåìÿ èç ÷àñèêîâ
void (*set)(volatile struct SRTCClock*); // Ïèñüíóòü âðåìÿ â ÷àñèêè
void (*msCalc)(volatile struct SRTCClock*);
void (*slowCalc)(volatile struct SRTCClock*);
};
typedef volatile struct SRTCClock TRTCClock;
#define RTC_CLOCK_DEFAULTS {0,0,0,0, 0,0,0, 0,0,0,0, 0,0, 0,0, 0,0,0,\
RTC_Clock_Init,\
RTC_Clock_Read_Time,\
RTC_Clock_Set_Time,\
RTC_Clock_Ms_Calc,\
RTC_Clock_Slow_Calc}
void RTC_Clock_Init (TRTCClock *);
void RTC_Clock_Read_Time (TRTCClock *);
void RTC_Clock_Set_Time (TRTCClock *);
void RTC_Clock_Ms_Calc (TRTCClock *);
void RTC_Clock_Slow_Calc (TRTCClock *);
#endif /* V_I2CCLOCK_H_ */

119
Vinclude/V_SSI_Encoder.h Normal file
View File

@ -0,0 +1,119 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file V_SSI_Encoder.h
\brief Ìîäóëü îöåíêè ñêîðîñòè è ïîëîæåíèÿ ïðè ïîìîùè öèôðîâîãî ýíêîäåðà, ðàáîòàþùåãî ïî èíòåðôåéñó SSI (ñì. TSSI_Encoder)
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 1.0 25/04/2016
\defgroup V_SSI_Encoder Ìîäóëü îöåíêè ñêîðîñòè è ïîëîæåíèÿ ïðè ïîìîùè SSI Encoder (ñì. TSSI_Encoder)
\addtogroup V_SSI_Encoder
@{*/
#include "V_IQmath.h"
#include "filter.h"
#ifndef V_SSI_ENCODER_H
#define V_SSI_ENCODER_H
#ifdef __cplusplus
extern "C" {
#endif
/*! \class TSSI_Encoder
\brief Ìîäóëü îáðàáîòêè ýíêîäåðà, ðàáîòàþùåãî ïî SSI (óïðîùåííûé SPI). À èìåííî äëÿ äàò÷èêà HENGSTLER absolute encoder AC 58.
Êëàññ \a TSSI_Encoder, îñíîâàííûé íà ñòðóêòóðå SSI_Encoder,
ÿâëÿåòñÿ ìîäóëåì äëÿ îïðåäåëåíèÿ óãëîâîãî ïîëîæåíèÿ è ñêîðîñòè ðîòîðà
äâèãàòåëÿ ïî äàííûì îò ýíêîäåðà, ðàáîòàþùåãî ïî SSI.
Äàò÷èê ïðåäïîëàãàåòñÿ ïîäêëþ÷àòü íà ðàçúåì J8 ïëàòû èç êîìïëåêòà DRV8301-HC-EVM.
Âîò òîëüêî ìèêðîñõåìó ãàëüâàíè÷åñêîé ðàçâÿçêè (U5) Texas òóäà ïîñòàâèëè ïî÷åìó-òî òàêîé ñòîðîíîé, ÷òî ìèêðîêîíòðîëåð
ðàáîòàåò êàê slave ñòðîéñòâî. ×òîáû ñäåëàòü åãî ìàñòåðîì, íóæíî ïîñòàâèòü äðóãóþ àíàëîãè÷íóþ ìèêðîñõåìó, èëè...
ïåðåâåðíóòü U5 ââåðõ íîãàìè, ïîñòàâèâ ìàðêèðîâêîé âíèç, ëàïêàìè ê âåðõó :)
*/
//! ñì. TSSI_Encoder
struct S_SSI_Encoder {
Uint32 resol; //!<INPUT: ðàçðåøåíèå äàò÷èêà â ìåòêàõ/îáîðîò;
float resol_inv; //!<îáðàòíàÿ âåëè÷èíà ê ðàçðåøåíèþ äàò÷èêà resol
Uint16 pole_pairs; //!<INPUT: ÷èñëî ïàð ïîëþñîâ;
Uint16 rotation_dir; //!<INPUT: íàïðàâëåíèå âðàùåíèÿ
float speed_nom; //!<INPUT: íîìèíàëüíàÿ ñêîðîñòü â îá/ìèí;
_iq speed_elec; //!<OUTPUT: ýëåêòðè÷åñêàÿ ñêîðîñòü â Q24(îòíîñèòåëüíûå åäèíèöû)
_iq theta_elec; //!<OUTPUT: ýëåêòðè÷åñêèé óãîë â Q24(îòíîñèòåëüíûå åäèíèöû)
Uint16 Poscnt_res; //!<Ìåõàíè÷åñê.óãîë â ìåòêàõ;
Uint16 Poscnt_resPrev; //!<Ìåõàíè÷åñê.óãîë â ìåòêàõ ïðåäûäóùåå çíà÷åíèå;
_iq theta_mech; //!<Ìåõàíè÷åñêèé óãîë;
_iq prevThetaMech; //!<Ìåõàíè÷åñêèé óãîë ïðåäûäóùåå çíà÷åíèå;
_iq theta_el_tmp; //!<TEMPORARY: ýëåêòðè÷åñêèé óãîë;
_iq theta_mech_filtered; //!<Ìåõàíè÷åñêèé óãîë ôèëüòðîâàííûé;
_iq theta_mech_filterK; //!<Êîýôôèöèåíò ôèëüòðà ìåõ. óãëà;
_iq AngleOffset;//!< Ñìåùåíèå ýëåêòðè÷åñêîãî óãëà â ãðàäóñàõ
int16 RevolutionCounter; // Êîëè÷åñòâî ìåõàíè÷åñêèõ îáîðîòîâ;
int16 Poscnt_resContinouosInt8;//!<Ìåõàíè÷åñê.óãîë â ìåòêàõ c ó÷åòîì êîë-âà îáîðîòîâ (ïåðåìåííàÿ 8 ðàçðÿäîâ îòñåêàåòñÿ)
int16 Poscnt_resContinouosInt;//!<Ìåõàíè÷åñê.óãîë â ìåòêàõ c ó÷åòîì êîë-âà îáîðîòîâ (ïåðåìåííàÿ 16 ðàçðÿäîâ)
long Poscnt_resContinouosLong;//!<Ìåõàíè÷åñê.óãîë â ìåòêàõ c ó÷åòîì êîë-âà îáîðîòîâ (ïåðåìåííàÿ 32 ðàçðÿäîâ)
_iq theta_mechContinouos; //!<Ìåõàíè÷åñêèé óãîë â ãðàäóñàõ àáñîëþòíûé;
_iq theta_elecContinouos; //!<Ýëåêòðè÷åñêèé óãîë â ãðàäóñàõ àáñîëþòíûé;
void (*init)(volatile struct S_SSI_Encoder*);
void (*calc)(volatile struct S_SSI_Encoder*);
void (*read)(volatile struct S_SSI_Encoder*);
};
typedef volatile struct S_SSI_Encoder TSSI_Encoder;
//! Èíèöèàëèçàòîð ïî-óìîë÷àíèþ.
#define SSI_ENCODER_DEFAULTS {0,0,0,0, 0,0,0,0, 0,0,0,0,0,0, 0,0, 0,0,0,0,0,\
SSI_Encoder_init,\
SSI_Encoder_Calc,\
SSI_Encoder_Read,\
}
//! \memberof TSSI_Encoder
void SSI_Encoder_init(TSSI_Encoder*);
//! \memberof TSSI_Encoder
void SSI_Encoder_Calc(TSSI_Encoder*);
//! \memberof TSSI_Encoder
void SSI_Encoder_Read(TSSI_Encoder*);
#ifdef __cplusplus
}
#endif
#endif
/*@}*/

140
Vinclude/V_UserMemory.h Normal file
View File

@ -0,0 +1,140 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file V_UserMemory.h
\brief Ðàáîòà ñ ýíåðãîíåçàâèñèìîé ïàìÿòüþ 1921BK01 (ñì. TUserMemory)
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 2.0 25/03/2016
\defgroup V_UserMemory Ðàáîòà ñ ýíåðãîíåçàâèñèìîé ïàìÿòüþ (ñì. TUserMemory)
@{
*/
#ifndef V_USERMEMORY_H
#define V_USERMEMORY_H
#include "DSP.h"
#ifdef __cplusplus
extern "C" {
#endif
/*! \class TUserMemory
\brief Ðàáîòà ñ ïîëüçîâàòåëüñêîé ýíåðãîíåçàâèñèìîé ïàìÿòüþ ÌÑ01
Êëàññ \a TUserMemory, îñíîâàííûé íà ñòðóêòóðå TUserMemory, ïðåäñòàâëÿåò ñîáîé äðàéâåð äëÿ ðàáîòû ñ
flash ïàìÿòüþ.\n
ïðèìåð èñïîëüçîâàíèÿ:\n
äëÿ èíèöèàëèçàöèè\n
spimem.init.(&spimem);\n
äëÿ çàïèñè\n
UserMem.spiaddr=0;\n
UserMem.startaddr=buff;\n
UserMem.data_length=1000;\n
UserMem.write(&spimem);\n
*/
//! ñì. TUserMemory
#define USERMEMORY_USERFLASH_KEY 0xA4420000
#define USERMEMORY_MAX_WAITCLOCKS 2000
#define USERMEMORY_WRITE_HARDFAULT 0x1
#define USERMEMORY_WRITE_TIMEOUT 0x2
#define USERMEMORY_READ_HARDFAULT 0x3
#define USERMEMORY_READ_TIMEOUT 0x4
#define USERMEMORY_OP_OK 0x0
#define USERMEMORY_PAGE_SIZE 256
#define USERMEMORY_CMD_WRITE (1<<0)
#define USERMEMORY_CMD_PAGE_ERASE (1<<1)
#define USERMEMORY_CMD_FULL_ERASE (1<2)
#define USERMEMORY_CMD_READ (1<<3)
struct SUserMemory {Uint16 MemStartAddr;//!Àäðåñ íà flash
Uint8 *MCUStartAddr8; //!àäðåñ íà ìàññèâ ñ äàííûìè êàê áàéòîâûé óêàçàòåëü
Uint16 *MCUStartAddr; //!àäðåñ íà ìàññèâ ñ äàííûìè
Uint16 data_length;//!äëèíà äàííûõ
int16 receivedCode;//!Ñòàòóñ îïåðàöèè
Uint16 waitClocks;//!Ñ÷åò÷èê äëÿ îæèäàíèÿ òàéìàóòà îïåðàöèè
Uint16 PageInCache;//!Íîìåð òåêóùåé çàêåøèðîâàííîé ñòðàíèöû
Uint16 autoFlushCounter;//!Ñ÷åò÷èê äëÿ ñîõðàíåíèÿ êåøà íà ôëåø ïî òàéìàóòó
Uint8 PageRAM_and_FLASH_IdenticalFlag;//!Ôëàã î òîì, ÷òî äàííûå â êåøå è íà ôëåøå èäåíòè÷íû
Uint8 NeedFlushRequest;//ôëàã çàïðîñà íà çàïèñü äàííûõ èç êåøà íà ôëåø
Uint8 cacheArr[USERMEMORY_PAGE_SIZE];//êåø äàííûõ - îäíà ñòðàíèöà ïàìÿòè
void (*init)(struct SUserMemory*);
void (*write)(struct SUserMemory*);
void (*read)(struct SUserMemory*);
void (*full_erase)(struct SUserMemory*);
void (*flush)(struct SUserMemory*);
void (*ms_calc)(struct SUserMemory*);
void (*slow_calc)(struct SUserMemory*);
};
typedef struct SUserMemory TUserMemory;
//!Èíèöèàëèçàòîð ïî óìîë÷àíèþ
#define USERMEMORY_DEFAULTS {0,0,0,0,0,0,0,0,0,0, \
{0},\
USERMEMORY_Init, \
USERMEMORY_Write,\
USERMEMORY_Read,\
USERMEMORY_Full_Erase,\
USERMEMORY_Flush,\
USERMEMORY_ms_calc,\
USERMEMORY_slow_calc,\
}
//! \memberof TUserMemory
void USERMEMORY_Init(TUserMemory*);
//! \memberof TUserMemory
void USERMEMORY_Write(TUserMemory*);
//! \memberof TUserMemory
void USERMEMORY_Read(TUserMemory*);
//! \memberof TUserMemory
void USERMEMORY_Full_Erase(TUserMemory*);
//! \memberof TUserMemory
void USERMEMORY_ReadToCache(TUserMemory *p, int16 pageNum);
//! \memberof TUserMemory
void USERMEMORY_WriteFromCache(TUserMemory *p, int16 pageNum);
//! \memberof TUserMemory
void USERMEMORY_Flush(TUserMemory *p);
//! \memberof TUserMemory
void USERMEMORY_ms_calc(TUserMemory *p);
//! \memberof TUserMemory
void USERMEMORY_slow_calc(TUserMemory *p);
//! \memberof TUserMemory
void USERMEMORY_UpdateCurrentPage(TUserMemory *p, Uint16 spiaddr);
#ifdef __cplusplus
}
#endif
#endif
/*@}*/

145
Vinclude/V_adc.h Normal file
View File

@ -0,0 +1,145 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file V_adc.h
\brief Ìîäóëü îáðàáîòêè ÀÖÏ (ñì. TAdcDrv)
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 2.0 25/03/2016
\defgroup V_adc Ìîäóëü îáðàáîòêè ÀÖÏ (ñì. TAdcDrv)
@{
*/
#ifndef V_ADC_H
#define V_ADC_H
#ifdef __cplusplus
extern "C"
{
#endif
/*! \class TAdcDrv
\brief Ìîäóëü îáðàáîòêè ÀÖÏ
Êëàññ \a TAdcDrv, îñíîâàííûé íà ñòðóêòóðå SAdcDrv, ñîäåðæèò â ñåáå
ìåòîäû äëÿ îáðàáîòêè ðåçóëüòàòîâ ÀÖÏ. À èìåííî: ñ÷èòûâàíèå, íîðìèðîâêó è
ïðèâåäåíèå ê îòíîñèòåëüíûì åäèíèöàì, ôèëüòðàöèþ. Ó êàæäîãî èçìåðÿåìîãî ñèãíàëà
åñòü êàê ìèíèìóì äâà ïàðàìåòðà äëÿ íàñòðîéêè: êîýôôèöèåíò óñèëåíèÿ è ñìåùåíèå.
Íàñòðîéêó äàò÷èêîâ æåëàòåëüíî ïðîèçâîäèòü òàê: ïîäàòü íóëåâîé ñèãíàë è íàñòðîèòü
ñìåùåíèå, ÷òîáû èçìåðÿåìîå çíà÷åíèå ïîêàçûâàëî íîëü. Ïîäàòü óðîâåíü ñèãíàëà, áëèçêèé
ê íîìèíàëüíîìó è íàñòðîèòü êîýôôèöèåíò óñèëåíèÿ, ÷òîáû èçìåðåííîå çíà÷åíèå ñîîòâåòñòâîâàëî
äåéñòâèòåëüíîñòè.*/
//! ñì. TAdcDrv
struct SAdcDrv
{
int16 Imeas_a_gain; //!< Êîýôôèöèåíò óñèëåíèÿ.
int16 Imeas_a_offset; //!< Ñìåùåíèå íóëÿ.
int32 Imeas_a; //!< Èçìåðåííîå çíà÷åíèå óñðåäíåííîå.
int32 IaGainNom; //!< Âñïîìîãàòåëüíûé êîýôô. óñèëåíèÿ.
int32 IA_temp; //!<Âðåìåííàÿ ïåðåìåííàÿ
int16 IASampleLength; //äëèíà âûáîðêè (êîë-âî òî÷åê íà ïåðèîäå ØÈÌ)
int16 IAPointer; //íîìåð ïîñëåäíåé âûáîðêè
int16 IABuf[4]; //ìàññèâ òî÷åê äëÿ óñðåäíåíèÿ
int16 Imeas_b_gain;
int16 Imeas_b_offset;
int32 Imeas_b;
int32 IbGainNom;
int32 IB_temp;
int16 IBSampleLength; //äëèíà âûáîðêè (êîë-âî òî÷åê íà ïåðèîäå ØÈÌ)
int16 IBPointer; //íîìåð ïîñëåäíåé âûáîðêè
int16 IBBuf[4]; //ìàññèâ òî÷åê äëÿ óñðåäíåíèÿ
int16 Imeas_c_gain;
int16 Imeas_c_offset;
int32 Imeas_c;
int32 IcGainNom;
int16 IC_temp;
int16 ICSampleLength; //äëèíà âûáîðêè (êîë-âî òî÷åê íà ïåðèîäå ØÈÌ)
int16 ICPointer; //íîìåð ïîñëåäíåé âûáîðêè
int16 ICBuf[4]; //ìàññèâ òî÷åê äëÿ óñðåäíåíèÿ
int16 Udc_meas_gain;
int16 Udc_meas_offset;
int32 Udc_meas;
int32 UdcGainNom;
int16 Udc_temp;
int16 UdcSampleLength; //äëèíà âûáîðêè (êîë-âî òî÷åê íà ïåðèîäå ØÈÌ)
int16 UdcPointer; //íîìåð ïîñëåäíåé âûáîðêè
int16 UdcBuf[4]; //ìàññèâ òî÷åê äëÿ óñðåäíåíèÿ
int16 T_meas_gain; //!< Êîýôôèöèåíò óñèëåíèÿ.
int32 T_meas; //!< Èçìåðåííîå çíà÷åíèå óñðåäíåííîå.
int32 TGainNom; //!< Âñïîìîãàòåëüíûé êîýôô. óñèëåíèÿ.
int16 T_temp; //!<Âðåìåííàÿ ïåðåìåííàÿ
void (*init)(struct SAdcDrv *);
void (*fast_calc)(struct SAdcDrv*);
void (*ms_calc)(struct SAdcDrv*);
void (*slow_calc)(struct SAdcDrv*);
};
typedef struct SAdcDrv TAdcDrv;
//!Èíèöèàëèçàòîð ïî óìîë÷àíèþ.
#define ADC_DRV_DEFAULTS {\
54,0,0,0,0, \
4,0,{0}, \
54,0,0,0,0, \
4,0,{0}, \
54,0,0,0,0, \
4,0,{0}, \
800,0,0,0,0, \
4,0,{0}, \
100,0,0,0, \
AdcDrv_init,\
AdcDrv_fast_calc,\
AdcDrv_ms_calc,\
AdcDrv_slow_calc,\
}
//! \memberof TAdcDrv
void AdcDrv_init(TAdcDrv*);
//! \memberof TAdcDrv
void AdcDrv_slow_calc(TAdcDrv*);
//! \memberof TAdcDrv
void AdcDrv_fast_calc(TAdcDrv*);
//! \memberof TAdcDrv
void AdcDrv_ms_calc(TAdcDrv*);
extern Uint16 rawResNAvg[16] __attribute__((deprecated));
extern Uint16 rawResAvg[4] __attribute__((deprecated));
#ifdef __cplusplus
}
#endif
#endif
/*@}*/

View File

@ -0,0 +1,77 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file V_bits_to_enum_numbers.h
\brief Ìîäóëü "ëèñòàíèÿ" áèòîâûõ ïåðåìåííûõ (ñì. TBitsToEnumNums)
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 2.0 25/03/2016
\defgroup V_bits_to_enum_numbers Ìîäóëü "ëèñòàíèÿ" áèòîâûõ ïåðåìåííûõ (ñì. TBitsToEnumNums)
@{
*/
#ifndef V_BITS_TO_ENUM_NUMS_H
#define V_BITS_TO_ENUM_NUMS_H
#ifdef __cplusplus
extern "C"
{
#endif
//!êîëè÷åñòâî çàðàçåðâèðîâàííûõ ìåñò äëÿ áèòîâûõ ïåðåìåííûõ
#define NUM_OF_W_PTRS 2
/*! \class TBitsToEnumNums
\brief Ìîäóëü "ëèñòàíèÿ" áèòîâûõ ïåðåìåííûõ
Êëàññ \a TBitsToEnumNums, îñíîâàííûé íà ñòðóêòóðå SBitsToEnumNums, ïðåîáðàçóåò
áèòîâûå ïåðåìåííûå â ÷èñëà (ñîîòâåòñòâóþùèå íîìåðàì áèòîâ âõîäíîé ïåðåìåíîé),
ìåíÿþùèåñÿ ñ çàäàííûì èíòåðâàëîì. Çíà÷åíèå â ñàìîì ìëàäøåì áèòå ñîîòâåòñòâóåò 1.
Âûäàåò 0 åñëè íèêàêèå áèòû â ïðîâåðÿåìûõ ñëîâàõ íå óñòàíîâëåíû. Ïðåäïîëàãàåòñÿ äëÿ
"ïðîëèñòûâàíèÿ" áèòîâ ñëîâ àâàðèé è ïðåäóïðåæäåíèé â öåëÿõ âûâîäà íà ÏÓ. */
//! ñì. TBitsToEnumNums
struct SBitsToEnumNums
{
Uint16 out_refresh_devisor;//!< äåëèòåëü, çàäàþùèé òåìï ëèñòàíèÿ
Uint16 counter;//!<ñ÷åò÷èê òàéìàóòà ëèñòàíèÿ
Uint16 num_of_words;//!<êîë-âî áèòîâûõ ïåðåìåííûõ
Uint16 last_word;//!<òåêóùåå ñëîâî
Uint16 last_bit;//!<òåêóùèé áèò
Uint16 *w_ptrs[NUM_OF_W_PTRS]; //!<óêàçàòåëü íà áèòîâûå ïåðåìåííûå (íåñêîëüêî)
Uint16 output;//!<âûõîä ìîäóëÿ (ëèñòàþùååñÿ ÷èñëî)
void (*calc)(volatile struct SBitsToEnumNums*);
};
typedef volatile struct SBitsToEnumNums TBitsToEnumNums;
//!èíèöèàëèçàòîð ïî óìîë÷àíèþ
#define BITS_TO_ENUM_NUMS_DEFAULTS {1000,0,4,0,0,{0},0,\
BitsToEnumNums,\
}
//! \memberof TBitsToEnumNums
void BitsToEnumNums(TBitsToEnumNums*);
#ifdef __cplusplus
}
#endif
#endif
/*@}*/

128
Vinclude/V_common.h Normal file
View File

@ -0,0 +1,128 @@
/*!
Copyright 2017 АО "НИИЭТ" и ООО "НПФ ВЕКТОР"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file v_common.h
\brief Объявление структур данных различного назначения, которые еще слишком малы для того, чтобы
организовывать их в отдельный модуль
\author ООО "НПФ Вектор". Все права защищены. http://motorcontrol.ru
\version v 2.0 25/03/2016
\defgroup v_common Объявление структур данных различного назначения
@{*/
#ifndef V_COMMON_H
#define V_COMMON_H
#ifdef __cplusplus
extern "C"
{
#endif
//!Битовое поле для битового статуса системы управления
typedef struct
{
unsigned int ready:
1;
unsigned int running:
1;
unsigned int fault:
1;
unsigned int alarm:
1;
unsigned int testing:
1;
unsigned int overheat:
1;
} DRV_STATUS_BIT;
//!Структура для статуса системы управления (содержит DRV_STATUS_BIT)
typedef union
{
int all;
DRV_STATUS_BIT bit;
}TDrvStatus;
//!Битовое поле слова управления
typedef struct
{
unsigned int start:
1;
unsigned int stop:
1;
unsigned int trip_reset:
1;
unsigned int reserved:
5;
} CMD_BIT;
//!Структура слова управления (содержит DRV_STATUS_BIT)
typedef union
{
unsigned int all;
CMD_BIT bit;
}TCmd;
//! Структура, содержащия основные задания для привода
typedef volatile struct
{
long speed_ref;//!< Задание скорости
long Iq_ref;//!< Задание токоограничения для векторной системы управления
long i_flux_ref;//!< Задание тока для замкнутой по току системы управления (не векторной)
long theta_elec;//!< Задание углового положения вектора тока/напряжения
long ua_ref, uf_ref; // Задания тока якоря и тока ОВ для ДПТ
long DCMspeed_ref;//!< Задание скорости
} TRefs;
//! Структура для хранения параметров привода, двигателя, базовых величин системы управления
typedef struct
{
long Rs;//!< Сопротивление фазы статора
long Ls;//!< Индуктивность фазы статора
int p;//!< Количество пар полюсов
int I_nom;//!< Номинальный (базовый) фазный ток в формате 16.0
long _1_I_nom;//!< 1/I_nom
int U_nom;//!< Номинальное (базовое) фазное напряжение в формате 16.0
long _1_U_nom;//!< 1/U_nom
int Udc_nom;//!< Номинальное (базовое) напряжение ЗПТ в формате 16.0
long _1_Udc_nom;//!< 1/Udc_nom
int speed_nom;//!< Номинальная (базовая) скорость в формате 16.0
int freq_nom;//!< Номинальная (базовая) частота в формате 16.0
int power;//!< Номинальная (базовая) мощность в формате 16.0
int sens_type;//!< Тип датчика положения
} TDrvParams;
//! Структура для битовых "переключателей", таких как направление вращения, разрешение рекуперации и т.п.
typedef struct {
Uint16 recuperation_ena;//!< Разрешение рекуперации энергии при торможении
Uint16 rotation_dir;//!< Направление вращения
Uint16 Reboot;//!< Программная перезагрузка
Uint16 AutoOffset;//!< автосмещение АЦП
Uint16 HardwareType;//!< Тип железа, под который собран проект
Uint16 excitation_ena;//!< Разрешение возбудителя
} TSysSwitches;
#ifdef __cplusplus
}
#endif
#endif
/*@}*/

224
Vinclude/V_data_log.h Normal file
View File

@ -0,0 +1,224 @@
/*!
\file v_data_log.h
\brief 4-х канальный логгер длЯ осциллографированиЯ в реальном времени (см. TDataLog)
В версии 2.0 реализован 32-битный режим работы. Основные положения:
Тип данных даталоггера определяется символьной константой в заголовочном файле 'V_data_log.h'
(один из вариантов нужно раскомментировать):
//#define DLOG_DATA_SIZE 16
#define DLOG_DATA_SIZE 32
Для 16-битного режима даталоггер работает "классическим" методом. Старый Юникон работает как было.
Новый Юникон при этом не получает флаг 32-битного режима (см. ниже) и работает по "классическому" алгоритму
(правда, буфер принимаемых данных у него теперь 32-битный, но это тонкости). При буферной передаче каждый
канал передаётся, как и раньше, одним запросом.
32-битный режим:
В переменную 'dlog.control' добавлен флаг '32-битные данные', по которому новый Юникон узнаёт тип даталоггера.
При SDO-чтении осциллограмм данные, как и раньше, выдвигаются через 32-битную переменную 'dlog.next_value_var'
(там, кроме 16-битного значения, есть всякие поля). В неё добавлены два флага:
- флаг, что в поле "значение" - старшие 16 бит точки
- флаг, что переменная 16-разрядная
Юникон сначала запрашивает младшую часть значения, потом - старшую и т.д. по всем точкам.
Если переменная 16-разрядная, то старшая часть не запрашивается. При буферной передаче:
Т.к. один буферный запрос ограничен у нас 256-тью 16-битными словами, то Юникон сначала запрашивает
первые 256 слов (128 32-битных точек), затем - остальные 256 слов. Т.е. используется два буферных запроса.
\author Коллектив ООО НПФ Вектор
\version v 2.0 10/04/2017
\defgroup v_data_log Цифровой осциллограф (см. TDataLog)
@{
*/
#ifndef V_DATA_LOG_H
#define V_DATA_LOG_H
#include "CANOpen_drv.h"
#ifdef __cplusplus
extern "C"
{
#endif
// Размер значений, передаваемых через логгер (бит)
//#define DLOG_DATA_SIZE 16
#define DLOG_DATA_SIZE 32
#if DLOG_DATA_SIZE == 16
typedef int16 type_data;
#elif DLOG_DATA_SIZE == 32
typedef int32 type_data;
#endif
//! Размер массивов длЯ осциллографированиЯ.
//!Если нужно менЯть, то это делать надо не только тут - слишком много завЯзано на это число
//!Переделать сложно, так как на это число завЯзка косвеннаЯ: например, длЯ ускорениЯ работы
//!применЯютсЯ такие конструкции: p->Wcounter&=0xFF; Где FF - маска (символизирует 256 точек)
#define NUMBER_SAMPLES 256
/*! \class TDataLog
\brief 4-х канальный логгер длЯ осциллографированиЯ в реальном времени
Класс \a TDataLog, основанный на структуре SDataLog, позволЯет записывать выбранные 4 переменных в массивы
из 255 точек с заданной дискретизацией по времени. Кроме того, имеет
свЯзь с драйвером CANOpen длЯ автоматизации указаниЯ этих переменных: можно
"зарЯдить" в даталоггер любой существующий элемент словарЯ.*/
//! см. TDataLog
struct SDataLog
{
type_data buff[(NUMBER_SAMPLES*4)]; //4 массива для отснятых осциллограмм, слепленные в один большой
#if DLOG_DATA_SIZE == 16
type_data *dlog_iptr1; //!< указатели на переменные для записи (например. ток фазы A, скорость и т.д.)
type_data *dlog_iptr2; //!< Input: Second input pointer (Q15)
type_data *dlog_iptr3;
type_data *dlog_iptr4;
#endif
int dlog_cntr_max; //!< Parameter: Maximum number of samples
Uint16 Wcounter; //!< Счетчик по массиву длЯ записи
Uint16 Rcounter; //!< Счетчик по массиву длЯ чтениЯ
type_data* dl_buffer1_adr; //!< Указатели на массивы, где лежат отснятые осциллограммы
type_data* dl_buffer2_adr; //!< Parameter: Buffer starting address 2
type_data* dl_buffer3_adr;
type_data* dl_buffer4_adr;
type_data upload_buff[NUMBER_SAMPLES]; //массив для отправки осциллограммы в юникон. Сюда копируется осциллограмма из одного из четырех массивов buff со смещением, чтобы начало осциллограммы было в начале массива.
type_data* dl_upload_buffer_adr; //указатель на массив для отправки.
Uint32 trig_shift; //сдвиг первой точки после срабатывания триггера. Используется, чтобы задать, сколько точек предыстории сохранять.
Uint16 trig_shift_int; //то же, переведенное в точки
Uint16 first_point_written; //первая точка, относящаяся к записываемой осциллограмме с учетом длины предыстории и точки срабатывания триггера
Uint16 prehistory_length; //длина записанной предыстории (если даталоггер переинициализировался кнопкой "обновить", она обнуляется)
Uint16 valid_points_num; //счетчик валидных точек предыстории, записанных после переинициализации кнопкой "обновить" в юниконе
/*! Режимов работы четыре:\n
0 - стоп\n
1 - однократнаЯ запись\n
2 - запись по кругу без остановки\n
3 - однократнаЯ запись одной переменной во все 4 массива последовательно, длЯ получениЯ длинной осциллограммы.\n
Устанавливать переменную надо только вызовом функции set_mode! */
Uint16 mode_reset; //!< задаетсЯ режим работы
Uint16 mode_reset_prev; //!< предыдущий режим работы
int E; // флаг энтри
/*! "control" имеет 32 разрЯда. Первые 16 бит - флаги, последние 16 бит - установка разреживания.\n
9 8 7 6 5 4 3 2 1 0\n
| x | x | x | x | x | x | x | x | x | x |\n
| | | | | | первые 4 бита - какие из 4х переменых интересуют (какие адреса обновлЯть, какие данные записывать)\n
| | | | 2 бита - желаемый режим даталоггера: 0, 1, 2\n
| | | бит "данные готовы" - устанавливаетсЯ контроллером\n
| | бит "поддерживается блочная передача"\n
| бит "32-битные данные"\n
резерв */
long control; //!< управление даталоггером через внешние программы
unsigned int WriteDelimiter; //!<делитель данных при записи
unsigned int WriteDelimiterCounter; //!<Счетчик длЯ делителЯ
long ind_subind1; //!<записываетсЯ индекс и подындекс длЯ словарЯ
long ind_subind2;
long ind_subind3;
long ind_subind4;
unsigned long next_value_var; //!<через эту переменную выдвигаютсЯ записанные значениЯ при считывании:
//!<биты 0-15: значение точки
//!<биты 16-23: Rcounter (отдаваемая точка)
//!<биты 24-25: buff_num
//!<бит 26: флаг, что в поле "значение" - старшие 16 бит точки (используется при DLOG_DATA_SIZE = 32)
//!<бит 27: флаг, что переменная 16-разрядная (используется при DLOG_DATA_SIZE = 32)
Uint16 StartBits;
int buff_num; //!<номер массива, из которого идет выдвижение значений в next_value_var
int ResetAfterStart; //!<флаг обнулениЯ счетчика записи при запуске
Uint16 OneShotOperation; //!<флаг синхронизации осциллографа только по первому событию (переход в 1 возможен только из 2)
TCo_OdVars *pco_vars; //!<адрес структуры драйвера CANopen
#if DLOG_DATA_SIZE == 32
int highPartOfValue; //!<флаг выдачи старшей части
TObjectInfo object1Info; //!<информация о записываемом объекте №1
TObjectInfo object2Info; //!<информация о записываемом объекте №2
TObjectInfo object3Info; //!<информация о записываемом объекте №3
TObjectInfo object4Info; //!<информация о записываемом объекте №4
#endif
void (*update)(volatile struct SDataLog *); //!<Pointer to update function
void (*set_mode)(Uint16 mode_reset,volatile struct SDataLog *); //!<Pointer to set_mode function
void (*background_analizer)(volatile struct SDataLog *); //!<Pointer to background_analizer function
} ;
typedef volatile struct SDataLog TDataLog;
#if defined(CAN_1_ENABLE)
#define COX_VARS co1_vars
#elif defined(CAN_2_ENABLE)
#define COX_VARS co2_vars
#endif
//! Инициализатор по-умолчанию длЯ данного класса
#if DLOG_DATA_SIZE == 16
#define DATALOG_DEFAULTS { {0},\
(type_data *)0x00000300, \
(type_data *)0x00000300, \
(type_data *)0x00000300, \
(type_data *)0x00000300, \
NUMBER_SAMPLES, \
0,0,\
((type_data *)&dlog.buff), \
((type_data *)&dlog.buff+NUMBER_SAMPLES), \
((type_data *)&dlog.buff+NUMBER_SAMPLES*2), \
((type_data *)&dlog.buff+NUMBER_SAMPLES*3), \
{0}, ((type_data *)&dlog.upload_buff), 0, 0, 0, 0, 0,\
2, 2, 0,\
0,\
0,0,\
0,0,0,0,\
0,0,\
0,\
1,\
0,\
&COX_VARS,\
data_log_update,\
dlog_set_mode,\
dlog_background_analizer }
#endif
#if DLOG_DATA_SIZE == 32
#define DATALOG_DEFAULTS { {0},\
NUMBER_SAMPLES, \
0,0,\
((type_data *)&dlog.buff), \
((type_data *)&dlog.buff+NUMBER_SAMPLES), \
((type_data *)&dlog.buff+NUMBER_SAMPLES*2), \
((type_data *)&dlog.buff+NUMBER_SAMPLES*3), \
{0}, ((type_data *)&dlog.upload_buff), 0, 0, 0, 0, 0,\
2, 2, 0,\
0,\
0,0,\
0,0,0,0,\
0,0,\
0,\
1,\
0,\
&COX_VARS,\
0,\
{ 0 }, { 0 }, { 0 }, { 0 },\
data_log_update,\
dlog_set_mode,\
dlog_background_analizer }
#endif
//! \memberof TDataLog
void data_log_update(TDataLog *);
//! \memberof TDataLog
void dlog_set_mode(Uint16 mode_reset,TDataLog *);
//! \memberof TDataLog
void dlog_background_analizer(TDataLog *);
#ifdef __cplusplus
}
#endif
#endif
/*@}*/

131
Vinclude/V_event_log.h Normal file
View File

@ -0,0 +1,131 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file V_event_log.h
\brief Ñîõðàíåíèå ñîáûòèé è âðåìåíè âîçíèêíîâåíèß â ÝíÎÇÓ
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 1.0 2009_01_20
*/
#ifndef W_EVENT_LOG_H
#define W_EVENT_LOG_H
#ifdef __cplusplus
extern "C"
{
#endif
//#define LOG_BUF_SIZE 50 //ñîõðàíßåì ïîñëåäíèå 50 ñîáûòèé
#define LOG_FIFO_SIZE 10 //ðàçìåð ôèôî äëß áóôåðèðîâàíèß ñîîáùåíèé ïðåæäå ÷åì îíè áóäóò çàïèñàíû â SPI
//#define LOG_SPI_START_ADDR 3000 //íà÷àëüíûé àäðåñ â SPI
#define LOG_NUM_LENGTH 2 //äëèíà íîìåðà ñîáûòèß (16áèò) - 2áàéòà
#define LOG_TIME_LENGTH 4 //äëèíà âðåìåíè ñîáûòèß (32áèò) - 4áàéòà
#define LOG_CODE_LENGTH 2 //äëèíà êîäà ñîáûòèß (16áèò) - 2áàéòà
#define LOG_LENGTH LOG_NUM_LENGTH + LOG_TIME_LENGTH + LOG_CODE_LENGTH //îáùàß äëèíà çàïèñè îøèáêè
#define EVENT_FIFO_SUCCESSFUL 0
#define EVENT_FIFO_EMPTY 1
#define EVENT_FIFO_FULL 2
#define EVENT_FIFO_BUSY 3
typedef struct
{
Uint16 ev_num;
Uint32 ev_time;
Uint16 ev_code;
}TEvent;
struct SEventFIFO
{
Uint16 busy_flag;
Uint16 size;
Uint16 number_of_msgs;
Uint16 read_ptr;
Uint16 write_ptr;
TEvent msg_array[LOG_FIFO_SIZE];
Uint16(*read)(struct SEventFIFO*,TEvent*);
Uint16(*write)(struct SEventFIFO*,TEvent*);
};
typedef struct SEventFIFO TEventFIFO;
#define EVENT_FIFO_DEFAULTS {0,\
LOG_FIFO_SIZE,\
0,0,0,\
{0},\
Event_FIFO_Read,\
Event_FIFO_Write,\
}
Uint16 Event_FIFO_Read(TEventFIFO*,TEvent*);
Uint16 Event_FIFO_Write(TEventFIFO*,TEvent*);
struct SLogger
{
Uint16 INTERNAL_last_log_index;
Uint16 INTERNAL_last_log_num;
Uint16 INTERNAL_last_log_code;
Uint16 SPI_buf_size;
Uint16 SPI_start_addr;
Uint32* time_ptr;
Uint16 bit_fault_written[4]; //ôëàãè çàïèñàííûõ àâàðèé
Uint16 WriteCounter; //ñ÷åò÷èê áèòîâ äëÿ çàïèñè àâàðèé â áàíê
Uint16 mainDCDCwritten;
Uint16 DCDC3phwritten;
Uint16 mcwritten;
Uint16 chargerwritten;
TEventFIFO FIFO;
void (*init)(volatile struct SLogger*,Uint16 BS,Uint16 SA,Uint32* tptr);
void (*background_calc)(volatile struct SLogger*);
void (*ms_calc)(volatile struct SLogger*);
void (*clear)(volatile struct SLogger*);
Uint16(*write)(volatile struct SLogger*,Uint16);
void (*read)(volatile struct SLogger*,Uint16,TEvent*);
};
typedef volatile struct SLogger TLogger;
//ò.ê. ÷àñîâ ðåàëüíîãî âðåìåíè íåò (ÌÊ 30.1), â êà÷åñòâå âðåìåííÎãî ìàðêåðà àâàðèé èñïîëüçóåòñÿ âðåìÿ âêëþ÷åííîãî ñîñòîÿíèÿ
#define LOGGER_DEFAULTS {0,0,0,1,0,\
(Uint32*)&RTCclock.packed_time,\
{0,0,0,0},0,0,0,0,0,\
EVENT_FIFO_DEFAULTS,\
Logger_Init,\
Logger_Background_Calc,\
Logger_ms_Calc,\
Logger_Clear,\
Logger_Event_Write,\
Logger_Event_Read,\
}
void Logger_Init(TLogger*,Uint16 BS,Uint16 SA,Uint32* tptr);
void Logger_Background_Calc(TLogger*);
void Logger_ms_Calc(TLogger*);
void Logger_Clear(TLogger*);
Uint16 Logger_Event_Write(TLogger*,Uint16);
void Logger_Event_Read(TLogger* p,Uint16 shift_index,TEvent* event);
#ifdef __cplusplus
}
#endif
#endif

72
Vinclude/V_fifo.h Normal file
View File

@ -0,0 +1,72 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file V_fifo.c
\brief Êîëüöåâîé ìàñèâ òèïà FIFO. Ïîçâîëÿåò çàïèñûâàòü äàííûå òèïà "Uint8"
ïàêåòàìè ïðîèçâîëüíîé äëèíû.
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 1.0 08/08/2017
*/
#ifndef V_FIFO_C_
#define V_FIFO_C_
#define BUFFER_SIZE 64
#define FIFO_BUSY -1 // Ôèôî çàíÿò
#define FIFO_NOT_ENOUGH_SPACE 2 // Íå õâàòàåò ìåñòà äëÿ çàïèñè
#define FIFO_NOT_ENOUGH_DATA 3 // Íåò ñòîëüêî äàííûõ, ñêîëüêî õîòÿò âû÷èòàòü
#define FIFO_OK 0 // Âñ¸ îê
struct Sfifo;
typedef volatile struct Sfifo Tfifo;
struct Sfifo {
Uint16 busy;
Uint16 size; // Ðàçìåð áóôåðà (íàäî)
Uint16 wp; // Write pointer
Uint16 rp; // Read pointer
Uint8 wrapFlag; // Âçâîäèòñÿ â 1, åñëè wp ïåðåø¸ë çà ãðàíèöû áóôåðà;
// Ñáðàñûâàåòñÿ, åñëè rp ïåðåø¸ë
// Ïîìîãàåò îòñëåäèòü ñèòóàöèþ, êîãäà áóôåðà çàïîëíåí íà 100%: rp == wp && wrap == 1
// Ëèáî åñëè áóôåð ïîëíîñòüþ ïóñò: rp == wp && wrap == 0
Uint8 buff[BUFFER_SIZE];
int16 (*put)(Tfifo*, Uint16, Uint8*);
int16 (*get)(Tfifo*, Uint16, Uint8*);
int16 (*availSpace)(Tfifo*);
int16 (*filledSpace)(Tfifo*);
void (*clear)(Tfifo*);
};
int16 Fifo_Put (volatile struct Sfifo*, Uint16, Uint8*);
int16 Fifo_Get (volatile struct Sfifo*, Uint16, Uint8*);
int16 getFill (Tfifo*);
int16 getFreeSpace (Tfifo*);
void Fifo_Clear (Tfifo*);
#define FIFO_DEFAULTS {.size = BUFFER_SIZE,\
.put = Fifo_Put,\
.get = Fifo_Get,\
.availSpace = getFreeSpace,\
.filledSpace = getFill,\
.clear = Fifo_Clear}
extern Tfifo fifosha;
extern Tfifo usbRxBuf;
extern Tfifo usbTxBuf;
#endif /* V_FIFO_C_ */

69
Vinclude/V_hzprof.h Normal file
View File

@ -0,0 +1,69 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file vhzprof.h
\brief Êðèâàÿ U(f) (ñì. TVhzProf)
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 2.0 25/03/2016
\defgroup vhzprof Ìîäóëü êðèâîé U(f) (ñì. TVhzProf)
*/
#ifndef VHZPOF_H
#define VHZPOF_H
#ifdef __cplusplus
extern "C" {
#endif
/*! \class TVhzProf
\brief Êðèâàÿ U(f)
Êëàññ \a TVhzProf, îñíîâàííûé íà ñòðóêòóðå SVhzProf,
ïðåäñòàâëÿåò ñîáîé äâóìåðíóþ çàâèñèìîñòü íàïðÿæåíèÿ U (vout) îò
÷àñòîòû f (freq). Ìîäóëü íóæåí ïðè ñêàëÿðíîì óïðàâëåíèè äâèãàòåëåì,
áåç êîíòóðîâ òîêà - êîãäà íàïðÿæåíèå ðàñòåò âìåñòå ñ ÷àñòîòîé. Äàííûé ìîäóëü
ïîçâîëÿåò íàñòðîèòü ëèíåéíóþ çàâèñèìîñòü íàïðÿæåíèÿ îò ÷àñòîòû ïî äâóì òî÷êàì. */
//! ñì. TVhzProf
struct SVhzProf{ _iq freq;//!< Input: Input frequency (pu)
_iq vout;//!< Output: Output voltage (pu)
_iq FL;//!< Parameter: Low frequency (pu)
_iq FH;//!< Parameter: High frequency at rated voltage (pu)
_iq Fmax; //!<Parameter: Maximum frequency (pu)
_iq Vmax;//!< Parameter: Rated voltage (pu)
_iq Vmin;//!< Parameter: Voltage at low frequency range (pu)
void (*calc)(struct SVhzProf*);//!< Pointer to calculation function
};
typedef struct SVhzProf TVhzProf;
//! Èíèöèàëèçàòîð ïî-óìîë÷àíèþ
#define VHZPROF_DEFAULTS { 0,0, \
0,0,0,0,0, \
vhz_prof_calc }
//! \memberof TVhzProf
void vhz_prof_calc(TVhzProf *v);
#ifdef __cplusplus
}
#endif
#endif
/*@}*/

68
Vinclude/V_led.h Normal file
View File

@ -0,0 +1,68 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file Vled.h
\brief Óïðàâëåíèå ñâåòîäèîäàìè
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 2.0 25/03/2016
*/
#ifndef VINCLUDE_V_LED_H_
#define VINCLUDE_V_LED_H_
#ifdef __cplusplus
extern "C"
{
#endif
#include "DSP.h"
#define LED1 0
#define LED2 1
#define LED3 2
#define LED4 3
#define LED5 4
#define LED6 5
#define LED_ALL 6
struct Sled;
typedef volatile struct Sled Tled;
struct Sled{
Uint16 timer1, timer2, timer3, timer4, timer5, timer6;
Uint16 mode, prevMode;
Uint16 mode3counter;
void (*init)(Tled*);
void (*toggle)(Tled*, Uint16);
void (*on)(Tled*, Uint16);
void (*off)(Tled*, Uint16);
void (*msCalc)(Tled*);
};
#define LED_DEFAULTS {0,0,0,0,0,0,0,0,0, LED_init, LED_toggle, LED_on, LED_off, LED_msCalc}
void LED_init (Tled*);
void LED_toggle (Tled*, Uint16);
void LED_on (Tled*, Uint16);
void LED_off (Tled*, Uint16);
void LED_msCalc (Tled*);
#ifdef __cplusplus
}
#endif
#endif /* VINCLUDE_V_LED_H_ */

108
Vinclude/V_pid_reg3.h Normal file
View File

@ -0,0 +1,108 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file V_pid_reg3.h
\brief ÏÈÄ-ðåãóëÿòîð (ñì. TPidReg3)
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 2.0 25/03/2016
\defgroup V_pid_reg3 ÏÈÄ-ðåãóëÿòîð
@{*/
#ifndef PID_REG3_H
#define PID_REG3_H
#ifdef __cplusplus
extern "C" {
#endif
/*! \class TPidReg3
\brief Ìîäóëü ÏÈÄ-ðåãóëÿòîðà
Êëàññ \a TPidReg3, îñíîâàííûé íà ñòðóêòóðå SPidReg3, ïðåäñòàâëÿåò
ñîáîé ïðîïîðöèîíàëüíî - èíòåãðàëüíî - äèôôåðåíöèàëüíûé ðåãóëÿòîð.
Âñå êîýôôèöèåíòû íàñòðàèâàåìûå, äèôôåðåíöèàëüíàÿ ÷àñòü èìååò íàñòðàèâàåìûé ôèëüòð.
*/
//! ñì. TPidReg3
typedef struct SPidReg3{ long pid_ref_reg3; //!< Input: Reference input
long pid_fdb_reg3;//!< Input: Feedback input
long e_reg3;//!<Variable: Error
long e_reg3Dz;//!<Variable: Error after dead zone
long Kp_reg3;//!< Parameter: Proportional gain
long up_reg3;//!< Variable: Proportional output
long ui_reg3;//!< Variable: Integral output
long ud_reg3;//!< Variable: Derivative output
long uprsat_reg3;//!< Variable: Pre-saturated output
long saterr_reg3Add;//!< Variable: Äîïîëíèòåëüíàÿ îøèáêà íàñûùåíèÿ îò "âåðõíåãî óðîâíÿ"
long pid_out_max;//!< Parameter: Maximum output
long pid_out_min;//!< Parameter: Minimum output
long pid_out_reg3;//!< Output: PID output */
long saterr_reg3;//!< Variable: Saturated difference
long Ki_reg3;//!< Parameter: Integral gain
long Kc_reg3;//!< Parameter: Integral correction gain
long Kd_reg3;//!< Parameter: Derivative gain
long up1_reg3;//!< History: Previous proportional output
long pid_out_test;//!< Output: PID output for test
long DeadZone;//!< Ìåðòâàÿ çîíà
long Kf_d;//!<Ôèëüòð äèôôåðåíöèàëüíîé ÷àñòè
long e_reg3_filterOut;//!<Âûõîä ôèëüòðà äèôôåðåíöèàëüíîé ÷àñòè
long DiffDelim;//!<Äåëèòåëü äëÿ òàêòèðîâàíèÿ ðàñ÷åòà ïðîèçâîäíîé
long DiffCounter;//!<Ñ÷åò÷èê äëÿ äåëèòåëÿ
int KdFilterInitFlag;//!<Ôëàã ïåðâîãî çàïóñêà äëÿ èíèöèàëèçàöèè ôèëüòðà äèôô. ÷àñòè
void (*calc)(struct SPidReg3*);//!< Pointer to calculation function
void (*reset)(struct SPidReg3*);//!< Pointer to reset function
}TPidReg3;
//! Èíèöèàëèçàòîð ïî-óìîë÷àíèþ
#define PIDREG3_DEFAULTS { 0,0, \
0, \
0, \
0, \
0, \
0, \
0, \
0,0, \
_IQ(1), \
_IQ(-1), \
0, \
0, \
_IQ(0.05), \
_IQ(0.5), \
_IQ(0), \
0,0,0,0,0,0,0,0,\
pid_reg3_calc,\
pid_reg3_reset}
//! \memberof TPidReg3
void pid_reg3_calc(TPidReg3*);
void pid_reg3_reset(TPidReg3*);
#ifdef __cplusplus
}
#endif
#endif
/*@}*/

108
Vinclude/V_pid_reg3_pos.h Normal file
View File

@ -0,0 +1,108 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file V_pid_reg3.h
\brief ÏÈÄ-ðåãóëÿòîð (ñì. TPidReg3)
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 2.0 25/03/2016
\defgroup V_pid_reg3 ÏÈÄ-ðåãóëÿòîð
@{*/
#ifndef PID_REG3_POS_H
#define PID_REG3_POS_H
#ifdef __cplusplus
extern "C" {
#endif
/*! \class TPidReg3
\brief Ìîäóëü ÏÈÄ-ðåãóëÿòîðà
Êëàññ \a TPidReg3, îñíîâàííûé íà ñòðóêòóðå SPidReg3, ïðåäñòàâëÿåò
ñîáîé ïðîïîðöèîíàëüíî - èíòåãðàëüíî - äèôôåðåíöèàëüíûé ðåãóëÿòîð.
Âñå êîýôôèöèåíòû íàñòðàèâàåìûå, äèôôåðåíöèàëüíàÿ ÷àñòü èìååò íàñòðàèâàåìûé ôèëüòð.
*/
//! ñì. TPidReg3
typedef struct SPidReg3_pos{ long pid_ref_reg3; //!< Input: Reference input
long pid_fdb_reg3;//!< Input: Feedback input
long e_reg3;//!<Variable: Error
long e_reg3Dz;//!<Variable: Error after dead zone
long Kp_reg3;//!< Parameter: Proportional gain
long up_reg3;//!< Variable: Proportional output
long ui_reg3;//!< Variable: Integral output
long ud_reg3;//!< Variable: Derivative output
long uprsat_reg3;//!< Variable: Pre-saturated output
long saterr_reg3Add;//!< Variable: Äîïîëíèòåëüíàÿ îøèáêà íàñûùåíèÿ îò "âåðõíåãî óðîâíÿ"
long pid_out_max;//!< Parameter: Maximum output
long pid_out_min;//!< Parameter: Minimum output
long pid_out_reg3;//!< Output: PID output */
long saterr_reg3;//!< Variable: Saturated difference
long Ki_reg3;//!< Parameter: Integral gain
long Kc_reg3;//!< Parameter: Integral correction gain
long Kd_reg3;//!< Parameter: Derivative gain
long up1_reg3;//!< History: Previous proportional output
long pid_out_test;//!< Output: PID output for test
long DeadZone;//!< Ìåðòâàÿ çîíà
long Kf_d;//!<Ôèëüòð äèôôåðåíöèàëüíîé ÷àñòè
long e_reg3_filterOut;//!<Âûõîä ôèëüòðà äèôôåðåíöèàëüíîé ÷àñòè
long DiffDelim;//!<Äåëèòåëü äëÿ òàêòèðîâàíèÿ ðàñ÷åòà ïðîèçâîäíîé
long DiffCounter;//!<Ñ÷åò÷èê äëÿ äåëèòåëÿ
int KdFilterInitFlag;//!<Ôëàã ïåðâîãî çàïóñêà äëÿ èíèöèàëèçàöèè ôèëüòðà äèôô. ÷àñòè
void (*calc)(struct SPidReg3_pos*);//!< Pointer to calculation function
void (*reset)(struct SPidReg3_pos*);//!< Pointer to reset function
}TPidReg3_pos;
//! Èíèöèàëèçàòîð ïî-óìîë÷àíèþ
#define PIDREG3_DEFAULTS_POS { 0,0, \
0, \
0, \
0, \
0, \
0, \
0, \
0,0, \
_IQ(1), \
_IQ(-1), \
0, \
0, \
_IQ(0.05), \
_IQ(0.5), \
_IQ(0), \
0,0,0,0,0,0,0,0,\
pid_reg3_calc_pos,\
pid_reg3_reset_pos}
//! \memberof TPidReg3
void pid_reg3_calc_pos(TPidReg3_pos*);
void pid_reg3_reset_pos(TPidReg3_pos*);
#ifdef __cplusplus
}
#endif
#endif
/*@}*/

67
Vinclude/V_relay_reg.h Normal file
View File

@ -0,0 +1,67 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file V_relay_reg.h
\brief Ðåëåéíûé ðåãóëÿòîð
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 1.0 23/01/2016
\defgroup V_realy_reg
@{*/
#ifndef V_RELAY_REG_H
#define V_RELAY_REG_H
#ifdef __cplusplus
extern "C" {
#endif
/*! \class TRelayReg
\brief Ìîäóëü ðåëåéíîãî ðåãóëÿòîðà
Êëàññ \a TRelayReg, îñíîâàííûé íà ñòðóêòóðå SRelayReg, ïðåäñòàâëÿåò
ñîáîé ðåëåéíûé ðåãóëÿòîð.
*/
//! ñì. TRelayReg
typedef struct SRelayReg{ long ref; //!< Çàäàíèå
long fdb;//!< Îáðàòíàÿ ñâÿçü
long out;//!< Âûõîä
void (*calc)(struct SRelayReg*);//!< Pointer to calculation function
}TRelayReg;
//! Èíèöèàëèçàòîð ïî-óìîë÷àíèþ
#define RELAY_REG_DEFAULTS { 0,0,0, \
relay_reg_calc}
//! \memberof TRelayReg
void relay_reg_calc(TRelayReg*);
#ifdef __cplusplus
}
#endif
#endif
/*@}*/

74
Vinclude/V_rmp_ctrl.h Normal file
View File

@ -0,0 +1,74 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file V_rmp_ctrl.h
\brief Çàäàò÷èê èíòåíñèâíîñòè (ñì. TRMPCtrl)
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 2.0 25/03/2016
\defgroup V_rmp_ctrl Çàäàò÷èê èíòåíñèâíîñòè (ñì. TRMPCtrl)
@{
*/
#ifndef V_RMP_CTRL_H
#define V_RMP_CTRL_H
#ifdef __cplusplus
extern "C" {
#endif
/*! \class TRMPCtrl
\brief Çàäàò÷èê èíòåíñèâíîñòè
Êëàññ \a TRMPCtrl, îñíîâàííûé íà ñòðóêòóðå SRMPCtrl, ïðåäñòàâëÿåò
ñîáîé çàäàò÷èê èíòåíñèâíîñòè - ìîäóëü, ëèíåéíî ñ çàäàííûì òåìïîì
èçìåíÿþùèé ñâîé âûõîä, ïîêà îí íå ñðàâíÿåòñÿ ñî âõîäîì. ×àùå âñåãî ñëóæèò
äëÿ ïëàâíîãî ðàçãîíà äâèãàòåëÿ ïðè èçìåíåíèè çàäàíèÿ ñêà÷êîì.*/
//! ñì. TRMPCtrl
struct SRMPCtrl{ long input;//!< Âõîä
long output;//!< Âûõîä
long Ts;//!< ×àñòîòà äèñêðåòèçàöèè
unsigned long T;//!< Òåìï ðàçãîíà (âðåìÿ â ñåêóíäàõ äî èçìåíåíèÿ âûõîäà îò íóëÿ äî åäèíèöû)
long step;//!<Ñëóæåáíàÿ ïåðåìåííàÿ
void (*calc)(struct SRMPCtrl*); //!< Ôóíêöèÿ ðàñ÷åòà, äîëæíà âûçûâàòüñÿ ñ çàäàííîé â Ts äèñêðåòíîñòüþ
void (*slow_calc)(struct SRMPCtrl*); //!< Ôóíêöèÿ ïåðåñ÷åòà êîýôôèöèåíòîâ
};
typedef struct SRMPCtrl TRMPCtrl;
//!Èíèöèàëèçàòîð ïî-óìîë÷àíèþ
#define V_RMP_CTRL_DEFAULTS {0, \
0, \
_IQ(0.0001), \
_IQ(20), \
0,\
V_RMP_CTRL_calc,\
V_RMP_CTRL_slow_calc,\
}
//! \memberof TRMPCtrl
void V_RMP_CTRL_calc(TRMPCtrl*);
//! \memberof TRMPCtrl
void V_RMP_CTRL_slow_calc(TRMPCtrl*);
#ifdef __cplusplus
}
#endif
#endif
/*@}*/

View File

@ -0,0 +1,61 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file v_rotor_observer.h
\brief Íàáëþäàòåëü ðîòîðà ÀÄ (ñì. TRotorObserver)
\author ÎÎÎ ÍÏÔ Âåêòîð
\version v 1.0 28/06/2016
*/
/** \addtogroup TRotorObserver */
/*@{*/
#ifndef ROTOR_OBSERVER_H
#define ROTOR_OBSERVER_H
struct SRotorObserver{
_iq Ks;
_iq id;
_iq iq;
_iq psi_d;
_iq psi_q;
_iq theta_psi_elec; //!< Óãîë ïîòîêîñöåïëåíèÿ ðîòîðà îòíîñèòåëüíî ÄÏÐ
_iq Tr; //!< Ïîñòîÿííàÿ âðåìåíè ÀÄ
_iq FluxCurrentRatio; //!< Ñîîòíîøåíèå òîêà âîçáóæäåíèÿ îñè x ê ìîìåíòîîáðàçóþùåìó òîêó îñè y
_iq FluxCurrentMin; //!< Ìèíèìóì òîêà âîçáóæäåíèÿ
void (*calc)(struct SRotorObserver*);
void (*slow_calc)(struct SRotorObserver*);
};
typedef struct SRotorObserver TRotorObserver;
#define ROTOR_OBSERVER_DEFAULTS {\
0,0,\
0,0,0,0,\
0,0,0,\
RotorObserver_calc,\
RotorObserver_slow_calc,\
}
void RotorObserver_calc(TRotorObserver *);
void RotorObserver_slow_calc(TRotorObserver *p);
#endif
/*@}*/

35
Vinclude/V_usblib.h Normal file
View File

@ -0,0 +1,35 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file V_usblib.c
\brief Íàáîð ôóíêöèé äëÿ èíèöèàëèçàöèè äðàéâåðà USB. Îñíîâàí íà ïðèìåðå
USB VCP" îò ÍÈÈÝÒ:
https://bitbucket.org/niietcm4/
---> / chip / K1921VK01T / GCC / USB / CDC_VCP /
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru, ÍÈÈÝÒ http://niiet.ru
\version v 1.0 08/08/2017
*/
#ifndef VINCLUDE_V_USBLIB_H_
#define VINCLUDE_V_USBLIB_H_
int USB_init_hardware(void);
void USB_enable_peripheral (void);
void SystemInit (void);
extern Uint8 usbActiveFlag;
#endif /* VINCLUDE_V_USBLIB_H_ */

32
Vinclude/V_watchdog.h Normal file
View File

@ -0,0 +1,32 @@
/*
* V_watchdog.h
*
* Created on: 12 èþë. 2018 ã.
* Author: Dmitry
*/
#ifndef V_WATCHDOG_H_
#define V_WATCHDOG_H_
struct Swdog;
typedef volatile struct Swdog Twdog;
struct Swdog {
void (*enable)();
void (*disable)();
void (*feed)();
void (*resetCPU)();
};
void WDog_Enable();
void WDog_Disable();
void WDog_Feed();
void WDog_ResetSystem();
#define WDOG_DEFAULTS {.enable = WDog_Enable,\
.disable = WDog_Disable,\
.feed = WDog_Feed,\
.resetCPU = WDog_ResetSystem}
extern Twdog Watchdog;
#endif /* V_WATCHDOG_H_ */

View File

@ -0,0 +1,51 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file X_CANFlashProgData.h
\brief Áèíàðíûé ôàéë ïðîøèâàëüùèêà - ãðóçèòñÿ â ÎÇÓ è åìó ïåðåäàåòñÿ óïðàâëåíèå, äàëåå ïî CANopen ìîæíî îáíîâèòü ïðîãðàììó ïî flash.
\author Àëÿìêèí Ä.
\version v 1.0 30/05/2017
\defgroup X_CANFlashProgData */
/*@{*/
#ifndef X_CANFLASHPROGDATA_H
#define X_CANFLASHPROGDATA_H
#ifdef __cplusplus
extern "C"
{
#endif
//àäðåñ ñòðóêòóðû íàñòðîåê
extern Uint32 const FPSettingsAddr;
//àäðåñ íà÷àëà ïðîãðàììû ïðîøèâàëüùèêà
extern Uint32 const FPStartAddr;
//êîëè÷åñòâî àäðåñîâ â ìàññèâå FPAddrs
extern Uint16 const FPNumOfAddrs;
//àäðåñà íà÷àëà ÷àñòåé ïðîøèâàëüùèêà
extern Uint32 const FPAddrs[];
//äëèíà ÷àñòåé ïðîøèâàëüùèêà
extern Uint16 const FPPartsLength[];
//äàííûå ïðîøèâàëüùèêà
extern Uint16 const FPData[];
#ifdef __cplusplus
}
#endif
#endif
/*@}*/

View File

@ -0,0 +1,82 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file X_CANFlashProgStarter.h
\brief Èíèöèàëèçèðóåò ïðîöåññ ïðîæèãà ïî CANó
\author Àëÿìêèí Ä.
\version v 1.0 30/05/2017
\defgroup TCANFlashProgStarter */
/*@{*/
#ifndef X_CANFLASHPROGSTARTER_H
#define X_CANFLASHPROGSTARTER_H
#ifdef __cplusplus
extern "C"
{
#endif
//#define FP_DEVICE_2810
//#define FP_DEVICE_28335
//#define FP_DEVICE_28035
//#define FP_DEVICE_28069
#define FP_DEVICE_M4F
//Ïåðåîïðåäåëßåìûå ïîëüçîâàòåëåì ìàêðîñû
#define FP_BLOCK_PWM pwm.Off(&pwm); //âûêëþ÷åíèå ØÈÌ
#define FP_CTRL_STOP sm_ctrl.state=CTRL_STOP
#define FP_FAULT_SET sm_prot.bit_fault2|= F_FLASH_PROGRAM
struct SFlashProgSettings{
Uint16 magic_number;
Uint16 CANa_nodeID; //2000.0 íîìåð äàííîãî óçëà
Uint16 CANa_bitRate; //2001.0
Uint16 CANa_enable;
Uint16 CANb_nodeID; //2000.0 íîìåð äàííîãî óçëà
Uint16 CANb_bitRate; //2001.0
Uint16 CANb_enable;
};
typedef volatile struct SFlashProgSettings TFlashProgSettings;
extern TFlashProgSettings FPsettings;
/*
struct SFlashProgStarter
{
Uint16 input;
void(*start)(volatile struct SFlashProgStarter*);
};
typedef volatile struct SFlashProgStarter TFlashProgStarter;
#define TFLASHPROGSTARTER_DEFAULTS {0,\
StartFlashProgrammer,\
}
*/
void StartFlashProgrammer();
extern long swu_vars;
#ifdef __cplusplus
}
#endif
#endif
/*@}*/

117
Vinclude/build.h Normal file
View File

@ -0,0 +1,117 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file build.h
\brief Êîíôèãóðàöèîííûé çàãîëîâî÷íûé ôàéë
Ñîäåðæèò ãëîáàëüíûå ìàêðîîïðåäåëåíèÿ, èñïîëüçóåìûå âî âñåì ïðîåêòå.
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 3.0 30/05/2017
@{
*/
// Ðàçðåøèòü ñòîðîæåâîé òàéìåð
//#define WATCHDOG_ON
//Âûáîð òèïà àïïàðàòíîé ÷àñòè
//Äëÿ UART, âûáèðàåòñÿ ÷åì åãî çàíÿòü - MODBUS èëè CANtoRS äðàéâåðîì
//#define MODBUS_ENA
#define CANTORS_ENA
// Òàêæå ìîæíî çàäåéñòâîâàòü USB äëÿ CANopen
#define CANTOUSB_ENA
//!Ðåæèìû ðàáîòû (ñîñòîÿíèÿ ÄÀ sm_ctrl)
//! Ðåæèì îñòàíîâ
#define CTRL_STOP 0
//! Ðåæèì çàïóñêà (âêëþ÷åíèå ØÈÌ, ïåðåõîä â äðóãîé æåëàåìûé ðåæèì ðàáîòû)
#define CTRL_RUN 1
//! Ðåæèì íàìàãíè÷èâàíèå (ïîñòîÿííûé òîê), ðàáîòàåò êîíòóð òîêà
#define CTRL_FLUXING 2
//! Ðåæèì ñêàëÿðíîãî óïðàâëåíèÿ ïî êðèâîé U(f) áåç êîíòóðîâ òîêà
#define CTRL_RUN_U2F 3
//! Ðåæèì âðàùåíèÿ âåêòîðà òîêà
#define CTRL_RUN_I2F 4
//! Âåêòîðíàÿ ñòðóêòóðà óïðàâëåíèÿ äâóõêîíòóðíàÿ ñ äàò÷èêîì äëÿ ñèíõðîííîé ìàøèíû
#define CTRL_RUN_VECTOR_SM 5
//! Âåêòîðíàÿ ñòðóêòóðà óïðàâëåíèÿ ñ ýíêîäåðîì è ñ êîíòóðîì ïîëîæåíèÿ äëÿ ñèíõðîííîé ìàøèíû
#define CTRL_RUN_VECTOR_SM_ENCODER_POS 10
//! Âåêòîðíîå óïðàâëåíèå äëÿ àñèíõðîííîãî äâèãàòåëÿ ñ ýíêîäåðîì.
#define CTRL_RUN_VECTOR_IM_ENCODER 55
//! Ðåæèì êàëèáðîâêè äàò÷èêà ïîëîæåíèÿ
#define CTRL_AUTO_SENSOR_TUNING 29
//! Ðåæèì àâòîêîììóòàöèè äëÿ SRM
#define CTRL_RUN_SRM_AUTOCOMMUTATION 101
//! Ðåæèì èçìåðåíèÿ çàäåðæêè ìåæäó ØÈÌ è äàò÷èêàìè òîêà
#define CTRL_RUN_LATENCY_TEST 31
//Ôëàãè àâàðèé äëÿ ìîäóëÿ çàùèò
//bit_fault1
#define F_CTRL_LOW_UDC 0x1
#define F_CTRL_HI_UDC 0x2
#define F_ENCODER_FAULT 0x4
#define F_MODEL_FAULT 0x8
#define F_FLASH_PROGRAM 0x10
//#define F_RESERVED 0x20
//#define F_RESERVED 0x40
//#define F_RESERVED 0x80
#define F_PROGRAM_1K 0x100
#define F_PROGRAM_10K 0x200
#define F_PROGRAM_40K 0x400
//#define F_RESERVED 0x800
#define F_PDPINT 0x1000
//#define F_RESERVED 0x2000
//#define F_RESERVED 0x4000
//#define F_RESERVED 0x8000
//bit_fault2
//#define F_RESERVED 0x1
//#define F_RESERVED 0x2
//#define F_RESERVED 0x4
//#define F_RESERVED 0x8
#define F_CTRL_MAX_I_PH_A 0x10
#define F_CTRL_MAX_I_PH_B 0x20
#define F_CTRL_MAX_I_PH_C 0x40
//#define F_RESERVED 0x80
//#define F_RESERVED 0x100
#define F_CTRL_SPEED_MAX 0x200
//#define F_RESERVED 0x400
//#define F_RESERVED 0x800
//#define F_RESERVED 0x1000
//#define F_RESERVED 0x2000
//#define F_RESERVED 0x4000
//#define F_RESERVED 0x8000
#define POS_SENSOR_TYPE_NO_SENSOR 0
#define POS_SENSOR_TYPE_ENCODER 1
#define POS_SENSOR_TYPE_HALL 2
#define POS_SENSOR_TYPE_ENC_HALL 3
#define POS_SENSOR_TYPE_SSI 4
#define POS_SENSOR_TYPE_SENSORLESS 5
//!Âðåìÿ äèñêðåòèçàöèè áûñòðîãî ðàñ÷åòà (ïðåðûâàíèå, êîòîðîå îáû÷íî 10êÃö)
#define FAST_CALC_TS _IQ(0.0001)
/*@}*/

71
Vinclude/clarke.h Normal file
View File

@ -0,0 +1,71 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file clarke.h
\brief Ìîäóëü ôàçíûõ ïðåîáðàçîâàíèé (ñì. TClarke)
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 2.0 25/03/2016
\defgroup clarke Ìîäóëü ôàçíûõ ïðåîáðàçîâàíèé (ñì. Tclarke)
@{
*/
#ifndef CLARKE_H
#define CLARKE_H
#ifdef __cplusplus
extern "C" {
#endif
/*! \class TClarke
\brief Ôàçíûå ïðåîáðàçîâàíèÿ
Êëàññ \a TClarke, îñíîâàííûé íà ñòðóêòóðå SClarke, îáåñïå÷èâàåò
ïðåîáðàçîâàíèå âåëè÷èíû èç òðåôàçíîé ñèñòåìû êîîðäèíàò â äâóõôàçíóþ.
Òàê, äëÿ ïðåîáðàçîâàíèÿ òîêîâ ôàç âõîäíûì ïåðåìåííûì as è bs íåîáõîäèìî
ïðèñâîèòü çíà÷åíèå òîêîâ ôàç A è B, âûçâàòü ôóíêöèþ calc, ïîñëå ÷åãî â âûõîäíûõ
ïåðåìåííûõ ds, qs áóäåò çíà÷åíèå âåêòîðà òîêà âî âçàèìíî ïåðïåíäèêóëÿðíûõ îñÿõ
àëüôà, áåòòà (â àíãëîÿçû÷íîé ëèòåðàòóðå îñè d,q).*/
//! ñì. TClarke
struct SClarke{ long as; //!< Input: phase-a stator variable
long bs;//!< Input: phase-b stator variable
long ds; //!< Output: stationary d-axis stator variable
long qs; //!< Output: stationary q-axis stator variable
void (*calc)(struct SClarke*); //!< Pointer to calculation function
};
typedef struct SClarke TClarke;
//! èíèöèàëèçàòîð ïî-óìîë÷àíèþ
#define CLARKE_DEFAULTS { 0, \
0, \
0, \
0, \
clarke_calc }
//! \memberof TClarke
void clarke_calc(TClarke*);
#ifdef __cplusplus
}
#endif
#endif
/*@}*/

867
Vinclude/co_ODvars.h Normal file
View File

@ -0,0 +1,867 @@
/*!
Copyright 2017 АО "НИИЭТ" и ООО "НПФ ВЕКТОР"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file co_ODvars.h
\brief Объявляет некоторые служебные структуры для драйвера CANOpen
\author ООО "НПФ Вектор". http://motorcontrol.ru
\version v 2.3 28/06/2019
\defgroup CANOpen_drv Драйвер CANOpen
@{
*/
#ifndef CO_OD_VARS_H
#define CO_OD_VARS_H
#ifdef __cplusplus
extern "C" {
#endif
#include "DSP.h"
//****************************************************************************************************************************************
//! Начальный адрес для сохранения в SPI памяти словаря 1-го CAN
#define CO1_SPI_START_ADDR 0
//! Начальный адрес для сохранения в SPI памяти словаря 2-го CAN
#define CO2_SPI_START_ADDR 3500
// количество "замеппированных" объектов для каждого PDO
#define RPDO1NUMOFPARAMS 4
#define RPDO2NUMOFPARAMS 4
#define RPDO3NUMOFPARAMS 4
#define RPDO4NUMOFPARAMS 4
#define RPDO5NUMOFPARAMS 4
#define RPDO6NUMOFPARAMS 4
#define RPDO7NUMOFPARAMS 4
#define RPDO8NUMOFPARAMS 4
#define TPDO1NUMOFPARAMS 4
#define TPDO2NUMOFPARAMS 4
#define TPDO3NUMOFPARAMS 4
#define TPDO4NUMOFPARAMS 4
#define TPDO5NUMOFPARAMS 4
#define TPDO6NUMOFPARAMS 4
#define TPDO7NUMOFPARAMS 4
#define TPDO8NUMOFPARAMS 4
//структура с таблицами параметров для настройки скорости CAN (для каждого микроконтроллера настройки свои)
typedef struct {
Uint16 co_DIV8[6];
Uint16 co_BRP[6];
Uint16 co_TSEG1[6];
Uint16 co_TSEG2[6];
Uint16 co_SJW[6];
} TCANSpeedTableOptions;
//структура пользовательских настроек драйвера
struct S_CANOPEN_DRV_SETTINGS
{
Uint16 LoadParamsFromUserMemory_ena; //Загружать параметры из пользовательской памяти при инициализации
Uint16 CAN_ISR_priority; //Приоритет прерываний CAN
Uint16 MultiPDO_ena; /* //разрешение принимать PDO от любых устройств в сети:
//для каждого RPDO доступны 8 диапазонов принимаемых идентификаторов:
// 0x181-0x1FF
// 0x200-0x27F
// 0x280-0x2FF
// ...
// 0x480-0x4FF
// 0x500-0x57F
//Каждому RPDO должен быть сопоставлен свой диапазон идентификаторов.
//Для сопоставления данному RPDO диапазона идентификаторов необходимо присвоить
//соответствующему RPDOxCOBID любой идентификатор требуемого диапазона.
//Двум RPDO одного устройства не может быть сопоставлен один и тот же диапазон идентификаторов -
//в этом случае поведение непредсказуемо. */
Uint16 RX_PDO_Callback_ena; /*//разрешение вызова CallBack при приеме PDO. (может использоваться как в обычном режиме, так и в режиме МультиPDO).
//Если дефайн объявлен, то после каждого приема узлом PDO будет вызываться соответствующая CallBack функция
//(ф-ии описаны в файле CANOpenCallbacks.c) вида: void co_RPDOx_Callback(Uint16 nodeID)
//Где x = 1,2,..8 при приеме RPDO1, RPDO2,..RPDO8 соответственно.
//В качестве параметра в функцию передается только номер узла (nodeID) от которого принято PDO,
//а принятая информация находится по соответствующему(-им) мэппингу данного PDO адресу(-ам).*/
Uint16 AutoBusON_ena; /*//разрешение CAN устройству оставаться в работе даже при наличии большого количества ошибок на линии CAN.
//С одной стороны разрешение позволяет работать устройству в сильно зашумленной линии, но с другой -
//при отказе в устройстве, например rx, устройство забьет всю сеть, пытаясь отправить свою посылку...*/
Uint16 BlockTransfer_ena; //разрешение использования в драйвере функций блочной передачи
Uint32 BaseAdressCanRegisters; //адрес в памяти, с которого начинаются CAN-регистры. Нужно для унификация библиотеки драйвера CANOpen для разных
//микроконтроллеров фирмы НИИЭТ
Uint16 CAN_IRQn; //номер перечисления прерывания CAN из таблицы прерываний. Нужно для унификация библиотеки драйвера CANOpen для
//разных микроконтроллеров фирмы НИИЭТ
TCANSpeedTableOptions *speedCANTablePointer;//указатель на массив структур с таблицами параметров для настройки скорости CAN для разных микроконтроллеров.
void (*resetCPU)(void); //указатель на функцию перезагрузки микроконтроллера. Нужна, потому как для разных микроконтроллеров фирмы НИИЭТ
//используются разные функции для ресета.
};
// Тип доступа к параметру (согласно формату)
typedef enum EObjAccess
{
OBJ_ACCESS_READONLY, // read-only
OBJ_ACCESS_RW, // read/write
OBJ_ACCESS_WP, // read/writeable protected
OBJ_ACCESS_SWP, // read/secret writeable protected
} TObjAccess;
// Тип параметра (согласно формату)
typedef enum EObjType
{
OBJ_TYPE_UNKNOWN,
OBJ_TYPE_ROOT,
OBJ_TYPE_U8,
OBJ_TYPE_U16,
OBJ_TYPE_QU16,
OBJ_TYPE_I8,
OBJ_TYPE_I16,
OBJ_TYPE_QI16,
OBJ_TYPE_U32,
OBJ_TYPE_QU32,
OBJ_TYPE_I32,
OBJ_TYPE_QI32,
OBJ_TYPE_BIT_FIELD,
OBJ_TYPE_FLOAT_ABS,
OBJ_TYPE_FLOAT_PU,
} TObjType;
// Структура, содержащая различную информацию об объекте.
typedef struct
{
void* varAddr; // адрес переменной в ОЗУ
int varSize; // размер переменной в битах (16/32)
TObjAccess access; // тип доступа к объекту
TObjType type; // тип объекта
Uint16 subIndNum; // число подындексов (для ROOT)
Uint16 scaleNum; // номер масштабирующего коэффициента (для QU16, QI16, QU32, QI32, FLOAT_PU)
Uint16 Q; // число разрядов дробной части (для QU16, QI16, QU32, QI32)
Uint16 bitOffset; // смещение битового поля (для BIT_FIELD)
Uint16 bitNum; // размер битового поля (для BIT_FIELD)
Uint16 precision; // число знаков, отображаемых после запятой (для FLOAT_ABS)
Uint16 prefix; // префикс размерности (для FLOAT_ABS)
Uint16 units; // размерность (для FLOAT_ABS)
} TObjectInfo;
typedef volatile struct S_CANOPEN_DRV_SETTINGS T_CANOPEN_DRV_SETTINGS;
//!Конфигурирование полей SDO
struct SDOcommSpecifier {
Uint16 s:1; //!< 0 - если s=1, то размер передаваемых данных известен и указан
Uint16 e:1; //!< 1 - expedited или нет
Uint16 n:2; //!< 3:2 - количество байт данных не содержащих данных
Uint16 X:1; //!< 4 - reserved
Uint16 cs:3;//!< 7:5 - SDO команда
Uint16 reserved:8;//
};
//! Нулевой байт мейл-бокса
union MBOXByte0{
struct SDOcommSpecifier SDO_Spicifier;
Uint16 byte0;
};
//! Байты мейл-бокса, используемого для альтернативной CAN связи (ZigBee, USB)
typedef struct {
union MBOXByte0 MByte0;
Uint16 byte1;
Uint16 byte2;
Uint16 byte3;
Uint16 byte4;
Uint16 byte5;
Uint16 byte6;
Uint16 byte7;
Uint16 senderNodeID;
}Z_MBytes;
typedef struct {
Uint32 id;
Uint8 data[8];
Uint8 dlc;
} TZCanMsg;
///сообщение в виде полей SDO
struct SDOmsg
{ Uint32 s:1; //!< 0 - если s=1, то размер передаваемых данных известен и указан
Uint32 e:1; //!< 1 - expedited или нет
Uint32 n:2; //!< 3:2 - количество байт данных не содержащих данных
Uint32 X:1; //!< 4 - reserved
Uint32 cs:3;//!< 7:5 - SDO команда
Uint32 index:16;
Uint32 subindex:8;
Uint32 data:32;
};
//сообщение в виде байтов
struct MBOX_bytes
{ Uint16 byte0:8;
Uint16 byte1:8;
Uint16 byte2:8;
Uint16 byte3:8;
Uint16 byte4:8;
Uint16 byte5:8;
Uint16 byte6:8;
Uint16 byte7:8;
};
//сообщение в виде слов
struct MBOX_words
{ Uint16 word0;
Uint16 word1;
Uint16 word2;
Uint16 word3;
};
//сообщение в виде MDRL, MDRH
struct MBOX_Uint32
{ Uint32 MDRL;
Uint32 MDRH;
};
//все представления накладываем друг на друга
union MBOX_data {
struct MBOX_Uint32 u32;
struct MBOX_words u16;
struct MBOX_bytes u8;
struct SDOmsg SDO;
};
typedef volatile union MBOX_data TMBOX_data;
struct MID_bits
{ Uint32 rsvd1:18; //пока не используем
Uint32 senderNodeID:7; //номер узла
Uint32 rsvd2:7; //пока не используем
};
union MID_data {
Uint32 all;
struct MID_bits bit;
};
// мейл-бокс
struct MData
{
union MBOX_data data;
union MID_data MID;
};
typedef volatile struct MData TCo_MOData;
//! Сборник данных всех мейл-боксов
struct CO_MBOXDATA
{
struct MData MBOX_0;
struct MData MBOX_1;
struct MData MBOX_2;
struct MData MBOX_3;
struct MData MBOX_4;
struct MData MBOX_5;
struct MData MBOX_6;
struct MData MBOX_7;
struct MData MBOX_8;
struct MData MBOX_9;
struct MData MBOX_10;
struct MData MBOX_11;
struct MData MBOX_12;
struct MData MBOX_13;
struct MData MBOX_14;
struct MData MBOX_15;
struct MData MBOX_16;
struct MData MBOX_17;
struct MData MBOX_18;
struct MData MBOX_19;
struct MData MBOX_20;
struct MData MBOX_21;
struct MData MBOX_22;
struct MData MBOX_23;
struct MData MBOX_24;
struct MData MBOX_25;
struct MData MBOX_26;
struct MData MBOX_27;
struct MData MBOX_28;
struct MData MBOX_29;
struct MData MBOX_30;
struct MData MBOX_31;
};
typedef volatile struct CO_MBOXDATA TCo_MboxData;
//****************************************************************************************************************************************
//структуры модуля блочной передачи
#define BT_FIFO_SIZE 8 //8 сообщений должно хватить для 1Мбит/с, если обработка производится в 1мс
//внутримодульные дефайны
#define BT_FIFO_SUCCESSFUL 0
#define BT_FIFO_EMPTY 1
#define BT_FIFO_FULL 2
#define BT_FIFO_BUSY 3
struct S_BT_FIFO
{
Uint16 busy_flag; //флаг занятости ФИФО, показывает количество инстанций, использующих ФИФО в данный момент
Uint16 size;
Uint16 number_of_msgs;
Uint16 read_ptr;
Uint16 write_ptr;
TMBOX_data msg_array[BT_FIFO_SIZE];
Uint16(*read)(volatile struct S_BT_FIFO*,TMBOX_data*);
Uint16(*write)(volatile struct S_BT_FIFO*,TMBOX_data*);
Uint16(*clear)(volatile struct S_BT_FIFO*);
};
typedef volatile struct S_BT_FIFO T_BT_FIFO;
#define T_BT_FIFO_DEFAULTS {0,\
BT_FIFO_SIZE,\
0,0,0,\
{0},\
BT_FIFO_Read,\
BT_FIFO_Write,\
BT_FIFO_Clear}
Uint16 BT_FIFO_Read(T_BT_FIFO*,TMBOX_data*);
Uint16 BT_FIFO_Write(T_BT_FIFO*,TMBOX_data*);
Uint16 BT_FIFO_Clear(T_BT_FIFO* p);
#define CANBT_STATE_FREE 0
#define CANBT_STATE_RX 1
#define CANBT_STATE_TX 2
#define CANBT_STATUS_IDLE 0
#define CANBT_STATUS_BUSY 1
#define CANBT_STATUS_SUCCESSFUL 2
#define CANBT_STATUS_TIMEOUT 3
#define CANBT_STATUS_CRC_ERR 4
#define CANBT_STATUS_ANY_ERR 5
struct SBlockTransfer
{ Uint16 state; //Состояние.
Uint16 state_shadow;//Теневое состояние.
Uint16 state_prev; //Предыдущее состояние (на один такт)
Uint16 E; //Флаг первого вхождения.
Uint32 state_time; //время нахождения в текущем состоянии, в мс.
Uint16 RX_block_size; //размер принимаемого блока (определяется пользователем перед приемом)
Uint16 TX_block_size; //размер отправляемого блока (определяется пользователем перед отправкой)
Uint16 firstTXmsg; //флаг, показывающий, что 1-е сообщение блока еще не отправлялось.
Uint16* RX_dest_ptr;
Uint16* TX_source_ptr;
int RX_index;
int TX_index;
T_BT_FIFO RXmsgFIFO;
T_BT_FIFO TXmsgFIFO;
Uint16 blockCRC;
Uint16 rx_status; //обратная связь для внешней программы использующей блочную передачу
Uint16 tx_status; //
Uint32 timeout;
};
typedef volatile struct SBlockTransfer TBlockTransfer;
#define TBLOCK_TRANSFER_DEFAULTS {CANBT_STATE_FREE,\
CANBT_STATE_FREE,0xff,1,\
0,\
0,0,0,0,0,0,0,\
T_BT_FIFO_DEFAULTS,T_BT_FIFO_DEFAULTS,\
0,\
CANBT_STATUS_IDLE,CANBT_STATUS_IDLE,\
((Uint32)500)/*500мс*/,\
}
//****************************************************************************************************************************************
//структура работы с пользовательской памятью для сохранения и восстановления параметров словаря объектов
struct S_UserMemoryContext
{
Uint16 MemStartAddr; //!Адрес в пользовательской памяти (побайтовый доступ)
Uint16 *MCUStartAddr; //!Указатель на массив с данными в MCU
Uint16 data_length; //!длина данных (в байтах)
};
typedef volatile struct S_UserMemoryContext T_UserMemoryContext;
//****************************************************************************************************************************************
//Структура с данными драйвера CANOpen
//Помимо служебных и пользоваельских данных, необходимых для работы драйвера,
//в данную структуру входят стандартные переменные словаря CANOpen
struct SCo_OdVars{
Uint32 co_deviceType; //1000.0
Uint16 co_errorRegister; //1001.0 Регистр ошибки
Uint32 co_deviceState; //1002.0
Uint32 co_emcyCOBID; //1014.0
Uint32 co_CHBT; //1016.1 Consumer heartbeat time
Uint32 co_PHBT ; //1017.0 Producer heartbeat time
Uint32 co_vendorID; //1018.1
Uint32 co_productCode; //1018.2
Uint32 co_revisionNumber; //1018.3
Uint32 co_serialNumber; //1018.4
Uint32 co_csrxCOBID; //1200.1
Uint32 co_sctxCOBID; //1200.2
Uint32 co_cstxCOBID; //1280.1
Uint32 co_scrxCOBID; //1280.2
Uint16 co_ssNODEID; //1280.3
Uint32 co_RPDO1COBID; //1400.1
Uint16 co_transType; //1400.2 , 1401.2 , 1402.2 , 1403.2
Uint32 co_RPDO2COBID; //1401.1
Uint32 co_RPDO3COBID; //1402.1
Uint32 co_RPDO4COBID; //1403.1
Uint32 co_RPDO5COBID; //1404.1 rwp
Uint32 co_RPDO6COBID; //1405.1 rwp
Uint32 co_RPDO7COBID; //1406.1 rwp
Uint32 co_RPDO8COBID; //1407.1 rwp
//
Uint32 co_RPDO1_1Mapping; //1600.1
Uint32 co_RPDO1_2Mapping; //1600.2
Uint32 co_RPDO1_3Mapping; //1600.3
Uint32 co_RPDO1_4Mapping; //1600.4
Uint32 co_RPDO2_1Mapping; //1601.1
Uint32 co_RPDO2_2Mapping; //1601.2
Uint32 co_RPDO2_3Mapping; //1601.3
Uint32 co_RPDO2_4Mapping; //1601.4
Uint32 co_RPDO3_1Mapping; //1602.1
Uint32 co_RPDO3_2Mapping; //1602.2
Uint32 co_RPDO3_3Mapping; //1602.3
Uint32 co_RPDO3_4Mapping; //1602.4
Uint32 co_RPDO4_1Mapping; //1603.1
Uint32 co_RPDO4_2Mapping; //1603.2
Uint32 co_RPDO4_3Mapping; //1603.3
Uint32 co_RPDO4_4Mapping; //1603.4
//2007_03_14
Uint32 co_RPDO5_1Mapping; //1604.1 rwp
Uint32 co_RPDO5_2Mapping; //1604.2 rwp
Uint32 co_RPDO5_3Mapping; //1604.3 rwp
Uint32 co_RPDO5_4Mapping; //1604.4 rwp
Uint32 co_RPDO6_1Mapping; //1605.1 rwp
Uint32 co_RPDO6_2Mapping; //1605.2 rwp
Uint32 co_RPDO6_3Mapping; //1605.3 rwp
Uint32 co_RPDO6_4Mapping; //1605.4 rwp
Uint32 co_RPDO7_1Mapping; //1606.1 rwp
Uint32 co_RPDO7_2Mapping; //1606.2 rwp
Uint32 co_RPDO7_3Mapping; //1606.3 rwp
Uint32 co_RPDO7_4Mapping; //1606.4 rwp
Uint32 co_RPDO8_1Mapping; //1607.1 rwp
Uint32 co_RPDO8_2Mapping; //1607.2 rwp
Uint32 co_RPDO8_3Mapping; //1607.3 rwp
Uint32 co_RPDO8_4Mapping; //1607.4 rwp
//
Uint32 co_TPDO1COBID; //1800.1
Uint16 co_TPDO1ITime; //1800.3 rw
Uint16 co_compatEntry; //1800.4 rw
Uint16 co_TPDO1EventTimer; //1800.5 rw
Uint32 co_TPDO2COBID; //1801.1
Uint16 co_TPDO2ITime; //1801.3 rw
Uint16 co_TPDO2EventTimer; //1800.5 rw
Uint32 co_TPDO3COBID; //1802.1
Uint16 co_TPDO3ITime; //1802.3 rw
Uint16 co_TPDO3EventTimer; //1800.5 rw
Uint32 co_TPDO4COBID; //1803.1
Uint16 co_TPDO4ITime; //1803.3 rw
Uint16 co_TPDO4EventTimer; //1800.5 rw
Uint32 co_TPDO5COBID; //1804.1 r
Uint16 co_TPDO5ITime; //1804.3 rw
Uint16 co_TPDO5EventTimer; //1804.5 rw
Uint32 co_TPDO6COBID; //1805.1 r
Uint16 co_TPDO6ITime; //1805.3 rw
Uint16 co_TPDO6EventTimer; //1805.5 rw
Uint32 co_TPDO7COBID; //1806.1 r
Uint16 co_TPDO7ITime; //1806.3 rw
Uint16 co_TPDO7EventTimer; //1806.5 rw
Uint32 co_TPDO8COBID; //1807.1 r
Uint16 co_TPDO8ITime; //1807.3 rw
Uint16 co_TPDO8EventTimer; //1807.5 rw
//
Uint32 co_TPDO1_1Mapping; //1A00.1
Uint32 co_TPDO1_2Mapping; //1A00.2
Uint32 co_TPDO1_3Mapping; //1A00.3
Uint32 co_TPDO1_4Mapping; //1A00.4
Uint32 co_TPDO2_1Mapping; //1A01.1
Uint32 co_TPDO2_2Mapping; //1A01.2
Uint32 co_TPDO2_3Mapping; //1A01.3
Uint32 co_TPDO2_4Mapping; //1A01.4
Uint32 co_TPDO3_1Mapping; //1A02.1
Uint32 co_TPDO3_2Mapping; //1A02.2
Uint32 co_TPDO3_3Mapping; //1A02.3
Uint32 co_TPDO3_4Mapping; //1A02.4
Uint32 co_TPDO4_1Mapping; //1A03.1
Uint32 co_TPDO4_2Mapping; //1A03.2
Uint32 co_TPDO4_3Mapping; //1A03.3
Uint32 co_TPDO4_4Mapping; //1A03.4
Uint32 co_TPDO5_1Mapping; //1A04.1 rwp
Uint32 co_TPDO5_2Mapping; //1A04.2 rwp
Uint32 co_TPDO5_3Mapping; //1A04.3 rwp
Uint32 co_TPDO5_4Mapping; //1A04.4 rwp
Uint32 co_TPDO6_1Mapping; //1A05.1 rwp
Uint32 co_TPDO6_2Mapping; //1A05.2 rwp
Uint32 co_TPDO6_3Mapping; //1A05.3 rwp
Uint32 co_TPDO6_4Mapping; //1A05.4 rwp
Uint32 co_TPDO7_1Mapping; //1A06.1 rwp
Uint32 co_TPDO7_2Mapping; //1A06.2 rwp
Uint32 co_TPDO7_3Mapping; //1A06.3 rwp
Uint32 co_TPDO7_4Mapping; //1A06.4 rwp
Uint32 co_TPDO8_1Mapping; //1A07.1 rwp
Uint32 co_TPDO8_2Mapping; //1A07.2 rwp
Uint32 co_TPDO8_3Mapping; //1A07.3 rwp
Uint32 co_TPDO8_4Mapping; //1A07.4 rwp
//
Uint16 co_nodeID ; //2000.0 номер данного узла
Uint16 co_bitRate; //2001.0
Uint16 co_specialData1; //2003.1
Uint16 co_specialData2; //2003.2
Uint16 co_specialData3; //2003.3
Uint16 co_specialData4; //2003.4
Uint32 co_secretCode; //2004.0
Uint16 co_protectBit; //2005.0
Uint32 co_devicePresentFlag0;
Uint32 co_devicePresentFlag1;
Uint32 co_devicePresentFlag2;
Uint32 co_devicePresentFlag3;
Uint32 co_deviceGlobalPresent0;
Uint32 co_deviceGlobalPresent1;
Uint32 co_deviceGlobalPresent2;
Uint32 co_deviceGlobalPresent3;
Uint32 co_heartbeatFlag0 ; //2010.1 Флаги heartbeat с 0 по 31-е устройство
Uint32 co_heartbeatFlag1 ; //2010.2 Флаги heartbeat с 32 по 63-е устройство
Uint32 co_heartbeatFlag2 ; //2010.3 Флаги heartbeat с 64 по 95-е устройство
Uint32 co_heartbeatFlag3 ; //2010.4 Флаги heartbeat с 96 по 127-е устройство
Uint32 co_heartbeatMask0 ; //2011.1 Маски heartbeat с 0 по 31-е устройство (0110b)
Uint32 co_heartbeatMask1 ; //2011.2 Маски heartbeat с 32 по 63-е устройство
Uint32 co_heartbeatMask2 ; //2011.3 Маски heartbeat с 64 по 95-е устройство
Uint32 co_heartbeatMask3 ; //2011.4 Маски heartbeat с 96 по 127-е устройство
Uint16 co_heartbeatAutoStart ; //2012.0 Параметр, определяющий возможен ли автозапуск сети
Uint16 co_heartbeatAutoRecovery ; //2014.0 Параметр, определяющий возможен ли перезапуск системы из состояния STOPPED
Uint16 co_nodeState ; //2015.0 состояние данного узла - вначале BOOTUP
Uint16 co_emergencyErrorCode ; //2016.0 Код аварии
Uint32 co_deviceErrorState ; //2017.0 Статусный регистр ошибок производителя
Uint16 co_ODCommand; //2080.1
Uint16 co_currentODIndex; //2080.2
Uint16 co_currentODSubIndex; //2080.3
Uint16 co_currentODEText; //2080.4
Uint16 co_currentODEFormat; //2080.5
Uint16 co_currentODEMin; //2080.6
Uint16 co_currentODEMax; //2080.7
Uint16 co_currentODEDefault; //2080.8
Uint16 co_currentODEMinLow; //2080.9
Uint16 co_currentODEMaxLow; //2080.10
Uint16 co_currentODEDefaultLow; //2080.11
Uint16 co_currentODEAddrHigh; //2080.12
Uint16 co_currentODEAddrLow;
Uint16 co_currentODEType;
Uint16 co_odIndexSize;
Uint32 co_defaultIndex1; //2082.1 rw
Uint32 co_defaultIndex2; //2082.2 rw
Uint16 co_maskElement01; //2083.1,2 rw
Uint16 co_maskElement23; //2083.3,4 rw
Uint16 co_maskElement45; //2083.5,6 rw
Uint16 co_maskElement67; //2083.7,8 rw
Uint16 co_maskElement89; //2083.9,A rw
Uint16 co_maskElementAB; //2083.B,C rw
Uint16 co_maskElementCD; //2083.D,E rw
Uint16 co_maskElementEF; //2083.F,10 rw
Uint16 co_profileAccessMask; //2081.0 rw
Uint16 co_scaleNum0; //2100.1
Uint16 co_scaleNum0Format; //2100.2
Uint16 co_scaleNum1; //2101.1
Uint16 co_scaleNum1Format; //2101.2
Uint16 co_scaleNum2; //2102.1
Uint16 co_scaleNum2Format; //2102.2
Uint16 co_scaleNum3; //2103.1
Uint16 co_scaleNum3Format; //2103.2
Uint16 co_scaleNum4; //2104.1
Uint16 co_scaleNum4Format; //2104.2
Uint16 co_scaleNum5; //2105.1
Uint16 co_scaleNum5Format; //2105.2
Uint16 co_scaleNum6; //2106.1
Uint16 co_scaleNum6Format; //2106.2
Uint16 co_scaleNum7; //2107.1
Uint16 co_scaleNum7Format; //2107.2
Uint16 co_scaleNum8; //2108.1
Uint16 co_scaleNum8Format; //2108.2
Uint16 co_scaleNum9; //2109.1
Uint16 co_scaleNum9Format; //2109.2
Uint16 co_scaleNumA; //210A.1
Uint16 co_scaleNumAFormat; //210A.2
Uint16 co_scaleNumB; //210B.1
Uint16 co_scaleNumBFormat; //210B.2
Uint16 co_scaleNumC; //210C.1
Uint16 co_scaleNumCFormat; //210C.2
Uint16 co_scaleNumD; //210D.1
Uint16 co_scaleNumDFormat; //210D.2
Uint16 co_scaleNumE; //210E.1
Uint16 co_scaleNumEFormat; //210E.2
Uint16 co_scaleNumF; //210F.1
Uint16 co_scaleNumFFormat; //210F.2
Uint16 co_scaleNum10; //2110.1
Uint16 co_scaleNum10Format; //2110.2
Uint16 co_scaleNum11; //2111.1
Uint16 co_scaleNum11Format; //2111.2
Uint16 co_scaleNum12; //2112.1
Uint16 co_scaleNum12Format; //2112.2
Uint16 co_scaleNum13; //2113.1
Uint16 co_scaleNum13Format; //2113.2
Uint16 co_scaleNum14; //2114.1
Uint16 co_scaleNum14Format; //2114.2
Uint16 co_scaleNum15; //2115.1
Uint16 co_scaleNum15Format; //2115.2
Uint16 co_scaleNum16; //2116.1
Uint16 co_scaleNum16Format; //2116.2
Uint16 co_scaleNum17; //2117.1
Uint16 co_scaleNum17Format; //2117.2
Uint16 co_scaleNum18; //2118.1
Uint16 co_scaleNum18Format; //2118.2
Uint16 co_scaleNum19; //2119.1
Uint16 co_scaleNum19Format; //2119.2
Uint16 co_scaleNum1A; //211A.1
Uint16 co_scaleNum1AFormat; //211A.2
Uint16 co_scaleNum1B; //211B.1
Uint16 co_scaleNum1BFormat; //211B.2
Uint16 co_scaleNum1C; //211C.1
Uint16 co_scaleNum1CFormat; //211C.2
Uint16 co_scaleNum1D; //211D.1
Uint16 co_scaleNum1DFormat; //211D.2
Uint16 co_scaleNum1E; //211E.1
Uint16 co_scaleNum1EFormat; //211E.2
Uint16 co_scaleNum1F; //211F.1
Uint16 co_scaleNum1FFormat; //211F.2
Uint16 co_blockTransferCommand; //2700
//Указатели
Uint16 *co_currentWordODTbl1 ;//данные указатели ипользуются для работы интерпретатора
Uint16 *co_currentWordODTbl2 ;//команд в прерывании ШИМ (для обработки быстрых команд)
Uint16 co_currentAccessMask; //маска доступа индекса на который указывает co_currentWordODTbl1
Uint16 *co_shadow_currentWordODTbl1 ;//данные указатели ипользуются для работы интерпретатора
Uint16 *co_shadow_currentWordODTbl2 ;//команд в фоновой программе (для обработки медленных команд)
Uint16 *co_SDOcurrentWordODTbl1;
Uint16 *co_SDOcurrentWordODTbl2;
//ExternalInterface
Uint16 *Z_co_SDOcurrentWordODTbl1;
Uint16 *Z_co_SDOcurrentWordODTbl2;
Uint16 *co_PDOcurrentWordODTbl1;
Uint16 *co_PDOcurrentWordODTbl2;
Uint16 *co_PDOMAPcurrentWordODTbl1;
Uint16 *co_PDOMAPcurrentWordODTbl2;
Uint16 *co_endODTbl1 ;//указывает на последний элемент индекс в таблице ODTbl1
Uint32 co_MailboxMDRL;
Uint32 co_MailboxMDRH;
Uint32 co_MailboxMID;
Uint32 co_flagBackUp0;//
Uint32 co_flagBackUp1;// предыдущие состояния флагов
Uint32 co_flagBackUp2;//
Uint32 co_flagBackUp3;//
Uint32 co_backupEEC; // Предыдущее состояние кода аварии
Uint32 co_backupER; // Предыдущее состояние регистра ошибки
Uint32 co_backupDES; // Предыдущее состояние статусного регистра ошибок производителя
Uint32 co_consHBTimeCounter;// изначально должен быть равен co_CHBT
Uint32 co_prodHBTimeCounter;// изначально должен быть равен co_PHBT
Uint32 co_emcyNewState; // Состояние в которое перешел узел после ошибки
Uint32 co_msDevisor; // делитель частоты для получения 1мс - используется для отправки Heartbeat
Uint16 co_shadow_currentODIndex;
Uint16 co_shadow_currentODSubIndex;
Uint16 co_shadow_currentODEText;
Uint16 co_shadow_currentODEFormat;
Uint16 co_shadow_currentODEMin;
Uint16 co_shadow_currentODEMax;
Uint16 co_shadow_currentODEDefault;
Uint16 co_shadow_currentODEMinLow;
Uint16 co_shadow_currentODEMaxLow;
Uint16 co_shadow_currentODEDefaultLow;
Uint16 co_shadow_currentODEAddrLow;
Uint16 co_shadow_currentODEAddrHigh;
Uint16 co_shadow_currentODEType;
//переменные необходимые для работы SDO служб
Uint16 co_SDOrequestIndex;
Uint16 co_SDOrequestSubIndex;
Uint16 co_SDOrequestData;
Uint16 co_SDOrequestDataH;
Uint16 co_SDOrequestStatus;
Uint16 co_SDOrequestFlag;
Uint16 co_SDOSuspendedSend;
TMBOX_data SDOMsgData;
//временная переменная защиты секретных параметров от несанкционированного доступа
Uint16 co_secretProtectBit;
//переменные необходимые для работы PDO служб
Uint16 co_PDOMappingFlags;//RRRR RRRR TTTT TTTT - "T" - TPDO;- "R" - RPDO
Uint16 co_PDO1Devisor; // делитель для получения заданной скорости передачи PDO1
Uint16 co_PDO2Devisor;
Uint16 co_PDO3Devisor;
Uint16 co_PDO4Devisor;
Uint16 co_PDO5Devisor;
Uint16 co_PDO6Devisor;
Uint16 co_PDO7Devisor;
Uint16 co_PDO8Devisor;
//
Uint16 co_NumOfNextPDO;
Uint16 co_PDOTransmitFlags;//0000 0000 TTTT TTTT
Uint16 co_PDOTransmitEna; //0000 0000 TTTT TTTT
Uint16 co_PDOReceiveEna; //0000 0000 RRRR RRRR
Uint16 co_my_PDO1TransmitFlags;
Uint16 co_my_PDO2TransmitFlags;
Uint16 co_my_PDO3TransmitFlags;
Uint16 co_my_PDO4TransmitFlags;
Uint16 co_my_PDO5TransmitFlags;
Uint16 co_my_PDO6TransmitFlags;
Uint16 co_my_PDO7TransmitFlags;
Uint16 co_my_PDO8TransmitFlags;
Uint32 co_RPDO1_addr[RPDO1NUMOFPARAMS];
Uint32 co_RPDO2_addr[RPDO2NUMOFPARAMS];
Uint32 co_RPDO3_addr[RPDO3NUMOFPARAMS];
Uint32 co_RPDO4_addr[RPDO4NUMOFPARAMS];
Uint32 co_RPDO5_addr[RPDO5NUMOFPARAMS];
Uint32 co_RPDO6_addr[RPDO6NUMOFPARAMS];
Uint32 co_RPDO7_addr[RPDO7NUMOFPARAMS];
Uint32 co_RPDO8_addr[RPDO8NUMOFPARAMS];
//
Uint16 co_RPDO1_startBit[RPDO1NUMOFPARAMS];
Uint16 co_RPDO2_startBit[RPDO2NUMOFPARAMS];
Uint16 co_RPDO3_startBit[RPDO3NUMOFPARAMS];
Uint16 co_RPDO4_startBit[RPDO4NUMOFPARAMS];
Uint16 co_RPDO5_startBit[RPDO5NUMOFPARAMS];
Uint16 co_RPDO6_startBit[RPDO6NUMOFPARAMS];
Uint16 co_RPDO7_startBit[RPDO7NUMOFPARAMS];
Uint16 co_RPDO8_startBit[RPDO8NUMOFPARAMS];
//
Uint16 co_RPDO1_numOfBits[RPDO1NUMOFPARAMS];
Uint16 co_RPDO2_numOfBits[RPDO2NUMOFPARAMS];
Uint16 co_RPDO3_numOfBits[RPDO3NUMOFPARAMS];
Uint16 co_RPDO4_numOfBits[RPDO4NUMOFPARAMS];
Uint16 co_RPDO5_numOfBits[RPDO5NUMOFPARAMS];
Uint16 co_RPDO6_numOfBits[RPDO6NUMOFPARAMS];
Uint16 co_RPDO7_numOfBits[RPDO7NUMOFPARAMS];
Uint16 co_RPDO8_numOfBits[RPDO8NUMOFPARAMS];
//
Uint32 co_TPDO1_addr[TPDO1NUMOFPARAMS];
Uint32 co_TPDO2_addr[TPDO2NUMOFPARAMS];
Uint32 co_TPDO3_addr[TPDO3NUMOFPARAMS];
Uint32 co_TPDO4_addr[TPDO4NUMOFPARAMS];
Uint32 co_TPDO5_addr[TPDO5NUMOFPARAMS];
Uint32 co_TPDO6_addr[TPDO6NUMOFPARAMS];
Uint32 co_TPDO7_addr[TPDO7NUMOFPARAMS];
Uint32 co_TPDO8_addr[TPDO8NUMOFPARAMS];
//
Uint16 co_TPDO1_startBit[TPDO1NUMOFPARAMS];
Uint16 co_TPDO2_startBit[TPDO2NUMOFPARAMS];
Uint16 co_TPDO3_startBit[TPDO3NUMOFPARAMS];
Uint16 co_TPDO4_startBit[TPDO4NUMOFPARAMS];
Uint16 co_TPDO5_startBit[TPDO5NUMOFPARAMS];
Uint16 co_TPDO6_startBit[TPDO6NUMOFPARAMS];
Uint16 co_TPDO7_startBit[TPDO7NUMOFPARAMS];
Uint16 co_TPDO8_startBit[TPDO8NUMOFPARAMS];
//
Uint16 co_TPDO1_numOfBits[TPDO1NUMOFPARAMS];
Uint16 co_TPDO2_numOfBits[TPDO2NUMOFPARAMS];
Uint16 co_TPDO3_numOfBits[TPDO3NUMOFPARAMS];
Uint16 co_TPDO4_numOfBits[TPDO4NUMOFPARAMS];
Uint16 co_TPDO5_numOfBits[TPDO5NUMOFPARAMS];
Uint16 co_TPDO6_numOfBits[TPDO6NUMOFPARAMS];
Uint16 co_TPDO7_numOfBits[TPDO7NUMOFPARAMS];
Uint16 co_TPDO8_numOfBits[TPDO8NUMOFPARAMS];
//данные для работы с энергонезависимой памятью
T_UserMemoryContext UM;
Uint16 ParamRestorationError;
Uint16 co_requestCANInit;
Uint16 co_callbackTag; //передается в колбэк функции драйвера (соответствует 1 для 1го CAN и 2 для 2го CAN)
Uint32 ISRDroppingCounter;
//данные из coodedit-а
//Uint16 co_numOfInd;
int16* OD_TBL1;
Uint16* OD_TBL2;
int32* OD_TBL3;
Uint16* TYPE_DEF_TABLE;
int32* OD_CALLBACK_TBL;
Uint16 co_SPIrange1rw;
Uint16 co_SPIrange1rwCRC;
Uint16 co_SPIrange1rwp;
Uint16 co_SPIrange1rwpCRC;
Uint16 co_SPIrange1rwps;
Uint16 co_SPIrange1rwpsCRC;
Uint16 co_SPIrange2rw;
Uint16 co_SPIrange2rwCRC;
Uint16 co_SPIrange2rwp;
Uint16 co_SPIrange2rwpCRC;
Uint16 co_SPIrange2rwps;
Uint16 co_SPIrange2rwpsCRC;
Uint16 co_SPIrange3rw;
Uint16 co_SPIrange3rwCRC;
Uint16 co_SPIrange3rwp;
Uint16 co_SPIrange3rwpCRC;
Uint16 co_SPIrange3rwps;
Uint16 co_SPIrange3rwpsCRC;
Uint16 co_SPIrange4rw;
Uint16 co_SPIrange4rwCRC;
Uint16 co_SPIrange4rwp;
Uint16 co_SPIrange4rwpCRC;
Uint16 co_SPIrange4rwps;
Uint16 co_SPIrange4rwpsCRC;
Uint16 co_SPIrange5rw;
Uint16 co_SPIrange5rwCRC;
Uint16 co_SPIrange5rwp;
Uint16 co_SPIrange5rwpCRC;
Uint16 co_SPIrange5rwps;
Uint16 co_SPIrange5rwpsCRC;
Uint16 co_first1000;
Uint16 co_first2000;
Uint16 co_first3000;
Uint16 co_first4000;
Uint16 co_first5000;
//указатели для работы с регистрами и функциями, привязанными к аппаратной части
_CAN_Node_TypeDef* CAN_NODE_REGS;
CAN_TypeDef* CAN_REGS;
Uint16 CAN_NODE_MO_OFFSET;
Uint16 CAN_NODE_LIST;
Uint16 CAN_MO_ISR_LINE;
Uint16 CAN_NVIC_ISR_LINE;
void (*GpioInit)();
void (*CANINTDisable)();
void (*CANINTEnable)();
TBlockTransfer* BT; //указатель делаем чтоб легко инициализировать структуру TBlockTransfer
T_CANOPEN_DRV_SETTINGS settings;
};
typedef volatile struct SCo_OdVars TCo_OdVars;
extern TCo_OdVars co1_vars;
extern TCo_OdVars co2_vars;
extern TBlockTransfer CAN1BlockTransfer;
extern TBlockTransfer CAN2BlockTransfer;
//***************************************************************************************************************************************************
#ifdef __cplusplus
}
#endif
#endif
/*@}*/

78
Vinclude/cood1.h Normal file
View File

@ -0,0 +1,78 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file cood2.h
\brief Îáúÿâëÿåò íåêîòîðûå ñëóæåáíûå ïåðåìåííûå, ñîòîðûå äîëæíû áûòü îïðåäåëåíû â cood2.c
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 1.0 2017_01_25
@{
*/
#include "DSP.h"
//********************************************************************************************************
//ãëîáàëüíûå ïåðåìåííûå 1-ãî CAN-à
extern int16 const CO1_OD_TBL1[];
extern Uint16 const CO1_OD_TBL2[];
extern long const CO1_OD_TBL3[];
extern Uint16 const CO1_TYPE_DEF_TABLE[];
extern long const CO1_OD_CALLBACK_TBL[];
extern Uint16 const co1_first1000;
extern Uint16 const co1_first2000;
extern Uint16 const co1_first3000;
extern Uint16 const co1_first4000;
extern Uint16 const co1_first5000;
extern Uint16 const co1_SPIrange1rw;
extern Uint16 const co1_SPIrange1rwCRC;
extern Uint16 const co1_SPIrange1rwp;
extern Uint16 const co1_SPIrange1rwpCRC;
extern Uint16 const co1_SPIrange1rwps;
extern Uint16 const co1_SPIrange1rwpsCRC;
extern Uint16 const co1_SPIrange2rw;
extern Uint16 const co1_SPIrange2rwCRC;
extern Uint16 const co1_SPIrange2rwp;
extern Uint16 const co1_SPIrange2rwpCRC;
extern Uint16 const co1_SPIrange2rwps;
extern Uint16 const co1_SPIrange2rwpsCRC;
extern Uint16 const co1_SPIrange3rw;
extern Uint16 const co1_SPIrange3rwCRC;
extern Uint16 const co1_SPIrange3rwp;
extern Uint16 const co1_SPIrange3rwpCRC;
extern Uint16 const co1_SPIrange3rwps;
extern Uint16 const co1_SPIrange3rwpsCRC;
extern Uint16 const co1_SPIrange4rw;
extern Uint16 const co1_SPIrange4rwCRC;
extern Uint16 const co1_SPIrange4rwp;
extern Uint16 const co1_SPIrange4rwpCRC;
extern Uint16 const co1_SPIrange4rwps;
extern Uint16 const co1_SPIrange4rwpsCRC;
extern Uint16 const co1_SPIrange5rw;
extern Uint16 const co1_SPIrange5rwCRC;
extern Uint16 const co1_SPIrange5rwp;
extern Uint16 const co1_SPIrange5rwpCRC;
extern Uint16 const co1_SPIrange5rwps;
extern Uint16 const co1_SPIrange5rwpsCRC;
extern Uint16 const co1_numOfInd;
/*@}*/

78
Vinclude/cood2.h Normal file
View File

@ -0,0 +1,78 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file cood2.h
\brief Îáúÿâëÿåò íåêîòîðûå ñëóæåáíûå ïåðåìåííûå, ñîòîðûå äîëæíû áûòü îïðåäåëåíû â cood2.c
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 1.0 2017_01_25
@{
*/
#include "DSP.h"
//********************************************************************************************************
//ãëîáàëüíûå ïåðåìåííûå 2-ãî CAN-à
extern int16 const CO2_OD_TBL1[];
extern Uint16 const CO2_OD_TBL2[];
extern long const CO2_OD_TBL3[];
extern Uint16 const CO2_TYPE_DEF_TABLE[];
extern long const CO2_OD_CALLBACK_TBL[];
extern Uint16 const co2_first1000;
extern Uint16 const co2_first2000;
extern Uint16 const co2_first3000;
extern Uint16 const co2_first4000;
extern Uint16 const co2_first5000;
extern Uint16 const co2_SPIrange1rw;
extern Uint16 const co2_SPIrange1rwCRC;
extern Uint16 const co2_SPIrange1rwp;
extern Uint16 const co2_SPIrange1rwpCRC;
extern Uint16 const co2_SPIrange1rwps;
extern Uint16 const co2_SPIrange1rwpsCRC;
extern Uint16 const co2_SPIrange2rw;
extern Uint16 const co2_SPIrange2rwCRC;
extern Uint16 const co2_SPIrange2rwp;
extern Uint16 const co2_SPIrange2rwpCRC;
extern Uint16 const co2_SPIrange2rwps;
extern Uint16 const co2_SPIrange2rwpsCRC;
extern Uint16 const co2_SPIrange3rw;
extern Uint16 const co2_SPIrange3rwCRC;
extern Uint16 const co2_SPIrange3rwp;
extern Uint16 const co2_SPIrange3rwpCRC;
extern Uint16 const co2_SPIrange3rwps;
extern Uint16 const co2_SPIrange3rwpsCRC;
extern Uint16 const co2_SPIrange4rw;
extern Uint16 const co2_SPIrange4rwCRC;
extern Uint16 const co2_SPIrange4rwp;
extern Uint16 const co2_SPIrange4rwpCRC;
extern Uint16 const co2_SPIrange4rwps;
extern Uint16 const co2_SPIrange4rwpsCRC;
extern Uint16 const co2_SPIrange5rw;
extern Uint16 const co2_SPIrange5rwCRC;
extern Uint16 const co2_SPIrange5rwp;
extern Uint16 const co2_SPIrange5rwpCRC;
extern Uint16 const co2_SPIrange5rwps;
extern Uint16 const co2_SPIrange5rwpsCRC;
extern Uint16 const co2_numOfInd;
/*@}*/

74
Vinclude/filter.h Normal file
View File

@ -0,0 +1,74 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file filter.h
\brief Èíåðöèîííîå çâåíî â IQ ìàòåìàòèêå (ñì. TFilter)
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 2.0 25/03/2016
\defgroup filter Èíåðöèîííûé ôèëüòð (ñì. TFilter)
@{
*/
#ifndef FILTER_H
#define FILTER_H
#ifdef __cplusplus
extern "C"
{
#endif
/*! \class TFilter
\brief Èíåðöèîííîå çâåíî â IQ ìàòåìàòèêå
Êëàññ \a TFilter, îñíîâàííûé íà ñòðóêòóðå SFilter, ïðåäñòàâëÿåò èç ñåáÿ
èíåðöèîííîå çâåíî â òåðìèíàõ ÒÀÓ, à èìåííî W(p)=1/(Tfiltra*p+1).
Îáû÷íî îíî èñïîëüçóåòñÿ â êà÷åñòâå èíåðöèîííî ôèëüòðà, íà âõîä êîòîðîãî
ïîäàåòñÿ çàøóìëåííûé ñèãíàë, à íà âûõîäå îêàçûâàåòñÿ îòôèëüòðîâàííûé.*/
//! ñì. TFilter
struct SFilter
{
long input;//! Âõîä
long output;//! Âûõîä
long T; //! T=Ts/Tfiltra ãäå - Tfiltra ïîñòîÿííàÿ âðåìåíè ôèëüòðà
void (*calc)(volatile struct SFilter*);//óêàçàòåëü íà ôóíêöèþ ðàñ÷åòà
};
typedef volatile struct SFilter TFilter;
//! èíèöèàëèçàòîð ïî-óìîë÷àíèþ
#define FILTER_DEFAULTS {0,0,_IQ(0.01), \
TFilter_Calc}
//! \memberof TFilter
void TFilter_Calc(TFilter*);
#ifdef __cplusplus
}
#endif
#endif
/*@}*/

69
Vinclude/ipark.h Normal file
View File

@ -0,0 +1,69 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file ipark.h
\brief Ìîäóëü èíâåðñíûõ êîîðäèíàòíûõ ïðåîáðàçîâàíèé êîîðäèíàò (ñì. TIPark)
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 2.0 25/03/2016
\defgroup IPark Èíâåðñíûå êîîðäèíàòíûå ïðåîáðàçîâàíèÿ (ñì. TIPark)
@{
*/
#ifndef IPARK_H
#define IPARK_H
#ifdef __cplusplus
extern "C" {
#endif
/*! \class TIPark
\brief Èíâåðñíûå êîîðäèíàòíûå ïðåîáðàçîâàíèÿ
Êëàññ \a TIPark, îñíîâàííûé íà ñòðóêòóðå SIPark, îáåñïå÷èâàåò
ïîâîðîò âåêòîðà, çàäàííîãî â îðòîãîíàëüíûõ îñÿõ, íà òðåáóåìûé óãîë
ïîâîðîòà ang. Èíâåðñèÿ çàêëþ÷àåòñÿ â îáðàòíîì óãëå ïîâîðîòà ïî ñðàâíåíèþ
ñ ìîäóëåì TPark.*/
//! ñì. TIPark
struct SIPark{ _iq ds;//!< Output: stationary d-axis stator variable
_iq qs;//!< Output: stationary q-axis stator variable
_iq ang;//!< Input: rotating angle (pu)
_iq de;//!< Input: rotating d-axis stator variable
_iq qe;//!< Input: rotating q-axis stator variable
void (*calc)(struct SIPark*); //!< Pointer to calculation function
};
typedef struct SIPark TIPark;
//! èíèöèàëèçàòîð ïî-óìîë÷àíèþ
#define IPARK_DEFAULTS { 0, \
0, \
0, \
0, \
0, \
ipark_calc }
//! \memberof TIPark
void ipark_calc(TIPark*);
#ifdef __cplusplus
}
#endif
#endif
/*@}*/

192
Vinclude/main.h Normal file
View File

@ -0,0 +1,192 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file main.h
\brief Ãëàâíûé çàãîëîâî÷íûé ôàéë ïðîåêòà.
Ïîäêëþ÷àåò â ñåáå âñå çàãîëîâî÷íûå ôàéëû âñåõ ìîäóëåé,
Ñîäåðæèò îáúÿâëåíèÿ (extern) âñåõ íàèáîëåå âàæíûõ
ãëîáàëüíûõ ñòðóêòóð è ïåðåìåííûõ.
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 2.0 25/03/2016
\defgroup MAIN Ãëàâíûé ôàéë ïðîåêòà
@{*/
#ifndef MAIN_H
#define MAIN_H
#ifdef __cplusplus
extern "C" {
#endif
#include "DSP.h"
#include "build.h"
#include "V_common.h"
#include <stdlib.h> //äëÿ labs
#include "V_IQmath.h"
#include "SM_Sys.h"
#include "SM_Net.h"
#include "co_ODvars.h"
#include "CANOpen_drv.h"
#include "V_data_log.h"
#include "SM_Protect.h"
#include "V_bits_to_enum_numbers.h"
#include "SM_Ctrl.h"
#include "SM_CmdLogic.h"
#include "V_RTC_Clock.h"
#include "clarke.h"
#include "park.h"
#include "ipark.h"
#include "V_pid_reg3.h"
#include "V_pid_reg3_pos.h"
#include "V_rmp_ctrl.h"
#include "V_adc.h"
#include "V_PWM_Module.h"
#include "V_CurPar.h"
#include "V_hzprof.h"
#include "V_DPR_eCAP.h"
#include "V_QEP.h"
#include "V_led.h"
#include "V_AutoOffset.h"
#include "V_CANtoRS.h"
#include "V_SSI_Encoder.h"
#include "V_UserMemory.h"
#include "V_rotor_observer.h"
#include "V_relay_reg.h"
#include "DRV_INTERFACE.h"
#include "V_event_log.h"
#include "Global_time.h"
#include "V_fifo.h"
#include "V_usblib.h"
#include "V_watchdog.h"
extern TClarke clarke;
extern TPark park;
extern TIPark ipark;
extern TPidReg3 pid_id;
extern TPidReg3 pid_iq;
extern TPidReg3 pid_ia;
extern TPidReg3 pid_spd;
extern TPidReg3_pos pid_pos;
extern TSM_Sys sm_sys;
extern Uint16 disp_group_number;
extern TDataLog dlog;
extern TSM_Protect sm_prot;
extern TCmd cmd;
extern TDrvStatus drv_status;
extern TBitsToEnumNums pult_faults_lister;
extern TSM_Ctrl sm_ctrl;
extern TSM_CmdLogic sm_cmd_logic;
extern TRefs refs;
extern TSM_Net sm_net;
extern TRMPCtrl rmp;
extern TDrvParams drv_params;
extern TAdcDrv adc;
extern TPWM_Module pwm;
extern TCurPar cur_par;
extern TVhzProf vhz;
extern TDPReCAP DPReCAP;
extern TposspeedEqep posspeedEqep;
extern TRTCClock RTCclock;
extern TAutoOffset AutoOffset;
extern TSSI_Encoder SSI_Encoder;
extern TRotorObserver RotorObserver;
extern TCANtoRS CANtoRS;
extern TDrvInterface drv_interface;
extern TLogger FaultLog;
extern TGlobalTime global_time;
extern Uint16 msCounter;
extern Uint16 FastCounter;
extern Uint16 LoopCounter;
extern Uint16 TIsr10;
extern Uint16 TIsr1;
extern int drv_status_code;
extern Uint32 VendorToken;
volatile extern long Debug1;
volatile extern long Debug2;
volatile extern Uint16 Debug3;
volatile extern Uint16 Debug4;
volatile extern long DebugW1;
volatile extern long DebugW2;
volatile extern long DebugW3;
volatile extern long DebugW4;
volatile extern float DebugF1;
volatile extern float DebugF2;
volatile extern float DebugF3;
volatile extern float DebugF4;
//Ñ÷åò÷èêè ïðåðûâàíèé ìîäóëÿ çàõâàòà
extern Uint16 CounterCAP_isr;
extern Uint16 cap0_counter;
extern Uint16 cap1_counter;
extern Uint16 cap2_counter;
extern unsigned long CpuTimerIsr1;
extern TSysSwitches sw;
extern TUserMemory UserMem;
extern Tled leds;
//extern TCanBTInterface Can1BTInterface;
//extern TCanBTInterface Can2BTInterface;
extern TCANSpeedTableOptions canSpeedTable;
void callback_dlog(Uint16 par, Uint16 tag_CANnum);
void callback_RTC(Uint16 par, Uint16 tag_CANnum);
void propReset(void);
// Îáúÿâëåíèå ISR-îâ. Â CodeMaster-ñêîì è GCC-øíîì ñòàðòàïå îíè íàçèûâàþòñÿ ïî-ðàçíîìó
#if defined (__GNUC__)
void TIM1_IRQHandler(void);
void TIM0_IRQHandler(void);
void EPWM_TZ_0_IRQHandler(void);
void ECAP0_IRQHandler(void);
void ECAP1_IRQHandler(void);
void ECAP2_IRQHandler(void);
void EQEP1_IRQHandler(void);
#elif defined (__CMCPPARM__)
void TIM1_IRQHandler(void);
void TIM0_IRQHandler(void);
void PWM0_TZ_IRQHandler(void);
void CAP0_IRQHandler(void);
void CAP1_IRQHandler(void);
void CAP2_IRQHandler(void);
void QEP1_IRQHandler(void);
#endif
#if defined(TRUE) && (TRUE != 1)
#error "TRUE previously defined not equal to 1"
#endif
#if defined(FALSE) && (FALSE != 0)
#error "FALSE previously defined not equal to 0"
#endif
#ifndef TRUE
#define TRUE (1)
#endif
#ifndef FALSE
#define FALSE (0)
#endif
#ifdef __cplusplus
}
#endif
#endif
/*@}*/

44
Vinclude/mbod.h Normal file
View File

@ -0,0 +1,44 @@
/* Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
*/
#ifndef MBOD_H
#define MBOD_H
#include "DSP.h"
#define MB_VAR_WRITE 1 // ïðèçíàê çàïèñè â ModBus-ïåðåìåííóþ
#define MB_VAR_READ 2 // ïðèçíàê ÷òåíèÿ èç ModBus-ïåðåìåííîé
typedef struct
{
Uint16 index; // ModBus-àäðåñ
Uint16 type_or_acc; // íîìåð áèòà äëÿ áèòîâûõ ïåðåìåííûõ èëè ïðèçíàê çàïèñè/÷òåíèÿ
// äëÿ HR/IR-ïåðåìåííûõ (äîëæåí ñáðàñûâàòüñÿ ïîëüçîâàòåëåì):
// 1 - ïðîèçîøëà çàïèñü
// 2 - ïðîèçîøëî ÷òåíèå
Uint32 addr; // àäðåñ ïåðåìåííîé â êîíòðîëëåðå
} MB_Record;
extern volatile MB_Record mbodHR[];
extern volatile MB_Record mbodIR[];
extern volatile MB_Record mbodC[];
extern volatile MB_Record mbodDI[];
#endif

68
Vinclude/park.h Normal file
View File

@ -0,0 +1,68 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file park.h
\brief Ìîäóëü êîîðäèíàòíûõ ïðåîáðàçîâàíèé êîîðäèíàò (ñì. TPark)
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 2.0 25/03/2016
\defgroup Park Êîîðäèíàòíûå ïðåîáðàçîâàíèÿ (ñì. TPark)
@{
*/
#ifndef PARK_H
#define PARK_H
#ifdef __cplusplus
extern "C" {
#endif
#include "V_IQmath.h"
/*! \class TPark
\brief Êîîðäèíàòíûå ïðåîáðàçîâàíèÿ
Êëàññ \a TPark, îñíîâàííûé íà ñòðóêòóðå SPark, îáåñïå÷èâàåò
ïîâîðîò âåêòîðà (ds,qs), çàäàííîãî â îðòîãîíàëüíûõ îñÿõ, íà òðåáóåìûé óãîë
ïîâîðîòà ang. Âûõîäíîé ïîâåðíóòûé âåêòîð ñîõðàíÿåòñÿ â ïåðåìåííûõ de,qe. */
//! ñì. TPark
struct SPark{ _iq ds; //!< Input: stationary d-axis stator variable
_iq qs; //!< Input: stationary q-axis stator variable
_iq ang; //!< Input: rotating angle (pu)
_iq de; //!< Output: rotating d-axis stator variable
_iq qe; //!< Output: rotating q-axis stator variable
void (*calc)(struct SPark*);//!< Pointer to calculation function
};
typedef struct SPark TPark;
//! èíèöèàëèçàòîð ïî-óìîë÷àíèþ
#define PARK_DEFAULTS { 0, \
0, \
0, \
0, \
0, \
park_calc }
//! \memberof TPark
void park_calc(TPark*);
#ifdef __cplusplus
}
#endif
#endif
/*@}*/

400
Vsrc/CANOpenUDfuncs.c Normal file
View File

@ -0,0 +1,400 @@
/* ==================================================================================
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
//File name: CANOpenUDfuncs.c
//Description: Â ôàéë âûíåñåíû ôóíêöèè äðàéâåðà CANOpen îïðåäåëÿåìûå ïîëüçîâàòåëåì (êîëáýê ôóíêöèè, ôóíêöèè èíèöèàëèçàöèè è ò.ï.)
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 1.0 2017_02_08
//=====================================================================================*/
#include "DSP.h"
#include "co_ODvars.h"
#include "CANOpen_drv.h"
#include "main.h"
//! Òàáëèöà ñ íàñòðîéêàìè ñêîðîñòåé CAN äëÿ ìèêðîêîíòðîëëåðîâ ôèðìû ÍÈÈÝÒ. Ðàñêîììåíòèòü íóæíîå.
// Âíîñèòü èçìåíåíèß â íèæåîïèñàííûå ïåðåìåííûå è ìàññèâû ÇÀÏÐÅÙÅÍÎ!!!
//! Ìèêðîêîíòðîëëåð Ê1921ÂÊ01Ò
/*
// kb/s: 125 50 125 250 500 1000
TCANSpeedTableOptions canSpeedTable = { {1, 1, 1, 0, 0, 0 }, \
{9, 24, 9, 39, 19, 9 }, \
{6, 6, 6, 6, 6, 6 }, \
{1, 1, 1, 1, 1, 1 }, \
{1, 1, 1, 1, 1 , 1 }, \
};
// ^- íàñòðîéêà íà 125, ò.ê. 10 kb/s íå ðåàëèçóåìî
*/
//! Ìèêðîêîíòðîëëåð Ê1921ÂÊ028
/*
// kb/s: 125 50 125 250 500 1000
TCANSpeedTableOptions canSpeedTable = { {1, 1, 1, 1, 0, 0 }, \
{19, 49, 19, 9, 39, 19}, \
{6, 6, 6, 6, 6, 6 }, \
{1, 1, 1, 1, 1, 1 }, \
{1, 1, 1, 1, 1 , 1 }, \
};
// ^- íàñòðîéêà íà 125, ò.ê. 10 kb/s íå ðåàëèçóåìî
*/
//! Ìèêðîêîíòðîëëåð Ê1921ÂÊ035
// kb/s: 125 50 125 250 500 1000
TCANSpeedTableOptions canSpeedTable = { {1, 1, 1, 0, 0, 0 }, \
{9, 24, 9, 39, 19, 9 }, \
{6, 6, 6, 6, 6, 6 }, \
{1, 1, 1, 1, 1, 1 }, \
{1, 1, 1, 1, 1 , 1 }, \
};
// ^- íàñòðîéêà íà 125, ò.ê. 10 kb/s íå ðåàëèçóåìî
//**********************************************************************************************************************************************************************************************************
//ôóíêöèÿ èíèöèàëèçàöèè Gpio CAN1
#ifdef CAN_1_ENABLE
void co_CAN1GpioInit()
{
//ïåðåâîäèì ÃÏÈÎ íà âûïîëíåíèå ôóíêöèè CAN
GPIOB->ALTFUNCSET = (1 << 14) + (1 << 15); //CAN_TX[0], CAN_RX[0]
GPIOB->DENSET = (1 << 14) + (1 << 15);
}
#endif //CAN_1_ENABLE
//ôóíêöèÿ èíèöèàëèçàöèè Gpio CAN2
#ifdef CAN_2_ENABLE
void co_CAN2GpioInit()
{
// //âûáèðàåì àëüòåðíàòèâíóþ ôóíêöèþ ÃÏÈÎ
//#if defined HW_VECTOR_MK_40_4
// NT_COMMON_REG->GPIOPCTLC_bit.PIN1 = 1; //CAN_TX[1]
// NT_COMMON_REG->GPIOPCTLC_bit.PIN2 = 1; //CAN_RX[1]
//
// //ïåðåâîäèì ÃÏÈÎ íà âûïîëíåíèå ôóíêöèè CAN
// NT_GPIOC->ALTFUNCSET = (1 << 1) + (1 << 2); //CAN_TX[0], CAN_RX[0]
//
//#else
// NT_COMMON_REG->GPIOPCTLF_bit.PIN14 = 0; //CAN_TX[1]
// NT_COMMON_REG->GPIOPCTLF_bit.PIN15 = 0; //CAN_RX[1]
//
// //ïåðåâîäèì ÃÏÈÎ íà âûïîëíåíèå ôóíêöèè CAN
// NT_GPIOF->ALTFUNCSET = (1 << 14) + (1 << 15); //CAN_TX[0], CAN_RX[0]
//#endif
//
}
#endif //CAN_2_ENABLE
//**********************************************************************************************************************************************************************************************************
//Ôóíêöèè ðàáîòû ñ ýíåðãîíåçàâèñèìîé ïàìÿòüþ (â êà÷åñòâå ïàìÿòè ìîæåò èñïîëüçîâàòüñÿ êàê ïîëüçîâàòåëüñêàÿ ôëýø íà áîðòó MCU,
// òàê è âíåøíå ïîäêëþ÷àåìàÿ, íàïðèìåð ÷åðåç SPI, eeprom).
//Ôóíêöèè èñïîëüçóþòñÿ äðàéâåðîì CANopen ïðè ñîõðàíåíèè è âîññòàíîâëåíèè ïàðàìåòðîâ ñëîâàðÿ îáúåêòîâ
//Ñ òî÷êè çðåíèÿ äðàéâåðà CANOpen ôóíêöèè ðåàëèçóþò ïîáàéòîâîå ÷òåíèå è çàïèñü èç/â ÝíÎÇÓ
void co_UserMemoryRead (const T_UserMemoryContext *p)
{
// UserMem.MemStartAddr = p->MemStartAddr;
// UserMem.MCUStartAddr = p->MCUStartAddr;
// UserMem.data_length = p->data_length;
// UserMem.read(&UserMem);
}
void co_UserMemoryWrite (const T_UserMemoryContext *p)
{
// UserMem.MemStartAddr = p->MemStartAddr;
// UserMem.MCUStartAddr = p->MCUStartAddr;
// UserMem.data_length = p->data_length;
// UserMem.write(&UserMem);
}
//**********************************************************************************************************************************************************************************************************
//ôóíêöèÿ, êîòîðàÿ âûçûâàåòñÿ äðàéâåðîì CANOpen ïðè íåîáõîäèìîñòè îòïðàâêè CAN ñîîáùåíèÿ âî âíåøíèé èíòåðôåéñ
//âíóòðü ôóíêöèè ïîëüçîâàòåëåì äîëæåí áûòü âñòàâëåí âûçîâ ñîîòâåòñòâóþùåé ôóíêöèè, îñóùåñòâëÿþùåé ïåðåäà÷ó CAN ïàêåòà
void co_CANToExtInterface_Send(TZCanMsg* MSG, Uint16 tag_CANnum)
{
CANtoRS.write(MSG,&CANtoRS);
}
//êîëáýêè ïî ïðèåìó PDO
void co_RPDO1_Callback(Uint16 nodeID, Uint16 tag_CANnum)
{
/*
switch(nodeID)
{
case 1:
{
//îáðàáàòûâàåì êàê-íèáóäü...
break;
}
case 2:
{
PDO_cntr2++;
//îáðàáàòûâàåì êàê-íèáóäü...
break;
}
default:
break;
}
*/
}
void co_RPDO2_Callback(Uint16 nodeID, Uint16 tag_CANnum)
{
/*
switch(nodeID)
{
case 1:
{
//îáðàáàòûâàåì êàê-íèáóäü...
break;
}
default:
break;
}
*/
}
void co_RPDO3_Callback(Uint16 nodeID, Uint16 tag_CANnum)
{
/*
switch(nodeID)
{
case 1:
{
//îáðàáàòûâàåì êàê-íèáóäü...
break;
}
default:
break;
}
*/
}
void co_RPDO4_Callback(Uint16 nodeID, Uint16 tag_CANnum)
{
/*
switch(nodeID)
{
case 1:
{
//îáðàáàòûâàåì êàê-íèáóäü...
break;
}
default:
break;
}
*/
}
void co_RPDO5_Callback(Uint16 nodeID, Uint16 tag_CANnum)
{
/*
switch(nodeID)
{
case 1:
{
//îáðàáàòûâàåì êàê-íèáóäü...
break;
}
default:
break;
}
*/
}
void co_RPDO6_Callback(Uint16 nodeID, Uint16 tag_CANnum)
{
/*
switch(nodeID)
{
case 1:
{
//îáðàáàòûâàåì êàê-íèáóäü...
break;
}
default:
break;
}
*/
}
void co_RPDO7_Callback(Uint16 nodeID, Uint16 tag_CANnum)
{
/*
switch(nodeID)
{
case 1:
{
//îáðàáàòûâàåì êàê-íèáóäü...
break;
}
default:
break;
}
*/
}
void co_RPDO8_Callback(Uint16 nodeID, Uint16 tag_CANnum)
{
/*
switch(nodeID)
{
case 1:
{
//îáðàáàòûâàåì êàê-íèáóäü...
break;
}
default:
break;
}
*/
}
//!Îáðàùåíèå ïî CANopen ê ÷àñàì ðåàëüíîãî âðåìåíè.
//!Åñëè ïðîèñõîäèò çàïèñü â ïàðàìåòð [5139h.01h] Òåêóù. çíà÷.×àñû ðåàëüíîãî âðåìåíè,
//òî âûçûâàåòñÿ callback_RTC - òàì óñòàíàâëèâàåòñÿ çàïðîñ íà êîððåêöèþ ÷àñîâ.
void callback_RTC(Uint16 par, Uint16 tag_CANnum) {
if (par == 1) {
RTCclock.setTimeFlag = 1; //ïðîèçîøëà çàïèñü â ÷àñû
}
}
//!Îáðàùåíèå ê ïåðåìåííîé dlog.next_value_var ñ äàííûìè öèôðîâîãî îñöèëëîãðàôà.
//!Ñóùåñòâóåò ñïåöèàëüíûé èíòåðôåéñ, ïîçâîëÿþùèé àâòîìàòèçèðîâàòü ñ÷èòûâàíèå îññöèëëîãðàôèðóåìûõ ïåðåìåííûõ
//!ìîäóëÿ TDataLog. Ýòà ôóíêöèÿ âûçûâàåòñÿ ïðè îáðàùåíèè ê ïåðåìåííîé, ÷åðåç êîòîðóþ âîçìîæíî ñ÷èòàòü çàïèñàííûå
//!îñöèëëîãðàììû. Çàïèñü â ýòó ïåðåìåííóþ óñòàíàâëèâàåò òðåáóåìûé íîìåð áóôåðà (îäèí è 4õ) è íîìåð èçâëåêàåìîé òî÷êè.
//!Ïðè ÷òåíèè æå â ýòó ïåðåìåííóþ âûäâèãàòþòñÿ ñàìè îòîñöèëëîãðàôôèðîâàííûå äàííûå.
void callback_dlog(Uint16 par, Uint16 tag_CANnum) {
//åñëè çàïèñü, òî óñòàíîâèì áóôåð íà íóæíóþ òî÷êó
if (par == 1) {
//â ïåðåìåííóþ next_value_var çàïèñûâàåòñß æåëàåìîå ñìåùåíèå, íîìåð áóôåðà, èç êîòîðîãî õîòèì ÷èòàòü,
//à òàê æå ðàçðåæèâàíèå
dlog.buff_num = (long)((dlog.next_value_var >> 24) & 3); //èçâëåêàåòñß íîìåð áóôåðà
#if DLOG_DATA_SIZE == 32
dlog.highPartOfValue = (int)((dlog.next_value_var >> 26) & 1); // îòäàâàòü ñòàðøóþ ÷àñòü 32-áèòíîãî çíà÷åíèÿ?
#endif
dlog.Rcounter = (dlog.next_value_var >> 16) & 0xFF; //êàêóþ òî÷êó íàäî îòäàâàòü
// //ïðîâåðßåì õîòßò ëè èñïîëüçîâàòü áëî÷íóþ ïåðåäà÷ó
// if ((dlog.next_value_var & 0xffff) == 1) {
// //õîòßò, ãîâîðèì îá ýòîì èíòåðôåéñó áëî÷íîé ïåðåäà÷è
//#ifdef CAN_1_ENABLE
// if (co1_vars.co_blockTransferCommand == CANBT_INTERFACE_FREE)
// co1_vars.co_blockTransferCommand = CANBT_INTERFACE_DATALOG1;
//#endif
//#ifdef CAN_2_ENABLE
// if (co2_vars.co_blockTransferCommand == CANBT_INTERFACE_FREE)
// co2_vars.co_blockTransferCommand = CANBT_INTERFACE_DATALOG1;
//#endif
// }
//#if DLOG_DATA_SIZE == 32
// if ((dlog.next_value_var & 0xffff) == 2) {
//#ifdef CAN_1_ENABLE
// if (co1_vars.co_blockTransferCommand == CANBT_INTERFACE_FREE)
// co1_vars.co_blockTransferCommand = CANBT_INTERFACE_DATALOG2;
//#endif
//#ifdef CAN_2_ENABLE
// if (co2_vars.co_blockTransferCommand == CANBT_INTERFACE_FREE)
// co2_vars.co_blockTransferCommand = CANBT_INTERFACE_DATALOG2;
//#endif
// }
//#endif // DLOG_DATA_SIZE == 32
}
//âûäâèãàåì äàííûå:
#if DLOG_DATA_SIZE == 16
switch (dlog.buff_num) { //òåêóùèé íîìåð áóôåðà
case 0: {
dlog.next_value_var = dlog.dl_buffer1_adr[(dlog.Rcounter + dlog.first_point_written) & 0xFF];
break;
}
case 1: {
dlog.next_value_var = dlog.dl_buffer2_adr[(dlog.Rcounter + dlog.first_point_written) & 0xFF];
break;
}
case 2: {
dlog.next_value_var = dlog.dl_buffer3_adr[(dlog.Rcounter + dlog.first_point_written) & 0xFF];
break;
}
case 3: {
dlog.next_value_var = dlog.dl_buffer4_adr[(dlog.Rcounter + dlog.first_point_written) & 0xFF];
break;
}
default: { //åñëè â buff_num ÷òî-òî íå òî, ïî-äåôîëòó ïóñòü ïåðâûé áóôåð
dlog.next_value_var = dlog.dl_buffer1_adr[(dlog.Rcounter + dlog.first_point_written) & 0xFF];
break;
}
}
//äàííûå òîëüêî â íèæíåé ÷àñòè
dlog.next_value_var &= 0xFFFF;
dlog.next_value_var |= (((unsigned long) dlog.Rcounter) << 16); //â âåðõíåé ÷àñòè ñëîâà Rcounter äëß êîíòðîëß
dlog.next_value_var |= (((unsigned long) dlog.buff_num) << 24); //â âåðõíåé ÷àñòè ñëîâà (åùå âûøå) buff_num äëß êîíòðîëß
dlog.Rcounter++; //êàêóþ òî÷êó îòäàåì. èíêðåìåíòèðóåòñß ñàìî ïîñëå ÷òåíèß òåêóùåé òî÷êè.
dlog.Rcounter &= 0xFF; //ïî êðóãó. íè÷åãî ñòðàøíîãî, ïåðåä ÷òåíèåì îáíóëßþ. ñì. çàïèñü
#endif
#if DLOG_DATA_SIZE == 32
int32 val32;
int varSizeIs16;
switch (dlog.buff_num) { //òåêóùèé íîìåð áóôåðà
default:
case 0: {
val32 = dlog.dl_buffer1_adr[(dlog.Rcounter + dlog.first_point_written) & 0xFF];
varSizeIs16 = (int)(dlog.object1Info.varSize == 16);
break;
}
case 1: {
val32 = dlog.dl_buffer2_adr[(dlog.Rcounter + dlog.first_point_written) & 0xFF];
varSizeIs16 = (int)(dlog.object2Info.varSize == 16);
break;
}
case 2: {
val32 = dlog.dl_buffer3_adr[(dlog.Rcounter + dlog.first_point_written) & 0xFF];
varSizeIs16 = (int)(dlog.object3Info.varSize == 16);
break;
}
case 3: {
val32 = dlog.dl_buffer4_adr[(dlog.Rcounter + dlog.first_point_written) & 0xFF];
varSizeIs16 = (int)(dlog.object4Info.varSize == 16);
break;
}
}
dlog.next_value_var = (dlog.highPartOfValue != 0 ? val32 >> 16 : val32) & 0x0000FFFF;
dlog.next_value_var |= ((Uint32)dlog.Rcounter) << 16;
dlog.next_value_var |= ((Uint32)dlog.buff_num) << 24;
dlog.next_value_var |= ((Uint32)dlog.highPartOfValue) << 26;
dlog.next_value_var |= ((Uint32)varSizeIs16) << 27;
if ((dlog.highPartOfValue != 0) || varSizeIs16)
{
// Ïðè ñëåäóþùåì çàïðîñå îòäàäèì ìëàäøóþ ÷àñòü ñëåäóþùåé òî÷êè.
dlog.Rcounter++;
dlog.Rcounter &= 0xFF;
dlog.highPartOfValue = 0;
}
else
{
// Ïðè ñëåäóþùåì çàïðîñå îòäàäèì ñòàðøóþ ÷àñòü ýòîé æå òî÷êè.
dlog.highPartOfValue = 1;
}
#endif
}

108
Vsrc/DRV_INTERFACE.c Normal file
View File

@ -0,0 +1,108 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file DRV_INTERFACE.c
\brief ×åðåç äàííûå ìîäóëü îáåñïå÷èâàåòñß ðàáîòà ñ áàíêîì àâàðèé (÷òåíèå, î÷èñòêà).
//Ïðåäïîëàãàåòñß, ÷òî ìîäóëü ìîæåò ðàñøèðßòü ôóíêöèîíàëüíîñòü (ñêà÷èâàòü êàèå-òî äðóãèå äàííûå)...
//ÏÐÈÌÅ×ÀÍÈÅ äëÿ ïðîãðàììèñòà:
1.äëÿ êîìàíä ðàáîòàþùèõ ïî ñåòè ñ àâòîìàòèçèðîâàííûìè ñèñòåìàìè (Þíèêîí,, ïóëüòû è ò.ä.) ïîñëå âûïîëíåíèÿ êîìàíäû ïîëå ans_data äîëæíî áûòü óñòàíîâëåíî çíà÷åíèåì çàïðîñà:
p->ans_data = temp;
÷òî ñîîáùèò âíåøíåé ñèñòåìå, ÷òî çàïðîñ îáðàáîòàí.  ýòîì ñëó÷àå ïîëå p->ans_data îáíóëÿåòñÿ âíåøíåé àâòîìàòèçèðîâàííîé ñèñòåìîé ïîñëå ñáîðà èíôîðìàöèè ñ ïîëåé
p->data_Low
p->data_High
2.äëÿ âíóòðåííèõ âûçîâîâ ïîëå p->ans_data òðîãàòü íå íóæíî
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 2.1 2017_07_24
*/
#include "main.h"
void DRV_INTERFACE_Calc(TDrvInterface *p) {
TEvent event;
long temp = (p->req_data); //ïðèíßòèå çàïðîñà
p->INTERFACE_delta_time_sec = global_time.relative_time1.second_counter - p->INTERFACE_time_sec;
// ïðîâåðêà "óõîäà" îòâåòà
if ((p->ans_data != 0) && (p->INTERFACE_delta_time_sec < DRV_INTERFACE_RESET_TIME))
return;
//ðàç ñþäà ïîïàëè çíà÷èò ëèáî òàéìàóò äëß àíñà èñòåê, ëèáî îí íóëåâîé
//â ëþáîì ñëó÷àå åãî îáíóëßåì
p->ans_data = 0;
//çàïðîñ îáíóëßåì òîëüêî ïîñëå âûïîëíåíèß, ÷òîáû âíåøíèå óñòðîéñòâà ìîãëè êîíòðîëèòü âûïîëíåíèå çàïðîñà
switch ((temp) >> 16)
{
case DATA_REQUEST_READ_FAULT: //çàïðîñ íà ÷òåíèå îøèáêè
{
FaultLog.read(&FaultLog, (temp & 0x0FFFF), &event);
//ôîðìèðóåì îòâåò
p->data_Low = (((Uint32) (event.ev_num)) << 16) + event.ev_code;
p->data_High = event.ev_time;
p->ans_data = temp; //ãîâîðèì Þíèêîíó, ÷òî êîìàíäà îáðàáîòàíà
//ôèêñèðóåì âðåìß îòâåòà
p->INTERFACE_time_sec = global_time.relative_time1.second_counter;
break;
}
case DATA_REQUEST_WRITE_FAULT: //çàïðîñ íà çàïèñü îøèáêè
{
//!!!
//ïîêà ÷åðåç èíòåðôåéñ ïèñàòü îøèáêó íåëüçß
break;
}
case DATA_REQUEST_WRITE_WORK_TIME: //çàïðîñ íà çàïèñü work_time
{
global_time.relative_time1.relative_date.hour = 0;
global_time.relative_time1.relative_date.minute = 0;
global_time.WtiteSPI_flag = 1;
break;
}
case DATA_REQUEST_READ_WORK_TIME: //çàïðîñ íà ÷òåíèå work_time
{
//Ma][: Áó!
break;
}
case DATA_REQUEST_WRITE_OPER_TIME: { //çàïðîñ íà çàïèñü oper_time
global_time.relative_time2.relative_date.hour = 0;
global_time.relative_time2.relative_date.minute = 0;
global_time.WtiteSPI_flag = 1;
break;
}
case DATA_REQUEST_READ_OPER_TIME: //çàïðîñ íà ÷òåíèå îøèáêè
{
//Ma][: Áó!
break;
}
case DATA_REQUEST_CLEAR_ALL: //çàïðîñ íà î÷èñòêó áàíêà àâàðèé
{
FaultLog.clear(&FaultLog);
//ôîðìèðóåì îòâåò
p->data_High = 0;
p->data_Low = 0;
p->ans_data = temp; //ãîâîðèì Þíèêîíó, ÷òî êîìàíäà îáðàáîòàíà
//ôèêñèðóåì âðåìß îòâåòà
p->INTERFACE_time_sec = global_time.relative_time1.second_counter;
break;
}
}
p->req_data = 0;//îáíóëßåì ïîëå çàïðîñà, ÷òîáû íå âûïîëíèòü åãî ïîâòîðíî
}

109
Vsrc/SM_CmdLogic.c Normal file
View File

@ -0,0 +1,109 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file SMCmdLogic.c
\brief Îáðàáîòêà êîìàíä è çàäàíèé, ïîñòóïàþùèõ èç ðàçëè÷íûõ èñòî÷íèêîâ. (ñì. TSM_CmdLogic)
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 2.0 25/03/2016
\addtogroup SMCmdLogic
@{*/
#include "DSP.h"
#include "V_IQmath.h"
#include "main.h"
//!Èíèöèàëèçàöèÿ
//!Âñÿêèå îáíóëåíèÿ...
//! \memberof TSM_CmdLogic
void SM_CmdLogicInit(TSM_CmdLogic *p) {
p->state = 0;
p->state_prev = 0xFF;
cmd.all = 0;
}
//!Ìåäëåííûé ðàñ÷åò
//! \memberof TSM_CmdLogic
void SM_CmdLogicSlow_Calc(TSM_CmdLogic *p) {
}
//!1êÃö ðàñ÷åò
//!Îáðàáîòêà ðàçëè÷íûõ èñòî÷íèêîâ êîìàíä è ðàñ÷åò ÄÀ,
//!êîòîðûé ïåðåêëþ÷àåò ãëîáàëüíî ðåæèìû ÐÀÁÎÒÀ è ÎÑÒÀÍÎÂ.
//! \memberof TSM_CmdLogic
void SM_CmdLogicms_Calc(TSM_CmdLogic *p) {
//Ñòàíäàðòíàÿ îáðàáîòêà äèñêðåòíîãî àâòîìàòà
if (p->state_prev != p->state)
p->E = 1;
else
p->E = 0;
p->state_prev = p->state;
//îïðåäåëÿåì ðåæèì ðàáîòû
switch (p->state) {
case CMD_LOGIC_TURNED_OFF: { //ñîñòîÿíèå 0- ÎÒÊËÞ×ÅÍ
if (p->E == 1) {
/*ENTRY*/
sm_ctrl.state = CTRL_STOP;
drv_status.bit.ready = 1;
drv_status.bit.running = 0;
}
if (sm_prot.state == PROT_ON_OK) {//åñëè ÄÀ çàùèò âêëþ÷èëñÿ, îáðàáàòûâàåì êîìàíäû âêëþ÷åíèÿ
if ((cmd.bit.start == 1) && (sm_sys.state == SYS_READY))//åñòü áèòîâàÿ êîìàíäà ñòàðòà
p->state = CMD_LOGIC_TURNED_ON; //ïîåõàëè
}
//äèñêðåòíûé àâòîìàò ñî ñòðóêòóðàìè óïðàâëåíèÿ â ÑÒÎÏå âñåãäà òîæå ïðèíóäèòåëüíî ïåðåâîäèì â ñòîï
sm_ctrl.state = CTRL_STOP;
//âñåãäà ñáðàñûâàåì áèòîâûå êîìàíäû óïðàâëåíèÿ
cmd.bit.stop = 0;
cmd.bit.start = 0;
break;
}
case CMD_LOGIC_TURNED_ON: { //ñîñòîÿíèå - ÐÀÁÎÒÀ
if (p->E == 1) {
/*ENTRY*/
drv_status.bit.ready = 1;
drv_status.bit.running = 1;
sm_ctrl.state = CTRL_RUN;//ïîåõàëè
}
//åñëè ÀÂÀÐÈÿ èëè ÊÎÌÀÍÄÀ ÑÒÎÏ òî ñîñòîÿíèå ñòîï
if ((sm_prot.state == PROT_FAIL) || (cmd.bit.stop == 1)
|| (sm_ctrl.state == CTRL_STOP)){
p->state = CMD_LOGIC_TURNED_OFF;
}
//âñåãäà ñáðàñûâàåì êîìàíäó óïðàâëåíèÿ
cmd.bit.stop = 0;
cmd.bit.start = 0;
break;
}
default:
break;
} // êîíåö switch(p->state)
}
/*@}*/

783
Vsrc/SM_Ctrl.c Normal file
View File

@ -0,0 +1,783 @@
/*!
Copyright 2017 АО "НИИЭТ" и ООО "НПФ ВЕКТОР"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file SMCtrl.c
\brief Основной ДА переключения систем управления (см. TSM_Ctrl)
\author ООО "НПФ Вектор". http://motorcontrol.ru
\version v 2.0 25/03/2016
*/
/** \addtogroup SMCtrl */
/*@{*/
#include "DSP.h"
#include "V_IQmath.h"
#include "main.h"
//!Инициализация
//!Всякие обнуления
//! \memberof TSM_Ctrl
void SM_Ctrl_Init(TSM_Ctrl *p) {
p->state_prev = 0xff;
p->state = 0x00;
}
//!Фоновый расчет
//! \memberof TSM_Ctrl
void SM_Ctrl_Slow_Calc(TSM_Ctrl *p) {
}
//!Миллисекундный расчет
//! \memberof TSM_Ctrl
void SM_Ctrl_ms_Calc(TSM_Ctrl *p) {
}
//!Быстрый расчет
//!Реализует все структуры управления (режимы работы), такие как
//!Векторное управление, скалярное, режим постоянного тока и т.п.
//!Здесь реализован основной ДА переключения систем управления.
//!Кроме того, происходит расчет некоторых вспомогательных модулей.
//!Можно сказать, здесь находится "ядро" всей системы управления,
//!и именно в этой функции происходит непосредственное управление двигателем с
//!использованием всех остальных модулей.
//! \memberof TSM_Ctrl
void SM_Ctrl_Fast_Calc(TSM_Ctrl *p) {
//если система находится в перееинициализации,
//то пропускаем контур управления
if (sm_sys.state == SYS_INIT) {
return;
}
//если команда остановить, то переходим
//в режим ОСТАНОВЛЕН
if (cmd.bit.stop == 1)
p->state = CTRL_STOP;
// если есть авария, то переходим в стоп
if (sm_prot.state == PROT_FAIL)
p->state = CTRL_STOP;
//считаем дискретный автомат
if (p->state_prev != p->state)
p->E = 1;
else
p->E = 0;
//нужно для дискретного автомата, определение
//первого вхождения
p->state_prev = p->state;
switch (p->state) {
case CTRL_STOP: { //Состояние ОСТАНОВ
if (p->E == 1) { //Если первое вхождение в состояние
cmd.bit.start = 0;
DPReCAP.speed = 0;
DPReCAP.Ts = 0;
DPReCAP.Tspeed = 0;
global_time.WtiteSPI_flag = 1; //записать времЯ работы
//при переходе в стоп и работающем
//осциллографе переводим его в режим
//однократной записи, чтобы зафиксир. возможную аварию.
if (dlog.StartBits & (1 << 8)) //Если пользователь задал этот бит
dlog.set_mode(1, &dlog); //запускаем осциллограф по этому событию
if (sm_prot.state==PROT_FAIL)//если мы перешли в стоп, а модуль защит в аварии
if (dlog.mode_reset==2)//и даталоггер крутился
dlog.mode_reset=1;//то остановим осц, пусть будет осца аварии
}
pwm.Off(&pwm); //Выкл ШИМ
// refs.theta_elec=0;
//Обнуление всего опасного
pwm.UalphaRef = 0;
pwm.UbetaRef = 0;
pwm.update(&pwm);
pid_id.reset(&pid_id);
pid_iq.reset(&pid_iq);
pid_ia.reset(&pid_ia);
pid_spd.reset(&pid_spd);
pid_pos.reset(&pid_pos);
cur_par.Is = 0;
cur_par.power = 0;
cur_par.speed = 0;
// cur_par.ThetaRefCurr=0;
/* Конец */
break;
}
case CTRL_RUN: { //Состояние запуска
if (p->E == 1) {
/*ENTRY START*/
drv_status.bit.running = 1;
pwm.On(&pwm);//Включение модуля ШИМ
p->ctrl_counter = 0;
if (dlog.StartBits & (1 << 0)) //Если пользователь задал этот бит
dlog.set_mode(1, &dlog); //запускаем осциллограф по этому событию
/*ENTRY END*/
}
/*DO START*/
p->ctrl_counter++;
if (p->run_mode == CTRL_RUN_U2F) {//скалярный режим
p->state = CTRL_RUN_U2F;
}
if (p->run_mode == CTRL_FLUXING) {//режим удержания (постоянный ток)
p->state = CTRL_FLUXING;
}
if (p->run_mode == CTRL_RUN_I2F) {//частотно-токовый режим (вращение вектора тока)
p->state = CTRL_RUN_I2F;
}
if (p->run_mode == CTRL_RUN_VECTOR_SM) {//векторная СУ синхронной машины с двумя контурами
p->state = CTRL_RUN_VECTOR_SM;
}
if (p->run_mode == CTRL_RUN_VECTOR_SM_ENCODER_POS) {//векторная СУ синхронной машины с обратной связью по энкодеру и контуром положения
p->state = CTRL_RUN_VECTOR_SM_ENCODER_POS;
}
if (p->run_mode == CTRL_RUN_VECTOR_IM_ENCODER) {//векторная СУ синхронной машины с обратной связью по энкодеру и контуром положения
p->state = CTRL_RUN_VECTOR_IM_ENCODER;
}
if (p->run_mode == CTRL_AUTO_SENSOR_TUNING) {//автоматическая настройка смещений в ДПР (частотно-токовая+доп. логика)
p->state = CTRL_AUTO_SENSOR_TUNING;
}
if (p->run_mode == CTRL_RUN_LATENCY_TEST) { // Режим измерения задержки между ШИМ и датчиками тока
p->state = CTRL_RUN_LATENCY_TEST;
}
/*DO END*/
break;
}
case CTRL_FLUXING: { //Режим постоянный ток
if (p->E == 1) {
/*ENTRY START*/
pwm.On(&pwm);
pid_id.ui_reg3 = 0; //сбрасывем интегральные каналы
pid_iq.ui_reg3 = 0; //чтобы не накапливались
pid_spd.ui_reg3 = 0;
refs.theta_elec = 0;//заданный угол - 0. Но он есть в группе Задания, его можно менять на ходу!
if (dlog.StartBits & (1 << 1))
dlog.set_mode(1, &dlog);
/*ENTRY END*/
}
/*DO START*/
//два тока фаз из АЦП в модуль фазных преобразований
clarke.as = adc.Imeas_a;
clarke.bs = adc.Imeas_b;
clarke.calc(&clarke);//расчет
//из фазных преобразований в координатные преобразования.
//Поворачиваем вектор на заданный угол refs.theta_elec
park.ds = clarke.ds;
park.qs = clarke.qs;
park.ang = refs.theta_elec;
park.calc(&park);
//регулятор тока "как бы" оси d (на самом деле эта ось к двигателю к оси d не привязана, это свободная ось)
pid_id.pid_ref_reg3 = refs.i_flux_ref; //задание на ток намагничивания
pid_id.pid_fdb_reg3 = park.de;//обратная связь - то что пришло с фазных преобразований
pid_id.calc(&pid_id);
//регулятор тока "как бы" оси q (на самом деле эта ось к двигателю к оси q не привязана, это свободная ось)
pid_iq.pid_ref_reg3 = 0;//задание - ноль
pid_iq.pid_fdb_reg3 = park.qe;park.de;//обратная связь - то что пришло с фазных преобразований
pid_iq.calc(&pid_iq);
//обратные фазные преобразования.
//Крутим вектор напряжения, который выдают регуляторы токов обратно на угол refs.theta_elec
ipark.de = pid_id.pid_out_reg3;
ipark.qe = pid_iq.pid_out_reg3;
ipark.ang = refs.theta_elec;
ipark.calc(&ipark);
//получившиеся задания напряжения по осям альфа и бета отправляем на модуль ШИМ
pwm.UalphaRef = ipark.ds;
pwm.UbetaRef = ipark.qs;
pwm.update(&pwm);
//в наблюдаемые переменные - текущий амплитудный ток в статоре (обратная связь регулятора d)
cur_par.Is = pid_id.pid_fdb_reg3;
break;
}
case CTRL_RUN_U2F: { //Режим скалярное управление U(f)
if (p->E == 1) {
/*ENTRY START*/
pwm.On(&pwm);
rmp.output = 0;
if (dlog.StartBits & (1 << 2)) //Если пользователь задал этот бит осциллографирования
dlog.set_mode(1, &dlog); //запускаем осциллограф по этому событию
/*ENTRY END*/
}
/*DO START*/
//задание скорости на вход задатчика интенсивности
rmp.input = refs.speed_ref;
rmp.calc(&rmp);//расчет задатчика
cur_par.speed = rmp.output; //скорость (частоту вращения) показываем в налюдаемых параметрах, которая задана
//угол refs.theta_elec - интеграл от скорости rmp.output.
//Константа FAST_CALC_TS - период дискретизации
//drv_params.freq_nom номинальная частота (базовый параметр частоты для относительных единиц измерения)
refs.theta_elec += _IQmpy(_IQmpyI32(drv_params.freq_nom,FAST_CALC_TS),
rmp.output);
refs.theta_elec &= 0x00FFFFFF; //отсечение лишней верхней части, если угол больше единицы в IQ (360 градусов)
//на вход кривой U/f подается текущая скорость (частота)
vhz.freq = rmp.output;
vhz.calc(&vhz);
//в модуль координатных преоразований подаем заданную амплитуду напряжения vhz.vout с модуля U/f
//Используем фазные преобразования как "крутилку" вектора напряжения
ipark.de = vhz.vout;
ipark.qe = 0;
ipark.ang = refs.theta_elec;
ipark.calc(&ipark);
//получившиеся задания напряжения по осям альфа и бета отправляем на модуль ШИМ
pwm.UalphaRef = ipark.ds;
pwm.UbetaRef = ipark.qs;
pwm.update(&pwm);
/*DO END*/
break;
}
case CTRL_RUN_I2F: { //Режим частотно-токового управления - вращающийся вектор тока.
if (p->E == 1) {
/*ENTRY START*/
pid_id.ui_reg3 = 0; //сбрасывем интегральные каналы
pid_iq.ui_reg3 = 0; //чтобы не накапливались
pid_spd.ui_reg3 = 0;
pid_id.pid_ref_reg3 = 0;
pid_iq.pid_ref_reg3 = 0;
pwm.On(&pwm);//влючение ШИМ
rmp.output = 0;
if (dlog.StartBits & (1 << 3))
dlog.set_mode(1, &dlog);
/*ENTRY END*/
}
/*DO START*/
{
//два тока фаз из АЦП в модуль фазных преобразований
clarke.as = adc.Imeas_a;
clarke.bs = adc.Imeas_b;
clarke.calc(&clarke);
//текущий вектор тока - в наблюдаемые параметры (чтобы на него смотреть)
cur_par.Ialpha = clarke.ds;
cur_par.Ibeta = clarke.qs;
//задание скорости на вход задатчика интенсивности
rmp.input = refs.speed_ref;
rmp.calc(&rmp);//расчет задатчика
//угол refs.theta_elec - интеграл от скорости rmp.output.
//Константа FAST_CALC_TS - период дискретизации
//drv_params.freq_nom номинальная частота (базовый параметр частоты для относительных единиц измерения)
refs.theta_elec += _IQmpy(
_IQmpyI32(drv_params.freq_nom,FAST_CALC_TS), rmp.output);
cur_par.ThetaRefCurr = refs.theta_elec;
refs.theta_elec &= 0x00FFFFFF;//отсечение лишней верхней части, если угол больше единицы в IQ (360 градусов)
//текущий угол с датчика положения, переведенный в электрический из механического
//cur_par.ThetaCurr = posspeedEqep.theta_elecContinouos;
//Текущий угол - заданный угол
cur_par.ThetaCurr = refs.theta_elec;
//из фазных преобразований в координатные преобразования.
//Поворачиваем вектор на заданный угол refs.theta_elec
park.ds = clarke.ds;
park.qs = clarke.qs;
park.ang = refs.theta_elec;
park.calc(&park);
//регулятор тока "как бы" оси d (на самом деле эта ось к двигателю к оси d не привязана, это свободная ось)
pid_id.pid_ref_reg3 = refs.i_flux_ref;
pid_id.pid_fdb_reg3 = park.de;
pid_id.calc(&pid_id);
//регулятор тока "как бы" оси q (на самом деле эта ось к двигателю к оси q не привязана, это свободная ось)
pid_iq.pid_ref_reg3 = 0;
pid_iq.pid_fdb_reg3 = park.qe;
pid_iq.calc(&pid_iq);
//обратные фазные преобразования.
//Крутим вектор напряжения, который выдают регуляторы токов обратно на угол refs.theta_elec
ipark.de = pid_id.pid_out_reg3;
ipark.qe = pid_iq.pid_out_reg3;
ipark.ang = refs.theta_elec;
ipark.calc(&ipark);
//получившиеся задания напряжения по осям альфа и бета отправляем на модуль ШИМ
pwm.UalphaRef = ipark.ds;
pwm.UbetaRef = ipark.qs;
pwm.update(&pwm);
//в наблюдаемые переменные - текущий амплитудный ток в статоре (обратная связь регулятора d)
cur_par.Is = pid_id.pid_fdb_reg3;
//и текущую частоту (скорость)
cur_par.speed = rmp.output;
/*DO END*/
}
break;
}
case CTRL_RUN_VECTOR_SM: { //Датчиковая СУ для синхронной машины
if (p->E == 1) {
/*ENTRY START*/
pwm.On(&pwm); //Включение ШИМ
rmp.output = 0; //Обнуление задатчика интенсивности
if (dlog.StartBits & (1 << 4)) //Если пользователь задал этот бит осциллографирования
dlog.set_mode(1, &dlog); //Запуск осциллографа по этому событию
/*ENTRY END*/
}
/*DO START*/
{
if (drv_params.sens_type == POS_SENSOR_TYPE_HALL){ //В типе датчика выбран ДПР на элементах Холла
cur_par.speed = DPReCAP.speed; //Текущая скорость - с ДПР
refs.theta_elec = DPReCAP.Angle; //текущее угловое положение - с ДПР
}
if (drv_params.sens_type == POS_SENSOR_TYPE_ENCODER){ //В типе датчика выбран ДПР на элементах Холла
cur_par.speed = posspeedEqep.speed_elec; //Текущая скорость - с ДПР
refs.theta_elec = posspeedEqep.theta_elec; //текущее угловое положение - с ДПР
}
if (drv_params.sens_type == POS_SENSOR_TYPE_SSI){ //В типе датчика выбран ДПР цифровой с SSI интерфейсом
cur_par.speed = SSI_Encoder.speed_elec; //Текущая скорость - с ДПР
refs.theta_elec = SSI_Encoder.theta_elec; //текущее угловое положение - с ДПР
}
cur_par.Is = pid_iq.pid_fdb_reg3; //Текущий ток статора - ток по оси q
//Преобразование токов из трехфазной системы координат в двухфазную
clarke.as = adc.Imeas_a;
clarke.bs = adc.Imeas_b;
clarke.calc(&clarke);
cur_par.Ialpha = clarke.ds;
cur_par.Ibeta = clarke.qs;
// задание скорости от задатчика интенсивности (ЗИ)
rmp.input = refs.speed_ref;
rmp.calc(&rmp);//Расчет ЗИ
pid_spd.pid_ref_reg3 = rmp.output; //на воход регулятора скорости - выход ЗИ
pid_spd.pid_fdb_reg3 = cur_par.speed; //обратная связь регулятора скорости - скорость ДПР
pid_spd.pid_out_max = refs.Iq_ref; //Максимум выхода регулятора скорости - заданный ток
if (sw.recuperation_ena & 1) //если разрешена рекуперация
pid_spd.pid_out_min = -refs.Iq_ref; //минимум рег. скор. - отрицательный ток
else
//иначе
pid_spd.pid_out_min = 0; //нулевой ток не даст рекупераци при вращении в положительную сторону
pid_spd.calc(&pid_spd); //расчет регулятора скорости
cur_par.ThetaRefCurr = refs.theta_elec;
refs.theta_elec &= 0x00FFFFFF; //Ограничение угла на 1.0 в формате 8.24
//Поворот токов фаз на угол refs.theta_elec
park.ds = clarke.ds;
park.qs = clarke.qs;
park.ang = refs.theta_elec;
park.calc(&park); //расчет преобразования координат
//задание рег. тока по оси q (оси момента) - выход регулятора скорости
pid_iq.pid_ref_reg3 = pid_spd.pid_out_reg3;
pid_iq.pid_fdb_reg3 = park.qe; //обратная связь рег. тока оси q - вычисленный ток по фазе q
pid_iq.calc(&pid_iq); //расчет регулятора тока оси q
pid_id.pid_ref_reg3 = 0; //задание тока по оси d - оси возбудения
pid_id.pid_fdb_reg3 = park.de; //обратная связь рег. тока оси d - вычисленный ток по фазе d
pid_id.calc(&pid_id); //расчет регулятора тока оси d
//Обратный поворот на угол refs.theta_elec для
//выходов регуляторов тока (напряжений по осям d и q)
ipark.de = pid_id.pid_out_reg3;
ipark.qe = pid_iq.pid_out_reg3;
ipark.ang = refs.theta_elec;
ipark.calc(&ipark); //расчет преобразования координат
//Задание напряжение на модуль ШИМ после преобразования координат
pwm.UalphaRef = ipark.ds; //Ось альфа
pwm.UbetaRef = ipark.qs; //Ось бета
pwm.update(&pwm); //Расчет модуля ШИМ
/*DO END*/
}
break;
}
case CTRL_RUN_VECTOR_SM_ENCODER_POS: { //Датчиковая СУ с энкодером и с контуром положения
if (p->E == 1) {
/*ENTRY START*/
pwm.On(&pwm); //Включение ШИМ
rmp.output = 0; //Обнуление задатчика интенсивности
if (dlog.StartBits & (1 << 4)) //Если пользователь задал этот бит осциллографирования
dlog.set_mode(1, &dlog); //Запуск осциллографа по этому событию
/*ENTRY END*/
}
/*DO START*/
{
cur_par.Is = pid_iq.pid_fdb_reg3; //Текущий ток статора - ток по оси q
cur_par.speed = posspeedEqep.speed_elec; //Текущая скорость - с ДПР фильтрованная
//Преобразование токов из трехфазной системы координат в двухфазную
clarke.as = adc.Imeas_a;
clarke.bs = adc.Imeas_b;
clarke.calc(&clarke);
cur_par.Ialpha = clarke.ds;
cur_par.Ibeta = clarke.qs;
/* //Для демо-режима контура положения сделаем задание положения, изменяющегося по синусу
//Как быстро менять задание - пусть управляется из переменной для отладки DebugW1
if (DebugW1!=0){//если какая-то скорость вращения задана
p->AngleDemo+=(DebugW1>>10);//инкрементируем переменную
if (p->AngleDemo>_IQ(2))//период равен 2, что в о.е. дает 360*2 градусов
p->AngleDemo=0;
//задание угла в контур положения
//пусть будет синус от линейно увеличивающейся переменной, да еще и в 4 раза увеличим
refs.theta_elec=_IQsinPU(p->AngleDemo)<<2;
}
*/
/*
//Другой демо-режим контура положения - задавать положение от двигателя датчика, абсолютного энкодера с интерфейсом SSI
//Для работы датчика его нужно, собственно, подключить (в комплект поставки не входит!),
//а также выбрать его в настройках
#define REVOLUTION_DROP_NUMBER 3
//чтобы можно было вращать неограниченно в одну сторону и не переполнилась переменная по положению
//но чтобы нельзя было накрутить 100500 оборотов вперед привода и он крутил бы дальше и дальше
//ограничим максимальное расхождение в обототах числом REVOLUTION_DROP_NUMBER
if (labs(SSI_Encoder.RevolutionCounter-posspeedEqep.RevolutionCounter)>REVOLUTION_DROP_NUMBER){
if (posspeedEqep.RevolutionCounter>SSI_Encoder.RevolutionCounter){
posspeedEqep.RevolutionCounter=SSI_Encoder.RevolutionCounter+REVOLUTION_DROP_NUMBER;
}
if (SSI_Encoder.RevolutionCounter>posspeedEqep.RevolutionCounter){
SSI_Encoder.RevolutionCounter=posspeedEqep.RevolutionCounter+REVOLUTION_DROP_NUMBER;
}
}
if ((posspeedEqep.RevolutionCounter>10) || (SSI_Encoder.RevolutionCounter>10)){
posspeedEqep.RevolutionCounter-=10;
SSI_Encoder.RevolutionCounter-=10;
}
if ((posspeedEqep.RevolutionCounter<-10) || (SSI_Encoder.RevolutionCounter<-10)){
posspeedEqep.RevolutionCounter+=10;
SSI_Encoder.RevolutionCounter+=10;
}
//задание угла - от SSI энкодера
refs.theta_elec=SSI_Encoder.theta_elecContinouos;
*/
//текущий угол с датчика положения, переведенный в электрический из механического
cur_par.ThetaCurr = posspeedEqep.theta_elecContinouos;
cur_par.ThetaRefCurr=refs.theta_elec;//заданный угол электрический (продублируем в эту переменную задание для удобства наблюдения)
//ошибка - разница между заданием и текущим углом. Эта разница обычно считается внутри ПИД регулятора,
//однако в данном случае нужно после расчета произвести ограничение, чтобы в регуляторе ничего не переполнилось
long posRefError=refs.theta_elec - cur_par.ThetaCurr;
//ограничим ошибку - чтобы при расчете регулятора внутри него не было переполнения.
if (posRefError>_IQ(1))
posRefError=_IQ(1);
if (posRefError<-_IQ(1))
posRefError=-_IQ(1);
//обычно на ПИД регулятор подается задание и обратная связь, а внутри считается их разница.
//но разницу мы посчитали выше (и ограничили). Потому пусть задание на регулятор будет всё время нулевым,
//а в обратную связь подадим уже посчитанную и ограниченную ошибку (со знаком минус)
pid_pos.pid_ref_reg3 = 0;//задавать задание на положение надо через refs.theta_elec (группа задания)
pid_pos.pid_fdb_reg3 = -posRefError;//обратная связь
pid_pos.pid_out_max=refs.speed_ref;//ограничение рег. положения - максимум задаваемой скорости
pid_pos.pid_out_min=-refs.speed_ref;//и в минус
pid_pos.saterr_reg3Add=pid_spd.saterr_reg3;//это улучшайзер. Учитывает насыщение рег. скорости и передает его в рег. положения.
pid_pos.calc(&pid_pos); //расчет регулятора положения
pid_spd.pid_ref_reg3 = pid_pos.pid_out_reg3; //на вход регулятора скорости - выход рег. положения
pid_spd.pid_fdb_reg3 = posspeedEqep.speed_filter.output; //обратная связь регулятора скорости - скорость ДПР
pid_spd.pid_out_max = refs.Iq_ref; //Максимум выхода регулятора скорости - заданный ток
pid_spd.pid_out_min = -refs.Iq_ref; //минимум рег. скор. - отрицательный ток
pid_spd.calc(&pid_spd); //расчет регулятора скорости
//Поворот токов фаз на угол refs.theta_elec
park.ds = clarke.ds;
park.qs = clarke.qs;
park.ang = posspeedEqep.theta_elec;
park.calc(&park); //расчет преобразования координат
//задание рег. тока по оси q (оси момента) - выход регулятора скорости
pid_iq.pid_ref_reg3 = pid_spd.pid_out_reg3;
pid_iq.pid_fdb_reg3 = park.qe; //обратная связь рег. тока оси q - вычисленный ток по фазе q
pid_iq.calc(&pid_iq); //расчет регулятора тока оси q
pid_id.pid_ref_reg3 = 0; //задание тока по оси d - оси возбудения
pid_id.pid_fdb_reg3 = park.de; //обратная связь рег. тока оси d - вычисленный ток по фазе d
pid_id.calc(&pid_id); //расчет регулятора тока оси d
//Обратный поворот на угол refs.theta_elec для
//выходов регуляторов тока (напряжений по осям d и q)
ipark.de = pid_id.pid_out_reg3;
ipark.qe = pid_iq.pid_out_reg3;
ipark.ang = posspeedEqep.theta_elec;
ipark.calc(&ipark); //расчет преобразования координат
//Задание напряжение на модуль ШИМ после преобразования координат
pwm.UalphaRef = ipark.ds; //Ось альфа
pwm.UbetaRef = ipark.qs; //Ось бета
pwm.update(&pwm); //Расчет модуля ШИМ
/*DO END*/
}
break;
}
case CTRL_RUN_VECTOR_IM_ENCODER: { //Датчиковая СУ с энкодером
if (p->E == 1) {
/*ENTRY START*/
pwm.On(&pwm); //Включение ШИМ
RotorObserver.psi_d=0;
RotorObserver.psi_q=0;
rmp.output = 0; //Обнуление задатчика интенсивности
if (dlog.StartBits & (1 << 4)) //Если пользователь задал этот бит осциллографирования
dlog.set_mode(1, &dlog); //Запуск осциллографа по этому событию
/*ENTRY END*/
}
/*DO START*/
{
cur_par.Is = _IQmag(pid_iq.pid_fdb_reg3,pid_id.pid_fdb_reg3) ; //Текущий ток статора - амплитуда из токов d и q
cur_par.speed = posspeedEqep.speed_elec; //posspeedEqep.speed.output;//Текущая скорость - с ДПР фильтрованная
//Преобразование токов из трехфазной системы координат в двухфазную
clarke.as = adc.Imeas_a;
clarke.bs = adc.Imeas_b;
clarke.calc(&clarke);
cur_par.Ialpha = clarke.ds;
cur_par.Ibeta = clarke.qs;
// задание скорости от задатчика интенсивности (ЗИ)
rmp.input = refs.speed_ref;
rmp.calc(&rmp);//Расчет ЗИ
pid_spd.pid_ref_reg3 = rmp.output; //на воход регулятора скорости - выход ЗИ
pid_spd.pid_fdb_reg3 = posspeedEqep.speed_elec; //обратная связь регулятора скорости - скорость ДПР
pid_spd.pid_out_max = refs.Iq_ref; //Максимум выхода регулятора скорости - заданный ток
if (sw.recuperation_ena & 1) //если разрешена рекуперация
pid_spd.pid_out_min = -refs.Iq_ref; //минимум рег. скор. - отрицательный ток
else
//иначе
pid_spd.pid_out_min = 0; //нулевой ток не даст рекупераци при вращении в положительную сторону
pid_spd.calc(&pid_spd); //расчет регулятора скорости
//Поворот токов фаз на угол refs.theta_elec
park.ds = clarke.ds;
park.qs = clarke.qs;
park.ang = posspeedEqep.theta_elec;
park.calc(&park); //расчет преобразования координат
RotorObserver.id=park.de;//на наблюдатель ротора АД - токи статора, повернутый на угол ДПРа
RotorObserver.iq=park.qe;
RotorObserver.calc(&RotorObserver);
refs.theta_elec = RotorObserver.theta_psi_elec+posspeedEqep.theta_elec; //текущее угловое положение - с ДПР и наблюдателя ротора (оси x,y)
refs.theta_elec &= 0x00FFFFFF; //Ограничение угла на 1.0 в формате 8.24
cur_par.ThetaRefCurr = refs.theta_elec;
//Теперь refs.theta_elec - угол потокосцепления ротора. Повторяем векторную систему от синхронной машины для этого угла
park.ds = clarke.ds;
park.qs = clarke.qs;
//второе слагаемое - доворот для устойчивости регуляторов на высокой скорости. Дублироваться второй раз для ipark не должен!
park.ang = refs.theta_elec;
park.calc(&park);
//регуляторы токов d, q используются для регулирования осей x, y (чтобы не делать разных названий)
//задание рег. тока по оси y (оси момента) - выход регулятора скорости
pid_iq.pid_ref_reg3 = pid_spd.pid_out_reg3;
pid_iq.pid_fdb_reg3 = park.qe; //обратная связь рег. тока оси y - вычисленный ток по фазе y
pid_iq.calc(&pid_iq); //расчет регулятора тока оси y
pid_id.pid_ref_reg3 = _IQmpy(RotorObserver.FluxCurrentRatio,labs(pid_iq.pid_ref_reg3)); //задание тока по оси x - оси возбудения. Пропорционально амплитуде задания тока статора
if (pid_id.pid_ref_reg3 < RotorObserver.FluxCurrentMin)
pid_id.pid_ref_reg3=RotorObserver.FluxCurrentMin;
pid_id.pid_fdb_reg3 = park.de; //обратная связь рег. тока оси x - вычисленный ток по фазе x
pid_id.calc(&pid_id); //расчет регулятора тока оси x
//Обратный поворот на угол refs.theta_elec для
//выходов регуляторов тока (напряжений по осям x и y)
ipark.de = pid_id.pid_out_reg3;
ipark.qe = pid_iq.pid_out_reg3;
ipark.ang = refs.theta_elec;
ipark.calc(&ipark); //расчет преобразования координат
//Задание напряжение на модуль ШИМ после преобразования координат
pwm.UalphaRef = ipark.ds; //Ось альфа
pwm.UbetaRef = ipark.qs; //Ось бета
pwm.update(&pwm); //Расчет модуля ШИМ
/*DO END*/
}
break;
}
case CTRL_AUTO_SENSOR_TUNING: { //Авто настройка ДПР
if (p->E == 1) {
/*ENTRY START*/
pwm.On(&pwm);
rmp.output = 0;
DPReCAP.AngleOffset = 0;
if (dlog.StartBits & (1 << 3))
dlog.set_mode(1, &dlog);
/*ENTRY END*/
}
/*DO START*/
{
//по структуре это тоже самое, что частотно-токовая система управления
cur_par.Is = pid_id.pid_fdb_reg3;
cur_par.speed = rmp.output;
clarke.as = adc.Imeas_a;
clarke.bs = adc.Imeas_b;
clarke.calc(&clarke);
cur_par.Ialpha = clarke.ds;
cur_par.Ibeta = clarke.qs;
rmp.input = refs.speed_ref;
rmp.calc(&rmp);
refs.theta_elec += _IQmpy(
_IQmpyI32(drv_params.freq_nom,FAST_CALC_TS), rmp.output);
cur_par.ThetaRefCurr = refs.theta_elec;
refs.theta_elec &= 0x00FFFFFF;
park.ds = clarke.ds;
park.qs = clarke.qs;
park.ang = refs.theta_elec;
park.calc(&park);
pid_iq.pid_ref_reg3 = 0;
pid_iq.pid_fdb_reg3 = park.qe;
pid_iq.calc(&pid_iq);
pid_id.pid_ref_reg3 = refs.i_flux_ref;
pid_id.pid_fdb_reg3 = park.de;
pid_id.calc(&pid_id);
ipark.de = pid_id.pid_out_reg3;
ipark.qe = pid_iq.pid_out_reg3;
ipark.ang = refs.theta_elec;
ipark.calc(&ipark);
pwm.UalphaRef = ipark.ds;
pwm.UbetaRef = ipark.qs;
pwm.update(&pwm);
//автоматическая настрока смещения для датчика Холла
if (p->AnglePrev != DPReCAP.Angle6) {
if (((DPReCAP.Angle6 == _IQ(5.0 / 6.0)) && (p->AnglePrev == 0))
|| ((p->AnglePrev == _IQ(5.0 / 6.0))
&& (DPReCAP.Angle6 == 0))) {
DPReCAP.AngleOffset =
DPReCAP.AngleOffset
+ _IQmpy(_IQ(0.5),
((refs.theta_elec-DPReCAP.AngleOffset+_IQ(0.5))&0x00FFFFFF)-_IQ(0.5));
DPReCAP.AngleOffset &= 0x00FFFFFF;
}
p->AnglePrev = DPReCAP.Angle6;
}
//автоматическая настрока смещения для энкодера
posspeedEqep.AngleOffset =
posspeedEqep.AngleOffset
+ _IQmpy(_IQ(0.0001),
((refs.theta_elec-posspeedEqep.theta_elec+_IQ(0.5))&0x00FFFFFF)-_IQ(0.5));
posspeedEqep.AngleOffset &= 0x00FFFFFF;
/*DO END*/
}
break;
}
case CTRL_RUN_LATENCY_TEST: { //Режим постоянный ток
if (p->E == 1) {
/*ENTRY START*/
pwm.On(&pwm);
p->ctrl_counter = 0;
if (dlog.StartBits & (1 << 1))
dlog.set_mode(1, &dlog);
/*ENTRY END*/
}
/*DO START*/
p->ctrl_counter++;
pwm.UalphaRef = 0;
pwm.UbetaRef = 0;
DebugW1++;
if (p->ctrl_counter > 100){
if (labs(adc.Imeas_a)< refs.i_flux_ref){
pwm.UalphaRef = _IQ(1);
pwm.UbetaRef = 0;
} else {
p->ctrl_counter = 0;
}
}
pwm.update(&pwm);
break;
}
default: {
break;
}
}
}
/*@}*/

157
Vsrc/SM_Net.c Normal file
View File

@ -0,0 +1,157 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file SMNet.c
\brief Ìîäóëü îáùåãî íàçíà÷åíèÿ äëÿ ðàáîòû ñ ñåòüþ. (ñì. TSM_Net)
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 2.0 25/03/2016
*/
/** \addtogroup SMNet */
/*@{*/
#include "DSP.h"
#include "V_IQmath.h"
#include "main.h"
//!Èíèöèàëèçàöèÿ.
//!Ïðèñâîåíèå ìàñøòàáèðóþùèõ êîýôôèöèåíòîâ, èíèöèàëèçàöèÿ äðóãèõ ìîäóëåé.
//! \memberof TSM_Net
void SM_Net_Init(TSM_Net *p) {
p->state = 0;
p->state_prev = 0xff;
//Íàñòðîéêà äðàéâåðà CANOpen
co1_vars.settings.LoadParamsFromUserMemory_ena = 1;//Ðàçðåøèòü çàãðóæàòü çíà÷åíèÿ ïàðàìåòðîâ èç ÝÍÎÇÓ
co1_vars.CAN_REGS = (CAN_TypeDef *)CAN_BASE;//Ïåðåäàåì äðàéâåðó àäðåñ ñòðóêòóðû ðåãèñòðîâ CAN
co1_vars.settings.CAN_ISR_priority = IRQ_PRIORITY_CAN;//Ïðèñâîåíèå ïðèîðèòåòà ïåðûâàíèÿ CAN (îáðàáîò÷èê âíóòðè áèáëèîòåêè)
co1_vars.settings.CAN_IRQn = CAN1_IRQn;//Ïåðåäàåì íîìåð ïðåðûâàíèÿ CAN1 èç òàáëèöû ïðåðûâàíèé â äðàéâåð CANOpen
co1_vars.settings.MultiPDO_ena = 0;//Îòêëþ÷åíèå îáðàáîòêè PDO áåç ó÷åòà íîìåðà óçëà (ñïåö. ôóíêöèÿ)
co1_vars.settings.RX_PDO_Callback_ena = 0; //Íå âûçûâàòü ôóíêöèè îáðàòíîãî âûçîâà ïðè ïðèåìå PDO
co1_vars.settings.AutoBusON_ena = 1; //Àâòîìàòè÷åñêè ïåðåçàïóñêàòü CAN ïðè îøèáêàõ íà ëèíèè
co1_vars.settings.BlockTransfer_ena = 1;//Ðàçðåøèòü áëî÷íóþ ïåðåäà÷ó (íóæíà äëÿ îñöèëëîãðàôà)
co1_vars.settings.speedCANTablePointer = &canSpeedTable;//Ïåðåäàåì äðàéâåðó ïàðàìåòðû äëÿ íàñòðîéêè ñêîðîñòè CAN
co1_vars.settings.resetCPU = Watchdog.resetCPU;//Ïåðåäàåì äðàéâåðó àäðåñ ôóíêöèè ðåñåòà ìèêðîêîíòðîëëåðà
co1_Init(&co1_vars); //Èíèöèàëèçàöèÿ äðàéâåðà CANOpen
//ëîããåð ñîáûòèé:
// ðàçìåð áóôåðà: 50
// ñòàðòîâûé àäðåñ â SPI: 3000
FaultLog.init(&FaultLog, 50, 3000, (Uint32*)&RTCclock.packed_time);//íèæå óêàçàòåëü íà âðåìÿ ìîæåò áûòü ïåðåîïðåäåëåí â çàâèñèìîñòè îò ðàáîòû ÷àñîâ
////Ðàáîòà ñ CANopen ÷åðåç UART (ïàðàëëåëüíî ñ CAN, íåò êîíôëèêòà)
CANtoRS.nodeID = (Uint16*)&co1_vars.co_nodeID; //Íîìåð óçëà èç CANopen
CANtoRS.callback = Z_co_receiveSDOrequest;//Óêàçàòåëü íà ôóíêöèþ îáðàòíîãî âûçîâà èç äðàéâåðà CANopen ïî ïðèõîäó SDO ñîîáùåíèÿ
CANtoRS.init(&CANtoRS);
}
//!Ìåäëåííûé ðàñ÷åò.
//! Ïðèñâîåíèå ìàñøòàáèðóþùèõ êîýôôèöèåíòîâ, ôîíîâûé ðàñ÷åò íåêîòîðûõ ìîäóëåé.
//! \memberof TSM_Net
void SM_Net_Slow_Calc(TSM_Net *p) {
co1_vars.co_scaleNum0 = 1; //áåç ìàñøòàáèðîâàíèÿ
co1_vars.co_scaleNum1 = 100; // %
co1_vars.co_scaleNum2 = drv_params.freq_nom; //Ãö
co1_vars.co_scaleNum3 = drv_params.U_nom;//íàïðÿæåíèå ôàçíîå íîìèíàëüíîå àìïëèòóäíîå
co1_vars.co_scaleNum4 = drv_params.I_nom; //Òîê ôàçíûé áàçîâûé
co1_vars.co_scaleNum5 = 1;
co1_vars.co_scaleNum6 = 1;
co1_vars.co_scaleNum7 = drv_params.Udc_nom; //íàïðÿæåíèå ÇÏÒ áàçîâîå
co1_vars.co_scaleNum8 = drv_params.power; //18 â ôîðìàòå 9.6 //Ìîùíîñòü
co1_vars.co_scaleNum9 = 1;
co1_vars.co_scaleNumA = 20; //òåìïåðàòóðà
co1_vars.co_scaleNumB = 1;
co1_vars.co_scaleNumC = 1;
co1_vars.co_scaleNumD = 1;
co1_vars.co_scaleNumE = 1;
co1_vars.co_scaleNumF = 1;
co1_vars.co_scaleNum10 = 1; //
co1_vars.co_scaleNum11 = 1; //
co1_vars.co_scaleNum12 = drv_params.power; //18 â ôîðìàòå 10.6 //Ìîùíîñòü
co1_vars.co_scaleNum13 = 360; //
co1_vars.co_scaleNum14 = drv_params.speed_nom; //íîìèíàëüíàÿ ÷àñòîòà âðàùåíèÿ
co1_vars.co_scaleNum15 = 1; //
co1_vars.co_scaleNum16 = 1; //
co1_vars.co_scaleNum17 = ((((long) drv_params.Udc_nom) << 6)
/ (long) drv_params.I_nom); //Ráàç 10.6
co1_vars.co_scaleNum18 = 1000;
co1_vars.co_scaleNum19 = 1;
co1_vars.co_scaleNum1A = 1;
co1_vars.co_scaleNum1B = 1;
co1_vars.co_scaleNum1C = 1;
co1_vars.co_scaleNum1D = 1;
co1_vars.co_scaleNum1E = 1;
co1_vars.co_scaleNum1F = 1;
drv_params.U_nom = 0.5759 * drv_params.Udc_nom;//íîìèíàëüíîå ôàçíîå íàïðÿæåíèå
drv_params.power = ((long) 300) << 6; //ïðèâåäåì ê ôîðìàòó 10.6
drv_params.freq_nom = ((float) drv_params.speed_nom * drv_params.p) / 60 + 0.5; //íîìèí ÷àñòîòà
co_background_calc(&co1_vars); //Ðàñ÷åò äðàéâåðà CANOpen ôîíîâûé
drv_interface.calc(&drv_interface);
FaultLog.background_calc(&FaultLog);
#ifdef MODBUS_ENA
MBVarsConv.slow_calc(&MBVarsConv);
#endif
if (RTCclock.ClockOk)//÷àñû ðàáîòàþò?
FaultLog.time_ptr = (Uint32*)&RTCclock.packed_time;//âðåìÿ äëÿ áàíêà àâàðèé èç ÷àñîâ
else
FaultLog.time_ptr = (Uint32*)&global_time.PowerOn_time;//åñëè íå ðàáîòàþò, òî èç ìîäóëÿ ïîäñ÷åòà âðåìåíè íàðàáîòêè
}
//!Áûñòðûé ðàñ÷åò
//!Áûñòðûé ðàñ÷åò íåêîòîðûõ ñåòåâûõ ìîäóëåé, âûçîâ ìåòîäîâ "ïðîëèñòûâàíèÿ" êîäîâ àâàðèé è ïðåäóïðåæäåíèé
//! \memberof TSM_Net
void SM_Net_ms_Calc(TSM_Net *p) {
//Ïåðåâîä áèòîâîãî ñîñòîÿíèÿ ñèñòåìû óïðàâëåíèÿ â êîíñòàíòó.
//Ïî drv_status_code îòîáðàæàåòñÿ ñòàòóñ ïðèâîäà â UniCON
if (drv_status.bit.ready == 1)
drv_status_code = DRV_STATUS_READY;
if (drv_status.bit.running == 1)
drv_status_code = DRV_STATUS_RUNNING;
if (drv_status.bit.testing == 1)
drv_status_code = DRV_STATUS_TESTING;
if (drv_status.bit.fault == 1)
drv_status_code = DRV_STATUS_FAULT;
if (drv_status.bit.alarm == 1)
drv_status_code |= DRV_STATUS_ALARM;
else
drv_status_code &= ~DRV_STATUS_ALARM;
//ôóíêöèÿ ëèñòàíèÿ àâàðèé äëÿ ïóëüòà (UniCON)
pult_faults_lister.calc(&pult_faults_lister);
sm_prot.Main_ErrorCode = 0xFF & pult_faults_lister.output;
co_1ms_calc(&co1_vars); //Ðàñ÷åò äðàéâåðà CANOpen
CANtoRS.calc(&CANtoRS);
}
void SM_Net_fast_Calc(TSM_Net *p) {
#ifdef MODBUS_ENA
ModBus.Execute(&ModBus);
#endif
}
/*@}*/

205
Vsrc/SM_Protect.c Normal file
View File

@ -0,0 +1,205 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file SMProtect.c
\brief Ìîäóëü çàùèò. (ñì. TSM_Protect)
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 2.0 25/03/2016
\addtogroup SMProtect
@{ */
#include "DSP.h"
#include "main.h"
#include "stdlib.h"
int16 WriteCounter = 0;
//!Èíèöèàëèçàöèÿ
//!Ïðèñâàèâàíèå âñÿêèõ ïåðåìåííûõ
//! \memberof TSM_Protect
void SM_Protect_Init(TSM_Protect *p) {
p->state_prev = 0xff;
p->state = 0x00;
GPIOA->DENSET = (1 << 7);//äëÿ ïðèåìà íîæêè àïï. àâàðèè ðàçðåøàåì ðàáîòó íîæêè êàê öèôðû
}
//! Áûñòðûé ðàñ÷åò.
//!Îáðàáàòûâàåò âñå àâàðèè è ïðè èõ âîçíèêíîâåíèè îñòàíàâëèâàåò ïðèâîä.
//! \memberof TSM_Protect
void SM_Protect_Fast_Calc(TSM_Protect *p) {
//àïïàðàòíàÿ àâàðèÿ îò èíâåðòîðà
if (pwm.PDP_Fault) {
if ((sm_ctrl.state != CTRL_STOP) && (sm_ctrl.state != CTRL_RUN))
sm_prot.bit_fault1 |= F_PDPINT;
}
if (!DRV_FAULT) {
//èìååòñÿ êàêàÿ-òî àïïàðàòíàÿ àâàðèÿ
sm_prot.bit_fault1 |= F_PDPINT;
}
/*Çàùèòà ïî ìàêñèìàëüíîìó òîêó*/
if (adc.Imeas_a > sm_prot.Imax_protect) sm_prot.bit_fault2 |= F_CTRL_MAX_I_PH_A;
if (adc.Imeas_a < -sm_prot.Imax_protect) sm_prot.bit_fault2 |= F_CTRL_MAX_I_PH_A;
if (adc.Imeas_b > sm_prot.Imax_protect) sm_prot.bit_fault2 |= F_CTRL_MAX_I_PH_B;
if (adc.Imeas_b < -sm_prot.Imax_protect) sm_prot.bit_fault2 |= F_CTRL_MAX_I_PH_B;
if (adc.Imeas_c > sm_prot.Imax_protect) sm_prot.bit_fault2 |= F_CTRL_MAX_I_PH_C;
if (adc.Imeas_c < -sm_prot.Imax_protect) sm_prot.bit_fault2 |= F_CTRL_MAX_I_PH_C;
//ïðè ïðåâûøåíèè ñêîðîñòè âûøå àâàðèéíîé íîðìû
if (labs(cur_par.speed) > sm_prot.speed_max) {
sm_prot.bit_fault2 |= F_CTRL_SPEED_MAX; // ìàêñèììàëüíîå Ud
}
//ïðè ïðåâûøåíèè íàïðÿæåíèÿ âûøå àâàðèéíîé íîðìû
if (adc.Udc_meas > sm_prot.Umax_protect) {
sm_prot.bit_fault1 |= F_CTRL_HI_UDC; // ìàêñèììàëüíîå Ud
}
//ñíèæåíèå íàïðÿæåíèÿ
if (adc.Udc_meas < sm_prot.Umin_protect) { //åñëè ïðèâîä ðàáîòàë òî ëîâèì àâàðèþ
if (sm_ctrl.state != CTRL_STOP) {
sm_prot.bit_fault1 |= F_CTRL_LOW_UDC;
}
}
DINT; //Çàïðåùåíèå ïðåðûâàíèé
//Àâàðèè, òðåáóþùèå ïîëíîãî îñòàíîâà
p->masked_bit_fault1 = p->bit_fault1 & p->mask_fault1;//ìàñêèðîâàíèå ôëàãîâ àâàðèé
p->masked_bit_fault2 = p->bit_fault2 & p->mask_fault2;
EINT; //Ðàçðåøåíèå ïðåðûâàíèé
//ñ÷èòàåì äèñêðåòíûé àâòîìàò çàùèò
if (p->state_prev != p->state) //ñìåíà ñîñòîÿíèÿ?
p->E = 1;//Âîçâîäèì ôëàã ïåðâîãî âõîæäåíèÿ "entry"
else
p->E = 0;//èíà÷å ñáðàñûâàåì
p->state_prev = p->state;
switch (p->state) {//â çàâèñèìîñòè îò òåêóùåãî ñîñòîÿíèÿ
case PROT_OFF: { //Çàùèòà âûêëþ÷åíà
if (p->E == 1) { //Ïåðâîå âõîæäåíèå
}
//Îáíóëÿåì âñå àâàðèè
p->bit_fault1 = 0;
p->bit_fault2 = 0;
//Ïðîïóñêàåì íåêîòîðûé òàéìàóò ïîñëå âêëþ÷åíèÿ êîíòðîëëåðà
//÷òîáû íå ëîâèòü ëîæíûå ñðàáàòûâàíèÿ àâàðèé ÀÖÏ
if (p->powered_okCounter++ > 5000) {
p->state = PROT_ON_OK;
}
break;
}
case PROT_ON_OK: { //Íîðìà
if (p->E == 1) { //Ïåðâîå âõîæäåíèå
drv_status.bit.fault = 0;
}
//åñòü àâàðèè?
if ((p->masked_bit_fault1 | p->masked_bit_fault2) != 0) {
p->state = PROT_FAIL; //ïåðåõîäèì â ñîñòîÿíèå àâàðèè
}
break;
}
case PROT_FAIL: { //ñîñòîÿíèå àâàðèè (ñðàáîòàëà çàùèòà)
if (p->E == 1) {
cmd.all = 0;
}
drv_status.bit.fault = 1;
//Âûêëþ÷åíèå ØÈÌ. Ïîêà òàì âñå îñòàëüíûå äèñêðåòíûå àâòîìàòû ïðîáóðëÿòñÿ, ÷òîáû èõ íå æäàòü
pwm.Off(&pwm);
//ëîãèêà ñáîðîñà àâàðèè
if (cmd.bit.trip_reset == 1) {//êîìàíäà íà ñáðîñ àâàðèè
p->state = PROT_ON_OK;//èäåì â "íîðìà"
p->clearDrvFault = 1; //îòïðàâèòü äðàéâåðó êëþ÷åé êîìàíäó ñáðîñà
//îáíóëÿåì âñå ôëàãè àâàðèé
p->bit_fault1 = 0;
p->bit_fault2 = 0;
cmd.all = 0;//êîìàíäíîå ñëîâî
//â ñàìîì íèçó!!! ïûòàåìñÿ ñáðîñèòü ôëàã pdp àïïàðàòíûé
//åñëè àâàðèÿ âñå åùå èìååòñÿ, òî ñðàçó ïðîèçîéäåò ïðåðûâàíèå
//è âîçâåäåòñÿ ôëàã àâàðèè
if (PWM0->TZFLG_bit.OST == 1) { //èìååòñÿ ôëàã àïïàðàòíîé àâàðèè
//ôëàã ìîæíî ñáðàñûâàòü
PWM0->TZCLR = 0x7;
PWM1->TZCLR = 0x7;
PWM2->TZCLR = 0x7;
}
}
break;
}
}
}
//! \memberof TSM_Protect
void SM_Protect_ms_Calc(TSM_Protect *p) {
if (WriteCounter <= 15) //åñëè ïåðâîå ñëîâî
{
if (((sm_prot.masked_bit_fault1 >> WriteCounter) & 0x1) != 0) //ñòîèò ii-é ôëàã àâàðèè
{
if (((sm_prot.bit_fault_written1 >> WriteCounter) & 0x1) == 0) //è îíà íå çàïèñàíà
{
FaultLog.write(&FaultLog, WriteCounter + 1);
sm_prot.bit_fault_written1 |= (1 << WriteCounter);
}
}
else
sm_prot.bit_fault_written1 &= ~(1 << WriteCounter);
}
else if (WriteCounter <= 31) //âòîðîå ñëîâî
{
if (((sm_prot.masked_bit_fault2 >> (WriteCounter - 16)) & 0x1) != 0) //ñòîèò ii-é ôëàã àâàðèè
{
if (((sm_prot.bit_fault_written2 >> (WriteCounter - 16)) & 0x1) == 0) //è îíà òîëüêî ÷òî ïîßâèëàñü
{
FaultLog.write(&FaultLog, WriteCounter + 1);
sm_prot.bit_fault_written2 |= (1 << (WriteCounter - 16));
}
}
else
sm_prot.bit_fault_written2 &= ~(1 << (WriteCounter - 16));
}
WriteCounter++;
if (WriteCounter >= (33 - 1))
WriteCounter = 0;
}
//! Ìåäëåííûé ðàñ÷åò.
//! \memberof TSM_Protect
void SM_Protect_Slow_Calc(TSM_Protect *p) {
/* Ïðîâåðêà àïïàðàòíûõ çàùèò äðàéâåðà. Îí àâòîìàòè÷åñêè âûðóáàåò êëþ÷è ïðè àâàðèÿõ,
* è îïóñêàåò ñèãíàëû /FAULT è /OCTW, íî ÷òîáû ïîíÿòü, ÷òî èìåííî ñëó÷èëîñü, íàäî ïî SPI ïðî÷èòàòü ñòàòóñû.
* Ïîýòîìó, âèäèìî, ìîæíî â ôîíå.
*/
if (p->readDrvSts == 1) {
p->readDrvSts = 0;
}
/* ×òîáû ñáðîñèòü àâàðèþ, íàäî ïðîïèñàòü åìó áèòèê GATE_RESET */
if (p->clearDrvFault == 1) {
p->clearDrvFault = 0;
}
}
/*@}*/

278
Vsrc/SM_Sys.c Normal file
View File

@ -0,0 +1,278 @@
/*!
Copyright 2017 АО "НИИЭТ" и ООО "НПФ ВЕКТОР"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file SMSys.c
\brief Модуль-обертка для расчета остальных модулей. (см. TSM_Sys)
\author ООО "НПФ Вектор". http://motorcontrol.ru
\version v 2.0 25/03/2016
*/
/** \addtogroup SMSys */
/*@{*/
#include "main.h"
/* Объявление адреса размещения таблицы векторов прерываний */
#if defined ( __CMCPPARM__ )
extern const Uint32 __Vectors;
#elif defined (__GNUC__)
#endif
//! Инициализация системы управления после включения
//!Инициализация некоторых модулей и настройка прерываний системы.
//!Здесь настраивается большинство прерываний
//! \memberof TSM_Sys
void SM_Sys_Init(TSM_Sys *p) {
#if defined (HW_VECTORCARD_DRV8301_EVM)
sw.HardwareType = 0;
#elif defined (HW_VECTORCARD_DRV8312_EVM)
sw.HardwareType = 1;
#elif defined (HW_VECTORCARD_SIMULATOR)
sw.HardwareType = 2;
#endif
cmd.all = 0;
drv_status.all = 0;
sm_net.init(&sm_net); //Сетевая часть
adc.init(&adc); //Инициализация АЦП
sm_prot.init(&sm_prot); //Защиты
sm_cmd_logic.init(&sm_cmd_logic); //Логика включения/выключения
sm_ctrl.init(&sm_ctrl); //Структура системы управления
pwm.init(&pwm); //Модуль ШИМ
cur_par.init(&cur_par); //Расчет текущих показателей привода
leds.init(&leds);//светодиоды
//глобальное времЯ (внешние или внутр. часы)
global_time.init(&global_time);
if (drv_params.sens_type == POS_SENSOR_TYPE_HALL){ //В типе датчика выбран ДПР на элементах Холла
// DPReCAP.Init(&DPReCAP); //ДПР иниц.
}
if (drv_params.sens_type == POS_SENSOR_TYPE_ENCODER){ //В типе датчика выбран энкодер
//настроим квадратурный декодер
posspeedEqep.speed_nom = drv_params.speed_nom; //базовая скорость
posspeedEqep.pole_pairs = drv_params.p; //кол-во пар полюсов дригателя
posspeedEqep.Posspeed_CTL.bit.dir = 1; //направление движения
posspeedEqep.RevolutionCounter=0;
posspeedEqep.init(&posspeedEqep);//инициализация модуля энкодера
}
if (drv_params.sens_type == POS_SENSOR_TYPE_SSI){ //В типе датчика выбран датчик с SSI интерфейсом. Читайте заголовочник модуля перед использованием!
//настроим модуль датчика положения SSI
SSI_Encoder.speed_nom = drv_params.speed_nom; //базовая скорость
SSI_Encoder.pole_pairs = drv_params.p; //кол-во пар полюсов дригателя
SSI_Encoder.rotation_dir = 0; //направление движения
SSI_Encoder.RevolutionCounter=0;
SSI_Encoder.init(&SSI_Encoder);//Датчик положения SSI
}
if (drv_params.sens_type == POS_SENSOR_TYPE_ENC_HALL){
//настроим квадратурный декодер
// DPReCAP.Init(&DPReCAP); //ДПР иниц.
posspeedEqep.speed_nom = drv_params.speed_nom; //базовая скорость
posspeedEqep.pole_pairs = drv_params.p; //кол-во пар полюсов дригателя
posspeedEqep.Posspeed_CTL.bit.dir = 1; //направление движения
posspeedEqep.RevolutionCounter=0;
posspeedEqep.init(&posspeedEqep);//инициализация модуля энкодера
}
//листалка аварий для отображения на пульте управления (UniCON)
pult_faults_lister.num_of_words = 2;
pult_faults_lister.out_refresh_devisor = 1000; //при вызове в мс таймере период обновления будет равен 1сек
pult_faults_lister.w_ptrs[0] = (Uint16*) &sm_prot.masked_bit_fault1;//перебираются эти флаги аварий модуля защит
pult_faults_lister.w_ptrs[1] = (Uint16*) &sm_prot.masked_bit_fault2;
AutoOffset.FilterK = _IQ(0.00001);//постоянная времени фильтра для автосмещения АЦП
AutoOffset.init(&AutoOffset); //авто смещение некоторых каналов АЦП (токи)
#if defined(HW_VECTORCARD_SIMULATOR) || defined(HW_NIIET_BOARD_SIMULATOR)
//model.motorInternals.udc = 540; //задается через словарь объектов
model.tpr = _IQ10div(_IQ10(SystemCoreClock/1000.0), pwm.Frequency << 1) >> 10; //период частоты ШИМ
model.dt = _IQ4mpy(_IQ4(150 / 4), pwm.DeadBand >> 20) >> 4; //величина мертвого времени
model.Init(&model); //Модель двигателя
#endif
// Настройка таймера 0 на 10 кГц
TMR0->INTSTATUS_bit.INT = 1;
TMR0->LOAD_bit.VAL = 10000 - 1; //9999 надо чтобы не плыло отностильно прерывания ШИМа, когда у того частота 10кГц
TMR0->CTRL = ((1 << 0) | (1 << 3)); // Запуск и разрешение прерываний
// Настройка таймера 1 на 1 кГц
TMR1->INTSTATUS_bit.INT = 1;
TMR1->LOAD_bit.VAL = 100000 - 1;
TMR1->CTRL = ((1 << 0) | (1 << 3)); // Запуск и разрешение прерываний
//Для подсчета тактов
TMR2->LOAD_bit.VAL = 0xFFFFFFFF;
TMR2->CTRL = (1 << 0); // Запуск
extern int *g_pfnVectors; //там, где-то в стартап файле есть такой символ
//Надо показать в этом регистре, где лежит таблица прерываний.
//А лежит она там, куда записал её линкер, в зависимости от файла компоновки.
//Поэтому берем адрес от массива g_pfnVectors и кладем туда
#if defined (__CMCPPARM__)
SCB->VTOR = (uint32_t) (&__Vectors);
#elif defined (__GNUC__)
extern int *g_pfnVectors;
SCB->VTOR = (uint32_t) (&g_pfnVectors);
#endif
NVIC_SetPriorityGrouping(3); // 4 bit preemption, 0 bit of subprio
NVIC_DisableIRQ(TMR0_IRQn);
NVIC_DisableIRQ(TMR1_IRQn);
NVIC_DisableIRQ(ECAP0_IRQn);
NVIC_DisableIRQ(ECAP1_IRQn);
NVIC_DisableIRQ(ECAP2_IRQn);
NVIC_DisableIRQ(PWM0_TZ_IRQn);
NVIC_DisableIRQ(QEP_IRQn);
NVIC_ClearPendingIRQ(TMR0_IRQn);
NVIC_ClearPendingIRQ(TMR1_IRQn);
NVIC_ClearPendingIRQ(ECAP0_IRQn);
NVIC_ClearPendingIRQ(ECAP1_IRQn);
NVIC_ClearPendingIRQ(ECAP2_IRQn);
NVIC_ClearPendingIRQ(PWM0_TZ_IRQn);
NVIC_ClearPendingIRQ(QEP_IRQn);
/* Прерывание 10 кГц */
NVIC_EnableIRQ(TMR0_IRQn);
NVIC_SetPriority(TMR0_IRQn, IRQ_PRIORITY_10K);
/* Прерывание 1 кГц */
NVIC_EnableIRQ(TMR1_IRQn);
NVIC_SetPriority(TMR1_IRQn, IRQ_PRIORITY_1K);
NVIC_EnableIRQ(ECAP0_IRQn); //CAP0
NVIC_SetPriority(ECAP0_IRQn, IRQ_PRIORITY_CAP);
NVIC_EnableIRQ(ECAP1_IRQn); //CAP1
NVIC_SetPriority(ECAP1_IRQn, IRQ_PRIORITY_CAP);
NVIC_EnableIRQ(ECAP2_IRQn); //CAP2
NVIC_SetPriority(ECAP2_IRQn, IRQ_PRIORITY_CAP);
NVIC_EnableIRQ(PWM0_TZ_IRQn); //PDP (в инверторе тексас нету такого пина)
NVIC_SetPriority(PWM0_TZ_IRQn, IRQ_PRIORITY_TZ);
NVIC_EnableIRQ(QEP_IRQn); //QEP
NVIC_SetPriority(QEP_IRQn, IRQ_PRIORITY_EQEP);
sm_sys.state = SYS_READY;
#ifdef WATCHDOG_ON
Watchdog.enable(); //если сторожевой таймер используется, инициализируем
#endif //WATCHDOG_ON
}
//!Быстрый расчет (обычно 10кГц).
//!Вызов быстрых расчетов модулей системы управления
//! \memberof TSM_Sys
void SM_Sys_Fast_Calc(TSM_Sys *p) {
sm_net.fast_calc(&sm_net);//расчет коммуникационных драйверов
if (drv_params.sens_type == POS_SENSOR_TYPE_ENCODER) //В типе датчика выбран энкодер
posspeedEqep.calc(&posspeedEqep); //ДПР энкодер
if (drv_params.sens_type == POS_SENSOR_TYPE_HALL){ //В типе датчика выбран ДПР Холла
DPReCAP.AngleCalc(&DPReCAP); //ДПР Холл, интерполяция угла положения (результат в DPReCAP.Angle)
DPReCAP.Angle6Calc(&DPReCAP); //ДПР Холл, получение угла с точнгстью 60 градусов (результат в DPReCAP.Angle6)
DPReCAP.SpeedCalc(&DPReCAP); //ДПР Холл, расчет скорости вращения (DPReCAP.speed)
DPReCAP.calc_10k(&DPReCAP); //ДПР Холл, служебные функции
}
if (drv_params.sens_type == POS_SENSOR_TYPE_SSI){ //Датчик с интерфейсом SSI. Перед употреблением читайте заголовочный файл!
SSI_Encoder.calc(&SSI_Encoder);//Датчик положения SSI
}
sm_prot.fast_calc(&sm_prot); //Защиты
sm_ctrl.fast_calc(&sm_ctrl); //Главный дискретный автомат системы управления
global_time.calc(&global_time);
cur_par.calc(&cur_par); //Расчет текущих показателей привода
drv_params.sens_type = drv_params.sens_type & 3; //Отсекаем верхнюю часть переменной, там мусор
#ifdef WATCHDOG_ON
// Watchdog.feed();//если сторожевой таймер используется, сбрасываем его здесь
#endif //WATCHDOG_ON
}
//!Миллисекундный расчет 1кГц.
//!Вызов расчетов модулей системы управления, требующих миллисекундной дискретизации
//! \memberof TSM_Sys
void SM_Sys_ms_Calc(TSM_Sys* p) {
sm_cmd_logic.ms_calc(&sm_cmd_logic); //Обработка команд управления
sm_net.ms_calc(&sm_net); //обертка для вызова коммуникационных драйверов
adc.ms_calc(&adc); //АЦП
sm_prot.ms_calc(&sm_prot); //Защиты
AutoOffset.ms_calc(&AutoOffset); //авто смещение некоторых каналов АЦП
//блочная передача драйвера CANopen. Через неё, в частности, грузятся осциллограммы dlog
// Can2BTInterface.ms_calc(&Can2BTInterface, TMR2->VALUE, &co2_vars);
leds.msCalc(&leds);//светодиоды
RTCclock.msCalc(&RTCclock);//часы
UserMem.ms_calc(&UserMem);//пользовательская память в МК
if ((drv_params.sens_type == 2) || (drv_params.sens_type == 3)){ //В типе датчика выбран ДПР Холла
DPReCAP.ms_calc(&DPReCAP);
}
global_time.ms_calc(&global_time);
}
//!Медленный расчет (фоновый).
//!Вызов медленных расчетов остальных модулей
//! \memberof TSM_Sys
void SM_Sys_Slow_Calc(TSM_Sys *p) {
// Can2BTInterface.slow_calc(&Can2BTInterface);//интерфейс блочной передачи CANopen, медленный расчет
UserMem.slow_calc(&UserMem);//пользовательская память в МК
RTCclock.slowCalc(&RTCclock);//часы реального времени
sm_prot.slow_calc(&sm_prot);//модуль защит
sm_net.slow_calc(&sm_net); //обертка для вызова коммуникационных драйверов
dlog.background_analizer(&dlog); //фоновый обработчик модуля осциллографирования
global_time.slow_calc(&global_time);
rmp.slow_calc(&rmp); //пересчет интенсивности разгона из пользовтельской во внутреннее представление
pwm.slow_calc(&pwm); //фоновый обработчик модуля ШИМ (пересчет пользовательских заданий)
adc.slow_calc(&adc); //Фоновый обработчик АЦП
cur_par.slow_calc(&cur_par); //Расчет текущих показателей привода
AutoOffset.slow_calc(&AutoOffset);
posspeedEqep.slow_calc(&posspeedEqep);//инициализация модуля энкодера
RotorObserver.slow_calc(&RotorObserver);//наблюдатель потока ротора АД
DPReCAP.slow_calc(&DPReCAP);//ДПР Холла
//Пересчет коэффициентов для масштабирования токов и напряжений
drv_params._1_Udc_nom = _IQdiv(_IQ16(1), _IQ16(drv_params.Udc_nom));
drv_params._1_I_nom = _IQdiv(_IQ16(1), _IQ16(drv_params.I_nom));
drv_params._1_U_nom = _IQdiv(_IQ16(1), _IQ16(drv_params.U_nom));
if (sw.Reboot & 1) { //команда перезагрузки
sw.Reboot = 0; //сбрасываем её
if (sm_ctrl.state == CTRL_STOP) { //перезагружаемся только в останове
//выполняем сброс проца
//Перезагружает во флеш!
Watchdog.resetCPU();
}
}
//вызов расчета смещения АЦП для токов фаз
//Делаем расчет только в останове и отсутствии аварии
if ((sw.AutoOffset & 1) && (sm_ctrl.state == CTRL_STOP)) AutoOffset.Enabled=1;
else AutoOffset.Enabled=0;
}
/*@}*/

73
Vsrc/V_AutoOffset.c Normal file
View File

@ -0,0 +1,73 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file V_AutoOffset.c
\brief Àâòîñìåùåíèå ÀÖÏ (ñì. TAutoOffset)
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 2.0 25/03/2016
@{
*/
/** \addtogroup TAutoOffset */
/*@{*/
#include "DSP.h"
#include "v_IQmath.h"
#include "V_adc.h"
#include "V_AutoOffset.h"
#include "V_common.h"
extern TAdcDrv adc;
extern TDrvParams drv_params;
void AutoOffset_init(TAutoOffset *p) {
p->FilterK = _IQ(0.001);
}
void AutoOffset_calc(TAutoOffset *p) {
//èíòåãðàòîðû äëÿ òîêîâ ôàç. Êîãäà ìîäóëü âûçûâàåòñÿ, òîêè äîëæíû áûòü íóëåâûìè.
//åñëè ýòî íå òàê, òî èíòåãðàòîðû ïîéäóò ñ÷èòàòü
p->IA_int = p->IA_int + _IQmpy(p->FilterK, adc.Imeas_a);
p->IB_int = p->IB_int + _IQmpy(p->FilterK, adc.Imeas_b);
p->IC_int = p->IC_int + _IQmpy(p->FilterK, adc.Imeas_c);
}
void AutoOffset_slow_calc(TAutoOffset *p) {
long IA_pu;
long IB_pu;
long IC_pu;
if (p->Enabled){//åñëè ìîäóëü àâòîðàñ÷åòà ñìåùåíèÿ òîêîâ âêëþ÷åí
//ïåðåñ÷èòûâàåì èç î.å. îáðàòíî â çíà÷åíèÿ ÀÖÏ
IA_pu = -p->IA_int / (_IQ16mpy(adc.Imeas_a_gain, drv_params._1_I_nom));
adc.Imeas_a_offset = IA_pu >> 1;
IB_pu = -p->IB_int / (_IQ16mpy(adc.Imeas_b_gain, drv_params._1_I_nom));
adc.Imeas_b_offset = IB_pu >> 1;
IC_pu = -p->IC_int / (_IQ16mpy(adc.Imeas_c_gain, drv_params._1_I_nom));
adc.Imeas_c_offset = IC_pu >> 1;
} else {//ìîäóëü âûêëþ÷åí, èíèöèàëèçèðóåì èíòåãðàòîðû òåêóùèìè çíà÷åíÿìè ñìåùåíèé
p->IA_int=-(((long)adc.Imeas_a_offset)<<1)*_IQ16mpy(adc.Imeas_a_gain, drv_params._1_I_nom);
p->IB_int=-(((long)adc.Imeas_b_offset)<<1)*_IQ16mpy(adc.Imeas_b_gain, drv_params._1_I_nom);
p->IC_int=-(((long)adc.Imeas_c_offset)<<1)*_IQ16mpy(adc.Imeas_c_gain, drv_params._1_I_nom);
}
}
/*@}*/

327
Vsrc/V_CANtoRS.c Normal file
View File

@ -0,0 +1,327 @@
/*!
Copyright 2017 АО "НИИЭТ" и ООО "НПФ ВЕКТОР"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file v_CANtoRS.c
\brief Преобразователь посылок CAN в RS и обратно. Работает
совместно с драйвером CANOpen
\author ООО "НПФ Вектор". http://motorcontrol.ru
\version v 2.0 25/03/2016
\addtogroup v_CANtoRS
@{
*/
#include "DSP.h"
#include "main.h"
//! \memberof TCANtoRS
void CANtoRS_init(TCANtoRS *p) {
GPIOB->ALTFUNCSET = (1 << 8) + (1 << 9);
GPIOB->DENSET = (1 << 8) + (1 << 9);
p->UART=UART1;//Используемый в драйвере номер UART (0, 1)
p->UART->CR_bit.UARTEN = 1; // Разрешить работу UART
// Настройка частоты в двух регистрах:
// задание делителя частоты для получения BaudRate
// Т.к. блок UART тактируется с частотой 25 МГц (так настроено в ините микроконтроллера),
// то для получения частоты 57600 бит/с необходим
// делитель 25000000 / (16 * 57600) = 27,126736111111111111111111111111
// Целая часть I = 27
// Дробная часть F = (int)( 0.126736111*64 + 0.5 ) = 8
// Формулы см. в документации
p->UART->IBRD_bit.DIVINT= 27;
p->UART->FBRD_bit.DIVFRAC = 8;
p->UART->LCRH_bit.SPS = 0; // Нет проверки четности
p->UART->LCRH_bit.WLEN = 3; // Длина посылки 8 бит
p->UART->LCRH_bit.FEN = 1; // Использовать FIFO
p->UART->CR_bit.TXE = 1; // Разрешить приём
p->UART->CR_bit.RXE = 1; // Разрешить передачу
p->UART->LCRH_bit.STP2 = 0; // 1 стоп-бит
p->CounterWrongCRC=0;
p->CounterRes=0;
p->CounterSended=0;
p->PacketInWait=0;
}
//! Из заданного для передачи массива функция формирует
//!API пакет, а затем вызывает функцию
//!побайтовой отправки
//! \memberof TCANtoRS
Uint16 CANtoRS_SendP(Uint16* Data, int16 len, TCANtoRS *p) {
volatile int16 i;
Uint16 MyCRC;
p->buf_out[0]=0x7E;
for (i=0;i<len;i++)
p->buf_out[i+1]=Data[i];
MyCRC=CANtoRS_C_CRC(p,Data,len);
p->buf_out[len+1]=MyCRC & 0xFF;//первый байт
p->buf_out[len+2]=(MyCRC>>8) & 0xFF;//второй байт
p->all_len=1+len+2;//полная длина=сигнатура+данные + контрольная сумма
i = 0;
// Если буфер TX не заполнен, то отправляем все байты из буфера
while ((p->UART->FR_bit.TXFF != 1) && (i < p->all_len)){
p->UART->DR = p->buf_out[i];
i++;
}
return 1;
}
#define CRC_MAGIC_NUMBER 0xA001
//! Функция считает контрольную сумму пакета
//! и сравнивает с принятой. Если все верно, то возвращает 1
//! \memberof TCANtoRS
Uint16 CANtoRS_C_CRC(TCANtoRS *p,Uint16 *Data,Uint16 len) { //проверка контрольной суммы принятого API пакета
int16 i,j;
Uint16 MyCalcCRC=0xFFFF;
for (j=0;j<len;j++) {
MyCalcCRC=MyCalcCRC^(Data[j++]&0xFF);
for (i=0; i<16; i++)
if (MyCalcCRC&0x01) {
MyCalcCRC=(MyCalcCRC>>1);
MyCalcCRC=MyCalcCRC^CRC_MAGIC_NUMBER;
} else
MyCalcCRC=(MyCalcCRC>>1);
}
return MyCalcCRC;
}
/*! Функция вызывается, когда пришли какие-то данные,
и обрабатывает их как переданный CAN пакет. Выделяет
идентификатор, длину и прочее. Рез-т помещает в структуру
p->MSG */
//! \memberof TCANtoRS
void CANtoRS_Analysis(TCANtoRS *p) {
int16 i,j;
//посылка данных начинается с 12го байта,
//до этого служебная информация API пакета
p->MSG.id=0;
p->MSG.id=(p->ReadPackData[0] & 7)<<8; //нижние 3 бита сдвигаем наверх;
p->MSG.id|=p->ReadPackData[1];
p->MSG.dlc=(p->ReadPackData[0]>>4) & 0xF; //верхние 4 бита сдвигаем вниз; длина посылки
for (i=2,j=0;i<CANTORS_READ_DATA_MAX_LEN;i++,j++)
p->MSG.data[j]=p->ReadPackData[i];
p->callback_go=1;
}
/*! Побайтовый обработчик приходящих по SCI данных.
Работает по принципу дискретного автомата и пытается
найти в посылке API пакет. Сначала ждет заданную сигнатуру,
потом длину и т.п. В конце проверяет контрольную сумму и
вызывает дальнейшие обработчики */
//! \memberof TCANtoRS
void CANtoRS_Receive(TCANtoRS *p) {
Uint16 MyReadCRC_u16;
Uint16 MyCalcCRC;
Uint32 temp_byte;
Uint16 repeat;
for (repeat=0;repeat<7; repeat++) {//обработка не более n байт за один вход в функцию
switch (p->APIpacketMode) {
case 0: { //ожидание сигнатуры
if (p->UART->FR_bit.RXFE)
return;
temp_byte = p->UART->DR_bit.DATA;
if (temp_byte!=0x7e) {
p->MessDrop3++;
return;
}
p->ReadPackDataCounter=0;//счетчик данных
p->APIpacketMode=1; //сигрнатура найдена, режим приема данных
break;
};
case 1: { //ожидание данных(полезная нагрузка) пакета
//все последующие байты складываем в API буфер
if (p->UART->FR_bit.RXFE)
return;
temp_byte = p->UART->DR_bit.DATA;
p->ReadPackData[p->ReadPackDataCounter++]=temp_byte;
if (p->ReadPackDataCounter>=CANTORS_READ_DATA_MAX_LEN) {
p->ReadPackDataCounter=0;//счетчик данных
p->ReadCRCCounter=0;//счетчик контрольной суммы
p->APIpacketMode=2; //данные приняты, режим приема и проверси CRC
}
break;
};
case 2: { //ожидание CRC
//все последующие байты складываем в CRC буфер
if (p->UART->FR_bit.RXFE)
return;
temp_byte = p->UART->DR_bit.DATA;
p->ReadCRC[p->ReadCRCCounter++]=temp_byte;
if (p->ReadCRCCounter>=2) {
p->ReadCRCCounter=0;//счетчик контрольной суммы
MyReadCRC_u16=(p->ReadCRC[0]&0xFF)+((p->ReadCRC[1]<<8)&0xFF00);//запаковываем двухбайтовую CRC в одну переменную
MyCalcCRC=CANtoRS_C_CRC(p,p->ReadPackData,CANTORS_READ_DATA_MAX_LEN);
if (MyCalcCRC!=MyReadCRC_u16) {
//ошибка!
p->CounterWrongCRC++;
p->APIpacketMode=0;
break;
}//контрольная сумма принята и верна
CANtoRS_Analysis(p);
if (p->callback_go) { //если выставлен флаг, вызов callback
p->callback_go=0;
p->APIpacketMode=3; //обработка callback
}
else
p->APIpacketMode=0;
return;
}
break;
};
case 3: { //обработка callback
p->CounterRes++;
p->callback(&co1_vars, &(p->MSG));
p->APIpacketMode=0;
break;
};
default:
return;
}
}
return;
}
/*! Должна вызываться каждую секунду и отсылает
CAN пакеты HeartBeat. Если отослать не выходит (передача занята),
то сокращает последующий таймаут и, немного обождав, пытается
отправить заново */
//! \memberof TCANtoRS
void CANtoRS_HeartBeat(TCANtoRS *p) {
TZCanMsg MSG;
int16 i;
MSG.id=0xE<<7;//heartbeat
MSG.id|=*p->nodeID;//номер узла
MSG.dlc=1;//длина
for (i=0;i<8;MSG.data[i++]=0);//очистка
MSG.data[0]=5;//данные heartbeat
if (!CANtoRS_Write(&MSG,p)) { //если не получилось отправить
p->HeartCounter=(CANTORS_HEART_COUNTER_MAX-3); //вскоре пробуем сделать это еще раз
p->HeartBeatGo=1;//и если будет событие на отправку SDO, но будет знать, что надо пропустить
} else {
p->HeartBeatGo=0;
}
}
//! \memberof TCANtoRS
Uint16 CANtoRS_WriteHelper(TZCanMsg* MSG,TCANtoRS *p) {
if (p->HeartBeatGo) { //хочет отправиться HeartBeat
CANtoRS_HeartBeat(p);
p->MessDrop1++;
return 0;//сообщение теряем...
}
if (CANtoRS_Write(MSG,p))
p->CounterSended++;
else {
p->MessDrop2++;
return 0;
}
return 1;
}
/*! Из структуры CAN пакета формирует массив-посылку,
где вначале 4 бита - длина, потом 1 бит пропуск и 11 идентификатор.
Далее непосредственно данные. После конструирования посылка отправляется*/
//! \memberof TCANtoRS
Uint16 CANtoRS_Write(TZCanMsg* MSG,TCANtoRS *p) {
if (!p->PacketInWait) { //нет пакета в буфере
//копируем во временный буфер
p->bufMSG=*MSG;
p->PacketInWait=1;//флаг, что в буфере что-то есть
return 1;
//считается, что буфера на 1 позицию должно хватать
} else
return 0;
}
//! \memberof TCANtoRS
Uint16 CANtoRS_Write_Real(TZCanMsg* MSG,TCANtoRS *p) {
int16 i;
p->TempData[0]=(MSG->dlc & 0xF)<<4;
p->TempData[0]|=(MSG->id >> 8) & 7;
p->TempData[1]=MSG->id & 0xFF;
for (i=0;i<8;i++) p->TempData[i+2]=MSG->data[i];
CANtoRS_SendP(p->TempData,10,p);
return 1;
}
/*! Вызывается из миллисекундного таймера, отсчитывает 1 секунду
и вызывает функцию отправки HeartBeat. Заодно проверяет,
если в SCI возникла какая-то ошибка и он остановился, перезапускает.
*/
//! \memberof TCANtoRS
void CANtoRS_calc(TCANtoRS *p) {
//если в буфере есть пакет, ожидающий отправки и передатчик свободен и не ждет heartbeat
if (p->PacketInWait) {
if (!CANtoRS_Write_Real(&p->bufMSG,p))//отправить не удалось?
p->MessDrop2++;
p->PacketInWait=0;//очищаем буфер
}
else{//если пакета на отправк нет, обрабатывается всё остальное. Можно бы и обрабатывать сразу, но не хватает ресурсов
CANtoRS_Receive(p);
p->HeartCounter++; //счетчик для HeartBeat
//не пора ли отправить HeartBeat?
if (p->HeartCounter>=(CANTORS_HEART_COUNTER_MAX-1)) {
p->HeartCounter=0;
CANtoRS_HeartBeat(p);
}
}
}
/*@}*/

89
Vsrc/V_CurPar.c Normal file
View File

@ -0,0 +1,89 @@
/*!
Copyright 2017 АО "НИИЭТ" и ООО "НПФ ВЕКТОР"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file V_CurPar.c
\brief Расчет наблюдаемых текущих параметров (см. TCurPar)
\author ООО "НПФ Вектор". http://motorcontrol.ru
\version v 2.0 25/03/2016
*/
/** \addtogroup V_CurPar */
/*@{*/
#ifdef __cplusplus
extern "C" {
#endif
#include "DSP.h" // Device Headerfile and Examples Include File
#include "V_IQmath.h" // библиотека IQmath
#include "V_CurPar.h" // заголовочный файл
#include "main.h"
#ifdef __cplusplus
}
#endif
//! Инициализация модуля
//! Так, всяие обнуления...
//! \memberof TCurPar
void CurPar_init(TCurPar* p) {
//фильтры
p->fPower.T = _IQ(0.001); //фильтр мощности для вывода на экран
}
//!Расчет мощности из данных фаз
//!Расчет происходит в двухфазной системе координат, привязанной к статору
//!Для расчета используются мгнованнеые напряжения фаз UalphaRef, UbetaRef,
//!мгнованные токи фаз Ialpha, Ibeta. Для каждой из осей напряжение умножается на ток,
//!полученная мгновенная мощность суммируется с аналогичной мощностью по другой оси,
//!а затем полученная суммартная мгновенная мощность фильтруется инерционным звеном первого порядка.
//! \memberof TCurPar
void CurPar_PowerCalcUf(TCurPar* p) {
p->Ualpha = pwm.UalphaRef; //Напряжение заданное оси альфа
p->Ubeta = pwm.UbetaRef; //Напряжение заданное оси бета
//мгновенная мощность по осям альфа и бета подается на вход фильтра
p->fPower.input = _IQmpy(p->PowerK,
_IQmpy(p->Ualpha,p->Ialpha)+_IQmpy(p->Ubeta,p->Ibeta));
//расчет фильтра
p->fPower.calc(&p->fPower);
//результат работы фильтра - текущая активная мощность.
p->power = p->fPower.output;
}
//!Расчет текущих параметров привода
//! \memberof TCurPar
void CurPar_calc(TCurPar* p) {
CurPar_PowerCalcUf(p); //Расчет мощности
}
//! \memberof TCurPar
//Расчет внутреннего масштабирующего коэффицента мощности
//для приведения различных типов расчетов мощности к базовой мощности drv_params.power
void CurPar_slow_calc(TCurPar* p) {
float PowerMaxReal;
float PowerMaxScale;
PowerMaxReal = (float) drv_params.I_nom * drv_params.U_nom;
PowerMaxScale = _IQ6toF(drv_params.power);
p->PowerK = _IQmpy(_IQ(PowerMaxReal / PowerMaxScale), _IQ(3.0/2));//дробь 3/2 нужна для преобразования мощности от 2х фазного представления к 3х фазному
}
/*@}*/

605
Vsrc/V_DPR_eCAP.c Normal file
View File

@ -0,0 +1,605 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file V_DPR_eCAP.c
\brief Ìîäóëü äàò÷èêà àáñîëþòíîãî ïîëîæåíèÿ ðîòîðà ñ èñïîëüçîâàíèåì ìîäóëåé CAP TDPReCAP (ñì. TDPReCAP)
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 1.1 03/01/2013
*/
/** \addtogroup V_DPR_eCAP */
/*@{*/
#include "DSP.h" // Device Headerfile and Examples Include File
#include "V_IQmath.h" // áèáëèîòåêà IQmath
#include "V_DPR_eCAP.h" // çàãîëîâî÷íûé ôàéë ìîäóëÿ
#include "main.h"
extern TDrvParams drv_params;
//! Èíèöèàëèçàöèÿ
//!Ìîäóëè CAP_3, CAP_4, CAP_5 èíèöèàëèçèðóþòñÿ
//!äëÿ çàõâàòà âðåìåíè ìåæäó ñîáûòèÿìè íàðàñòàþùåãî è ñïàäàþùåãî
//!ôðîíòîâ, à òàêæå ãåíåðàöèè ïðåðûâàíèé ïî ýòèì ñîáûòèÿì.
//! \memberof TDPReCAP
void DPReCAP_Init(TDPReCAP* p) {
//Èíèöèàëèçàöèÿ ECAP1
ECAP0->ECEINT = 0x0000; // Disable all capture interrupts
ECAP0->ECCLR = 0xFFFF; // Clear all CAP interrupt flags
ECAP0->ECCTL0_bit.CAPLDEN = 0; // Disable CAP1-CAP4 register loads
ECAP0->ECCTL1_bit.TSCTRSTOP = 0; // Make sure the counter is stopped
ECAP0->ECCTL0_bit.PRESCALE = 0; // DIV1
// Configure peripheral registers
ECAP0->ECCTL1_bit.CONTOST = 0; // continuous mode
ECAP0->ECCTL0_bit.CAP0POL = 0; // rising edge
ECAP0->ECCTL0_bit.CAP1POL = 1; // falling edge
ECAP0->ECCTL0_bit.CTRRST0 = 0; // absolute time stamp
ECAP0->ECCTL0_bit.CTRRST1 = 0; // absolute time stamp
ECAP0->ECCTL1_bit.STOPWRAP = 1; // Wrap after Capture Event 2
// ECAP0->ECCTL1_bit.SYNCI_EN = 1; // Enable sync in
ECAP0->ECCTL1_bit.SYNCOSEL = 0; // Pass through
ECAP0->ECCTL0_bit.CAPLDEN = 1; // Enable capture units
ECAP0->ECCTL1_bit.TSCTRSTOP = 1; // Start Counter
ECAP0->ECCTL1_bit.REARM = 0; // Has no effect (Íå î÷åíü ïîíèìàþ ýòîò ðåãèñòð)
ECAP0->ECCTL0_bit.CAPLDEN = 1; // Enable CAP1-CAP4 register loads
ECAP0->ECEINT_bit.CEVT0 = 1; // 1 events = interrupt
ECAP0->ECEINT_bit.CEVT1 = 1; // 2 events = interrupt
//Èíèöèàëèçàöèÿ ECAP2
ECAP1->ECEINT = 0x0000; // Disable all capture interrupts
ECAP1->ECCLR = 0xFFFF; // Clear all CAP interrupt flags
ECAP1->ECCTL0_bit.CAPLDEN = 0; // Disable CAP1-CAP4 register loads
ECAP1->ECCTL1_bit.TSCTRSTOP = 0; // Make sure the counter is stopped
ECAP1->ECCTL0_bit.PRESCALE = 0; // DIV1
// Configure peripheral registers
ECAP1->ECCTL1_bit.CONTOST = 0; // continuous mode
ECAP1->ECCTL0_bit.CAP0POL = 0; // rising edge
ECAP1->ECCTL0_bit.CAP1POL = 1; // falling edge
ECAP1->ECCTL0_bit.CTRRST0 = 0; // absolute time stamp
ECAP1->ECCTL0_bit.CTRRST1 = 0; // absolute time stamp
ECAP1->ECCTL1_bit.STOPWRAP = 1; // Wrap after Capture Event 2
// ECAP1->ECCTL1_bit.SYNCI_EN = 1; // Enable sync in
ECAP1->ECCTL1_bit.SYNCOSEL = 0; // Pass through
ECAP1->ECCTL0_bit.CAPLDEN = 1; // Enable capture units
ECAP1->ECCTL1_bit.TSCTRSTOP = 1; // Start Counter
ECAP1->ECCTL1_bit.REARM = 0; // Has no effect (Íå î÷åíü ïîíèìàþ ýòîò ðåãèñòð)
ECAP1->ECCTL0_bit.CAPLDEN = 1; // Enable CAP1-CAP4 register loads
ECAP1->ECEINT_bit.CEVT0 = 1; // 1 events = interrupt
ECAP1->ECEINT_bit.CEVT1 = 1; // 2 events = interrupt
//Èíèöèàëèçàöèÿ ECap3
ECAP2->ECEINT = 0x0000; // Disable all capture interrupts
ECAP2->ECCLR = 0xFFFF; // Clear all CAP interrupt flags
ECAP2->ECCTL0_bit.CAPLDEN = 0; // Disable CAP1-CAP4 register loads
ECAP2->ECCTL1_bit.TSCTRSTOP = 0; // Make sure the counter is stopped
ECAP2->ECCTL0_bit.PRESCALE = 0; // DIV1
// Configure peripheral registers
ECAP2->ECCTL1_bit.CONTOST = 0; // continuous mode
ECAP2->ECCTL0_bit.CAP0POL = 0; // rising edge
ECAP2->ECCTL0_bit.CAP1POL = 1; // falling edge
ECAP2->ECCTL0_bit.CTRRST0 = 0; // absolute time stamp
ECAP2->ECCTL0_bit.CTRRST1 = 0; // absolute time stamp
ECAP2->ECCTL1_bit.STOPWRAP = 1; // Wrap after Capture Event 2
// ECAP2->ECCTL1_bit.SYNCI_EN = 1; // Enable sync in
ECAP2->ECCTL1_bit.SYNCOSEL = 0; // Pass through
ECAP2->ECCTL0_bit.CAPLDEN = 1; // Enable capture units
ECAP2->ECCTL1_bit.TSCTRSTOP = 1; // Start Counter
ECAP2->ECCTL1_bit.REARM = 0; // Has no effect (Íå î÷åíü ïîíèìàþ ýòîò ðåãèñòð)
ECAP2->ECCTL0_bit.CAPLDEN = 1; // Enable CAP1-CAP4 register loads
ECAP2->ECEINT_bit.CEVT0 = 1; // 1 events = interrupt
ECAP2->ECEINT_bit.CEVT1 = 1; // 2 events = interrupt
p->TsNom = ((SystemCoreClock / (drv_params.speed_nom * drv_params.p)) * 15*2);
//êîýôôèöèåíò äëÿ ïåðåñ÷åòà âðåìåíè ìåæäó ìåòêàìè â ìñ â ñêîðîñòü â îá/ìèí
//60 - îá/ìèí, 1000 ìñ â ñåêóíäå, 6 ìåòîê íà ýë. îáîðîò
p->TsNomMilsec = (60.0*1000 / (6*drv_params.speed_nom * drv_params.p));
DPReCAP_Angle6Calc(p);
p->CAP_WrongEdgeCnt = 0;
}
//! Îïðåäåëåíèå óãëîâîãî ïîëîæåíèÿ ñ äèñêðåòíîñòüþ 60 ãðàäóñîâ
//!Îïðåäåëåíèå óãëîâîãî ïîëîæåíèÿ ïðîèñõîäèò èñõîäÿ èç îïðîñà òðåõ êàíàëîâ äàò÷èêà
//!÷åðåç GPIO. Ðåçóëüòàò ïîïàäàåò â ïåðåìåííóþ Angle6.
//! \memberof TDPReCAP
void DPReCAP_Angle6Calc(TDPReCAP* p) {
// Íà ìîìåíò ðàñ÷¸òà, çàïðåùàåì ïðåðûâàíèÿ ïî äàò÷èêàì.
//Åñëè ýòîãî íå ñäåëàòü, òî ýòà ôóíêöèÿ ìîæåò âûçâàòüñÿ â 10ê,
//íà ïîëîâíå ïðåðâàòüñÿ ïðåðûâàíèåì CAP, â êîòîðîì îíà âûçîâåòñÿ âòîðîé ðàç,
//ïîòîì óïðàâëåíèå âåðíåòñÿ ê ýòîé ôóíêöèè â 10ê è â p->Angle6 ïîïàäåò ñòàðûé ðåçóëüòàò
ECAP0->ECEINT = 0x0000;
ECAP1->ECEINT = 0x0000;
ECAP2->ECEINT = 0x0000;
// Ôîðìèðóåì êîä ïî ñîñòîÿíèþ íîæåê.
p->HallCode = 0;
#if defined(HW_VECTORCARD_SIMULATOR) || defined(HW_NIIET_BOARD_SIMULATOR)
p->HallCode = model.hallSensor;
#else
if (p->UserDirection == 0) {
if (GPIOA->DATA & (1 << 4))
p->HallCode = p->HallCode + 1;
if (GPIOA->DATA & (1 << 5))
p->HallCode = p->HallCode + 2;
if (GPIOA->DATA & (1 << 6))
p->HallCode = p->HallCode + 4;
} else {
if (GPIOA->DATA & (1 << 4))
p->HallCode = p->HallCode + 4;
if (GPIOA->DATA & (1 << 5))
p->HallCode = p->HallCode + 2;
if (GPIOA->DATA & (1 << 6))
p->HallCode = p->HallCode + 1;
}
#endif
switch (p->HallCode) {
case 5: // 0
p->Angle6 = 0;
break;
case 4: // 60
p->Angle6 = _IQ(1.0 / 6.0);
break;
case 6: // 120
p->Angle6 = _IQ(1.0 / 3.0);
break;
case 2: //180
p->Angle6 = _IQ(1.0 / 2.0);
break;
case 3: // 240
p->Angle6 = _IQ(2.0 / 3.0);
break;
case 1: // 300
p->Angle6 = _IQ(5.0 / 6.0);
break;
}
// Ðàçðåøàåì ïðåðûâàíèÿ íàçàä.
ECAP0->ECEINT = 6;
ECAP1->ECEINT = 6;
ECAP2->ECEINT = 6;
}
void DPReCAP_AngleErrorCalc(TDPReCAP* p) {
long AngleDiff = 0;
AngleDiff = (labs(
((p->Angle6 - p->AnglePrev + _IQ(0.5)) & 0x00FFFFFF) - _IQ(0.5)))
& 0x00FFFFFF;
p->AnglePrev = p->Angle6;
if (AngleDiff > _IQ(61.0 / 360)) { //åñëè óãîë ñ ïðîøëîãî ðàçà èçìåíèëñÿ áîëüøå, ÷åì íà 60 ãðàäóñîâ, òî äàò÷èê êîñÿ÷èò
p->WrongCodeCounter++;
p->WrongCodeCounterPerSec++;
}
}
//! Îïðåäåëåíèå óãëîâîãî ïîëîæåíèÿ ñ ó÷åòîì ðàáîòû èíòåðïîëÿòîðà óãëîâîãî ïîëîæåíèÿ
//!Èíòåðïîëÿòîð óãëîâîãî ïîëîæåíèÿ (à âåðíåå äàæå ýêñòðàïîëÿòîð)
//!èñïîëüçóåò äèñêðåòíîå óãëîâîå ïîëîæåíèå Angle6, âûäàâàåìîå ôóíêöèåé DPReCAP_Angle6Calc.
//!Ôóíêöèÿ "ñãëàæèâàåò" óãëîâîå ïîëîæåíèå âî âðåìåíè, äåëàÿ èç ñòåïåí÷àòîé ñìåíû óãëà "ëåñåíêîé"
//!íåïðåðûâíóþ "ïèëó" (ïåðåìåííàÿ Angle). Äëÿ ýòîãî èñïîëüçóåòñÿ ñîõðàíåííîå âðåìÿ ìåæäó äâóìÿ ëþáûìè
//!ïðåäûäóùèìè ôðîíòàìè ñ êàíàëîâ äàò÷èêà ïîëîæåíèÿ (PrevTs). Ñ÷èòàÿ, ÷òî ñêîðîñòü âðàùåíèÿ ïîñòîÿííà,
//!ñëåäóþùèé ôðîíò (à çíà÷èò ñìåíó óãëîâîãî ïîëîæåíèÿ) ìîæíî ïðîãíîçèðîâàòü ÷åðåç òî æå ñàìîå âðåìÿ.
//!Òàêèì îáðàçîì, ó òåêóùåìó äèñêðåòíîìó óãëîâîìó ïîëîæåíèþ Angle6 ïðèáàâëÿåòñÿ
//!äîáàâêà, ðàññ÷èòûâàåìàÿ ïî ôîðìóëå 60*(Òåêóùåå âðåìÿ/Ïåðèîä).
//!Òàê, â ìîìåíò ïðèõîäà ôðîíòà ñ äàò÷èêà ïåðåìåííàÿ Angle ðàâíà Angle6. ×åðåç íåêîòîðûé ìîìåíò âðåìåíè
//! Angle ñòàíåò ðàâíûì Angle6+60*(delta/Ts), ãäå delta - òåêóùåå âðåìÿ ñ ìîìåíòà ñîáûòèÿ ïîñëåäíåãî ôðîíòà ñ äàò÷èêà,
//! à Ts - ïåðèîä, âðåìÿ ìåæäó ïðåäûäóùèìè äâóìÿ ñîáûòèÿìè ôðîíðîâ äàò÷èêà.
//! Ôóíêöèÿ òàêæå ó÷èòûâàåò íàïðàâëåíèå âðàùåíèÿ, à òàêæå äîáàâëÿåò ïîëüçîâàòåëüñêîå ñìåùåíèå
//! AngleOffset ê ðåçóëüòèðóþùåìó óãëîâîìó ïîëîæåíèþ.
//! \memberof TDPReCAP
void DPReCAP_AngleCalc(TDPReCAP* p) {
Uint32 delta, Timer;
Uint32 PrevTs;
_iq Angle;
_iq Angle6;
// Ôèêñèðóåì çíà÷åíèÿ ïåðåìåííûõ íà ìîìåíò íà÷àëà ðàñ÷¸òà
Angle6 = p->Angle6;
#if (!defined(HW_VECTORCARD_SIMULATOR)) && (!defined(HW_NIIET_BOARD_SIMULATOR))
PrevTs = p->PrevTs;
// Íà ìîìåíò ðàñ÷¸òà, çàïðåùàåì ïðåðûâàíèÿ ïî äàò÷èêàì.
ECAP0->ECEINT = 0x0000;
ECAP1->ECEINT = 0x0000;
ECAP2->ECEINT = 0x0000;
// Ôèêñèðóåì çíà÷åíèå îäíîãî èç òàéìåðîâ íà ìîìåíò íà÷àëà âûïîëíåíèÿ ìîäóëÿ.
switch (p->DPReCAP_FLG1.bit.CAPnumber) {
case 1:
Timer = ECAP0->TSCTR;
break;
case 2:
Timer = ECAP1->TSCTR;
break;
case 3:
Timer = ECAP2->TSCTR;
break;
}
// Åñëè ñêîðîñòü ðàâíà íóëþ èëè âûáðàí ñîîòâåòñòâóþùèé ðåæèì, òî óãîë íå èíòåïîëèðóåì.
if ((p->speed == 0) || (p->DPReCAP_FLG1.bit.AngleMode == 0)
|| (p->Ts == 0)) {
Angle = _IQ(1.0 / 12);
} else {
delta = Timer - PrevTs; // Ñêîëüêî íàòèêàë òàéìåð ñ ìîìåíòà ïðîøëîãî îáíîâëåíèÿ ïåðèîäà.
Angle = _IQdiv(delta, p->Ts); // Èíòåïîëèðóåì óãîë. Îòíîøåíèå ïðîøëîãî ïåðåõîäà ê òåêóùèì "òèêàì".
if (Angle >= _IQ(1.0 / 6.0)) // îãðàíè÷èâàåì óãîë â ïðèäåëàõ 1/6.
Angle = _IQ(1.0 / 6.0);
}
#else //ñèìóëÿòîð
Angle=_IQ(model.hallSensorInterpAdd * (1/(2*MOTOR_MODEL_PI)));//ïðèðàùåíèå óãëà äëÿ èíòåðïîëÿòîðà óæå ïðåäïîñ÷èòàíî â ìîäåëè äâèãàòåëÿ ñ ó÷åòîì äèñêðåòíîñòè
#endif
if (p->DPReCAP_FLG1.bit.Dir == 1)
Angle = _IQ(1.0/6.0) - Angle;
if (p->UserDirection) //ïîëüçîâàòåëüñêàÿ èíâåðñèÿ íàïðàâëåíèÿ
Angle = -Angle + _IQ(1.0/6);
p->Angle = Angle6 + Angle + p->AngleOffset;
p->Angle &= 0x00FFFFFF;
// Ðàçðåøàåì ïðåðûâàíèÿ íàçàä.
ECAP0->ECEINT = 6;
ECAP1->ECEINT = 6;
ECAP2->ECEINT = 6;
}
//! Ôóíêöèÿ ðàñ÷åòà ñêîðîñòè
//!Äëÿ ðàñ÷åòà ñêîðîñòè èñïîëüçóåòñÿ ïåðåìåííàÿ Tspeed,
//!êîòîðàÿ ïðåäñòàâëÿåò ñîáîé âðåìÿ ìåæäó ñîáûòèÿìè ôðîíòîâ äàò÷èêà ïîëîæåíèÿ
//!ïðîèçîøåäøèõ ïî îäíîìó è òîìó æå êàíàëó. Òàê, íàïðèìåð, âðåìåíåì ìåæäó íàðàñòàþùèì è ñïàäàþùèì ôðîíòîì
//!êàíàëà CAP3, çàòåì ìåæäó ñïàäàþùèì è íàðàñòàþùèì ôðîíòîì CAP4 è ò.ï.
//!Íà îñíîâå ýòîãî âðåìåíè, íàïðàâëåíèÿ âðàùåíèÿ è ïðåäïîñ÷èòàííîé êîíñòàíòîé TsNom
//!ðàññ÷èòûâàåòñÿ ñêîðîñòü âðàùåíèÿ.
//! \memberof TDPReCAP
void DPReCAP_SpeedCalc(TDPReCAP* p) {
#if (!defined(HW_VECTORCARD_SIMULATOR)) && (!defined(HW_NIIET_BOARD_SIMULATOR))
_iq speed;
// Ñ÷èòàåì ñêîðîñòü â îòíîñèòåëüíûõ åäèíèöàõ îòíîñèòåëüíî íîìèíàëüíîé.
if ((p->Tspeed != 0) && (p->DPReCAP_FLG1.bit.ZeroFLG == 0)) {
// Çíàê ñêîðîñòè îïðäåëÿåòñÿ â çàâèñèìîñòè îò íàïðàâëåíèÿ.
if (p->DPReCAP_FLG1.bit.Dir == 0)
speed = _IQdiv(p->TsNom, p->Tspeed);
else
speed = -_IQdiv(p->TsNom, p->Tspeed);
if (p->UserDirection) { //çàäàåòñÿ ïîëüçîâàòåëåì
speed = -speed;
}
} else {
speed = 0;
}
p->speed = speed;
DINT;//íóæíî äëÿ ïîòîêîáåçîïàñíîãî îáðàùåíèÿ ê ïåðåìåííîé DPReCAP_FLG1 (÷òîáû íå ïåðåòåðåòü ïðèñâàèâàíèå â ïðåðûâàíèè çàõâàòà)
// Îáíóëåíèå ñêîðîñòè, åñëè ïðèâûñèëè çàäàííîå âðåìÿ ìåæäó äâóìÿ ñîñåäíèìè ñîáûòèÿìè.
if (p->milsec > p->milsecFIX) {
p->speed = 0;
p->DPReCAP_FLG1.bit.ZeroFLG = 1;
// p->cnt1 = 0; // Íàäî îáíóëÿòü ïðè ñòîïå è hold'å. Çäåñü íå íàäî, òîëüêî äëÿ òåñòà.
}
EINT;
DINT;//íóæíî äëÿ ïîòîêîáåçîïàñíîãî îáðàùåíèÿ ê ïåðåìåííîé DPReCAP_FLG1 (÷òîáû íå ïåðåòåðåòü ïðèñâàèâàíèå â ïðåðûâàíèè çàõâàòà)
// Ïðè ñêîðîñòè ìåíüøå çàäàííîé, îòêëþ÷àåì èíòåðïîëÿöèþ óãëà.
if ((labs(p->speed)) <= (p->speedMIN))
p->DPReCAP_FLG1.bit.SpeedMinFLG = 0;
else
p->DPReCAP_FLG1.bit.SpeedMinFLG = 1;
EINT;
#else //ñèìóëÿòîð
p->speed=p->SimulatorOmega2IQ_factor*model.hallSensorOmega;//×àñòîòà âðàùåíèÿ óæå ïðåäïîñ÷èòàíà â ìîäåëè äâèãàòåëÿ ñ ó÷åòîì äèñêðåòíîñòè
#endif
}
//! Ôóíêöèÿ, âûçûâàåìàÿ â ïðåðûâàíèè ïî íàðàñòàþùåìó è ñïàäàþùåìó ôðîíòó êàíàëà äàò÷èêà 1
//! Â ôóíêöèè çàïîìèíàåòñÿ âðåìÿ òàéìåðà ìîäóëÿ CAP â ïåðåìåííóþ Timer1.
//! Èñõîäÿ èç ýòîãî ñ÷èòàþòñÿ äâå ïåðåìåííûå - p->Ts, âðåìÿ ìåæäó äâóìÿ áëèæàéøèìè ôðîíòàìè,
//!íåîáõîäèìîå äëÿ èíòåðïîëÿòîðà óãëîâîãî ïîëîæåíèÿ, è ïåðåìåííàÿ p->Tspeed,
//!âðåìÿ ìåæäó äâóìÿ ôðîíòàìè îäíîãî è òîãî æå êàíàëà, íåîáîäèìîå äëÿ ðàñ÷åòà ñêîðîñòè.
//! \memberof TDPReCAP
void DPReCAP_CAP1Calc(TDPReCAP* p) {
Uint32 Timer=0;
if (p->cnt >= 2) {
p->cnt=2;
p->HelpCalc(p);
// Â çàâèñèìîñòè îò íîìåðà ïðåäóäûùåãî CAP îïðåäåëÿåì íàïðàâëåíèå âðàùåíèÿ.
if (p->DPReCAP_FLG1.bit.CAPnumber == 3)
p->DPReCAP_FLG1.bit.Dir = 0;
if (p->DPReCAP_FLG1.bit.CAPnumber == 2)
p->DPReCAP_FLG1.bit.Dir = 1;
if (p->DPReCAP_FLG1.bit.CAPnumber == 1) {
if (p->DPReCAP_FLG1.bit.PrevDir == 0)
p->DPReCAP_FLG1.bit.Dir = 1;
else
p->DPReCAP_FLG1.bit.Dir = 0;
}
if (p->DPReCAP_FLG1.bit.Dir != p->DPReCAP_FLG1.bit.PrevDir) {
p->DPReCAP_FLG1.bit.PrevDir = p->DPReCAP_FLG1.bit.Dir;
p->cnt2 = 1;
}
if (ECAP0->ECFLG_bit.CEVT0==1)//Ôðîíò ââåðõ
{
Timer = ECAP0->CAP0;
}
if (ECAP0->ECFLG_bit.CEVT1==1)//Ôðîíò âíèç
{
Timer = ECAP0->CAP1;
}
// ñ÷èòàåì ïåðèîäû äëÿ ðàñ÷¸òà óãëà è ñêîðîñòè.
p->Ts = (Timer - p->PrevTs) * 6;
p->PrevTs = Timer;
p->Tspeed = Timer - p->PrevTspeed1;
p->PrevTspeed1 = Timer;
} else {
p->Ts = 0;
p->Tspeed = 0;
}
p->cnt++;
p->milsec = 0;
p->DPReCAP_FLG1.bit.CAPnumber = 1;
}
//! Ôóíêöèÿ, âûçûâàåìàÿ â ïðåðûâàíèè ïî íàðàñòàþùåìó è ñïàäàþùåìó ôðîíòó êàíàëà äàò÷èêà 2
//! Â ôóíêöèè çàïîìèíàåòñÿ âðåìÿ òàéìåðà ìîäóëÿ CAP â ïåðåìåííóþ Timer1.
//! Èñõîäÿ èç ýòîãî ñ÷èòàþòñÿ äâå ïåðåìåííûå - p->Ts, âðåìÿ ìåæäó äâóìÿ áëèæàéøèìè ôðîíòàìè,
//!íåîáõîäèìîå äëÿ èíòåðïîëÿòîðà óãëîâîãî ïîëîæåíèÿ, è ïåðåìåííàÿ p->Tspeed,
//!âðåìÿ ìåæäó äâóìÿ ôðîíòàìè îäíîãî è òîãî æå êàíàëà, íåîáîäèìîå äëÿ ðàñ÷åòà ñêîðîñòè.
//! \memberof TDPReCAP
void DPReCAP_CAP2Calc(TDPReCAP* p) {
Uint32 Timer=0;
if (p->cnt >= 2) {
p->cnt=2;
p->HelpCalc(p);
// Â çàâèñèìîñòè îò íîìåðà ïðåäóäûùåãî CAP îïðåäåëÿåì íàïðàâëåíèå âðàùåíèÿ.
if (p->DPReCAP_FLG1.bit.CAPnumber == 1)
p->DPReCAP_FLG1.bit.Dir = 0;
if (p->DPReCAP_FLG1.bit.CAPnumber == 3)
p->DPReCAP_FLG1.bit.Dir = 1;
if (p->DPReCAP_FLG1.bit.CAPnumber == 2) {
if (p->DPReCAP_FLG1.bit.PrevDir == 0)
p->DPReCAP_FLG1.bit.Dir = 1;
else
p->DPReCAP_FLG1.bit.Dir = 0;
}
if (p->DPReCAP_FLG1.bit.Dir != p->DPReCAP_FLG1.bit.PrevDir) {
p->DPReCAP_FLG1.bit.PrevDir = p->DPReCAP_FLG1.bit.Dir;
p->cnt2 = 1;
}
if (ECAP1->ECFLG_bit.CEVT0==1)
{
Timer = ECAP1->CAP0;
}
if (ECAP1->ECFLG_bit.CEVT1==1)
{
Timer = ECAP1->CAP1;
}
// ñ÷èòàåì ïåðèîäû äëÿ ðàñ÷¸òà óãëà è ñêîðîñòè.
p->Ts = (Timer - p->PrevTs) * 6;
p->PrevTs = Timer;
p->Tspeed = Timer - p->PrevTspeed2;
p->PrevTspeed2 = Timer;
} else {
p->Ts = 0;
p->Tspeed = 0;
}
p->cnt++;
p->milsec = 0;
p->DPReCAP_FLG1.bit.CAPnumber = 2;
}
//! Ôóíêöèÿ, âûçûâàåìàÿ â ïðåðûâàíèè ïî íàðàñòàþùåìó è ñïàäàþùåìó ôðîíòó êàíàëà äàò÷èêà 3
//! Â ôóíêöèè çàïîìèíàåòñÿ âðåìÿ òàéìåðà ìîäóëÿ CAP â ïåðåìåííóþ Timer1.
//! Èñõîäÿ èç ýòîãî ñ÷èòàþòñÿ äâå ïåðåìåííûå - p->Ts, âðåìÿ ìåæäó äâóìÿ áëèæàéøèìè ôðîíòàìè,
//!íåîáõîäèìîå äëÿ èíòåðïîëÿòîðà óãëîâîãî ïîëîæåíèÿ, è ïåðåìåííàÿ p->Tspeed,
//!âðåìÿ ìåæäó äâóìÿ ôðîíòàìè îäíîãî è òîãî æå êàíàëà, íåîáîäèìîå äëÿ ðàñ÷åòà ñêîðîñòè.
//! \memberof TDPReCAP
void DPReCAP_CAP3Calc(TDPReCAP* p) {
Uint32 Timer;
if (p->cnt >= 2) {
p->cnt=2;
p->HelpCalc(p);
// Â çàâèñèìîñòè îò íîìåðà ïðåäóäûùåãî CAP îïðåäåëÿåì íàïðàâëåíèå âðàùåíèÿ.
if (p->DPReCAP_FLG1.bit.CAPnumber == 2)
p->DPReCAP_FLG1.bit.Dir = 0;
if (p->DPReCAP_FLG1.bit.CAPnumber == 1)
p->DPReCAP_FLG1.bit.Dir = 1;
if (p->DPReCAP_FLG1.bit.CAPnumber == 3) {
if (p->DPReCAP_FLG1.bit.PrevDir == 0)
p->DPReCAP_FLG1.bit.Dir = 1;
else
p->DPReCAP_FLG1.bit.Dir = 0;
}
if (p->DPReCAP_FLG1.bit.Dir != p->DPReCAP_FLG1.bit.PrevDir) {
p->DPReCAP_FLG1.bit.PrevDir = p->DPReCAP_FLG1.bit.Dir;
p->cnt2 = 1;
}
if (ECAP2->ECFLG_bit.CEVT0==1)
{
Timer = ECAP2->CAP0;
}
if (ECAP2->ECFLG_bit.CEVT1==1)
{
Timer = ECAP2->CAP1;
}
// ñ÷èòàåì ïåðèîäû äëÿ ðàñ÷¸òà óãëà è ñêîðîñòè.
p->Ts = (Timer - p->PrevTs) * 6;
p->PrevTs = Timer;
p->Tspeed = Timer - p->PrevTspeed3;
p->PrevTspeed3 = Timer;
} else {
p->Ts = 0;
p->Tspeed = 0;
}
p->cnt++;
p->milsec = 0;
p->DPReCAP_FLG1.bit.CAPnumber = 3;
}
void DPReCAP_calc_10k(TDPReCAP* p) {
DINT;
if (p->CAPCalcEna1==0){
p->CAPCalcEna1=1;
ECAP0->ECCLR_bit.CEVT0 = 1;
ECAP0->ECCLR_bit.CEVT1 = 1;
ECAP0->ECCLR_bit.INT = 1;
}
if (p->CAPCalcEna2==0){
p->CAPCalcEna2=1;
ECAP1->ECCLR_bit.CEVT0 = 1;
ECAP1->ECCLR_bit.CEVT1 = 1;
ECAP1->ECCLR_bit.INT = 1;
}
if (p->CAPCalcEna3==0){
p->CAPCalcEna3=1;
ECAP2->ECCLR_bit.CEVT0 = 1;
ECAP2->ECCLR_bit.CEVT1 = 1;
ECAP2->ECCLR_bit.INT = 1;
}
EINT;
}
void DPReCAP_HelpCalc(TDPReCAP* p) {
// Îáíóëÿåì ñêîðîñòü è âûñòàâëÿåì ôëàã,
// åñëè âðåìÿ ìåæäó äâóìÿ ñîáûòèÿìè áîëüøå çàäàííîãî.
if (p->milsec > p->milsecFIX) {
p->speed = 0;
p->DPReCAP_FLG1.bit.ZeroFLG = 1;
} else {
p->DPReCAP_FLG1.bit.ZeroFLG = 0;
}
}
void DPReCAP_SlowCalc(TDPReCAP* p) {
//ôîðìóëà äëÿ ðàñ÷åòà T=Ts/Tfiltra ãäå - Tfiltra ïîñòîÿííàÿ âðåìåíè ôèëüòðà
// p->AngleFilter_1_T=_IQdiv(FAST_CALC_TS,AngleFilterT);
if (p->enabled)
if (p->initialized==0){
p->Init(p);
GPIOA->ALTFUNCSET = (1 << 4) + (1 << 5) + (1 << 6);
GPIOA->DENSET = (1 << 4) + (1 << 5) + (1 << 6);
SIU->REMAPAF_bit.ECAP0EN = 1;
SIU->REMAPAF_bit.ECAP1EN = 1;
SIU->REMAPAF_bit.ECAP2EN = 1;
p->initialized=1;
}
}
void DPReCAP_msCalc(TDPReCAP* p) {
p->milsec++;//ñ÷åò÷èê âðåìåíè îòñóòñòâèÿ ìåòîê
if (p->milsecREF != p->milsecPrevREF) {
p->milsecFIX=p->milsecREF;
p->speedMinREF = _IQdiv(p->TsNomMilsec, p->milsecFIX);
p->milsecPrevREF = p->milsecREF;
}
p->ErrorLevelTimeCounterBig++;
if (p->ErrorLevelTimeCounterBig > 10000) {
p->ErrorLevel = p->ErrorLevelCounter;
p->ErrorLevelCounter = 0;
p->ErrorLevelTimeCounterBig = 0;
}
p->ErrorLevelTimeCounter++;
if (p->ErrorLevelTimeCounter > 1000) {
if (p->WrongCodeCounterPerSec > p->WrongCodeCounterLimitPerSec){
p->SensorFault = 1;
} else
p->SensorFault = 0;
p->WrongCodeCounterPerSec=0;
p->ErrorLevelTimeCounter = 0;
}
if (p->CAP_WrongEdgeCntPrev != p->CAP_WrongEdgeCnt)
p->ErrorLevelCounter++;
p->CAP_WrongEdgeCntPrev = p->CAP_WrongEdgeCnt;
}
/*@}*/

217
Vsrc/V_Global_time.c Normal file
View File

@ -0,0 +1,217 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file Global_time.c
\brief Ìîäóëü ðàáîòû ñî âðåìåíåì
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 1.2 2013_10_16
*/
/** \addtogroup Global_time */
/*@{*/
#ifdef __cplusplus
extern "C" {
#endif
#include <main.h>
//!Èíèöèàëèçàöèß ìîäóëß
//!Åñëè åñòü ÷àñû ðåàëüíîãî âðåìåíè, ñ÷èòûâàåò èç íèõ âðåìß.
//!Âîññòàíàâëèâàåò âðåìß ðàáîòû è âðåìåíè âêëþ÷åííîãî ñîñòîßíèß èç SPI.
//! \memberof TGlobalTime
void GlobalTime_init(TGlobalTime *p)
{
p->read_PowerOn_time(p);
p->read_oper_time(p);
#ifdef USE_ABSOLUTE_TIME_CLOCK
//èíèöèàëèçàöèß àáñîëþòíîãî âðåìåíè
if (p->time_type == 1)
{
//èíèöèàëèçàöèß èç ÷àñîâ ðåàëüíîãî âðåìåíè
p->absolute_time.day=spiclock.day;
p->absolute_time.hour=spiclock.hour;
p->absolute_time.minute=spiclock.minute;
p->absolute_time.second=spiclock.second;
p->absolute_time.year=spiclock.year;
}
#endif
//èíèöèàëèçàöèß îòíîñèòåëüíîãî âðåìåíè
p->relative_time1.ON = 1;//ò.ê. 1-å âðåìß ßâëßåòñß îáßçàòåëüíûì
p->relative_time1.relative_date.hour = (p->PowerOn_time >> 6);
p->relative_time1.relative_date.minute = (p->PowerOn_time & 0x3f);
p->relative_time2.relative_date.hour = (p->operational_time >> 6);
p->relative_time2.relative_date.minute = (p->operational_time & 0x3f);
}
//!Ðàñ÷åò îòíîñèòåëüíîãî âðåìåíè.
//!Âûçûâàåò ôóíêöèè ðàñ÷åòà îòíîñèòåëüíî âðåìåíè è, åñëè åñòü, ñ÷èòûâàåò âðåìß
//!ñ ìîäóëß ÷àñîâ ðåàëüíîãî âåðìåíè â àáñîëþòíîå âðåìß.
//! \memberof TGlobalTime
void GlobalTime_calc(TGlobalTime *p)
{
//ñ÷åò îòíîñèòåëüíûõ âðåìåí
GlobalTime_REL_TIME_calc(&p->relative_time1);
GlobalTime_REL_TIME_calc(&p->relative_time2);
}
//!Ðàñ÷åò îòíîñèòåëüíîãî âðåìåíè.
//!Âûçûâàåò ôóíêöèè ðàñ÷åòà îòíîñèòåëüíî âðåìåíè è, åñëè åñòü, ñ÷èòûâàåò âðåìß
//!ñ ìîäóëß ÷àñîâ ðåàëüíîãî âåðìåíè â àáñîëþòíîå âðåìß.
//! \memberof TGlobalTime
void GlobalTime_ms_calc(TGlobalTime *p) {
//óïðàâëåíèå ñ÷åòîì operational_time
if (sm_ctrl.state != 0) //Åñëè â êàêîì-òî ðåæèìå ðàáîòû
global_time.relative_time2.ON = TRUE;
else
global_time.relative_time2.ON = FALSE;
//Âðåìß çàïèòàííîãî ñîñòîßíèß â ìèíóòàõ
p->PowerOn_time = (global_time.relative_time1.relative_date.hour << 6) + (global_time.relative_time1.relative_date.minute & 0x3f);
//Âðåìß â ðàáîòå, â ìèíóòàõ
p->operational_time = (global_time.relative_time2.relative_date.hour << 6) + (global_time.relative_time2.relative_date.minute & 0x3f);
p->PowerOn_time_min = p->relative_time1.relative_date.hour*60 +p->relative_time1.relative_date.minute;
p->operational_time_min = p->relative_time2.relative_date.hour*60 + p->relative_time2.relative_date.minute;
#ifdef USE_ABSOLUTE_TIME_CLOCK
if (global_time.time_type == 1) {
//âðåìß - èç ÷àñîâ ðåàëüíîãî âðåìåíè
global_time.absolute_time.day = spiclock.day;
global_time.absolute_time.hour = spiclock.hour;
global_time.absolute_time.minute = spiclock.minute;
global_time.absolute_time.second = spiclock.second;
global_time.absolute_time.year = spiclock.year;
}
#endif
}
//!Ðàñ÷åò îòíîñèòåëüíîãî âðåìåíè
//!Ó÷èòûâàß, ÷òî ôóíêöèß âûçûâàåòñß ñ êàêîé-òî îïðåäåëåííîé äèñêðåòèçàöèåé,
//!èíêðåìåíòèðóåò îòíîñèòåëüíîå âðåìß, ïåðåäåííîå åé â ñòðóêòóðå òèïà RELATIVE_TIME
//! \memberof TGlobalTime
void GlobalTime_REL_TIME_calc(RELATIVE_TIME *p) {
if (p->ON == 0)
return;
if (p->tic_isr != 0)
p->tic_isr--;
p->delta_millisecond = 0;
p->delta_second = 0;
if (p->tic_isr == 0) {
//ìèëëèñåêóíäà
p->tic_isr = GLOBAL_TIME_CALC_FREQ;
p->millisecond_counter++;
p->delta_millisecond = 1;
if (p->relative_date.millisecond == 999) {
//ñåêóíäà
p->relative_date.millisecond = 0;
p->second_counter++;
p->delta_second = 1;
if (p->relative_date.second == 59) {
//ìèíóòà
p->relative_date.second = 0;
if (p->relative_date.minute == 59) {
//÷àñ
p->relative_date.minute = 0;
p->relative_date.hour++;
} else
p->relative_date.minute++;
} else
p->relative_date.second++;
} else
p->relative_date.millisecond++;
}
}
//!×èòàåò âðåìß íàðàáîòêè.
//! \memberof TCurPar
void GlobalTime_read_PowerOn_time(TGlobalTime *p) { //÷òåíèå work_time
UserMem.MemStartAddr = GLOBAL_TIME_POWER_ON_TIME_ADDR;
UserMem.MCUStartAddr = (Uint16*) (&(p->PowerOn_time));
UserMem.data_length = 4;
UserMem.read(&UserMem);
}
//!çàïèñûâàåò âðåìß íàðàáîòêè.
//! \memberof TCurPar
void GlobalTime_write_PowerOn_time(TGlobalTime *p) { //çàïèñü work_time
UserMem.MemStartAddr = GLOBAL_TIME_POWER_ON_TIME_ADDR;
UserMem.MCUStartAddr = (Uint16*) (&(p->PowerOn_time));
UserMem.data_length = 4;
UserMem.write(&UserMem);
}
//!×èòàåò âðåìß âêëþ÷åííîãî ñîñîòßíèß.
//! \memberof TCurPar
void GlobalTime_read_oper_time(TGlobalTime *p) { //÷òåíèå operational_time
UserMem.MemStartAddr = GLOBAL_TIME_OPERATIONAL_TIME_ADDR;
UserMem.MCUStartAddr = (Uint16*) (&(p->operational_time));
UserMem.data_length = 4;
UserMem.read(&UserMem);
}
//!çàïèñûâàåò âðåìß âêëþ÷åííîãî ñîñîòßíèß.
//! \memberof TCurPar
void GlobalTime_write_oper_time(TGlobalTime *p) { //çàïèñü operational_time
UserMem.MemStartAddr = GLOBAL_TIME_OPERATIONAL_TIME_ADDR;
UserMem.MCUStartAddr = (Uint16*) (&(p->operational_time));
UserMem.data_length = 4;
UserMem.write(&UserMem);
}
void GlobalTime_slow_calc(TGlobalTime*p) {
//åñëè ñòîèò ôëàã íà ñîõðàíåíèå âðåìåí â SPI èëè ñ ìîìåíò ïðîøëîé çàïèñè ïðîøåë ÷àñ
if ((p->WtiteSPI_flag) || (p->PrevWriteSPIHour != global_time.relative_time1.relative_date.hour)) {
p->write_PowerOn_time(p); //çàïèñü âðåìåíè âêë. ñîñòîßíèß
p->write_oper_time(p); //çàïèñü ðàáî÷åãî âðåìåíè
p->PrevWriteSPIHour = global_time.relative_time1.relative_date.hour;
p->WtiteSPI_flag = 0;
}
}
#ifdef __cplusplus
} // Extern "C"
#endif
/*@}*/

280
Vsrc/V_IQmath.c Normal file
View File

@ -0,0 +1,280 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file V_IQmath.c
\brief Áèáëèîòåêà ôóíêöèé öåëî÷èñëåííîé ìàòåìàòèêè
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 2.0 25/03/2016
\addtogroup V_IQmath
@{*/
#include "V_IQmath.h"
#include "stdlib.h"
#include "math.h"
#if defined (__GNUC__) || defined (CMCPPARM)
#if defined (__GNUC__)
// Count leading zeros, using processor-specific instruction if available.
#define clz(x) __builtin_clzl(x)
#endif
#if defined (CMCPPARM) //CodeMaster
#define clz(x) __CLZ(x)
#endif
#else
static uint8_t clz(uint32_t x) {
uint8_t result = 0;
if (x == 0) return 32;
while (!(x & 0xF0000000)) {
result += 4;
x <<= 4;
}
while (!(x & 0x80000000)) {
result += 1;
x <<= 1;
}
return result;
}
#endif
//! Äåëåíèå äâóõ ÷èñåë â ôîðìàòå 22.10
//! \memberof V_IQmath
int32 _IQ10div(int32 a, int32 b) {
if (b == 0)
return 0;
return _IQ10((float )(a) / b); //32 òàêòà
}
//! Äåëåíèå äâóõ ÷èñåë â ôîðìàòå 8.24
//! \memberof V_IQmath
int32 _IQ24div(int32 a, int32 b) {
if (b == 0)
return 0;
return _IQ24((float )a / b); //32 òàêòà
}
//! Êâàäðàòíûé êîðåíü â ôîðìàòå 8.24. Ðàáîòàåò ÷åðåç àïïàðàòíûé float, çàíèìàåò 43 òàêòà.
//! Â CodeMaster íåò ôóíêöèè sqrtf, ïîýòîìó äëÿ íåãî âûçûâàåòñÿ sqrt. Äëÿ GCC âûçûâàòü
//! sqrt íåëüçÿ, ò.ê. òîãäà îí ïîïûòàåòñÿ ðàáîòàòü ñ double, à íå float.
int32 _IQ24sqrt(int32 number) {
return _IQ(sqrtf((float)_IQtoF(number)));
}
static const int16 sinTableQ15[259] = {
0xfcdc, 0x0, 0x324, 0x648, 0x96b, 0xc8c, 0xfab, 0x12c8,
0x15e2, 0x18f9, 0x1c0c, 0x1f1a, 0x2224, 0x2528, 0x2827, 0x2b1f,
0x2e11, 0x30fc, 0x33df, 0x36ba, 0x398d, 0x3c57, 0x3f17, 0x41ce,
0x447b, 0x471d, 0x49b4, 0x4c40, 0x4ec0, 0x5134, 0x539b, 0x55f6,
0x5843, 0x5a82, 0x5cb4, 0x5ed7, 0x60ec, 0x62f2, 0x64e9, 0x66d0,
0x68a7, 0x6a6e, 0x6c24, 0x6dca, 0x6f5f, 0x70e3, 0x7255, 0x73b6,
0x7505, 0x7642, 0x776c, 0x7885, 0x798a, 0x7a7d, 0x7b5d, 0x7c2a,
0x7ce4, 0x7d8a, 0x7e1e, 0x7e9d, 0x7f0a, 0x7f62, 0x7fa7, 0x7fd9,
0x7ff6, 0x7fff, 0x7ff6, 0x7fd9, 0x7fa7, 0x7f62, 0x7f0a, 0x7e9d,
0x7e1e, 0x7d8a, 0x7ce4, 0x7c2a, 0x7b5d, 0x7a7d, 0x798a, 0x7885,
0x776c, 0x7642, 0x7505, 0x73b6, 0x7255, 0x70e3, 0x6f5f, 0x6dca,
0x6c24, 0x6a6e, 0x68a7, 0x66d0, 0x64e9, 0x62f2, 0x60ec, 0x5ed7,
0x5cb4, 0x5a82, 0x5843, 0x55f6, 0x539b, 0x5134, 0x4ec0, 0x4c40,
0x49b4, 0x471d, 0x447b, 0x41ce, 0x3f17, 0x3c57, 0x398d, 0x36ba,
0x33df, 0x30fc, 0x2e11, 0x2b1f, 0x2827, 0x2528, 0x2224, 0x1f1a,
0x1c0c, 0x18f9, 0x15e2, 0x12c8, 0xfab, 0xc8c, 0x96b, 0x648,
0x324, 0x0, 0xfcdc, 0xf9b8, 0xf695, 0xf374, 0xf055, 0xed38,
0xea1e, 0xe707, 0xe3f4, 0xe0e6, 0xdddc, 0xdad8, 0xd7d9, 0xd4e1,
0xd1ef, 0xcf04, 0xcc21, 0xc946, 0xc673, 0xc3a9, 0xc0e9, 0xbe32,
0xbb85, 0xb8e3, 0xb64c, 0xb3c0, 0xb140, 0xaecc, 0xac65, 0xaa0a,
0xa7bd, 0xa57e, 0xa34c, 0xa129, 0x9f14, 0x9d0e, 0x9b17, 0x9930,
0x9759, 0x9592, 0x93dc, 0x9236, 0x90a1, 0x8f1d, 0x8dab, 0x8c4a,
0x8afb, 0x89be, 0x8894, 0x877b, 0x8676, 0x8583, 0x84a3, 0x83d6,
0x831c, 0x8276, 0x81e2, 0x8163, 0x80f6, 0x809e, 0x8059, 0x8027,
0x800a, 0x8000, 0x800a, 0x8027, 0x8059, 0x809e, 0x80f6, 0x8163,
0x81e2, 0x8276, 0x831c, 0x83d6, 0x84a3, 0x8583, 0x8676, 0x877b,
0x8894, 0x89be, 0x8afb, 0x8c4a, 0x8dab, 0x8f1d, 0x90a1, 0x9236,
0x93dc, 0x9592, 0x9759, 0x9930, 0x9b17, 0x9d0e, 0x9f14, 0xa129,
0xa34c, 0xa57e, 0xa7bd, 0xaa0a, 0xac65, 0xaecc, 0xb140, 0xb3c0,
0xb64c, 0xb8e3, 0xbb85, 0xbe32, 0xc0e9, 0xc3a9, 0xc673, 0xc946,
0xcc21, 0xcf04, 0xd1ef, 0xd4e1, 0xd7d9, 0xdad8, 0xdddc, 0xe0e6,
0xe3f4, 0xe707, 0xea1e, 0xed38, 0xf055, 0xf374, 0xf695, 0xf9b8,
0xfcdc, 0x0, 0x324
};
//! Ôóíêöèÿ ñèíóñà, òàáëè÷íàÿ, òî÷íàÿ, ñ êóáè÷åñêîé èíòåðïîëÿöèåé ìåæäó òî÷êàìè.
//! Âíóòðè ðàáîòàåò ñ òîíîñòüþ 16.16, íî êîíâåðòèðóåòñÿ â 8.24
//! 83 òàêòà
//!Âçÿòî èç áèáëèîòåêè DSP ARM
//! \memberof V_IQmath
int32 _IQ24sinPU_accurate(
int32 x) {
int32 sinVal; /* Temporary variables output */
int16 *tablePtr; /* Pointer to table */
int16 fract, in, in2; /* Temporary variables for input, output */
int32 wa, wb, wc, wd; /* Cubic interpolation coefficients */
int16 a, b, c, d; /* Four nearest output values */
int16 fractCube, fractSquare; /* Temporary values for fractional value */
int16 oneBy6 = 0x1555; /* Fixed point16 value of 1/6 */
int16 tableSpacing = 0x80; /* Table spacing */
int32 index; /* Index variable */
in = (x>>9)&0x7FFF;
/* Calculate the nearest index */
index = (int32_t) in / tableSpacing;
/* Calculate the nearest value of input */
in2 = (int16) ((index) * tableSpacing);
/* Calculation of fractional value */
fract = (in - in2) << 8;
/* fractSquare = fract * fract */
fractSquare = (int16) ((fract * fract) >> 15);
/* fractCube = fract * fract * fract */
fractCube = (int16) ((fractSquare * fract) >> 15);
/* Checking min and max index of table */
if (index < 0) {
index = 0;
} else if (index > 256) {
index = 256;
}
/* Initialise table pointer */
tablePtr = (int16 *) & sinTableQ15[index];
/* Cubic interpolation process */
/* Calculation of wa */
/* wa = -(oneBy6)*fractCube + (fractSquare >> 1u) - (0x2AAA)*fract; */
wa = (int32) oneBy6 *fractCube;
wa += (int32) 0x2AAA *fract;
wa = -(wa >> 15);
wa += ((int32) fractSquare >> 1u);
/* Read first nearest value of output from the sin table */
a = *tablePtr++;
/* sinVal = a * wa */
sinVal = a * wa;
/* Calculation of wb */
wb = (((int32) fractCube >> 1u) - (int32) fractSquare) -
(((int32) fract >> 1u) - 0x7FFF);
/* Read second nearest value of output from the sin table */
b = *tablePtr++;
/* sinVal += b*wb */
sinVal += b * wb;
/* Calculation of wc */
wc = -(int32) fractCube + fractSquare;
wc = (wc >> 1u) + fract;
/* Read third nearest value of output from the sin table */
c = *tablePtr++;
/* sinVal += c*wc */
sinVal += c * wc;
/* Calculation of wd */
/* wd = (oneBy6)*fractCube - (oneBy6)*fract; */
fractCube = fractCube - fract;
wd = ((int16) (((int32) oneBy6 * fractCube) >> 15));
/* Read fourth nearest value of output from the sin table */
d = *tablePtr++;
/* sinVal += d*wd; */
sinVal += d * wd;
/* Return the output value */
return sinVal>>6;
}
//! Ôóíêöèÿ ñèíóñà, ïðèáëèæåííàÿ, áûñòðàÿ.
//!A sine approximation via a fourth-order cosine approx.
//! Âíóòðè ðàáîòàåò ñ òî÷íîñòüþ 16.16, íî êîíâåðòèðóåòñÿ â 8.24
//! http://www.coranac.com/2009/07/sines/
//! 30 òàêòîâ
//! \memberof V_IQmath
int32 _IQ24sinPU(int32 x) {
int32 c, y;
static const int32 qN = 13, qA = 12, B = 19900, C = 3516;
x = x >> 9; //from 8.24
c = x << (30 - qN); // Semi-circle info into carry.
x -= 1 << qN; // sine -> cosine calc
x = x << (31 - qN); // Mask with PI
x = x >> (31 - qN); // Note: SIGNED shift! (to qN)
x = x * x >> (2 * qN - 14); // x=x^2 To Q14
y = B - (x * C >> 14); // B - x^2*C
y = (1 << qA) - (x * y >> 16); // A - x^2*(B-x^2*C)
y = y << 12; // to 8.24
return c >= 0 ? y : -y;
}
//! Ôóíêöèÿ atan2.
//!http://www.dspguru.com/dsp/tricks/fixed-point-atan2-with-self-normalization
//!100 òàêòîâ
//! \memberof V_IQmath
int32 _IQ24atan2PU(int32 inY , int32 inX) {
int32 abs_inY, angle, r, r_3;
abs_inY = labs(inY)+1;// kludge to prevent 0/0 condition
if (inX >= 0) {
r = _IQ24div( (inX - abs_inY), (inX + abs_inY));
r_3=_IQmpy(_IQmpy(r,r),r);
angle = _IQ24mpy(_IQ(0.1963f/(2.0f*_PI)),r_3)-_IQ24mpy(_IQ(0.9817f/(2.0f*_PI)),r)+_IQ24(_PI/4.0f/(2.0f*_PI));
} else {
r = _IQ24div( (inX + abs_inY), (abs_inY - inX));
r_3=_IQmpy(_IQmpy(r,r),r);
angle = _IQ24mpy(_IQ(0.1963f/(2.0f*_PI)),r_3)-_IQ24mpy(_IQ(0.9817f/(2.0f*_PI)),r)+_IQ24(3.0f*_PI/4.0f/(2.0f*_PI));
}
if (inY < 0) {
angle = -angle;
}
angle=angle&0xFFFFFF;
return angle;
}
//! Ôóíêöèÿ âû÷èñëåíèÿ àìïëèòóäû âåêòîðà
//! 60 òàêòîâ
//! \memberof V_IQmath
int32 _IQ24mag(int32 a, int32 b) {
return _IQ24sqrt(_IQ24mpy(a, a) + _IQ24mpy(b, b));
}
/*@}*/

652
Vsrc/V_PWM_Module.c Normal file
View File

@ -0,0 +1,652 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file V_PWM_Module.c
\brief Ìîäóëü ðåàëèçàöèè âåêòîðíîé ØÈÌ (ñì. TPWM_Module)
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 2.0 25/03/2016
\addtogroup V_PWM_Module
@{*/
#include "V_IQmath.h"
#include "V_PWM_Module.h"
#include "main.h"
//! Èíèöèàëèçàöèÿ
//! \memberof TPWM_Module
void PWM_Module_Init(TPWM_Module *p) {
SIU->PWMSYNC_bit.PRESCRST = 0; //ñèíõðîíèçàöèÿ òàéìåðîâ - ñáðîñ âíóòðåííèõ ñ÷åò÷èêîâ
// ------------------------------------------------------------------------
// Íàñòðàèâàåì ìîäóëü ePWM0
// ------------------------------------------------------------------------
if (p->Frequency < PWM_FREQ_MIN)
p->Frequency = PWM_FREQ_MIN;
if (p->Frequency > PWM_FREQ_MAX)
p->Frequency = PWM_FREQ_MAX;
PWM0->TBPRD = _IQ10div(_IQ10(SystemCoreClock/1000.0), p->Frequency << 1) >> 10; //ïåðèîä
p->k_pwm = PWM0->TBPRD;
p->FreqPrev = p->Frequency; //ïðåäûäóùàÿ ÷àñòîòà
PWM0->TBPHS_bit.TBPHS = 0x0000; // Phase is 0
PWM0->TBCTR = 0x0000; // Clear counter
// Setup counter mode
PWM0->TBCTL_bit.PRDLD = TB_SHADOW; // çàãðóçêà TBPRD ïðè TBCTR = 0
PWM0->TBCTL_bit.CTRMODE = TB_COUNT_UPDOWN; // Count up-down
PWM0->TBCTL_bit.PHSEN = TB_DISABLE; // Disable phase loading
PWM0->TBCTL_bit.PHSDIR = TB_UP; // Ñ÷èòàòü ââåðõ ïîñëå çàãðóçêè ôàçû
PWM0->TBCTL_bit.HSPCLKDIV = 0; // High Speed Time-base Clock Prescale
PWM0->TBCTL_bit.CLKDIV = 0; // Time-base Clock Prescale
PWM0->TBCTL_bit.SYNCOSEL = TB_CTR_ZERO; // âûäà¸ì ñèíõðî-ñèãíàë ïðè TBCTR = 0
// Setup shadowing
PWM0->CMPCTL_bit.SHDWAMODE = CC_SHADOW; //âêëþ÷èòü SHADOW äëÿ ñðàâíåíèÿ
PWM0->CMPCTL_bit.LOADAMODE = CC_CTR_ZERO; // Load on period and zero
PWM0->CMPCTL_bit.SHDWBMODE = CC_SHADOW; //âêëþ÷èòü SHADOW äëÿ ñðàâíåíèÿ
PWM0->CMPCTL_bit.LOADBMODE = CC_CTR_ZERO; // Load on period and zero
// Set Compare values
PWM0->CMPA_bit.CMPA = 0; // Set compare A value
// Set actions
PWM0->AQCTLA = AQ_EPWM_DISABLE; // äëÿ íà÷àëà ñîáûòèÿ äëÿ PWM1A çàïðåùåíû
PWM0->AQCTLA_bit.ZRO = 1; //îáíóëÿåì ïðè íóëå ñ÷åò÷èêà
PWM0->AQCTLA_bit.CAU = 2; //âêëþ÷àåì ïðè ñðàâíåíèè è èíêðåìåíòèîâàíèè
PWM0->AQCTLA_bit.CAD = 1; //îáíóëÿåì ïðè ñðàâíåíèè è äåêðåìåíòðîâàíèè
//Äëÿ PWMB òîæå ñàìîå, ÷òî äëÿ PWMÀ. Áåç èíâåðñèè. Èíâåðñèÿ äàëåå â ìîäóëå ÌÂ
PWM0->AQCTLB = PWM0->AQCTLA; // äëÿ íà÷àëà ñîáûòèÿ äëÿ PWM1B çàïðåùåíû
PWM0->AQCTLB_bit.ZRO = PWM0->AQCTLA_bit.ZRO; //îáíóëÿåì ïðè íóëå ñ÷åò÷èêà
PWM0->AQCTLB_bit.CAU = PWM0->AQCTLA_bit.CAU; //âêëþ÷àåì ïðè ñðàâíåíèè è èíêðåìåíòèîâàíèè
PWM0->AQCTLB_bit.CAD = PWM0->AQCTLA_bit.CAD; //îáíóëÿåì ïðè ñðàâíåíèè è äåêðåìåíòðîâàíèè
PWM0->AQSFRC_bit.RLDCSF = 0; //ïî ÒÎ íàäî ïèñàòü 0
// Setup Deadband
// DBRED = DBFED = 150 * Tì_ìêñ / 4
PWM0->DBRED = _IQ4mpy(_IQ4(150 / 4), p->DeadBand >> 20) >> 4;
PWM0->DBFED = PWM0->DBRED;
// Íàñòðîéêà ìîäóëÿ ì¸ðòâîãî âðåìåíè:
// INMODE: S5=0 S4=0 - ñèãíàë ñ çàäåðæàííûì ïåðåäíèì ôðîíòîì è ñèãíàë ñ çàäåðæàííûì çàäíèì ôðîíòîì
// ôîðìèðóþòñÿ èç ñèãíàëà PWMA
// POLSEL: S3 = 1 S2 = 1 - ñèãíàë ñ çàäåðæàííûì ïåðåäíèì ôðîíòîì èä¸ò êàê åñòü, à ñèãíàë
// ñ çàäåðæàííûì çàäíèì ôðîíòîì èíâåðòèðóåòñÿ
// OUTMODE:S0 = 1 S1 = 1 íà êàíàë PWMA âûõîäèò èñõîäíûé ñèãíàë PWMA, íî ñ çàäåðæàííûì ïåðåäíèì ôðîíòîì
// Íà êàíàë PWMB âûõîäèò ñèãíàë PWMA ñ çàäåðæàííûì çàäíèì ôðîíòîì äà åù¸ è ñ èíâåðñèåé
PWM0->DBCTL_bit.INMODE = DBA_ALL;
PWM0->DBCTL_bit.POLSEL = DB_ACTV_HIC;
PWM0->DBCTL_bit.OUTMODE = DB_FULL_ENABLE;
PWM0->ETSEL_bit.INTSEL = ET_DISABLE; // Disable INT (øèìîâñêîå)
PWM0->ETSEL_bit.INTEN = 0; // Disable INT
//ðàçðåøàåì TZ áûòü èñòî÷íèêîì àïïàðàòíîé àâàðèè (one-shot)
// PWM0->TZSEL_bit.OSHT1 = TZ_ENABLE;
// PWM0->TZSEL_bit.OSHT2 = TZ_ENABLE;
// PWM0->TZSEL_bit.OSHT3 = TZ_ENABLE;
// Trip-Zone
PWM0->TZCTL_bit.TZA = TZ_STATE; // ïî ñîáûòèþ "One-Shot Trip" ïåðåâîäèì
PWM0->TZCTL_bit.TZB = TZ_STATE; // ØÈÌ âûõîäû â íóæíîå ñîñòîÿíèå
//Äëÿ VectorCARD îò ØÈÌà çàïóñêàåòñÿ ADC
//PWM0->ETSEL_bit.SOCAEN = 1; // Ðàçðåøèòü çàïóñê àöï
//PWM0->ETSEL_bit.SOCASEL = 1; // Çàïóñêàòü ïðè CTR == 0 (Underflow)
// ------------------------------------------------------------------------
// Íàñòðàèâàåì ìîäóëü ePWM1
// ------------------------------------------------------------------------
// Setup TBCLK
PWM1->TBPRD = PWM0->TBPRD; //ïåðèîä òàêîé æå
PWM1->TBPHS_bit.TBPHS = 0x0001; // Ôàçà ðàâíà 1 èç-çà çàäåðæêè â îäèí òàêò íà ñèíõðîíèçàöèþ
PWM1->TBCTR = 0x0000; // Clear counter
// Setup counter mode
PWM1->TBCTL_bit.PRDLD = TB_SHADOW; // çàãðóçêà TBPRD ïðè TBCTR = 0
PWM1->TBCTL_bit.CTRMODE = TB_COUNT_UPDOWN; // Count up-down
PWM1->TBCTL_bit.PHSEN = TB_ENABLE; // Enable phase loading
PWM1->TBCTL_bit.PHSDIR = TB_UP; // Ñ÷èòàòü ââåðõ ïîñëå çàãðóçêè ôàçû
PWM1->TBCTL_bit.HSPCLKDIV = 0; // High Speed Time-base Clock Prescale
PWM1->TBCTL_bit.CLKDIV = 0; // Time-base Clock Prescale
PWM1->TBCTL_bit.SYNCOSEL = TB_SYNC_IN; // ïðîïóñêàåì ñèíõðî-ñèãíàë "íàñêâîçü"
// Setup shadowing
PWM1->CMPCTL_bit.SHDWAMODE = CC_SHADOW; //âêëþ÷èòü SHADOW äëÿ ñðàâíåíèÿ
PWM1->CMPCTL_bit.LOADAMODE = CC_CTR_ZERO; // Load on period and zero
PWM1->CMPCTL_bit.SHDWBMODE = CC_SHADOW; //âêëþ÷èòü SHADOW äëÿ ñðàâíåíèÿ
PWM1->CMPCTL_bit.LOADBMODE = CC_CTR_ZERO; // Load on period and zero
// Set Compare values
PWM1->CMPA_bit.CMPA = 0; // Set compare A value
// Set actions
PWM1->AQCTLA = AQ_EPWM_DISABLE; // äëÿ íà÷àëà ñîáûòèÿ çàïðåùåíû
PWM1->AQCTLA_bit.ZRO = 1; //îáíóëÿåì ïðè íóëå ñ÷åò÷èêà
PWM1->AQCTLA_bit.CAU = 2; //âêëþ÷àåì ïðè ñðàâíåíèè è èíêðåìåíòèîâàíèè
PWM1->AQCTLA_bit.CAD = 1; //îáíóëÿåì ïðè ñðàâíåíèè è äåêðåìåíòðîâàíèè
//Äëÿ PWMB òîæå ñàìîå, ÷òî äëÿ PWMÀ. Áåç èíâåðñèè. Èíâåðñèÿ äàëåå â ìîäóëå ÌÂ
PWM1->AQCTLB = PWM0->AQCTLA; // äëÿ íà÷àëà ñîáûòèÿ äëÿ PWM1B çàïðåùåíû
PWM1->AQCTLB_bit.ZRO = PWM0->AQCTLA_bit.ZRO; //îáíóëÿåì ïðè íóëå ñ÷åò÷èêà
PWM1->AQCTLB_bit.CAU = PWM0->AQCTLA_bit.CAU; //âêëþ÷àåì ïðè ñðàâíåíèè è èíêðåìåíòèîâàíèè
PWM1->AQCTLB_bit.CAD = PWM0->AQCTLA_bit.CAD; //îáíóëÿåì ïðè ñðàâíåíèè è äåêðåìåíòðîâàíèè
PWM1->AQSFRC_bit.RLDCSF = 0; //ïî ÒÎ íàäî ïèñàòü 0
// Active high complementary PWMs - Setup Deadband
PWM1->DBRED = PWM0->DBRED;
PWM1->DBFED = PWM1->DBRED;
PWM1->DBCTL_bit.INMODE = PWM0->DBCTL_bit.INMODE;
PWM1->DBCTL_bit.OUTMODE = PWM0->DBCTL_bit.OUTMODE;
PWM1->DBCTL_bit.POLSEL = PWM0->DBCTL_bit.POLSEL;
// Interrupt where we will change the Compare Values
PWM1->ETSEL_bit.INTSEL = ET_DISABLE; // Disable INT
PWM1->ETSEL_bit.INTEN = 0; // Disable INT
// Trip-Zone
PWM1->TZCTL_bit.TZA = TZ_STATE; // ïî ñîáûòèþ "One-Shot Trip" ïåðåâîäèì
PWM1->TZCTL_bit.TZB = TZ_STATE; // ØÈÌ âûõîäû â íóæíîå ñîñòîÿíèå
// ------------------------------------------------------------------------
// Íàñòðàèâàåì ìîäóëü ePWM2
// ------------------------------------------------------------------------
// Setup TBCLK
PWM2->TBPRD = PWM0->TBPRD;
PWM2->TBPHS_bit.TBPHS = 0x0001; // Ôàçà ðàâíà 1 èç-çà çàäåðæêè â îäèí òàêò íà ñèíõðîíèçàöèþ
PWM2->TBCTR = 0x0000; // Clear counter
// Setup counter mode
PWM2->TBCTL_bit.PRDLD = TB_SHADOW; // çàãðóçêà TBPRD ïðè TBCTR = 0
PWM2->TBCTL_bit.CTRMODE = TB_COUNT_UPDOWN; // Count up-down
PWM2->TBCTL_bit.PHSEN = TB_ENABLE; // Enable phase loading
PWM2->TBCTL_bit.PHSDIR = TB_UP; // Ñ÷èòàòü ââåðõ ïîñëå çàãðóçêè ôàçû
PWM2->TBCTL_bit.HSPCLKDIV = 0; // High Speed Time-base Clock Prescale
PWM2->TBCTL_bit.CLKDIV = 0; // Time-base Clock Prescale
PWM2->TBCTL_bit.SYNCOSEL = TB_SYNC_IN; // ðàçðåøàåì âûäà÷ó ñèíõðî-ñèãíàëà
// Setup shadowing
PWM2->CMPCTL_bit.SHDWAMODE = CC_SHADOW; //âêëþ÷èòü SHADOW äëÿ ñðàâíåíèÿ
PWM2->CMPCTL_bit.LOADAMODE = CC_CTR_ZERO; // Load on period and zero
PWM2->CMPCTL_bit.SHDWBMODE = CC_SHADOW; //âêëþ÷èòü SHADOW äëÿ ñðàâíåíèÿ
PWM2->CMPCTL_bit.LOADBMODE = CC_CTR_ZERO; // Load on period and zero
// Set Compare values
PWM2->CMPA_bit.CMPA = 0; // Set compare A value
// Set actions
PWM2->AQCTLA = AQ_EPWM_DISABLE; // äëÿ íà÷àëà ñîáûòèÿ çàïðåùåíû
PWM2->AQCTLA_bit.ZRO = 1; //îáíóëÿåì ïðè íóëå ñ÷åò÷èêà
PWM2->AQCTLA_bit.CAU = 2; //âêëþ÷àåì ïðè ñðàâíåíèè è èíêðåìåíòèîâàíèè
PWM2->AQCTLA_bit.CAD = 1; //îáíóëÿåì ïðè ñðàâíåíèè è äåêðåìåíòðîâàíèè
//Äëÿ PWMB òîæå ñàìîå, ÷òî äëÿ PWMÀ. Áåç èíâåðñèè. Èíâåðñèÿ äàëåå â ìîäóëå ÌÂ
PWM2->AQCTLB = PWM0->AQCTLA; // äëÿ íà÷àëà ñîáûòèÿ äëÿ PWM1B çàïðåùåíû
PWM2->AQCTLB_bit.ZRO = PWM0->AQCTLA_bit.ZRO; //îáíóëÿåì ïðè íóëå ñ÷åò÷èêà
PWM2->AQCTLB_bit.CAU = PWM0->AQCTLA_bit.CAU; //âêëþ÷àåì ïðè ñðàâíåíèè è èíêðåìåíòèîâàíèè
PWM2->AQCTLB_bit.CAD = PWM0->AQCTLA_bit.CAD; //îáíóëÿåì ïðè ñðàâíåíèè è äåêðåìåíòðîâàíèè
PWM2->AQSFRC_bit.RLDCSF = 0; //ïî ÒÎ íàäî ïèñàòü 0
// Active high complementary PWMs - Setup Deadband
PWM2->DBRED = PWM0->DBRED;
PWM2->DBFED = PWM2->DBRED;
PWM2->DBCTL_bit.INMODE = PWM0->DBCTL_bit.INMODE;
PWM2->DBCTL_bit.OUTMODE = PWM0->DBCTL_bit.OUTMODE;
PWM2->DBCTL_bit.POLSEL = PWM0->DBCTL_bit.POLSEL;
// Interrupt where we will change the Compare Values
PWM2->ETSEL_bit.INTSEL = ET_DISABLE; // Disable INT
PWM2->ETSEL_bit.INTEN = 0; // Disable INT
// Trip-Zone
PWM2->TZCTL_bit.TZA = TZ_STATE; // ïî ñîáûòèþ "One-Shot Trip" ïåðåâîäèì
PWM2->TZCTL_bit.TZB = TZ_STATE; // ØÈÌ âûõîäû â íóæíîå ñîñòîÿíèå
// Îòêëþ÷àåì êëþ÷è
PWM0->TZFRC_bit.OST = 1;
PWM1->TZFRC_bit.OST = 1;
PWM2->TZFRC_bit.OST = 1;
//PWM0->TBCTL_bit.FREESOFT = 0;
//ØÈÌ 6 âûâîäîâ
GPIOA->ALTFUNCSET = (1 << 8) + (1 << 9) + (1 << 10) + (1 << 11) + (1 << 12) + (1 << 13);
GPIOA->DENSET = (1 << 8) + (1 << 9) + (1 << 10) + (1 << 11) + (1 << 12) + (1 << 13);
//Ñèíõðîííûé çàïóñê ØÈÌ
SIU->PWMSYNC_bit.PRESCRST= 0b111;
}
//! Íîðìèðîâàíèå âõîäíûõ âåëè÷èí.
//!Ó÷èòûâàåò êîìïåíñàöèþ íàïðÿæåíèÿ ïðè èçìåíåíèè Ud,
//!âûïîëíÿåò âïèñûâàíèå âåêòîðà â îêðóæíîñòü, åñëè òðåáóåòñÿ, è
//!âûïîëíÿåò ñìåíó áàçèñà, îòíîñèòåëüíî êîòîðîãî èäåò íîðìèðîâêà.
//! \memberof TPWM_Module
void PWM_Module_NormInput(TPWM_Module* p) {
_iq knorm;
p->UalphaNorm=p->UalphaRef;
p->UbetaNorm=p->UbetaRef;
//íàõîäèì àìïëèòóäó (áåç ó÷åòà îãðàíè÷åíèÿ)
p->U_mag=_IQmag(p->UalphaNorm,p->UbetaNorm);
p->UdCorTmp=_IQdiv(_IQ(1.0),(_IQ(1.0)+_IQmpy((adc.Udc_meas-_IQ(1.0)),p->UdCompK)));
//ó÷åò ïóëüñàöèé íàïðÿæåíèÿ íà Ud
if (p->UdCompEnable&1) { //îí âêëþ÷åí?
p->UalphaNorm=_IQmpy(p->UalphaNorm, p->UdCorTmp);//èçìåíèì ïðîïîðöèîíàëüíî êîýôô-òó êîððåêöèè
p->UbetaNorm=_IQmpy(p->UbetaNorm, p->UdCorTmp);//è ýòî òîæå
}
//âïèñûâàíèå çàäàííîé àìïëèòóäû íàïðÿæåíèÿ â îêðóæíîñòü, âïèñûâàåìóþ â øåñòèóãîëüíèê áàçûâûõ âåêòîðîâ
//êîãäà U_lim=1.0, ýòî è åñòü òàêàÿ îêðóæíîñòü. Áûâàåò, ÷òî ìû õîòèì âïèñûâàòü â øåñòèóãîëüíèê. Òîãäà ïðîñòî çàäèðàåì ââåðõ îãðèàíè÷åíèå U_lim
if (p->U_lim>_IQ(1.0/0.866)) //íî íåò ñìûñëà çàäèðàòü âûøå ìàêñèìàëüíî-ðåàëèç. íàïðÿæåíèÿ (áîëüøå áàçîâîãî âåêòîðà)
p->U_lim=_IQ(1.0/0.866);
/* ðàññ÷èòûâàåì àìïëèòóäó âåêòîðà, êîòîðûé õîòèì îòðàáîòàòü*/
knorm=_IQmag(p->UalphaNorm,p->UbetaNorm);//ïëþñ íîðìèðóåì îò 540 ê 311
if (knorm>=p->U_lim) { //îí áîëüøå, ÷åì íàøå îãðàíè÷åíèå?
knorm=_IQdiv(p->U_lim,knorm);//â ýòó æå ïåðåìåííóþ, äëÿ ýêîíîìèè, ðàññ÷èòûâàåì íîðìèðîâêó
p->UalphaNorm=_IQmpy(knorm,p->UalphaNorm);//óìåíüøàåì ïðîïîðöèîíàëüíî íîðìèðîâêå
p->UbetaNorm=_IQmpy(knorm,p->UbetaNorm);//è ýòî
p->ULimitation=1;//ôëàã î òîì, ÷òî èäåò îãðàíè÷åíèå íàïðÿæåíèÿ
} else
p->ULimitation=0;
/* ðàññ÷èòûâàåì ïðèâåäåííûå âåêòîðà*/
/* Äî ýòîãî ìîìåíòà íàïðÿæåíèå íîðìèðîâàëîñü îòíîñèòåëüíî
áàçèñà ôàçíîãî àìïëèòóäíîãî çíà÷åíèÿ, íàïðèìåð, 220*sqrt(2)
Òåïåðü ïðîèçâîäèòñÿ ïåðåõîä, ãäå çà åäèíèöó ïðèíèìàåòñÿ ìàêñèìàëüíî
ðåàëèçóåìîå íàïðÿæåíèå (äëèíà áàçîâîãî âåêòîðà)
*/
p->UalphaNorm=_IQmpy(p->UalphaNorm,_IQ(0.866));
p->UbetaNorm=_IQmpy(p->UbetaNorm,_IQ(0.866));
}
//! Ôóíêöèÿ 6òè ñåêòîðíîé âåêòîðíîé ØÈÌ
//! \memberof TPWM_Module
void PWM_Module_No_SV_Update(TPWM_Module *p) {
_iq lambda1;
_iq lambda2;
_iq lambda3;
int16 gamma;
int16 gamma1;
long tmp_pwm;
//Ïðèñâîåíèå òðåõ óñòàâîê ñðàâíåíèÿ òîëüêî åñëè ñ÷åò÷èê òàéìåðà äàëåê îò íóëÿ, ÷òîáû
//ïðåäîòâðàòèòü ÷àñòè÷íîå ïðèìåíåíèå ñêâàæíîñòåé, ÷òî â âåêòîðíîé ØÈÌ ìîæåò áûòü êðèòè÷íî è èñïîðòèòü ïåðèîä ØÈÌ.
DINT;
if (PWM0->TBCTR>30) {
PWM0->CMPA_bit.CMPA=(Uint16)p->GammaA;
PWM1->CMPA_bit.CMPA=(Uint16)p->GammaB;
PWM2->CMPA_bit.CMPA=(Uint16)p->GammaC;
}
EINT;
PWM_Module_NormInput(p);
//Ðàñ÷åò ñêâàæíîñòåé ïî ìåòîäó Èçîñèìîâà.
//Ïîäðîáíåå ñì. äèññåðòàöèþ ×óåâà Ï.Â. http://motorcontrol.ru/wp-content/uploads/2015/11/Chuev_vector_control.pdf
tmp_pwm = _IQmpy(_1_SQRT3,p->UbetaNorm); /*äåëèì íà êîðåíü èç 3*/
lambda1 = _IQmpy(p->k_pwm,(p->UalphaNorm - tmp_pwm));
lambda2 = _IQmpy(p->k_pwm,2*tmp_pwm);
lambda3 = _IQmpy(p->k_pwm,p->UalphaNorm + tmp_pwm);
if (lambda1<=0)
if (lambda3>0) {
gamma=lambda3;
gamma1=-lambda1;
p->sector=1; /*110 íà÷àëî */
p->GammaA=p->k_pwm-gamma;
p->GammaB=p->k_pwm-(gamma+gamma1+1);
p->GammaC=p->k_pwm-0;
} else if (lambda2>0) {
gamma=lambda2;
gamma1=-lambda3;
p->sector=2; /*011 íà÷àëî */
p->GammaA=p->k_pwm-0;
p->GammaB=p->k_pwm-(gamma+gamma1+1);
p->GammaC=p->k_pwm-gamma1;
/*011 íà÷àëî */
} else if (lambda1!=0) {
gamma=-lambda1;
gamma1=-lambda2;
p->sector=3; /*011 íà÷àëî */
p->GammaA=p->k_pwm-0;
p->GammaB=p->k_pwm-gamma;
p->GammaC=p->k_pwm-(gamma+gamma1+1);
/*011 íà÷àëî */
} else {
gamma=-lambda3;
gamma1 = lambda1;
p->sector= 4; /*101 íà÷àëî */
p->GammaA=p->k_pwm-gamma1;
p->GammaB=p->k_pwm-0;
p->GammaC=p->k_pwm-(gamma+gamma1+1);
/*101 íà÷àëî */
}
else if (lambda2>0) {
gamma=lambda1;
gamma1=lambda2;
p->sector= 0; /*110 íà÷àëî */
p->GammaA=p->k_pwm-(gamma+gamma1+1);
p->GammaB=p->k_pwm-gamma1;
p->GammaC=p->k_pwm-0;
/*110 íà÷àëî */
} else if (lambda3<0) {
gamma=-lambda3;
gamma1 = lambda1;
p->sector= 4; /*101 íà÷àëî */
p->GammaA=p->k_pwm-gamma1;
p->GammaB=p->k_pwm-0;
p->GammaC=p->k_pwm-(gamma+gamma1+1);
/*101 íà÷àëî */
} else {
gamma=-lambda2;
gamma1=lambda3;
p->sector=5; /*101 íà÷àëî */
p->GammaA=p->k_pwm-(gamma+gamma1+1);
p->GammaB=p->k_pwm-0;
p->GammaC=p->k_pwm-gamma;
/*101 íà÷àëî */
}
/*íàñûùåíèÿ */
if (p->GammaA<0) p->GammaA=0;
if (p->GammaB<0) p->GammaB=0;
if (p->GammaC<0) p->GammaC=0;
if (p->GammaA>p->k_pwm) p->GammaA=p->k_pwm+1;
if (p->GammaB>p->k_pwm) p->GammaB=p->k_pwm+1;
if (p->GammaC>p->k_pwm) p->GammaC=p->k_pwm+1;
//Ïðèñâîåíèå òðåõ óñòàâîê ñðàâíåíèÿ òîëüêî åñëè ñ÷åò÷èê òàéìåðà äàëåê îò íóëÿ, ÷òîáû
//ïðåäîòâðàòèòü ÷àñòè÷íîå ïðèìåíåíèå ñêâàæíîñòåé, ÷òî â âåêòîðíîé ØÈÌ ìîæåò áûòü êðèòè÷íî è èñïîðòèòü ïåðèîä ØÈÌ.
//Âòîðîé ðàç - ÷òîáû ïðåäîòâðàòèòü ñèòóàöèþ ñ ïîñòîÿííîé "íåçàãðóçêîé" ïðè ðàâåíñòâå ÷àñòîò ðàñ÷åòà è ØÈÌ
DINT;
if (PWM0->TBCTR>30) {
PWM0->CMPA_bit.CMPA=(Uint16)p->GammaA;
PWM1->CMPA_bit.CMPA=(Uint16)p->GammaB;
PWM2->CMPA_bit.CMPA=(Uint16)p->GammaC;
}
EINT;
}
//! Ôóíêöèÿ ñèíóñîèäàëüíîé ØÈÌ
//! \memberof TPWM_Module
void PWM_Module_Sin_Update(TPWM_Module *p) {
_iq PhasePtsA;
_iq PhasePtsB;
_iq PhasePtsC;
_iq knorm;
p->UalphaNorm = p->UalphaRef;
p->UbetaNorm = p->UbetaRef;
//íàõîäèì àìïëèòóäó (áåç ó÷åòà îãðàíè÷åíèÿ)
p->U_mag = _IQmag(p->UalphaNorm, p->UbetaNorm);
/* ðàññ÷èòûâàåì àìïëèòóäó âåêòîðà, êîòîðûé õîòèì îòðàáîòàòü*/
knorm = _IQmag(p->UalphaNorm, p->UbetaNorm);
if (knorm >= p->U_lim) { //îí áîëüøå, ÷åì íàøå îãðàíè÷åíèå?
knorm = _IQdiv(p->U_lim, knorm); //â ýòó æå ïåðåìåííóþ, äëÿ ýêîíîìèè, ðàññ÷èòûâàåì íîðìèðîâêó
p->UalphaNorm = _IQmpy(knorm, p->UalphaNorm); //óìåíüøàåì ïðîïîðöèîíàëüíî íîðìèðîâêå
p->UbetaNorm = _IQmpy(knorm, p->UbetaNorm); //è ýòî
p->ULimitation = 1; //ôëàã î òîì, ÷òî èäåò îãðàíè÷åíèå íàïðÿæåíèÿ
} else
p->ULimitation = 0;
//Íîðìèðîâàíèå âõîäíîãî íàïðÿæåíèÿ. Òàê êàê ñèíóñîèäàëüíàÿ ØÈÌ ôîðìèðóåò íà 0.866 ìåíüøåå íàïðÿæåíèå,
//÷åì âåêòîðíàÿ ØÈÌ (270 àìïëèòóäíîãî ôàçíîãî íàïðÿæåíèÿ âìåñòî 311Â), òî äëÿ òîãî, ÷òîáû ïðè òîì æå çàäàíèè â ïåðåìåííûõ
//p->UalphaNorm, p->UbetaNorm ïîëó÷èëîñü òî æå ñàìîå íàïðÿæåíèå íà âûõîäå, ÷òî è â âåêòîðíîé ØÈÌ, íóæíî çàäàíèÿ óâåëè÷èòü â 1/0.866 ðàç.
//Äåëåíèå íà äâà íóæíî äëÿ ïîñëåäóþùèõ ôîðìóë, ÷òîáû ïåðåìåíûå ìåíÿëèñü â ïîëîâèííîì îò ìàêñèìàëüíîãî äèàïàçîíå.
p->UalphaNorm = _IQmpy(p->UalphaNorm, _IQ(1/0.866/2));
p->UbetaNorm = _IQmpy(p->UbetaNorm, _IQ(1/0.866/2));
/*ôàçíîå ïðåîáðàçîâàíèå èç ñèñòåìû àëüôà, áåòòà â a,b,c */
PhasePtsA = _IQ(0.5) - (p->UalphaNorm);
PhasePtsB = _IQ(0.5) - (_IQmpy(p->UbetaNorm,_IQ(0.8660254)) - (p->UalphaNorm >> 1));
PhasePtsC = _IQ(0.5) - (-_IQmpy(p->UbetaNorm, _IQ(0.8660254)) - (p->UalphaNorm >> 1));
p->GammaA = _IQmpy(p->k_pwm, PhasePtsA);
p->GammaB = _IQmpy(p->k_pwm, PhasePtsB);
p->GammaC = _IQmpy(p->k_pwm, PhasePtsC);
/*íàñûùåíèÿ */
if (p->GammaA < 0)
p->GammaA = 0;
if (p->GammaB < 0)
p->GammaB = 0;
if (p->GammaC < 0)
p->GammaC = 0;
if (p->GammaA > p->k_pwm)
p->GammaA = p->k_pwm + 1;
if (p->GammaB > p->k_pwm)
p->GammaB = p->k_pwm + 1;
if (p->GammaC > p->k_pwm)
p->GammaC = p->k_pwm + 1;
PWM0->CMPA_bit.CMPA = (Uint16) p->GammaA;
PWM1->CMPA_bit.CMPA = (Uint16) p->GammaB;
PWM2->CMPA_bit.CMPA = (Uint16) p->GammaC;
}
//! Ôóíêöèÿ ØÈÌ ñ ðàçäåëüíûìè ôàçàìè (äëÿ ìîäåëè SRM)
//! \memberof TPWM_Module
void PWM_Module_Separate_Update(TPWM_Module *p) {
_iq PhasePtsA;
_iq PhasePtsB;
_iq PhasePtsC;
_iq knorm;
p->UPhARef = _IQmpy(p->UPhARef, _IQ(0.5));
p->UPhBRef = _IQmpy(p->UPhBRef, _IQ(0.5));
p->UPhCRef = _IQmpy(p->UPhCRef, _IQ(0.5));
PhasePtsA = _IQ(0.5) - p->UPhARef;
PhasePtsB = _IQ(0.5) - p->UPhBRef;
PhasePtsC = _IQ(0.5) - p->UPhCRef;
p->GammaA = _IQmpy(p->k_pwm, PhasePtsA);
p->GammaB = _IQmpy(p->k_pwm, PhasePtsB);
p->GammaC = _IQmpy(p->k_pwm, PhasePtsC);
/*íàñûùåíèÿ */
if (p->GammaA < 0)
p->GammaA = 0;
if (p->GammaB < 0)
p->GammaB = 0;
if (p->GammaC < 0)
p->GammaC = 0;
if (p->GammaA > p->k_pwm)
p->GammaA = p->k_pwm + 1;
if (p->GammaB > p->k_pwm)
p->GammaB = p->k_pwm + 1;
if (p->GammaC > p->k_pwm)
p->GammaC = p->k_pwm + 1;
PWM0->CMPA_bit.CMPA = (Uint16) p->GammaA;
PWM1->CMPA_bit.CMPA = (Uint16) p->GammaB;
PWM2->CMPA_bit.CMPA = (Uint16) p->GammaC;
}
//! Ôóíêöèÿ ØÈÌ äëÿ íà÷àëüíîé çàðÿäêè áóäñòðåïíûõ êîíäåíñàòîðîâ èíâåðòîðà
//! \memberof TPWM_Module
void PWM_Module_ChargingMode(TPWM_Module *p) {
p->GammaA = p->k_pwm;
p->GammaB = p->k_pwm;
p->GammaC = p->k_pwm;
DINT;
if (PWM0->TBCTR > 30) {
PWM0->CMPA_bit.CMPA = (Uint16) p->GammaA;
PWM1->CMPA_bit.CMPA = (Uint16) p->GammaB;
PWM2->CMPA_bit.CMPA = (Uint16) p->GammaC;
}
EINT;
}
//! Îáùàÿ ôóíêöèÿ-îáåðòêà äëÿ ðàñ÷åòà ØÈÌ
//Âûçûâàþùàåò òó âåðñèþ ØÈÌ (òó ôóíêöèþ), ÷òî âûáðàíà â íàñòðîéêàõ.
//! \memberof TPWM_Module
void PWM_Module_Update(TPWM_Module *p) {
if (p->ChargingMode)
PWM_Module_ChargingMode(p);
else {
switch (p->PWM_type) {
case PWM_TYPE_6SECT_NO_SV: {
PWM_Module_No_SV_Update(p);
break;
}
case PWM_TYPE_SIN_PWM: {
PWM_Module_Sin_Update(p);
break;
}
case PWM_TYPE_SRD: {
PWM_Module_Separate_Update(p);
break;
}
}
}
}
//! Ìåäëåííûé ðàñ÷åò
//! Ïåðåñ÷èòûâàþòñÿ ââåäåííûå ïîëüçîâàòåëåì âåëè÷èíû
//! Âåëè÷èíà ìåðòâîãî âðåìåíè, ÷àñòîòà ØÈÌ è ò.ï.
//! \memberof TPWM_Module
void PWM_Module_SlowCalc(TPWM_Module *p) {
Uint16 tmp;
//ïðîâåðêà îãðàíè÷åíèé âåëè÷èíû ìåðòâîãî âðåìåíè
if (p->DeadBand < DEAD_BAND_MIN)
p->DeadBand = DEAD_BAND_MIN;
if (p->DeadBand > DEAD_BAND_MAX)
p->DeadBand = DEAD_BAND_MAX;
//ïåðåñ÷åò Ì èç ôîðìàòà IQ â ìêñ â òàêòû òàéìåðà íà 100ìÃö
PWM0->DBRED = _IQ4mpy(_IQ4(100), p->DeadBand >> 20) >> 4;
//âî âñå êëþ÷è òî æå ñàìîå
PWM0->DBFED = PWM0->DBRED;
PWM1->DBFED = PWM0->DBRED;
PWM1->DBRED = PWM0->DBRED;
PWM2->DBFED = PWM0->DBRED;
PWM2->DBRED = PWM0->DBRED;
if (p->MinGammaLimit < DEAD_BAND_MIN)
p->MinGammaLimit = GAMMA_LIMIT_MIN;
if (p->MinGammaLimit > DEAD_BAND_MAX)
p->MinGammaLimit = GAMMA_LIMIT_MAX;
PWM0->FWDTH = _IQ4mpy(_IQ4(100), p->MinGammaLimit >> 20) >> 4;
PWM1->FWDTH = PWM0->FWDTH;
PWM2->FWDTH = PWM0->FWDTH;
//÷àñòîòà ØÈÌ. Ñìåíà "íà ëåòó".
if (p->FreqPrev != p->Frequency) { //ñìåíèëè ÷àñòîòó
DINT; //çàïðåùåíèå ïðåðûâàíèé
//ïðîâåðêà ìàêñèìóìà/ìèíèìóìà
if (p->Frequency < PWM_FREQ_MIN)
p->Frequency = PWM_FREQ_MIN;
if (p->Frequency > PWM_FREQ_MAX)
p->Frequency = PWM_FREQ_MAX;
//èçìåíÿåì ïåðèîä
p->k_pwm = _IQ10div(_IQ10(SystemCoreClock/1000.0), p->Frequency << 1) >> 10; //ïåðèîä
PWM0->TBPRD = p->k_pwm;
//äëÿ âñåõ ñòîåê òî æå ñàìîå
PWM1->TBPRD = p->k_pwm;
PWM2->TBPRD = p->k_pwm;
//ïîñ÷èòàåì äëèíó âûáîðêè äëÿ óñðåäíåíèÿ òîêîâ, èñõîäÿ èç ÷àñòîòû ØÈÌ
adc.IASampleLength = (p->Frequency >> 10) / 10; //×àñòîòà ØÈÌ â ôîðìàòå 22.10, ïðèâîäèì ê èíòó è äåëèì íà 10 - ÷àñòîòó ðàñ÷åòà ñèñòåìû óïðàâëåíèÿ
if (adc.IASampleLength > 4) //íå áîëåå 4 òî÷åê
adc.IASampleLength = 4;
if (adc.IASampleLength < 1) //íå ìåíåå 1 òî÷êè
adc.IASampleLength = 1;
adc.IBSampleLength = adc.IASampleLength;
adc.ICSampleLength = adc.IASampleLength;
adc.UdcSampleLength = adc.IASampleLength;
p->FreqPrev = p->Frequency; //ïðåäûäóùàÿ ÷àñòîòà
EINT;
}
}
//! Ôóíêöèÿ âêëþ÷åíèÿ ØÈÌ (âêëþ÷åíèå èíâåðòîðà)
//! \memberof TPWM_Module
void PWM_Module_On(TPWM_Module *p) {
p->Enabled = 1; //ôëàã "âêëþ÷åíî"
// Ñíèìàåì ïðèíóäèòåëüíóþ óñòàíîâêó âûõîäîâ
PWM0->TZCLR_bit.OST = 1;
PWM1->TZCLR_bit.OST = 1;
PWM2->TZCLR_bit.OST = 1;
}
//! Ôóíêöèÿ âûêëþ÷åíèÿ ØÈÌ (âûêëþ÷åíèå èíâåðòîðà)
//! \memberof TPWM_Module
void PWM_Module_Off(TPWM_Module *p) {
p->Enabled = 0; //ôëàã "âûêëþ÷åíî"
// Ïðèíóäèòåëüíî îáíóëèì âñå íîæêè
PWM0->TZFRC_bit.OST = 1;
PWM1->TZFRC_bit.OST = 1;
PWM2->TZFRC_bit.OST = 1;
}
/*@}*/

318
Vsrc/V_QEP.c Normal file
View File

@ -0,0 +1,318 @@
/*!
Copyright 2017 АО "НИИЭТ" и ООО "НПФ ВЕКТОР"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file V_QEP.c
\brief Модуль оценки скорости и положения при помощи eQEP (см. TposspeedEqep)
\author ООО "НПФ Вектор". http://motorcontrol.ru
\version v 2.0 25/03/2016
\addtogroup V_QEP
@{*/
#include "DSP.h"
#include "V_IQmath.h"
#include "V_QEP.h"
#include "math.h"
#include "stdlib.h"
#include "main.h"
#define FIRST_LAUNCH_UP 1//!< первый пуск при переходе с низкой скорости на более высокую
#define NOT_FIRST_LAUNCH 0//!< не первый пуск
#define SCALE_IQ_K 10
#define LOWEST_UPSS 0
//Как рассчитывать скорость -
//Таймеров QEP между метками аппаратно
#define SPEED_CALC_TYPE_BY_QEP 0
//Программно по производной угла
#define SPEED_CALC_TYPE_BY_SOFT 1
//! Инициализация
//! \memberof TposspeedEqep
void TposspeedEqep_init(TposspeedEqep *p) {
QEP->QCAPCTL_bit.UPPS = LOWEST_UPSS;
QEP->QCAPCTL_bit.CCPS = 4;
QEP->QDECCTL_bit.QSRC = 0; //Вкл. режим квадратурного счёта
QEP->QEPCTL_bit.FREESOFT = 0; //Режим отладчика
QEP->QPOSINIT = 0; //Значение счётчика положения после инициализации или положительного переполнения
QEP->QEPCTL_bit.SWI = 1; //Сброс счётчика
QEP->QPOSMAX = (p->resol << 2) - 1; //Максимальное значение счётчика, после чего обнуление
if (p->Posspeed_CTL.bit.dir == 1) { //Проверка направления движения
QEP->QDECCTL_bit.QAP = 1;
}
QEP->QEPCTL_bit.QPEN = 1; //Вкл. квадратурного счётчика
QEP->QCLR = 0xFFFF; //Отчистка всех флагов
QEP->QEPCTL_bit.QCLM = 0; //Режим захвата - по умолчанию, по событию отработки заданного числа импульсов
if (p->Posspeed_CTL.bit.index_en == 1) { //если индексная метка есть
QEP->QEPCTL_bit.PCRM = 0;
QEP->QEINT_bit.IEL = 1;
} else {
QEP->QEPCTL_bit.PCRM = 1; //Режим обнуления счётчика - по максимальному значению
}
QEP->QWDPRD = 200000 / (1 << 2); //Ввод периода сторожевого таймера
QEP->QEPCTL_bit.WDE = 1; //Вкл. сторожевого таймера
/*Расчёт вспомогательного коэффициента для расчёта скорости,
где 15=60/4, 60 - для перевода в об/мин; 4 - для получения интерполяции разрешения датчика (1 период дает 4 фронта);
SystemCoreClock - частота процессора*/
p->k_low = SystemCoreClock / ((float) p->resol * p->speed_nom) * 15.0;
//В iq формате уменьшаем число в 1<<(24-SCALE_IQ_K), где 24 - дробная часть iq, а SCALE_IQ_K - то, насколько сдвигается величина
//с которой speedK дальше участвует в формуле
p->speedK = _IQ(p->k_low / (1 << (24 - 10)));
p->resol_inv = 1.0 / ((float) p->resol);
//Инициализация портов ввода вывода
GPIOB->ALTFUNCSET = (1 << 11) + (1 << 12) + (1 << 13);
SIU->REMAPAF_bit.QEPEN = 1;
GPIOB->DENSET = (1 << 11) + (1 << 12) + (1 << 13);//для приема ножки апп. аварии разрешаем работу ножки как цифры
}
//! Функция расчёта скорости и положения, вызывается с необходимой дискретностью
//! \memberof TposspeedEqep
void TposspeedEqep_Calc(TposspeedEqep *p) {
long temp;
//Текущее значение GPIO для отладки. Можно смотреть в осцах
p->GPIOsValue = (GPIOB->DATA >> 12) & 3;
//если скорость высокая, а делитель UPEVNT не высокий
if ((labs(p->speed_elec) > _IQ(2)) && (QEP->QCAPCTL_bit.UPPS != 5)) {
QEP->QCAPCTL_bit.UPPS = 5; //делаем делитель UPEVNT высокий
p->skip_counter = 2; //два такта пропустим расчет скорости
}
//если скорость низкая, а делитель не низкий
if ((labs(p->speed_elec) < _IQ(1.5)) && (QEP->QCAPCTL_bit.UPPS != LOWEST_UPSS)) {
QEP->QCAPCTL_bit.UPPS = LOWEST_UPSS; //делаем делитель UPEVNT низкий
p->skip_counter = 2; //два такта пропустим расчет скорости
}
p->UPPS_forWatch = QEP->QCAPCTL_bit.UPPS; //для отображения UPPS наружу
if (p->Posspeed_CTL.bit.CmdInit == 1) { //Команда переинициализации - все обнуляем
QEP->QEPCTL_bit.SWI = 1;
p->Posspeed_FLG1.bit.first_theta = 1;
p->Posspeed_FLG2.bit.pos_ident = 0;
p->Posspeed_CTL.bit.CmdInit = 0;
p->theta_elec = 0;
p->Poscnt_res = 0;
}
p->Poscnt_resPrev=p->Poscnt_res;
p->Poscnt_res = (unsigned long) QEP->QPOSCNT; //захват положения
p->Poscnt_res16=p->Poscnt_res;//Для наблюдения на осциллографе
p->Posspeed_FLG1.bit.PCO_tmp = QEP->QFLG_bit.PCO; //копия флага положительного переполнения счётчика
p->Posspeed_FLG1.bit.PCU_tmp = QEP->QFLG_bit.PCU; //копия флага отрицательного переполнения счётчика
QEP->QCLR_bit.PCO = 1; //отчистка флага положительного переполнения счётчика
QEP->QCLR_bit.PCU = 1; //отчистка флага отрицательного переполнения счётчика
//перевод угла в метках на обороте в механический угол
//Здесь расчет во float - желательно переделать в IQ
p->theta_mech = _IQ((float )p->Poscnt_res * p->resol_inv * 0.25); //расчёт механического угла
p->theta_mech &= 0x00FFFFFF;
// Подсчёт количества полных оборотов. Через PCO и PCU получается как-то глючно
if (p->prevThetaMech - p->theta_mech > _IQ(0.5))
p->RevolutionCounter++;
if (p->prevThetaMech - p->theta_mech < _IQ(-0.5))
p->RevolutionCounter--;
p->prevThetaMech=p->theta_mech;
//угол в метках без обнуления на обороте, абсолютный
p->Poscnt_resContinouosLong=p->Poscnt_res+((QEP->QPOSMAX+1)*p->RevolutionCounter);
p->Poscnt_resContinouosInt=p->Poscnt_resContinouosLong;//чтобы было уднобно смотреть в 16ти разрядном осциллографе
p->Poscnt_resContinouosInt8=p->Poscnt_resContinouosLong&0xF;//чтобы видеть метки в крупном масштабе
//перевод угла в метках абсолютных (не обнуляемых наобороте) в механический угол
//на 127 оборотах всё переполнится, но для демо сгодится
p->theta_mechContinouos = _IQ((float )p->Poscnt_resContinouosLong * p->resol_inv * 0.25); //расчёт механического угла
p->theta_elecContinouos = p->theta_mechContinouos*p->pole_pairs+ p->AngleOffset;//электрический угол абсолютный (не обнуляемый)
//Расчёт электрического положения обнулемого по достижению 360 градусов
p->theta_el_tmp = p->theta_mech*p->pole_pairs + p->AngleOffset;
p->theta_elec = p->theta_el_tmp & 0x00FFFFFF;
//рассчитывать скорость аппаратно, засекая время между метками средствами QEP
if (p->SpeedCalcType==SPEED_CALC_TYPE_BY_QEP){
/*Проверка на срабатывание сторожевого таймера - не пришло не единого импульса*/
if (QEP->QFLG_bit.WTO == 1) {
p->Posspeed_FLG1.bit.first_launch = FIRST_LAUNCH_UP; //указатель первого запуска алгоритма после срабатывания таймера
p->speed_elec = 0; //обнуление скорости
QEP->QCLR_bit.WTO = 1; //отчистка флага
QEP->QWDTMR = 0; //обнуление таймера
} else {
/*переключение по первому запуску для инициализации*/
if (p->Posspeed_FLG1.bit.first_launch == FIRST_LAUNCH_UP) {
//Откл. блока захвата
QEP->QCAPCTL_bit.CEN = 0;
QEP->QCAPCTL_bit.CEN = 1;
p->Posspeed_FLG1.bit.first_launch = NOT_FIRST_LAUNCH;
}
p->QEPSTS=QEP->QEPSTS;//копия регистра статуса
if (p->QEPSTS_bit.UPEVNT == 1) { //есть событие UPEVNT, значит в таймере захвачено время
p->Qcprdlat_tmp = QEP->QCPRD; //копия счетчика времени
p->speed_calc_skip = 0; //пропуск расчета скорости - не пропускать
if (p->QEPSTS_bit.COEF == 1) { //проверка флага переполнения таймера
p->speed_elec = 0;
p->speed_calc_skip = 1; //пропустить расчет скорости
QEP->QEPSTS = 1 << 3;
}
if (p->QEPSTS_bit.CDEF == 1) { //проверка на изменения направления движения во время захвата
p->speed_elec = 0;
p->speed_calc_skip = 1; //пропустить расчет скорости
QEP->QEPSTS = 1 << 2;
}
if (p->Qcprdlat_tmp<7){//ложный фронт
p->speed_calc_skip = 1; //пропустить расчет скорости
}
if (p->QEPSTS_bit.QDF!=p->DirPrev){//сменилось направление движения
p->speed_elec = 0;
p->speed_calc_skip = 1; //пропустить расчет скорости
}
p->DirPrev=p->QEPSTS_bit.QDF;
if (p->skip_counter != 0) { //Сменился UPPS
p->skip_counter--;
p->speed_calc_skip = 1; //пропустить расчет скорости
}
if (p->Qcprdlat_tmp > ((1<<(32-SCALE_IQ_K-1)))) { //Счетчик 32 разряда, а драйвер предназначен для меньшего числа, определяемого SCALE_IQ_K
p->speed_elec = 0;
p->speed_calc_skip = 1; //пропустить расчет скорости
}
if (!p->speed_calc_skip) { //если расчет скорости пропускать не надо
if (p->QEPSTS_bit.QDF == 1) //в зависимости от направления движения
p->speed_tmpIQ = _IQdiv(p->speedK, p->Qcprdlat_tmp << SCALE_IQ_K); //коэффициет скорости делется на 16ти разрядное время, подвинутое вверх на 15
else
p->speed_tmpIQ = -_IQdiv(p->speedK, p->Qcprdlat_tmp << SCALE_IQ_K);
//На сколько нужно подвинуть результат в зависимости от
//делителей на UPEVNT и тактировании счетчика времени
p->MoveK = QEP->QCAPCTL_bit.UPPS
- QEP->QCAPCTL_bit.CCPS;
if (p->MoveK >= 0) //надо подвинуть вверх
p->speed_tmpIQ = p->speed_tmpIQ << p->MoveK;
else
//вниз
p->speed_tmpIQ = p->speed_tmpIQ >> -p->MoveK;
p->speed_elec = p->speed_tmpIQ; //готовая скорость в формате 8.24
}
QEP->QEPSTS = 1 << 7;
}
else if (QEP->QCTMR > QEP->QCPRD)
{ //нет события UPEVNT, считаем по таймеру QCTMR, а не по периоду QCPRD
p->Qcprdlat_tmp = QEP->QCTMR; //копия счетчика
if (p->QEPSTS_bit.COEF == 1) { //проверка флага переполнения таймера
p->speed_elec = 0;
p->speed_calc_skip = 1; //пропустить расчет скорости
}
if (p->QEPSTS_bit.CDEF == 1) { //проверка на изменения направления движения во время захвата
p->speed_elec = 0;
p->speed_calc_skip = 1; //пропустить расчет скорости
}
if (p->Qcprdlat_tmp<7){//ложный фронт
p->speed_calc_skip = 1; //пропустить расчет скорости
}
if (p->Qcprdlat_tmp > ((1<<(32-SCALE_IQ_K-1)))) { //Счетчик 32 разряда, а драйвер предназначен для меньшего числа, определяемого SCALE_IQ_K
p->speed_elec = 0;
p->speed_calc_skip = 1; //пропустить расчет скорости
}
if (!p->speed_calc_skip) { //если расчет скорости пропускать не надо
if (p->QEPSTS_bit.QDF == 1) //в зависимости от направления движения
p->speed_tmpIQ = _IQdiv(p->speedK, p->Qcprdlat_tmp << SCALE_IQ_K); //коэффициет скорости делется на 16ти разрядное время, подвинутое вверх на 15
else
p->speed_tmpIQ = -_IQdiv(p->speedK, p->Qcprdlat_tmp << SCALE_IQ_K);
//На сколько нужно подвинуть результат в зависимости от
//делителей на UPEVNT и тактировании счетчика времени
p->MoveK = QEP->QCAPCTL_bit.UPPS
- QEP->QCAPCTL_bit.CCPS;
if (p->MoveK >= 0) //надо подвинуть вверх
p->speed_tmpIQ = p->speed_tmpIQ << p->MoveK;
else
//вниз
p->speed_tmpIQ = p->speed_tmpIQ >> -p->MoveK;
p->speed_elec = p->speed_tmpIQ; //готовая скорость в формате 8.24
}
}
}
}
//рассчитывать скорость программно через производную угла
if (p->SpeedCalcType==SPEED_CALC_TYPE_BY_SOFT){
//Сначала легкий фильтр на сам угол
//0.5 и маски - это магия нечувствительности фильтра к разнице углов больше 360
//Чтобы при обнулении угла при переходе через 360 градусов при
//вычитании из 5 градусов 355 получилось 10 (в IQ формате)
p->theta_finish=p->theta_finish+_IQmpy(_IQ(0.5),((p->theta_elec-p->theta_finish+_IQ(0.5))&0x00FFFFFF)-_IQ(0.5));
p->theta_finish&=0x00FFFFFF;
//расчитываем приращение угла
temp = (p->theta_finish << 8) - (p->theta_start << 8);
p->d_fi = (temp >> 8);
p->theta_start = p->theta_finish;
//скорость нефильтрованная, рассчитанная из производной угла за один период
p->speed_elec_temp=_IQmpy(p->d_fi,p->KThetaToSpeed)<<3;
//инерционный фильтр для скорости
p->speed_filter.input = p->speed_elec_temp;
p->speed_filter.calc(&p->speed_filter);
p->speed_elec=p->speed_filter.output;
}
}
//! Функция обработки репера (событие индекса)
//! \memberof TposspeedEqep
void TposspeedEqep_IndexEvent(TposspeedEqep *p) {
p->Posspeed_FLG2.bit.pos_ident = 1;
}
//! \memberof TposspeedEqep
void TposspeedEqep_SlowCalc(TposspeedEqep *p) {
//коэффициент перевода производной от угла (вычисляемую неизвестно в чем) в скорость
//сдвиг на 3 чтобы результат деления не переполнил 127, потом при использовании коэфа
//сдвинется назад на 3
p->KThetaToSpeed=_IQdiv(_IQ(1.0),_IQmpyI32(drv_params.freq_nom,FAST_CALC_TS)<<3);
}
/*@}*/

206
Vsrc/V_RTC_Clock.c Normal file
View File

@ -0,0 +1,206 @@
/*!
Copyright 2017 АО "НИИЭТ" и ООО "НПФ ВЕКТОР"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file V_RTC_Clock.c
\brief Модуль для работы с часами реального времени
\author ООО "НПФ Вектор". http://motorcontrol.ru
\version v 2.0 25/03/2016
*/
/*
*
* Часы DS1340 работают в режиме слэйва и имеют 10 регимтров данных/контроля (0x0 ... 0x9).
* Время и дата лежат в регистрах 0x0 ... 0x6.
* Регистр контроля часов, регистр заряда акк., и регистр флагов лежат в 0x7 ... 0x9.
* Указатель на текущий регистр можно поменять, отправив в часы соответствующий номер .
* Чтобы прочитать что-то из часов, сначала нужно обратиться к часам в режиме записи и передать номер
* регистра, с которого нужно считать данные. После этого снова нужно обратиться к часам, но уже
* в режиме чтения. Тогда часы начнут слать содержимое всех регистров по очереди, начиная с того
* регистра, адрес которого был передан в предыдущем обращении. При такой "потоковой" передаче
* указатель на текущий регистр будет автоинкрементироваться, причем в такой последовательности
* (предположим, был установлен адрес 0x5)
* 0x5 -> 0x6 -> 0x7 -> 0x0 -> 0x1 -> ... -> 0x7 -> 0x0
* Чтобы попасть в последние два регистра, нужно передать их адреса явно.
*
* Для того, чтобы записать в часики время, нужно проделать примерно то же самое.
* В режиме записи отправляется сначала номер регистра, в который нужно записать что-то, а затем
* данные, которые нужно туда положить. Указатель на регистры при потоковой передаче инкрементируется
* так же, как и при чтении.
*
* Данные хранятся в двоично-десятичном формате.
*/
//Закомменченные функции вверху отличаются от нижних регистрами (NT_RTC и RTC_REG). Нужны ли закомменченные - не знаю.
#include <DSP.h>
#include <main.h>
// Включатель постоянного считывания времени с ЧРВ. Если дефайн закоменчен - считывание производится только при запуске, а потом
// время считается программно. Если раскомменчен - каждую секунду время считается с часов (секунда отсчитывается в мс)
//#define USE_RTC
/* Инициализация RTC */
void RTC_Clock_Init(TRTCClock *p) {
}
/* Функция считывания текущего времени */
void RTC_Clock_Read_Time(TRTCClock *p) {
// Uint16 tempSec, tempMin, tempHour, tempDOW, tempDay, tempMonth, tempYear;
//
// /* Остановить обновление теневых регисторв */
// NT_RTC->SHDW = 0x0;
//
// /* Прочитать время */
// tempSec = NT_RTC->SECOND;
// tempMin = NT_RTC->MINUTE;
// tempHour = NT_RTC->HOUR;
// tempDOW = NT_RTC->WDAY;
// tempDay = NT_RTC->DAY;
// tempMonth = NT_RTC->MONTH;
// tempYear = NT_RTC->YEAR;
//
// /* Запустить обновление теневых регисторв */
//// NT_RTC->SHDW = 0x80;
//
// // Затем нужно отформатировать пришедшие данные, т.к. они приходят в виде двоично-десятичных чисел (отстой)
// p->second = (tempSec & 0xF) + (((tempSec & 0x70) >> 4) * 10);
// p->minute = (tempMin & 0xF) + (((tempMin & 0x70) >> 4) * 10);
// p->hour = (tempHour & 0xF) + (((tempHour & 0x30) >> 4) * 10);
// p->DOW = (tempDOW & 0x7);
// p->day = (tempDay & 0xF) + (((tempDay & 0x30) >> 4) * 10);
// p->month = (tempMonth & 0xF) + (((tempMonth & 0x10) >> 4) * 10);
// p->year = (tempYear & 0xF) + (((tempYear & 0xF0) >> 4) * 10);
//
// // Наконец, упаковка основных показателей в структурку
// p->packed_time = ((Uint32) p->day << 27) + ((Uint32) p->month << 23)
// + ((Uint32) p->year << 17) + ((Uint32) p->hour << 12)
// + ((Uint32) p->minute << 6) + (Uint32) p->second;
}
/* Функция установки времени */
void RTC_Clock_Set_Time(TRTCClock *p) {
// // Временные переменные (секунды, минуты, часы...)
// unsigned char tempSec, tempMin, tempHour, tempDOW, tempDay, tempMonth,
// tempYear;
// p->tryCounter = 0;
//
// // Сначала нужно распаковать дату
// p->second = p->timeToSet & 0x3F;
// p->minute = (p->timeToSet >> 6) & 0x3F;
// p->hour = (p->timeToSet >> 12) & 0x1F;
// p->year = (p->timeToSet >> 17) & 0x3F;
// p->month = (p->timeToSet >> 23) & 0xF;
// p->day = (p->timeToSet >> 27) & 0x1F;
//
// tempSec = ((p->second / 10) << 4) + ((p->second % 10) & 0xF);
// tempMin = ((p->minute / 10) << 4) + ((p->minute % 10) & 0xF);
// tempHour = ((p->hour / 10) << 4) + ((p->hour % 10) & 0xF);
// tempDOW = p->DOW & 0x3;
// tempDay = ((p->day / 10) << 4) + ((p->day % 10) & 0xF);
// tempMonth = ((p->month / 10) << 4) + ((p->month % 10) & 0xF);
// tempYear = ((p->year / 10) << 4) + ((p->year % 10) & 0xF);
//
// p->msInDay = (Uint32) p->hour * 3600000 + (Uint32) p->minute * 60000
// + (Uint32) p->second * 1000;
//
// // Расчёт дня недели (пижонство)
// int16 a = (14 - p->month) / 12;
// int16 y = p->year - a;
// int16 m = p->month + 12 * a - 2;
// p->DOW = (7000 + (p->day + y + y / 4 - y / 100 + y / 400 + (31 * m) / 12))
// % 7;
//
// NT_RTC->YEAR = tempYear;
// NT_RTC->MONTH = tempMonth;
// NT_RTC->DAY = tempDay;
// NT_RTC->WDAY = tempDOW;
// NT_RTC->HOUR = tempHour;
// NT_RTC->MINUTE = tempMin;
// NT_RTC->SECOND = tempSec;
}
void RTC_Clock_Ms_Calc(TRTCClock *p) {
p->ms++;
p->msInDay++;
#ifdef USE_RTC
if (p->ms > 999) {
p->ms = 0;
p->readTimeFlag = 1;
}
//проверка работы часов реального времени и установка, в зависимсоти от этого, указателя для банка аварий
if (p->secondPrev == p->second) //секунда не меняется
p->stoppedCounter++; //считаем, как долго
else //сменилась, значит часы работают
p->stoppedCounter = 0;
if ((p->stoppedCounter < RTC_SECOND_WAITING_TIMEOUT) && (p->year<48)) //часы работают - тикают и год не 2048 (как когда нет батарейки)
p->ClockOk=1;
else
{
p->ClockOk=0;
p->stoppedCounter = RTC_SECOND_WAITING_TIMEOUT;
}
p->secondPrev = p->second;
#else
if (p->ms == 1000) {
p->ms = 0;
p->second++;
if (p->second == 60) {
p->second = 0;
p->minute++;
if (p->minute == 60) {
p->minute = 0;
p->hour++;
if (p->hour == 24) {
p->hour = 0;
p->msInDay = 0;
p->day++;
}
}
}
p->packed_time = ((Uint32)p->day << 27) + ((Uint32)p->month << 23) + ((Uint32)p->year << 17) +
((Uint32)p->hour << 12) + ((Uint32)p->minute << 6) + (Uint32)p->second;
}
#endif
}
void RTC_Clock_Slow_Calc(TRTCClock *p) {
if (p->setTimeFlag == 1) {
p->timeToSet = p->packed_time;
p->set(p);
p->read(p);
p->msInDay = (Uint32) p->hour * 3600000 + (Uint32) p->minute * 60000
+ (Uint32) p->second * 1000;
p->setTimeFlag = 0;
} else if (p->readTimeFlag == 1) {
p->read(p);
p->readTimeFlag = 0;
}
}

164
Vsrc/V_SSI_Encoder.c Normal file
View File

@ -0,0 +1,164 @@
/*!
Copyright 2017 АО "НИИЭТ" и ООО "НПФ ВЕКТОР"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file V_SSI_Encoder.c
\brief Модуль оценки скорости и положения при помощи цифрового энкодера, работающего по интерфейсу SSI (см. TSSI_Encoder)
\author ООО "НПФ Вектор". http://motorcontrol.ru
\version v 1.0 25/04/2016
\addtogroup V_QEP
@{*/
#include "DSP.h"
#include "V_IQmath.h"
#include "V_SSI_Encoder.h"
#include "math.h"
#include "stdlib.h"
#include "main.h"
//! Инициализация
//! \memberof TSSI_Encoder
void SSI_Encoder_init(TSSI_Encoder *p) {
// volatile long delay;
// volatile Uint32 tempREG;
//
// //SPI-SOMI - на VectorCard нога 88, на проце B15, SPI_RXD2
// //SPI-SIMO - на VectorCard нога 38, на проце C6, SPI_TXD2
// //SPI-CLK - на VectorCard нога 39, на проце B14, SPI_CLK2
// //SPI-STE - на VectorCard нога 89, на проце B13, SPI_FSS2
// //Плата texas DRV8301-HC-EVM разведена так, что микроконтроллер - это ведомое устройство.
// //Нужно сделать его мастером. Подробнее читайте комментарий в заголовочном файле.
//
// // Настройка ног SPI
// GPIOB->ALTFUNCSET = (1 << 13);//чип-селект
// GPIOB->ALTFUNCSET = (1 << 14) | (1 << 15);
// NT_GPIOC->ALTFUNCSET = (1 << 6);//SIMO
// NT_COMMON_REG->GPIOPCTLB_bit.PIN13 = 2;//чип-селект
// NT_COMMON_REG->GPIOPCTLB_bit.PIN14 = 2;
// NT_COMMON_REG->GPIOPCTLB_bit.PIN15 = 2;
// NT_COMMON_REG->GPIOPCTLC_bit.PIN6 = 2;//SIMO
//
//
// // Настройка тактирования SSP модуля
// // Всего 4 модуля, на каждый модуль по 8 бит из регистра SSP_CLK_CTRL и по два бита из UART_SSP_CLK_SEL
//
// // UART_SSP_CLK_SEL
// // Во втором байте слова на каждый из 4-ёх модулей SSP отводится по два бита для выбора источника тактирования 0x0000XX00
// // "00" - в качестве иточника тактирования модуля SSP выбирается системная частота 100 МГц, таким образом f_SSP_IN = SysClk = 100 MHz
//
// // SSP_CLK_CTRL
// // Младший бит разрешает тактирование (1 - разрешить)
// // Второй бит разрешает деление частоты f_SSP_IN источника тактового сигнала (0 - не делить, 1 - делить)
// // Старшие шесть выбирают делитель частоты этого исотчника:
// // X - деление по формуле SSPclk = f_SSP_IN /( 2 * (X +1) )
// // Из документации на блок SSP - минимальная частота для работы модуля в режимах и мастер и слейв,
// // f_SSP_IN > 22.12 MHz, поэтому 25 МГц сделаем
// /* закомменчены, так как тоже самое делается в DRV8301_SPI
// tempREG = NT_COMMON_REG->UART_SPI_CLK_SEL;// Через tempREG, чтобы не задеть другие биты, отвечающие за тактирование UART'a
// tempREG &= 0xFFFF00FF;
// NT_COMMON_REG->UART_SPI_CLK_SEL = tempREG;
// NT_COMMON_REG->SPI_CLK = 0x07070707;// Разрешить тактирование, разрешить деление частоты, делить на 4 - 25 МГц
// */
//
//
// // Настройка самого модуля SPI
// // Продолжение настройки тактирования.
// // Полученная ранее частота f_SSP_IN проходит ещё через два делителя.
// // SSPCPSR - первый делитель, в диапазоне 2 ... 254, может быть только чётным (младший бит всегда хардварно равен 0)
// // SSPCR0.bit.SCR - второй делитель от 0 до 255.
// // Битрейт в итоге BitRate = f_SSP_IN / ( SSPCPSR * (SCR + 1) )
//
// SPI2->SPI_CR1 = 0;// Режим - мастер, LoopBack отключён, сам модуль SSP тоже отключён
// SPI2->SPI_IMSC = 0x0; // Запретить все прерывания
// SPI2->SPI_DMACR = 0; // Запретить DMA
// SPI2->SPI_ICR = 0x3; // Очистка прерываний ("переполнение FIFO приёма" и "необслуженное FIFO приёма")
//
// SPI2->SPI_CPSR = 4; // Деление входной частоты на 4 -> 6,25 MHz
// SPI2->SPI_CR0_bit.DSS = 12; // Размер данных - 12 бит
// SPI2->SPI_CR0_bit.SCR = 0x3F; // Второй делитель
// SPI2->SPI_CR0_bit.FRF = 0x0; // Какая-то "фаза" для протокола Motorola SPI
// SPI2->SPI_CR0_bit.SPH = 0x1; // Какая-то "полярность" для протокола Motorola SPI
// SPI2->SPI_CR0_bit.SPO = 0x0; // Выбор формата кадра Motorola/TI/Microwire. "0" - по протоколу Motorola SPI
// SPI2->SPI_CR1_bit.SSE = 1; // Разрешить работу
//
// p->resol_inv = 1.0 / ((float) p->resol);
//
// p->read(p);
}
//! Функция расчёта скорости и положения, вызывается с необходимой дискретностью
//! \memberof TSSI_Encoder
void SSI_Encoder_Calc(TSSI_Encoder *p) {
p->read(p);
}
void SSI_Encoder_Read(TSSI_Encoder*p) {
// _iq theta_elec_temp;
// Uint16 Data_read=0;
// _iq theta_mech_temp;
//
// if (SPI2->SPI_SR_bit.BSY == 0){//SPI свободен
// Data_read = SPI2->SPI_DR;//код с датчика (число от 0 до resol)
// SPI2->SPI_DR = 0xff;//отправляем что угодно, главное, чтобы тактирование шло
//
//
// if (p->rotation_dir)//обратное направление вращения
// Data_read=(p->resol-1)-Data_read;//период - текущее
// p->Poscnt_res=Data_read;
// }
//
// //перевод угла в метках на обороте в механический угол
// //Здесь расчет во float - желательно переделать в IQ
// p->theta_mech = _IQ((float )p->Poscnt_res * p->resol_inv); //расчёт механического угла
// p->theta_mech &= 0x00FFFFFF;
// //Фильтр угла
// if (p->theta_mech_filterK!=0){
// p->theta_mech_filtered=p->theta_mech_filtered+_IQmpy(p->theta_mech_filterK,((p->theta_mech-p->theta_mech_filtered+_IQ(0.5))&0x00FFFFFF)-_IQ(0.5));
// p->theta_mech_filtered&=0x00FFFFFF;
// }else
// p->theta_mech_filtered=p->theta_mech;
//
// // Подсчёт количества полных оборотов.
// if (p->prevThetaMech - p->theta_mech_filtered > _IQ(0.5))
// p->RevolutionCounter++;
// if (p->prevThetaMech - p->theta_mech_filtered < _IQ(-0.5))
// p->RevolutionCounter--;
// p->prevThetaMech=p->theta_mech_filtered;
//
// //угол в метках без обнуления на обороте, абсолютный
// p->Poscnt_resContinouosLong=p->Poscnt_res+(p->resol*p->RevolutionCounter);
// p->Poscnt_resContinouosInt=p->Poscnt_resContinouosLong;//чтобы было уднобно смотреть в 16ти разрядном осциллографе
// p->Poscnt_resContinouosInt8=p->Poscnt_resContinouosLong&0xF;//чтобы видеть метки в крупном масштабе
//
// //перевод угла в метках абсолютных (не обнуляемых наобороте) в механический угол
// //на 127 оборотах всё переполнится, но для демо сгодится
// p->theta_mechContinouos = p->theta_mech_filtered + _IQ(p->RevolutionCounter); //расчёт механического угла
// p->theta_elecContinouos = p->theta_mechContinouos*p->pole_pairs+ p->AngleOffset;//электрический угол абсолютный (не обнуляемый)
//
// //Расчёт электрического положения обнулемого по достижению 360 градусов
// p->theta_el_tmp = p->theta_mech_filtered*p->pole_pairs + p->AngleOffset;
// p->theta_elec = p->theta_el_tmp & 0x00FFFFFF;
}
/*@}*/

132
Vsrc/V_UserMemory.c Normal file
View File

@ -0,0 +1,132 @@
/*!
Copyright 2017 АО "НИИЭТ" и ООО "НПФ ВЕКТОР"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file V_UserMemory.c
\brief Работа с пользовательской энергонезависимой памятью 1921BK01 (см. TUserMemory)
\author Лашкевич М.М., Шпак Д.М.
\version v 1.0 18/12/2014
*/
/** \addtogroup TUserMemory */
/*@{*/
#include <V_UserMemory.h>
#include "DSP.h"
//!Инициализация
//!Инициализация USERMEMORY
//! \memberof TUserMemory
void USERMEMORY_Init(TUserMemory *p)
{
I2C->CTL1_bit.ENABLE = 1;
I2C->CTL1_bit.SCLFRQ = 63; // Divider: 100 000 000 / (63 * 4) ~ 400 кГц
I2C->CTL3_bit.SCLFRQ = 0; // Divider
}
//! Проверка, не нужно ли сменить страницу
//! Проверяет текущий адрес на флешке, с которым работает пользователь. Если адрес вышел из текущей страницы, страница записывается на флеш и читается в RAM новый
//! \memberof TUserMemory
void USERMEMORY_UpdateCurrentPage(TUserMemory *p, Uint16 spiaddr)
{
}
//! Запись в память
//!Медленная функция, записывающая на flash заданные данные.
//!Работает с закешированными в оперативке данными, а физическ пишет на флеш только если адрес вылез за границы текущей страницы
//! Адрес во флеше spiaddr, адрес 16ти разрядных данных пользователя startaddr, размер data_length. Все в байтах
//! При выполении операции startaddr инкрементируется, а spiaddr нет
//! \memberof TUserMemory
void USERMEMORY_Write(TUserMemory *p)
{
}
//! Чтение из памяти
//!Медленная функция, считывающая из flash заданные данные. Подробности см. TUserMemory.
//! Адрес во флеше spiaddr, адрес адрес 16ти разрядных данных пользователя startaddr, размер data_length. Все в байтах.
//! При выполении операции startaddr инкрементируется, а spiaddr нет
//! \memberof TUserMemory
void USERMEMORY_Read(TUserMemory *p)
{
}
//! Записывает страницу данные на флешку из кеша (из оперативки одну страницу)
//! \memberof TUserMemory
void USERMEMORY_WriteFromCache(TUserMemory *p, int16 pageNum)
{
}
//! Читает страницу данных из флеша в кеш (в оперативку)
//! \memberof TUserMemory
void USERMEMORY_ReadToCache(TUserMemory *p, int16 pageNum)
{
}
//! Стереть всю флешку (будут FF)
//! \memberof TUserMemory
void USERMEMORY_Full_Erase(TUserMemory *p){
}
//! Сбросить кеш из оперативки на флешку
//! \memberof TUserMemory
void USERMEMORY_Flush(TUserMemory *p){
}
//! Медленный фоновый постоянный расчет - нужен пока для систематического сброса кеша на флешку по времени
//! \memberof TUserMemory
void USERMEMORY_slow_calc(TUserMemory *p){
// }
}
//! Миллисекундный расчет - нужен пока для систематического сброса кеша на флешку по времени
//! \memberof TUserMemory
void USERMEMORY_ms_calc(TUserMemory *p){
}
/*@}*/

185
Vsrc/V_adc.c Normal file
View File

@ -0,0 +1,185 @@
/*!
Copyright 2017 АО "НИИЭТ" и ООО "НПФ ВЕКТОР"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file V_adc.c
\brief Модуль обработки АЦП (см. TAdcDrv)
\author ООО "НПФ Вектор". http://motorcontrol.ru
\version v 2.0 25/03/2016
\addtogroup V_adc
@{*/
#include "main.h"
//!Инициализация.
//! Настраиваются секвенсоры и тип оцифровки данных. каналы для оцифровки, частота.
//! В данном случае оцифровка происходит по событию таймера,частота которого
//! равна частоте ШИМ, чтобы измерять ровно посередине периода ШИМ (требуется для шунтовых
//! датчиков тока)
//Запуск оцифровки производится по таймеру NT_PWM3, который синхронизирован с другими таймерами ШИМ.
//Оцифрованные измерения складываются в ФИФО. Каждый канал АЦП настроен на отдельный секвенсор с ФИФО длиной до 16 измерений.
//В прерывании с частотой 10 кГц данные забираются из ФИФО и складываются в кольцевые массивы (старые затираются новыми).
//В том же прерывании из кольцевого массива берется N последних точек и из них вычисляется среднее арифметическое.
//Число выборок для усреднения N зависит от частоты ШИМ и равна Fшим/10кГц. Если частоты ШИМ меньше 10 кГц, то берется одна выборка, если больше 40 кГц - 4 выборки.
//К вычисленному среднему значению добавляется калибровочный сдвиг, и оно умножается на коэффициент измерения, в результате получается окончательный результат измерения.
//! \memberof TAdcDrv
void AdcDrv_init(TAdcDrv *p) {
PWM0->ETSEL_bit.SOCAEN = 1;
PWM0->ETSEL_bit.SOCASEL = ET_CTR_ZERO;
PWM0->ETPS_bit.SOCAPRD = 2;
Uint32 AdcClock, AdcDiv, trash;
Uint32 pwmPrd = PWM0->TBPRD; // Предположим, частота 10 кГц
if (pwmPrd < 1000) pwmPrd = 1000;
//Инициализация ADC
RCU->ADCCFG_bit.CLKSEL = RCU_ADCCFG_CLKSEL_PLLCLK; // Тактирование от PLL
RCU->ADCCFG_bit.DIVN = 0x1; // N = 2 * (DIVN + 1) = 4 -> ACLK = 25 MHz
RCU->ADCCFG_bit.DIVEN = 0x1; // Разрешить делитель
AdcDiv = 2 * (RCU->ADCCFG_bit.DIVN + 1); // Итого деление частоты
AdcClock = SystemCoreClock / AdcDiv;
RCU->ADCCFG_bit.CLKEN = 0x1; // Разрешить тактирование
RCU->ADCCFG_bit.RSTDIS = 0x1; // Снимаем сброс
ADC->ACTL_bit.ADCEN = 0x1; // Разрешаем работу АЦП
//Настройка секвенсора 0
// CH0, CH1, CH2, CH3.
ADC->EMUX_bit.EM0 = ADC_EMUX_EM0_PWM012A; // Запуск от таймера
ADC->SEQSYNC = ADC_SEQSYNC_SYNC0_Msk; // Разрешить секвенсор SEQ0
ADC->SEQ[0].SRQCTL_bit.RQMAX = 0x3; // Опрашивать 4 канала за раз = RQMAX + 1
ADC->SEQ[0].SRQSEL_bit.RQ0 = 0x0; // Какой вход АЦП когда опрашивается
ADC->SEQ[0].SRQSEL_bit.RQ1 = 0x1; // --//--
ADC->SEQ[0].SRQSEL_bit.RQ2 = 0x2; // --//--
ADC->SEQ[0].SRQSEL_bit.RQ3 = 0x3; // --//--
ADC->SEQ[0].SCCTL_bit.RCNT = 3; // Делать ещё три перезапуска после первого запуска
ADC->SEQ[0].SRTMR_bit.VAL = (pwmPrd / AdcDiv) / (ADC->SEQ[0].SCCTL_bit.RCNT + 1); // Пауза между пусами АЦП на период ШИМ
ADC->SEQ[0].SCCTL_bit.ICNT = 3; // Вызов прерывания через каждые (ICNT + 1) оцифровки
ADC->SEQ[0].SCCTL_bit.RAVGEN = 1; // Разрешить усреднять по 4 точкам
ADC->SEQEN_bit.SEQEN0 = 1; // Разрешить секвенсор 0
// Очистка FIFO
while (ADC->SEQ[0].SFLOAD)
trash = ADC->SEQ[0].SFIFO;
// Разрешить EPWM0 запускать АЦП по нулю
// Ждём, пока АЦП выставит флаг "ГОТОВ" (можно вставить этот цикл после "ADCEN = 1")
while (!ADC->ACTL_bit.ADCRDY) {};
// Разрешить прерывание от первого секвенсера
ADC->IM_bit.SEQIM0 = 1;
NVIC_EnableIRQ(ADC_SEQ0_IRQn);
NVIC_SetPriority(ADC_SEQ0_IRQn, IRQ_PRIORITY_ADC);
}
//!Расчет АЦП с частотой основного расчета всей системы управления (обычно 10кГц).
//! Занимается обработкой измеренных АЦП значений и преобразует в формат IQ24.
//! Токи фаз для повышения точности усредняются за несколько измерений
//! \memberof TAdcDrv
void AdcDrv_fast_calc(TAdcDrv *p) {
Uint32 trash;
// Если всё пошло хорошо, то в ФИФЕ будут уже усреднённые результаты - 4 штуки.
p->IA_temp = ADC->SEQ[0].SFIFO;
p->IB_temp = ADC->SEQ[0].SFIFO;
p->Udc_temp = ADC->SEQ[0].SFIFO;
p->T_temp = ADC->SEQ[0].SFIFO;
// Очистка FIFO на случай, если почему-то там оказалось больше чем надо значений (бывает после остановки житагом)
while (ADC->SEQ[0].SFLOAD)
trash = ADC->SEQ[0].SFIFO;
p->Imeas_a = p->IaGainNom * (((p->IA_temp<< 4) + p->Imeas_a_offset));
p->Imeas_b = p->IbGainNom * (((p->IB_temp<< 4) + p->Imeas_b_offset));
p->Udc_meas = p->UdcGainNom * (p->Udc_temp + p->Udc_meas_offset);
p->Imeas_c = -p->Imeas_a - p->Imeas_b;
//ADC->SEQ[0].SCCTL_bit.RAVGEN ^= 1;
}
//!Медленный расчет.
//!Занимается пересчетом коэффициентов, используемых в скоростной функции расчета,
//!чтобы не занимать процессорное время там. Находит коэффициенты,
//!на которые надо умножить полученное с АЦП значение, чтобы получить
//!относительные единицы с заданной базой.
//! Пример p->PvalveGainNom=_IQ16mpy(p->Pvalve_gain,_IQ(1.0/100));
//! Pvalve_gain - значение в формате int. задается пользователем в UniCON.
//!Определяет, скольким процентам соответствует полный диапазон АЦП. В простейшем случае
//!равен 100. Т.е. когда на АЦП максимальный сигнал, это соответствует 100%.
//!_IQ(1.0/100) обратное значение для масштабирующего коэффициента. Так как величину процентов
//!естественнее всего перевести в относительные единицы так, что 100% соответствут 1.0,
//!то масштабирующий коэффициент (база) равен 100. Т.е. UniCON, прочитав из системы управления
//! число 1.0 в формате 8.24 должен умножить его на 100, чтобы отобразились проценты.
//! Здесь коэффициент задан явно как 1.0/100, но для ряда случаев базовое значение нужно менять.
//!Так, для токов фаз используется значение _1_I_nom, в формате 8.24, соответствующее единице деленной на
//базовое значение тока, например, 200 А. Так как в зависимости от мощности преобразователя базовый ток может меняться,
//то это значение, в отличие от процентов, сделано настраиваемым. Расчет _1_I_nom идет в другом месте, так как
//занимает много тактов расчета.
//Для беззнакового значения АЦП измеряет число от 0 до 65535. (16 разрядов, где заполнены верхние).
//Для примера с процентами необходимо сделать так, чтобы получилось результирующее значение в формате 8.24,
//где 1.0 это 65535. Таким образом, нужно сдвинуть число 65535 на 24-16=8 разрядов.
//Сдвиг на 8 разрядов - это умножение на число 255. Число 255 - это 1.0 в формате 24.8.
//Таким образом, PvalveGainNom - это коэффициент в формате 24.8. он получается в результате использования функции
//_IQ16mpy, аргумены которой Pvalve_gain (int) и 1.0/100 в формате 8.24. Функция IQ множения
//по сути представляет собой обычное оуможение в 64 разрядах со сдвигом результата вправо на Q разрядов.
//Т.е. _IQ16mpy умножает число в формате IQ24 9второй аргумент) на целочисленный коэффициент (первый аргумент),
//а потом сдвигате результат на 16 разрядов вправо.
//Так, в результате _IQ16mpy(p->Pvalve_gain,_IQ(1.0/100)); получается целочисленное число 255, являющейся
//1.0 в формате 24.8 из-за сдвига на 16 разрядов вправо.
//Всё вышеприведенное мутево сделано с одной целью - увеличить производитлеьность обработки АЦП.
//! \memberof TAdcDrv
void AdcDrv_slow_calc(TAdcDrv *p) {
// Пересчёт пауз между перезапусками
volatile Uint16 pwmPrd = PWM0->TBPRD;
// Если считает вверх-вниз, то период на деле в два раза больше
if (PWM0->TBCTL_bit.CTRMODE == TB_COUNT_UPDOWN)
pwmPrd = pwmPrd << 1;
// Делитель частоты АЦП
Uint16 AdcDiv = 2 * (RCU->ADCCFG_bit.DIVN + 1);
if (pwmPrd < 1000) pwmPrd = 1000;
ADC->SEQ[0].SRTMR_bit.VAL = (pwmPrd / AdcDiv) / (ADC->SEQ[0].SCCTL_bit.RCNT + 1);
p->IaGainNom = _IQ16mpy(p->Imeas_a_gain, drv_params._1_I_nom) << 1;
p->IbGainNom = _IQ16mpy(p->Imeas_b_gain, drv_params._1_I_nom) << 1;
p->IcGainNom = _IQ16mpy(p->Imeas_c_gain, drv_params._1_I_nom) << 1;
p->UdcGainNom = _IQ16mpy(p->Udc_meas_gain, drv_params._1_Udc_nom) << 4;
}
//! Миллисекундный расчет
//! \memberof TAdcDrv
void AdcDrv_ms_calc(TAdcDrv *p) {
}
/*@}*/

View File

@ -0,0 +1,72 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file V_bits_to_enum_numbers.c
\brief Ìîäóëü "ëèñòàíèÿ" áèòîâûõ ïåðåìåííûõ (ñì. TBitsToEnumNums)
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 2.0 25/03/2016
*/
/** \addtogroup V_bits_to_enum_numbers */
/*@{*/
#include "DSP.h"
#include "V_bits_to_enum_numbers.h"
//! Ïðåîáðàçóåò áèòîâûå ïåðåìåííûå â ÷èñëà
//!Òðåáóåòñÿ â îñíîâíîì äëÿ ìîäóëÿ çàùèò èëè ïðåäóïðåæäåíèé,
//!äëÿ ïðåîáðàçîâàíèÿ âûñòàâëåííûõ áèò àâàðèè â ñëîâàõ àâàðèè â
//!ïîðÿäêîâûé íîìåð ýòèõ áèò è "ëèñòàíèÿ" ýòèõ íîìåðîâ ñ îïðåäåëåííîé
//!÷àñòîòîé, åñëè âûñòàâëåíî íåñêîëüêî áèò. Òàêîå ïðåîáðàçîâàíèå íóæíî äëÿ
//!óäîáñòâà íàáëþäåíèÿ àâàðèé/ïðåäóïðåæäåíèé ïîëüçîâàòåëåì.
//!Âûçûâàòü íåîáõîäèìî ñ îïðåäåëåííîé äèñêðåòèçàöèåé (íàïðèìåð, 10êÃö).
//! \memberof TBitsToEnumNums
void BitsToEnumNums(TBitsToEnumNums* p) {
Uint16 i;
p->counter++;
if (p->counter < p->out_refresh_devisor)
return;
p->counter = 0;
//ïðîâåðêà ïðàâèëüíîñòè âûçîâà
if ((p->num_of_words > NUM_OF_W_PTRS) || (p->num_of_words == 0))
return;
//ïåðåáèðàåì áèòû â ïîðÿäêå âîçðàñòàíèÿ
for (i = 0; i < (16 * p->num_of_words); i++) {
p->last_bit++;
if (p->last_bit > 15) {
p->last_bit = 0;
p->last_word++;
if (p->last_word > (p->num_of_words - 1))
p->last_word = 0;
}
//äåëàåì ïðîâåðêó áèòà
if ((*(p->w_ptrs[p->last_word])) & (0x1 << p->last_bit)) {
//áèòèê èìååòñÿ âûâîäèì ðåçóëüòàò
p->output = p->last_word * 16 + p->last_bit + 1;
return;
}
}
//åñëè äîøëè äî ñþäà çíà÷èò íåò áèòèêîâ, ïîòîìó âûäàåì 0
p->output = 0;
}
/*@}*/

281
Vsrc/V_data_log.c Normal file
View File

@ -0,0 +1,281 @@
/*!
\file v_data_log.c
\brief 4-х канальный логгер длЯ осциллографированиЯ в реальном времени TDataLog (см. TDataLog)
\author Коллектив ООО НПФ Вектор
\version v 2.01 18/09/2012
*/
/** \addtogroup v_data_log */
/*@{*/
#include "DSP.h"
#include "co_ODvars.h"
#include "V_data_log.h"
#include "CANOpen_drv.h"
//! Фоновый обработчик.
/*! работает в фоне. Нужно длЯ установки адресов переменных через CAN.
если нет CAN, можно записать нужные адреса вручную в TDataLog.dlog_iptr */
//! \memberof TDataLog
void dlog_background_analizer(TDataLog *p) {
//перевод длины предыстории из % в точки
p->trig_shift_int = (p->trig_shift&0xFFFFFF)>>16; //делаем количество точек
if (p->trig_shift_int > 255) //ограничим
p->trig_shift_int = 255;
unsigned char mode;
//если не стоит хоть один из первых шести бит control,
//то ничего анализировать и делать не надо
if (!(p->control & 0x3F))
return;
//В любом случае перед всеми изменениЯми
//тормозим даталоггер. Иначе он может начать записывать данные по прерыванию,
//пока тут, в фоне, идет, скажем, запись адресов.
//И тогда в лучшем случае будет каша из данных, в худшем - останов контроллера
//при обращении по неправильному адресу.
p->mode_reset = 0;
p->valid_points_num = 0; //т.к. даталоггер останавливался (mode = 0), то предыстория неактуальна, т.к.
//1) за время стопа даталоггера между записанной предысторией и новыми данными будет разрыв по времени и
//2) выбранные записываемые переменные вообще могли смениться и предыстория останется от старых, а новые данные - от новых
//спрашиваем адреса у драйвера CANopen
#if DLOG_DATA_SIZE == 16
if (p->control & 1)
if (!(p->dlog_iptr1 = (type_data*)co_getAddr(p->pco_vars, p->ind_subind1))) //если адрес=0
p->dlog_iptr1 = (type_data*)&p->ind_subind1; //пусть указывает на ind_subind
if (p->control & 2)
if (!(p->dlog_iptr2 = (type_data*)co_getAddr(p->pco_vars, p->ind_subind2)))
p->dlog_iptr2 = (type_data*)&p->ind_subind2;
if (p->control & 4)
if (!(p->dlog_iptr3 = (type_data*)co_getAddr(p->pco_vars, p->ind_subind3)))
p->dlog_iptr3 = (type_data*)&p->ind_subind3;
if (p->control & 8)
if (!(p->dlog_iptr4 = (type_data*)co_getAddr(p->pco_vars, p->ind_subind4)))
p->dlog_iptr4 = (type_data*)&p->ind_subind4;
#endif
#if DLOG_DATA_SIZE == 32
if (p->control & 1)
{
if (co_getObjectInfo(p->pco_vars, p->ind_subind1, (TObjectInfo*)&p->object1Info) == 0)
{
p->object1Info.varAddr = (void*)(&p->ind_subind1);
p->object1Info.varSize = 32;
}
}
if (p->control & 2)
{
if (co_getObjectInfo(p->pco_vars, p->ind_subind2, (TObjectInfo*)&p->object2Info) == 0)
{
p->object2Info.varAddr = (void*)(&p->ind_subind2);
p->object2Info.varSize = 32;
}
}
if (p->control & 4)
{
if (co_getObjectInfo(p->pco_vars, p->ind_subind3, (TObjectInfo*)&p->object3Info) == 0)
{
p->object3Info.varAddr = (void*)(&p->ind_subind3);
p->object3Info.varSize = 32;
}
}
if (p->control & 8)
{
if (co_getObjectInfo(p->pco_vars, p->ind_subind4, (TObjectInfo*)&p->object4Info) == 0)
{
p->object4Info.varAddr = (void*)(&p->ind_subind4);
p->object4Info.varSize = 32;
}
}
p->highPartOfValue = 0;
#endif
p->WriteDelimiter = (p->control >> 16) & 0xFF; //прореживание. ОграничиваетсЯ 8ю битами
mode = (p->control >> 4) & 3; //режим - 2 бита
p->control = 0; //все обработали, обнулЯем, чтобы при след. вызове не начать обрабатывать снова
dlog_set_mode(mode, p); //длЯ установки режима вызываетсЯ спец. функциЯ. НапрЯмую нельзЯ
}
//! функциЯ длЯ установки mode_reset.
//! предполагаетсЯ длЯ управлениЯ логгером из других модулей
//! проверЯет mode_reset на валидность и обнулЯет счетчики
//! \memberof TDataLog
void dlog_set_mode(Uint16 mode_reset, TDataLog *p) {
if (mode_reset > 3)
return;
//в 1 переводим только если текущий режим 2, чтоб синхронизироватьсЯ
//по первому событию (очень полезно когда событий много)
if (p->OneShotOperation == 1) {
if ((mode_reset == 1)) {
if (p->mode_reset == 2)
p->mode_reset = mode_reset;
else
return;
}
} else
p->mode_reset = mode_reset;
if (mode_reset == 3) //Хотим перейти в режим однократной записи 1024 точек.
p->Wcounter = 0; //в этом режиме нужно писать с первой точки первого массива. Сбрасываем счетчик.
//при смене режима в любом случае сбрасываем флаг "данные готовы"
p->control &= ~(1 << 6);
p->WriteDelimiterCounter = 0;
#if DLOG_DATA_SIZE == 32
p->highPartOfValue = 0;
#endif
}
//! Записывает очередные точки в массивы осциллограммы.
//!Должна вызыватьсЯ с заданной дискретизацией и занимаетсЯ записью массивов,
//! т.е. непосредственно осциллографированием. Умеет записывать данные
//! в массивы по-разному в зависимости от выбранного режима работы осциллографа
//! \memberof TDataLog
void data_log_update(TDataLog *p) {
//везде испоьзуетсЯ p-> , а не p* - так быстрее
//прореживание данных. Если не достигли уставки WriteDelimiter, выходим
//WriteDelimiter=1 - не делим
//WriteDelimiter=2 - берем каждую вторую
if ((p->WriteDelimiterCounter++ + 1) < p->WriteDelimiter)
return;
else
p->WriteDelimiterCounter = 0;
if (p->mode_reset != p->mode_reset_prev) p->E=1;
else p->E=0;
p->mode_reset_prev = p->mode_reset;
switch (p->mode_reset) {
case 0: {
p->Wcounter = 0;
return;
}
case 1: //однократнаЯ запись - дошли до конца и стоп (режим 0)
{
//При входе в режим получаем точку срабатывания триггера (это текущий Wcounter, с которым мы сюда зашли) и рассчитываем первую точку, относящуюся к данной осце (исходя из текущей точки и заданной длины предыстории)
if (p->E==1)
{
p->prehistory_length = p->valid_points_num; //длина предыстории равна количеству валидных точек
if (p->prehistory_length > p->trig_shift_int) //если предыстория длиннее заданного, ограничим
p->prehistory_length = p->trig_shift_int;
#if DLOG_DATA_SIZE == 16
p->Wcounter &= 0xFE;
p->prehistory_length &= 0xFE;
p->first_point_written = (p->Wcounter - p->prehistory_length) & 0xFE;
#endif
#if DLOG_DATA_SIZE == 32
p->first_point_written = (p->Wcounter - p->prehistory_length) & 0xFF;
p->highPartOfValue = 0;
#endif
}
p->Wcounter &= 0xFF; //защита - если вдруг в counter не валидное значение
#if DLOG_DATA_SIZE == 16
p->dl_buffer1_adr[p->Wcounter] = *p->dlog_iptr1;
p->dl_buffer2_adr[p->Wcounter] = *p->dlog_iptr2;
p->dl_buffer3_adr[p->Wcounter] = *p->dlog_iptr3;
p->dl_buffer4_adr[p->Wcounter] = *p->dlog_iptr4;
#endif
#if DLOG_DATA_SIZE == 32
p->dl_buffer1_adr[p->Wcounter] = p->object1Info.varSize == 16 ?
*((int16*)p->object1Info.varAddr) : *((int32*)p->object1Info.varAddr);
p->dl_buffer2_adr[p->Wcounter] = p->object2Info.varSize == 16 ?
*((int16*)p->object2Info.varAddr) : *((int32*)p->object2Info.varAddr);
p->dl_buffer3_adr[p->Wcounter] = p->object3Info.varSize == 16 ?
*((int16*)p->object3Info.varAddr) : *((int32*)p->object3Info.varAddr);
p->dl_buffer4_adr[p->Wcounter] = p->object4Info.varSize == 16 ?
*((int16*)p->object4Info.varAddr) : *((int32*)p->object4Info.varAddr);
#endif
p->Wcounter++;
p->Wcounter &= 0xFF; //если прошли 256 точек, обнулитсЯ
if (p->Wcounter == p->first_point_written) //если дошли до последней записываемой точки
{
p->mode_reset = 0; //режим СТОП
#if DLOG_DATA_SIZE == 16
p->control |= 192; // "данные готовы" + "поддерживается блочная передача"
#else
p->control |= 192 | (1 << 8); // "данные готовы" + "поддерживается блочная передача" + "32-битные данные"
#endif
}
return;
}
case 2: //записываем лог по кругу
{
if (p->E == 1)
{
#if DLOG_DATA_SIZE == 32
p->highPartOfValue = 0;
#endif
}
p->valid_points_num++; //считаем количество записанных валидных точек предыстории
if (p->valid_points_num > 256) //ограничиваем
p->valid_points_num = 256;
p->Wcounter &= 0xFF; //защита - если вдруг в counter не валидное значение
#if DLOG_DATA_SIZE == 16
p->dl_buffer1_adr[p->Wcounter] = *p->dlog_iptr1;
p->dl_buffer2_adr[p->Wcounter] = *p->dlog_iptr2;
p->dl_buffer3_adr[p->Wcounter] = *p->dlog_iptr3;
p->dl_buffer4_adr[p->Wcounter] = *p->dlog_iptr4;
#endif
#if DLOG_DATA_SIZE == 32
p->dl_buffer1_adr[p->Wcounter] = p->object1Info.varSize == 16 ?
*((int16*)p->object1Info.varAddr) : *((int32*)p->object1Info.varAddr);
p->dl_buffer2_adr[p->Wcounter] = p->object2Info.varSize == 16 ?
*((int16*)p->object2Info.varAddr) : *((int32*)p->object2Info.varAddr);
p->dl_buffer3_adr[p->Wcounter] = p->object3Info.varSize == 16 ?
*((int16*)p->object3Info.varAddr) : *((int32*)p->object3Info.varAddr);
p->dl_buffer4_adr[p->Wcounter] = p->object4Info.varSize == 16 ?
*((int16*)p->object4Info.varAddr) : *((int32*)p->object4Info.varAddr);
#endif
p->Wcounter++;
p->Wcounter &= 0xFF; //если прошли 256 точек, обнулитсЯ
return;
}
case 3: //режим однократной записи 1024 точек
{
if (p->E==1)
{
p->first_point_written = 0; //пишем с первой точки, предыстория не нужна.
#if DLOG_DATA_SIZE == 32
p->highPartOfValue = 0;
#endif
}
//с учетом того, что буферы в памЯти расположены последовательно,
//записываем в первый, "заезжаЯ" на остальные три
#if DLOG_DATA_SIZE == 16
p->dl_buffer1_adr[p->Wcounter] = *p->dlog_iptr1;
#endif
#if DLOG_DATA_SIZE == 32
p->dl_buffer1_adr[p->Wcounter] = p->object1Info.varSize == 16 ?
*((int16*)p->object1Info.varAddr) : *((int32*)p->object1Info.varAddr);
#endif
p->Wcounter++;
if (p->Wcounter >= 1024) //если дошли до конца
{
p->mode_reset = 0; //режим СТОП
#if DLOG_DATA_SIZE == 16
p->control |= 192; // "данные готовы" + "поддерживается блочная передача"
#else
p->control |= 192 | (1 << 8); // "данные готовы" + "поддерживается блочная передача" + "32-битные данные"
#endif
}
return;
}
}
}
/*@}*/

252
Vsrc/V_event_log.c Normal file
View File

@ -0,0 +1,252 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file V_event_log.c
\brief Ñîõðàíåíèå ñîáûòèé è âðåìåíè âîçíèêíîâåíèß â ÝíÎÇÓ
Èñïîëüçóåòñß äðàéâåð ðàáîòû ñ ýíåðãîíåçàâèñèìîé ïàìßòüþ
Ïîýòîìó âûçîâ init(); äîëæåí áûòü ïîñëå èíèöèàëèçàöèè ÝíÎÇÓ
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 1.0 2009_01_20
*/
/** \addtogroup W_event_log */
/*@{*/
#ifdef __cplusplus
extern "C" {
#endif
#include <main.h>
//!<Ïðîòîêîëèðîâàíèå àâàðèé
//Ïðîöåäóðû çàïèñè ñîáûòèé â ýíåðãîíåçàâèñèìóþ ôëåøêó î÷åíü äîëãèå (ñâÿçàíî ñ òàéìèíãàìè I2C-èíòåðôåéñà
//è áîëüøèì îáúåìîì äàííûõ, ïåðåäàâàåìûì ïî I2C â ïðîöåññå çàïèñè).
//Ïîýòîìó àëãîðèòì ðàáîòû òàêîé:
//Åñëè íóæíî ïðî÷èòàòü àâàðèþ [Logger_Event_Read] (ñðî÷íî ñ÷èòûâàòü àâàðèþ èç áàíêà íå òðåáóåòñÿ) -
//îíà ÷èòàåòñÿ â ôîíîâîì öèêëå ïðÿìèêîì èç ÝíÎÇÓ.
//Åñëè íóæíî çàïèñàòü àâàðèþ â áàíê [Logger_Event_Write] - â ïðåðûâàíèè (íàïðèìåð, 1ìñ) äàííûå àâàðèè ïèøóòñÿ â FIFO;
//çàòåì â ôîíîâîì öèêëå [Logger_Background_Calc] àâàðèè ÷èòàþòñÿ èç FIFO [Event_FIFO_Read]
//(ïî îäíî çà 1 ôîíîâûé öèêë) è ïèøóòñÿ â ÝíÎÇÓ.
//ïðî÷èòàòü ñîáûòèå èç FIFO (äëÿ äàëüíåéøåé çàïèñè â ÝíÎÇÓ).
Uint16 Event_FIFO_Read(TEventFIFO* p,TEvent* ev)
{
if (p->busy_flag > 0) return EVENT_FIFO_BUSY;
//âûñòàâëßåì ôëàæîê ðàáîòû ñ FIFO
p->busy_flag = 1;
if (p->number_of_msgs == 0)
{
//îñâîáîæäàåì ôëàã ðàáîòû ñ FIFO
p->busy_flag = 0;
return EVENT_FIFO_EMPTY;
}
//÷èòàåì äàííûå èç FIFO
ev->ev_code = p->msg_array[(p->read_ptr)].ev_code;
ev->ev_time = p->msg_array[(p->read_ptr)].ev_time;
ev->ev_num = p->msg_array[(p->read_ptr)].ev_num;
//ïîäãîòîâêà FIFO ê ñëåäóþùåìó âûçîâó
p->read_ptr++;
if (p->read_ptr >= p->size) p->read_ptr = 0;
p->number_of_msgs--;
//îñâîáîæäàåì ôëàã ðàáîòû ñ FIFO
p->busy_flag = 0;
return EVENT_FIFO_SUCCESSFUL;
}
//Çàïèñàòü ñîáûòèå â FIFO (âûçûâàåòñÿ â Logger_Event_Write, â ïðåðûâàíèè)
Uint16 Event_FIFO_Write(TEventFIFO* p,TEvent* ev)
{
if (p->busy_flag > 0) return EVENT_FIFO_BUSY;
//âûñòàâëßåì ôëàæîê ðàáîòû ñ FIFO
p->busy_flag = 1;
if (p->number_of_msgs == p->size)
{
//îñâîáîæäàåì ôëàã ðàáîòû ñ FIFO
p->busy_flag = 0;
return EVENT_FIFO_FULL;
}
//çàïèñûâàåì äàííûå â FIFO
p->msg_array[(p->write_ptr)].ev_code = ev->ev_code;
p->msg_array[(p->write_ptr)].ev_time = ev->ev_time;
p->msg_array[(p->write_ptr)].ev_num = ev->ev_num;
//ïîäãîòîâêà FIFO ê ñëåäóþùåìó âûçîâó
p->write_ptr++;
if (p->write_ptr >= p->size)p->write_ptr = 0;
p->number_of_msgs++;
//îñâîáîæäàåì ôëàã ðàáîòû ñ FIFO
p->busy_flag = 0;
return EVENT_FIFO_SUCCESSFUL;
}
//èíèöèàëèçàöèÿ (åñëè áàíê çàáèò ìóñîðîì - âñå äàííûå FFFF, î÷èùàåì åãî)
void Logger_Init(TLogger* p,Uint16 BS,Uint16 SA,Uint32* tptr)
{
TEvent tmp;
Uint16 i;
Uint16 last_log_num = 0;
Uint16 last_log_index = 0;
//èíèöèàëèçèðóåì âíóòðåííèå ïåðåìåííûå
p->SPI_buf_size = BS;
p->SPI_start_addr = SA;
p->time_ptr = tptr;
//äàëåå íóæíî ïðîñêàíèðîâàòü áóôåð â ÝíÎÇÓ - íàéòè ïîñëåäíþþ
UserMem.MemStartAddr = p->SPI_start_addr;
UserMem.data_length = 0;
for (i=0;i<p->SPI_buf_size;i++)
{
//÷èòàåì íîìåð
UserMem.MemStartAddr += UserMem.data_length;
UserMem.MCUStartAddr = (Uint16*)(&tmp.ev_num);
UserMem.data_length = LOG_NUM_LENGTH;
UserMem.read(&UserMem);
//÷èòàåì âðåìß
UserMem.MemStartAddr += UserMem.data_length;
UserMem.MCUStartAddr = (Uint16*)(&tmp.ev_time);
UserMem.data_length = LOG_TIME_LENGTH;
UserMem.read(&UserMem);
//÷èòàåì êîä
UserMem.MemStartAddr += UserMem.data_length;
UserMem.MCUStartAddr = (Uint16*)(&tmp.ev_code);
UserMem.data_length = LOG_CODE_LENGTH;
UserMem.read(&UserMem);
//äåëàåì íåîáõîäèìûå ïðîâåðêè
//åñëè âñå ïîëß 0xFFFF, òî ÷èñòèì âñþ ïàìßòü
if ((tmp.ev_num == 0xFFFF) && (tmp.ev_time == 0xFFFFFFFF) && (tmp.ev_code == 0xFFFF))
{
//÷èñòèì
p->clear(p);
//èíèöèàëèçèðóåì ïåðåìåííûå
p->INTERNAL_last_log_num = 0;
p->INTERNAL_last_log_index = 0;
return;
}
//èùåì ïîñëåäíþþ çàïèñü
if (last_log_num < tmp.ev_num)
{
last_log_num = tmp.ev_num;
last_log_index = i;
}
}
p->INTERNAL_last_log_num = last_log_num;
p->INTERNAL_last_log_index = last_log_index;
}
//ôóíêöèß î÷èñòêè áóôåðà â ÝíÎÇÓ
void Logger_Clear(TLogger* p)
{
Uint16 zero = 0;
UserMem.MemStartAddr = p->SPI_start_addr;
UserMem.MCUStartAddr = (Uint16*)(&zero);
UserMem.data_length = 1;
for (int i=0;i<(p->SPI_buf_size * (LOG_LENGTH));i++)
{
UserMem.write(&UserMem);
UserMem.MemStartAddr++;
}
p->INTERNAL_last_log_index = 0;
p->INTERNAL_last_log_num = 0;
}
//áûñòðàß ôóíêöèß çàïèñè ñîáûòèß â FIFO
Uint16 Logger_Event_Write(TLogger* p,Uint16 code)
{
TEvent event;
//ôîðìèðóåì äàííûå
__disable_irq();
event.ev_time = *(p->time_ptr);
event.ev_code = code;
event.ev_num = ++p->INTERNAL_last_log_num;
p->INTERNAL_last_log_code = code;
__enable_irq();
//ïèøåì â FIFO
return p->FIFO.write((struct SEventFIFO*)&(p->FIFO),(TEvent*)&event);
}
//ïðî÷èòàòü àâàðèþ èç áàíêà, ñëîæèòü äàííûå â TEvent* event
void Logger_Event_Read(TLogger* p,Uint16 shift_index,TEvent* event)
{
Uint16 correction = 0;
//ïðîâåðßåì ïðàâèëüíîñòü çàïðîñà
if (shift_index > (p->SPI_buf_size - 1)) return;
//ââîä êîððåêöèè äëß îðãàíèçàöèè êîëüöà
if (((int16)p->INTERNAL_last_log_index - (int16)shift_index) < 0) correction = p->SPI_buf_size;
//÷òåíèå íîìåðà
UserMem.MemStartAddr = p->SPI_start_addr + ((p->INTERNAL_last_log_index - shift_index + correction)*(LOG_LENGTH));
UserMem.MCUStartAddr = (Uint16*)(&(event->ev_num));
UserMem.data_length = LOG_NUM_LENGTH;
UserMem.read(&UserMem);
//÷òåíèå âðåìåíè
UserMem.MemStartAddr += UserMem.data_length;
UserMem.MCUStartAddr = (Uint16*)(&(event->ev_time));
UserMem.data_length = LOG_TIME_LENGTH;
UserMem.read(&UserMem);
//÷òåíèå êîäà
UserMem.MemStartAddr += UserMem.data_length;
UserMem.MCUStartAddr = (Uint16*)(&(event->ev_code));
UserMem.data_length = LOG_CODE_LENGTH;
UserMem.read(&UserMem);
}
//ôóíêöèß îáðàáîòêè FIFO è çàïèñè àâàðèé â ÝíÎÇÓ. Åñëè â FIFO ÷òî-òî êëàëè - çàïèøåì âî ôëåøêó.
//Åñëè FIFO çàíÿòà èëè ïóñòàÿ - îòäûõàåì.
void Logger_Background_Calc(TLogger* p)
{
Uint16 ret;
TEvent event;
//÷òîáû íå ñèëüíî çàòîðìàæèâàòü ôîíîâûé öèêë áóäåì çàïèñûâàòü ïî 1 çàïèñè çà ðàç
ret = p->FIFO.read((struct SEventFIFO*)&(p->FIFO),(TEvent*)&event);
if (ret == EVENT_FIFO_SUCCESSFUL)
{
//ïèøåì â ÝíÎÇÓ
if (p->INTERNAL_last_log_index >= (p->SPI_buf_size - 1)) p->INTERNAL_last_log_index = 0;
else p->INTERNAL_last_log_index++;
//çàïèñü íîìåðà
UserMem.MemStartAddr = p->SPI_start_addr + (p->INTERNAL_last_log_index)*(LOG_LENGTH);
UserMem.MCUStartAddr = (Uint16*)(&(event.ev_num));
UserMem.data_length = LOG_NUM_LENGTH;
UserMem.write(&UserMem);
//çàïèñü âðåìåíè
UserMem.MemStartAddr += UserMem.data_length;
UserMem.MCUStartAddr = (Uint16*)(&(event.ev_time));
UserMem.data_length = LOG_TIME_LENGTH;
UserMem.write(&UserMem);
//çàïèñü êîäà
UserMem.MemStartAddr += UserMem.data_length;
UserMem.MCUStartAddr = (Uint16*)(&(event.ev_code));
UserMem.data_length = LOG_CODE_LENGTH;
UserMem.write(&UserMem);
}
}
//ôóíêöèÿ ïðîâåðêè è çàïèñè âèñÿùèõ â äàííûé ìîìåíò ôëàãîâ àâàðèé
//Ïîñëåäîâàòåëüíî ñìîòðèòñÿ êàæäûé áèò ñëîâ àâàðèé è, åñëè îí âçâåäåí, íî åùå íå çàïèñàí, ïðîèçâîäèòñÿ çàïèñü.
void Logger_ms_Calc(TLogger* p){
}
#ifdef __cplusplus
} // Extern "C"
#endif
/*@}*/

53
Vsrc/V_hzprof.c Normal file
View File

@ -0,0 +1,53 @@
/*!
Copyright 2017 Texas Instruments, ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file V_hzprof.c
\brief Êðèâàÿ U(f) (ñì. TVhzProf)
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 2.0 25/03/2016
\addtogroup vhzprof
*/
#include "V_IQmath.h" /* Include header for IQmath library */
#include "V_hzprof.h"
#include <stdlib.h>
//! Ôóíêöèÿ ðàñ÷åòà êðèâîé U(f)
//!Íà âõîä ïðèíèìàåò ÷àñòîòó freq, è èñõîäÿ èç íàñòðîåííûõ çíà÷åíèé
//!ìèíèìàëüíîãî íàïðÿæåíèÿ íà ìèíèìàëüíîé ÷àñòîòå è ìàêñèìàëüíîãî
//!íàïðÿæåíèÿ íà ìàêñèìàëüíîé ÷àñòîòå, âûäàåò vout - íàïðÿæåíèå
//!äëÿ ÷àñòîòû freq. Äðóãèìè ñëîâàìè, ìîäóëü ïðåäñòàâëÿåò ñîáîé
//!ëèíåéíûé èíòåðïîëÿòîð ïî äâóì ðåïåðíûì òî÷êàì ñ îãðàíè÷åíèåì ìàêñèìóìà è
//!ìèíèìóìà.
//! \memberof TVhzProf
void vhz_prof_calc(TVhzProf *v) {
_iq vf_slope, freq_abs;
freq_abs = labs(v->freq);
if (freq_abs <= v->FL)
v->vout = v->Vmin; /* Profile #1 */
else if ((freq_abs > v->FL) & (freq_abs <= v->FH)) {
vf_slope = _IQdiv((v->Vmax - v->Vmin), (v->FH - v->FL)); /* Computing v/f slope */
v->vout = v->Vmin + _IQmpy(vf_slope, (freq_abs - v->FL)); /* Profile #2 */
} else if ((freq_abs > v->FH) & (freq_abs < v->Fmax))
v->vout = v->Vmax; /* Profile #3 */
}
/*@}*/

78
Vsrc/V_led.c Normal file
View File

@ -0,0 +1,78 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file Vled.c
\brief Óïðàâëåíèå ñâåòîäèîäàìè
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 2.0 25/03/2016
\addtogroup led
*/
#include "DSP.h"
#include "main.h"
void LED_init(Tled *p) {
}
void LED_toggle(Tled *p, Uint16 led) {
}
void LED_on(Tled *p, Uint16 led) {
}
void LED_off(Tled *p, Uint16 led) {
}
void LED_clearAll(Tled *p) {
}
void LED_mode0(Tled *p) {
}
void LED_mode1(Tled *p) {
}
void LED_mode2(Tled *p) {
}
void LED_mode3(Tled *p) {
}
void LED_msCalc(Tled *p) {
}

111
Vsrc/V_pid_reg3.c Normal file
View File

@ -0,0 +1,111 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file V_pid_reg3.c
\brief ÏÈÄ-ðåãóëÿòîð (ñì. TPidReg3)
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 2.0 25/03/2016
\addtogroup V_pid_reg3
@{*/
#include "V_IQmath.h" // Include header for IQmath library
#include "V_pid_reg3.h"
#include "stdlib.h"
#include "main.h"
//! Ôóíêöèÿ ðàñ÷åòà ÏÈÄ ðåãóëÿòîðà
//! Âîîáùå ýòî ÷óòü äîðàáîòàííàÿ âåðñèÿ òåêñàñîâñêîãî ðåãóëÿòîðà
//! Äîêóìåíòàöèþ ýòîé ìàãèè ëó÷øå âñåãî ïîñìîòðåòü, çàãóãëèâ pid_reg3.pdf
//! Íà âõîäå pid_ref_reg3 - çàäàíèå, pid_fdb_reg3 - îáðàòíàÿ ñâÿçü
//! Íà âûõîäå pid_out_reg3.
//! \memberof TPidReg3
void pid_reg3_calc(TPidReg3 *v) {
v->e_reg3 = v->pid_ref_reg3 - v->pid_fdb_reg3;//îøèáêà - çàäàíèå ìèíóñ îáðàòíàÿ ñâÿçü
v->e_reg3Dz=v->e_reg3;//îøèáêà ïîñëå êîððåêöèè áëîêà ìåðòâîé çîíû
if (v->DeadZone!=0){//åñëè åñòü óñòàâêà çîíû íå÷óâñòâèòåëüíîñòè
if (v->e_reg3Dz>0){//îøèáêà â ïëþñ
v->e_reg3Dz=v->e_reg3Dz-v->DeadZone;//âû÷èòàåì ìåðòâóþ çîíó
if (v->e_reg3Dz<0)//íî òàê, ÷òîáû îøèáêà íå ñòàëà îòðèöàòåëüíîé
v->e_reg3Dz=0;
}
if (v->e_reg3Dz<0){
v->e_reg3Dz=v->e_reg3Dz+v->DeadZone;
if (v->e_reg3Dz>0)
v->e_reg3Dz=0;
}
}
v->up_reg3 = _IQmpy(v->Kp_reg3, v->e_reg3Dz);
v->uprsat_reg3 = v->up_reg3 + v->ui_reg3 + v->ud_reg3;
if (v->uprsat_reg3 > v->pid_out_max)
v->pid_out_reg3 = v->pid_out_max;
else if (v->uprsat_reg3 < v->pid_out_min)
v->pid_out_reg3 = v->pid_out_min;
else
v->pid_out_reg3 = v->uprsat_reg3;
v->saterr_reg3 = v->pid_out_reg3 - v->uprsat_reg3 + v->saterr_reg3Add;
//èñïîëüçîâàòü ëè ôèëüòð äëÿ äèôô. ÷àñòè. Åñëè êôèëüòðà íîëü, òî íåò.
if (v->Kf_d == 0){
v->e_reg3_filterOut = v->e_reg3;//âûõîä ôèëüòðà
}
else{//èíà÷å ñ÷èòàåì ôèëüòð
v->e_reg3_filterOut = v->e_reg3_filterOut
+ _IQmpy(v->Kf_d, (v->e_reg3 - v->e_reg3_filterOut));
}
if ((v->DiffCounter++ + 1) >= v->DiffDelim) {//êàæäûå ñêîëüêî âûçîâîâ ñ÷èòàòü äèôô. ÷àñòü
if (v->KdFilterInitFlag==1){//ýòî ïåðâûé òàêò ðàñ÷åòà ðåãóëÿòîðà
v->e_reg3_filterOut = v->e_reg3;//âûõîä ôèëüòðà îøèáêè èíèöèàëèçèðóåì îøèáêîé
v->up1_reg3 = v->e_reg3_filterOut;//ïðîèçâîäíàÿ íîëü
v->KdFilterInitFlag=0;//èíèöèàëèçàöèÿ çàâåðøåíà
}
v->ud_reg3 = _IQmpy(v->Kd_reg3, (v->e_reg3_filterOut - v->up1_reg3)<<6);//äèôôåðåíöèàëüíàÿ ÷àñòü
v->up1_reg3 = v->e_reg3_filterOut;
v->DiffCounter = 0;
}
if (v->Ki_reg3 != 0)//åñòü èíòåãðàëüíàÿ ñîñòàâëÿþùàÿ
v->ui_reg3 = v->ui_reg3
+ _IQmpy(v->Ki_reg3,
v->up_reg3) + _IQmpy(v->Kc_reg3,v->saterr_reg3);
else
v->ui_reg3 = 0;
if (v->Kc_reg3 == 0) {
if (v->ui_reg3 > v->pid_out_max)
v->ui_reg3 = v->pid_out_max;
else if (v->ui_reg3 < v->pid_out_min)
v->ui_reg3 = v->pid_out_min;
}
}
//! \memberof TPidReg3
void pid_reg3_reset(TPidReg3 *v) {
v->pid_fdb_reg3=0;
v->pid_ref_reg3=0;
v->ui_reg3=0;
v->KdFilterInitFlag=1;
}
/*@}*/

109
Vsrc/V_pid_reg3_pos.c Normal file
View File

@ -0,0 +1,109 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file V_pid_reg3.c
\brief ÏÈÄ-ðåãóëÿòîð (ñì. TPidReg3)
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 2.0 25/03/2016
\addtogroup V_pid_reg3
@{*/
#include "V_IQmath.h" // Include header for IQmath library
#include "V_pid_reg3_pos.h"
#include "stdlib.h"
#include "main.h"
//! Ôóíêöèÿ ðàñ÷åòà ÏÈÄ ðåãóëÿòîðà
//! Âîîáùå ýòî ÷óòü äîðàáîòàííàÿ âåðñèÿ òåêñàñîâñêîãî ðåãóëÿòîðà
//! Äîêóìåíòàöèþ ýòîé ìàãèè ëó÷øå âñåãî ïîñìîòðåòü, çàãóãëèâ pid_reg3.pdf
//! Íà âõîäå pid_ref_reg3 - çàäàíèå, pid_fdb_reg3 - îáðàòíàÿ ñâÿçü
//! Íà âûõîäå pid_out_reg3.
//! \memberof TPidReg3
void pid_reg3_calc_pos(TPidReg3_pos *v) {
v->e_reg3 = v->pid_ref_reg3 - v->pid_fdb_reg3;//îøèáêà - çàäàíèå ìèíóñ îáðàòíàÿ ñâÿçü
v->e_reg3Dz=v->e_reg3;//îøèáêà ïîñëå êîððåêöèè áëîêà ìåðòâîé çîíû
if (v->DeadZone!=0){//åñëè åñòü óñòàâêà çîíû íå÷óâñòâèòåëüíîñòè
if (v->e_reg3Dz>0){//îøèáêà â ïëþñ
v->e_reg3Dz=v->e_reg3Dz-v->DeadZone;//âû÷èòàåì ìåðòâóþ çîíó
if (v->e_reg3Dz<0)//íî òàê, ÷òîáû îøèáêà íå ñòàëà îòðèöàòåëüíîé
v->e_reg3Dz=0;
}
if (v->e_reg3Dz<0){
v->e_reg3Dz=v->e_reg3Dz+v->DeadZone;
if (v->e_reg3Dz>0)
v->e_reg3Dz=0;
}
}
v->up_reg3 = _IQmpy(v->Kp_reg3, v->e_reg3Dz);
v->uprsat_reg3 = v->up_reg3 + v->ui_reg3 + v->ud_reg3;
if (v->uprsat_reg3 > v->pid_out_max)
v->pid_out_reg3 = v->pid_out_max;
else if (v->uprsat_reg3 < v->pid_out_min)
v->pid_out_reg3 = v->pid_out_min;
else
v->pid_out_reg3 = v->uprsat_reg3;
v->saterr_reg3 = v->pid_out_reg3 - v->uprsat_reg3 + v->saterr_reg3Add;
//èñïîëüçîâàòü ëè ôèëüòð äëÿ äèôô. ÷àñòè. Åñëè êôèëüòðà íîëü, òî íåò.
if (v->Kf_d == 0){
v->e_reg3_filterOut = v->e_reg3;//âûõîä ôèëüòðà
}
else{//èíà÷å ñ÷èòàåì ôèëüòð
v->e_reg3_filterOut = posspeedEqep.speed_elec;
}
if ((v->DiffCounter++ + 1) >= v->DiffDelim) {//êàæäûå ñêîëüêî âûçîâîâ ñ÷èòàòü äèôô. ÷àñòü
if (v->KdFilterInitFlag==1){//ýòî ïåðâûé òàêò ðàñ÷åòà ðåãóëÿòîðà
v->e_reg3_filterOut = posspeedEqep.speed_elec;//âûõîä ôèëüòðà îøèáêè èíèöèàëèçèðóåì îøèáêîé
v->KdFilterInitFlag=0;//èíèöèàëèçàöèÿ çàâåðøåíà
}
//v->ud_reg3 = _IQmpy(v->Kd_reg3, (v->e_reg3_filterOut - v->up1_reg3)<<6);//äèôôåðåíöèàëüíàÿ ÷àñòü
v->ud_reg3 = _IQmpy(v->Kd_reg3,-posspeedEqep.speed_filter.output);
v->DiffCounter = 0;
}
if (v->Ki_reg3 != 0)//åñòü èíòåãðàëüíàÿ ñîñòàâëÿþùàÿ
v->ui_reg3 = v->ui_reg3
+ _IQmpy(v->Ki_reg3,
v->up_reg3) + _IQmpy(v->Kc_reg3,v->saterr_reg3);
else
v->ui_reg3 = 0;
if (v->Kc_reg3 == 0) {
if (v->ui_reg3 > v->pid_out_max)
v->ui_reg3 = v->pid_out_max;
else if (v->ui_reg3 < v->pid_out_min)
v->ui_reg3 = v->pid_out_min;
}
}
//! \memberof TPidReg3
void pid_reg3_reset_pos(TPidReg3_pos *v) {
v->pid_fdb_reg3=0;
v->pid_ref_reg3=0;
v->ui_reg3=0;
v->KdFilterInitFlag=1;
}
/*@}*/

66
Vsrc/V_rmp_ctrl.c Normal file
View File

@ -0,0 +1,66 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file v_rmp_ctrl.c
\brief Çàäàò÷èê èíòåíñèâíîñòè (ñì. TRMPCtrl)
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 2.0 25/03/2016
*/
/** \addtogroup V_rmp_ctrl */
/*@{*/
#ifdef __cplusplus
extern "C" {
#endif
#include "v_rmp_ctrl.h"
#include "V_IQmath.h"
#include "stdlib.h"
#ifdef __cplusplus
}
#endif
//! Ôóíêöèÿ ðàñ÷åòà çàäàò÷èêà èíòåíñèâíîñòè
//!Èçìåíÿåò output ñ çàäàííûì òåìïîì T,
//!ïîêà output íå äîñòèãíåò input.
//! \memberof TRMPCtrl
void V_RMP_CTRL_calc(TRMPCtrl *p) {
//âûõîä ìåíüøå âõîäà?
if (p->output < p->input)
p->output += p->step;//óâåë÷è÷èâàåì ñ çàäàííûì òåìïîì âûõîä
if (p->output > p->input)
p->output -= p->step;
if ((labs(p->output - p->input) <= p->step) || (p->T==0)) {//âîøëè â çàäàíèå ñ òî÷íîñòü äî øàãà èëè ÇÈ âîîáùå îòêëþ÷åí
p->output = p->input;//âûõîä ðàâåí âõîäó
}
}
//! Âñïîìîãàòåëüíàÿ ôóíêöèÿ çàäàò÷èêà èíòåíñèâíîñòè
//!Ïåðåñ÷èòûâàåò òåìï ðàçãîíà T â øàã step c ó÷åòîì ÷àñòîòû
//!âûçîâà îñíîâíîé ôóíêöèè Ts (äèñêðåòèçàöèÿ, îáû÷íî 10êÃö).
//! \memberof TRMPCtrl
void V_RMP_CTRL_slow_calc(TRMPCtrl *p) {
p->step = _IQdiv(p->Ts, p->T);//øàã èíòåãðàòîðà ÇÈ
}
/*@}*/

47
Vsrc/V_rotor_observer.c Normal file
View File

@ -0,0 +1,47 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file v_rotor_observer.c
\brief Íàáëþäàòåëü ðîòîðà ÀÄ (ñì. TRotorObserver)
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 1.0 28/06/2016
*/
/** \addtogroup TRotorObserver */
/*@{*/
#include "main.h"
#ifdef __cplusplus
#pragma CODE_SECTION("secureRamFuncs")
#else
#pragma CODE_SECTION(RotorObserver_calc,"secureRamFuncs");
#endif
void RotorObserver_calc(TRotorObserver *p) {
//èíåðöèîííîå çâåíî ñ ïàðàìåòðàìè ðîòîðà
p->psi_d = p->psi_d + _IQmpy(p->Ks,p->id - p->psi_d);
p->psi_q = p->psi_q + _IQmpy(p->Ks,p->iq - p->psi_q);
p->theta_psi_elec = _IQatan2PU(p->psi_q ,p->psi_d);
}
void RotorObserver_slow_calc(TRotorObserver *p) {
p->Ks=_IQdiv(FAST_CALC_TS,p->Tr);
}
/*@}*/

69
Vsrc/V_watchdog.c Normal file
View File

@ -0,0 +1,69 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file V_PWM_Module.c
\brief Ìîäóëü ðåàëèçàöèè âåêòîðíîé ØÈÌ (ñì. TPWM_Module)
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 2.0 25/03/2016
\addtogroup Twdog
@{*/
#include "main.h"
Twdog Watchdog = WDOG_DEFAULTS;
// Ðàçðåøåíèå âî÷äîãà
void WDog_Enable (){
RCU->WDTCFG_bit.CLKSEL = 2; // PLL
RCU->WDTCFG_bit.DIVN = 1; // PLL / 4
RCU->WDTCFG_bit.DIVEN = 1;
RCU->WDTCFG_bit.RSTDIS = 1;
RCU->WDTCFG_bit.CLKEN = 1;
WDT->LOCK = 0x1ACCE551;
WDT->LOAD_bit.VAL = 100000;
WDT->CTRL_bit.INTEN = 1;
WDT->CTRL_bit.RESEN = 1;
WDT->LOCK = 0x1ACCE551;
}
// Îòêëþ÷åíèå âî÷äîãà
void WDog_Disable (){
WDT->LOCK = 0x1ACCE551;
WDT->CTRL_bit.INTEN = 0;
WDT->CTRL_bit.RESEN = 0;
WDT->LOCK = 0x1ACCE551;
}
// Ñáðîñ òàéìåðà âî÷äîãà
void WDog_Feed (){
WDT->LOCK = 0x1ACCE551;
WDT->LOAD_bit.VAL = 2500 * 3; // 3 * 10 êÃö ïðåðûâàíèÿ
WDT->LOCK = 0x1ACCE551;
}
// Ïåðåçàãðóçêà ïðîöà âî÷äîãîì
void WDog_ResetSystem (){
DINT;
WDog_Enable();
WDT->LOCK = 0x1ACCE551;
WDT->LOAD_bit.VAL = 2; // 2 òàêòà
WDT->LOCK = 0x1ACCE551;
while(1);
}
/*@}*/

35
Vsrc/clarke.c Normal file
View File

@ -0,0 +1,35 @@
/*!
Copyright 2017 Texas Instruments, ÀÎ "ÍÈÈÝÒ" , ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file clarke.c
\brief Ìîäóëü ôàçíûõ ïðåîáðàçîâàíèé (ñì. TClarke)
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 2.0 25/03/2016
\addtogroup clarke
@{
*/
#include "V_IQmath.h" /* Include header for IQmath library */
#include "clarke.h"
//! Ôóíêöèÿ ôàçíûõ ïðåîáðàçîâàíèé
//! \memberof TClarke
void clarke_calc(TClarke *v) {
v->ds = v->as;
v->qs = _IQmpy((v->as + _IQmpy(_IQ(2),v->bs)), _IQ(0.57735026918963));
}
/*@}*/

3939
Vsrc/cood1.c Normal file

File diff suppressed because it is too large Load Diff

43
Vsrc/filter.c Normal file
View File

@ -0,0 +1,43 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file filter.c
\brief Èíåðöèîííîå çâåíî â IQ ìàòåìàòèêå (ñì. TFilter)
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 2.0 25/03/2016
*/
/** \addtogroup filter */
/*@{*/
#include "DSP.h"
#include "filter.h"
#include "V_IQmath.h"
//! Èíåðöèîííîå çâåíî 1/(Tp+1)
//! Èñïîëüçóåòñÿ êàê ôèëüòð ïåðâîãî ïîðÿäêà
//!Äîëæíà âûçûâàòüñÿ ñ çàäàííîé äèñêðåòèçàöèåé. Ïðåäâàðèòåëüíî íåîáõîäèìî îïðåäåëèòü
//! ïåðåìåííóþ, ñâÿçàííóþ ñ ïîñòîÿííîé âðåìåíè:
//! T=Ts/Tfiltra ãäå - Tfiltra ïîñòîÿííàÿ âðåìåíè ôèëüòðà, à
//! Ts - âðåìÿ äèñêðåòèçàöèè âûçîâà ôóíöèè
//! \memberof TFilter
void TFilter_Calc(TFilter *p) {
p->output = _IQmpy(p->T,(p->input-p->output)) + p->output;
}
/*@}*/

45
Vsrc/ipark.c Normal file
View File

@ -0,0 +1,45 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file ipark.c
\brief Ìîäóëü èíâåðñíûõ êîîðäèíàòíûõ ïðåîáðàçîâàíèé êîîðäèíàò (ñì. TIPark)
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 2.0 25/03/2016
\addtogroup IPark
@{
*/
#include "V_IQmath.h" /* Include header for IQmath library */
#include "ipark.h"
//! Ôóíêöèÿ èíâåðñíûõ ïðåîáðàçîâàíèé êîîðäèíàò
//!Íà âõîäå óãîë ang, âåêòîð (de,qe).
//!Íà âûõîäå ïîâåðíóòûé íà çàäàííûé óãîë âåêòîð (ds,qs)
//! \memberof TIPark
void ipark_calc(TIPark *v) {
_iq cos_ang, sin_ang;
sin_ang = _IQsinPU(v->ang);
cos_ang = _IQcosPU(v->ang);
v->ds = _IQmpy(v->de,cos_ang) - _IQmpy(v->qe, sin_ang);
v->qs = _IQmpy(v->qe,cos_ang) + _IQmpy(v->de, sin_ang);
}
/*@}*/

322
Vsrc/main.c Normal file
View File

@ -0,0 +1,322 @@
/*!
Copyright 2017 АО "НИИЭТ" и ООО "НПФ ВЕКТОР"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file main.c
\brief Главный файл проекта. Содержит main(), а также обработчики прерываний.
\author ООО "НПФ Вектор". http://motorcontrol.ru
\version v 2.0 25/03/2016
*/
/** \addtogroup MAIN */
/*@{*/
#include "main.h"
#include <string.h> //для memcpy
TClarke clarke = CLARKE_DEFAULTS; //!<Фазные преобразования
TPark park = PARK_DEFAULTS; //!<Координатные преобразования
TIPark ipark = IPARK_DEFAULTS; //!<Обратные координатные преобразования
TPidReg3 pid_id = PIDREG3_DEFAULTS; //!<Рег. тока по оси d
TPidReg3 pid_iq = PIDREG3_DEFAULTS; //!<Рег. тока по оси q
TPidReg3 pid_ia = PIDREG3_DEFAULTS; //!<Рег. тока якоря ДПТ
TPidReg3 pid_spd = PIDREG3_DEFAULTS; //!<Рег. скорости
TPidReg3_pos pid_pos = PIDREG3_DEFAULTS_POS; //!<Рег. положения
TVhzProf vhz = VHZPROF_DEFAULTS; //!< закон U/f=const
TSM_Sys sm_sys = SM_Sys_DEFAULTS; //!< Главная оболочка для вызова всех модулей
Uint16 disp_group_number = 0; //!< Необходимо для драйвера CANOpen и Unicon
TDataLog dlog = DATALOG_DEFAULTS; //!< Модуль осциллографирования переменных CANOpen
TSM_Protect sm_prot = SM_PROTECT_DEFAULTS; //!< Модуль защит
TBitsToEnumNums pult_faults_lister = BITS_TO_ENUM_NUMS_DEFAULTS; //!<Листалка аварий для Unicon
TSM_Ctrl sm_ctrl = SM_CTRL_DEFAULTS; //!< Главный дискретный автомат, реализует структуру управления
TSM_CmdLogic sm_cmd_logic = SM_CMD_LOGIC_DEFAULTS; //!< Обработка пользовательских команд управления
TSM_Net sm_net = SM_NET_DEFAULTS; //!< Оболочка для вызова сетевых драйверов
TRMPCtrl rmp = V_RMP_CTRL_DEFAULTS; //!< Задатчик интенсивности
TAdcDrv adc = ADC_DRV_DEFAULTS; //!< Модуль АЦП
TPWM_Module pwm = PWM_Module_DEFAULTS; //!< Модуль ШИМ
TDPReCAP DPReCAP = DPRECAP_DEFAULTS; //!< Модуль ДПР на элементах Холла
TposspeedEqep posspeedEqep = POSSPEED_DEFAULTS; //!< Модуль ДПР типа энкодер
TCurPar cur_par = TCUR_PAR_DEFAULTS; //!< Модуль расчета и хранения текущих показателей привода - мощность, скорость
TUserMemory UserMem = USERMEMORY_DEFAULTS; //!< Модуль работы с энергонезависимой памятью.
Tled leds = LED_DEFAULTS; //!< модуль для красивого мигания светодиодами
//TCanBTInterface Can2BTInterface = T_CANBT_INTERFACE_DEFAULTS;//!<Пакетная передача CANopen
TRTCClock RTCclock = RTC_CLOCK_DEFAULTS; //!< Модуль работы с часами реальноговремени. "spi" - по историческим причинам совместимости
TAutoOffset AutoOffset = AUTO_OFFSET_DEFAULTS; //!<Автоматическая подстройка смещения токов АЦП
TSSI_Encoder SSI_Encoder = SSI_ENCODER_DEFAULTS; //!<Драйвер обработки датчика положения с SSI интерфейсом
//TMotorModel model = MOTOR_MODEL_DEFAULTS; //!< Модели электродвигателей для отладки "на столе" в режиме симулятора
TRotorObserver RotorObserver = ROTOR_OBSERVER_DEFAULTS; //!<Датчиковый наблюдатель потокосцепления ротора асинхронного двигателя
TCANtoRS CANtoRS = CAN_TO_RS_DEFAULTS; //!<Модуль для работы с драйвером CANopen через UART (RS). Посылки CAN запаковываются в UART
//TModBus ModBus = MODBUS_DEFAULTS; //!<Драйвер для работы по протоколу MODBUS
//TMBVarsConv MBVarsConv = MBVARSCONV_DEFAULTS;//!< Модуль преобразования данных из формата 16 разрядов Modbus в формат системы управления (IQ 24)
TDrvInterface drv_interface = DRV_INTERFACE_DEFAULTS; //!<Интерфейс длЯ работы с банками аварий, событий и т.п.
TLogger FaultLog = LOGGER_DEFAULTS; //!<Протоколирование аварий
TGlobalTime global_time = GLOBAL_TIME_DEFAULTS; //!<Работа с часами
TRefs refs; //!< Структура с заданиями (токи, скорости)
TCmd cmd = { 0 }; //!< Структура с командами управления
TDrvStatus drv_status = { 0 }; //!< Текущий статус привода
TDrvParams drv_params; //!< Параметры двигателя
TSysSwitches sw; //!< Различные дискретные настройки системы управления
Uint32 VendorToken=0x11111111;//!< Уникальный ключ производителя, нужный для программы UniCON и COODEdit для различных наборов текстов разных произхводителей
int drv_status_code; //!<Статус системы управления в виде константы (ГОТОВ, РАБОТА и т.п.)
//Переменные для отладки - выведены в словарь CANOpen,
//В них можно присваивать любую другую переменную и наблюдать её
//в UniCon, а также использовать их напрямую в ПО для отладки и менять на ходу.
volatile long Debug1 = 0;
volatile long Debug2 = 0;
volatile Uint16 Debug3 = 0;
volatile Uint16 Debug4 = 0;
volatile long DebugW1 = 0;
volatile long DebugW2 = 0;
volatile long DebugW3 = 0;
volatile long DebugW4 = 0;
volatile float DebugF1 = 0;
volatile float DebugF2 = 0;
volatile float DebugF3 = 0;
volatile float DebugF4 = 0;
//Счетчики прерываний модуля захвата
Uint16 CounterCAP_isr = 0;
Uint16 cap0_counter = 0;
Uint16 cap1_counter = 0;
Uint16 cap2_counter = 0;
Uint16 LoopCounter = 0; //!< Счетчик итераций фонового цикла
//!С этой функции начинается запуск программы
//! \memberof MAIN_C
int main(void) {
co1_vars.co_productCode = 51;
co1_vars.co_revisionNumber = 1;
/* Настройка тактирования, включение периферии */
SystemInit(); // Настройка клоков
SystemCoreClockUpdate(); // Апдейти системных переменных настроенными клоками (хз зачем, необязательно)
// Копирование некоторых функций и всех прерываний в RAM
#if defined (__GNUC__)
memcpy(&__isr_vector_ram_start, &__isr_vector_flash_start,
((Uint32) (&__isr_vector_ram_end)
- (Uint32) (&__isr_vector_ram_start)));
#elif defined (__CMCPPARM__)
// Для CodeMaster непонятно, как разместить таблицу прерываний во флеше, а обращатся к ней в раме,
// так что пока так.
#endif
pwm.Off(&pwm); //выключить ШИМ (на всякий случай)
DINT;
//Инициализация, собственно, всего.
sm_sys.init(&sm_sys);
EINT;//разрешение прерываний
//тип и версия устройства для драйвера CANOpen
while (1) { //Фоновый цикл
LoopCounter++;
sm_sys.slow_calc(&sm_sys); //Фоновый расчет
}
}
unsigned long CpuTimerIsr1 = 0;
Uint16 TIsr1 = 0;
Uint16 msCounter = 0;
//! Прервыние, вызываемое по таймеру с частотой 1кГц
//! \memberof MAIN_C
void TMR1_IRQHandler(void) {
CpuTimerIsr1 = TMR2->VALUE; //Засекается время выполнения функции
sm_sys.ms_calc(&sm_sys); //миллисекундный расчет всего
msCounter++;
TIsr1 = (CpuTimerIsr1 - TMR2->VALUE) & 0xFFFFFF; //время выполнения функции
if (TIsr1 > 97000) {
sm_prot.bit_fault1 |= F_PROGRAM_1K; //если расчет слишком долгий, ошибка
}
TMR1->INTSTATUS_bit.INT = 1; //сброс прерывания
}
Uint16 FastCounter = 0;
unsigned long CpuTimerIsr10 = 0;
Uint16 TIsr10 = 0;
//! Прервыние, вызываемое по таймеру с частотой 10кГц
//! \memberof MAIN_C
void TMR0_IRQHandler(void) {
CpuTimerIsr10 = TMR2->VALUE; //Засекается время выполнения функции
sm_sys.fast_calc(&sm_sys); //расчет 10кГц всего
FastCounter++;
TIsr10 = (CpuTimerIsr10 - TMR2->VALUE) & 0xFFFFFF; //время выполнения функции
if (TIsr10 > 9700) {
sm_prot.bit_fault1 |= F_PROGRAM_10K; //если расчет слишком долгий, ошибка
}
TMR0->INTSTATUS_bit.INT = 1; //сброс прерывания
}
Uint16 ePWM0_TZ_isr_counter = 0;
//!Прерывание, возникающее при аппаратной аварии
//! \memberof MAIN_C
#if defined (__GNUC__)
void PWM0_TZ_IRQHandler(void)
#elif defined (__CMCPPARM__)
void PWM0_TZ_IRQHandler(void)
#endif
{
//Так как аппаратная авария возникает при включении ШИМ
//и удерживается пока заряжаются будстрепные конденсаторы,
//в прерывании на нее не реагируем
//Хотя в "настоящем" инверторе на высокое напряжение это, конечно, надо делать
//Здесь микросхема драйверов защитит всё сама, такого выхода у неё нет
ePWM0_TZ_isr_counter++;
/*
pwm12.Off(&pwm12);
if (sm_ctrl.state!=CTRL_STOP)
{
sm_prot.bit_fault1|= F_PDPINT;
}
sm_ctrl.state=CTRL_STOP;
//сбрасываем флаги прерываний по этой ножке
*/
}
//!Прерывание, возникающее по событиям захвата модуля CAP0
//! \memberof MAIN_C
#if defined (__GNUC__)
void ECAP0_IRQHandler(void)
#elif defined (__CMCPPARM__)
void CAP0_IRQHandler(void)
#endif
{
//Подтверждаем это прерывание для NVIC - иначе при выходе из функции оно возникнет опять
ECAP0->PEINT = 1;
if (DPReCAP.CAPCalcEna1 == 0) { //если функция вызвалась повторно
DPReCAP.CAP_WrongEdgeCnt = (++DPReCAP.CAP_WrongEdgeCnt) & 0xFF;
DPReCAP.CAP_WrongEdgeCnt1++;
return;
}
DPReCAP.CAPCalcEna1 = 0;//расчет будет разрешен, когда тикнет прерывание 10кГц. Чаще считать нет смысла, это помехи
CounterCAP_isr++;//общий счётчик всех прерываний модуля захвата
CounterCAP_isr = CounterCAP_isr & 0xF;
cap0_counter++;//счётчик прерываний именно этого канала
//исходя из состояния ног трех датчиков Холла высчитывает текущий угол с точностью 60 градусов.
//выходом функции является DPReCAP.Angle6 - угол с точностью 60 градусов.
DPReCAP.Angle6Calc(&DPReCAP);
//обработчик модуля захвата канала1 (0, если считать с нуля, но не переименовывать же какждый раз функции, в зависимости от версии заголовочных файлов...).
//Засекает время между этим импульсом и предыдущими для расчета интерполятора угла и частоты вращения (скорости)
DPReCAP.CAP1Calc(&DPReCAP);
//Подтверждение прерываний
ECAP0->ECCLR_bit.CEVT0 = 1;
ECAP0->ECCLR_bit.CEVT1 = 1;
ECAP0->ECCLR_bit.INT = 1;
}
//!Прерывание, возникающее по событиям захвата модуля CAP1
//! \memberof MAIN_C
#if defined (__GNUC__)
void ECAP1_IRQHandler(void)
#elif defined (__CMCPPARM__)
void CAP1_IRQHandler(void)
#endif
{
//Подтверждаем это прерывание для NVIC - иначе при выходе из функции оно возникнет опять
ECAP1->PEINT = 1;
if (DPReCAP.CAPCalcEna2 == 0) { //если функция вызвалась повторно
DPReCAP.CAP_WrongEdgeCnt = (++DPReCAP.CAP_WrongEdgeCnt) & 0xFF;
DPReCAP.CAP_WrongEdgeCnt2++;
return;
}
DPReCAP.CAPCalcEna2 = 0;
CounterCAP_isr++;
CounterCAP_isr = CounterCAP_isr & 0xF;
cap1_counter++;
DPReCAP.Angle6Calc(&DPReCAP);
DPReCAP.CAP2Calc(&DPReCAP);
//Подтверждение прерываний
ECAP1->ECCLR_bit.CEVT0 = 1;
ECAP1->ECCLR_bit.CEVT1 = 1;
ECAP1->ECCLR_bit.INT = 1;
}
//!Прерывание, возникающее по событиям захвата модуля CAP2
//! \memberof MAIN_C
#if defined (__GNUC__)
void ECAP2_IRQHandler(void)
#elif defined (__CMCPPARM__)
void CAP2_IRQHandler(void)
#endif
{
//Подтверждаем это прерывание для NVIC - иначе при выходе из функции оно возникнет опять
ECAP2->PEINT = 1;
if (DPReCAP.CAPCalcEna3 == 0) { //если функция вызвалась повторно
DPReCAP.CAP_WrongEdgeCnt = (++DPReCAP.CAP_WrongEdgeCnt) & 0xFF;
DPReCAP.CAP_WrongEdgeCnt3++;
return;
}
DPReCAP.CAPCalcEna3 = 0;
CounterCAP_isr++;
CounterCAP_isr = CounterCAP_isr & 0xF;
cap2_counter++;
DPReCAP.Angle6Calc(&DPReCAP); //если убрать, то в момент прихода метки на один период ШИМ косяк, так как прерывание посчиталось, а Angle6Calc нет
DPReCAP.CAP3Calc(&DPReCAP);
//Подтверждение прерываний
ECAP2->ECCLR_bit.CEVT0 = 1;
ECAP2->ECCLR_bit.CEVT1 = 1;
ECAP2->ECCLR_bit.INT = 1;
}
//!Прерывание, возникающее по событию реперной метки(индекса) модуля QEP
//! \memberof MAIN_C
//! Но - на двигателе ACM601V36-1000 нет индексной метки.
//Так что этого прерывания c таким двигателем не будет (или будет от помех, как повезет)
#if defined (__GNUC__)
void QEP_IRQHandler(void)
#elif defined (__CMCPPARM__)
void QEP1_IRQHandler(void)
#endif
{
//Обработка репера
posspeedEqep.index(&posspeedEqep);
//Подтверждаем это прерывание для NVIC
QEP->INTCLR = 1;
QEP->QCLR_bit.IEL = 1;
QEP->QCLR_bit.INT = 1;
}
//Прерывание вызывается один раз на периоде ШИМ и забирает 4 результата за период
void ADC_SEQ0_IRQHandler (void) {
adc.fast_calc(&adc);
dlog.update(&dlog); //Осциллографирование данных
ADC->IC_bit.SEQIC0 = 1;
}
/*@}*/

47
Vsrc/park.c Normal file
View File

@ -0,0 +1,47 @@
/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file park.c
\brief Ìîäóëü êîîðäèíàòíûõ ïðåîáðàçîâàíèé êîîðäèíàò (ñì. TPark)
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 2.0 25/03/2016
\addtogroup Park
@{
*/
#include "V_IQmath.h" /* Include header for IQmath library */
#include "park.h"
//! Ôóíêöèÿ ïðåîáðàçîâàíèé êîîðäèíàò
//!Íà âõîäå óãîë ang, âåêòîð (ds,qs).
//!Íà âûõîäå ïîâåðíóòûé íà çàäàííûé óãîë âåêòîð (de,qe)
//! \memberof TPark
void park_calc(TPark *v) {
_iq cos_ang, sin_ang;
/* Using look-up IQ sine table */
sin_ang = _IQsinPU(v->ang);
cos_ang = _IQcosPU(v->ang);
v->de = _IQmpy(v->ds,cos_ang) + _IQmpy(v->qs, sin_ang);
v->qe = _IQmpy(v->qs,cos_ang) - _IQmpy(v->ds, sin_ang);
}
/*@}*/

View File

@ -0,0 +1,307 @@
/**
******************************************************************************
* @file startup_MCP.s
* @author Vector / NIIET
* @version V1.0.0
* @date 28 - September - 2014
* @brief NIIET MC01 vector table for Sourcery Codebench.
* This module performs:
* - Set the initial SP
* - Set the initial PC == Reset_Handler,
* - Set the vector table entries with the exceptions ISR address
* - Branches to main in the C library (which eventually
* calls main()).
* - enables FPU (COMING SOON!)
* After Reset the Cortex-M4 processor is in Thread mode,
* priority is Privileged, and the Stack is set to Main.
*/
.syntax unified
.cpu cortex-m3
.fpu vfpv4
.thumb
.global g_pfnVectors
.global Default_Handler
/* start address for the initialization values of the .data section.
defined in linker script */
.word _sidata
/* start address for the .data section. defined in linker script */
.word _sdata
/* end address for the .data section. defined in linker script */
.word _edata
/* start address for the .bss section. defined in linker script */
.word _sbss
/* end address for the .bss section. defined in linker script */
.word _ebss
/* stack used for SystemInit_ExtMemCtl; always internal RAM used */
/**
* @brief This is the code that gets called when the processor first
* starts execution following a reset event. Only the absolutely
* necessary set is performed, after which the application
* supplied main() routine is called.
* @param None
* @retval : None
*/
.section .text.Reset_Handler
.weak Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
/* Copy the data segment initializers from flash to SRAM */
movs r1, #0
b LoopCopyDataInit
CopyDataInit:
ldr r3, =_sidata
ldr r3, [r3, r1]
str r3, [r0, r1]
adds r1, r1, #4
LoopCopyDataInit:
ldr r0, =_sdata
ldr r3, =_edata
adds r2, r0, r1
cmp r2, r3
bcc CopyDataInit
ldr r2, =_sbss
b LoopFillZerobss
/* Zero fill the bss segment. */
FillZerobss:
movs r3, #0
str r3, [r2], #4
LoopFillZerobss:
ldr r3, = _ebss
cmp r2, r3
bcc FillZerobss
/* Âêëþ÷åíèå ïëàâîòî÷êè*/
ldr.w R0, =0xE000ED88
ldr R1, [R0]
orr R1, R1, #(0xF << 20)
str R1, [R0]
dsb
isb /*reset pipeline now the FPU is enabled*/
ldr r0, = _estack /* Ýòè äâå ñòðîêè - çàãðóçêà SP àäðåñîì 2000à000 â ñëó÷àå, åñëè ôëåøêà ïîò¸ðòà. Åñëè ïðîåêò øü¸òñÿ âî ôëåø - óäàëèòü.*/
msr msp, r0 /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
bl main
bx lr
.size Reset_Handler, .-Reset_Handler
/**
* @brief This is the code that gets called when the processor receives an
* unexpected interrupt. This simply enters an infinite loop, preserving
* the system state for examination by a debugger.
* @param None
* @retval None
*/
.section .text.Default_Handler,"ax",%progbits
Default_Handler:
Infinite_Loop:
b Infinite_Loop
.size Default_Handler, .-Default_Handler
/******************************************************************************
*
* The minimal vector table for a Cortex M3. Note that the proper constructs
* must be placed on this to ensure that it ends up at physical address
* 0x0000.0000.
*
*******************************************************************************/
.section .isr_vector,"a",%progbits
.type g_pfnVectors, %object
.size g_pfnVectors, .-g_pfnVectors
g_pfnVectors:
.word _estack
.word Reset_Handler
.word NMI_Handler
.word HardFault_Handler
.word MemManage_Handler
.word BusFault_Handler
.word UsageFault_Handler
.word 0
.word 0
.word 0
.word 0
.word SVC_Handler
.word DebugMon_Handler
.word 0
.word PendSV_Handler
.word SysTick_Handler
.word WDT_IRQHandler
.word RCU_IRQHandler
.word MFLASH_IRQHandler
.word GPIOA_IRQHandler
.word GPIOB_IRQHandler
.word DMA_CH0_IRQHandler
.word DMA_CH1_IRQHandler
.word DMA_CH2_IRQHandler
.word DMA_CH3_IRQHandler
.word DMA_CH4_IRQHandler
.word DMA_CH5_IRQHandler
.word DMA_CH6_IRQHandler
.word DMA_CH7_IRQHandler
.word DMA_CH8_IRQHandler
.word DMA_CH9_IRQHandler
.word DMA_CH10_IRQHandler
.word DMA_CH11_IRQHandler
.word DMA_CH12_IRQHandler
.word DMA_CH13_IRQHandler
.word DMA_CH14_IRQHandler
.word DMA_CH15_IRQHandler
.word TMR0_IRQHandler
.word TMR1_IRQHandler
.word TMR2_IRQHandler
.word TMR3_IRQHandler
.word UART0_TD_IRQHandler
.word UART0_RX_IRQHandler
.word UART0_TX_IRQHandler
.word UART0_E_RT_IRQHandler
.word UART1_TD_IRQHandler
.word UART1_RX_IRQHandler
.word UART1_TX_IRQHandler
.word UART1_E_RT_IRQHandler
.word SPI_RO_RT_IRQHandler
.word SPI_RX_IRQHandler
.word SPI_TX_IRQHandler
.word I2C_IRQHandler
.word ECAP0_IRQHandler
.word ECAP1_IRQHandler
.word ECAP2_IRQHandler
.word PWM0_IRQHandler
.word PWM0_HD_IRQHandler
.word PWM0_TZ_IRQHandler
.word PWM1_IRQHandler
.word PWM1_HD_IRQHandler
.word PWM1_TZ_IRQHandler
.word PWM2_IRQHandler
.word PWM2_HD_IRQHandler
.word PWM2_TZ_IRQHandler
.word QEP_IRQHandler
.word ADC_SEQ0_IRQHandler
.word ADC_SEQ1_IRQHandler
.word ADC_DC_IRQHandler
.word CAN0_IRQHandler
.word CAN1_IRQHandler
.word CAN2_IRQHandler
.word CAN3_IRQHandler
.word CAN4_IRQHandler
.word CAN5_IRQHandler
.word CAN6_IRQHandler
.word CAN7_IRQHandler
.word CAN8_IRQHandler
.word CAN9_IRQHandler
.word CAN10_IRQHandler
.word CAN11_IRQHandler
.word CAN12_IRQHandler
.word CAN13_IRQHandler
.word CAN14_IRQHandler
.word CAN15_IRQHandler
.word FPU_IRQHandler
/*******************************************************************************
*
* Provide weak aliases for each Exception handler to the Default_Handler.
* As they are weak aliases, any function with the same name will override
* this definition.
*
*******************************************************************************/
/* Macro to define default handlers. Default handler
* will be weak symbol and just dead loops. They can be
* overwritten by other handlers */
.macro def_irq_handler handler_name
.weak \handler_name
.thumb_set \handler_name, Default_Handler
.endm
def_irq_handler NMI_Handler
def_irq_handler HardFault_Handler
def_irq_handler MemManage_Handler
def_irq_handler BusFault_Handler
def_irq_handler UsageFault_Handler
def_irq_handler SVC_Handler
def_irq_handler DebugMon_Handler
def_irq_handler PendSV_Handler
def_irq_handler SysTick_Handler
/* External Interrupt Handlers */
def_irq_handler WDT_IRQHandler
def_irq_handler RCU_IRQHandler
def_irq_handler MFLASH_IRQHandler
def_irq_handler GPIOA_IRQHandler
def_irq_handler GPIOB_IRQHandler
def_irq_handler DMA_CH0_IRQHandler
def_irq_handler DMA_CH1_IRQHandler
def_irq_handler DMA_CH2_IRQHandler
def_irq_handler DMA_CH3_IRQHandler
def_irq_handler DMA_CH4_IRQHandler
def_irq_handler DMA_CH5_IRQHandler
def_irq_handler DMA_CH6_IRQHandler
def_irq_handler DMA_CH7_IRQHandler
def_irq_handler DMA_CH8_IRQHandler
def_irq_handler DMA_CH9_IRQHandler
def_irq_handler DMA_CH10_IRQHandler
def_irq_handler DMA_CH11_IRQHandler
def_irq_handler DMA_CH12_IRQHandler
def_irq_handler DMA_CH13_IRQHandler
def_irq_handler DMA_CH14_IRQHandler
def_irq_handler DMA_CH15_IRQHandler
def_irq_handler TMR0_IRQHandler
def_irq_handler TMR1_IRQHandler
def_irq_handler TMR2_IRQHandler
def_irq_handler TMR3_IRQHandler
def_irq_handler UART0_TD_IRQHandler
def_irq_handler UART0_RX_IRQHandler
def_irq_handler UART0_TX_IRQHandler
def_irq_handler UART0_E_RT_IRQHandler
def_irq_handler UART1_TD_IRQHandler
def_irq_handler UART1_RX_IRQHandler
def_irq_handler UART1_TX_IRQHandler
def_irq_handler UART1_E_RT_IRQHandler
def_irq_handler SPI_RO_RT_IRQHandler
def_irq_handler SPI_RX_IRQHandler
def_irq_handler SPI_TX_IRQHandler
def_irq_handler I2C_IRQHandler
def_irq_handler ECAP0_IRQHandler
def_irq_handler ECAP1_IRQHandler
def_irq_handler ECAP2_IRQHandler
def_irq_handler PWM0_IRQHandler
def_irq_handler PWM0_HD_IRQHandler
def_irq_handler PWM0_TZ_IRQHandler
def_irq_handler PWM1_IRQHandler
def_irq_handler PWM1_HD_IRQHandler
def_irq_handler PWM1_TZ_IRQHandler
def_irq_handler PWM2_IRQHandler
def_irq_handler PWM2_HD_IRQHandler
def_irq_handler PWM2_TZ_IRQHandler
def_irq_handler QEP_IRQHandler
def_irq_handler ADC_SEQ0_IRQHandler
def_irq_handler ADC_SEQ1_IRQHandler
def_irq_handler ADC_DC_IRQHandler
def_irq_handler CAN0_IRQHandler
def_irq_handler CAN1_IRQHandler
def_irq_handler CAN2_IRQHandler
def_irq_handler CAN3_IRQHandler
def_irq_handler CAN4_IRQHandler
def_irq_handler CAN5_IRQHandler
def_irq_handler CAN6_IRQHandler
def_irq_handler CAN7_IRQHandler
def_irq_handler CAN8_IRQHandler
def_irq_handler CAN9_IRQHandler
def_irq_handler CAN10_IRQHandler
def_irq_handler CAN11_IRQHandler
def_irq_handler CAN12_IRQHandler
def_irq_handler CAN13_IRQHandler
def_irq_handler CAN14_IRQHandler
def_irq_handler CAN15_IRQHandler
def_irq_handler FPU_IRQHandler

242
cmd/build.ld Normal file
View File

@ -0,0 +1,242 @@
/******************************************************************************
Copyright 2017 АО "НИИЭТ" и ООО "НПФ ВЕКТОР"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
* @file build.ld
* @brief Файл распределения памяти для выполнения из FLASH
* @version v1.0
* @date 11 декабря 2015
*
* @author ООО "НПФ Вектор", http://motorcontrol.ru
*
******************************************************************************/
/* Entry Point */
ENTRY(Reset_Handler)
/* Generate a link error if heap and stack don't fit into RAM */
_Stack_Size = 0x1000; /* required amount of stack */
/* Specify the memory areas */
/* Буквы в скобках определяют атрибуты: доступ на чтение,
* запись, исполнение, выделение памяти. */
MEMORY
{
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x10000
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x4000
}
/* Конец РАМы на НИИЭТЕ (с запасиком) - отсюда внутрь будет расти стек*/
_estack = ORIGIN(RAM) + LENGTH(RAM) - 4;
/* Define output sections */
SECTIONS
{
. = ORIGIN(RAM);
/* таблица векторов прерываний, обязана быть выровнена по 0х80 */
.isr_vector ALIGN(0x80):
{
__isr_vector_flash_start = LOADADDR (.isr_vector); /* Берем адрес, где на флеше лежит эта таблица */
__isr_vector_ram_start = .;
KEEP(*(.isr_vector)) /* Startup code - KEEP запрещает удалить секцию сборщику мусора */
. = ALIGN(4);
__isr_vector_ram_end = .; /* конец оперативки, куда будет скопирован код */
} >RAM AT>FLASH
/* Секция для кода, который исполняется в оперативке, а лежит на флеше.
* В начале мейна он копируется из ROM в RAM.*/
.fastcode ALIGN(4): {
__fastcode_flash_start = LOADADDR (.fastcode); /* Берем адрес, где на флеше лежит код. */
/* Точка - это курсор текущего размещения в памяти. Т.е. в
* __fastcode_ram_start будет лежать адрес оперативки, где будет исполняться скопированный код.*/
__fastcode_ram_start = .;
*(.glue_7t) *(.glue_7)
*(.fastcode)
*(.fastcode*)
. = ALIGN (4);
__fastcode_ram_end = .; /* конец оперативки, куда будет скопирован код */
} >RAM AT>FLASH
/* The program code and other data goes into RAM */
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
*(.eh_frame)
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
/* define a global symbols at end of code - указатель на конец кода,
т.к. точка - это переменная с инкрементирующимся значением адреса (называют её курсор)*/
_etext = .;
} >FLASH
/* .preinit_array - секция для указателей на функции пре-инициализации,
* вызываемых перед любыми другими функциями
* инициализации (перед выполнением кода из секции
* '.init' и вызовами функций из секции '.init_array').
*
* Специальная секция с именем '.preinit_array' и вышеназванным
* назначением описана в System V gABI. Вызов функций, указатели на
* которые содержатся в секции '.preinit_array', возлагается на библиотеку
* времени выполнения (runtime library) -- например, на C runtime. Если в
* библиотеке не предусмотрен такой вызов, то функции из секции
* '.preinit_array' не будут вызваны.
*
* Секция '.preinit_array' предназначена для пре-инициализации
* исполняемого файла (executable), выполняемой перед инициализацией
* динамически скомпонованных с ним разделяемых объектов (shared objects).
*
* Символы __preinit_array_start и __preinit_array_end используются
* библиотекой C времени выполнения (newlib, glibc).
*/
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >FLASH
/* .init_array - секции с указателями на функции инициализации,
* выполняющиеся перед вызовом входной точки программы, т.е.
* перед вызовом функции main.
*
* Специальная секция с именем '.init_array' и вышеназванным назначением
* описана в System V gABI. Вызов функций, указатели на которые содержатся в
* секции '.init_array', возлагается на библиотеку времени выполнения
* (runtime library) -- например, на C runtime. Если в библиотеке не
* предусмотрен такой вызов, то функции из секции '.init_array' не будут
* вызваны.
*
* GCC использует секцию '.init_array' для обеспечения вызова статических
* конструкторов: функций, объявленных с __attribute__((constructor)).
*
* Для статических конструкторов с объявленным приоритетом PRIORITY,
* используются секции с именем '.init_array.PRIORITY'
*
* Также GCC использует секцию '.init_array' для вызова конструкторов
* статических объектов C++.
*
* Символы __init_array_start и __init_array_end используются библиотекой
* C времени выполнения (newlib, glibc).
*/
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN (__init_array_end = .);
} >FLASH
/* .fini_array - секции с указателями на функции терминации,
* выполняющиеся по завершению программы (после возврата из
* входной точки программы, т.е. из функции main).
*
* Специальная секция с именем '.fini_array' и вышеназванным назначением
* описана в System V gABI. Вызов функций, указатели на которые содержатся в
* секции '.fini_array', возлагается на библиотеку времени выполнения
* (runtime library) -- например, на C runtime. Если в библиотеке не
* предусмотрен такой вызов, то функции из секции '.fini_array' не будут
* вызваны.
*
* GCC использует секцию '.fini_array' для обеспечения вызова статических
* деструкторов: функций, объявленных с __attribute__((destructor)).
*
* Для статических деструкторов с объявленным приоритетом PRIORITY,
* используются секции с именем '.fini_array.PRIORITY'
*
* Символы __fini_array_start и __fini_array_end используются библиотекой
* C времени выполнения (newlib, glibc).
*/
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(.fini_array*))
KEEP (*(SORT(.fini_array.*)))
PROVIDE_HIDDEN (__fini_array_end = .);
} >FLASH
/* used by the startup to initialize data */
_sidata = .;
/* Выражение _sidata, которое следует за ключевым словом AT,
* определяет адрес загрузки секции. По умолчанию, если Вы
* не использовали ключевое слово AT, адрес загрузки равен адресу перемещения.
* Так как _sidata до этого было равно точке (указатель на текущий адрес),
* то .data пойдет сразу дальше после неё. Как бы динамическое смещение такое.
* */
/* Initialized data sections goes into RAM, load LMA copy after code */
.data : AT ( _sidata )
{
. = ALIGN(4);
_sdata = .; /* create a global symbol at data start */
*(.data) /* .data sections */
*(.data*) /* .data* sections */
. = ALIGN(4);
_edata = .; /* define a global symbol at data end */
} >RAM
_________________________ZHOPA__________________________ = .;
/* Uninitialized data section */
. = ALIGN(4);
.bss :
{
/* This is used by the startup in order to initialize the .bss secion */
_sbss = .; /* define a global symbol at bss start */
__bss_start__ = _sbss;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .; /* define a global symbol at bss end */
__bss_end__ = _ebss;
} >RAM
/* Функци проверяет, что после всего кода осталось место под стек.
* Стек сделан снизу оперативки!
* Не размещайте свои секции после этой функции, только перед!*/
._user_heap_stack :
{
. = ALIGN(4);
PROVIDE ( end = . );
PROVIDE ( _end = . );
. = . + _Stack_Size + 4;
. = ALIGN(4);
} >RAM
/* Remove information from the standard libraries */
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
/* Тут какие-то атрибуты об особенностях компиляции, специфичная инфа производителя и хз еще что, читайте
* 4.3.6 Build Attributes http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044e/IHI0044E_aaelf.pdf */
.ARM.attributes 0 : { *(.ARM.attributes) }
}

4547
cood.xml Normal file

File diff suppressed because it is too large Load Diff

10232
include/K1921VK035.h Normal file

File diff suppressed because it is too large Load Diff

1758
include/core_cm4.h Normal file

File diff suppressed because it is too large Load Diff

650
include/core_cm4_simd.h Normal file
View File

@ -0,0 +1,650 @@
/**************************************************************************//**
* @file core_cm4_simd.h
* @brief CMSIS Cortex-M4 SIMD Header File
* @version V3.01
* @date 06. March 2012
*
* @note
* Copyright (C) 2010-2012 ARM Limited. All rights reserved.
*
* @par
* ARM Limited (ARM) is supplying this software for use with Cortex-M
* processor based microcontrollers. This file can be freely distributed
* within development tools that are supporting such ARM based processors.
*
* @par
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*
******************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
#ifndef __CORE_CM4_SIMD_H
#define __CORE_CM4_SIMD_H
/*******************************************************************************
* Hardware Abstraction Layer
******************************************************************************/
/* ################### Compiler specific Intrinsics ########################### */
/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics
Access to dedicated SIMD instructions
@{
*/
#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/
/* ARM armcc specific functions */
/*------ CM4 SIMD Intrinsics -----------------------------------------------------*/
#define __SADD8 __sadd8
#define __QADD8 __qadd8
#define __SHADD8 __shadd8
#define __UADD8 __uadd8
#define __UQADD8 __uqadd8
#define __UHADD8 __uhadd8
#define __SSUB8 __ssub8
#define __QSUB8 __qsub8
#define __SHSUB8 __shsub8
#define __USUB8 __usub8
#define __UQSUB8 __uqsub8
#define __UHSUB8 __uhsub8
#define __SADD16 __sadd16
#define __QADD16 __qadd16
#define __SHADD16 __shadd16
#define __UADD16 __uadd16
#define __UQADD16 __uqadd16
#define __UHADD16 __uhadd16
#define __SSUB16 __ssub16
#define __QSUB16 __qsub16
#define __SHSUB16 __shsub16
#define __USUB16 __usub16
#define __UQSUB16 __uqsub16
#define __UHSUB16 __uhsub16
#define __SASX __sasx
#define __QASX __qasx
#define __SHASX __shasx
#define __UASX __uasx
#define __UQASX __uqasx
#define __UHASX __uhasx
#define __SSAX __ssax
#define __QSAX __qsax
#define __SHSAX __shsax
#define __USAX __usax
#define __UQSAX __uqsax
#define __UHSAX __uhsax
#define __USAD8 __usad8
#define __USADA8 __usada8
#define __SSAT16 __ssat16
#define __USAT16 __usat16
#define __UXTB16 __uxtb16
#define __UXTAB16 __uxtab16
#define __SXTB16 __sxtb16
#define __SXTAB16 __sxtab16
#define __SMUAD __smuad
#define __SMUADX __smuadx
#define __SMLAD __smlad
#define __SMLADX __smladx
#define __SMLALD __smlald
#define __SMLALDX __smlaldx
#define __SMUSD __smusd
#define __SMUSDX __smusdx
#define __SMLSD __smlsd
#define __SMLSDX __smlsdx
#define __SMLSLD __smlsld
#define __SMLSLDX __smlsldx
#define __SEL __sel
#define __QADD __qadd
#define __QSUB __qsub
#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \
((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) )
#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \
((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) )
/*-- End CM4 SIMD Intrinsics -----------------------------------------------------*/
#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/
/* IAR iccarm specific functions */
/*------ CM4 SIMD Intrinsics -----------------------------------------------------*/
#include <cmsis_iar.h>
/*-- End CM4 SIMD Intrinsics -----------------------------------------------------*/
#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/
/* TI CCS specific functions */
/*------ CM4 SIMD Intrinsics -----------------------------------------------------*/
#include <cmsis_ccs.h>
/*-- End CM4 SIMD Intrinsics -----------------------------------------------------*/
#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/
/* GNU gcc specific functions */
/*------ CM4 SIMD Intrinsics -----------------------------------------------------*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SADD8(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("sadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD8(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UADD8(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("uadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USUB8(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("usub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SADD16(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("sadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD16(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UADD16(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("uadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("ssub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USUB16(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("usub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SASX(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("sasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QASX(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHASX(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UASX(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("uasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQASX(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHASX(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSAX(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("ssax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSAX(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USAX(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("usax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USAD8(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3)
{
uint32_t result;
__ASM volatile ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
return(result);
}
#define __SSAT16(ARG1,ARG2) \
({ \
uint32_t __RES, __ARG1 = (ARG1); \
__ASM ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
__RES; \
})
#define __USAT16(ARG1,ARG2) \
({ \
uint32_t __RES, __ARG1 = (ARG1); \
__ASM ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
__RES; \
})
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UXTB16(uint32_t op1)
{
uint32_t result;
__ASM volatile ("uxtb16 %0, %1" : "=r" (result) : "r" (op1));
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTB16(uint32_t op1)
{
uint32_t result;
__ASM volatile ("sxtb16 %0, %1" : "=r" (result) : "r" (op1));
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3)
{
uint32_t result;
__ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3)
{
uint32_t result;
__ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
return(result);
}
#define __SMLALD(ARG1,ARG2,ARG3) \
({ \
uint32_t __ARG1 = (ARG1), __ARG2 = (ARG2), __ARG3_H = (uint32_t)((uint64_t)(ARG3) >> 32), __ARG3_L = (uint32_t)((uint64_t)(ARG3) & 0xFFFFFFFFUL); \
__ASM volatile ("smlald %0, %1, %2, %3" : "=r" (__ARG3_L), "=r" (__ARG3_H) : "r" (__ARG1), "r" (__ARG2), "0" (__ARG3_L), "1" (__ARG3_H) ); \
(uint64_t)(((uint64_t)__ARG3_H << 32) | __ARG3_L); \
})
#define __SMLALDX(ARG1,ARG2,ARG3) \
({ \
uint32_t __ARG1 = (ARG1), __ARG2 = (ARG2), __ARG3_H = (uint32_t)((uint64_t)(ARG3) >> 32), __ARG3_L = (uint32_t)((uint64_t)(ARG3) & 0xFFFFFFFFUL); \
__ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (__ARG3_L), "=r" (__ARG3_H) : "r" (__ARG1), "r" (__ARG2), "0" (__ARG3_L), "1" (__ARG3_H) ); \
(uint64_t)(((uint64_t)__ARG3_H << 32) | __ARG3_L); \
})
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3)
{
uint32_t result;
__ASM volatile ("smlsd %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3)
{
uint32_t result;
__ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
return(result);
}
#define __SMLSLD(ARG1,ARG2,ARG3) \
({ \
uint32_t __ARG1 = (ARG1), __ARG2 = (ARG2), __ARG3_H = (uint32_t)((ARG3) >> 32), __ARG3_L = (uint32_t)((ARG3) & 0xFFFFFFFFUL); \
__ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (__ARG3_L), "=r" (__ARG3_H) : "r" (__ARG1), "r" (__ARG2), "0" (__ARG3_L), "1" (__ARG3_H) ); \
(uint64_t)(((uint64_t)__ARG3_H << 32) | __ARG3_L); \
})
#define __SMLSLDX(ARG1,ARG2,ARG3) \
({ \
uint32_t __ARG1 = (ARG1), __ARG2 = (ARG2), __ARG3_H = (uint32_t)((ARG3) >> 32), __ARG3_L = (uint32_t)((ARG3) & 0xFFFFFFFFUL); \
__ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (__ARG3_L), "=r" (__ARG3_H) : "r" (__ARG1), "r" (__ARG2), "0" (__ARG3_L), "1" (__ARG3_H) ); \
(uint64_t)(((uint64_t)__ARG3_H << 32) | __ARG3_L); \
})
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SEL (uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("sel %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
#define __PKHBT(ARG1,ARG2,ARG3) \
({ \
uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \
__ASM ("pkhbt %0, %1, %2, lsl %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \
__RES; \
})
#define __PKHTB(ARG1,ARG2,ARG3) \
({ \
uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \
if (ARG3 == 0) \
__ASM ("pkhtb %0, %1, %2" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2) ); \
else \
__ASM ("pkhtb %0, %1, %2, asr %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \
__RES; \
})
/*-- End CM4 SIMD Intrinsics -----------------------------------------------------*/
#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/
/* TASKING carm specific functions */
/*------ CM4 SIMD Intrinsics -----------------------------------------------------*/
/* not yet supported */
/*-- End CM4 SIMD Intrinsics -----------------------------------------------------*/
#endif
/*@} end of group CMSIS_SIMD_intrinsics */
#endif /* __CORE_CM4_SIMD_H */
#ifdef __cplusplus
}
#endif

617
include/core_cmFunc.h Normal file
View File

@ -0,0 +1,617 @@
/**************************************************************************//**
* @file core_cmFunc.h
* @brief CMSIS Cortex-M Core Function Access Header File
* @version V3.01
* @date 06. March 2012
*
* @note
* Copyright (C) 2009-2012 ARM Limited. All rights reserved.
*
* @par
* ARM Limited (ARM) is supplying this software for use with Cortex-M
* processor based microcontrollers. This file can be freely distributed
* within development tools that are supporting such ARM based processors.
*
* @par
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*
******************************************************************************/
#ifndef __CORE_CMFUNC_H
#define __CORE_CMFUNC_H
/* ########################### Core Function Access ########################### */
/** \ingroup CMSIS_Core_FunctionInterface
\defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions
@{
*/
#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/
/* ARM armcc specific functions */
#if (__ARMCC_VERSION < 400677)
#error "Please use ARM Compiler Toolchain V4.0.677 or later!"
#endif
/* intrinsic void __enable_irq(); */
/* intrinsic void __disable_irq(); */
/** \brief Get Control Register
This function returns the content of the Control Register.
\return Control Register value
*/
__STATIC_INLINE uint32_t __get_CONTROL(void)
{
register uint32_t __regControl __ASM("control");
return(__regControl);
}
/** \brief Set Control Register
This function writes the given value to the Control Register.
\param [in] control Control Register value to set
*/
__STATIC_INLINE void __set_CONTROL(uint32_t control)
{
register uint32_t __regControl __ASM("control");
__regControl = control;
}
/** \brief Get IPSR Register
This function returns the content of the IPSR Register.
\return IPSR Register value
*/
__STATIC_INLINE uint32_t __get_IPSR(void)
{
register uint32_t __regIPSR __ASM("ipsr");
return(__regIPSR);
}
/** \brief Get APSR Register
This function returns the content of the APSR Register.
\return APSR Register value
*/
__STATIC_INLINE uint32_t __get_APSR(void)
{
register uint32_t __regAPSR __ASM("apsr");
return(__regAPSR);
}
/** \brief Get xPSR Register
This function returns the content of the xPSR Register.
\return xPSR Register value
*/
__STATIC_INLINE uint32_t __get_xPSR(void)
{
register uint32_t __regXPSR __ASM("xpsr");
return(__regXPSR);
}
/** \brief Get Process Stack Pointer
This function returns the current value of the Process Stack Pointer (PSP).
\return PSP Register value
*/
__STATIC_INLINE uint32_t __get_PSP(void)
{
register uint32_t __regProcessStackPointer __ASM("psp");
return(__regProcessStackPointer);
}
/** \brief Set Process Stack Pointer
This function assigns the given value to the Process Stack Pointer (PSP).
\param [in] topOfProcStack Process Stack Pointer value to set
*/
__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack)
{
register uint32_t __regProcessStackPointer __ASM("psp");
__regProcessStackPointer = topOfProcStack;
}
/** \brief Get Main Stack Pointer
This function returns the current value of the Main Stack Pointer (MSP).
\return MSP Register value
*/
__STATIC_INLINE uint32_t __get_MSP(void)
{
register uint32_t __regMainStackPointer __ASM("msp");
return(__regMainStackPointer);
}
/** \brief Set Main Stack Pointer
This function assigns the given value to the Main Stack Pointer (MSP).
\param [in] topOfMainStack Main Stack Pointer value to set
*/
__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack)
{
register uint32_t __regMainStackPointer __ASM("msp");
__regMainStackPointer = topOfMainStack;
}
/** \brief Get Priority Mask
This function returns the current state of the priority mask bit from the Priority Mask Register.
\return Priority Mask value
*/
__STATIC_INLINE uint32_t __get_PRIMASK(void)
{
register uint32_t __regPriMask __ASM("primask");
return(__regPriMask);
}
/** \brief Set Priority Mask
This function assigns the given value to the Priority Mask Register.
\param [in] priMask Priority Mask
*/
__STATIC_INLINE void __set_PRIMASK(uint32_t priMask)
{
register uint32_t __regPriMask __ASM("primask");
__regPriMask = (priMask);
}
#if (__CORTEX_M >= 0x03)
/** \brief Enable FIQ
This function enables FIQ interrupts by clearing the F-bit in the CPSR.
Can only be executed in Privileged modes.
*/
#define __enable_fault_irq __enable_fiq
/** \brief Disable FIQ
This function disables FIQ interrupts by setting the F-bit in the CPSR.
Can only be executed in Privileged modes.
*/
#define __disable_fault_irq __disable_fiq
/** \brief Get Base Priority
This function returns the current value of the Base Priority register.
\return Base Priority register value
*/
__STATIC_INLINE uint32_t __get_BASEPRI(void)
{
register uint32_t __regBasePri __ASM("basepri");
return(__regBasePri);
}
/** \brief Set Base Priority
This function assigns the given value to the Base Priority register.
\param [in] basePri Base Priority value to set
*/
__STATIC_INLINE void __set_BASEPRI(uint32_t basePri)
{
register uint32_t __regBasePri __ASM("basepri");
__regBasePri = (basePri & 0xff);
}
/** \brief Get Fault Mask
This function returns the current value of the Fault Mask register.
\return Fault Mask register value
*/
__STATIC_INLINE uint32_t __get_FAULTMASK(void)
{
register uint32_t __regFaultMask __ASM("faultmask");
return(__regFaultMask);
}
/** \brief Set Fault Mask
This function assigns the given value to the Fault Mask register.
\param [in] faultMask Fault Mask value to set
*/
__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask)
{
register uint32_t __regFaultMask __ASM("faultmask");
__regFaultMask = (faultMask & (uint32_t)1);
}
#endif /* (__CORTEX_M >= 0x03) */
#if (__CORTEX_M == 0x04)
/** \brief Get FPSCR
This function returns the current value of the Floating Point Status/Control register.
\return Floating Point Status/Control register value
*/
__STATIC_INLINE uint32_t __get_FPSCR(void)
{
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
register uint32_t __regfpscr __ASM("fpscr");
return(__regfpscr);
#else
return(0);
#endif
}
/** \brief Set FPSCR
This function assigns the given value to the Floating Point Status/Control register.
\param [in] fpscr Floating Point Status/Control value to set
*/
__STATIC_INLINE void __set_FPSCR(uint32_t fpscr)
{
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
register uint32_t __regfpscr __ASM("fpscr");
__regfpscr = (fpscr);
#endif
}
#endif /* (__CORTEX_M == 0x04) */
#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/
/* IAR iccarm specific functions */
#include <cmsis_iar.h>
#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/
/* TI CCS specific functions */
#include <cmsis_ccs.h>
#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/
/* GNU gcc specific functions */
/** \brief Enable IRQ Interrupts
This function enables IRQ interrupts by clearing the I-bit in the CPSR.
Can only be executed in Privileged modes.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_irq(void)
{
__ASM volatile ("cpsie i");
}
/** \brief Disable IRQ Interrupts
This function disables IRQ interrupts by setting the I-bit in the CPSR.
Can only be executed in Privileged modes.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_irq(void)
{
__ASM volatile ("cpsid i");
}
/** \brief Get Control Register
This function returns the content of the Control Register.
\return Control Register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_CONTROL(void)
{
uint32_t result;
__ASM volatile ("MRS %0, control" : "=r" (result) );
return(result);
}
/** \brief Set Control Register
This function writes the given value to the Control Register.
\param [in] control Control Register value to set
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_CONTROL(uint32_t control)
{
__ASM volatile ("MSR control, %0" : : "r" (control) );
}
/** \brief Get IPSR Register
This function returns the content of the IPSR Register.
\return IPSR Register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_IPSR(void)
{
uint32_t result;
__ASM volatile ("MRS %0, ipsr" : "=r" (result) );
return(result);
}
/** \brief Get APSR Register
This function returns the content of the APSR Register.
\return APSR Register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_APSR(void)
{
uint32_t result;
__ASM volatile ("MRS %0, apsr" : "=r" (result) );
return(result);
}
/** \brief Get xPSR Register
This function returns the content of the xPSR Register.
\return xPSR Register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_xPSR(void)
{
uint32_t result;
__ASM volatile ("MRS %0, xpsr" : "=r" (result) );
return(result);
}
/** \brief Get Process Stack Pointer
This function returns the current value of the Process Stack Pointer (PSP).
\return PSP Register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PSP(void)
{
register uint32_t result;
__ASM volatile ("MRS %0, psp\n" : "=r" (result) );
return(result);
}
/** \brief Set Process Stack Pointer
This function assigns the given value to the Process Stack Pointer (PSP).
\param [in] topOfProcStack Process Stack Pointer value to set
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack)
{
__ASM volatile ("MSR psp, %0\n" : : "r" (topOfProcStack) );
}
/** \brief Get Main Stack Pointer
This function returns the current value of the Main Stack Pointer (MSP).
\return MSP Register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_MSP(void)
{
register uint32_t result;
__ASM volatile ("MRS %0, msp\n" : "=r" (result) );
return(result);
}
/** \brief Set Main Stack Pointer
This function assigns the given value to the Main Stack Pointer (MSP).
\param [in] topOfMainStack Main Stack Pointer value to set
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack)
{
__ASM volatile ("MSR msp, %0\n" : : "r" (topOfMainStack) );
}
/** \brief Get Priority Mask
This function returns the current state of the priority mask bit from the Priority Mask Register.
\return Priority Mask value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PRIMASK(void)
{
uint32_t result;
__ASM volatile ("MRS %0, primask" : "=r" (result) );
return(result);
}
/** \brief Set Priority Mask
This function assigns the given value to the Priority Mask Register.
\param [in] priMask Priority Mask
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask)
{
__ASM volatile ("MSR primask, %0" : : "r" (priMask) );
}
#if (__CORTEX_M >= 0x03)
/** \brief Enable FIQ
This function enables FIQ interrupts by clearing the F-bit in the CPSR.
Can only be executed in Privileged modes.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_fault_irq(void)
{
__ASM volatile ("cpsie f");
}
/** \brief Disable FIQ
This function disables FIQ interrupts by setting the F-bit in the CPSR.
Can only be executed in Privileged modes.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_fault_irq(void)
{
__ASM volatile ("cpsid f");
}
/** \brief Get Base Priority
This function returns the current value of the Base Priority register.
\return Base Priority register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_BASEPRI(void)
{
uint32_t result;
__ASM volatile ("MRS %0, basepri_max" : "=r" (result) );
return(result);
}
/** \brief Set Base Priority
This function assigns the given value to the Base Priority register.
\param [in] basePri Base Priority value to set
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI(uint32_t value)
{
__ASM volatile ("MSR basepri, %0" : : "r" (value) );
}
/** \brief Get Fault Mask
This function returns the current value of the Fault Mask register.
\return Fault Mask register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FAULTMASK(void)
{
uint32_t result;
__ASM volatile ("MRS %0, faultmask" : "=r" (result) );
return(result);
}
/** \brief Set Fault Mask
This function assigns the given value to the Fault Mask register.
\param [in] faultMask Fault Mask value to set
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask)
{
__ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) );
}
#endif /* (__CORTEX_M >= 0x03) */
#if (__CORTEX_M == 0x04)
/** \brief Get FPSCR
This function returns the current value of the Floating Point Status/Control register.
\return Floating Point Status/Control register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FPSCR(void)
{
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
uint32_t result;
__ASM volatile ("VMRS %0, fpscr" : "=r" (result) );
return(result);
#else
return(0);
#endif
}
/** \brief Set FPSCR
This function assigns the given value to the Floating Point Status/Control register.
\param [in] fpscr Floating Point Status/Control value to set
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr)
{
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
__ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) );
#endif
}
#endif /* (__CORTEX_M == 0x04) */
#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/
/* TASKING carm specific functions */
/*
* The CMSIS functions have been implemented as intrinsics in the compiler.
* Please use "carm -?i" to get an up to date list of all instrinsics,
* Including the CMSIS ones.
*/
#endif
/*@} end of CMSIS_Core_RegAccFunctions */
#endif /* __CORE_CMFUNC_H */

Some files were not shown because too many files have changed in this diff Show More