Initial commit

This commit is contained in:
Bogdan Kolbov 2019-07-29 08:18:57 +03:00
commit 010df1c0a4
145 changed files with 75626 additions and 0 deletions

280
.cproject Normal file
View File

@ -0,0 +1,280 @@
<?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.most" 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"/>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.spconstant.1553061732" name="Single precision constants (-fsingle-precision-constant)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.spconstant" useByScannerDiscovery="true" value="false" valueType="boolean"/>
<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/K1921VK028.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/libCANOpen_drv.a}&quot;"/>
<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;"/>
</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>
<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>
<sourceEntries>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="Vinclude"/>
<entry excluding="CANOpen_drv.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"/>
<storageModule moduleId="ilg.gnumcueclipse.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="CANOpen_drv.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">
<resource resourceType="PROJECT" workspacePath="/MCD_028"/>
</configuration>
<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>

2
.gitignore vendored Normal file
View File

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

32
.project Normal file
View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>MCD_028</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="502850917606847431" 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.

17
README.md Normal file
View File

@ -0,0 +1,17 @@
Данный репозиторий включает в себя полноценный работоспособный проект для задач управления двигателем на базе микроконтроллеров серии 1921ВК028 фирмы АО «НИИЭТ». Помимо исходного кода проекта, репозиторий содержит специализированное программное обеспечение, позволяющее производить разработку, отладку и исследование систем управления через интерфейс CAN (RS) с протоколом высокого уровня CANopen. Начинать знакомство с данным ПО следует с файла ```Описание структуры ПО MotorControlDemo.pdf```, находящегося в разделе [Downloads](https://bitbucket.org/niietcm4/motorcontroldemo/downloads/) репозитория [MotorControlDemo](https://bitbucket.org/niietcm4/motorcontroldemo/).
Состав репозитория:
- MotorControlDemo проект с исходными кодами - реализует различные структуры управления электродвигателями различных типов, а также содержит математические модели электродвигателей, которые могут быть опционально подключены вместо реального объекта управления на время отладки. ПО может быть сконфигурировано перед компиляцией для различных аппаратных конфигураций (различных контроллеров и отладочных плат на базе 1921BK028). Для некоторых аппаратных конфигураций ПО может работать только с математическими моделями двигателей, а для конфигураций, поддерживающих управление реальным электродвигателем может по выбору пользователя управлять и реальным объектом (например, конфигурация для отладочного комплекта VectorCARD с инвертором). ПО микроконтроллера разработано для бесплатной среды разработки [VectorIDE (Eclipse+GCC+OpenOCD)](http://motorcontrol.ru/production/soft/vector-ide/). Каталог ```MotorControlDemo\EclipseIDE\```.
- 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
/*@}*/

140
Vinclude/DRV8301_SPI.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 DRV8301_SPI.h
\brief Äðàéâåð äëÿ äðàéâåðà êëþ÷åé èíâåðòîðà DRV8301
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 2.0 25/03/2016
*/
#ifndef DRV8301_INTERFACE_H
#define DRV8301_INTERFACE_H
// DRV8301 SPI Input Data bit definitions:
struct DRV8301_SPI_WRITE_WORD_BITS { // bit description
Uint16 DATA:11; // 10:0 FIFO reset
Uint16 ADDRESS:4; // 14:11 Enhancement enable
Uint16 R_W:1; // 15 R/W
};
union DRV8301_SPI_WRITE_WORD_REG {
Uint16 all;
struct DRV8301_SPI_WRITE_WORD_BITS bit;
};
// DRV8301 SPI Status Reister 1 bit definitions:
struct DRV8301_STATUS_REG_1_BITS { // bit description
Uint16 FETLC_OC:1; // 0 Phase C, low-side FET OC
Uint16 FETHC_OC:1; // 1 Phase C, high-side FET OC
Uint16 FETLB_OC:1; // 2 Phase B, low-side FET OC
Uint16 FETHB_OC:1; // 3 Phase B, high-side FET OC
Uint16 FETLA_OC:1; // 4 Phase A, low-side FET OC
Uint16 FETHA_OC:1; // 5 Phase A, high-side FET OC
Uint16 OTW:1; // 6 Over-temperature warning
Uint16 OTSD:1; // 7 Over-temperature shut down
Uint16 PVDD_UV:1; // 8 PVDD < 6V
Uint16 GVDD_UV:1; // 9 GVDD < 8V
Uint16 FAULT:1; // 10 FAULTn pin is asserted
Uint16 Reserved:5; // 15:11
};
union DRV8301_STATUS_REG_1 {
Uint16 all;
struct DRV8301_STATUS_REG_1_BITS bit;
};
// DRV8301 SPI Status Reister 2 bit definitions:
struct DRV8301_STATUS_REG_2_BITS { // bit description
Uint16 DEVICE_ID:4; // 3:0 Device ID
Uint16 Reserved1:3; // 6:4
Uint16 GVDD_OV:1; // 7 GVDD > 16V
Uint16 Reserved2:8; // 15:8
};
union DRV8301_STATUS_REG_2 {
Uint16 all;
struct DRV8301_STATUS_REG_2_BITS bit;
};
// DRV8301 SPI Control Reister 1 bit definitions:
struct DRV8301_CONTROL_REG_1_BITS { // bit description
Uint16 GATE_CURRENT:2; // 1:0 Gate driver peak current, 1.7A (00b), 0.7A (01b), 0.25A (10b), Reserved (11b)
Uint16 GATE_RESET:1; // 2 Reset all latched faults (1), Normal Mode (0)
Uint16 PWM_MODE:1; // 3 Three (1) or six (0) pwm inputs
Uint16 OC_MODE:2; // 5:4 over-current mode, current limit (00b), latched shut down (01b), Report only (10b), OC disabled (11b)
Uint16 OC_ADJ_SET:5; // 10:6 Set Vds trip point for OC see the table in the datasheet
Uint16 Reserved:5; // 15:11
};
union DRV8301_CONTROL_REG_1 {
Uint16 all;
struct DRV8301_CONTROL_REG_1_BITS bit;
};
// DRV8301 SPI Control Reister 2 bit definitions:
struct DRV8301_CONTROL_REG_2_BITS { // bit description
Uint16 OCTW_SET:2; // 1:0 Report OT and OC (00b), Report OT (01b), Report OC (10b), Reserved (11b)
Uint16 GAIN:2; // 3:2 Gain of shunt amplifier, 10 (00b), 20 (01b), 40 (10b), 80 (11b)
Uint16 DC_CAL_CH1:1; // 4 Shunt amplifier inputs shorted and disconnected from load (1) or shunt amplifier inputs connected to load (0)
Uint16 DC_CAL_CH2:1; // 5 Shunt amplifier inputs shorted and disconnected from load (1) or shunt amplifier inputs connected to load (0)
Uint16 OC_TOFF:1; // 6 Normal CBC operation (0), off time control during OC (1)
Uint16 Reserved:9; // 15:7
};
union DRV8301_CONTROL_REG_2 {
Uint16 all;
struct DRV8301_CONTROL_REG_2_BITS bit;
};
struct Sdrv8301interface {
union DRV8301_CONTROL_REG_1 CTRL1;
union DRV8301_CONTROL_REG_2 CTRL2;
union DRV8301_STATUS_REG_1 STS1;
union DRV8301_STATUS_REG_2 STS2;
union DRV8301_SPI_WRITE_WORD_REG writeWord;
void (*init)(volatile struct Sdrv8301interface*);
void (*write)(volatile struct Sdrv8301interface*, Uint16);
void (*read)(volatile struct Sdrv8301interface*);
};
typedef volatile struct Sdrv8301interface Tdrv8301interface;
/***************************************************************************************************/
//defines
/***************************************************************************************************/
//DRV8301 Register Addresses
#define STAT_REG_1_ADDR 0x00
#define STAT_REG_2_ADDR 0x01
#define CNTRL_REG_1_ADDR 0x02
#define CNTRL_REG_2_ADDR 0x03
#define DRV8301_INTERFACE_DEFAULTS {0,0,0,0,0,\
DRV8301_Interface_Init,\
DRV8301_Interface_Write,\
DRV8301_Interface_Read}
/***************************************************************************************************/
//function prototypes
/***************************************************************************************************/
//void DRV8301_SPI_Init(volatile struct SPI_REGS *s);
//Uint16 DRV8301_SPI_Read(volatile struct SPI_REGS *s, Uint16 address);
//Uint16 DRV8301_SPI_Write(volatile struct SPI_REGS *s, Uint16 address, Uint16 data);
void DRV8301_Interface_Init (Tdrv8301interface*);
void DRV8301_Interface_Write (Tdrv8301interface*, Uint16);
void DRV8301_Interface_Read (Tdrv8301interface*);
#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

112
Vinclude/DSP.h Normal file
View File

@ -0,0 +1,112 @@
/******************************************************************************
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 DSP.h
* @brief Ôàéë ïîäêëþ÷åíèÿ çàãîëîâî÷íûõ ôàéëîâ ïåðèôåðèè è îáúÿâëåíèÿ ñèñòåìíûõ êîíñòàíò
* @author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
* @version v1.0
* @date 11 äåêàáðÿ 2015
******************************************************************************/
#ifndef VINCLUDE_DSP_H_
#define VINCLUDE_DSP_H_
#ifdef __cplusplus
extern "C" {
#endif
// Âûáîð ÷àñòîòû êâàðöà. Âëèÿåò íà äåëèòåëè ïðè íàñòðîéêå òàêòèðîâàíèÿ
//#define QUARTZ_10MHZ
#define QUARTZ_12MHZ
//÷àñòîòà òàêòèðîâàíèÿ ïðîöà
#define CORE_CLK 200000000
#define GPIO_PIN_0 0x0001
#define GPIO_PIN_1 0x0002
#define GPIO_PIN_2 0x0004
#define GPIO_PIN_3 0x0008
#define GPIO_PIN_4 0x0010
#define GPIO_PIN_5 0x0020
#define GPIO_PIN_6 0x0040
#define GPIO_PIN_7 0x0080
#define GPIO_PIN_8 0x0100
#define GPIO_PIN_9 0x0200
#define GPIO_PIN_10 0x0400
#define GPIO_PIN_11 0x0800
#define GPIO_PIN_12 0x1000
#define GPIO_PIN_13 0x2000
#define GPIO_PIN_14 0x4000
#define GPIO_PIN_15 0x8000
#define __CM4_REV 0x0001 //â K1921VK01T.h åñòü îáúÿâëåíèå __CM4F_REV, íî â core_cm4.h ïðîâåðÿåòñÿ èìåííî __CM4_REV. Åñëè íå îáúÿâëåíî òàì îáúÿâëÿåòñÿ íóëåì è áîëüøå íèãäå, âðîäå, íå èñïîëüçóåòñÿ ýòà êîíñòàíòà
#define __CHECK_DEVICE_DEFINES
#include <stdint.h>
#include "K1921VK028.h"
#include "core_cm4.h" /* Cortex-M4 processor and core peripherals */
#include "EPwm_defines.h" //Ôàéë îáúÿâëåíèÿ ñèñòåìíûõ êîíñòàíò äëÿ ðàáîòû ñ ØÈÌ ìîäóëÿìè
void gpioPeripheralInit();
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()
//! Ïðîöåäóðà áåçîïàñíîãî ðåñåòà ïðîöà, íå âûçûâàþùåãî çàâèñàíèé
void propReset(void);
//! Ïðîöåäóðà áåçîïàñíîé èíèöèàëèçàöèè àëüòåðíàòèâíûõ ôóíêöèé äèñêðåòíûõ íîæåê
void K1921VK01T_GPIO_SafeInit();
//ïðèîðèòåòû ïðåðûâàíèé
#define IRQ_PRIORITY_TZ 1
#define IRQ_PRIORITY_ADC 2
#define IRQ_PRIORITY_CAP 3
#define IRQ_PRIORITY_EQEP 3
#define IRQ_PRIORITY_10K 4
#define IRQ_PRIORITY_CAN 5
#define IRQ_PRIORITY_1K 6
#ifdef __cplusplus
}
#endif
#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
/*@}*/

118
Vinclude/SM_CmdLogic.h Normal file
View File

@ -0,0 +1,118 @@
/*!
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
#if defined (HW_VECTORCARD_DRV8301_EVM) || defined (HW_VECTORCARD_DRV8312_EVM)
#define STARTBUTTON ((NT_GPIOA->DATA & (1 << 14))==0) //îáðàáîòêà íîæêè ñòàðòà
#define STOPBUTTON ((NT_GPIOA->DATA & (1 << 13))==0) //îáðàáîòêà íîæêè ñòîïà
#define RESETBUTTON 0
#endif
#if defined (HW_MOTORCONTROLBOARD)
//Äëÿ óïðàâëåíèÿ êîíòðîëëåðîì ìû èñïîëüçóåì âíåøíèå äèñêðåòíûå âõîäû ñ èñïîëüçîâàíèåì ôèëüòðàöèè (ñì. V_DIO)
#define STARTBUTTON (BIT_IS_SET(input_vect, 0) ? 1 : 0) //Ïðîâåðêà íà óñòàâêó áèòà â âåêòîðå äèñêðåòíûõ âõîäîâ
#define STOPBUTTON (BIT_IS_SET(input_vect, 1) ? 1 : 0) //Ïðîâåðêà íà óñòàâêó áèòà â âåêòîðå äèñêðåòíûõ âõîäîâ
#define RESETBUTTON (BIT_IS_SET(input_vect, 2) ? 1 : 0) //Ïðîâåðêà íà óñòàâêó áèòà â âåêòîðå äèñêðåòíûõ âõîäîâ
#endif
#if !defined (HW_MOTORCONTROLBOARD) && !defined (HW_VECTORCARD_DRV8301_EVM) && !defined (HW_VECTORCARD_DRV8312_EVM)
#define STARTBUTTON 0
#define STOPBUTTON 0
#define RESETBUTTON 0
#endif
/*! \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;
int ResetButton;
int ResetButtonPrev;
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,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
/*@}*/

94
Vinclude/SM_Net.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 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
#define DRV_STATUS_OVERHEAT 0xC
/*! \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
/*@}*/

152
Vinclude/SM_Protect.h Normal file
View File

@ -0,0 +1,152 @@
/*!
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
//Ìàêðîñ ïðèåìà (åñëè íîëü, òî àâàðèÿ) è ñáðîñà (åñëè 1, òî ñáðîñ) àïïàðàòíîé àâàðèè
#if defined HW_VECTOR_MK_40_4
#define DRV_FAULT (NT_GPIOA->DATA & (1 << 8))
#define RESET_FAULT_BUTTON 0 //êíîïêà ñáðîñà àâàðèé íå ïðåäóñìîòðåíà
#endif
#if defined (HW_VECTORCARD_DRV8301_EVM) || defined(HW_VECTORCARD_DRV8312_EVM)
#define DRV_FAULT (NT_GPIOC->DATA & (1 << 4))
#define RESET_FAULT_BUTTON 0 //êíîïêà ñáðîñà àâàðèé íå ïðåäóñìîòðåíà
#endif
#if defined (HW_VECTORCARD_SIMULATOR) || defined(HW_NIIET_BOARD_SIMULATOR)
#define DRV_FAULT 0 //àâàðèé êëþ÷à â ñèìóëÿòîðå íå ïðåäóñìîòðåíî
#define RESET_FAULT_BUTTON 0 //êíîïêà ñáðîñà àâàðèé íå ïðåäóñìîòðåíà
#endif
#if defined (HW_MOTORCONTROLBOARD)
#define DRV_FAULT (GPIOB->DATA & (1 << 3)) //Ïðèåì îáùåé àâàðèè
#define DRV_FAULT1 (GPIOB->DATA & (1 << 4)) //Àâàðèÿ êëþ÷à A0
#define DRV_FAULT2 (GPIOB->DATA & (1 << 5)) //Àâàðèÿ êëþ÷à A1
#define DRV_FAULT3 (GPIOD->DATA & (1 << 4)) //Àâàðèÿ êëþ÷à A2
#define DRV_FAULT4 (GPIOD->DATA & (1 << 5)) //Àâàðèÿ êëþ÷à B0 èëè B1 èëè B2
//Äëÿ ñáðîñà àïïàðàòíîé àâàðèè â äàííîì êîíòðîëëåðå èñïîëüçóååòñÿ âíåøíèé äèñêðåòíûé ïîðò ââîäà
#define RESET_FAULT_BUTTON (BIT_IS_SET(input_vect, 2) ? 1 : 0) //Åñëè óñòàíîâëåí 3-é áèò â âåêòîðå äèñêðåòíûõ âõîäîâ
#endif
/*! \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 *NT_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
/*@}*/

119
Vinclude/V_DIO.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_DIO.h
\brief Ìîäóëü äèñêðåòíûõ âõîäîâ/âûõîäîâ
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 1.0 25/08/2017
\addtogroup
@{*/
#ifndef V_DIO_H
#define V_DIO_H
#ifdef __cplusplus
extern "C" {
#endif
// Ìàêðîñ óñòàíîâêè â '1' çàäàííîãî áèòà
// var - öåëåâàß ïåðåìåííàß
// index - èíäåêñ (ñìåùåíèå) óñòàíàâëèâàåìîãî áèòà
#define SET_BIT(var, index) var |= (1 << index);
// Ìàêðîñ ñáðîñà â '0' çàäàííîãî áèòà
// var - öåëåâàß ïåðåìåííàß
// index - èíäåêñ (ñìåùåíèå) î÷èùàåìîãî áèòà
#define CLEAR_BIT(var, index) var &= (~(1 << index));
// Ìàêðîñ ïðîâåðêè íåíóëåâîãî ñîñòîßíèÿ çàäàííîãî áèòà
// var - öåëåâàß ïåðåìåííàß
// index - èíäåêñ (ñìåùåíèå) ïðîâåðßåìîãî áèòà
#define BIT_IS_SET(var, index) ((var & (1 << index)) != 0)
// Ìàêðîñ ïðîâåðêè íóëåâîãî ñîñòîßíèÿ çàäàííîãî áèòà
// var - öåëåâàß ïåðåìåííàß
// index - èíäåêñ (ñìåùåíèå) ïðîâåðßåìîãî áèòà
#define BIT_IS_CLEAR(var, index) ((var & (1 << index)) == 0)
// Äåôàéíèì äèñêðåòíûå âõîäû
#ifdef HW_MOTORCONTROLBOARD
//TODO ïåðåäåëàòü
#define D_IN1 ((GPIOM->DATA & (1 << 13)) == 0) //M13 Ñòàðò
#define D_IN2 ((GPIOM->DATA & (1 << 11)) == 0) //M11 Ñòîï
#define D_IN3 ((GPIOM->DATA & (1 << 10)) == 0) //M10 Ñáðîñ àâàðèé
#else
#define D_IN1 0
#define D_IN2 0
#define D_IN3 0
#endif
// Äåôàéíèì äèñêðåòíûå âûõîäû
#ifdef HW_MOTORCONTROLBOARD
#define D_OUT1_ON GPIOD->DATAOUTSET = GPIO_PIN_1
#define D_OUT1_OFF GPIOD->DATAOUTCLR = GPIO_PIN_1
#define D_OUT2_ON GPIOD->DATAOUTSET = GPIO_PIN_2
#define D_OUT2_OFF GPIOD->DATAOUTCLR = GPIO_PIN_2
#define D_OUT3_ON GPIOM->DATAOUTSET = GPIO_PIN_14
#define D_OUT3_OFF GPIOM->DATAOUTCLR = GPIO_PIN_14
#else
#define D_OUT1_ON
#define D_OUT1_OFF
#define D_OUT2_ON
#define D_OUT2_OFF
#define D_OUT3_ON
#define D_OUT3_OFF
#endif
// Âåêòîð ñîñòîßíèß äèñêðåòíûõ âûõîäîâ
extern volatile Uint16 output_vect;
// Ìàñêà èíâåðòèðîâàíèß âåêòîðà ñîñòîßíèß äèñêðåòíûõ âûõîäîâ
extern volatile Uint16 output_mask;
// Âåêòîð ñîñòîßíèß äèñêðåòíûõ âõîäîâ
extern volatile Uint16 input_vect;
// Ìàñêà èíâåðòèðîâàíèß âåêòîðà ñîñòîßíèß äèñêðåòíûõ âõîäîâ
extern volatile Uint16 input_mask;
// Êîýôôèöèåíò ôèëüòðàöèè äèñêðåòíûõ âõîäîâ Kf = 0.0001/Tô
// (Tô - ïîñòîßííàß âðåìåíè ôèëüòðà, ñåê)
extern volatile _iq inputKf;
#define in_Kf inputKf // ïñåâäîíèì äëß óæå èìåþùåéñÿ ïåðåìåííîé â ñëîâàðå CANopen
// Ïîðîã ïåðåõîäà äèñêðåòíîãî âõîäà â ñîñòîßíèå OFF (0)
extern volatile _iq inputOff;
// Ïîðîã ïåðåõîäà äèñêðåòíîãî âõîäà â ñîñòîßíèå ON (1)
extern volatile _iq inputOn;
void DIO_Init();
void DIO_slow_calc(); // âûçûâàòü â ôîíîâîé ïðîãðàììå
void DIO_fast_calc(); // âûçûâàòü ñ ÷àñòîòîé 1êÃö èëè 10 êÃö
#ifdef __cplusplus
}
#endif
#endif
/*@}*/

225
Vinclude/V_DPR_eCAP.h Normal file
View File

@ -0,0 +1,225 @@
/*!
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 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,\
&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

65
Vinclude/V_Excitation.h Normal file
View File

@ -0,0 +1,65 @@
/*!
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_excitation.h
\brief Ìîäóëü âîçáóäèòåëÿ
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 1.0 28/03/2017
\defgroup V_excitation
@{*/
#ifndef V_excitation_H
#define V_excitation_H
#ifdef __cplusplus
extern "C" {
#endif
/*! \class Texcitation
\brief Ìîäóëü âîçáóäèòåëÿ
Êëàññ \a Texcitation, îñíîâàííûé íà ñòðóêòóðå Sexcitation, ïðåäñòàâëÿåò
ñîáîé ìîäóëü âîçáóäèòåëÿ.
*/
//! ñì. Texcitation
typedef struct Sexcitation{ long ref; //!< Çàäàíèå
void (*calc)(struct Sexcitation*);//!< Pointer to calculation function
}Texcitation;
//! Èíèöèàëèçàòîð ïî-óìîë÷àíèþ
#define excitation_DEFAULTS { 0, \
excitation_calc}
//! \memberof TRelayReg
void excitation_calc(Texcitation*);
#ifdef __cplusplus
}
#endif
#endif
/*@}*/

85
Vinclude/V_Fan.h Normal file
View File

@ -0,0 +1,85 @@
/*!
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_Fan.h
\brief Ìîäóëü ðàáîòû âåíòèëÿòîðà
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 1.0 25/08/2017
\addtogroup
@{*/
#ifndef V_FAN_H
#define V_FAN_H
//! âåíòèëÿòîð âûêëþ÷åí
#define FAN_CONTROL_STATE_OFF 0
//! âåíòèëÿòîð âêëþ÷åí
#define FAN_CONTROL_STATE_ON 1
//! ñîñòîÿíèå ïåðåãðåâà
#define FAN_CONTROL_STATE_OVERHEAT 2
/* Âêëþ÷åíèå è âûêëþ÷åíèå âåíòèëÿòîðà */
#if defined (HW_MOTORCONTROLBOARD)
#define FAN_ON GPIOB->DATAOUTSET = GPIO_PIN_13
#define FAN_OFF GPIOB->DATAOUTCLR = GPIO_PIN_13
#endif
#if !defined (HW_MOTORCONTROLBOARD)
/* Äåôàéíû äëÿ äðóãèõ êîíòðîëëåðîâ */
#define FAN_ON
#define FAN_OFF
#endif
struct SFanControl{
Uint16 Enabled;
int state; //!<ñîñòîÿíèå
int state_shadow;//!< ñîñòîÿíèå òåíåâîå
int state_prev;//!<ñîñòîÿíèå ïðåäûäóùåå
int StateOn;//!<äâîè÷íîå ñîñòîÿíèå: âêëþ÷åí/íå âêëþ÷åí
long T_on;//!<òåìïåðàòóðà âêëþ÷åíèÿ
long T_off;//!<òåìïåðàòóðà âûêëþ÷åíèÿ
long T_alarm;//!òåìïåðàòóðà âûâîäà ïðåäóïðåæäåíèÿ
void (*init)(volatile struct SFanControl*);
void (*slow_calc)(volatile struct SFanControl*);
};
typedef volatile struct SFanControl TFanControl;
//! \memberof TFanControl
void FanControl_init(TFanControl*);
//! \memberof TFanControl
void FanControl_slow_calc(TFanControl*); //ðàñ÷åò â ôîíîâîì ðåæèìå
#define FAN_CONTROL_DEFAULTS {0,\
FAN_CONTROL_STATE_OFF,FAN_CONTROL_STATE_OFF,FAN_CONTROL_STATE_OFF,0,\
_IQ(2.5),_IQ(2), _IQ(4),\
FanControl_init,\
FanControl_slow_calc}
#endif
/*@}*/

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 *NT_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
/*@}*/

172
Vinclude/V_MotorModel.h Normal file
View File

@ -0,0 +1,172 @@
/*!
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_MotorModel.h
\brief Модуль моделей электродвигателей (см. TMotorModel)
\author ООО "НПФ Вектор". http://motorcontrol.ru
\version v 2.0 25/03/2017
\defgroup V_MotorModel.h Модуль моделей электродвигателей (см. TMotorModel)
@{
*/
#ifndef V_MOTOR_MODEL_H
#define V_MOTOR_MODEL_H
#ifdef __cplusplus
extern "C" {
#endif
#include "DSP.h"
#include "V_IQmath.h"
// faults
#define MODEL_WRONG_PARAMETERS 1
#define MODEL_MAX_CURRENT_FAULT 2
#define MODEL_MAX_SPEED_FAULT 3
// motor types (for internal use)
#define MODEL_INDUCTION_MOTOR 0
#define MODEL_SYNC_MOTOR 1
#define MODEL_DC_MOTOR 2
#define MODEL_SRD_MOTOR 3
#define MOTOR_MODEL_PI 3.1415926f
#define MODEL_INV_2PI 0.15915494f
//структура с параметрами двигателя и преобразователя
struct Smotor
{
int cmpr0, cmpr1, cmpr2, cmpr3; //!< уставки сравнения ШИМ
int tpr; //!< период ШИМ
float inv_tpr; //!< 1/период ШИМ
int dt; //!< величина мертвого времени в тактах
int dta, dtb, dtc, dtf; //!< влияние мертвого времени на потенциалы фаз
float udc; //!< напряжение ЗПТ
float fia, fib, fic, fiav; //!< потенциалы фаз и средней точки
float ua, ub, uc; //!< фазные напряжения
float isa, isb, isc, isd, isq; //!< фазные токи в осях альфа, бетта
float usa, usb, usd, usq, urd, urq; //!< напряжения в ортогональных осях
float ird, irq, ira, irb; //!< токи в ортогональных осях
float omega,omega_rpm,torque; //!< скорость (частота вращения), момент
float torque_a, torque_b, torque_c; //!< момент от каждой фазы (SRD)
float j, inv_j; //!< момент инерции и обратная величина
float MechLoss; //!< момент инерции
float pp; //!< число пар полюсов
float inv_pp; //!< 1/pp
float tetaR; //!< угол положения ротора, электрический
float tetaRM; //!< угол положения ротора, механический
float cosTetaR, sinTetaR; //!< cos и sin угла положения ротора
float lm, lr, ls, lsd, lsq; //!< индуктивности - взаимная, ротора, статора
float lmin, lmax, dls; //!< минимальная индуктивность (зуб-паз), максимальная индуктивность (зуб-зуб), амплитуда изменения индуктивности
float inv_lmin; //!< 1/lmin
float l; //!< текущая индуктивнасть
float lp; //!< индуктивнасть в окрестности текущего положения
float ip, im; //!< токи в окрестности текущего положения
float wp, wm; //!< магнитные энергии фазной катушки в окрестности текущего положения
float isat; //!< ток насыщения
float rr, rs; //!< сопротивление ротра и статора
float ks, kr, km; //!< коэффициенты индуктивностей
float psa, psb, psc, psd, psq, prd, prq, pra, prb; //!< потокосцепления статора и ротора в ортогональных осях или фазные
float ppsa, ppsb, ppsd, ppsq, pprd, pprq, ppra, pprb; //!< предикторы потокосцеплений в ортогональных осях
float dpsa, dpsb, dpsd, dpsq, dprd, dprq; //!< производные потокосцеплений в ортогональных осях
int type; //!< тип двигателя
float t, t2; //!< период дискретизации, половина периода дискретизации
float speedK; //!< коэффициент датчика скорости
float iSenseK, ifSenseK, udSenseK, iSenseR, iSenseN; //!< коэффициент датчика тока, сопротивление измерительного резистора ДТ, количество витков провода через ДТ
float RatedPower; //!< номинальная мощность (справочная величина, не используется в расчетах)
float RatedSpeed; //!< номинальная скорость (справочная величина, не используется в расчетах)
float RatedCurrent; //!< номинальный ток
float RatedFluxCurrent; //!< номинальный ток возбуждения
int iADCk, ifADCk;
float QEPResolution; //!< число меток ДПР
float m; //!< потокосцепление ротора синхронной машины
float i_a, i_f, u_a, u_f, u_an;
float r_a, r_f, r_ad, l_a, l_f;
float _1_l_a, _1_l_f;
float _1_lsd, _1_lsq;
float dia, dif, dpa, dpf, pia, pif;
float l_m,kf; //!< коэффициент тока ОВ, потов ОВ
int dcm_pm; //!< флаг, что ДПТ с ПМ.
int syncm_pm; //!< флаг, что СД с ПМ.
float isPhaseA,isPhaseB,isPhaseC,isPhaseD; //!< ток фазы A,B,C
float isPhaseA_prev,isPhaseB_prev,isPhaseC_prev; //!< ток фазы A,B,C предыдущие значения
int CurrentInvertedFlag; //!< Флаг о том, что после выклчюения инвертора токи фаз один раз сменили свой знак
float cos30; //!< cos 30 градусов
float pisa,dprb,disa; //!< предиктор тока статора альфа, приращения потокосцепления ротора по оси бета, тока статора по оси альфа
float ThetaMax, PsiMax, IMax; //!< максимальный угол, поток и ток SRM (для интерполяции)
float ThetaStep, PsiStep, IStep; //!< шаг по углу, потоку и току SRM (для интерполяции)
float ThetaStep_inv, PsiStep_inv, IStep_inv; //!< обратные значения шага по углу, потоку и току SRM (для интерполяции)
float power; //!< Мощность на валу
long iAtemp, iBtemp, iCtemp, iDtemp, Udc_temp, adcSpeedtemp;//!<Временные переменные для расчета модели
Uint16 hallSensor; //!< сигнал с датчика положения Холла
Uint16 hallSensorPrev; //!< сигнал с датчика положения Холла предыдущий
float hallSensorOmegaPrev; //!< Для имитации измерения частоты вращения с датчика Холла
};
typedef volatile struct Smotor Tmotor;
//Структура с данными модели. является интерфейсом между основной программой и моделью двигателя.
//Принимает уставки сравнения, период ШИМ и величину мертвого времени, момент нагрузки. Выдает показания датчиков.
struct SMotorModel
{
Uint16 MotorType; //!< Тип двигателя в модели (для симулятора)
Uint16 MotorParametersNum; //!< Номер параметров двигателя из таблицы
Uint16 MotorParametersNumMax; // Максимальный возможный номер параметров из таблицы
Uint16 cmpr0; //!< уставки сравнения ШИМ
Uint16 cmpr1;
Uint16 cmpr2;
Uint16 cmpr3;
int16 InvertorEna; //!< Флаг включения инвертора (если нет, то ключи не управляются)
Uint16 tpr; //!< период ШИМ
Uint16 dt; //!< мертвое время в тиках таймера
Uint16 adc_code_Speed; //!< измеренная скорость
Uint32 qepCounter; //!< положение с энкодера
Uint16 hallSensor; //!< Дискретный сигнал с датчика положения Холла (три первых бита)
float hallSensorInterpAdd; //!< Для имитации интерполяции датчика Холла
float hallSensorOmega; //!< Для имитации измерения частоты вращения с датчика Холла
Uint16 adc_code_iA; //!< измеренные токи
Uint16 adc_code_iB;
Uint16 adc_code_iC;
Uint16 adc_code_iD;
Uint16 adc_code_Udc; //!< измеренное значение напряжения звена постоянного тока (ЗПТ)
int16 fault; //!< ошибка модели
float load; //!< момент нагрузки
float loadTmp; //!< момент нагрузки временная переменная
void (*Init)(volatile struct SMotorModel*); //!< Pointer to the init function
void (*Execute)(volatile struct SMotorModel*); //!< Pointer to the update function
Tmotor motorInternals; //!< Внутренние переменные для расчета модели двигателя
};
typedef volatile struct SMotorModel TMotorModel;
#define MOTOR_MODEL_DEFAULTS {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,MotorModel_Init, MotorModel_Execute}
void MotorModel_Init(TMotorModel*);
void MotorModel_Execute(TMotorModel*);
#ifdef __cplusplus
}
#endif
#endif
/*@}*/

20
Vinclude/V_MotorParams.h Normal file
View File

@ -0,0 +1,20 @@
/* 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.
*/
// V_motorParams.h
#include "V_MotorParams_DCM.h"
#include "V_MotorParams_IM.h"
#include "V_MotorParams_SM.h"
#include "V_MotorParams_SRM.h"

View File

@ -0,0 +1,54 @@
/* 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.
*/
// V_motorParams_DCM.h
//Ôàéë ñ ìàññèâàìè ïàðàìåòðîâ ìîäåëè äëÿ ðàçëè÷íûõ âàðèàíòîâ ÄÏÒ
// !!! Âíèìàíèå! Ïðè ñîîòíîøåíèè ïàðàìåòðîâ Πñ ìàëîé èíäóêòèâíîñòü è áîëüøèì ñîïðîòèâëåíèåì ðàñ÷åò Πìîæåò âûïîëíÿòüñÿ íåêîððåêòíî
// !!! Êðèòè÷åñêîå ñîîòíîøåíèå ïàðàìåòðîâ Lf=6.3 ìÃí è Rf=125 Îì
// !!! Åñëè ÄÏÒ ñ ïîñòîÿííûìè ìàãíèòàìè, òî ïàðàìåòðû èíäóêòèâíîñòü è ñîïðîòèâëåíèå ÎÂ äîëæíû áûòü çàäàíû ðàâíûìè íóëþ.
//ñòðóêòóðà ñ ïàðàìåòðàìè äâèãàòåëÿ
struct Sdcm_param
{
float r_f; //!< ñîïðîòèâëåíèå ÎÂ
float l_f; //!< èíäóêòèâíîñòü ÎÂ, ìÃí
float l_m; //!< êîýôôèöèåíò ìàãíèòíîãî ïîòîêà (âçàèìíàÿ èíäóêòèâíîñòü)
float r_a; //!< ñîïðîòèâëåíèÿ ÿêîðÿ
float l_a; //!< èíäóêòèâíîñòü ÿêîðÿ, ìÃí
float RatedFluxCurrent;//!< íîìèíàëüíûé òîê ÎÂ
float RatedCurrent; //!< íîìèíàëüíûé òîê ÿêîðÿ
float j; //!< ìîìåíò èíåðöèè
float qep; //!< ÷èñëî ìåòîê ýíêîäåðà
float RatedPower; //!< íîìèíàëüíàÿ ìîùíîñòü (ñïðàâî÷íàÿ âåëè÷èíà, íå èñïîëüçóåòñÿ â ðàñ÷åòàõ)
float RatedSpeed; //!< íîìèíàëüíàÿ ñêîðîñòü (ñïðàâî÷íàÿ âåëè÷èíà, íå èñïîëüçóåòñÿ â ðàñ÷åòàõ)
};
typedef volatile struct Sdcm_param Tdcm_param;
// !!! Âíèìàíèå! Ïîñëåäíèé íàáîð ïàðàìåòðîâ â ìàññèâå ÎÁÿÇÀÒÅËÜÍÎ äîëæåí áûòü íóëåâûì!
Tdcm_param DCMDATA[] = {\
// |r_f |l_f |l_m |r_a |l_a |If |Current |j |qep |Power |Speed
{0, 0, 0.075073632, 70.2, 6.68, 0, 0.347, 0.0000012, 3000, 0.011, 3900},\
{0, 0, 0.070452941, 16.6, 2.22, 0, 0.659, 0.00000438, 3000, 0.02, 4210},\
{107, 6.197183099, 1.546863917, 0.423, 48.85355617, 1.42, 47, 0.3, 2000, 8.5, 870},\
{94, 8.25, 1.531438221, 0.266, 40.06358237, 1.6, 65, 0.425, 1000, 12, 790},\
{70, 7.727272727, 1.25299365, 0.177, 34.78965363, 2.2, 85, 0.8, 2000, 16, 710},\
{65, 10.20833333, 1.249697876, 0.1155, 29.29350547, 2.4, 110, 1.05, 3000, 21, 660},\
{58, 11.15384615, 1.019986658, 0.0545, 17.38016729, 2.6, 164, 1.87, 5000, 32, 760},\
{42, 12.5, 0.900878093, 0.0332, 15.1587913, 3.6, 233, 4, 10000, 46, 625},\
{36, 13.25581395, 0.802128868, 0.0204, 11.08986109, 4.3, 338, 8.25, 1000, 67, 590},\
{34.4, 20, 0.890579855, 0.0117, 9.550454994, 4.6, 470, 17, 2000, 95, 500},\
{24.4, 17.93650794, 0.693407611, 0.00745, 7.155498472, 6.3, 670, 32.5, 3000, 135, 470},\
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},\
};

View File

@ -0,0 +1,49 @@
/* 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.
*/
// V_motorParams_IM.h
//Ôàéë ñ ìàññèâàìè ïàðàìåòðîâ ìîäåëè äëÿ ðàçëè÷íûõ âàðèàíòîâ ÀÄ
//ñòðóêòóðà ñ ïàðàìåòðàìè äâèãàòåëÿ
struct SIm_param
{
float l_s; //!< èíäóêòèâíîñòü ñòàòîðà ÀÄ, ìÃí
float l_r; //!<èíäóêòèâíîñòü ðîòîðà ÀÄ, ìÃí
float l_m; //!< âçàèìíàÿ èíäóêòèâíîñòü ÀÄ, ìÃí
float r_s; //!< ñîïðîòèâëåíèÿ ñòàòîðà ÀÄ, Îì
float r_r; //!< ñîïðîòèâëåíèÿ ðîòîðà ÀÄ, Îì
float pp; //!< ÷èñëî ïàð ïîëþñîâ
float j; //!< ìîìåíò èíåðöèè
float qep; //!< ÷èñëî ìåòîê ýíêîäåðà
float RatedPower; //!< íîìèíàëüíàÿ ìîùíîñòü (ñïðàâî÷íàÿ âåëè÷èíà, íå èñïîëüçóåòñÿ â ðàñ÷åòàõ)
float RatedSpeed; //!< íîìèíàëüíàÿ ñêîðîñòü (ñïðàâî÷íàÿ âåëè÷èíà, íå èñïîëüçóåòñÿ â ðàñ÷åòàõ)
float RatedCurrent;//!< íîìèíàëüíûé äåéñòâóþùèé òîê
};
typedef volatile struct SIm_param TIm_param;
// !!! Âíèìàíèå! Ïîñëåäíèé íàáîð ïàðàìåòðîâ â ìàññèâå ÎÁßÇÀÒÅËÜÍÎ äîëæåí áûòü íóëåâûì!
TIm_param IMDATA[] = {\
// |l_s |l_r |l_m |r_s |r_r |pp |j |qep |Power |Speed |Current
{5590.601309, 5737.268318, 5392.169472, 101.64, 94.864, 1, 0.000025, 10000, 0.09, 2742, 0.33},\
{396.0356208, 400.9617219, 389.5056727, 2.59129728, 1.69154128, 1, 0.0035, 10000, 3, 2871, 6.11},\
{143.0596483, 145.1464178, 139.1179724, 0.6992832, 0.4807572, 2, 0.028, 7500, 7.5, 1456.5, 15.1},\
{100.2417862, 101.3460409, 98.15597183, 0.362330144, 0.1927288, 2, 0.1, 7500, 15, 1465.5, 28.5},\
{71.64092383, 72.15142923, 69.76907071, 0.2673, 0.128304, 3, 0.4, 7500, 22, 977, 41.2},\
{38.44412805, 38.74763433, 37.43244047, 0.133489031, 0.060387895, 3, 0.74, 7500, 37, 982, 69.2},\
{21.18984563, 21.74726654, 20.41259675, 0.091259168, 0.039463424, 4, 0.4, 5000, 45, 732.75, 89.2},\
{17.01462802, 17.14451068, 16.23533208, 0.07140672, 0.044884224, 4, 3.2, 5000, 55, 733.5, 107.8},\
{10.47720097, 10.65862436, 9.978286639, 0.041321984, 0.038472192, 5, 6.2, 5000, 75, 590.4, 154.4},\
{6.858182237, 7.037715804, 6.463208391, 0.027073024, 0.022560853, 6, 10, 5000, 90, 493.5, 195},\
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},\
};

View File

@ -0,0 +1,56 @@
/* 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.
*/
// V_motorParams.h
//Ôàéë ñ ìàññèâàìè ïàðàìåòðîâ ìîäåëè äëÿ ðàçëè÷íûõ âàðèàíòîâ ÑÄÏÌ
//ñòðóêòóðà ñ ïàðàìåòðàìè äâèãàòåëÿ
struct Ssm_param
{
float r_f; //!< ñîïðîòèâëåíèå ÎÂ
float l_f; //!< èíäóêòèâíîñòü ÎÂ, ìÃí
float l_m; //!< êîýôôèöèåíò ìàãíèòíîãî ïîòîêà (âçàèìíàÿ èíäóêòèâíîñòü)
float RatedFluxCurrent;//!< íîìèíàëüíûé òîê ÎÂ
float psi_pm; //!< ïîòîêîñöåïëåíèÿ ïîñòîÿííûõ ìàãíèòîâ ÑÄÏÌ
float r_s; //!< ñîïðîòèâëåíèÿ ñòàòîðà ÑÄÏÌ, Îì
float l_sd; //!< èíäóêòèâíîñòü ñòàòîðà ïî îñè "d" ÑÄÏÌ, ìÃí
float l_sq; //!< èíäóêòèâíîñòü ñòàòîðà ïî îñè "q" ÑÄÏÌ, ìÃí
float pp; //!< ÷èñëî ïàð ïîëþñîâ
float j; //!< ìîìåíò èíåðöèè
float qep; //!< ÷èñëî ìåòîê ýíêîäåðà
float RatedPower; //!< íîìèíàëüíàÿ ìîùíîñòü (ñïðàâî÷íàÿ âåëè÷èíà, íå èñïîëüçóåòñÿ â ðàñ÷åòàõ)
float RatedSpeed; //!< íîìèíàëüíàÿ ñêîðîñòü (ñïðàâî÷íàÿ âåëè÷èíà, íå èñïîëüçóåòñÿ â ðàñ÷åòàõ)
float RatedCurrent; //!< íîìèíàëüíûé äåéñòâóþùèé òîê (ñïðàâî÷íàÿ âåëè÷èíà, íå èñïîëüçóåòñÿ â ðàñ÷åòàõ)
};
typedef volatile struct Ssm_param Tsm_param;
// !!! Âíèìàíèå! Ïîñëåäíèé íàáîð ïàðàìåòðîâ â ìàññèâå ÎÁÿÇÀÒÅËÜÍÎ äîëæåí áûòü íóëåâûì!
Tsm_param SMDATA[] = {\
// |r_f |l_f |l_m |If |psi_pm |r_s |l_sd |l_sq |pp |j |qep |Power |Speed |Current
{0, 0, 0, 0, 0.162056937, 0.38, 0.91, 0.91, 4, 0.00001032, 2500, 0.1, 3000, 4},\
{0, 0, 0, 0, 1.035363764, 21.62, 45.6, 53.7, 1, 0.000014, 1000, 0.145, 3000, 0.81},\
{0, 0, 0, 0, 1.035363764, 10.2, 27.8, 29.3, 1, 0.000028, 2500, 0.298, 3000, 1.3},\
{0, 0, 0, 0, 1.035363764, 5.66, 16.26, 19.42, 1, 0.000042, 3000, 0.425, 3000, 2.3},\
{0, 0, 0, 0, 0.241876025, 1.03, 0.82, 0.82, 1, 0.0000831, 5000, 0.4, 2680, 5.9},\
{0, 0, 0, 0, 0.130691078, 0.345, 0.273, 0.273, 1, 0.0000831, 10000, 0.4, 4960, 9.56},\
{0, 0, 0, 0, 0.118074271, 1.01, 0.448, 0.448, 1, 0.0000209, 5000, 0.25, 5490, 4.86},\
{0, 0, 0, 0, 0.064822775, 0.336, 0.149, 0.149, 1, 0.0000209, 2500, 0.25, 10000, 7.94},\
{0, 0, 0, 0, 1.035363764, 0.59, 6.85, 6.85, 3, 0.00678, 2000, 2.83, 3000, 6.3},\
{0, 0, 0, 0, 1.035363764, 6.5, 18, 20, 3, 0.00417, 3000, 1.7, 3000, 3.8},\
{0, 0, 0, 0, 0.051993267, 0.002, 0.125, 0.125, 1, 0.01, 9000, 93, 60000, 141},\
{0, 0, 0, 0, 0.414145505, 1.144, 5.3, 5.3, 2, 0.000153, 10000, 1.5, 6000, 4.5},\
{0, 0, 0, 0, 0.865211934, 0.129, 4.541, 7.424, 2, 0.1, 10000, 29.864, 3100, 60},\
{65, 10.21, 1.25, 2.4, 0, 0.129, 4.541, 7.424, 2, 0.1, 10000, 29.864, 3100, 60},\
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},\
};

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.
*/
// V_motorParams_SRM.h
//Файл с массивами параметров модели для различных вариантов ВИД
//структура с параметрами двигателя
struct Ssrm_param
{
float r_s; //!< сопротивление статора Swithed Reluctance Motor
float pp; //!< число пар полюсов (зубцов на роторе) Swithed Reluctance Motor
float j; //!< момент инерции
float qep; //!< число меток энкодера
float sk; //!< коэффициент датчика скорости Swithed Reluctance Motor
float RatedPower; //!< номинальная мощность (справочная величина, не используется в расчетах)
float RatedSpeed; //!< номинальная скорость (справочная величина, не используется в расчетах)
float RatedCurrent;//!< номинальный действующий ток
};
typedef volatile struct Ssrm_param Tsrm_param;
// !!! Внимание! Последний набор параметров в массиве ОБяЗАТЕЛЬНО должен быть нулевым!
Tsrm_param SRMDATA[] = {\
// |r_s |pp |j |qep |sk |p_n |n_n |i_n
{3, 4, 0.031, 4000, 14.323944878270580219199538703526, 8.5, 1500, 13},\
{2, 4, 0.04227273, 4000, 4.7746482927568600730665129011754, 12, 1500, 18},\
{1.5, 4, 0.062, 4000, 4.7746482927568600730665129011754, 15, 1500, 23},\
{1, 4, 0.10427273, 4000, 14.323944878270580219199538703526, 18, 1500, 27.5},\
{0.6, 4, 0.155, 4000, 4.7746482927568600730665129011754, 20, 1500, 30},\
{0.3, 8, 0.42272727, 4000, 14.323944878270580219199538703526, 27, 1000, 20.5},\
{0.1, 4, 1.104272727, 4000, 4.7746482927568600730665129011754, 57, 1500, 86.5},\
{0.05, 4, 1.155, 4000, 4.7746482927568600730665129011754, 60, 1000, 91},\
{0.03, 4, 2.211363636, 4000, 4.7746482927568600730665129011754, 120, 1500, 182},\
{0.02, 8, 3.31, 4000, 14.323944878270580219199538703526, 90, 1000, 70},\
{0, 0, 0, 0, 0, 0, 0, 0},\
};
//Структурка точки для кривой намагничивания (задается по точкам, с переменным шагом)
struct SFluxCurvePoint
{
float i; //ток
float psi; //потокосцепление
};
typedef volatile struct SFluxCurvePoint TFluxCurvePoint;
//Кривые намагничивания. Формат: {ток, потокосцепление}
//Согласованное положение
#define SRM_FLUX_CURVE_S {{0, 0}, {1.125, 0.45}, {2.25, 0.9}, {3.375, 1.35}, {4.5, 1.58}, {6.0, 1.7}, {7.5, 1.8}, {9.0, 1.89}, {10.5, 1.98}, {12.0, 2.06}, {13.5, 2.13}, {-1, -1}}
//Расоогласованное положение
#define SRM_FLUX_CURVE_R {{0, 0}, {1.35, 0.111}, {2.7, 0.221}, {4.05, 0.331}, {5.4, 0.44}, {6.75, 0.54}, {8.1, 0.648}, {9.45, 0.756}, {10.8, 0.863}, {12.15, 0.969}, {13.5, 1.075}, {-1, -1}}
#define SRD_SURFACE_RESOLUTION 100 //разрешение поверхностей момента от положения и потока M=f(theta,psi), потокосцепления от тока и положения psi=f(i,theta), тока от потокосцепления и положения i=f(psi,theta)
//ПРИМЕЧАНИЕ: задается число отрезков, т.е. число точек будет на 1 больше (например, 11 точек и 10 отрезков между ними), аналогично заданы разрешения других кривых и поверхностей
#define SRD_DELTA_THETA 0.01 //маленькое приращение углу для расчета момента SRD через разность коэнергий для соседних с текущим положений ротора
#define SRD_DELTA_THETA_INV 100.0 // 1/SRD_DELTA_THETA
TFluxCurvePoint Psi_I_s[] = SRM_FLUX_CURVE_S; //кривая намагничивания для согласованного положения (зуб-зуб, максимальная индуктивность)
TFluxCurvePoint Psi_I_r[] = SRM_FLUX_CURVE_R; //кривая намагничивания для рассогласованного положения (зуб-паз, миниимальная индуктивность)
float Psi_I_s_acc[SRD_SURFACE_RESOLUTION+1]; //кривая намагничивания для согласованного положения - уточненная, с постоянным шагом по току
float Psi_I_r_acc[SRD_SURFACE_RESOLUTION+1]; //кривая намагничивания для рассогласованного положения - уточненная, с постоянным шагом по току
float Psi_ITheta[SRD_SURFACE_RESOLUTION+1][SRD_SURFACE_RESOLUTION+1]; //Поверхность зависимости потокосцепления от тока и положения psi=f(i,theta)
float I_PsiTheta[SRD_SURFACE_RESOLUTION+1][SRD_SURFACE_RESOLUTION+1]; //Поверхность зависимости тока от потокосцепления и положения i=f(psi,theta)
float M_ITheta[SRD_SURFACE_RESOLUTION+1][SRD_SURFACE_RESOLUTION+1]; //поверхность зависимости момента одной фазы SRD от тока и положения M=f(i,theta)
float MotorModel_FluxCubicInterpolation (volatile float Isource, volatile TFluxCurvePoint SourceArray[], volatile int SourceResolution);

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_FORCE_LO
/*! \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
/*@}*/

101
Vinclude/V_TMU.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_TMU.h
\brief Ìîäóëü áëîêà òðèãîíîìåòðè÷åñêèõ ïðåîáðàçîâàíèé (ñì. TTMU, TTMUPark, TTMUIPark)
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 1.0 24/06/2019
\defgroup V_TMU
@{
*/
#ifndef V_TMU_H_
#define V_TMU_H_
typedef volatile struct STMUPark {
_iq ds, qs;
_iq ang;
_iq de, qe;
void (*calc)(volatile struct STMUPark*);
}TTMUPark;
typedef volatile struct STMUIPark {
_iq ds, qs;
_iq ang;
_iq de, qe;
void (*calc)(volatile struct STMUIPark*);
}TTMUIPark;
typedef volatile struct STMUCarToPol {
_iq x, y;
_iq r, phi;
void (*calc)(volatile struct STMUCarToPol*);
}TTMUCarToPol;
typedef volatile struct STMUPolToCar {
_iq x, y;
_iq r, phi;
void (*calc)(volatile struct STMUPolToCar*);
}TTMUPolToCar;
typedef volatile struct STMU {
_iq (*sin)(_iq);
_iq (*cos)(_iq);
_iq (*atan2)(_iq, _iq);
TTMUCarToPol carToPol;
TTMUPolToCar polToCar;
}TTMU;
void TMU_park_calc_IQ24PU (TTMUPark*);
void TMU_ipark_calc_IQ24PU (TTMUIPark*);
_iq TMU_sin_IQ24PU (_iq);
_iq TMU_cos_IQ24PU (_iq);
_iq TMU_atan2_IQ24PU (_iq, _iq);
void TMU_cartesianToPolar_calc_IQ24PU (TTMUCarToPol*);
void TMU_polarToCartesian_calc_IQ24PU (TTMUPolToCar*);
#define TMUPARK_DEFAULTS { 0, \
0, \
0, \
0, \
0, \
TMU_park_calc_IQ24PU }
#define TMUIPARK_DEFAULTS { 0, \
0, \
0, \
0, \
0, \
TMU_ipark_calc_IQ24PU }
#define TMUCARTOPOL_DEFAULTS {.calc = TMU_cartesianToPolar_calc_IQ24PU}
#define TMUPOLTOCAR_DEFAULTS {.calc = TMU_polarToCartesian_calc_IQ24PU}
#define TMU_DEFAULTS { .sin = TMU_sin_IQ24PU,\
.cos = TMU_cos_IQ24PU,\
.atan2 = TMU_atan2_IQ24PU,\
.carToPol = TMUCARTOPOL_DEFAULTS,\
.polToCar = TMUPOLTOCAR_DEFAULTS }
#endif /* V_TMU_H_ */
/*@}*/

113
Vinclude/V_UdControl.h Normal file
View File

@ -0,0 +1,113 @@
/*!
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_UdControl.h
\brief Ìîäóëü ïëàâíîãî çàðÿäà ÇÏÒ
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 1.0 25/08/2017
\addtogroup
@{*/
#ifndef V_UD_CONTROL_H
#define V_UD_CONTROL_H
#include "build.h"
#ifdef __cplusplus
extern "C" {
#endif
//! ñîñòîÿíèå âûêëþ÷åíî
#define UD_CONTROL_STATE_OFF 0
//! ñîñòîÿíèå îæèäàíèÿ âêëþ÷åíèÿ
#define UD_CONTROL_STATE_WAIT 1
//! ñîñòîÿíèå âêëþ÷åíî
#define UD_CONTROL_STATE_ON 2
#if defined (HW_MOTORCONTROLBOARD)
#define UD_CONTROL_OFF GPIOB->DATAOUTCLR = GPIO_PIN_14;
#define UD_CONTROL_ON GPIOB->DATAOUTSET = GPIO_PIN_14;
#else
#define UD_CONTROL_OFF // îïåðàöèÿ äëÿ âûêëþ÷åíèÿ
#define UD_CONTROL_ON // îïåðàöèÿ äëÿ âêëþ÷åíèÿ
#endif
/*! \class TUdControl
\brief Óïðàâëåíèå öåïüþ çàðÿäà çâåíà ïîñòîÿííîãî òîêà
Êëàññ \a TUdControl, îñíîâàííûé íà ñòðóêòóðå SUdControl, ñëóæèò
äëÿ óïðàâëåíèÿ äèñêðåòíûì âûõîäîì, êîòîðûé çàìûêàåò öåïü çàðÿäà
çâåíà ïîñòîÿííîãî òîêà. Ïåðåä âêëþ÷åíèåì ñëåäóþò òðè ïðîâåðêè:
âûäåðæêà òàéìàóòà, ïðåâûøåíèå íàïðÿæåíèÿ âûøå çàäàííîé óñòàâêè è
âûïîëàæèâàíèå êðèâîé íàïðÿæåíèÿ (ïðîèçâîäíàÿ ñòðåìèòñÿ ê íóëþ).
*/
//!ñì. TUdControl
struct SUdControl{
Uint16 Enabled;
int fault_start; //!<ïîïûòêà ïóñêà ïðè íåçàøóíòèðîâàííîì ðåëå
int state; //!<ñîñòîÿíèå
int state_shadow;//!< ñîñòîÿíèå òåíåâîå
int state_prev;//!<ñîñòîÿíèå ïðåäûäóùåå
int E;//!<ôëàã ïåðâîãî âõîæäåíèÿ
int StateCounter;//!<ñ÷åò÷èê âðåìåíè íàõîæäåíèÿ â ñîñòîÿíèè
long fUdc_output_prev;//!<çíà÷åíèÿ íàïðÿæåíèÿ ïðåäûäóùåå
long U_on;//!<íàïðÿæåíèå âêëþ÷åíèÿ
long U_off;//!<íàïðÿæåíèå âûêëþ÷åíèÿ
long Timeout_on;//!<òàéìàóò âêëþ÷åíèÿ â ìñ.
long deriv_time_ZPT; //!<ïðîèçâîäíàÿ ïî íàïðÿæåíèþ íà ìèëëèñåêóíäå
long deriv_const; //!<êîíñòàíòà óñòàâêè ñðàâíåíèÿ ïðîèçâîäíîé
int StateOn;//!<äâîè÷íîå ñîñòîÿíèå: âêëþ÷åí/íå âêëþ÷åí
TFilter fUdc;//!<ôèëüòð íàïðÿæåíèÿ íà ÇÏÒ
Uint16 ExternCheckKey;//!<Âõîä áëîê-êîíòàêòà
Uint16 ExternCheckKeyEnabled;//!<Íàäî ëè àíàëèçèðîâàòü áëîê-êîíòàêòà
void (*init)(volatile struct SUdControl*);
void (*calc)(volatile struct SUdControl*);
};
typedef volatile struct SUdControl TUdControl;
//! \memberof TUdControl
void UdControl_init(TUdControl*);
//! \memberof TUdControl
void UdControl_calc(TUdControl*);
#define UD_CONTROL_DEFAULTS {0,0,UD_CONTROL_STATE_OFF,UD_CONTROL_STATE_OFF,UD_CONTROL_STATE_OFF,\
0,0,0,\
_IQ(0.8),_IQ(0.5),3000,0,\
0,0, FILTER_DEFAULTS,\
0,0,\
UdControl_init,\
UdControl_calc}
#ifdef __cplusplus
}
#endif
#endif
/*@}*/

162
Vinclude/V_UserMemory.h Normal file
View File

@ -0,0 +1,162 @@
/*!
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 Ðàáîòà ñ ýíåðãîíåçàâèñèìîé ïàìÿòüþ 1921BK028 (ñì. TUserMemory)
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 2.0 20/03/2019
\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
//Ïîëüçîâàòåëüñêóþ ïàìÿòü íå ðåêîìåíäóåòñÿ ðàçìåøàòü â òîé æå îáëàñòè, ãäå íàõîäèòñÿ îñíîâíàÿ ïðîãðàììà.
//Òàê êàê, åñëè èñïîëíÿòüñÿ èç BFlash è ïîäàòü êîìàíäó çàïèñè/ñòèðàíèÿ NVR ÿ÷åéêè òîé æå BFlash, òî ïðîèçîéäåò ïðèîñòàíîâêà
//ðàáîòû ÿäðà íà âðåìÿ çàïèñè/ñòèðàíèÿ. Ïîòîìó ÷òî ýòî îäèí ôèçè÷åñêèé áëîê, è îí ìîæåò ðàáîòàòü òîëüêî ëèáî ñ îñíîâíûì
//ìàññèâîì flash èëè ñ ìàññèâîì NVR flash
//#define NVR_MAIN_FLASH //ðàçìåùàòü ïîëüçîâàòåëüñêèå äàííûå â NVR îñíîâíîé ïàìÿòè
#define NVR_BOOT_FLASH //ðàçìåùàòü ïîëüçîâàòåëüñêèå äàííûå â NVR çàãðóçî÷íîé ïàìÿòè
#define USERMEMORY_USERFLASH_KEY 0xC0DE0100 // Êëþ÷ 0xC0DE0000 + áèò NVRON
#define USERMEMORY_MAX_WAITCLOCKS 2000000L
#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
#ifdef NVR_MAIN_FLASH
#define USERMEMORY_PAGE_SIZE MEM_MFLASH_PAGE_SIZE
#define NVRFLASH MFLASH
#define NUMBER_OF_BYTE_ON_PAGE 64
#define NUMBER_OF_32BIT_WORDS_AT_ONCE 16
#define PAGE_SIZE_LOG2 MEM_MFLASH_PAGE_SIZE_LOG2
#endif
#ifdef NVR_BOOT_FLASH
#define USERMEMORY_PAGE_SIZE MEM_BFLASH_PAGE_SIZE
#define NVRFLASH BFLASH
#define NUMBER_OF_BYTE_ON_PAGE 16
#define NUMBER_OF_32BIT_WORDS_AT_ONCE 4
#define PAGE_SIZE_LOG2 MEM_BFLASH_PAGE_SIZE_LOG2
#endif
#define USERMEMORY_CMD_READ (1<<0)
#define USERMEMORY_CMD_WRITE (1<<1)
#define USERMEMORY_CMD_PAGE_ERASE (1<<2)
#define USERMEMORY_CMD_FULL_ERASE (3<<2) // áèò ERASESEC + áèò ALLSEC
#define USERMEMORY_NVRON_BIT (1 << 8)
struct SUserMemory {
Uint16 MemStartAddr; //!Àäðåñ íà flash
Uint8 *MCUStartAddr8; //!àäðåñ íà ìàññèâ ñ äàííûìè êàê áàéòîâûé óêàçàòåëü
Uint16 *MCUStartAddr; //!àäðåñ íà ìàññèâ ñ äàííûìè
Uint16 data_length; //!äëèíà äàííûõ
int16 receivedCode; //!Ñòàòóñ îïåðàöèè
Uint32 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 {\
.init = USERMEMORY_Init, \
.write = USERMEMORY_Write,\
.read = USERMEMORY_Read,\
.full_erase = USERMEMORY_Full_Erase,\
.flush = USERMEMORY_Flush,\
.ms_calc = USERMEMORY_ms_calc,\
.slow_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
/*@}*/

163
Vinclude/V_adc.h Normal file
View File

@ -0,0 +1,163 @@
/*!
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;
int32 IC_temp;
int16 ICSampleLength; //äëèíà âûáîðêè (êîë-âî òî÷åê íà ïåðèîäå ØÈÌ)
int16 ICPointer; //íîìåð ïîñëåäíåé âûáîðêè
int16 ICBuf[4]; //ìàññèâ òî÷åê äëÿ óñðåäíåíèÿ
int16 Imeas_d_gain;
int16 Imeas_d_offset;
int32 Imeas_d;
int32 IdGainNom;
int16 ID_temp;
int16 IDSampleLength; //äëèíà âûáîðêè (êîë-âî òî÷åê íà ïåðèîäå ØÈÌ)
int16 IDPointer; //íîìåð ïîñëåäíåé âûáîðêè
int16 IDBuf[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; //!<Âðåìåííàÿ ïåðåìåííàÿ
int16 ref_meas_gain;
int16 ref_meas_offset;
int32 ref_meas;
int32 refGainNom;
int16 ref_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}, \
54,0,0,0,0, \
4,0,{0}, \
800,0,0,0,0, \
4,0,{0}, \
100,0,0,0, \
54,0,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*);
#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
/*@}*/

225
Vinclude/V_data_log.h Normal file
View File

@ -0,0 +1,225 @@
/*!
\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
{
Uint32 update_sample_rate; //
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 { 10000, {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 { 10000, {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
/*@}*/

53
Vinclude/V_led.h Normal file
View File

@ -0,0 +1,53 @@
/*!
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"
struct Sled;
typedef volatile struct Sled Tled;
struct Sled{
Uint16 timerRunLed, timerFaultLed;
Uint16 prdRunLed, prdFaultLed;
Uint16 mode3counter;
void (*init)(Tled*);
void (*msCalc)(Tled*);
};
#define LED_DEFAULTS {.init = LED_init,\
.msCalc = LED_msCalc}
void LED_init (Tled*);
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
/*@}*/

152
Vinclude/build.h Normal file
View File

@ -0,0 +1,152 @@
/*!
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
@{
*/
//Âûáîð òèïà àïïàðàòíîé ÷àñòè
//VectorCARD ñ îòëàäî÷íûì êîìïëåêòîì DRV8301
//#define HW_VECTORCARD_DRV8301_EVM
//VectorCARD ñ îòëàäî÷íûì êîìïëåêòîì DRV8312
//#define HW_VECTORCARD_DRV8312_EVM
//VectorCARD ñ èìèòàöèîííûìè ìîäåëÿìè äâèãàòåëåé
//#define HW_VECTORCARD_SIMULATOR
//Îòëàäî÷íàÿ ïëàòà ÍÈÈÝÒ ñ èìèòàöèîííûìè ìîäåëÿìè äâèãàòåëåé
//#define HW_NIIET_BOARD_SIMULATOR
//Êîíòðîëëåð ÌÊ40.4 ÍÏÔ ÂÅÊÒÎÐ
//#define HW_VECTOR_MK_40_4
//Êîíòðîëëåð Motor Control Board
#define HW_MOTORCONTROLBOARD
//Äëÿ UART, âûáèðàåòñÿ ÷åì åãî çàíÿòü - MODBUS èëè CANtoRS äðàéâåðîì
//#define MODBUS_ENA
#define CANTORS_ENA
// Òàêæå ìîæíî çàäåéñòâîâàòü USB äëÿ CANopen
//#define CANTOUSB_ENA
//Âûáîð òèïà òðèãîíîìåòðè÷åñêèõ îïåðàöèé äëÿ ïðåîáðàçîâàíèé Park è iPark - àïïàðàòíî ÷åðåç áëîê TMU èëè ïðîãðàììíî ñ ïîìîùüþ áèáëèîòåêè IQMath
#define PARK_IPARK_TMU
//#define PARK_IPARK_IQMATH
//!Ðåæèìû ðàáîòû (ñîñòîÿíèÿ ÄÀ 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_RUN_VECTOR_IM_ENCODER_POS 60
//! Ðåæèì êàëèáðîâêè äàò÷èêà ïîëîæåíèÿ
#define CTRL_AUTO_SENSOR_TUNING 29
//! Ñòðóêòóðà óïðàâëåíèÿ äâèãàòåëåì ïîñòîÿííîãî òîêà áåç êîíòóðîâ: çàäàíèå íàïðÿæåíèÿ íà îáìîòêè
#define CTRL_DC_DRIVE 35
//! Ñòðóêòóðà óïðàâëåíèÿ äâèãàòåëåì ïîñòîÿííîãî òîêà ñ êîíòóðîì òîêà è ñêîðîñòè
#define CTRL_DC_DRIVE_FB 36
//! Ðåæèì àâòîêîììóòàöèè äëÿ SRM
#define CTRL_RUN_SRM_AUTOCOMMUTATION 101
//Ôëàãè àâàðèé äëÿ ìîäóëÿ çàùèò
//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_CTRL_HI_TEMP 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_RELAY_START 0x2000
#define F_PROGRAM_IS_ON_BFLASH 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_PDP_SWITCH_A0 0x1000
#define F_PDP_SWITCH_A1 0x2000
#define F_PDP_SWITCH_A2 0x4000
#define F_PDP_SWITCH_LOWER 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)
#if (!defined(HW_VECTORCARD_DRV8301_EVM)) && (!defined(HW_VECTORCARD_DRV8312_EVM)) && (!defined(HW_VECTORCARD_SIMULATOR))\
&& (!defined(HW_NIIET_BOARD_SIMULATOR)) && (!defined(HW_VECTOR_MK_40_4)) && (!defined(HW_MOTORCONTROLBOARD))
#error íåîáõîäèìî îïðåäåëèòü õîòÿ áû îäíó âåðñèþ àïïàðàòíîé ÷àñòè
#endif
/*@}*/

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
/*@}*/

227
Vinclude/main.h Normal file
View File

@ -0,0 +1,227 @@
/*!
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 "DRV8301_SPI.h"
#include "V_AutoOffset.h"
#include "V_CANtoRS.h"
#include "V_SSI_Encoder.h"
#include "V_MotorModel.h"
#include "V_UserMemory.h"
#include "V_rotor_observer.h"
#include "V_relay_reg.h"
#include "V_ModBus.h"
#include "V_MBVarsConv.h"
#include "V_excitation.h"
#include "X_CANFlashProgData.h"
#include "X_CANFlashProgStarter.h"
#include "CANBlockTransferInterface.h"
#include "DRV_INTERFACE.h"
#include "V_event_log.h"
#include "Global_time.h"
#include "V_UdControl.h"
#include "V_DIO.h"
#include "V_fifo.h"
#include "V_usblib.h"
#include "V_Fan.h"
#include "V_watchdog.h"
#include "V_TMU.h"
extern TClarke clarke;
#if defined (PARK_IPARK_IQMATH)
extern TPark park;
extern TIPark ipark;
#elif defined (PARK_IPARK_TMU)
extern TTMUPark park;
extern TTMUIPark ipark;
#endif
extern TPidReg3 pid_id;
extern TPidReg3 pid_iq;
extern TPidReg3 pid_ia;
extern TPidReg3 pid_spd;
extern TPidReg3_pos pid_pos;
extern TRelayReg i_a_reg;
extern TRelayReg i_b_reg;
extern TRelayReg i_c_reg;
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 TMotorModel model;
extern Tmotor motor;
extern TRotorObserver RotorObserver;
extern TCANtoRS CANtoRS;
extern TModBus ModBus;
extern TMBVarsConv MBVarsConv;
extern Texcitation pwm_ex;
extern TDrvInterface drv_interface;
extern TLogger FaultLog;
extern TGlobalTime global_time;
extern TUdControl udControl;
extern TFanControl FanControl;
extern TTMU tmu;
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 Tdrv8301interface drv8301;
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);
// Îáúÿâëåíèå 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
// Ôóíêöèÿ îãðàíè÷åíèÿ ïåðåìåííîé
inline float __fsat (float input, float max, float min) {
if (input > max) return max;
else if (input < min) return min;
else return input;
}
#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)(volatile struct SPark*);//!< Pointer to calculation function
};
typedef volatile struct SPark TPark;
//! èíèöèàëèçàòîð ïî-óìîë÷àíèþ
#define PARK_DEFAULTS { 0, \
0, \
0, \
0, \
0, \
park_calc }
//! \memberof TPark
void park_calc(TPark*);
#ifdef __cplusplus
}
#endif
#endif
/*@}*/

View File

@ -0,0 +1,250 @@
/* ==================================================================================
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: CANBlockTransferInterface.c
//
//Originator: Aliamkin Dmitry I
//
//Description: âñå âçàèìîäåéñòâèÿ ñ áëî÷íîé ïåðåäà÷åé ïî CAN îñóùåñòâëÿþòñÿ
â ÄÀ äàííîãî ôàéëà
//ÏÐÈÌÅ×ÀÍÈÅ:
//=====================================================================================
//-------------------------------------------------------------------------------------
01.09.2016 Release Rev 1.05
Ñòýéò CAN ïðîøèâàòîðà ÷àñòè÷íî ïåðåíåñåí â ôîí äëÿ ïðàâèëüíîãî ïåðåõîäà â äðóãîé ïðîåêò (àêòóàëüíî äëÿ M4F)
20.09.2012 Release Rev 1.04
Äîáàâèë àâòîìàòè÷åñêîå îñâîáîæäåíèå èíåòðïðåòàòîðà ïðè ïðîñòîå â CANBT_INTERFACE_BUSY áîëåå 5 ñåêóíä
20.09.2012 Release Rev 1.03
Ïðàâèëüíåå ñäåëàí âûõîä èç ñîñòîÿíèÿ CANBT_INTERFACE_DATALOG
19.09.2012 Release Rev 1.02
Äîáàâëåíà ïîääåðæêà ñêà÷êè êàíàëîâ äàòàëîããåðà ÷åðåç áëî÷íóþ ïåðåäà÷ó
// 26.12.2011 Release Rev 1.01
//----------------------------------------------------------------------------------*/
#include "DSP.h"
#include "main.h"
#include "co_ODvars.h"
#include "CANOpen_drv.h"
#include "CANBlockTransferInterface.h"
void SMCanBTInterface_ms(volatile struct SCanBTInterface* p, Uint32 time, TCo_OdVars* co_ptr)
{
//îòäåëüíóþ ôóíêöèþ äëÿ èíèöèàëèçàöèè íå äåëàåì, ò.ê. íåèçâåñòíî, ÷òî ïîëüçîâàòåëü ðàíüøå âûçîâåò
//èíèò CANOpen-à èëè äàííîãî ìîäóëÿ, ÷òî äåëàåò ïîâåäåíèå àâòîìàòà íåïðåäñêàçóåìûì èç-çà òîãî, ÷òî
//â SPI ìîæåò áûòü ÷òî-òî ñîõðàíåíî (íàïðèìåð ïðîæèã ïî CAN :))
if(p->alreadyInit == 0)
{
co_ptr->co_blockTransferCommand = CANBT_INTERFACE_FREE;
p->time_prev = time;
p->alreadyInit = 1;
}
//ñ÷èòàåì äèñêðåòíûé àâòîìàò
p->state_shadow = co_ptr->co_blockTransferCommand; //êîïèðóåì ïåðåìåííóþ ñîñòîÿíèÿ, òàê êàê state ìîæåò áûòü èçìåíåí èçâíå âíåçàïíî
//äàëåå âñ¸ àíàëèçèðóåì ïî state_shadow
if (p->state_prev!=p->state_shadow)
{
p->E=1;//ôëàã ïåðâîãî âõîæäåíèÿ (E - ENTRY)
p->state_time = 0;
}
else
p->E=0;
p->state_prev=p->state_shadow;
//âðåìÿ íàõîæäåíèÿ â òåêóùåì ñîñòîÿíèè
p->state_time += p->time_prev - time;
p->time_prev = time;
switch (p->state_shadow)//â çàâèñèìîñòè îò ñîñòîÿíèÿ:
{
case CANBT_INTERFACE_FREE:
{
if (p->E)
{
//ENTRY
}
break;
}
case CANBT_INTERFACE_BUSY:
{
if (p->E)
{
//ENTRY
}
//åñëè íàõîäèìñÿ â çàíÿòîì ñîñòîÿíèè ñëèøêîì äîëãî, çíà÷èò êòî òî ïðîñòî çàáûë î÷èñòèòü èíåòðïåðòàòîð
if(p->state_time > (150000*5000)) //5 ñåêóíä
co_ptr->co_blockTransferCommand = CANBT_INTERFACE_FREE;
break;
}
case CANBT_INTERFACE_FLASH_PROG:
{//êåéç â ìñ íóæåí ÷òîáû íå ïîïàäàòü â äàííîì ñâè÷å â default:
if (p->E)
{
//ENTRY
}
//îñòàíàâëèâàåì óïðàâëåíèå êëþ÷àìè
FP_BLOCK_PWM;
//ïîïóòíî íåïðåðûâíî ñáðàñûâàåì sm_ctrl è âûñòàâëÿåì àâàðèþ, ÷òîá óæ íàâåðíÿêà âñå ñòîÿëî
FP_CTRL_STOP;
FP_FAULT_SET;
//ïåðåõîä â ïðîøèâàëüùèê áóäåò âûïîëíåí â ñëîó êàëêå.
break;
}
case CANBT_INTERFACE_DATALOG1:
{
if (p->E)
{
// Êîïèðóåì äàííûå èç ìàññèâà îñöèëëîãðàììû â ìàññèâ äëÿ îòïðàâêè ñî ñìåùåíèåì.
#if DLOG_DATA_SIZE == 16
//DINT;
//Uint32 t0 = CpuTimer2Regs.TIM.all;
/*
// 'memcpy' êîïèðóåò 16-áèòíûìè ñëîâàìè, ÷òî ïîçâîëÿåò èñïîëüçîâàòü è íå÷¸òíûå çíà÷åíèÿ
// 'dlog.first_point_written', íî ýòî ðàáîòàåò ìåäëåííåå, ÷åì âàðèàíò ñ öèêëîì 'for'
// (ñì. íèæå) ãäå êîïèðóþòñÿ 32-áèòíûå ñëîâà.
size_t n = 256 - dlog.first_point_written;
memcpy((void*)&dlog.upload_buff[0],
(void*)&dlog.buff[dlog.first_point_written + (dlog.buff_num << 8)], n);
memcpy((void*)&dlog.upload_buff[n],
(void*)&dlog.buff[dlog.buff_num << 8], dlog.first_point_written);
//Uint32 t1 = t0 - CpuTimer2Regs.TIM.all;
*/
//t0 = CpuTimer2Regs.TIM.all;
Uint32* CopyPtrFrom = (Uint32*)(&dlog.buff[dlog.first_point_written + (dlog.buff_num << 8)]);
Uint32* CopyPtrTo = (Uint32*)(&dlog.upload_buff[0]);
for (register int i = 128 - (dlog.first_point_written >> 1); i > 0; i--)
*CopyPtrTo++ = *CopyPtrFrom++;
CopyPtrFrom = (Uint32*)(&dlog.buff[dlog.buff_num << 8]); //óêàçàòåëü ìàññèâà-èñòî÷íèêà ïåðåíîñèì íà íà÷àëî, äëÿ ìàññèâà-ïðèåìíèêà îí è òàê, ãäå íàäî
for (register int i = dlog.first_point_written >> 1; i > 0; i--)
*CopyPtrTo++ = *CopyPtrFrom++;
//Uint32 t2 = t0 - CpuTimer2Regs.TIM.all;
//EINT;
#endif
#if DLOG_DATA_SIZE == 32
//DINT;
//Uint32 t0 = CpuTimer2Regs.TIM.all;
Uint32* CopyPtrFrom = (Uint32*)(&dlog.buff[dlog.first_point_written + (dlog.buff_num << 8)]);
Uint32* CopyPtrTo = (Uint32*)(&dlog.upload_buff[0]);
for (register int i = 256 - dlog.first_point_written; i > 0; i--)
*CopyPtrTo++ = *CopyPtrFrom++;
CopyPtrFrom = (Uint32*)(&dlog.buff[dlog.buff_num << 8]);
for (register int i = dlog.first_point_written; i > 0; i--)
*CopyPtrTo++ = *CopyPtrFrom++;
//Uint32 t1 = t0 - CpuTimer2Regs.TIM.all;
//EINT;
#endif
CANBlockTransferInitTX(co_ptr, 256, (Uint16*)&dlog.upload_buff[0]);
}
// Åñëè ÄÀ áëî÷íîé ïåðåäà÷è îñâîáîäèëñÿ, îñâîáîæäàåì è èíòåðôåéñ.
if (co_ptr->BT->tx_status != CANBT_STATUS_BUSY)
{
co_ptr->co_blockTransferCommand = CANBT_INTERFACE_FREE;
}
break;
}
#if DLOG_DATA_SIZE == 32
case CANBT_INTERFACE_DATALOG2:
{
if (p->E)
{
// Èíèöèèðóåì ïåðåäà÷ó âòîðîé ïîëîâèíû áóôåðà äàòàëîããåðà.
CANBlockTransferInitTX(co_ptr, 256, (Uint16*)&dlog.upload_buff[128]);
}
// Åñëè ÄÀ áëî÷íîé ïåðåäà÷è îñâîáîäèëñÿ, îñâîáîæäàåì è èíòåðôåéñ.
if (co_ptr->BT->tx_status != CANBT_STATUS_BUSY)
{
co_ptr->co_blockTransferCommand = CANBT_INTERFACE_FREE;
}
break;
}
#endif
default:
co_ptr->co_blockTransferCommand = CANBT_INTERFACE_FREE;
}
}
void SMCanBTInterface_slow(volatile struct SCanBTInterface* p)
{
//ñ÷èòàåì äèñêðåòíûé àâòîìàò
switch (p->state_shadow)//â çàâèñèìîñòè îò ñîñòîßíèß:
{
case CANBT_INTERFACE_FLASH_PROG:
{
if (p->E)
{
//ENTRY
}
//îñòàíàâëèâàåì óïðàâëåíèå êëþ÷àìè
FP_BLOCK_PWM;
//ïîïóòíî íåïðåðûâíî ñáðàñûâàåì sm_ctrl è âûñòàâëßåì àâàðèþ, ÷òîá óæ íàâåðíßêà âñå ñòîßëî
FP_CTRL_STOP;
FP_FAULT_SET;
//æäåì ìàëåíüêî (100ìñ), ÷òîá âñå ÄÀ îäóïëèëèñü è èäåì â ïðîæèã
if(p->state_time > (150000*100))
StartFlashProgrammer();
break;
}
}
}
//êîëáýê äëÿ áëî÷íîé ïåðåäà÷è îïèñàí òóò, ÷òîáû èçáàâèòü ïîëüçîâàòåëÿ îò íèõ
void callback_BTcmd(Uint16 par, Uint16 tag_CANnum)
{
#ifdef CAN_1_ENABLE
if(tag_CANnum == 1)
{
if(par==0)
{
if(co1_vars.co_blockTransferCommand == 0)
co1_vars.co_blockTransferCommand = 0x8000;
}
if(par==1)
{
if(co1_vars.co_blockTransferCommand == 1)
{ //ïî 1-ìó CANó õîòÿò ïðîøèâàòüñÿ, îòðàçèì ýòî â íàñòðîéêàõ ïðîøèâàëüùèêà
FPsettings.CANa_enable = 1;
FPsettings.CANb_enable = 0;
}
}
}
#endif
#ifdef CAN_2_ENABLE
if(tag_CANnum == 2)
{
if(par==0)
{
if(co2_vars.co_blockTransferCommand == 0)
co2_vars.co_blockTransferCommand = 0x8000;
}
if(par==1)
{
if(co2_vars.co_blockTransferCommand == 1)
{ //ïî 2-ìó CANó õîòÿò ïðîøèâàòüñÿ, îòðàçèì ýòî â íàñòðîéêàõ ïðîøèâàëüùèêà
FPsettings.CANb_enable = 1;
FPsettings.CANa_enable = 0;
}
}
}
#endif
}

406
Vsrc/CANOpenUDfuncs.c Normal file
View File

@ -0,0 +1,406 @@
/* ==================================================================================
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()
{
#ifdef HW_MOTORCONTROLBOARD
// CAN0: C12 / C13
GPIOC->ALTFUNCNUM1_bit.PIN12 = 1; // CAN0_TX
GPIOC->ALTFUNCNUM1_bit.PIN13 = 1; // CAN0_RX
GPIOC->ALTFUNCSET = GPIO_PIN_12 | GPIO_PIN_13;
#endif
#ifdef HW_VECTORCARD_SIMULATOR
// CAN0: C12 / C13
GPIOC->ALTFUNCNUM1_bit.PIN12 = 1; // CAN0_TX
GPIOC->ALTFUNCNUM1_bit.PIN13 = 1; // CAN0_RX
GPIOC->ALTFUNCSET = GPIO_PIN_12 | GPIO_PIN_13;
#endif
}
#endif //CAN_1_ENABLE
//ôóíêöèÿ èíèöèàëèçàöèè Gpio CAN2
#ifdef CAN_2_ENABLE
void co_CAN2GpioInit()
{
#ifdef HW_MOTORCONTROLBOARD
// CAN1: C14 / C15
GPIOC->ALTFUNCNUM1_bit.PIN14 = 1; // CAN0_TX
GPIOC->ALTFUNCNUM1_bit.PIN15 = 1; // CAN0_RX
GPIOC->ALTFUNCSET = GPIO_PIN_14 | GPIO_PIN_15;
#endif
#ifdef HW_VECTORCARD_SIMULATOR
// CAN1: C14 / C15
GPIOC->ALTFUNCNUM1_bit.PIN14 = 1; // CAN0_TX
GPIOC->ALTFUNCNUM1_bit.PIN15 = 1; // CAN0_RX
GPIOC->ALTFUNCSET = GPIO_PIN_14 | GPIO_PIN_15;
#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
}

195
Vsrc/DRV8301_SPI.c Normal file
View File

@ -0,0 +1,195 @@
/*!
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 DRV8301_SPI.c
\brief Äðàéâåð äëÿ äðàéâåðà êëþ÷åé èíâåðòîðà DRV8301
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 2.0 25/03/2016
\addtogroup drv8301interface
@{
*/
#include "DSP.h"
#include "main.h"
void DRV8301_Interface_Init(Tdrv8301interface*p) {
#ifdef HW_VECTORCARD_DRV8301_EVM
volatile long delay;
volatile Uint32 tempREG;
// Íàñòðîéêà íîã SPI
NT_GPIOC->ALTFUNCSET = (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11);
NT_COMMON_REG->GPIOPCTLC_bit.PIN8 = 1;
NT_COMMON_REG->GPIOPCTLC_bit.PIN9 = 1;
NT_COMMON_REG->GPIOPCTLC_bit.PIN10 = 1;
NT_COMMON_REG->GPIOPCTLC_bit.PIN11 = 1;
// Íàñòðîéêà òàêòèðîâàíèÿ 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 ÌÃö ñäåëàåì
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) )
NT_SPI0->SPI_CR1 = 0;// Ðåæèì - ìàñòåð, LoopBack îòêëþ÷¸í, ñàì ìîäóëü SSP òîæå îòêëþ÷¸í
NT_SPI0->SPI_IMSC = 0x0; // Çàïðåòèòü âñå ïðåðûâàíèÿ
NT_SPI0->SPI_DMACR = 0; // Çàïðåòèòü DMA
NT_SPI0->SPI_ICR = 0x3; // Î÷èñòêà ïðåðûâàíèé ("ïåðåïîëíåíèå FIFO ïðè¸ìà" è "íåîáñëóæåííîå FIFO ïðè¸ìà")
NT_SPI0->SPI_CPSR = 4; // Äåëåíèå âõîäíîé ÷àñòîòû íà 4 -> 6,25 MHz
NT_SPI0->SPI_CR0_bit.DSS = 0xF; // Ðàçìåð äàííûõ - 16 áèò
NT_SPI0->SPI_CR0_bit.SCR = 0x3F; // Âòîðîé äåëèòåëü = 15 -> f_SPI = 416 kHz
NT_SPI0->SPI_CR0_bit.FRF = 0x0; // Êàêàÿ-òî "ôàçà" äëÿ ïðîòîêîëà Motorola SPI
NT_SPI0->SPI_CR0_bit.SPH = 0x1; // Êàêàÿ-òî "ïîëÿðíîñòü" äëÿ ïðîòîêîëà Motorola SPI
NT_SPI0->SPI_CR0_bit.SPO = 0x0; // Âûáîð ôîðìàòà êàäðà Motorola/TI/Microwire. "0" - ïî ïðîòîêîëó Motorola SPI
NT_SPI0->SPI_CR1_bit.SSE = 1; // Ðàçðåøèòü ðàáîòó
// Íàñòðîéêà íîã äëÿ ïðè¸ìà àâàðèé îò DRV8301: Ñ4 - Fault, C5 - OCTW
NT_GPIOC->ALTFUNCCLR = (1 << 4) | (1 << 5);
NT_GPIOC->OUTENCLR = (1 << 4) | (1 << 5);
// Íàñòðîéêà íîãè äëÿ âêëþ÷åíèÿ DRV8301: G8 - EN_GATE
NT_GPIOG->ALTFUNCCLR = (1 << 8);
NT_GPIOG->OUTENSET |= (1 << 8); //÷åðåç ÈËÈ, ÷òîáû íå ïîïîðòèòü îñòàëüíûå íîã ïîðòà G
NT_GPIOG->DATA |= (1 << 8); //DATA.bit.GPIO8 = 1
// Âûæäàòü 10 ìñ ïåðåä íàñòðîéêîé
delay = 10000000;
while (delay > 0)
delay--;
// Íàñòðîéêà ñàìîãî DRV8301
p->CTRL1.bit.GATE_CURRENT = 0; // full current 1.7A
// p->CTRL1.bit.GATE_CURRENT = 1; // med current 0.7A
// p->CTRL1.bit.GATE_CURRENT = 2; // min current 0.25A
p->CTRL1.bit.GATE_RESET = 0; // Normal Mode
p->CTRL1.bit.PWM_MODE = 0; // six independant PWMs
// p->CTRL1.bit.OC_MODE = 0; // current limiting when OC detected
p->CTRL1.bit.OC_MODE = 1; // latched OC shutdown
// p->CTRL1.bit.OC_MODE = 2; // Report on OCTWn pin and SPI reg only, no shut-down
// p->CTRL1.bit.OC_MODE = 3; // OC protection disabled
// p->CTRL1.bit.OC_ADJ_SET = 0; // OC @ Vds=0.060V
// p->CTRL1.bit.OC_ADJ_SET = 4; // OC @ Vds=0.097V
// p->CTRL1.bit.OC_ADJ_SET = 6; // OC @ Vds=0.123V
// p->CTRL1.bit.OC_ADJ_SET = 9; // OC @ Vds=0.175V
p->CTRL1.bit.OC_ADJ_SET = 15; // OC @ Vds=0.358V
// p->CTRL1.bit.OC_ADJ_SET = 16; // OC @ Vds=0.403V
// p->CTRL1.bit.OC_ADJ_SET = 17; // OC @ Vds=0.454V
// p->CTRL1.bit.OC_ADJ_SET = 18; // OC @ Vds=0.511V
p->CTRL1.bit.Reserved = 0;
// p->CTRL2.bit.OCTW_SET = 0; // report OT and OC
p->CTRL2.bit.OCTW_SET = 1; // report OT only
// p->CTRL2.bit.GAIN = 0; // CS amplifier gain = 10
p->CTRL2.bit.GAIN = 1; // CS amplifier gain = 20
// p->CTRL2.bit.GAIN = 2; // CS amplifier gain = 40
// p->CTRL2.bit.GAIN = 3; // CS amplifier gain = 80
p->CTRL2.bit.DC_CAL_CH1 = 0; // not in CS calibrate mode
p->CTRL2.bit.DC_CAL_CH2 = 0; // not in CS calibrate mode
p->CTRL2.bit.OC_TOFF = 0; // normal mode
p->CTRL2.bit.Reserved = 0;
// Çàïèøåì
p->write(p, CNTRL_REG_1_ADDR);
p->write(p, CNTRL_REG_2_ADDR);
p->read(p);
#endif
}
void DRV8301_Interface_Write(Tdrv8301interface*p, Uint16 reg) {
#ifdef HW_VECTORCARD_DRV8301_EVM
Uint16 trash;
p->writeWord.bit.R_W = 0; //we are initiating a write
p->writeWord.bit.ADDRESS = reg; //load the address
if (reg == CNTRL_REG_1_ADDR)
p->writeWord.bit.DATA = p->CTRL1.all; //data to be written;
else
p->writeWord.bit.DATA = p->CTRL2.all;
NT_SPI0->SPI_DR = p->writeWord.all; //send out the data
while (NT_SPI0->SPI_SR_bit.BSY == 1)
; //wait for the packet to complete
trash = NT_SPI0->SPI_DR;//read returned value of Status Register 1 and clear the INT_FLAG bit
#endif
}
void DRV8301_Interface_Read(Tdrv8301interface*p) {
#ifdef HW_VECTORCARD_DRV8301_EVM
Uint16 trash;
// Ñíà÷àëà ãîâîðèì, ÷òî õîòèì ÷èòàòü ïåðâûé ðåãèñòð
p->writeWord.bit.R_W = 1; //we are initiating a read
p->writeWord.bit.ADDRESS = STAT_REG_1_ADDR; //load the address
p->writeWord.bit.DATA = 0; //dummy data;
NT_SPI0->SPI_DR = p->writeWord.all; //send out the data
while (NT_SPI0->SPI_SR_bit.BSY == 1)
; //wait for the packet to complete
// Â ýòî âðåìÿ DRV íàì ïðèñëàë ìóñîð (õîòÿ ýòî íå ñîâñåì òàê)
trash = NT_SPI0->SPI_DR; //dummy read to clear the INT_FLAG bit
// Òåïåðü ãîâîðèì, ÷òî ïî÷èòàåì âòîðîé ðåãèñòð
p->writeWord.bit.R_W = 1; //we are initiating a read
p->writeWord.bit.ADDRESS = STAT_REG_2_ADDR; //load the address
p->writeWord.bit.DATA = 0; //dummy data;
NT_SPI0->SPI_DR = p->writeWord.all; //send out the data
while (NT_SPI0->SPI_SR_bit.BSY == 1)
; //wait for the packet to complete
// Â ýòî âðåìÿ DRV íàì ïðèñëàë îòâåò íà ïðîøëûé çàïðîñ - òî åñòü ñîäåðæèìîå ïåðâîãî ðåãèñòðà
p->STS1.all = NT_SPI0->SPI_DR; //dummy read to clear the INT_FLAG bit
// Òåïåðü ãîâîðèì, ÷òî óãîäíî
p->writeWord.bit.R_W = 1; //we are initiating a read
p->writeWord.bit.ADDRESS = STAT_REG_2_ADDR; //load the address
p->writeWord.bit.DATA = 0; //dummy data;
NT_SPI0->SPI_DR = p->writeWord.all; //send out the data
while (NT_SPI0->SPI_SR_bit.BSY == 1)
; //wait for the packet to complete
// Â ýòî âðåìÿ DRV íàì ïðèñëàë îòâåò íà ïðîøëûé çàïðîñ - òî åñòü ñîäåðæèìîå âòîðîãî ðåãèñòðà
p->STS2.all = NT_SPI0->SPI_DR;
#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;//îáíóëßåì ïîëå çàïðîñà, ÷òîáû íå âûïîëíèòü åãî ïîâòîðíî
}

155
Vsrc/SM_CmdLogic.c Normal file
View File

@ -0,0 +1,155 @@
/*!
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;
#if defined (HW_VECTORCARD_DRV8301_EVM) || defined (HW_VECTORCARD_DRV8312_EVM)
/* Ðàçðåøèòü íîãàì ðàáîòàòü íà âõîä, ýòî êíîïêè ñòàðò è ñòîï */
NT_GPIOA->ALTFUNCCLR = (1 << 13) | (1 << 14);//âûêëþ÷èòü àëüò. ôóíêöèþ
NT_GPIOA->OUTENCLR = (1 << 13) | (1 << 14);//íà âõîä
#endif
#if defined (HW_MOTORCONTROLBOARD)
/* Ðàçðåøèòü íîãàì ðàáîòàòü íà âõîä, ýòî êíîïêè ñòàðò è ñòîï */
/* Äëÿ âêëþ÷åíèÿ/âûêëþ÷åíèÿ äàííîãî êîíòðîëëåðà èñïîëüçîâàíû âíåøíèå äèñêðåòíûå âõîäû */
/*
* Çäåñü îïèñûâàþòñÿ (îòêëþ÷àåòñÿ àëüòåðíàòèâíàÿ ôóíêöèÿ,
* ðàçðåøàåòñÿ ðàáîòà íà âûõîä) íîæêè äëÿ ðàáîòû ñ êíîïêàìè
* íà ñàìîì êîíòðîëëåðå. Íî òàê êàê äëÿ äàííîãî êîíòðîëëåðà
* ìû èñïîëüçóåì âíåøíèå äèñêðåòíûå âõîäû (ñì. V_DIO), îñòàâèì
* ýòî ìåñòî ïóñòûì.
*/
#endif
}
//!Ìåäëåííûé ðàñ÷åò
//! \memberof TSM_CmdLogic
void SM_CmdLogicSlow_Calc(TSM_CmdLogic *p) {
}
//!1êÃö ðàñ÷åò
//!Îáðàáîòêà ðàçëè÷íûõ èñòî÷íèêîâ êîìàíä è ðàñ÷åò ÄÀ,
//!êîòîðûé ïåðåêëþ÷àåò ãëîáàëüíî ðåæèìû ÐÀÁÎÒÀ è ÎÑÒÀÍÎÂ.
//! \memberof TSM_CmdLogic
void SM_CmdLogicms_Calc(TSM_CmdLogic *p) {
p->StartButton = STARTBUTTON;//îáðàáîòêà íîæêè ñòàðòà
p->StopButton = STOPBUTTON;//îáðàáîòêà íîæêè ñòîïà
p->ResetButton = RESETBUTTON;
//Ñòàíäàðòíàÿ îáðàáîòêà äèñêðåòíîãî àâòîìàòà
if (p->state_prev != p->state)
p->E = 1;
else
p->E = 0;
p->state_prev = p->state;
#if defined (HW_VECTORCARD_DRV8301_EVM) || defined (HW_VECTORCARD_DRV8312_EVM) || defined (HW_MOTORCONTROLBOARD)
if ((p->StartButton==1) && (p->StartButtonPrev==0)){
cmd.bit.start=1;//êîìàíäà íà çàïóñê. Îíà æå ñòàâèòñÿ ÷åðåç CAN
}
if ((p->StopButton==1) && (p->StopButtonPrev==0)){
cmd.bit.stop=1;
}
p->StartButtonPrev=p->StartButton;
p->StopButtonPrev=p->StopButton;
p->ResetButtonPrev = p->ResetButton;
#endif
//îïðåäåëÿåì ðåæèì ðàáîòû
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)) {//åñòü áèòîâàÿ êîìàíäà ñòàðòà
if (udControl.Enabled == 0) { //Åñëè öåïü ïëàâíîãî çàðÿäà ÇÏÒ îòêëþ÷åíà, òî ïåðåõîäèì ê ïóñêó
p->state = CMD_LOGIC_TURNED_ON; //ïîåõàëè
}
else {
if (udControl.StateOn == 1) { //Åñëè öåïü ïëàâíîãî çàðÿäà ÇÏÒ âêëþ÷åíà, æäåì ñðàáàòûâàíèÿ ðåëå, à ïîòîì çàïóñêàåì
p->state = CMD_LOGIC_TURNED_ON; //ïîåõàëè
}
else {
udControl.fault_start = 1; //åñëè ïûòàåìñÿ ïóñòèòñÿ ïðè íåçàøóíòèðîâàííîì ðåëå, ïîïàäàåì â àâàðèþ
}
}
}
}
//äèñêðåòíûé àâòîìàò ñî ñòðóêòóðàìè óïðàâëåíèÿ â ÑÒÎÏå âñåãäà òîæå ïðèíóäèòåëüíî ïåðåâîäèì â ñòîï
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: { //íà âñÿêèé ñëó÷àé äåëàåì ðåæèì ïî-óìîë÷àíèþ "âûêëþ÷åí"
p->state = CMD_LOGIC_TURNED_OFF;
break;
}
} // êîíåö switch(p->state)
}
/*@}*/

1078
Vsrc/SM_Ctrl.c Normal file

File diff suppressed because it is too large Load Diff

225
Vsrc/SM_Net.c Normal file
View File

@ -0,0 +1,225 @@
/*!
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
UserMem.init(&UserMem);
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
co2_vars.settings.LoadParamsFromUserMemory_ena = 1;//Ðàçðåøèòü çàãðóæàòü çíà÷åíèÿ ïàðàìåòðîâ èç ÝÍÎÇÓ
co2_vars.CAN_REGS = (CAN_TypeDef *)CAN_BASE;//Ïåðåäàåì äðàéâåðó àäðåñ ñòðóêòóðû ðåãèñòðîâ CAN
co2_vars.settings.CAN_ISR_priority = IRQ_PRIORITY_CAN;//Ïðèñâîåíèå ïðèîðèòåòà ïåðûâàíèÿ CAN (îáðàáîò÷èê âíóòðè áèáëèîòåêè)
co2_vars.settings.CAN_IRQn = CAN2_IRQn;//Ïåðåäàåì íîìåð ïðåðûâàíèÿ CAN2 èç òàáëèöû ïðåðûâàíèé â äðàéâåð CANOpen
co2_vars.settings.MultiPDO_ena = 0;//Îòêëþ÷åíèå îáðàáîòêè PDO áåç ó÷åòà íîìåðà óçëà (ñïåö. ôóíêöèÿ)
co2_vars.settings.RX_PDO_Callback_ena = 0; //Íå âûçûâàòü ôóíêöèè îáðàòíîãî âûçîâà ïðè ïðèåìå PDO
co2_vars.settings.AutoBusON_ena = 1; //Àâòîìàòè÷åñêè ïåðåçàïóñêàòü CAN ïðè îøèáêàõ íà ëèíèè
co2_vars.settings.BlockTransfer_ena = 1;//Ðàçðåøèòü áëî÷íóþ ïåðåäà÷ó (íóæíà äëÿ îñöèëëîãðàôà)
co2_vars.settings.speedCANTablePointer = &canSpeedTable;//Ïåðåäàåì äðàéâåðó ïàðàìåòðû äëÿ íàñòðîéêè ñêîðîñòè CAN
co2_vars.settings.resetCPU = Watchdog.resetCPU;//Ïåðåäàåì äðàéâåðó àäðåñ ôóíêöèè ðåñåòà ìèêðîêîíòðîëëåðà
co2_Init(&co2_vars); //Èíèöèàëèçàöèÿ äðàéâåðà CANOpen
//ëîããåð ñîáûòèé:
// ðàçìåð áóôåðà: 50
// ñòàðòîâûé àäðåñ â SPI: 3000
FaultLog.init((TLogger*)&FaultLog, 50, 3000,(Uint32*) &RTCclock.packed_time);//íèæå óêàçàòåëü íà âðåìÿ ìîæåò áûòü ïåðåîïðåäåëåí â çàâèñèìîñòè îò ðàáîòû ÷àñîâ
#if (defined(CANTORS_ENA)) || (defined(CANTOUSB_ENA))
//Ðàáîòà ñ CANopen ÷åðåç UART (ïàðàëëåëüíî ñ CAN, íåò êîíôëèêòà)
CANtoRS.nodeID = (Uint16*)&co1_vars.co_nodeID; //Íîìåð óçëà èç CANopen
CANtoRS.callback = Z_co_receiveSDOrequest;//Óêàçàòåëü íà ôóíêöèþ îáðàòíîãî âûçîâà èç äðàéâåðà CANopen ïî ïðèõîäó SDO ñîîáùåíèÿ
CANtoRS.init(&CANtoRS);
#endif
#ifdef MODBUS_ENA
// Íàñòðàèâàåì MODBUS
ModBus.ExecutionFreq = 10000;//×àñòîòà âûçîâà ðàñ÷åòà ìîäóëÿ ìîäáàñ â êÃö
ModBus.Init(&ModBus);
MBVarsConv.init(&MBVarsConv);
#endif
}
//!Ìåäëåííûé ðàñ÷åò.
//! Ïðèñâîåíèå ìàñøòàáèðóþùèõ êîýôôèöèåíòîâ, ôîíîâûé ðàñ÷åò íåêîòîðûõ ìîäóëåé.
//! \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;
co2_vars.co_scaleNum0 = 1; //áåç ìàñøòàáèðîâàíèÿ
co2_vars.co_scaleNum1 = 100; // %
co2_vars.co_scaleNum2 = drv_params.freq_nom; //Ãö
co2_vars.co_scaleNum3 = drv_params.U_nom;//íàïðÿæåíèå ôàçíîå íîìèíàëüíîå àìïëèòóäíîå
co2_vars.co_scaleNum4 = drv_params.I_nom; //Òîê ôàçíûé áàçîâûé
co2_vars.co_scaleNum5 = 1;
co2_vars.co_scaleNum6 = 1;
co2_vars.co_scaleNum7 = drv_params.Udc_nom; //íàïðÿæåíèå ÇÏÒ áàçîâîå
co2_vars.co_scaleNum8 = drv_params.power; //18 â ôîðìàòå 9.6 //Ìîùíîñòü
co2_vars.co_scaleNum9 = 1;
co2_vars.co_scaleNumA = 20; //òåìïåðàòóðà
co2_vars.co_scaleNumB = 1;
co2_vars.co_scaleNumC = 1;
co2_vars.co_scaleNumD = 1;
co2_vars.co_scaleNumE = 1;
co2_vars.co_scaleNumF = 1;
co2_vars.co_scaleNum10 = 1; //
co2_vars.co_scaleNum11 = 1; //
co2_vars.co_scaleNum12 = drv_params.power; //18 â ôîðìàòå 10.6 //Ìîùíîñòü
co2_vars.co_scaleNum13 = 360; //
co2_vars.co_scaleNum14 = drv_params.speed_nom; //íîìèíàëüíàÿ ÷àñòîòà âðàùåíèÿ
co2_vars.co_scaleNum15 = 1; //
co2_vars.co_scaleNum16 = 1; //
co2_vars.co_scaleNum17 = ((((long) drv_params.Udc_nom) << 6)
/ (long) drv_params.I_nom); //Ráàç 10.6
co2_vars.co_scaleNum18 = 1000;
co2_vars.co_scaleNum19 = 1;
co2_vars.co_scaleNum1A = 1;
co2_vars.co_scaleNum1B = 1;
co2_vars.co_scaleNum1C = 1;
co2_vars.co_scaleNum1D = 1;
co2_vars.co_scaleNum1E = 1;
co2_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 ôîíîâûé
co_background_calc(&co2_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;
if (drv_status.bit.overheat == 1)
drv_status_code = DRV_STATUS_OVERHEAT;
else
drv_status_code &= ~DRV_STATUS_OVERHEAT;
//ôóíêöèÿ ëèñòàíèÿ àâàðèé äëÿ ïóëüòà (UniCON)
pult_faults_lister.calc(&pult_faults_lister);
sm_prot.Main_ErrorCode = 0xFF & pult_faults_lister.output;
co_1ms_calc(&co1_vars); //Ðàñ÷åò äðàéâåðà CANOpen
co_1ms_calc(&co2_vars); //Ðàñ÷åò äðàéâåðà CANOpen
#if (defined(CANTORS_ENA)) || (defined(CANTOUSB_ENA))
CANtoRS.calc(&CANtoRS);
#endif
#ifdef MODBUS_ENA
MBVarsConv.calc(&MBVarsConv);
#endif
}
void SM_Net_fast_Calc(TSM_Net *p) {
#ifdef MODBUS_ENA
ModBus.Execute(&ModBus);
#endif
}
/*@}*/

277
Vsrc/SM_Protect.c Normal file
View File

@ -0,0 +1,277 @@
/*!
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;
#if defined (HW_MOTORCONTROLBOARD)
/*
* Инициализация кнопки СБРОС АВАРИЙ не требуется, так как мы используем для этого дискретный вход
*/
#endif
}
//! Быстрый расчет.
//!Обрабатывает все аварии и при их возникновении останавливает привод.
//! \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 defined (HW_MOTORCONTROLBOARD)
if (!DRV_FAULT1) {
//имеется какая-то аппаратная авария
sm_prot.bit_fault2 |= F_PDP_SWITCH_A0;
}
if (!DRV_FAULT2) {
//имеется какая-то аппаратная авария
sm_prot.bit_fault2 |= F_PDP_SWITCH_A1;
}
if (!DRV_FAULT3) {
//имеется какая-то аппаратная авария
sm_prot.bit_fault2 |= F_PDP_SWITCH_A2;
}
if (!DRV_FAULT4) {
//имеется какая-то аппаратная авария
sm_prot.bit_fault2 |= F_PDP_SWITCH_LOWER;
}
#endif
/*Защита от пуска при незашунтированном реле плавного заряда ЗПТ*/
if (udControl.Enabled == 1) { //Если есть цепь шунтирования ЗПТ, то выставляем аварии по выполнению условий
if (udControl.fault_start == 1)
sm_prot.bit_fault1 |= F_RELAY_START;
}
/*Авария, если программа записана в загрузочную область памяти (BFLASH)*/
if (programMemType == 0x4) {
sm_prot.bit_fault1 |= F_PROGRAM_IS_ON_BFLASH;
}
/*Защита по максимальному току*/
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;
}
}
//при превышении температуры выше аварийной нормы
if (adc.T_meas > sm_prot.T_max) {
sm_prot.bit_fault1 |= F_CTRL_HI_TEMP; // максимальная температура
}
#if defined(HW_VECTORCARD_SIMULATOR) || defined(HW_NIIET_BOARD_SIMULATOR)
if(model.fault){
sm_prot.bit_fault1 |= F_MODEL_FAULT;
}
#endif
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++ > 30000) {
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) || (RESET_FAULT_BUTTON == 1)) {//команда на сброс аварии
p->state = PROT_ON_OK;//идем в "норма"
p->clearDrvFault = 1; //отправить драйверу ключей команду сброса
//обнуляем все флаги аварий
p->bit_fault1 = 0;
p->bit_fault2 = 0;
cmd.all = 0;//командное слово
if (udControl.Enabled == 1) { //Если есть цепь шунтирования ЗПТ, то сбрасываем возможные состояния аварий
udControl.fault_start = 0;
}
//в самом низу!!! пытаемся сбросить флаг pdp аппаратный
//если авария все еще имеется, то сразу произойдет прерывание
//и возведется флаг аварии
if (PWM0->TZFLG_bit.OST == 1) { //имеется флаг аппаратной аварии
//флаг можно сбрасывать
PWM0->TZCLR = 0x7;
PWM1->TZCLR = 0x7;
PWM2->TZCLR = 0x7;
}
#if defined(HW_VECTORCARD_SIMULATOR) || defined(HW_NIIET_BOARD_SIMULATOR)
model.fault=0;
#endif
}
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;
drv8301.read(&drv8301);
}
/* Чтобы сбросить аварию, надо прописать ему битик GATE_RESET */
if (p->clearDrvFault == 1) {
p->clearDrvFault = 0;
drv8301.CTRL1.bit.GATE_RESET = 1;
drv8301.write(&drv8301, CNTRL_REG_1_ADDR);
drv8301.write(&drv8301, CNTRL_REG_2_ADDR);
}
}
/*@}*/

302
Vsrc/SM_Sys.c Normal file
View File

@ -0,0 +1,302 @@
/*!
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;
#elif defined (HW_MOTORCONTROLBOARD)
sw.HardwareType = 3;
#endif
cmd.all = 0;
drv_status.all = 0;
adc.init(&adc); //Инициализация АЦП
sm_net.init(&sm_net); //Сетевая часть
sm_prot.init(&sm_prot); //Защиты
drv8301.init(&drv8301);//драйвер ключей
sm_cmd_logic.init(&sm_cmd_logic); //Логика включения/выключения
sm_ctrl.init(&sm_ctrl); //Структура системы управления
pwm.init(&pwm); //Модуль ШИМ
cur_par.init(&cur_par); //Расчет текущих показателей привода
leds.init(&leds);//светодиоды
udControl.init(&udControl); //плавная зарядка ЗПТ через термисторы
DIO_Init(); //дискретные входы/выходы
FanControl.init(&FanControl); //вентилятор
//глобальное времЯ (внешние или внутр. часы)
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(APB0BusClock/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 = (APB0BusClock / 10000L) - 1; //9999 надо чтобы не плыло отностильно прерывания ШИМа, когда у того частота 10кГц
TMR0->CTRL = ((1 << 0) | (1 << 3)); // Запуск и разрешение прерываний
// Настройка таймера 1 на 1 кГц
TMR1->INTSTATUS_bit.INT = 1;
TMR1->LOAD_bit.VAL = (APB0BusClock / 1000L) - 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(QEP0_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(QEP0_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(QEP0_IRQn); //QEP
NVIC_SetPriority(QEP0_IRQn, IRQ_PRIORITY_EQEP);
sm_sys.state = SYS_READY;
gpioPeripheralInit();
#ifdef WATCHDOG_ON
WatchDog.init(WATCHDOG_PERIOD); //если сторожевой таймер используется, инициализируем
#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
}
// adc.fast_calc(&adc); //АЦП
dlog.update(&dlog); //Осциллографирование данных
sm_prot.fast_calc(&sm_prot); //Защиты
sm_ctrl.fast_calc(&sm_ctrl); //Главный дискретный автомат системы управления
udControl.calc(&udControl);//Плавная зарядка ЗПТ через термисторы
#if defined(HW_VECTORCARD_SIMULATOR) || defined(HW_NIIET_BOARD_SIMULATOR)
//Передача текущих скважностей таймеров ШИМ в модель
model.cmpr0 = PWM0->CMPA_bit.CMPA;
model.cmpr1 = PWM1->CMPA_bit.CMPA;
model.cmpr2 = PWM2->CMPA_bit.CMPA;
model.InvertorEna=pwm.Enabled;//Флаг разрешения работы инвертора
model.Execute(&model);
#endif
global_time.calc(&global_time);
cur_par.calc(&cur_par); //Расчет текущих показателей привода
drv_params.sens_type = drv_params.sens_type & 7; //Отсекаем верхнюю часть переменной, там мусор
#ifdef WATCHDOG_ON
WatchDog.calc();//если сторожевой таймер используется, сбрасываем его здесь
#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
Can1BTInterface.ms_calc(&Can1BTInterface, TMR2->VALUE, &co1_vars);
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);
DIO_fast_calc(); //дискретные входы/выходы
}
//!Медленный расчет (фоновый).
//!Вызов медленных расчетов остальных модулей
//! \memberof TSM_Sys
void SM_Sys_Slow_Calc(TSM_Sys *p) {
Can1BTInterface.slow_calc(&Can1BTInterface);//интерфейс блочной передачи CANopen, медленный расчет
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);//наблюдатель потока ротора АД
DIO_slow_calc(); //дискретные входы/выходы
FanControl.slow_calc(&FanControl);//вентилятор
//Пересчет коэффициентов для масштабирования токов и напряжений
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) &&
#ifdef HW_VECTORCARD_DRV8301_EVM
(sm_prot.state==PROT_ON_OK) && //условие отсутствия аварии проверяем только на железе HW_VECTORCARD_DRV8301_EVM, потому что там нельзя измерять токи при аварии
#endif
(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);
}
}
/*@}*/

410
Vsrc/V_CANtoRS.c Normal file
View File

@ -0,0 +1,410 @@
/*!
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/USB и обратно. Работает
совместно с драйвером CANOpen
\author ООО "НПФ Вектор". http://motorcontrol.ru
\version v 3.0 08/08/2017
\addtogroup v_CANtoRS
@{
*/
#include "DSP.h"
#include "main.h"
void usb_irq_en(void);
void usb_irq_dis(void);
//! \memberof TCANtoRS
void CANtoRS_init(TCANtoRS *p) {
#ifdef CANTORS_ENA
#ifdef HW_NIIET_BOARD_SIMULATOR
//UART TX - плата микроконтроллера разъем XP6 пин 57 (соответствует обозначению UART_TXD1 в шелкографии на основной плате)
//UART RX - плата микроконтроллера разъем XP6 пин 59 (соответствует обозначению UART_RXD1 в шелкографии на основной плате)
NT_COMMON_REG->GPIOPCTLA_bit.PIN3 = 1; //UART_TxD1]
NT_COMMON_REG->GPIOPCTLA_bit.PIN4 = 1; //UART_RxD[1]
NT_GPIOA->ALTFUNCSET = (1 << 3);
NT_GPIOA->ALTFUNCSET = (1 << 4);
NT_COMMON_REG->GPIOPCTLA_bit.PIN3 = 0;
NT_COMMON_REG->GPIOPCTLA_bit.PIN4 = 0;
p->NT_UART=NT_UART1;//Используемый в драйвере номер UART (1,2,3)
#elif defined (HW_MOTORCONTROLBOARD)
p->NT_UART=UART2;//Используемый в драйвере номер UART (1,2,3)
p->NT_UART->CR_bit.UARTEN = 1; // Разрешить работу UART
#else
p->NT_UART=UART2;//Используемый в драйвере номер UART (1,2,3)
p->NT_UART->CR_bit.UARTEN = 1; // Разрешить работу UART
#endif
p->NT_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->NT_UART->IBRD_bit.DIVINT= 27;
p->NT_UART->FBRD_bit.DIVFRAC = 8;
p->NT_UART->LCRH_bit.SPS = 0; // Нет проверки четности
p->NT_UART->LCRH_bit.WLEN = 3; // Длина посылки 8 бит
p->NT_UART->LCRH_bit.FEN = 1; // Использовать FIFO
p->NT_UART->CR_bit.TXE = 1; // Разрешить приём
p->NT_UART->CR_bit.RXE = 1; // Разрешить передачу
p->NT_UART->LCRH_bit.STP2 = 0; // 1 стоп-бит
#endif
#ifdef CANTOUSB_ENA
USB_init_hardware();
#endif
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;
#ifdef CANTORS_ENA
// Если буфер TX не заполнен, то отправляем все байты из буфера
while ((p->NT_UART->FR_bit.TXFF != 1) && (i < p->all_len)){
p->NT_UART->DR = p->buf_out[i];
i++;
}
#endif
#ifdef CANTOUSB_ENA
usb_irq_dis();
if (usbTxBuf.busy == 0 && usbTxBuf.availSpace(&usbTxBuf) > p->all_len){
usbTxBuf.put(&usbTxBuf, p->all_len, (Uint8*)p->buf_out);
}
usb_irq_en();
#endif
return 1;
}
#define CRC_MAGIC_NUMBER 0xA001
//! Функция считает контрольную сумму пакета
//! и сравнивает с принятой. Если все верно, то возвращает 1
//! \memberof TCANtoRS
#if defined (__GNUC__)
__attribute__((section(".fastcode")))
#endif
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;
}
/*! Функция вызывается, когда пришли какие-то данные,
* и проверяет, что эти данные корректны и могут быть обработаны
* драйвером CANopen. Если это так - данные отправляются на
* обработку
*/
//! \memberof TCANtoRS
#if defined (__GNUC__)
__attribute__((section(".fastcode")))
#endif
void CANtoRS_CheckPacketValid(TCANtoRS *p) {
Uint8 i;
Uint16 readCRC, calcCRC; // Расчётная и пришедшая контрольные суммы
// Сначала проверим, не хотел ли предыдуищй принятый пакет запустить колбэк
// Если хотел - то выполним, а уже при следующем вызове проверим, пришли ли данные, чтобы не сильно загружать процессор
if (p->callback_go) {
p->callback_go = 0;
p->CounterRes++;
p->callback(&co1_vars, (TZCanMsg*)&(p->MSG));
return;
}
// Посмотрим, сколько байт начитали в буфер. Если меньше, чем нужно (13) - выходим и ждём следующего раза.
// Если насчитали - сбрасываем счётчик принятых байт и идём проверять посылку
if (p->ReadPackDataCounter < 13)
return;
p->ReadPackDataCounter = 0;
// Сначала проверяем сигнатуру, первый байт посылки (должна быть 0x7E)
// Если сигнатура не сошлась - сбрасываем счётчик начитанных байтов, и увеличиваем число потерянных пакетов
if (p->tempBuf[0] != 0x7E){
p->MessDrop3++;
return;
}
// Если сигнатура сошлась - следующие 10 байт кладём в DATA
for (i = 0; i < CANTORS_READ_DATA_MAX_LEN; i++){
p->ReadPackData[i] = p->tempBuf[i + 1];
}
// Теперь забираем последние два байт посылки - CRC. Сраниваем пришедшую CRC и расчётную.
// Если не сошлось - выходим отседова.
readCRC = ((Uint16)(p->tempBuf[12]) << 8) | ((Uint16)(p->tempBuf[11]));
calcCRC = CANtoRS_C_CRC(p, (Uint16*)p->ReadPackData, CANTORS_READ_DATA_MAX_LEN);
if (readCRC != calcCRC) {
p->CounterWrongCRC++;
return;
}
// Контрольная сумма сошлась - анализируем пакет
CANtoRS_Analysis(p);
// Может получится, что в результате обработки пакета мы увидели необходимость вызвать коллбэк.
// В таком случае будет взведён флаг "callback_go". Если это так - мы его обработаем при следующем
// вызове функции, чтобы не тратить слишком много времени. А пока выходим.
return;
}
//! Функция для приёма данных от периферии RS
//! \memberof TCANtoRS
#if defined (__GNUC__)
__attribute__((section(".fastcode")))
#endif
void CANtoRS_ReceiveRS(TCANtoRS *p) {
// Читаем из фифо данные, пока они там есть, либо пока фифо не опустеет
while ((p->NT_UART->FR_bit.RXFE != 1) && (p->ReadPackDataCounter < 13)) {
// Если что-то пришло по RS, а в прошлый раз приходило по USB - надо обнулить ReadDataCounter
if (p->lastActiveConnection == CANTOUSB_ACTIVE)
p->ReadPackDataCounter = 0;
p->tempBuf[p->ReadPackDataCounter] = p->NT_UART->DR_bit.DATA;
p->ReadPackDataCounter++;
// Указываем, что сейчас активен RS
p->lastActiveConnection = CANTORS_ACTIVE;
}
}
//! Функция для приёма данных от периферии USB
//! \memberof TCANtoRS
#if defined (__GNUC__)
__attribute__((section(".fastcode")))
#endif
void CANtoRS_ReceiveUSB(TCANtoRS *p) {
// Uint16 neededBytes;
// Uint16 tempLen;
// // Проверяем, сколько есть данных в буфере.
// // Если больше, чем нам надо - читаем сколько надо.
// // Если меньше, чем надо - читаем всё.
// usb_irq_dis();
// tempLen = usbRxBuf.filledSpace(&usbRxBuf);
// if (tempLen > 0){
// // Если что-то пришло по USB, а в прошлый раз приходило по RS - надо обнулить ReadDataCounter
// if (p->lastActiveConnection == CANTORS_ACTIVE)
// p->ReadPackDataCounter = 0;
//
// neededBytes = 13 - p->ReadPackDataCounter;
//
// if (tempLen >= neededBytes) {
// usbRxBuf.get(&usbRxBuf, neededBytes, (Uint8*)(p->tempBuf + p->ReadPackDataCounter));
// p->ReadPackDataCounter += neededBytes;
// } else {
// usbRxBuf.get(&usbRxBuf, tempLen, (Uint8*)(p->tempBuf + p->ReadPackDataCounter));
// p->ReadPackDataCounter += tempLen;
// }
//
// // Указываем, что у нас был активен USB
// p->lastActiveConnection = CANTOUSB_ACTIVE;
// }
// usb_irq_en();
}
//! Функция для приёма и обработки данных от периферии/
//! Работает сразу и с USB, и с RS
//! \memberof TCANtoRS
#if defined (__GNUC__)
__attribute__((section(".fastcode")))
#endif
void CANtoRS_Receive(TCANtoRS *p) {
#ifdef CANTORS_ENA
// Если RS-модуль задействован - обрабатываем UART
CANtoRS_ReceiveRS(p);
#endif
#ifdef CANTOUSB_ENA
// Если USB задействован - обрабатываем USB
CANtoRS_ReceiveUSB(p);
#endif
// Проверяем пришедшие данные
CANtoRS_CheckPacketValid(p);
}
/*! Должна вызываться каждую секунду и отсылает
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((Uint16*)p->TempData,10,p);
return 1;
}
/*! Вызывается из миллисекундного таймера, отсчитывает 1 секунду
и вызывает функцию отправки HeartBeat. Заодно проверяет,
если в SCI возникла какая-то ошибка и он остановился, перезапускает.
*/
//! \memberof TCANtoRS
#if defined (__GNUC__)
__attribute__((section(".fastcode")))
#endif
void CANtoRS_calc(TCANtoRS *p) {
//если в буфере есть пакет, ожидающий отправки и передатчик свободен и не ждет heartbeat
if (p->PacketInWait) {
if (!CANtoRS_Write_Real((TZCanMsg*)&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х фазному
}
/*@}*/

128
Vsrc/V_DIO.c 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_DIO.c
\brief Ìîäóëü äèñêðåòíûõ âõîäîâ/âûõîäîâ
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 1.0 25/08/2017
\addtogroup
@{*/
#include "main.h"
#include "filter.h"
// Âåêòîð ñîñòîßíèß äèñêðåòíûõ âûõîäîâ
volatile Uint16 output_vect = 0;
// Ìàñêà èíâåðòèðîâàíèß âåêòîðà ñîñòîßíèß äèñêðåòíûõ âûõîäîâ
volatile Uint16 output_mask = 0;
// Âåêòîð ñîñòîßíèß äèñêðåòíûõ âõîäîâ
volatile Uint16 input_vect = 0;
// Ìàñêà èíâåðòèðîâàíèß âåêòîðà ñîñòîßíèß äèñêðåòíûõ âõîäîâ
volatile Uint16 input_mask = 0;
// Êîýôôèöèåíò ôèëüòðàöèè äèñêðåòíûõ âõîäîâ Kf = 0.001/Tô
// (Tô - ïîñòîßííàß âðåìåíè ôèëüòðà, ñåê)
volatile _iq inputKf = _IQ(0.03); //Âðåìÿ ñðàáàòûâàíèÿ ñîñòàâëÿåòñÿ 60ìñ ïðè inputKf=_IQ(0.03) è inputOn = _IQ(0.8) â 1êÃö ïðåðûâàíèè;
// Ïîðîã ïåðåõîäà äèñêðåòíîãî âõîäà â ñîñòîßíèå OFF (0)
volatile _iq inputOff = _IQ(0.3);
// Ïîðîã ïåðåõîäà äèñêðåòíîãî âõîäà â ñîñòîßíèå ON (1)
volatile _iq inputOn = _IQ(0.8);
// Ïðîìåæóòî÷íûé âåêòîð ñîñòîßíèß äèñêðåòíûõ âõîäîâ (áåç ó÷¸òà ìàñêè èíâåðòèðîâàíèß)
Uint16 input = 0;
// Ôèëüòðû äèñêðåòíûõ âõîäîâ
TFilter fIn1 = FILTER_DEFAULTS;
TFilter fIn2 = FILTER_DEFAULTS;
TFilter fIn3 = FILTER_DEFAULTS;
void DIO_Init()
{
#if defined (HW_MOTORCONTROLBOARD)
//Ïðîèíèòèì äèñêðåòíûå âõîäû
// NT_GPIOB->ALTFUNCCLR = (1 << 5); //âûêëþ÷èòü àëüò. ôóíêöèþ
// NT_GPIOA->ALTFUNCCLR = (1 << 14) | (1 << 15); //âûêëþ÷èòü àëüò. ôóíêöèþ
// NT_GPIOB->OUTENCLR = (1 << 5); //íà âõîä
// NT_GPIOA->OUTENCLR = (1 << 14) | (1 << 15); //íà âõîä
//
// //Ïðîèíèòèì äèñêðåòíûå âûõîäû
// NT_GPIOB->ALTFUNCCLR = (1 << 6) | (1 << 15) | (1 << 4); //âûêëþ÷èòü àëüò. ôóíêöèþ
// NT_GPIOB->OUTENSET = (1 << 6) | (1 << 15) | (1 << 4); //íà âûõîä
#endif
}
void DIO_slow_calc()
{
// Ïîëó÷àåì âåêòîð ñîñòîßíèß äèñêðåòíûõ âûõîäîâ ñ ó÷¸òîì ìàñêè èíâåðòèðîâàíèß
Uint16 output = output_vect ^ output_mask;
// Âûâîäèì óïðàâëßþùåå âîçäåéñòâèå ïî Âûõîäó 1
if (BIT_IS_SET(output, 0))
D_OUT1_OFF;
else
D_OUT1_ON;
// Âûâîäèì óïðàâëßþùåå âîçäåéñòâèå ïî Âûõîäó 2
if (BIT_IS_SET(output, 1))
D_OUT2_OFF;
else
D_OUT2_ON;
// Âûâîäèì óïðàâëßþùåå âîçäåéñòâèå ïî Âûõîäó 3
if (BIT_IS_SET(output, 2))
D_OUT3_OFF;
else
D_OUT3_ON;
// Îáíîâëßåì êîýôôèöèåíòû ôèëüòðàöèè äèñêðåòíûõ âõîäîâ
fIn1.T = inputKf;
fIn2.T = inputKf;
fIn3.T = inputKf;
// Ïîëó÷àåì ñîñòîßíèå Âõîäà 1 ñ ó÷¸òîì ôèëüòðàöèè
if (fIn1.output > inputOn) SET_BIT(input, 0);
if (fIn1.output < inputOff) CLEAR_BIT(input, 0);
// Ïîëó÷àåì ñîñòîßíèå Âõîäà 2 ñ ó÷¸òîì ôèëüòðàöèè
if (fIn2.output > inputOn) SET_BIT(input, 1);
if (fIn2.output < inputOff) CLEAR_BIT(input, 1);
// Ïîëó÷àåì ñîñòîßíèå Âõîäà 3 ñ ó÷¸òîì ôèëüòðàöèè
if (fIn3.output > inputOn) SET_BIT(input, 2);
if (fIn3.output < inputOff) CLEAR_BIT(input, 2);
input_vect = input ^ input_mask;
}
void DIO_fast_calc()
{
// Èíåðöèîííûé ôèëüòð äèñêðåòíîãî Âõîäà 1
fIn1.input = (D_IN1 == 1) ? _IQ(1.0) : 0;
fIn1.calc(&fIn1);
// Èíåðöèîííûé ôèëüòð äèñêðåòíîãî Âõîäà 2
fIn2.input = (D_IN2 == 1) ? _IQ(1.0) : 0;
fIn2.calc(&fIn2);
// Èíåðöèîííûé ôèëüòð äèñêðåòíîãî Âõîäà 3
fIn3.input = (D_IN3 == 1) ? _IQ(1.0) : 0;
fIn3.calc(&fIn3);
}
/*@}*/

599
Vsrc/V_DPR_eCAP.c Normal file
View File

@ -0,0 +1,599 @@
/*!
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 = ((APB0BusClock / (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));
#if (!defined(HW_VECTORCARD_SIMULATOR)) && (!defined(HW_NIIET_BOARD_SIMULATOR))
// Íàñòðîéêà íîæåê â GpioPeripheralInit
#endif
DPReCAP_Angle6Calc(p);
p->CAP_WrongEdgeCnt = 0;
p->SimulatorOmega2IQ_factor=_IQ(60.0/(2*MOTOR_MODEL_PI*drv_params.speed_nom));
}
//! Îïðåäåëåíèå óãëîâîãî ïîëîæåíèÿ ñ äèñêðåòíîñòüþ 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 (GPIOM->DATA & (1 << 5))
p->HallCode = p->HallCode + 1;
if (GPIOM->DATA & (1 << 6))
p->HallCode = p->HallCode + 2;
if (GPIOM->DATA & (1 << 7))
p->HallCode = p->HallCode + 4;
} else {
if (GPIOM->DATA & (1 << 5))
p->HallCode = p->HallCode + 4;
if (GPIOM->DATA & (1 << 6))
p->HallCode = p->HallCode + 2;
if (GPIOM->DATA & (1 << 7))
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);
}
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;
}
/*@}*/

87
Vsrc/V_Fan.c Normal file
View File

@ -0,0 +1,87 @@
/*!
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_Fan.c
\brief Ìîäóëü ðàáîòû âåíòèëÿòîðà
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 1.0 25/08/2017
\addtogroup
@{*/
#include "main.h"
//! \memberof TFanControl
void FanControl_init(TFanControl *p)
{
#if defined (HW_MOTORCONTROLBOARD)
p->Enabled = 1; //Âêëþ÷àåì áëîê âåíòèëÿòîðà
//Ïðîèíèòèì âûõîä äëÿ óïðàâëåíèÿ âåíòèëÿòîðîì â GpioPeripheralInit
#endif
}
//! \memberof TFanControl
void FanControl_slow_calc(TFanControl *p) {
if (p->Enabled){//åñëè åñòü âåíòèëÿòîð
//ñ÷èòàåì äèñêðåòíûé àâòîìàò
p->state_shadow = p->state;
p->state_prev = p->state_shadow;
switch (p->state_shadow) {
case FAN_CONTROL_STATE_OFF: //âåíòèëÿòîð íå ðàáîòàåò, òåìïåðàòóðà èíâåðòîðà ìåíüøå T_on
{
FAN_OFF; //
p->StateOn = 0; //
if (adc.T_meas > p->T_on) //
p->state = FAN_CONTROL_STATE_ON; //
break;
}
case FAN_CONTROL_STATE_ON: //âêëþ÷åíèå âåíòèëÿòîðà, òåìïåðàòóðà áîëüøå T_on è ìåíüøå T_alarm
{
FAN_ON; //âêëþ÷èòü âåíòèëÿòîð
p->StateOn = 1; //ñîñòîÿíèå ðàáîòû
if (adc.T_meas > p->T_alarm) //åñëè òåìïåðàòóðà ïîäíÿëàñü åùå áîëüøå, ïåðåõîäèì â ðåæèì ïåðåãðåâà
p->state = FAN_CONTROL_STATE_OVERHEAT;
if (adc.T_meas < p->T_off) //åñëè òåìïåðàòóðà îïóñòèëàñü íèæå çàäàííîãî óðîâíÿ, ïåðåõîäèì â îáû÷íûé ðåæèì
p->state = FAN_CONTROL_STATE_OFF;
break;
}
case FAN_CONTROL_STATE_OVERHEAT: //òåìïåðàòóðà áîëüøå T_alarm, âåíòèëÿòîð ðàáîòàåò, âûâîäèòñÿ ïðåäóïðåæäåíèå î ïåðåãðåâå
{
FAN_ON; //âêëþ÷èòü âåíòèëÿòîð
p->StateOn = 1; //ñîñòîÿíèå ðàáîòû
drv_status.bit.overheat = 1; //âûâîä ïðåäóïðåæäåíèÿ î ïåðåãðåâå
if (adc.T_meas < p->T_alarm) { //åñëè òåìïåðàòóðà îïóñòèëàñü íèæå çàäàííîãî óðîâíÿ, ïåðåõîäèì â îáû÷íûé ðåæèì
drv_status.bit.overheat = 0; //ñáðîñ ïðåäóïðåæäåíèÿ î ïåðåãðåâå
p->state = FAN_CONTROL_STATE_ON;
}
break;
}
}
}
}
/*@}*/

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));
}
/*@}*/

135
Vsrc/V_MBVarsConvert.c Normal file
View File

@ -0,0 +1,135 @@
/*!
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.c
\brief Ìîäóëü ïðåîáðàçîâàíèÿ äàííûõ Modbus
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v.1.1. 02/03/2017
\addtogroup v_ModBus */
/*@{*/
#include "main.h"
#include "mbod.h"
#include "math.h" //äëÿ fabs
//! Èíèöèàëèçàöèÿ íå òðåáóåòñÿ
//! \memberof TMBVarsConv
void MBVarsConv_init(TMBVarsConv *p) {
}
//! Îñíîâíàÿ ïðîöåäóðà
//! Âõîä â .input, âûõîä â .output
//! Êðèâàÿ çàäàåòñÿ ìàññèâîì èç NumOfPoints òî÷åê ïî x è ïî y.
//! \memberof TMBVarsConv
void MBVarsConv_calc(TMBVarsConv *p) {
float number, scale, scaled;
long i, index;
if (ModBus.Enabled == 1){ // Åñëè âêëþ÷åí MODBUS
//Äëÿ óìåíüøåíèÿ âû÷èñëèòåëüíîé íàãðóçêè â ñëó÷àå íåîáõîäèìîñòè ìîæíî óáðàòü öèêë for è ïðîâåðÿòü ïî îäíîìó ýëåìåíòó çà îäèí çàõîä
for (i = 0; i < ModBus.MBInternals.NumOfHRs; i++)// Ïðîâåðÿåì âñå ýëåìåíòû ñëîâàðÿ HR (ðåäàêòèðóåìûõ ïàðàìåòðîâ)
if (mbodHR[i].type_or_acc == 1){// Åñëè ïàðàìåòð ìåíÿëñÿ, òî àíàëèçèðóåì, êàê åãî ïðåîáðàçîâàòü
mbodHR[i].type_or_acc = 0; // Ñáðàñûâàåì ôëàã èçìåíåíèÿ ïàðàìåòðà
index = mbodHR[i].index; //êàêîé èíäåêñ ìåíÿëè
if ((index != 2000) && (index != 2001)) //åñëè íå 2000 è íå 2001, òî íóæíî ñîõðàíèòü ïàðàìåòðû
p->NeedForSave = 1;//Íóæíî íå çëîóïîòðåáëÿòü ýòîé êîìàíäîé, èíà÷å âñÿ ïîëüçîâàòåëüñêàÿ ïàìÿòü ñîòðåòñÿ äî äûð!
//Â çàâèñèìîñòè îò òîãî, êàêîé èíäåêñ ñëîâàðÿ ïîìåíÿëñÿ, âûïîëíÿåì íóæíîå ïðåîáðàçîâàíèå.
//Íà êàæäóþ ïðîâåðêó èíäåêñà òðàòèòñÿ 3 òàêòà. Åñëè ïðîâåðîê áóäåò î÷åíü ìíîãî,
//òî ëîãè÷íî äîïîëíèòü äðàéâåð ôóíêöèÿìè îáðàòíîãî âûçîâà ïðè îáðàùåíèè ê ïàðàìåòðó
switch (index){
case 2000://ñëîâî óïðàâëåíèÿ
//åñëè çíà÷åíèå ïîëÿ êîìàíäà èçìåíèëîñü ïî ñðàâíåíèþ ñ ïðåäûäóùèì
if (p->Vars.Command!=p->Vars.CommandPrev){
if (p->Vars.Command & (1<<0))//êîìàíäà íà çàïóñê
cmd.bit.start = 1;
if (p->Vars.Command & (1<<1))//êîìàíäà íà îñòàíîâ
cmd.bit.stop = 1;
if (p->Vars.Command & (1<<2))//êîìàíäà íà ñáðîñ àâàðèè
cmd.bit.trip_reset = 1;
}
p->Vars.CommandPrev=p->Vars.Command;
break;
case 2001: // òåêóùàÿ ÷àñòîòà âðàùåíèÿ
number = (float) p->Vars.speed_ref;
number = fabs(number);
scale = (float) co1_vars.co_scaleNum14; // ×àñòîòà âðàùåíèÿ (îá/ìèí) 16.0
scaled = number / scale;
refs.speed_ref = _IQ(scaled);
break;
case 43116: //íàïðÿæåíèå çàùèòû â âîëüòàõ
number = (float) MBVarsConv.Vars.Umax_protect;
scale = (float) co1_vars.co_scaleNum7; //íàïðÿæåíèå ÇÏÒ áàçîâîå
scaled = number / scale;
sm_prot.Umax_protect = _IQ(scaled);
break;
}
}
}
// Äëÿ íàáëþäàåìûõ ïðåîáðàçîâàíèå çàïóñêàåì âñåãäà
// 40002
number = _IQtoF(cur_par.speed);
scale = (float) co1_vars.co_scaleNum14; // ×àñòîòà âðàùåíèÿ (îá/ìèí)
scaled = scale * number;
p->Vars.CurSpeed = scaled;
// 40007
number = _IQtoF(cur_par.Is);
scale = (float) co1_vars.co_scaleNum4; //Òîê ôàçíûé áàçîâûé
scaled = scale * number;
p->Vars.CurIs = scaled;
// 40054
p->Vars.Main_ErrorCode = sm_prot.Main_ErrorCode; //êîä òåêóùåé àâàðèè (ëèñòàåòñÿ, åñëè íåñêîëüêî)
}
void MBVarsConv_slow_calc(TMBVarsConv *p) {
if (p->NeedForSave) {//êîìàíäà íà ñîõðàíåíèå ïàðàìåòðîâ ïðèâîäà ÷åðåç ìîäáàñ
p->NeedForSave = 0;
//ñîõðàíÿåì ïîñðåäñòâîì äðàéâåðà CANopen (âñå åãî ïàðàìåòðû)
//âûçûâàÿ ôóíêöèþ ñîõðàíåíèÿ ñ ðàçíûìè äèàïàçîíàìè, ïåðåáèðàÿ èõ âñå.
co_ODexpositor_paramConservation(&co1_vars, 1, 1);
co_ODexpositor_paramConservation(&co1_vars, 2, 1);
co_ODexpositor_paramConservation(&co1_vars, 3, 1);
co_ODexpositor_paramConservation(&co1_vars, 1, 2);
co_ODexpositor_paramConservation(&co1_vars, 2, 2);
co_ODexpositor_paramConservation(&co1_vars, 3, 2);
co_ODexpositor_paramConservation(&co1_vars, 1, 3);
co_ODexpositor_paramConservation(&co1_vars, 2, 3);
co_ODexpositor_paramConservation(&co1_vars, 3, 3);
co_ODexpositor_paramConservation(&co1_vars, 1, 4);
co_ODexpositor_paramConservation(&co1_vars, 2, 4);
co_ODexpositor_paramConservation(&co1_vars, 3, 4);
co_ODexpositor_paramConservation(&co1_vars, 1, 5);
co_ODexpositor_paramConservation(&co1_vars, 2, 5);
co_ODexpositor_paramConservation(&co1_vars, 3, 5);
}
}
/*@}*/

721
Vsrc/V_ModBus.c Normal file
View File

@ -0,0 +1,721 @@
/*!
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.c
\brief Драйвер ModBus (см. TModBus)
24-03-2017 Перенос драйвера на К1921ВК01Т НИИЭТ. Сильный рефакторинг.
13-08-2012 Теперь поле type структуры MB_Record используется как признак записи/чтения
для не битовых HR/IR-переменных (раньше там был только признак записи).
24-01-2012 Теперь проще выбирать между SciaRegs, ScibRegs и ScicRegs. Это сделано
дефайном. Переименована структура RS в MODBUS_RS
26-02-2011 Исправлены какие-то баги, добавлена возможность отслеживать запись в объекты
типа "регистр" за счет изменения номера бита в словаре, поддержка большего
кол-ва процессоров.
27-11-2009 Сделана доработка драйвера для поддержки broadcast (широковещательных) сообщений. Естесственно,
что поддерживаются только команды записи (0x5 - write coils и 0x6 - write single register), т.к.
broadcast сообщения являются неподтверждаемыми сообщениями. Иными словами читать бесполезно, т.к.
ответа не придет... (Алямкин)
21-10-2008 Исправлена ошибка переполнения входного регистра - при переполнении выставлялась frame error (из драйвера SYS_VID800)
29-01-2008 Иправлена ошибка расчета таймаутов
28-01-2008 Иправлена ошибка в функции пойска нужного элемента словаря
29-11-2007 Драйвер переделан для работы с МК17.1
1.Исправлена ошибка при обнулении битовых регистров
2.Исправлен неправильный перебор элементов в словаре
3.Добавлена возможность автоматического перезапуска драйвера при большом количестве ошибок на линии
Замечание. Особенность реализации драйвера не предполагает наличия регистра 0х0000 в словаре
Для устранения недостатка необходимо в инициализации переделать пойск последних элементов
массивов с поля номера регистра на поле адреса переменной регистра.
16-11-2006 Release Rev 1.0
\author Alecksey Anuchin
\version v 1.2 24/03/2017
*/
/** \addtogroup V_ModBus */
/*@{*/
#include "V_ModBus.h"
#include "main.h"
#if defined (HW_MOTORCONTROLBOARD)
//Макросы для переключения RS485 между приемом и передачей
#define MODBUS_RX_RS485 GPIOM->DATAOUTCLR = (1 << 2) //M2
#define MODBUS_TX_RS485 GPIOM->DATAOUTSET = (1 << 2) //M2
#define MODBUS_GPIO_VALUE (GPIOK->DATA>>10) & 3
#else
#define MODBUS_RX_RS485 //NT_GPIOC->MASKHIGHBYTE_bit[4].MASKHB = 4
#define MODBUS_TX_RS485 //NT_GPIOC->MASKHIGHBYTE_bit[4].MASKHB = 0
#define MODBUS_GPIO_VALUE (GPIOC->DATA>>8) & 3
#endif
//Макрос для осциллографирования ножек UART (удобно для отладки, когда вообще ничего не работает)
//Частота тактирования блока UART (настраивается в инициализации микроконтроллера)
#define UART_CLOCK_FREQ 25000000
void ModBus_RS_Init(TModBus *p) {
#if defined (HW_MOTORCONTROLBOARD)
p->MBInternals.NT_UART = UART2; //Используемый в драйвере номер UART (1,2,3)
p->MBInternals.NT_UART->CR_bit.UARTEN = 1; // Разрешить работу UART
#else
p->MBInternals.NT_UART = UART2; //Используемый в драйвере номер UART (1,2,3)
p->MBInternals.NT_UART->CR_bit.UARTEN = 1; // Разрешить работу UART
#endif
//Текущая реализация драйвера не использует FIFO, обрабатывает данные по одному байту
//и вызывается в прерывании 10кГц. Поэтому частоты обмена больше 57600 не поддерживаются (будет терять байты)
if (p->BaudRate > 57600)
p->BaudRate = 57600;
// Настройка частоты в двух регистрах:
// задание делителя частоты для получения BaudRate
// Т.к. блок UART тактируется с частотой 25 МГц (так настроено в ините микроконтроллера),
// то для получения частоты, например, 57600 бит/с необходим
// делитель 25000000 / (16 * 57600) = 27,126736111111111111111111111111
// Целая часть I = 27
// Дробная часть F = (int)( 0.126736111*64 + 0.5 ) = 8
// Формулы см. в документации
float DivResFloat = (float) UART_CLOCK_FREQ / (16 * p->BaudRate);
long DivResInt = (long) DivResFloat;
long DivResFrac = (int) ((DivResFloat - DivResInt) * 64 + 0.5);
p->MBInternals.NT_UART->IBRD_bit.DIVINT = DivResInt;
p->MBInternals.NT_UART->FBRD_bit.DIVFRAC = DivResFrac;
// 8 бит данных, 1 стоп бит, без контроля четности
p->MBInternals.NT_UART->LCRH_bit.SPS = 0; // Нет проверки четности
p->MBInternals.NT_UART->LCRH_bit.WLEN = 3; // Длина посылки 8 бит
p->MBInternals.NT_UART->LCRH_bit.FEN = 0; // Не использовать FIFO
p->MBInternals.NT_UART->CR_bit.TXE = 1; // Разрешить приём
p->MBInternals.NT_UART->CR_bit.RXE = 1; // Разрешить передачу
p->MBInternals.NT_UART->LCRH_bit.STP2 = 0; // 1 стоп-бит
}
void ModBus_ResetError(TModBus *p) {
// Биты 0-3 - биты ошибок, сбрасываются записью в них "1"
p->MBInternals.NT_UART->RSR |= 0x000F;
}
int16 ModBus_CheckDataReady(TModBus *p) {
// return 1 - если буфер приёмника не пуст
return (!p->MBInternals.NT_UART->FR_bit.RXFE);
}
int16 ModBus_CheckTxEmpty(TModBus *p) //Если все отправлено (пуст и основной и теневой регистры)
{
// return 1 - если буфер передатчика пуст
return (p->MBInternals.NT_UART->FR_bit.TXFE);
}
int16 ModBus_CheckTxReady(TModBus *p) //В передатчик можно положить следующий символ (буфер свободен)
{
// "1" - если буфер передатчика пуст
return (p->MBInternals.NT_UART->FR_bit.TXFE);
}
void ModBus_Tx(TModBus *p, int16 data) // Передача данных
{
Uint8 tmp_data = data;
p->MBInternals.NT_UART->DR_bit.DATA = tmp_data;
}
//!Инициализация.
//!настройка таймаутов,
//!обработка словаря объектов для последующего быстрого поиска
//! \memberof TModBus
void ModBus_Init(TModBus *p) {
Uint16 x;
ModBus_RS_Init(p);
p->MBInternals.TimeOut1_5 = (int16) (((int32) p->ExecutionFreq * (int32) 17)
/ p->BaudRate + 2); // 17 ~ 11*1.5
p->MBInternals.TimeOut2_5 = (int16) (((int32) p->ExecutionFreq * (int32) 28)
/ p->BaudRate); // 28 ~ 11*2.5
p->MBInternals.RecievedCounter = -1;
////// HR
// поиск размера массива HR
x = 0;
while (mbodHR[x].index != 0)
x++;
p->MBInternals.NumOfHRs = x;
// поиск среднего элемента массива HR
p->MBInternals.MiddleOfHRs = x;
x = 0;
while ((p->MBInternals.MiddleOfHRs >> 1) != 0) {
p->MBInternals.MiddleOfHRs >>= 1;
x = x + x + 1;
}
p->MBInternals.MiddleOfHRs = x;
// поиск начального инкремента для метода последовательного
// приближения
p->MBInternals.InitialStepOfHRs = 1;
while (x != 0) {
x >>= 1;
p->MBInternals.InitialStepOfHRs <<= 1;
}
p->MBInternals.InitialStepOfHRs >>= 1;
////// Coils
// поиск размера массива C
x = 0;
while (mbodC[x].index != 0)
x++;
p->MBInternals.NumOfCs = x;
// поиск среднего элемента массива C
p->MBInternals.MiddleOfCs = x;
x = 0;
while ((p->MBInternals.MiddleOfCs >> 1) != 0) {
p->MBInternals.MiddleOfCs >>= 1;
x = x + x + 1;
}
p->MBInternals.MiddleOfCs = x;
// поиск начального инкремента для метода последовательного
// приближения
p->MBInternals.InitialStepOfCs = 1;
while (x != 0) {
x >>= 1;
p->MBInternals.InitialStepOfCs <<= 1;
}
p->MBInternals.InitialStepOfCs >>= 1;
// Discrete Inputs
// поиск размера массива DI
x = 0;
while (mbodDI[x].index != 0)
x++;
p->MBInternals.NumOfDIs = x;
// поиск среднего элемента массива DI
p->MBInternals.MiddleOfDIs = x;
x = 0;
while ((p->MBInternals.MiddleOfDIs >> 1) != 0) {
p->MBInternals.MiddleOfDIs >>= 1;
x = x + x + 1;
}
p->MBInternals.MiddleOfDIs = x;
// поиск начального инкремента для метода последовательного
// приближения
p->MBInternals.InitialStepOfDIs = 1;
while (x != 0) {
x >>= 1;
p->MBInternals.InitialStepOfDIs <<= 1;
}
p->MBInternals.InitialStepOfDIs >>= 1;
////// IR
// поиск размера массива HR
x = 0;
while (mbodIR[x].index != 0)
x++;
p->MBInternals.NumOfIRs = x;
// поиск среднего элемента массива HR
p->MBInternals.MiddleOfIRs = x;
x = 0;
while ((p->MBInternals.MiddleOfIRs >> 1) != 0) {
p->MBInternals.MiddleOfIRs >>= 1;
x = x + x + 1;
}
p->MBInternals.MiddleOfIRs = x;
// поиск начального инкремента для метода последовательного
// приближения
p->MBInternals.InitialStepOfIRs = 1;
while (x != 0) {
x >>= 1;
p->MBInternals.InitialStepOfIRs <<= 1;
}
p->MBInternals.InitialStepOfIRs >>= 1;
for (x = 0; x < 1000; x++)
;
}
//!Расчет
//!Фунция обработки посылок ModBus
//! \memberof TModBus
void ModBus_Execute(TModBus *p) {
Uint16 x;
volatile Uint16 RxReg;
if (ModBus.Enabled == 1) { // Если включен MODBUS
p->OfflineCounter += 1;
//долго нет собщений по сети?
if (p->OfflineCounter > p->OfflineCounterMax) {
p->isOnline = 0; //Мы не в сети
p->OfflineCounter = p->OfflineCounterMax + 1; //чтоб не убежал
} else
p->isOnline = 1; //в сети
//Контроль ошибок
if (p->errorCode) { //Если висит ошибка
p->error += 1;
if (p->AutoRestart == 1) //Если разрешен авто сброс ошибок
ModBus_ResetError(p);
}
if (p->clear_error == 1) //Если выставлен флаг однократного ручного сброса ошибки
{
ModBus_ResetError(p);
p->clear_error = 0;
p->error = 0;
}
//Текущее значение GPIO для отладки
p->GPIOsValue = MODBUS_GPIO_VALUE;
if (p->MBInternals.TxState < 1) //TxState==0 - передача не идет
if (ModBus_CheckDataReady(p)) //Если есть готовые принятные данные (байт)
{
p->MBInternals.TimeOut = p->MBInternals.TimeOut1_5; //Таймаут равный полтора символа
RxReg = p->MBInternals.NT_UART->DR; //Прием очередного символа
p->errorCode = (RxReg & 0x0F00) >> 8;
RxReg = RxReg & 0xFF;
p->received_data = RxReg; //Перекладывание принятых данных для отладки
p->ReceiveByteCounter++;
if (p->MBInternals.InCount == MODBUS_MAX_RX_COUNT) //Принятно слишком много байт
return;
p->MBInternals.In[p->MBInternals.InCount++] = RxReg; //Принятые данные в массив
p->MBInternals.RxCRC ^= RxReg; //Сразу же расчет контрольной суммы
for (RxReg = 0; RxReg < 8; RxReg++) //Это тоже продолжение расчета контрольной суммы
if (p->MBInternals.RxCRC & 0x01) {
p->MBInternals.RxCRC >>= 1;
p->MBInternals.RxCRC ^= p->MBInternals.MagicNumber;
} else
p->MBInternals.RxCRC >>= 1;
//больше ничего, если есть принятые данные, не делается
return;
}
if (p->MBInternals.TimeOut == 0) //Когда таймаут вышел, его обрабатывает условие p->MBInternals.TimeOut==1, а равен нулю он становится после приема
{
p->MBInternals.InCount = 0; //Обнуление счетчика массива
p->MBInternals.RxCRC = 0xFFFF; //Инициализация контрольной суммы на прием
if (ModBus_CheckTxEmpty(p)) //Если буфер на отправку пуст
{
MODBUS_RX_RS485; //Переключение RS485 на прием
p->MBInternals.TxState = 0; //TxState==0 - передача не идет
p->MBInternals.TxCRC = 0xFFFF; //Инициализация контрольной суммы на передачу
}
return;
}
if (p->MBInternals.TimeOut == 1) //; Сюда попадаем, когда межу символами появляется пауза в 1,5 символа
if (p->MBInternals.InCount != 0) //; Если количество входных данных не равно нулю, то рассматривем, что пришло
{
//поддержка broadcast осуществляется тут (по другому я незнаю как еще - Алямкин)
//далее переход в передачу - нам туда не нужно, потому обрабатываем здесь
//обрабатывать имеет смысл только команды на запись (0x5 - write coils и 0x6 - write single register).
if (p->MBInternals.In[0] == 0)//Входной массив, байт адреса равен 0 - широковещательный
{
//0x5 - write coils
if (p->MBInternals.In[1] == 5) {
x = (p->MBInternals.In[4] << 8) + p->MBInternals.In[5]; //Данные
//0 - если нашла, 3 - если запрос некорректен, 2 - ошибка в поиске
p->MBInternals.temp = ModBus_FindVocAddr(p, mbodC,
p->MBInternals.NumOfCs, 1,
(p->MBInternals.In[2] << 8)
+ p->MBInternals.In[3], 1,
p->MBInternals.MiddleOfCs,
p->MBInternals.InitialStepOfCs);
if ((x != 0xFF00) && (x != 0x0000)) //Данные не валидны, для битовой переменной должны быть FF00 или 0000
p->MBInternals.temp = 3;//делается как будто ModBus_FindVocAddr вернула некорректный запрос
if (p->MBInternals.temp == 0)//если ModBus_FindVocAddr нашла адрес
{
if (p->MBInternals.In[4] == 0) // reset bit
*(Uint16 *) (p->MBInternals.Addr->addr) &=
(0xFFFF
- (1
<< p->MBInternals.Addr->type_or_acc));
else
// set bit
*(Uint16 *) (p->MBInternals.Addr->addr) |= (1
<< p->MBInternals.Addr->type_or_acc);
}
}
if (p->MBInternals.In[1] == 6) //0x6 - write HR
{
p->MBInternals.temp = ModBus_FindVocAddr(p, mbodHR,
p->MBInternals.NumOfHRs, 16,
(p->MBInternals.In[2] << 8)
+ p->MBInternals.In[3], 1,
p->MBInternals.MiddleOfHRs,
p->MBInternals.InitialStepOfHRs);
if (p->MBInternals.temp == 0) //если ModBus_FindVocAddr нашла адрес
{
*(Uint16 *) (p->MBInternals.Addr->addr) =
(p->MBInternals.In[4] << 8)
+ p->MBInternals.In[5];
}
}
//делаем то же самое, что и ниже для правильной отбраковки сообщения и выходим
p->MBInternals.InCount = 0; //обнуление массива принятых байт
p->MBInternals.TimeOut = 0; //обнуление таймаута
p->MBInternals.RxCRC = 0xFFFF; //инициализация контрольной суммы
return;
}
if (p->MBInternals.In[0] != p->RSNodeID) //; Если номер узла не совпал с нашим, то выкидываем посылку.
{
p->MBInternals.InCount = 0;
p->MBInternals.TimeOut = 0;
p->MBInternals.RxCRC = 0xFFFF;
return;
}
if (p->MBInternals.RxCRC != 0) //; Если не сошлась контрольная сумма, то выкидываем посылку.
{
p->MBInternals.InCount = 0;
p->MBInternals.TimeOut = 0;
p->MBInternals.RxCRC = 0xFFFF;
return;
}
if (p->MBInternals.RecievedCounter < 0) //!!! //; Если еще не проинициализирован счетчик между фреймов (-1), то
{
//; инициализируем счетчик и выходим.
p->MBInternals.RecievedCounter = p->MBInternals.TimeOut2_5;
return;
}
if (p->MBInternals.RecievedCounter > 0) //!!! //; Если счетчик паузы между фреймов еще положительный, то уменьшаем его
{
//; и выходим
p->MBInternals.RecievedCounter--;
return;
}
//; Если счетчик RecievedCounter досчитал до нуля, то можно переключаться на передачу.
p->MBInternals.RecievedCounter = -1;
p->ReceivePacketCounter++;
MODBUS_TX_RS485; //RS485 на передачу
p->MBInternals.TxState = 1; //Передача
p->MBInternals.RxCRC = 0xFFFF;
p->MBInternals.TimeOut = p->MBInternals.TimeOut2_5;
ModBus_Tx(p, p->MBInternals.In[0]); //Передается первый байт - адрес устройства, почему-то взят из приема...
p->MBInternals.TxCRC ^= p->MBInternals.In[0]; //сразу расчет контрольноу суммы на передачу
//и это тоже расчет контрольной суммы
for (RxReg = 0; RxReg < 8; RxReg++)
if (p->MBInternals.TxCRC & 0x01) {
p->MBInternals.TxCRC >>= 1;
p->MBInternals.TxCRC ^= p->MBInternals.MagicNumber;
} else
p->MBInternals.TxCRC >>= 1;
return;
} else //количество принятых данных равно нулю.. почему-то
{
p->MBInternals.TimeOut = 0;
return;
}
p->MBInternals.TimeOut--; //отсчитывается таймаут
if (p->MBInternals.TxState < 1) //если TxState==0 - нет передачи, т выход, т.к. ниже - передача.
return;
if (ModBus_CheckTxReady(p) == 0) //если передатчик занят
return;
//Инициализация таймаута
p->MBInternals.TimeOut = p->MBInternals.TimeOut2_5;
// с этого момента включается дискретный автомат
// протокола
//p->TxState=0;
if (p->MBInternals.TxState == 1) //Состояние передачи 1
{
p->OfflineCounter = 0; //Счетчик для контроля пересылаемых пакетов ModBus
p->MBInternals.temp = p->MBInternals.In[1]; //Принятый массив, тут номер функции
if (p->MBInternals.temp == 1) // Функция read Coils
{
p->MBInternals.ToSend = p->MBInternals.temp; //для отправки - номер функции
p->MBInternals.temp = ModBus_FindVocAddr(p, mbodC,
p->MBInternals.NumOfCs, 1,
(p->MBInternals.In[2] << 8) + p->MBInternals.In[3],
(p->MBInternals.In[4] << 8) + p->MBInternals.In[5],
p->MBInternals.MiddleOfCs,
p->MBInternals.InitialStepOfCs);
if (p->MBInternals.temp == 0) //в словаре найден элемент
{
p->MBInternals.TxState = 10;
} else //ошибка, в словаре элемент не найден
{
p->MBInternals.ToSend |= 0x80; //добавляется маска ошибки
p->MBInternals.TxState = p->MBInternals.temp + 3;
}
} else if (p->MBInternals.temp == 2) // Код функции read DI
{
p->MBInternals.ToSend = p->MBInternals.temp; //для отправки - номер функции
p->MBInternals.temp = ModBus_FindVocAddr(p, mbodDI,
p->MBInternals.NumOfDIs, 1,
(p->MBInternals.In[2] << 8) + p->MBInternals.In[3],
(p->MBInternals.In[4] << 8) + p->MBInternals.In[5],
p->MBInternals.MiddleOfDIs,
p->MBInternals.InitialStepOfDIs);
if (p->MBInternals.temp == 0) //в словаре найден элемент
{
p->MBInternals.TxState = 10;
} else //ошибка, в словаре элемент не найден
{
p->MBInternals.ToSend |= 0x80; //добавляется маска ошибки
p->MBInternals.TxState = p->MBInternals.temp + 3;
}
} else if (p->MBInternals.temp == 3) // Функция read HR
{
p->MBInternals.ToSend = p->MBInternals.temp;
p->MBInternals.temp = ModBus_FindVocAddr(p, mbodHR,
p->MBInternals.NumOfHRs, 16,
(p->MBInternals.In[2] << 8) + p->MBInternals.In[3],
(p->MBInternals.In[4] << 8) + p->MBInternals.In[5],
p->MBInternals.MiddleOfHRs,
p->MBInternals.InitialStepOfHRs);
if (p->MBInternals.temp == 0) //в словаре найден элемент
{
p->MBInternals.TxState = 7;
} else //ошибка, в словаре элемент не найден
{
p->MBInternals.ToSend |= 0x80; //добавляется маска ошибки
p->MBInternals.TxState = p->MBInternals.temp + 3;
}
} else if (p->MBInternals.temp == 4) // Функция read IR
{
p->MBInternals.ToSend = p->MBInternals.temp;
p->MBInternals.temp = ModBus_FindVocAddr(p, mbodIR,
p->MBInternals.NumOfIRs, 16,
(p->MBInternals.In[2] << 8) + p->MBInternals.In[3],
(p->MBInternals.In[4] << 8) + p->MBInternals.In[5],
p->MBInternals.MiddleOfIRs,
p->MBInternals.InitialStepOfIRs);
if (p->MBInternals.temp == 0) //в словаре найден элемент
{
p->MBInternals.TxState = 7;
} else //ошибка, в словаре элемент не найден
{
p->MBInternals.ToSend |= 0x80; //добавляется маска ошибки
p->MBInternals.TxState = p->MBInternals.temp + 3;
}
} else if (p->MBInternals.temp == 5) // Функция write Coil
{
p->MBInternals.ToSend = p->MBInternals.temp;
x = (p->MBInternals.In[4] << 8) + p->MBInternals.In[5]; //Данные
p->MBInternals.temp = ModBus_FindVocAddr(p, mbodC,
p->MBInternals.NumOfCs, 1,
(p->MBInternals.In[2] << 8) + p->MBInternals.In[3], 1,
p->MBInternals.MiddleOfCs,
p->MBInternals.InitialStepOfCs);
if ((x != 0xFF00) && (x != 0x0000)) //Данные не валидны - можно только 0xFF00 и 0x0000
p->MBInternals.temp = 3; //Как будто бы ModBus_FindVocAddr вернула ошибку
if (p->MBInternals.temp == 0) //в словаре найден элемент
{
p->MBInternals.TxState = 12;
if (p->MBInternals.In[4] == 0) // Операция над словарем - reset bit
*(Uint16 *) (p->MBInternals.Addr->addr) &= (0xFFFF
- (1 << p->MBInternals.Addr->type_or_acc));
else
// set bit
*(Uint16 *) (p->MBInternals.Addr->addr) |= (1
<< p->MBInternals.Addr->type_or_acc);
p->Refresh = 1;
} else //ошибка, в словаре элемент не найден
{
p->MBInternals.ToSend |= 0x80; //добавляется маска ошибки
p->MBInternals.TxState = p->MBInternals.temp + 3;
}
} else if (p->MBInternals.temp == 6) // Функция write HR
{
p->MBInternals.ToSend = p->MBInternals.temp;
p->MBInternals.temp = ModBus_FindVocAddr(p, mbodHR,
p->MBInternals.NumOfHRs, 16,
(p->MBInternals.In[2] << 8) + p->MBInternals.In[3], 1,
p->MBInternals.MiddleOfHRs,
p->MBInternals.InitialStepOfHRs);
if (p->MBInternals.temp == 0) //в словаре найден элемент
{
p->MBInternals.TxState = 12;
//Операция над словарем - запись регистра
*(Uint16 *) (p->MBInternals.Addr->addr) =
(p->MBInternals.In[4] << 8) + p->MBInternals.In[5];
p->MBInternals.Addr->type_or_acc = MB_VAR_WRITE;
} else //ошибка, в словаре элемент не найден
{
p->MBInternals.ToSend |= 0x80; //добавляется маска ошибки
p->MBInternals.TxState = p->MBInternals.temp + 3;
}
} else //никакая из поддерживаемых функций
{
p->MBInternals.ToSend = p->MBInternals.temp | 0x80; //добавляется маска ошибки
p->MBInternals.TxState = 2;
}
} else if (p->MBInternals.TxState == 12) // send addr hi for write C
{
p->MBInternals.TxState = 13;
p->MBInternals.ToSend = p->MBInternals.In[2];
} else if (p->MBInternals.TxState == 13) // send addr low for write C
{
p->MBInternals.TxState = 14;
p->MBInternals.ToSend = p->MBInternals.In[3];
} else if (p->MBInternals.TxState == 14) // send data hi for write C
{
p->MBInternals.TxState = 15;
p->MBInternals.ToSend = p->MBInternals.In[4];
} else if (p->MBInternals.TxState == 15) // send data hi for write C
{
p->MBInternals.TxState = 3;
p->MBInternals.ToSend = p->MBInternals.In[5];
} else if (p->MBInternals.TxState == 10) // send length read Coils
{
p->MBInternals.TxState = 11;
p->MBInternals.In[5] = p->MBInternals.In[5]
+ (p->MBInternals.In[4] << 8);
p->MBInternals.ToSend = (p->MBInternals.In[5] + 7) >> 3;
} else if (p->MBInternals.TxState == 11) // send data read Coils
{
p->MBInternals.ToSend = 0;
for (x = 0; x < 8; x++) //Можно упаковать 8 битовых переменных за раз
{
if (p->MBInternals.In[5] != 0) //количество запрашиваемых элементов словаря
{
//Отправка элемента словаря
p->MBInternals.ToSend |=
(((*(Uint16 *) (p->MBInternals.Addr->addr))
>> (p->MBInternals.Addr->type_or_acc))
& 0x01) << x;
p->MBInternals.Addr++;
p->MBInternals.In[5]--;
}
if (p->MBInternals.In[5] == 0) //Если все отправили
p->MBInternals.TxState = 3;
}
} else if (p->MBInternals.TxState == 7) // send length read HR
{
p->MBInternals.TxState = 8;
p->MBInternals.ToSend = p->MBInternals.In[5] << 1;
} else if (p->MBInternals.TxState == 8) // send HR high word
{
p->MBInternals.TxState = 9;
//x= *p->MBInternals.Addr->addr;
p->MBInternals.temp = *(Uint16 *) (p->MBInternals.Addr->addr);
p->MBInternals.ToSend = p->MBInternals.temp >> 8;
} else if (p->MBInternals.TxState == 9) // send HR low word
{
p->MBInternals.ToSend = p->MBInternals.temp & 0xFF;
p->MBInternals.Addr->type_or_acc = MB_VAR_READ;
p->MBInternals.Addr += 1;
p->MBInternals.In[5]--; //уменьшение кол-ва запрошенных переменных во входном массиве
if (p->MBInternals.In[5] == 0) //Если это количество равно нулю (все переменные отправили)
p->MBInternals.TxState = 3;
else
p->MBInternals.TxState = 8;
} else if (p->MBInternals.TxState == 2) // no such function
{
p->MBInternals.ToSend = 1;
p->MBInternals.TxState = 3;
} else if (p->MBInternals.TxState == 5) // send error 2
{
p->MBInternals.ToSend = 2;
p->MBInternals.TxState = 3;
} else if (p->MBInternals.TxState == 6) // send error 3
{
p->MBInternals.ToSend = 3;
p->MBInternals.TxState = 3;
} else if (p->MBInternals.TxState == 3) // tx crc low
{
p->MBInternals.ToSend = p->MBInternals.TxCRC & 0x00FF;
p->MBInternals.TxState = 4;
} else if (p->MBInternals.TxState == 4) // tx crc high
{
p->MBInternals.ToSend = p->MBInternals.TxCRC & 0x00FF;
p->MBInternals.TxState = 0;
} else
p->MBInternals.TxState = 0;
p->MBInternals.TimeOut = p->MBInternals.TimeOut2_5;
ModBus_Tx(p, p->MBInternals.ToSend);
p->MBInternals.TxCRC ^= p->MBInternals.ToSend;
for (RxReg = 0; RxReg < 8; RxReg++)
if (p->MBInternals.TxCRC & 0x01) {
p->MBInternals.TxCRC >>= 1;
p->MBInternals.TxCRC ^= p->MBInternals.MagicNumber;
} else
p->MBInternals.TxCRC >>= 1;
return;
}
}
//!Вспомогательная функция поиска
//!функция ищет элемент в таблице и возвращает ссылку на него в p->MBInternals.Addr
//!возвращает:
//! 0 - если нашла
//! 3 - если запрос некорректен
//! 2 - ошибка в пойске
//! \memberof TModBus
int16 ModBus_FindVocAddr(TModBus *p, volatile MB_Record /*const*/Table[],
Uint16 TableSize, int16 Type, Uint16 Index, int16 NumOfIndexs,
int16 Mid, int16 Step) {
int16 x = 0;
if (Type == 16) {
if (NumOfIndexs == 0)
return (3);
if (NumOfIndexs > 0x7D)
return (3);
} else {
if (NumOfIndexs == 0)
return (3);
if (NumOfIndexs > 0x7D0)
return (3);
}
x += Mid;
Step <<= 1;
do {
Step >>= 1;
if (Index == Table[x].index) {
if ((x + NumOfIndexs) > TableSize)
return (2);
p->MBInternals.Addr = &Table[x];
return (0);
} else if (Index < Table[x].index)
x -= Step;
else {
x += Step;
if (x >= TableSize)
x = (TableSize - 1);
}
} while (Step != 0);
return (2);;
}
/*@}*/

1172
Vsrc/V_MotorModel.c Normal file

File diff suppressed because it is too large Load Diff

815
Vsrc/V_PWM_Module.c Normal file
View File

@ -0,0 +1,815 @@
/*!
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"
#ifdef HW_VECTORCARD_DRV8301_EVM
#define GPIO_INV_ON NT_GPIOG->MASKHIGHBYTE_bit[(1<<(8-8))].MASKHB = (1<<(8-8))
//Äëÿ äàííîé êîíôèãóðàöèè âûêëþ÷åíèå èíâåðòîðà àïïàðàòíîå íå èñïîëüçóåòñÿ, âûêëþ÷åíèå êëþ÷åé îñóùåñòâëÿåòñÿ âûâîäàìè óïðàëâåíèÿ êëþ÷àìè
#define GPIO_INV_OFF NT_GPIOG->MASKHIGHBYTE_bit[(1<<(8-8))].MASKHB = (1<<(8-8))
#endif
#ifdef HW_VECTORCARD_DRV8312_EVM
//A[10], F[2], F[4]
#define GPIO_INV_ON NT_GPIOA->MASKHIGHBYTE_bit[(1<<(10-8))].MASKHB = (1<<(10-8)); NT_GPIOF->MASKLOWBYTE_bit[(1<<2)].MASKLB = (1<<2);NT_GPIOF->MASKLOWBYTE_bit[(1<<4)].MASKLB = (1<<4)
#define GPIO_INV_OFF NT_GPIOA->MASKHIGHBYTE_bit[(1<<(10-8))].MASKHB = 0;NT_GPIOF->MASKLOWBYTE_bit[(1<<2)].MASKLB = 0;NT_GPIOF->MASKLOWBYTE_bit[(1<<4)].MASKLB = 0
#endif
#if defined(HW_VECTORCARD_SIMULATOR) || defined(HW_NIIET_BOARD_SIMULATOR)
#define GPIO_INV_ON
#define GPIO_INV_OFF
#endif
#if defined(HW_VECTOR_MK_40_4)
#define GPIO_INV_ON
#define GPIO_INV_OFF
#endif
#if defined(HW_MOTORCONTROLBOARD)
#define GPIO_INV_ON
#define GPIO_INV_OFF
#endif
//! Èíèöèàëèçàöèÿ
//! \memberof TPWM_Module
void PWM_Module_Init(TPWM_Module *p) {
SIU->PWMSYNC_bit.PRESCRST = 0; //ñèíõðîíèçàöèÿ òàéìåðîâ - ñáðîñ âíóòðåííèõ ñ÷åò÷èêîâ
// ------------------------------------------------------------------------
// Íàñòðàèâàåì ìîäóëü ePWM1
// ------------------------------------------------------------------------
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(APB0BusClock/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 zero
PWM0->CMPCTL_bit.SHDWBMODE = CC_SHADOW; //âêëþ÷èòü SHADOW äëÿ ñðàâíåíèÿ
PWM0->CMPCTL_bit.LOADBMODE = CC_CTR_ZERO; // Load on 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;
PWM0->DBCTL_bit.INMODE = DBA_RED_DBB_FED; //s4=0, s5=1 íà êàðòèíêå DT
PWM0->DBCTL_bit.OUTMODE = DB_FULL_ENABLE; //S1=1, S2=2 íà êàðòèíêå DT
PWM0->DBCTL_bit.POLSEL = DB_ACTV_HIC; // PWM1B = !PWM1A; S2=0, S3=1
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)
// ------------------------------------------------------------------------
// Íàñòðàèâàåì ìîäóëü ePWM2
// ------------------------------------------------------------------------
// 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 zero
PWM1->CMPCTL_bit.SHDWBMODE = CC_SHADOW; //âêëþ÷èòü SHADOW äëÿ ñðàâíåíèÿ
PWM1->CMPCTL_bit.LOADBMODE = CC_CTR_ZERO; // Load on 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
//ðàçðåøàåì TZ áûòü èñòî÷íèêîì àïïàðàòíîé àâàðèè (one-shot)
// PWM1->TZSEL_bit.OSHT1 = TZ_ENABLE;
// PWM1->TZSEL_bit.OSHT2 = TZ_ENABLE;
// PWM1->TZSEL_bit.OSHT3 = TZ_ENABLE;
// Trip-Zone
PWM1->TZCTL_bit.TZA = TZ_STATE; // ïî ñîáûòèþ "One-Shot Trip" ïåðåâîäèì
PWM1->TZCTL_bit.TZB = TZ_STATE; // ØÈÌ âûõîäû â íóæíîå ñîñòîÿíèå
// ------------------------------------------------------------------------
// Íàñòðàèâàåì ìîäóëü ePWM3
// ------------------------------------------------------------------------
// 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 zero
PWM2->CMPCTL_bit.SHDWBMODE = CC_SHADOW; //âêëþ÷èòü SHADOW äëÿ ñðàâíåíèÿ
PWM2->CMPCTL_bit.LOADBMODE = CC_CTR_ZERO; // Load on 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
//ðàçðåøàåì TZ áûòü èñòî÷íèêîì àïïàðàòíîé àâàðèè (one-shot)
// PWM2->TZSEL_bit.OSHT1 = TZ_ENABLE;
// PWM2->TZSEL_bit.OSHT2 = TZ_ENABLE;
// PWM2->TZSEL_bit.OSHT3 = TZ_ENABLE;
// Trip-Zone
PWM2->TZCTL_bit.TZA = TZ_STATE; // ïî ñîáûòèþ "One-Shot Trip" ïåðåâîäèì
PWM2->TZCTL_bit.TZB = TZ_STATE; // ØÈÌ âûõîäû â íóæíîå ñîñòîÿíèå
// ------------------------------------------------------------------------
// Íàñòðàèâàåì ìîäóëü ePWM3 ïîä ÀÖÏ
// ------------------------------------------------------------------------
// Setup TBCLK
PWM3->TBPRD = PWM0->TBPRD;
PWM3->TBPHS_bit.TBPHS = 0x0001; // Ôàçà ðàâíà 1 èç-çà çàäåðæêè â îäèí òàêò íà ñèíõðîíèçàöèþ
PWM3->TBCTR = 0x0000; // Clear counter
// Setup counter mode
PWM3->TBCTL_bit.PRDLD = TB_SHADOW; // çàãðóçêà TBPRD ïðè TBCTR = 0
PWM3->TBCTL_bit.CTRMODE = TB_COUNT_UPDOWN; // Count up-down
PWM3->TBCTL_bit.PHSEN = TB_ENABLE; // Enable phase loading
PWM3->TBCTL_bit.PHSDIR = TB_UP; // Ñ÷èòàòü ââåðõ ïîñëå çàãðóçêè ôàçû
PWM3->TBCTL_bit.HSPCLKDIV = 0; // High Speed Time-base Clock Prescale
PWM3->TBCTL_bit.CLKDIV = 0; // Time-base Clock Prescale
PWM3->TBCTL_bit.SYNCOSEL = TB_SYNC_IN; // ðàçðåøàåì âûäà÷ó ñèíõðî-ñèãíàëà
// Interrupt where we will change the Compare Values
PWM3->ETSEL_bit.INTSEL = ET_DISABLE; // Disable INT
PWM3->ETSEL_bit.INTEN = 0; // Disable INT
PWM3->ETSEL_bit.SOCAEN = 1; // Ðàçðåøèòü çàïóñê àöï
PWM3->ETSEL_bit.SOCASEL = 1; // Çàïóñêàòü ïðè CTR == 0 (Underflow)
//ñáðàñûâàåì âñå ôëàãè àâàðèé
PWM0->TZCLR = 0x7;
PWM1->TZCLR = 0x7;
PWM2->TZCLR = 0x7;
//íàñòðîéêà íîæåê
#ifdef HW_VECTORCARD_DRV8301_EVM
//ØÈÌ 6 âûâîäîâ
NT_GPIOG->ALTFUNCSET = (1 << 2) + (1 << 3) + (1 << 4); //ePWMxA(0), (1), (2)
NT_GPIOA->ALTFUNCSET = (1 << 10); //ePWMxB(0)
NT_GPIOF->ALTFUNCSET = (1 << 2) + (1 << 4); //ePWMxB(1), (2)
// Ïåðèôåðèéíàÿ ôóíêöèÿ - PWM
NT_COMMON_REG->GPIOPCTLA_bit.PIN10 = 2;//ePWMxB(0)
NT_COMMON_REG->GPIOPCTLF_bit.PIN2 = 0;//ePWMxB(1)
NT_COMMON_REG->GPIOPCTLF_bit.PIN4 = 0;//ePWMxB(2)
NT_COMMON_REG->GPIOPCTLG_bit.PIN2 = 0;//ePWMxA(0)
NT_COMMON_REG->GPIOPCTLG_bit.PIN3 = 0;//ePWMxA(1)
NT_COMMON_REG->GPIOPCTLG_bit.PIN4 = 0;//ePWMxA(2)
//NT_GPIOG->DATAOUT |= (1 << 6);
NT_GPIOG->OUTENSET = (1 << 6); //InvEnable
#endif
#if defined(HW_VECTORCARD_DRV8312_EVM)
//ØÈÌ 3 âûâîäà óïðàâëåíèÿ âåðõíèìè êëþ÷àìè (íèæíèå êëþ÷è ØÈÌÿò ñàìè äðàéâåðîì)
NT_GPIOG->ALTFUNCSET = (1 << 2) + (1 << 3) + (1 << 4); //ePWMxA(0), (1), (2)
// Ïåðèôåðèéíàÿ ôóíêöèÿ - PWM
NT_COMMON_REG->GPIOPCTLG_bit.PIN2 = 0;//ePWMxA(0)
NT_COMMON_REG->GPIOPCTLG_bit.PIN3 = 0;//ePWMxA(1)
NT_COMMON_REG->GPIOPCTLG_bit.PIN4 = 0;//ePWMxA(2)
//âûêëþ÷àåì àëüòåðíàòèâíûå ôóíêöèè (íà âñÿêèé)
NT_GPIOA->ALTFUNCCLR = (1 << 10); //A[10]
NT_GPIOF->ALTFUNCCLR = (1 << 2) + (1 << 4); //F[2], F[4]
//A[10], F[2], F[4] íîæêè ðåçåòà
NT_GPIOA->OUTENSET = (1 << 10);
NT_GPIOF->OUTENSET = (1 << 2);
NT_GPIOF->OUTENSET = (1 << 4);
#endif
#ifdef HW_VECTOR_MK_40_4
NT_GPIOG->ALTFUNCSET_bit.ALTFUNCSET = (1 << 2) + (1 << 3) + (1 << 4); //ePWMxA(0), (1), (2)
NT_GPIOF->ALTFUNCSET_bit.ALTFUNCSET = (1 << 0) + (1 << 2) + (1 << 4); //ePWMxB(0), (1), (2)
// Ïåðèôåðèéíàÿ ôóíêöèÿ - PWM
NT_COMMON_REG->GPIOPCTLF_bit.PIN0 = 0;//ePWMxB(0)
NT_COMMON_REG->GPIOPCTLF_bit.PIN2 = 0;//ePWMxB(1)
NT_COMMON_REG->GPIOPCTLF_bit.PIN4 = 0;//ePWMxB(2)
NT_COMMON_REG->GPIOPCTLG_bit.PIN2 = 0;//ePWMxA(0)
NT_COMMON_REG->GPIOPCTLG_bit.PIN3 = 0;//ePWMxA(1)
NT_COMMON_REG->GPIOPCTLG_bit.PIN4 = 0;//ePWMxA(2)
//Âõîä àïïàðàòíîé àâàðèè
NT_GPIOA->ALTFUNCCLR = (1<<8); //A[8]
#endif
#ifdef HW_MOTORCONTROLBOARD
//ØÈÌ 6 âûâîäîâ
// â GpioPeripheralInit
#endif
//Ñèíõðîííûé çàïóñê ØÈÌ
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;
}
void PWM_Module_DC_Update(TPWM_Module *p)
{
int32 UalphaRef = 0, UbetaRef = 0;
int32 gamma1_DC = 0, gamma2_DC = 0;
int32 temp32;
UalphaRef = p->UalphaRef;
UbetaRef = p->UbetaRef;
if (UalphaRef > _IQ(1))
UalphaRef = _IQ(1);
else if (UalphaRef < _IQ(-1))
UalphaRef = _IQ(-1);
if (UbetaRef > _IQ(1))
UbetaRef = _IQ(1);
else if (UbetaRef < _IQ(0))
UbetaRef = _IQ(0);
//äàííîå ïðåîáðàçîâàíèå äà¸ò âîçìîæíîñòü îòðàáàòûâàòü íàïðÿæåíèÿ â äèàïàçîíå -1 - 0 - +1 (â îòíîñèòåëüíûõ åäèíèöàõ)
//Íàïðÿæåíèå 1 - ñêâàæíîñòü (1/2 + 0.5) = 1, Íàïðÿæåíèå 0 - ñêâàæíîñòü 0,5 è ò.ä.
gamma1_DC = -(UalphaRef >> 1) + _IQ(0.5); // (IQ), Ïðèâîäèì çàäàííîå íàïðÿæåíèå ê ñîîòâåòñòâóþùåé ñêâàæíîñòè.
//Íà íèçêèõ ÷àñòîòàõ âåëè÷èíà p->k_pwm áîëüøàÿ, çíà÷èò áîëüøîé ìîæåò áûòü è temp32.
//ïî-ýòîìó äëÿ ðàñ÷¸òîâ öåëåñîîáðàçíî èñïîëüçîâàòü ôîðìàò iq16.
gamma1_DC = gamma1_DC >> 8; // (IQ16) ïåðåâîäèì òî, ÷òî âûøå, â iq16.
temp32 = _IQ16mpy(gamma1_DC, _IQ16(p->k_pwm)); // (IQ16) ïåðåâîäèì ñêâàæíîñòü â âåëè÷èíó äëÿ çàãðóçêè â ðåãèñòð ñðàâíåíèÿ.
p->GammaA = temp32 >> 16; // (IQ0) Çàãðóæåì öåëóþ ÷àñòü â ðåãèñòð ñðàâíåíèÿ.
p->GammaB = p->k_pwm - p->GammaA; // â ðåãèñòðå ñðàâíåíèÿ EPwm2 òî æå, ÷òî è â EPwm1.
//Íà íèçêèõ ÷àñòîòàõ âåëè÷èíà p->k_pwm áîëüøàÿ, çíà÷èò áîëüøîé ìîæåò áûòü è temp32.
//ïî-ýòîìó äëÿ ðàñ÷¸òîâ öåëåñîîáðàçíî èñïîëüçîâàòü ôîðìàò iq16.
gamma2_DC = UbetaRef >> 8; // (IQ16) ïåðåâîäèì òî, ÷òî âûøå, â iq16.
temp32 = _IQ16mpy(gamma2_DC, _IQ16(p->k_pwm)); // (IQ16) ïåðåâîäèì ñêâàæíîñòü â âåëè÷èíó äëÿ çàãðóçêè â ðåãèñòð ñðàâíåíèÿ.
p->GammaC = p->k_pwm - (temp32 >> 16); // (IQ0) Çàãðóæåì öåëóþ ÷àñòü â ðåãèñòð ñðàâíåíèÿ.
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_DC_DRIVE: {
PWM_Module_DC_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(APB0BusClock/1000.0), p->Frequency << 1) >> 10; //ïåðèîä
PWM0->TBPRD = p->k_pwm;
//äëÿ âñåõ ñòîåê òî æå ñàìîå
PWM1->TBPRD = p->k_pwm;
PWM2->TBPRD = p->k_pwm;
PWM3->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;
}
PWM3->TBPHS_bit.TBPHS = 1;//ïîäáîð ñäâèãà äëÿ çàïóñêà ÀÖÏ: 1 - ðîâíî íà íóëå òàéìåðà
}
//! Ôóíêöèÿ âêëþ÷åíèÿ ØÈÌ (âêëþ÷åíèå èíâåðòîðà)
//! \memberof TPWM_Module
void PWM_Module_On(TPWM_Module *p) {
p->Enabled = 1; //ôëàã "âêëþ÷åíî"
// Ñíèìàåì ïðèíóäèòåëüíóþ óñòàíîâêó âûõîäîâ
PWM0->AQCSFRC = 0;
PWM1->AQCSFRC = 0;
PWM2->AQCSFRC = 0;
GPIO_INV_ON;
}
//! Ôóíêöèÿ âûêëþ÷åíèÿ ØÈÌ (âûêëþ÷åíèå èíâåðòîðà)
//! \memberof TPWM_Module
void PWM_Module_Off(TPWM_Module *p) {
p->Enabled = 0; //ôëàã "âûêëþ÷åíî"
// Ïðèíóäèòåëüíî îáíóëèì âñå íîæêè
PWM0->AQCSFRC = 9; // 0x1 - 0 íà âûõîäå PWMxA, 0x8 - 1 íà âûõîäå PWMxB
PWM1->AQCSFRC = 9; // 0x1 - 0 íà âûõîäå PWMxA, 0x8 - 1 íà âûõîäå PWMxB
PWM2->AQCSFRC = 9; // 0x1 - 0 íà âûõîäå PWMxA, 0x8 - 1 íà âûõîäå PWMxB
GPIO_INV_OFF;
}
/*@}*/

340
Vsrc/V_QEP.c Normal file
View File

@ -0,0 +1,340 @@
/*!
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) {
QEP0->QCAPCTL_bit.UPPS = LOWEST_UPSS;
QEP0->QCAPCTL_bit.CCPS = 4;
//Вкл. режим квадратурного счёта
QEP0->QDECCTL_bit.QSRC = 0;
//Режим отладчика
QEP0->QEPCTL_bit.FREESOFT = 0;
//Значение счётчика положения после инициализации или положительного переполнения
QEP0->QPOSINIT = 0;
//Сброс счётчика
QEP0->QEPCTL_bit.SWI = 1;
//Максимальное значение счётчика, после чего обнуление
QEP0->QPOSMAX = (p->resol << 2) - 1;
//Проверка направления движения
if (p->Posspeed_CTL.bit.dir == 1) {
QEP0->QDECCTL_bit.QAP = 1;
}
//Вкл. квадратурного счётчика
QEP0->QEPCTL_bit.QPEN = 1;
//Отчистка всех флагов
QEP0->QCLR = 0xFFFF;
//Режим захвата - по умолчанию, по событию отработки заданного числа импульсов
QEP0->QEPCTL_bit.QCLM = 0;
//Режим обнуления счётчика - по реперному событию
if (p->Posspeed_CTL.bit.index_en == 1) { //если индексная метка есть
QEP0->QEPCTL_bit.PCRM = 0;
QEP0->QEINT_bit.IEL = 1;
} else {
//Режим обнуления счётчика - по максимальному значению
QEP0->QEPCTL_bit.PCRM = 1;
}
//Ввод периода сторожевого таймера
QEP0->QWDPRD = 200000 / (1 << 2);
//Вкл. сторожевого таймера
QEP0->QEPCTL_bit.WDE = 1;
/*Расчёт вспомогательного коэффициента для расчёта скорости,
где 15=60/4, 60 - для перевода в об/мин; 4 - для получения интерполяции разрешения датчика (1 период дает 4 фронта);
CORE_CLK - частота процессора*/
p->k_low = CORE_CLK / ((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);
if (p->Posspeed_CTL.bit.index_en){//если индексная метка есть
// TODO переделать NT_COMMON_REG->GPIOPCTLG_bit.PIN12 = 1; //QEP1 I
}
}
//! Функция расчёта скорости и положения, вызывается с необходимой дискретностью
//! \memberof TposspeedEqep
void TposspeedEqep_Calc(TposspeedEqep *p) {
long temp;
//Текущее значение GPIO для отладки. Можно смотреть в осцах
p->GPIOsValue = (GPIOG->DATA >> 10) & 3;
//если скорость высокая, а делитель UPEVNT не высокий
if ((labs(p->speed_elec) > _IQ(2)) && (QEP0->QCAPCTL_bit.UPPS != 5)) {
QEP0->QCAPCTL_bit.UPPS = 5; //делаем делитель UPEVNT высокий
p->skip_counter = 2; //два такта пропустим расчет скорости
}
//если скорость низкая, а делитель не низкий
if ((labs(p->speed_elec) < _IQ(1.5)) && (QEP0->QCAPCTL_bit.UPPS != LOWEST_UPSS)) {
QEP0->QCAPCTL_bit.UPPS = LOWEST_UPSS; //делаем делитель UPEVNT низкий
p->skip_counter = 2; //два такта пропустим расчет скорости
}
p->UPPS_forWatch = QEP0->QCAPCTL_bit.UPPS; //для отображения UPPS наружу
if (p->Posspeed_CTL.bit.CmdInit == 1) { //Команда переинициализации - все обнуляем
QEP0->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;
#if defined(HW_VECTORCARD_SIMULATOR) || defined(HW_NIIET_BOARD_SIMULATOR)
p->Poscnt_res = (unsigned long) model.qepCounter; //захват положения
#else
p->Poscnt_res = (unsigned long) QEP0->QPOSCNT; //захват положения
#endif
p->Poscnt_res16=p->Poscnt_res;//Для наблюдения на осциллографе
p->Posspeed_FLG1.bit.PCO_tmp = QEP0->QFLG_bit.PCO; //копия флага положительного переполнения счётчика
p->Posspeed_FLG1.bit.PCU_tmp = QEP0->QFLG_bit.PCU; //копия флага отрицательного переполнения счётчика
QEP0->QCLR_bit.PCO = 1; //отчистка флага положительного переполнения счётчика
QEP0->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+((QEP0->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 (QEP0->QFLG_bit.WTO == 1) {
p->Posspeed_FLG1.bit.first_launch = FIRST_LAUNCH_UP; //указатель первого запуска алгоритма после срабатывания таймера
p->speed_elec = 0; //обнуление скорости
QEP0->QCLR_bit.WTO = 1; //отчистка флага
QEP0->QWDTMR = 0; //обнуление таймера
} else {
/*переключение по первому запуску для инициализации*/
if (p->Posspeed_FLG1.bit.first_launch == FIRST_LAUNCH_UP) {
//Откл. блока захвата
QEP0->QCAPCTL_bit.CEN = 0;
QEP0->QCAPCTL_bit.CEN = 1;
p->Posspeed_FLG1.bit.first_launch = NOT_FIRST_LAUNCH;
}
p->QEPSTS=QEP0->QEPSTS;//копия регистра статуса
if (p->QEPSTS_bit.UPEVNT == 1) { //есть событие UPEVNT, значит в таймере захвачено время
p->Qcprdlat_tmp = QEP0->QCPRD; //копия счетчика времени
p->speed_calc_skip = 0; //пропуск расчета скорости - не пропускать
if (p->QEPSTS_bit.COEF == 1) { //проверка флага переполнения таймера
p->speed_elec = 0;
p->speed_calc_skip = 1; //пропустить расчет скорости
QEP0->QEPSTS = 1 << 3;
}
if (p->QEPSTS_bit.CDEF == 1) { //проверка на изменения направления движения во время захвата
p->speed_elec = 0;
p->speed_calc_skip = 1; //пропустить расчет скорости
QEP0->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 = QEP0->QCAPCTL_bit.UPPS
- QEP0->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
}
QEP0->QEPSTS = 1 << 7;
}
else if (QEP0->QCTMR > QEP0->QCPRD)
{ //нет события UPEVNT, считаем по таймеру QCTMR, а не по периоду QCPRD
p->Qcprdlat_tmp = QEP0->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 = QEP0->QCAPCTL_bit.UPPS
- QEP0->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;
}
//В симуляторе доступен только один способ измерения скорости - по углу программно.
#if (defined(HW_VECTORCARD_SIMULATOR)) || (defined(HW_NIIET_BOARD_SIMULATOR))
p->SpeedCalcType=SPEED_CALC_TYPE_BY_SOFT;
#endif
}
//! Функция обработки репера (событие индекса)
//! \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
* Чтобы попасть в последние два регистра, нужно передать их адреса явно.
*
* Для того, чтобы записать в часики время, нужно проделать примерно то же самое.
* В режиме записи отправляется сначала номер регистра, в который нужно записать что-то, а затем
* данные, которые нужно туда положить. Указатель на регистры при потоковой передаче инкрементируется
* так же, как и при чтении.
*
* Данные хранятся в двоично-десятичном формате.
*/
//Закомменченные функции вверху отличаются от нижних регистрами (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;
/* Остановить обновление теневых регисторв */
RTC->SHDW = 0x0;
/* Прочитать время */
tempSec = RTC->SEC;
tempMin = RTC->MIN;
tempHour = RTC->HOUR;
tempDOW = RTC->DOW;
tempDay = RTC->DAY;
tempMonth = RTC->MONTH;
tempYear = RTC->YEAR;
/* Запустить обновление теневых регисторв */
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;
RTC->YEAR = tempYear;
RTC->MONTH = tempMonth;
RTC->DAY = tempDay;
RTC->DOW = tempDOW;
RTC->HOUR = tempHour;
RTC->MIN = tempMin;
RTC->SEC = 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;
}
}

139
Vsrc/V_SSI_Encoder.c Normal file
View File

@ -0,0 +1,139 @@
/*!
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
#ifdef HW_MOTORCONTROLBOARD
#define SSI_NT_SPI SPI0 //Íàñòðîéêà íîìåðà SPI
// Â GpioPeripheralInit
#else
#define SSI_NT_SPI SPI2 //Íàñòðîéêà íîìåðà SPI
#endif
// Íàñòðîéêà ñàìîãî ìîäóëÿ SPI
// Ïðîäîëæåíèå íàñòðîéêè òàêòèðîâàíèÿ.
// Ïîëó÷åííàÿ ðàíåå ÷àñòîòà f_SSP_IN ïðîõîäèò åù¸ ÷åðåç äâà äåëèòåëÿ.
// SSPCPSR - ïåðâûé äåëèòåëü, â äèàïàçîíå 2 ... 254, ìîæåò áûòü òîëüêî ÷¸òíûì (ìëàäøèé áèò âñåãäà õàðäâàðíî ðàâåí 0)
// SSPCR0.bit.SCR - âòîðîé äåëèòåëü îò 0 äî 255.
// Áèòðåéò â èòîãå BitRate = f_SSP_IN / ( SSPCPSR * (SCR + 1) )
// Òàêòèðîâàíèå 25 ÌÃö çàäàíî â system_K1921VK028.c
SSI_NT_SPI->CR1 = 0;// Ðåæèì - ìàñòåð, LoopBack îòêëþ÷¸í, ñàì ìîäóëü SSP òîæå îòêëþ÷¸í
SSI_NT_SPI->IMSC = 0x0; // Çàïðåòèòü âñå ïðåðûâàíèÿ
SSI_NT_SPI->DMACR = 0; // Çàïðåòèòü DMA
SSI_NT_SPI->ICR = 0x3; // Î÷èñòêà ïðåðûâàíèé ("ïåðåïîëíåíèå FIFO ïðè¸ìà" è "íåîáñëóæåííîå FIFO ïðè¸ìà")
SSI_NT_SPI->CPSR_bit.CPSDVSR = 4; // Äåëåíèå âõîäíîé ÷àñòîòû íà 4 -> 6,25 MHz
SSI_NT_SPI->CR0_bit.SCR = 0x3F; // Âòîðîé äåëèòåëü
SSI_NT_SPI->CR0_bit.DSS = 12; // Ðàçìåð äàííûõ - 12 áèò
SSI_NT_SPI->CR0_bit.FRF = 0x0; // Âûáîð ïðîòîêîëà: 0 = SPI
SSI_NT_SPI->CR0_bit.SPO = 0x0; // Ïðè íåàêòèâíîé ëèíèè äåðæàòü êëîê â "0"
SSI_NT_SPI->CR0_bit.SPH = 0x0; // ×èòàòü äàííûå ïî çàäíåìó ôðîíòó êëîêà
SSI_NT_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 (SSI_NT_SPI->SR_bit.BSY == 0){
//SPI ñâîáîäåí
Data_read = SSI_NT_SPI->DR; //êîä ñ äàò÷èêà (÷èñëî îò 0 äî resol)
SSI_NT_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;
}
/*@}*/

235
Vsrc/V_TMU.c Normal file
View File

@ -0,0 +1,235 @@
/*!
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_TMU.c
\brief Модуль блока тригонометрических преобразований (см. TTMU, TTMUPark, TTMUIPark)
\author ООО "НПФ Вектор". http://motorcontrol.ru
\version v 1.0 24/06/2019
\addtogroup V_TMU
@{*/
#include "main.h"
//Функция преобразования Парка. Принимает на вход аргументы в относительных единицах в IQ24. По величине аргументы ограничены только самим форматом IQ24.
void TMU_park_calc_IQ24PU (TTMUPark *p) {
TMU->PHIN = _IQ24mpy(((p->ang & 0x00FFFFFF) << 4), _IQ24(2.0*_PI)); //ограничиваем угол единицей в IQ24, преобразуем в IQ28, а затем в абсолютный угол в радианах, как требует того блок TMU
TMU->YIN = (p->ds >> 3); //преобразуем неограниченное число в формате IQ24 в ограниченное единицей в формате IQ28
TMU->XIN = (p->qs >> 3); //то же
TMU->CMD = (3 << TMU_CMD_FUNC_Pos) | // Повернуть вектор
(0 << TMU_CMD_ARGT_Pos) | // Аргументы в IQ28
(1 << TMU_CMD_START_Pos); // Поехали
//Ждем, пока блок TMU закончит вычисления
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
p->de = ((int32)TMU->YOUT << 3); //преобразуем реультат обратно от максимально возможной единицы для блока TMU в IQ28 до максимально возможного числа в IQ24
p->qe = ((int32)TMU->XOUT << 3); //то же
}
//Функция обратного преобразования Парка. Принимает на вход аргументы в относительных единицах в IQ24. По величине аргументы ограничены только самим форматом IQ24.
void TMU_ipark_calc_IQ24PU (TTMUIPark *p) {
TMU->PHIN = _IQ24mpy(((p->ang & 0x00FFFFFF) << 4), _IQ24(2.0*_PI)); //ограничиваем угол единицей в IQ24, преобразуем в IQ28, а затем в абсолютный угол в радианах, как требует того блок TMU
TMU->YIN = (p->qe >> 3); //преобразуем неограниченное число в формате IQ24 в ограниченное единицей в формате IQ28
TMU->XIN = (p->de >> 3); //то же
TMU->CMD = (3 << TMU_CMD_FUNC_Pos) | // Повернуть вектор
(0 << TMU_CMD_ARGT_Pos) | // Аргументы в IQ28
(1 << TMU_CMD_START_Pos); // Поехали
//Ждем, пока блок TMU закончит вычисления
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
p->qs = ((int32)TMU->YOUT << 3); //преобразуем реультат обратно от максимально возможной единицы для блока TMU в IQ28 до максимально возможного числа в IQ24
p->ds = ((int32)TMU->XOUT << 3); //то же
}
//Функция синуса. Принимает на вход угол в относительных единицах в IQ24. По величине угол ограничен только самим форматом IQ24.
_iq TMU_sin_IQ24PU (_iq angle) {
TMU->PHIN = _IQ24mpy(angle & 0x00FFFFFF, _IQ24(2.0*_PI)); //ограничиваем угол единицей в IQ24 и преобразуем в абсолютный угол в радианах, как требует того блок TMU
TMU->CMD = (0 << TMU_CMD_FUNC_Pos) | // Вычислить синус/косинус
(4 << TMU_CMD_ARGT_Pos) | // Аргументы в IQ24
(1 << TMU_CMD_START_Pos); // Поехали
//Ждем, пока блок TMU закончит вычисления
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
return (TMU->YOUT);
}
//Функция косинуса. Принимает на вход угол в относительных единицах в IQ24. По величине угол ограничен только самим форматом IQ24.
_iq TMU_cos_IQ24PU (_iq angle) {
TMU->PHIN = _IQ24mpy(angle & 0x00FFFFFF, _IQ24(2.0*_PI)); //ограничиваем угол единицей в IQ24 и преобразуем в абсолютный угол в радианах, как требует того блок TMU
TMU->CMD = (0 << TMU_CMD_FUNC_Pos) | // Вычислить синус/косинус
(4 << TMU_CMD_ARGT_Pos) | // Аргументы в IQ24
(1 << TMU_CMD_START_Pos); // Поехали
//Ждем, пока блок TMU закончит вычисления
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
return (TMU->XOUT);
}
//Функция арктангенса. Принимает на вход аргументы в относительных единицах в IQ24. По величине аргументы ограничены только самим форматом IQ24.
_iq TMU_atan2_IQ24PU (_iq inY, _iq inX) {
TMU->XIN = (inX >> 3); //преобразуем неограниченное число в формате IQ24 в ограниченное единицей в формате IQ28
TMU->YIN = (inY >> 3); //то же
TMU->CMD = (1 << TMU_CMD_FUNC_Pos) | // Перевод из прямоугольной системы координат в полярную
(0 << TMU_CMD_ARGT_Pos) | // Аргументы в IQ28
(1 << TMU_CMD_START_Pos); // Поехали
//Ждем, пока блок TMU закончит вычисления
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
return (_IQ24mpy((((int32)TMU->PHOUT) >> 4), _IQ24(0.15915494309189533576))); //преобразуем угол из IQ28 в IQ24 и затем делим на 2Пи для преобразования в относительный угол
}
//Функция преобразования координат из прямоугольной системы в полярную. Принимает на вход аргументы в относительных единицах в IQ24. По величине аргументы ограничены только самим форматом IQ24.
void TMU_cartesianToPolar_calc_IQ24PU (TTMUCarToPol *p) {
TMU->XIN = (p->x >> 3); //преобразуем неограниченное число в формате IQ24 в ограниченное единицей в формате IQ28
TMU->YIN = (p->y >> 3); //то же
TMU->CMD = (1 << TMU_CMD_FUNC_Pos) | // Перевод из прямоугольной системы координат в полярную
(0 << TMU_CMD_ARGT_Pos) | // Аргументы в IQ28
(1 << TMU_CMD_START_Pos); // Поехали
//Ждем, пока блок TMU закончит вычисления
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
p->r = ((int32) TMU->XOUT << 3); //преобразуем реультат обратно от максимально возможной единицы для блока TMU в IQ28 до максимально возможного числа в IQ24
p->phi = _IQ24mpy((((int32)TMU->PHOUT) >> 4), _IQ24(0.15915494309189533576)); //преобразуем угол из IQ28 в IQ24 и затем делим на 2Пи для преобразования в относительный угол
}
//Функция преобразования координат из полярной системы в прямоугольную. Принимает на вход аргументы в относительных единицах в IQ24. По величине аргументы ограничены только самим форматом IQ24.
void TMU_polarToCartesian_calc_IQ24PU (TTMUPolToCar *p) {
TMU->XIN = (p->r >> 3); //преобразуем неограниченное число в формате IQ24 в ограниченное единицей в формате IQ28
TMU->PHIN = _IQ24mpy(((p->phi & 0x00FFFFFF) << 4), _IQ24(2.0*_PI)); //ограничиваем угол единицей в IQ24, преобразуем в IQ28, а затем в абсолютный угол в радианах, как требует того блок TMU
TMU->CMD = (2 << TMU_CMD_FUNC_Pos) | // Перевод из полярной системы координат в прямоугольную
(0 << TMU_CMD_ARGT_Pos) | // Аргументы в IQ28
(1 << TMU_CMD_START_Pos); // Поехали
//Ждем, пока блок TMU закончит вычисления
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
asm ("nop");
p->x = ((int32) TMU->XOUT << 3) ; //преобразуем реультат обратно от максимально возможной единицы для блока TMU в IQ28 до максимально возможного числа в IQ24
p->y = ((int32) TMU->YOUT << 3); //то же
}
/*@}*/

119
Vsrc/V_UdControl.c 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_UdControl.c
\brief Ìîäóëü ïëàâíîãî çàðÿäà ÇÏÒ
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 1.0 25/08/2017
\addtogroup
@{*/
#include "main.h"
//!Èíèöèàëèçàöèÿ.
//!Êîíôèãóðèðóåì íîæêó êîíòðîëëåðà, óïðàâëÿþùóþ öåïüþ çàðÿäà íà âûâîä.
//! \memberof TUdControl
void UdControl_init(TUdControl *p) {
#ifdef HW_MOTORCONTROLBOARD
p->Enabled = 1; //Âêëþ÷àåì áëîê çàðÿäà ÇÏÒ
//íîæêà, óïðàâëÿþùàÿ öåïüþ çàðÿäà
// D GpioPeripheralInit
UD_CONTROL_OFF; //ñíà÷àëà âûêëþ÷èì
p->state = UD_CONTROL_STATE_OFF; //è åùå â ñîñòîÿíèå "âûêëþ÷åíî"
p->StateOn = 0;
#else
p->Enabled = 0; //Âûêëþ÷èòü áëîê çàðÿäà ÇÏÒ
#endif
}
//!Ðàñ÷åò.
//!Äèñêðåòíûé àâòîìàò, óïðàâëÿþùèé öåïüþ çàðÿäà. Âûçûâàòü íàäî â êàêîì-íèáóäü
//!áûñòðîì ïðåðûâàíèè (íàïðèìåð 10êÃö). Ìîæåò, áóäåò ðàáîòàòü è â 1êÃö, íî
//!íå ïðîâåðÿëîñü. Èìååò òðè ñîñòîÿíèÿ: âûêëþ÷åíî, îæèäàíèå çàðÿäà è âêëþ÷åíî.
//!âñå ïåðåêëþ÷åíèÿ ïðîèñõîäÿò íà îñíîâå èçìåðÿåìîãî íàïðÿæåíèÿ íà ÇÏÒ.
//! \memberof TUdControl
void UdControl_calc(TUdControl *p) {
if (p->Enabled){//åñëè åñòü öåïü óïðàâëåíèÿ çàðÿäîì ÇÏÒ
p->fUdc.input = adc.Udc_meas; //íà âõîä ôèëüòðà - íàïðÿæåíèå ñ ÇÏÒ
p->fUdc.calc(&(p->fUdc));
//ñ÷èòàåì äèñêðåòíûé àâòîìàò
p->state_shadow = p->state;
if (p->state_prev != p->state_shadow)
p->E = 1; //ïåðâîå âõîæäåíèå
else
p->E = 0;
p->state_prev = p->state_shadow;
switch (p->state_shadow) {
case UD_CONTROL_STATE_OFF: //êëþ÷ âûêëþ÷åí
{
UD_CONTROL_OFF; //âûêëþ÷àåì êëþ÷
p->StateOn = 0; //ñîñòîÿíèå âûêëþ÷åíî
if (adc.Udc_meas > p->U_on) //íàïðÿæåíèå ïî÷òè âûñîêî
p->state = UD_CONTROL_STATE_WAIT; //ïåðåõîäèì â îæèäàíèå
break;
}
case UD_CONTROL_STATE_WAIT: //êëþ÷ âûêëþ÷åí, ãîòîâèìñÿ âêëþ÷èòü
{
if (p->E == 1) //ïåðâîå âõîæäåíèå
{
p->StateCounter = 0;
}
p->StateCounter += global_time.relative_time1.delta_millisecond;
UD_CONTROL_OFF; //âûêëþ÷àåì êëþ÷
p->StateOn = 0; //ñîñòîÿíèå âûêëþ÷åíî
if (adc.Udc_meas < p->U_off) //õîòåëè âðîäå âêëþ÷àòü, íî íàïðÿæåíèå ñíèçèëîñü...
p->state = UD_CONTROL_STATE_OFF;
if (global_time.relative_time1.delta_millisecond) { //åñëè ñòîèò áèò ìèëëèñåêóíäû
//ïðîèçâîäíàÿ íà ìèëëèñåêóíäå
p->deriv_time_ZPT = (labs(p->fUdc.output - p->fUdc_output_prev))<<11; //ïîäíèìåì çíà÷åíèå ïðîèçâîäíîé äëÿ ïîëó÷åíèÿ óðîâíÿ îêîëî 1
p->fUdc_output_prev = p->fUdc.output;
}
//òàéìàóò âêëþ÷åíèÿ è ïðîèçâîäíàÿ
if ((p->StateCounter >= p->Timeout_on) && (p->deriv_time_ZPT < p->deriv_const) && (adc.Udc_meas > p->U_off)) { //è ïðîèçâîäíàÿ ìåíüøå çàäàííîãî óðîâíÿ
p->state = UD_CONTROL_STATE_ON;
p->StateCounter = 0;
}
break;
}
case UD_CONTROL_STATE_ON: {
if ((adc.Udc_meas < p->U_off) && (drv_status.bit.running == 0)) //ðàáîòàëè-ðàáîòàëè, à òóò íàïðÿæåíèå ñíèçèëîñü... Åñëè âäðóã íàïðÿæåíèå ñíèçèëîñü âî âðåìÿ ðàáîòû, òî ðàçìûêàòü íå äàåì
p->state = UD_CONTROL_STATE_OFF;
UD_CONTROL_ON; //âêëþ÷åì êëþ÷
p->StateOn = 1; //ñîñòîÿíèå âêëþ÷åíî
break;
}
}
}
}
/*@}*/

258
Vsrc/V_UserMemory.c Normal file
View File

@ -0,0 +1,258 @@
/*!
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 Работа с пользовательской энергонезависимой памятью 1921BK028 (см. TUserMemory)
\author Лашкевич М.М., Шпак Д.М.
\version v 1.0 21/03/2019
*/
/** \addtogroup TUserMemory */
/*@{*/
#include "main.h"
#include "DSP.h"
//!Инициализация
//!Инициализация USERMEMORY
//! \memberof TUserMemory
void USERMEMORY_Init(TUserMemory *p)
{
USERMEMORY_ReadToCache(p,0);//читаем в оперативку нулевой страницы (чтобы была текущая страница и все работало корректно дальше)
}
//! Вспомогательная функция ожидания операции, возвращет "0" если всё ОК, и "1", если не всё ОК
Uint16 waitUserFlashBusy (TUserMemory *p) {
p->waitClocks = 0;
__NOP(); // В документации сказали подождать перед проверкой статуса
__NOP();
__NOP();
__NOP();
__NOP();
while(NVRFLASH->STAT_bit.BUSY == 0x1){//ждем
p->waitClocks++;
if (p->waitClocks > USERMEMORY_MAX_WAITCLOCKS){//устали ждать
return 1;
}
}
return 0;
}
//! Проверка, не нужно ли сменить страницу
//! Проверяет текущий адрес на флешке, с которым работает пользователь. Если адрес вышел из текущей страницы, страница записывается на флеш и читается в RAM новый
//! \memberof TUserMemory
void USERMEMORY_UpdateCurrentPage(TUserMemory *p, Uint16 spiaddr)
{
Uint16 newPage=spiaddr>>PAGE_SIZE_LOG2;//номер страницы - это верхнее значение адреса, так как страница 256 байт
if (newPage!=p->PageInCache){//страница другая?
if (p->PageRAM_and_FLASH_IdenticalFlag==0)//и есть измененные данные в этой странице в оперативке в кеше?
USERMEMORY_Flush(p);//загоняем страницу на флеш
if (p->receivedCode!=USERMEMORY_OP_OK)//не вышло?
return;
//читаем в оперативку новую страницу
USERMEMORY_ReadToCache(p,newPage);
if (p->receivedCode!=USERMEMORY_OP_OK)//не вышло?
return;
}
}
//! Запись в память
//!Медленная функция, записывающая на flash заданные данные.
//!Работает с закешированными в оперативке данными, а физическ пишет на флеш только если адрес вылез за границы текущей страницы
//! Адрес во флеше spiaddr, адрес 16ти разрядных данных пользователя startaddr, размер data_length. Все в байтах
//! При выполении операции startaddr инкрементируется, а spiaddr нет
//! \memberof TUserMemory
void USERMEMORY_Write(TUserMemory *p)
{
Uint16 i = 0;
Uint16 spiaddrTmp=p->MemStartAddr;//адрес на флеше в байтах
p->MCUStartAddr8=(Uint8*)p->MCUStartAddr;//меняем указатель на данные - из указателя на 16ти разрядные данные на указатель на байты - так удобнее
for(i = 0; i < p->data_length; i++){//по всем данным, что хочет пользователь
USERMEMORY_UpdateCurrentPage(p,spiaddrTmp);//сменить и перечитать страницу, если она другая
Uint16 addrInPage=spiaddrTmp&0xFFFF;//адрес внутри страницы
if (p->cacheArr[addrInPage] != (*(p->MCUStartAddr8))){//данные на совпадают с тем, что уже в оперативке в этом месте?
p->cacheArr[addrInPage]=(*(p->MCUStartAddr8));//кладем данные в оперативку
p->PageRAM_and_FLASH_IdenticalFlag=0;//флаг, что данные в оперативке отличаются от записанных на флеше
}
spiaddrTmp++;
p->MCUStartAddr8++;
}
//p->MCUStartAddr=(Uint16*)p->MCUStartAddr8;//чтобы адрес на данные поменялся (не знаю, надо это кому или нет)
p->receivedCode = USERMEMORY_OP_OK;
}
//! Чтение из памяти
//!Медленная функция, считывающая из flash заданные данные. Подробности см. TUserMemory.
//! Адрес во флеше spiaddr, адрес адрес 16ти разрядных данных пользователя startaddr, размер data_length. Все в байтах.
//! При выполении операции startaddr инкрементируется, а spiaddr нет
//! \memberof TUserMemory
void USERMEMORY_Read(TUserMemory *p)
{
Uint16 i = 0;
Uint16 spiaddrTmp=p->MemStartAddr;
p->MCUStartAddr8=(Uint8*)p->MCUStartAddr;
for(i = 0; i < p->data_length; i++){//по всем данным, что хочет пользователь
USERMEMORY_UpdateCurrentPage(p,spiaddrTmp);//сменить и перечитать страницу, если она другая
Uint16 addrInPage=spiaddrTmp&0xFFFF;//адрес внутри страницы
*(p->MCUStartAddr8) = p->cacheArr[addrInPage];//отдаем данные из оперативки, они должны быть там актуальные после USERMEMORY_UpdateCurrentPage
spiaddrTmp++;
p->MCUStartAddr8++;
}
p->MCUStartAddr=(Uint16*)p->MCUStartAddr8;//чтобы адрес на данные поменялся (не знаю, надо это кому или нет)
p->receivedCode = USERMEMORY_OP_OK;
}
//! Записывает страницу данные на флешку из кеша (из оперативки одну страницу)
//! \memberof TUserMemory
void USERMEMORY_WriteFromCache(TUserMemory *p, int16 pageNum)
{
int16 i = 0, readDataWord = 0;
Uint32 *arrayPointer;
Uint16 addrOffset=pageNum*USERMEMORY_PAGE_SIZE;//начальный адрес на флешке (от начала страницы)
NVRFLASH->STAT = 0x3;//сброс статуса
NVRFLASH->ADDR = addrOffset;//адрес начала страницы
NVRFLASH->CMD = (USERMEMORY_USERFLASH_KEY | USERMEMORY_CMD_PAGE_ERASE);//стираем страницу
if (waitUserFlashBusy(p) != 0){
p->receivedCode = USERMEMORY_WRITE_TIMEOUT;
return;
}
for(i = 0; i < USERMEMORY_PAGE_SIZE; i += NUMBER_OF_BYTE_ON_PAGE){//цикл по размеру страницы
NVRFLASH->STAT = 0x3; //сброс статуса
NVRFLASH->ADDR = addrOffset + i; //адрес
arrayPointer = (Uint32*)(&p->cacheArr[i]);
for (readDataWord = 0; readDataWord < NUMBER_OF_32BIT_WORDS_AT_ONCE; readDataWord++){
NVRFLASH->DATA[readDataWord].DATA = *arrayPointer;
arrayPointer++;
}
NVRFLASH->CMD = (USERMEMORY_USERFLASH_KEY | USERMEMORY_CMD_WRITE);//команда на запись байта
if (waitUserFlashBusy(p) != 0){
p->receivedCode = USERMEMORY_WRITE_TIMEOUT;
return;
}
}
NVRFLASH->STAT = 0x3;//сброс статуса
p->receivedCode = USERMEMORY_OP_OK;//все хорошо
p->PageRAM_and_FLASH_IdenticalFlag=1;//данные страницы в оперативке и во флеше теперь идентичны
}
//! Читает страницу данных из флеша в кеш (в оперативку)
//! \memberof TUserMemory
void USERMEMORY_ReadToCache(TUserMemory *p, int16 pageNum)
{
int16 i = 0, readDataWord = 0;
Uint16 addrOffset = pageNum * USERMEMORY_PAGE_SIZE;//начальный адрес на флешке (от начала страницы)
Uint32 *arrayPointer;
for(i = 0; i < USERMEMORY_PAGE_SIZE; i += NUMBER_OF_BYTE_ON_PAGE){//цикл по размеру страницы
NVRFLASH->STAT = 0x3;//сброс статуса
NVRFLASH->ADDR = addrOffset + i;//адрес
NVRFLASH->CMD = (USERMEMORY_USERFLASH_KEY | USERMEMORY_CMD_READ);//команда на чтение байта
if (waitUserFlashBusy(p) != 0){
p->receivedCode = USERMEMORY_READ_TIMEOUT;
return;
}
arrayPointer = (Uint32*)&(p->cacheArr[i]);
// Считывается по 16 или 4 32-разрядных слова{
for (readDataWord = 0; readDataWord < NUMBER_OF_32BIT_WORDS_AT_ONCE; readDataWord++){
*arrayPointer = NVRFLASH->DATA[readDataWord].DATA;//данные (один байт) в оперативку
arrayPointer++;
}
}
NVRFLASH->STAT = 0x3;//сброс статуса
p->receivedCode = USERMEMORY_OP_OK;
p->PageInCache=pageNum;//какая страница теперь в кеше
p->PageRAM_and_FLASH_IdenticalFlag=1;//данные в оперативке (в кеше) идентичны с флешем
}
//! Стереть всю флешку (будут FF)
//! \memberof TUserMemory
void USERMEMORY_Full_Erase(TUserMemory *p){
// Cброс статуса, команда стирания и ожидание завершения
NVRFLASH->STAT = 0x3;
NVRFLASH->CMD = (USERMEMORY_USERFLASH_KEY | USERMEMORY_CMD_FULL_ERASE);//команда на стирание фсей флеши
__NOP(); // В документации сказали подождать перед проверкой статуса
__NOP();
__NOP();
__NOP();
__NOP();
while(NVRFLASH->STAT_bit.BUSY == 0x1){};
}
//! Сбросить кеш из оперативки на флешку
//! \memberof TUserMemory
void USERMEMORY_Flush(TUserMemory *p){
USERMEMORY_WriteFromCache(p,p->PageInCache);
}
//! Медленный фоновый постоянный расчет - нужен пока для систематического сброса кеша на флешку по времени
//! \memberof TUserMemory
void USERMEMORY_slow_calc(TUserMemory *p){
if (p->NeedFlushRequest){//надо флушить?
USERMEMORY_Flush(p);
p->NeedFlushRequest=0;
}
}
//! Миллисекундный расчет - нужен пока для систематического сброса кеша на флешку по времени
//! \memberof TUserMemory
void USERMEMORY_ms_calc(TUserMemory *p){
if (!p->PageRAM_and_FLASH_IdenticalFlag)//данные на флешке и в оперативке не идентичны
p->autoFlushCounter++;
if (p->autoFlushCounter>10000) //зищита от переполнения
p->autoFlushCounter=10000;
if (p->autoFlushCounter>500){//долго не сбрасывается на флешку
p->NeedFlushRequest=1;//надо флушить, но тут это делать нельзя, ибо прерывание, ставим реквест фону
p->autoFlushCounter=0;
}
}
/*@}*/

212
Vsrc/V_adc.c Normal file
View File

@ -0,0 +1,212 @@
/*!
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) MCB_028
\author ООО "НПФ Вектор". http://motorcontrol.ru
\version v 2.0 22/03/2019
\addtogroup V_adc
@{*/
/* Расписание каналов
* ADC13 Ia
* ADC19 Ic
* ADC1 Udc
* ADC31 0.75V
* ADC18 0.03V
* ADC20 Pot
* ADC15 AIN1
* ADC27 AIN2
* ADC29 TempSens
*/
#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 = 0;
Uint32 AdcClock, AdcDiv, trash;
// Сколько SYSCLKOUT тактов занимает период ШИМ
Uint32 pwmPrd = PWM0->TBPRD * (SystemCoreClock / APB0BusClock);
if (PWM0->TBCTL_bit.CTRMODE == TB_COUNT_UPDOWN)
pwmPrd = pwmPrd << 1;
// Сколько SYSCLKOUT тактов занимает один такт АЦП (AdcDiv)
AdcDiv = 2 * (RCU->ADCCFG_bit.DIVN + 1); // Итого деление частоты
AdcClock = SystemCoreClock / AdcDiv; // Снимаем сброс
//Инициализация ADC
ADC->ACTL[0].ACTL_bit.ADCEN = 0x1; // Разрешаем работу АЦП
ADC->ACTL[0].ACTL_bit.SELRES = ADC_ACTL_ACTL_SELRES_12bit;
ADC->ACTL[1].ACTL_bit.ADCEN = 0x1; // Разрешаем работу АЦП
ADC->ACTL[1].ACTL_bit.SELRES = ADC_ACTL_ACTL_SELRES_12bit;
ADC->ACTL[2].ACTL_bit.ADCEN = 0x1; // Разрешаем работу АЦП
ADC->ACTL[2].ACTL_bit.SELRES = ADC_ACTL_ACTL_SELRES_12bit;
ADC->ACTL[3].ACTL_bit.ADCEN = 0x1; // Разрешаем работу АЦП
ADC->ACTL[3].ACTL_bit.SELRES = ADC_ACTL_ACTL_SELRES_12bit;
//Настройка секвенсора 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 = 0x6; // Опрашивать 4 канала за раз = RQMAX + 1
ADC->SEQ[0].SRQSEL0_bit.RQ0 = 13; // Какой вход АЦП когда опрашивается
ADC->SEQ[0].SRQSEL0_bit.RQ1 = 19; // --//--
ADC->SEQ[0].SRQSEL0_bit.RQ2 = 1; // --//--
ADC->SEQ[0].SRQSEL0_bit.RQ3 = 31; // --//--
ADC->SEQ[0].SRQSEL1_bit.RQ4 = 18; // --//--
ADC->SEQ[0].SRQSEL1_bit.RQ5 = 27; // --//--
ADC->SEQ[0].SRQSEL1_bit.RQ6 = 29; // --//--
ADC->SEQ[0].SCCTL_bit.RCNT = 3; // Делать ещё три перезапуска после первого запуска
ADC->SEQ[0].SRTMR_bit.VAL = pwmPrd / (ADC->SEQ[0].SCCTL_bit.RCNT + 1) / AdcDiv; // Пауза между пусками АЦП на период ШИМ в тактах ACLK
ADC->SEQ[0].SCCTL_bit.RAVGEN = 1; // Разрешить усреднять по 4 точкам
ADC->SEQEN_bit.SEQEN0 = 1; // Разрешить секвенсор 0
ADC->SEQ[0].SCCTL_bit.ICNT = 6; // Вызов прерывания через каждые (ICNT + 1) записи в fifo
// Очистка FIFO
while (ADC->SEQ[0].SFLOAD)
trash = ADC->SEQ[0].SFIFO;
// Ждём, пока АЦП выставит флаг "ГОТОВ" (можно вставить этот цикл после "ADCEN = 1")
while (!ADC->ACTL[0].ACTL_bit.ADCRDY) {};
while (!ADC->ACTL[1].ACTL_bit.ADCRDY) {};
while (!ADC->ACTL[2].ACTL_bit.ADCRDY) {};
while (!ADC->ACTL[3].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;
Uint16 pot, ain1, ain2, temper;
// Если всё пошло хорошо, то в ФИФЕ будут уже усреднённые результаты - 4 штуки.
p->IA_temp = ADC->SEQ[0].SFIFO;
p->IC_temp = ADC->SEQ[0].SFIFO;
p->Udc_temp = ADC->SEQ[0].SFIFO;
pot = ADC->SEQ[0].SFIFO;
ain1 = ADC->SEQ[0].SFIFO;
ain2 = ADC->SEQ[0].SFIFO;
temper = 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_c = p->IcGainNom * (((p->IC_temp<< 4) + p->Imeas_c_offset));
p->Udc_meas = p->UdcGainNom * (p->Udc_temp + p->Udc_meas_offset);
p->Imeas_b = -p->Imeas_a - p->Imeas_c;
}
//!Медленный расчет.
//!Занимается пересчетом коэффициентов, используемых в скоростной функции расчета,
//!чтобы не занимать процессорное время там. Находит коэффициенты,
//!на которые надо умножить полученное с АЦП значение, чтобы получить
//!относительные единицы с заданной базой.
//! Пример 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 * (SystemCoreClock / APB0BusClock);
// Если считает вверх-вниз, то период на деле в два раза больше
if (PWM0->TBCTL_bit.CTRMODE == TB_COUNT_UPDOWN)
pwmPrd = pwmPrd << 1;
// Делитель частоты АЦП
Uint16 AdcDiv = 2 * (RCU->ADCCFG_bit.DIVN + 1);
if (pwmPrd < 1000) pwmPrd = 1000;
// Пауза между перезапускмами
// VAL = (Период ШИМ в тактах SysClkOut) / (Кол-во перезапусков) / (Делитель частоты АЦП)
ADC->SEQ[0].SRTMR_bit.VAL = pwmPrd / (ADC->SEQ[0].SCCTL_bit.RCNT + 1) / AdcDiv;
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;
}
}
}
/*@}*/

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