添加一些关于midi播放的项目
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
lemcu.org GPL Exception version 1.0
|
||||
-----------------------------------
|
||||
|
||||
As an additional permission, if Lemcusb library is statically linked with one or more of the following
|
||||
software libraries, then, these software libraries are not subjected to the TERMS AND CONDITIONS of
|
||||
GNU General Public License version 3.0.
|
||||
|
||||
(1) Silicon Laboratories Inc's "emlib", "emdrv", any software supplied as part of application note and/or examples.
|
||||
(2) ARM Limited's "CMSIS".
|
||||
|
||||
They are bound by their own terms and conditions as specified by their authors.
|
||||
@@ -0,0 +1,681 @@
|
||||
The Lemcusb is Copyright (C) 2014 http://lemcu.org
|
||||
|
||||
You may use, distribute and copy the Lemcusb under the terms of
|
||||
GNU General Public License version 3.0, which is displayed below.
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
@@ -0,0 +1,35 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Lemcusb - Firmware USB driver for EFM32 Microcontroller
|
||||
** Copyright (C) 2014 http://lemcu.org
|
||||
**
|
||||
** This library is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License version 3.0 as
|
||||
** published by the Free Software Foundation and appearing in the file
|
||||
** LICENSE.txt included in the packaging of this file.
|
||||
**
|
||||
** In addition, as a special exception, http://lemcu.org gives you certain
|
||||
** additional rights. These rights are described in the lemcu.org GPL
|
||||
** Exception version 1.0, included in the file GPL_EXCEPTION.txt in this
|
||||
** package.
|
||||
**
|
||||
** This library is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __C_COMPAT_H__
|
||||
#define __C_COMPAT_H__
|
||||
|
||||
|
||||
#if defined ( __ICCARM__ )
|
||||
#define RAMFUNC __ramfunc
|
||||
#else
|
||||
#define RAMFUNC __attribute__((__long_call__)) __attribute__((section(".functioninRAM"))) __attribute__ ((noinline))
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,381 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Lemcusb - Firmware USB driver for EFM32 Microcontroller
|
||||
** Copyright (C) 2014 http://lemcu.org
|
||||
**
|
||||
** This library is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License version 3.0 as
|
||||
** published by the Free Software Foundation and appearing in the file
|
||||
** LICENSE.txt included in the packaging of this file.
|
||||
**
|
||||
** In addition, as a special exception, http://lemcu.org gives you certain
|
||||
** additional rights. These rights are described in the lemcu.org GPL
|
||||
** Exception version 1.0, included in the file GPL_EXCEPTION.txt in this
|
||||
** package.
|
||||
**
|
||||
** This library is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "usb.h"
|
||||
//#include "em_device.h"
|
||||
//#include "em_cmu.h"
|
||||
//#include "em_int.h"
|
||||
//#include "em_timer.h"
|
||||
#include "gpio.h"
|
||||
#include "usb_internal_ll.h"
|
||||
#include "usb_stack.h"
|
||||
#include "usb_helperfunctions.h"
|
||||
|
||||
|
||||
void usb_reset_received(void)
|
||||
{
|
||||
uint32_t cnt;
|
||||
uint32_t *ptr;
|
||||
|
||||
GPIOA->PSOR = (1<<1);
|
||||
|
||||
/* zero intitialize endpoint buffers and len/status fields */
|
||||
ptr = (uint32_t *)usb_ep_buffers;
|
||||
for (cnt=0; cnt < (sizeof(usb_ep_buffers)>>2); cnt++)
|
||||
{
|
||||
*ptr++ = 0;
|
||||
}
|
||||
|
||||
/* preinitialize DATA PIDS for IN endpoints */
|
||||
usb_ep_buffers[USB_EPBUF_OFFSET_EP0IN_BUF] = 0x4B;
|
||||
usb_ep_buffers[USB_EPBUF_OFFSET_EP1IN_BUF] = 0x4B;
|
||||
|
||||
/* reset usb device address to 0 (will be changed during enumeration) */
|
||||
usbstack_init();
|
||||
GPIOA->PSOR = (1<<1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Pinout information:
|
||||
* PA2 = D-
|
||||
* PA3 = D+
|
||||
* PA1 = debug output (to scope)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Pre-condition: GPIO clock enabled
|
||||
*
|
||||
*/
|
||||
void usb_init(void)
|
||||
{
|
||||
usb_reset_received();
|
||||
|
||||
/* Pinout: PA1 = USB connect line (1k5 resistor to PC0)
|
||||
PA2 = D-
|
||||
PA3 = D+
|
||||
*/
|
||||
/* set PA0 low (disconnected) Will enable the pulldown */
|
||||
GPIOA->PCOR = (1 << 2);
|
||||
/* Pin PA0 is configured to Input enabled with pull-down */
|
||||
//GPIO->P[0].MODEL = (GPIO->P[0].MODEL & ~_GPIO_P_MODEL_MODE0_MASK) | GPIO_P_MODEL_MODE0_INPUTPULL;
|
||||
|
||||
/* Pin PC0 is configured to Input enabled */
|
||||
//GPIO->P[2].MODEL = (GPIO->P[2].MODEL & ~_GPIO_P_MODEL_MODE0_MASK) | GPIO_P_MODEL_MODE0_INPUT;
|
||||
/* Pin PC1 is configured to Input enabled */
|
||||
// GPIO->P[2].MODEL = (GPIO->P[2].MODEL & ~_GPIO_P_MODEL_MODE1_MASK) | GPIO_P_MODEL_MODE1_INPUT;
|
||||
|
||||
/* set output state of PC0 PC1 (D- D+) to 1 0 */
|
||||
GPIOA->PSOR = (1<<2); /* D- = 1 */
|
||||
GPIOA->PCOR = (1<<3); /* D+ = 0 */
|
||||
|
||||
/* Pin PE13 is configured to Push-pull */
|
||||
//GPIO->P[4].MODEH = (GPIO->P[4].MODEH & ~_GPIO_P_MODEH_MODE13_MASK) | GPIO_P_MODEH_MODE13_PUSHPULL;
|
||||
|
||||
/* setup PC1 interrupt on rising edge (D+ first SYNC bit) */
|
||||
/* Configure PC1 interrupt on rising edge */
|
||||
// GPIO_IntConfig(gpioPortC, 1, true, false, true);
|
||||
/* Set Interrupt priority to highest */
|
||||
// NVIC_SetPriority(GPIO_ODD_IRQn, 0);
|
||||
/* Enable GPIO_EVEN interrupt vector in NVIC */
|
||||
// NVIC_EnableIRQ(GPIO_ODD_IRQn);
|
||||
}
|
||||
|
||||
void usb_connect(void)
|
||||
{
|
||||
GPIOA->PSOR = (1 << 3);
|
||||
//GPIO->P[0].MODEL = (GPIO->P[0].MODEL & ~_GPIO_P_MODEL_MODE0_MASK) | GPIO_P_MODEL_MODE0_PUSHPULL;
|
||||
}
|
||||
|
||||
void usb_disconnect(void)
|
||||
{
|
||||
/* Pin PA0 is configured to Input enabled with pull-down */
|
||||
// GPIO->P[0].MODEL = (GPIO->P[0].MODEL & ~_GPIO_P_MODEL_MODE0_MASK) | GPIO_P_MODEL_MODE0_INPUTPULL;
|
||||
/* set PA0 low (disconnected) Will enable the pulldown */
|
||||
GPIOA->PCOR = (1 << 3);
|
||||
}
|
||||
|
||||
bool usb_check_resetcondition(void)
|
||||
{
|
||||
return ( (GPIOA->PDIR & 0x00000006) == 0x00 );
|
||||
}
|
||||
|
||||
/* check if a setup packet was received */
|
||||
bool usb_setup_available(void)
|
||||
{
|
||||
return (usb_ep_buffers[USB_EPBUF_OFFSET_SETUP_BUF + USB_EPBUF_SUBOFFSET_STAT] & (1 << 0)) != 0x00;
|
||||
}
|
||||
|
||||
/* IDEA: The reordering / Bitreversal can be done in place to save some RAM */
|
||||
void usb_setup_get_data(setupData_t *psetupdata)
|
||||
{
|
||||
uint32_t i, j;
|
||||
uint8_t dat;
|
||||
uint8_t setupdat[8];
|
||||
volatile uint8_t *SETUP_BUF;
|
||||
|
||||
SETUP_BUF = &usb_ep_buffers[USB_EPBUF_OFFSET_SETUP_BUF];
|
||||
for (i=0; i<8; i++) /* walk through all bytes */
|
||||
{
|
||||
j = i+1;
|
||||
j = (j & 0xfC) | (3-(j & 0x03)); /* reverse byteorder => TODO: This can be done in the .s file using the REV instruction (single cycle) */
|
||||
dat = SETUP_BUF[j];
|
||||
dat = bitreverse(dat); /* reverse bits*/
|
||||
setupdat[i] = dat; /* store data */
|
||||
}
|
||||
usb_ep_buffers[USB_EPBUF_OFFSET_SETUP_BUF + USB_EPBUF_SUBOFFSET_STAT] &= ~(1 << 0); /* flag setup data as empty */
|
||||
|
||||
psetupdata->bmRequestType = setupdat[0];
|
||||
psetupdata->bRequest = setupdat[1];
|
||||
psetupdata->wValue = setupdat[2];
|
||||
psetupdata->wValue |= setupdat[3] << 8;
|
||||
psetupdata->wIndex = setupdat[4];
|
||||
psetupdata->wIndex |= setupdat[5] << 8;
|
||||
psetupdata->wLength = setupdat[6];
|
||||
psetupdata->wLength |= setupdat[7] << 8;
|
||||
}
|
||||
|
||||
bool usb_ep_in_buf_empty(uint32_t epnum)
|
||||
{
|
||||
if (epnum)
|
||||
{
|
||||
return (usb_ep_buffers[USB_EPBUF_OFFSET_EP1IN_BUF + USB_EPBUF_SUBOFFSET_STAT] & (1 << 0)) == 0x00;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (usb_ep_buffers[USB_EPBUF_OFFSET_EP0IN_BUF + USB_EPBUF_SUBOFFSET_STAT] & (1 << 0)) == 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO/IDEA: check parameters like len. This can be done e.g. with ASSERTIONS, so
|
||||
* that checks can be disabled later to save time & space
|
||||
*/
|
||||
void usb_ep_in_commit_pkt(uint32_t epnum, bool firstpkt, const uint8_t *pbuf, uint32_t len)
|
||||
{
|
||||
uint32_t i;
|
||||
uint8_t dat;
|
||||
uint16_t crc_value;
|
||||
volatile uint8_t *EP0IN_BUF;
|
||||
|
||||
if (!len)
|
||||
{
|
||||
GPIOA->PSOR = (1<<8);
|
||||
GPIOA->PCOR = (1<<8);
|
||||
}
|
||||
|
||||
if (epnum)
|
||||
{
|
||||
EP0IN_BUF = &usb_ep_buffers[USB_EPBUF_OFFSET_EP1IN_BUF];
|
||||
}
|
||||
else
|
||||
{
|
||||
EP0IN_BUF = &usb_ep_buffers[USB_EPBUF_OFFSET_EP0IN_BUF];
|
||||
}
|
||||
|
||||
if (firstpkt)
|
||||
{
|
||||
EP0IN_BUF[0] = 0x4B; /* first IN packet is always transmitted with DATA1 PID */
|
||||
}
|
||||
else
|
||||
{
|
||||
EP0IN_BUF[0] ^= 0x88; /* Following packets toggle between DATA0 and DATA1 PID */
|
||||
}
|
||||
|
||||
crc_value = 0xffff;
|
||||
for (i=0; i<len; i++)
|
||||
{
|
||||
dat = *pbuf++;
|
||||
EP0IN_BUF[i+1] = dat;
|
||||
crc_value = crc16(crc_value, dat);
|
||||
}
|
||||
|
||||
crc_value = ~crc_value; /* this is described in the USB spec. */
|
||||
|
||||
/* ADD CRC */
|
||||
EP0IN_BUF[1+len+0] = crc_value & 0xff; /* CRC low */
|
||||
EP0IN_BUF[1+len+1] = crc_value >> 8; /* CRC high */
|
||||
|
||||
/* set packet length */
|
||||
EP0IN_BUF[USB_EPBUF_SUBOFFSET_LEN] = len + 1 +2; /* DATAx PID + CRC16 */
|
||||
|
||||
/* Flag endpoint as "ready" for transmission. This needs to be done as the last step */
|
||||
EP0IN_BUF[USB_EPBUF_SUBOFFSET_STAT] |= (1 << 0);
|
||||
}
|
||||
|
||||
bool usb_ep_out_data_available(uint32_t epnum)
|
||||
{
|
||||
if (epnum == 0x00)
|
||||
{
|
||||
return (usb_ep_buffers[USB_EPBUF_OFFSET_EP0OUT_BUF + USB_EPBUF_SUBOFFSET_STAT] & (1 << 0)) != 0x00;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (usb_ep_buffers[USB_EPBUF_OFFSET_EP1OUT_BUF + USB_EPBUF_SUBOFFSET_STAT] & (1 << 0)) != 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t usb_ep_out_get_data(uint32_t epnum, uint8_t *pbuf)
|
||||
{
|
||||
uint32_t i, j, len;
|
||||
uint8_t dat, bytecount;
|
||||
volatile uint8_t *EP0OUT_BUF;
|
||||
|
||||
if (epnum == 0)
|
||||
{
|
||||
EP0OUT_BUF = &usb_ep_buffers[USB_EPBUF_OFFSET_EP0OUT_BUF];
|
||||
}
|
||||
else
|
||||
{
|
||||
EP0OUT_BUF = &usb_ep_buffers[USB_EPBUF_OFFSET_EP1OUT_BUF];
|
||||
}
|
||||
|
||||
len = EP0OUT_BUF[USB_EPBUF_SUBOFFSET_LEN];
|
||||
bytecount = ((len + 7) >> 3) - 1 - 2; /* -PID -CRC16 */
|
||||
|
||||
for (i=0; i<bytecount; i++) /* walk through all bytes */
|
||||
{
|
||||
j = i+1;
|
||||
j = (j & 0xfC) | (3-(j & 0x03)); /* reverse byteorder => TODO: This can be done in the .s file using the REV instruction (single cycle) */
|
||||
dat = EP0OUT_BUF[j];
|
||||
dat = bitreverse(dat); /* reverse bits*/
|
||||
*pbuf++ = dat; /* store data */
|
||||
}
|
||||
|
||||
//bytecount = 0;
|
||||
|
||||
if (bytecount > 0)
|
||||
{
|
||||
volatile int i;
|
||||
i=0;
|
||||
}
|
||||
|
||||
/* flag endpoint as empty. Needs to be done as last step */
|
||||
EP0OUT_BUF[USB_EPBUF_SUBOFFSET_STAT] &= ~(1 << 0);
|
||||
//usb_ep_buffers[USB_EPBUF_OFFSET_EP0OUT_BUF + USB_EPBUF_SUBOFFSET_STAT] &= ~(1 << 0);
|
||||
|
||||
return bytecount;
|
||||
}
|
||||
|
||||
void usb_ep_stall(uint32_t epnum)
|
||||
{
|
||||
usb_ep_buffers[epnum + USB_EPBUF_SUBOFFSET_STAT] |= (1 << 1);
|
||||
}
|
||||
|
||||
void usb_ep_unstall(uint32_t epnum)
|
||||
{
|
||||
usb_ep_buffers[epnum + USB_EPBUF_SUBOFFSET_STAT] &= ~(1 << 1);
|
||||
}
|
||||
|
||||
bool usb_ep_is_stalled(uint32_t epnum)
|
||||
{
|
||||
return (usb_ep_buffers[epnum + USB_EPBUF_SUBOFFSET_STAT] & (1 << 1));
|
||||
}
|
||||
|
||||
/* send a package via EP0IN which is longer as 7 bytes */
|
||||
void usb_ep_in_commit_pkt_long(uint32_t epnum, const uint8_t *pbuf, uint8_t len, bool sendshortpkt)
|
||||
{
|
||||
bool first;
|
||||
uint8_t curlen;
|
||||
|
||||
first = (epnum == 0x00); /* EP0IN packets always start with DATA1 PID, while EP1IN PID toggles between DATA0/1 */
|
||||
|
||||
curlen = 0;
|
||||
|
||||
while (len)
|
||||
{
|
||||
curlen = len;
|
||||
if (curlen > 8)
|
||||
{
|
||||
curlen = 8;
|
||||
}
|
||||
while (!usb_ep_in_buf_empty(epnum)); /* wait until endpoint buffer is free */
|
||||
usb_ep_in_commit_pkt(epnum, first, pbuf, curlen);
|
||||
len -= curlen;
|
||||
pbuf += curlen;
|
||||
first = false;
|
||||
}
|
||||
if (!sendshortpkt)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if ((curlen == 8) || (curlen == 0)) /* in case the last packet has 8 bytes a short packet needs to be sent to signalize the host, that this was the last packet*/
|
||||
{
|
||||
while (!usb_ep_in_buf_empty(epnum)); /* wait until endpoint buffer is free */
|
||||
usb_ep_in_commit_pkt(epnum, false, pbuf, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* receive a package via EP0OUT. It is allowed to be longer than 8 bytes */
|
||||
/* important: ensure, that pbuf has a buffer size with a multiple of 8 Bytes */
|
||||
/* returns received length */
|
||||
uint8_t usb_ep_out_get_data_long(uint8_t *pbuf, uint8_t maxlen)
|
||||
{
|
||||
uint8_t curlen, len;
|
||||
|
||||
curlen = 8;
|
||||
len = 0;
|
||||
do
|
||||
{
|
||||
if (usb_ep_out_data_available(0))
|
||||
{
|
||||
curlen = usb_ep_out_get_data(0, pbuf); /* TODO: Handle this within usb_stack.c. It is part of control transfers. setup */
|
||||
pbuf += curlen;
|
||||
if (len >= maxlen) /* at least a little bit of protection against buffer overruns */
|
||||
{
|
||||
pbuf -= curlen;
|
||||
}
|
||||
len += curlen;
|
||||
}
|
||||
} while ( (curlen == 8) && (len < maxlen) ); /* a short packet indicates the last packet */
|
||||
return len;
|
||||
}
|
||||
|
||||
/* Handle a Control transfer without data stage => transmits a ACK in status stage */
|
||||
void usb_control_acknowledge(void)
|
||||
{
|
||||
uint8_t response[8];
|
||||
while (!usb_ep_in_buf_empty(0x00))
|
||||
;
|
||||
usb_ep_in_commit_pkt(0, true, response, 0);
|
||||
}
|
||||
|
||||
/* Handle a Control IN transfer */
|
||||
bool usb_control_dataIn(const uint8_t *pbuf, uint8_t len)
|
||||
{
|
||||
usb_ep_in_commit_pkt_long(0, pbuf, len, false);//true);
|
||||
/* wait for status stage - acknowledge from HOST*/
|
||||
while ( !usb_ep_out_data_available(0) )
|
||||
{
|
||||
}
|
||||
usb_ep_buffers[USB_EPBUF_OFFSET_EP0OUT_BUF + USB_EPBUF_SUBOFFSET_STAT] &= ~(1 << 0); /* ignore ACK (OUT packet) */
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Handle a Control OUT transfer */
|
||||
uint8_t usb_control_dataOut(uint8_t *pbuf, uint8_t maxlen)
|
||||
{
|
||||
maxlen = usb_ep_out_get_data_long(pbuf, maxlen);
|
||||
usb_control_acknowledge();
|
||||
return maxlen;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* TODO: Combine the functions */
|
||||
@@ -0,0 +1,137 @@
|
||||
/****************************************************************************//*
|
||||
**
|
||||
** Lemcusb - Firmware USB driver for EFM32 Microcontroller
|
||||
** Copyright (C) 2014 http://lemcu.org
|
||||
**
|
||||
** This library is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License version 3.0 as
|
||||
** published by the Free Software Foundation and appearing in the file
|
||||
** LICENSE.txt included in the packaging of this file.
|
||||
**
|
||||
** In addition, as a special exception, http://lemcu.org gives you certain
|
||||
** additional rights. These rights are described in the lemcu.org GPL
|
||||
** Exception version 1.0, included in the file GPL_EXCEPTION.txt in this
|
||||
** package.
|
||||
**
|
||||
** This library is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __USB_H__
|
||||
#define __USB_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "usb_config.h"
|
||||
|
||||
/* public interface to virtual USB peripheral & Stack */
|
||||
|
||||
/* some definitions for USB descriptors */
|
||||
#define DESCRIPTOR_DEVICE (0x01) /* Get device descriptor: Device */
|
||||
#define DESCRIPTOR_CONFIGURATION (0x02) /* Get device descriptor: Configuration */
|
||||
#define DESCRIPTOR_STRING (0x03) /* Get device descriptor: String */
|
||||
#define DESCRIPTOR_INTERFACE (0x04)
|
||||
#define DESCRIPTOR_ENDPOINT (0x05)
|
||||
|
||||
#ifdef USB_ENABLE_HID
|
||||
#define DESCRIPTOR_HID (0x21) /* Get descriptor: HID */
|
||||
#define DESCRIPTOR_REPORT (0x22) /* Get descriptor: Report */
|
||||
#endif
|
||||
|
||||
#define EPTYPE_CONTROL (0x00)
|
||||
#define EPTYPE_INTERRUPT (0x03)
|
||||
|
||||
|
||||
/* Some defines for endpoint function parameters => TODO, will be used in a later stage */
|
||||
#define USB_EPSETUP (0)
|
||||
#define USB_EP0OUT (16)
|
||||
#define USB_EP0IN (32)
|
||||
#if USB_ENABLE_EP1OUT_EP1IN == 1
|
||||
#define USB_EP1OUT (48)
|
||||
#define USB_EP1IN (64)
|
||||
#endif
|
||||
|
||||
|
||||
/* struct, which is used for control transfers */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t bmRequestType;
|
||||
uint8_t bRequest;
|
||||
uint16_t wLength;
|
||||
uint16_t wValue;
|
||||
uint16_t wIndex;
|
||||
} setupData_t;
|
||||
|
||||
|
||||
|
||||
/* Initialize USB and all used peripherals
|
||||
It startes with the USB peripheral disconnected from PC.
|
||||
Call usb_connect after initialization.
|
||||
*/
|
||||
void usb_init(void);
|
||||
|
||||
void usb_connect(void);
|
||||
|
||||
void usb_disconnect(void);
|
||||
|
||||
bool usb_check_resetcondition(void);
|
||||
|
||||
void usb_reset_received(void);
|
||||
|
||||
|
||||
|
||||
/* check, if a setup packet was received */
|
||||
bool usb_setup_available(void);
|
||||
|
||||
/* read setup data. Setup data does have a fixed length of 8 Bytes */
|
||||
void usb_setup_get_data(setupData_t *psetupdata);
|
||||
|
||||
|
||||
|
||||
/* check, if data can be written to ep0in buffer (== buffer is empty) */
|
||||
bool usb_ep_in_buf_empty(uint32_t epnum);
|
||||
|
||||
|
||||
/* write data to ep0in buffer */
|
||||
void usb_ep_in_commit_pkt(uint32_t epnum, bool firstpkt, const uint8_t *pbuf, uint32_t len);
|
||||
|
||||
|
||||
|
||||
/* check, if received data is in OUT endpoint */
|
||||
bool usb_ep_out_data_available(uint32_t epnum);
|
||||
|
||||
/* get data from EPxOUT. Length [bytes] is returned. */
|
||||
uint32_t usb_ep_out_get_data(uint32_t epnum, uint8_t *pbuf);
|
||||
|
||||
/* stall endpoint */
|
||||
void usb_ep_stall(uint32_t epnum);
|
||||
|
||||
/* remove stall condition from endpoint */
|
||||
void usb_ep_unstall(uint32_t epnum);
|
||||
|
||||
/* returns true if endpoint is stalled */
|
||||
bool usb_ep_is_stalled(uint32_t epnum);
|
||||
|
||||
/* receive a package via EP0OUT. It is allowed to be longer than 8 bytes */
|
||||
/* important: ensure, that pbuf has a buffer size with a multiple of 8 Bytes */
|
||||
/* returns received length */
|
||||
uint8_t usb_ep_out_get_data_long(uint8_t *pbuf, uint8_t maxlen);
|
||||
|
||||
/* send a package via EP0IN which is longer as 7 bytes */
|
||||
//void usb_ep_in_commit_pkt_long(uint32_t epnum, const uint8_t *pbuf, uint8_t len);
|
||||
void usb_ep_in_commit_pkt_long(uint32_t epnum, const uint8_t *pbuf, uint8_t len, bool sendshortpkt);
|
||||
|
||||
|
||||
|
||||
/* Handle a Control transfer without data stage => transmits a ACK in status stage */
|
||||
void usb_control_acknowledge(void);
|
||||
|
||||
/* Handle a Control IN transfer */
|
||||
bool usb_control_dataIn(const uint8_t *pbuf, uint8_t len);
|
||||
|
||||
/* Handle a Control OUT transfer */
|
||||
uint8_t usb_control_dataOut(uint8_t *pbuf, uint8_t maxlen);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,40 @@
|
||||
/***************************************************************************//*
|
||||
**
|
||||
** Lemcusb - Firmware USB driver for EFM32 Microcontroller
|
||||
** Copyright (C) 2014 http://lemcu.org
|
||||
**
|
||||
** This library is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License version 3.0 as
|
||||
** published by the Free Software Foundation and appearing in the file
|
||||
** LICENSE.txt included in the packaging of this file.
|
||||
**
|
||||
** In addition, as a special exception, http://lemcu.org gives you certain
|
||||
** additional rights. These rights are described in the lemcu.org GPL
|
||||
** Exception version 1.0, included in the file GPL_EXCEPTION.txt in this
|
||||
** package.
|
||||
**
|
||||
** This library is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __USB_CONFIG_H__
|
||||
#define __USB_CONFIG_H__
|
||||
|
||||
/* Set to 1 to enable 2 additional endpoints.
|
||||
If set to 0, only control transfers will be supported, because only EP0OUT and EP0IN are present
|
||||
*/
|
||||
#define USB_ENABLE_EP1OUT_EP1IN (1)
|
||||
|
||||
#define USB_ENABLE_HID
|
||||
|
||||
/*
|
||||
Enable this define, if the USB low level protocol handling should be done in RAM.
|
||||
This is e.g. mandatory if Flash programming is used, otherwise USB will not be
|
||||
responsive anymore when flash is erased or programmed, because Flash accesses will
|
||||
be stalled.
|
||||
*/
|
||||
#define USB_PROTOCOL_HANDLING_IN_RAM
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,162 @@
|
||||
/***************************************************************************//*
|
||||
**
|
||||
** Lemcusb - Firmware USB driver for EFM32 Microcontroller
|
||||
** Copyright (C) 2014 http://lemcu.org
|
||||
**
|
||||
** This library is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License version 3.0 as
|
||||
** published by the Free Software Foundation and appearing in the file
|
||||
** LICENSE.txt included in the packaging of this file.
|
||||
**
|
||||
** In addition, as a special exception, http://lemcu.org gives you certain
|
||||
** additional rights. These rights are described in the lemcu.org GPL
|
||||
** Exception version 1.0, included in the file GPL_EXCEPTION.txt in this
|
||||
** package.
|
||||
**
|
||||
** This library is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __USB_DESCRIPTORS_H__
|
||||
#define __USB_DESCRIPTORS_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "usb.h"
|
||||
|
||||
/* include this file only once! */
|
||||
|
||||
#define WBVAL(x) (x & 0xFF),((x >> 8) & 0xFF)
|
||||
|
||||
|
||||
/* report descriptor for HID keyboard */
|
||||
const uint8_t hid_report_descriptor[] =
|
||||
{
|
||||
0x05, 0x01, 0x09,
|
||||
0x06, 0xA1,
|
||||
0x01, 0x05,
|
||||
0x07, 0x19,
|
||||
0xE0, 0x29, 0xE7,
|
||||
0x15, 0x00,
|
||||
0x25, 0x01,
|
||||
0x75, 0x01, 0x95, 0x08, 0x81, 0x02, 0x95, 0x01,
|
||||
0x75, 0x08, 0x81, 0x01, 0x95, 0x03, 0x75, 0x01,
|
||||
0x05, 0x08, 0x19, 0x01, 0x29, 0x03, 0x91, 0x02,
|
||||
0x95, 0x05, 0x75, 0x01, 0x91, 0x01, 0x95, 0x06,
|
||||
0x75, 0x08, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x05,
|
||||
0x07, 0x19, 0x00, 0x2A, 0xFF, 0x00, 0x81, 0x00,
|
||||
0xC0
|
||||
};
|
||||
|
||||
|
||||
const uint8_t device_descriptor[] =
|
||||
{
|
||||
0x12, /* descriptor length */
|
||||
0x01, /* descriptor type */
|
||||
WBVAL(0x0110), /* USB version */
|
||||
0x00, /* Devices class */
|
||||
0x00, /* Device sub class */
|
||||
0x00, /* Device sub sub class */
|
||||
0x08, /* max packet size (for EP0IN/OUT) */
|
||||
WBVAL(0x10C4), /* VID (low, high) */
|
||||
WBVAL(0x8944), /* PID */
|
||||
WBVAL(0x0100), /* DID */
|
||||
0x01, /* manufacturer string index */
|
||||
0x02, /* product string index */
|
||||
0x00, /* serial number string index */
|
||||
0x01 /* number of configurations */
|
||||
};
|
||||
|
||||
const uint8_t config_0_descriptor[] =
|
||||
{
|
||||
0x09, /* length of config descriptor */
|
||||
DESCRIPTOR_CONFIGURATION, /* descriptor type */
|
||||
0x12+7+9, 0x00, /* Config + Interface + Endpoints length (low, high) */
|
||||
0x01, /* number of interfaces */
|
||||
0x01, /* interface number */
|
||||
0x00, /* configuration string index */
|
||||
0xA0, /* attributes (buspowered = Bit7, Selfpowered = Bit6, RemoteWakeup = Bit 5) */
|
||||
50, /* power requirement (multiply by 2 to get current in mA) */
|
||||
|
||||
/* interface descriptor */
|
||||
0x09, /* length of interface descriptor */
|
||||
DESCRIPTOR_INTERFACE, /* descriptor type */
|
||||
0x00, /* Index of this interface (starts at 0) */
|
||||
0x00, /* Alternate setting */
|
||||
0x01, /* Number of Endpoints */
|
||||
0x03, /* Interface class */
|
||||
0x01, /* Interface sub class */
|
||||
0x01, /* Interface sub sub class */
|
||||
0x00, /* Interface descriptor string index */
|
||||
|
||||
/* HID descriptor - Keyboard */
|
||||
0x09, /* Length of this descriptor */
|
||||
DESCRIPTOR_HID, /* bDescriptorType */
|
||||
WBVAL(0x0100), /* 1.00 */ /* bcdHID */
|
||||
0x00, /* bCountryCode */
|
||||
0x01, /* bNumDescriptors */
|
||||
0x22, /* bDescriptorType */
|
||||
WBVAL(sizeof(hid_report_descriptor)), /* wDescriptorLength */
|
||||
|
||||
/* EP1IN */
|
||||
0x07, /* length of endpoint descriptor */
|
||||
DESCRIPTOR_ENDPOINT, /* descriptor type */
|
||||
0x81, /* Endpoint number and direction (Bit 7) */
|
||||
EPTYPE_INTERRUPT, /* Endpoint type */
|
||||
0x08, 0x00, /* Max packet size of this Endpoint (Low, High) */
|
||||
0x18 /* Polling Interval */
|
||||
};
|
||||
|
||||
const uint8_t string_0_descriptor[] =
|
||||
{
|
||||
0x04, /* length of string descriptor */
|
||||
DESCRIPTOR_STRING, /* descriptor type */
|
||||
0x09,
|
||||
0x04
|
||||
};
|
||||
|
||||
const uint8_t string_1_descriptor[] =
|
||||
{
|
||||
0x14, /* length of string descriptor */
|
||||
DESCRIPTOR_STRING, /* descriptor type */
|
||||
'L', 0,
|
||||
'E', 0,
|
||||
'M', 0,
|
||||
'C', 0,
|
||||
'U', 0,
|
||||
'.', 0,
|
||||
'O', 0,
|
||||
'R', 0,
|
||||
'G', 0,
|
||||
};
|
||||
|
||||
const uint8_t string_2_descriptor[] =
|
||||
{
|
||||
0x1A, /* length of string descriptor */
|
||||
DESCRIPTOR_STRING, /* descriptor type */
|
||||
'I', 0,
|
||||
't', 0,
|
||||
' ', 0,
|
||||
'w', 0,
|
||||
'o', 0,
|
||||
'r', 0,
|
||||
'k', 0,
|
||||
's', 0,
|
||||
' ', 0,
|
||||
':', 0,
|
||||
'-', 0,
|
||||
')', 0,
|
||||
};
|
||||
|
||||
const uint8_t hid_descriptor[] =
|
||||
{
|
||||
0x09,
|
||||
DESCRIPTOR_HID,
|
||||
0x10, 0x01, /* USB version */
|
||||
0x00, /* Localization*/
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,63 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Lemcusb - Firmware USB driver for EFM32 Microcontroller
|
||||
** Copyright (C) 2014 http://lemcu.org
|
||||
**
|
||||
** This library is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License version 3.0 as
|
||||
** published by the Free Software Foundation and appearing in the file
|
||||
** LICENSE.txt included in the packaging of this file.
|
||||
**
|
||||
** In addition, as a special exception, http://lemcu.org gives you certain
|
||||
** additional rights. These rights are described in the lemcu.org GPL
|
||||
** Exception version 1.0, included in the file GPL_EXCEPTION.txt in this
|
||||
** package.
|
||||
**
|
||||
** This library is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __USB_HELPERFUNCTIONS_H__
|
||||
#define __USB_HELPERFUNCTIONS_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* from bit twiddling hacks. Did not check efficiency.
|
||||
My guess is, that the standard assembly way using 8 consecutive ROR/ROL instructions is faster!
|
||||
so: TODO check and optimize
|
||||
*/
|
||||
static inline uint8_t bitreverse(uint8_t b)
|
||||
{
|
||||
return ((b * 0x0802LU & 0x22110LU) | (b * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16;
|
||||
}
|
||||
|
||||
|
||||
/* TODO: Make this nice and efficient! Maybe implement this directly in CM0+ assembly
|
||||
using uint32_t instead of uint8_t can also speed things up
|
||||
See: http%3A%2F%2Fwww.usb.org%2Fdevelopers%2Fwhitepapers%2Fcrcdes.pdf&ei=
|
||||
AKrAUtuBD4WMtQakyoCwAQ&usg=AFQjCNE71tY6EAUjJKXWbjtbNvDTiOKKlg&bvm=bv.
|
||||
58187178,d.Yms&cad=rja
|
||||
*/
|
||||
static uint16_t crc16(uint16_t crc, uint8_t c)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
for (i=0; i<8; i++)
|
||||
{
|
||||
if ((crc ^ c) & 1)
|
||||
{
|
||||
crc = (crc >> 1) ^ 0xa001; /* 0xa001*/
|
||||
}
|
||||
else
|
||||
{
|
||||
crc >>= 1;
|
||||
}
|
||||
c >>= 1;
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,104 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Lemcusb - Firmware USB driver for EFM32 Microcontroller
|
||||
** Copyright (C) 2014 http://lemcu.org
|
||||
**
|
||||
** This library is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License version 3.0 as
|
||||
** published by the Free Software Foundation and appearing in the file
|
||||
** LICENSE.txt included in the packaging of this file.
|
||||
**
|
||||
** In addition, as a special exception, http://lemcu.org gives you certain
|
||||
** additional rights. These rights are described in the lemcu.org GPL
|
||||
** Exception version 1.0, included in the file GPL_EXCEPTION.txt in this
|
||||
** package.
|
||||
**
|
||||
** This library is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "usb_stack.h"
|
||||
#include "usb.h"
|
||||
#include "usb_helperfunctions.h"
|
||||
#include "usb_config.h"
|
||||
#include "usb_hid.h"
|
||||
|
||||
//#include "em_device.h" /* removeme. Only needed for debugging */
|
||||
|
||||
|
||||
|
||||
#ifdef USB_ENABLE_HID
|
||||
|
||||
/* HID requests */
|
||||
#define HID_GET_REPORT (0x01) /* mandatory */
|
||||
#define HID_GET_IDLE (0x02) /* optional */
|
||||
#define HID_GET_PROTOCOL (0x03) /* mandatory for BOOT devices */
|
||||
#define HID_SET_REPORT (0x09) /* mandatory if USB device does not use EP1OUT */
|
||||
#define HID_SET_IDLE (0x0a) /* optional */
|
||||
#define HID_SET_PROTOCOL (0x0b) /* mandatory for BOOT devices */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool usbhid_got_setup_cmd(const setupData_t *psetupdata)
|
||||
{
|
||||
uint8_t response[8];
|
||||
bool doStall;
|
||||
|
||||
doStall = false;
|
||||
|
||||
switch(psetupdata->bRequest)
|
||||
{
|
||||
case HID_GET_REPORT:
|
||||
doStall = !HID_GetReport(psetupdata->wValue >> 8);
|
||||
break;
|
||||
case HID_SET_REPORT:
|
||||
doStall = !HID_SetReport(psetupdata->wValue >> 8);
|
||||
if (!doStall)
|
||||
{
|
||||
//usb_control_acknowledge(); //TODO: REMOVE UNCOMMENT!!!
|
||||
}
|
||||
break;
|
||||
case HID_GET_PROTOCOL:
|
||||
doStall = !HID_GetProtocol(response);
|
||||
if (!doStall)
|
||||
{
|
||||
usb_control_dataIn(response, 1);
|
||||
}
|
||||
break;
|
||||
case HID_SET_PROTOCOL:
|
||||
doStall = !HID_SetProtocol(psetupdata->wValue >> 8); /* low byte of value is interface number */
|
||||
if (!doStall)
|
||||
{
|
||||
usb_control_acknowledge();
|
||||
}
|
||||
break;
|
||||
case HID_GET_IDLE:
|
||||
doStall = !HID_GetIdle(response);
|
||||
if (!doStall)
|
||||
{
|
||||
usb_control_dataIn(response, 1);
|
||||
}
|
||||
break;
|
||||
case HID_SET_IDLE:
|
||||
doStall = !HID_SetIdle(psetupdata->wValue >> 8); /* low byte of value is interface number */
|
||||
if (!doStall)
|
||||
{
|
||||
usb_control_acknowledge();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (doStall)
|
||||
{
|
||||
usb_ep_stall(USB_EP0OUT);
|
||||
usb_ep_stall(USB_EP0IN);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,61 @@
|
||||
/***************************************************************************//*
|
||||
**
|
||||
** Lemcusb - Firmware USB driver for EFM32 Microcontroller
|
||||
** Copyright (C) 2014 http://lemcu.org
|
||||
**
|
||||
** This library is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License version 3.0 as
|
||||
** published by the Free Software Foundation and appearing in the file
|
||||
** LICENSE.txt included in the packaging of this file.
|
||||
**
|
||||
** In addition, as a special exception, http://lemcu.org gives you certain
|
||||
** additional rights. These rights are described in the lemcu.org GPL
|
||||
** Exception version 1.0, included in the file GPL_EXCEPTION.txt in this
|
||||
** package.
|
||||
**
|
||||
** This library is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __USB_HID_H__
|
||||
#define __USB_HID_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "usb.h"
|
||||
#include "usb_config.h"
|
||||
|
||||
#ifdef USB_ENABLE_HID
|
||||
|
||||
|
||||
/* HID Report Types */
|
||||
#define HID_RPRT_INPUT (0x01)
|
||||
#define HID_RPRT_OUTPUT (0x02)
|
||||
#define HID_RPRT_FEATURE (0x03)
|
||||
|
||||
|
||||
/* HID Requests functions, need to be defined by the user! */
|
||||
/* They are not implemented as callback functions to get */
|
||||
/* a more efficient code.*/
|
||||
/* The functions should false, if they were not handled */
|
||||
/* return TRUE if function was handled */
|
||||
extern bool HID_GetReport (uint8_t reportType);
|
||||
extern bool HID_SetReport (uint8_t reportType);
|
||||
extern bool HID_GetIdle (uint8_t *pIdleTime);
|
||||
extern bool HID_SetIdle (uint8_t idleTime);
|
||||
extern bool HID_GetProtocol (uint8_t *pProtocol);
|
||||
extern bool HID_SetProtocol (uint8_t protocol);
|
||||
|
||||
|
||||
|
||||
bool usbhid_got_setup_cmd(const setupData_t *psetupdata);
|
||||
|
||||
|
||||
|
||||
#else
|
||||
#warning "HID disabled, but hid includes compiled"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,484 @@
|
||||
//****************************************************************************
|
||||
//
|
||||
// Lemcusb - Firmware USB driver for EFM32 Microcontroller
|
||||
// Copyright (C) 2014 http://lemcu.org
|
||||
//
|
||||
// This library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 3.0 as
|
||||
// published by the Free Software Foundation and appearing in the file
|
||||
// LICENSE.txt included in the packaging of this file.
|
||||
//
|
||||
// In addition, as a special exception, http://lemcu.org gives you certain
|
||||
// additional rights. These rights are described in the lemcu.org GPL
|
||||
// Exception version 1.0, included in the file GPL_EXCEPTION.txt in this
|
||||
// package.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY// without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
//**************************************************************************/
|
||||
|
||||
#if defined ( __IAR_SYSTEMS_ASM__ )
|
||||
NAME usb_internal_bitbangusb
|
||||
|
||||
;; For a description of the purpose of the following part, look here:
|
||||
;; http://supp.iar.com/Support/?note=80737&from=search+result
|
||||
;; (TOPIC: IAR assembler ramfunction)
|
||||
#define SHT_PROGBITS 0x1
|
||||
#define SHF_WRITE 0x1
|
||||
#define SHF_EXECINSTR 0x4
|
||||
RSEG MYCODE:CODE:NOROOT(2)
|
||||
SECTION_TYPE SHT_PROGBITS, SHF_WRITE | SHF_EXECINSTR
|
||||
THUMB
|
||||
EXTERN usb_protocol_handle
|
||||
|
||||
PUBLIC GPIO_ODD_IRQHandler
|
||||
PUBLIC usb_transmit
|
||||
PUBLIC protocol_handled
|
||||
#else
|
||||
.syntax unified
|
||||
.arch armv6-m
|
||||
|
||||
.SECTION .functioninRAM
|
||||
|
||||
.thumb
|
||||
.thumb_func
|
||||
|
||||
.extern usb_protocol_handle
|
||||
|
||||
|
||||
|
||||
.global GPIO_ODD_IRQHandler
|
||||
.global usb_transmit
|
||||
.global protocol_handled
|
||||
|
||||
|
||||
.type GPIO_ODD_IRQHandler, %function // IMPORTANT FOR GCC to get lsb of address set to 1
|
||||
.type protocol_handled, %function // IMPORTANT FOR GCC to get lsb of address set to 1
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
#define USBEP_OFS_SETUP ( 0)
|
||||
#define USBEP_OFS_EP0OUT (16)
|
||||
#define USBEP_OFS_EP0IN (32)
|
||||
#define USBEP_OFS_EP1OUT (48)
|
||||
#define USBEP_OFS_EP1IN (64)
|
||||
|
||||
#define USBEP_SOFS_STAT (12)
|
||||
#define USBEP_SOFS_LEN (13)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// This is the Interrupt handler, triggered by a rising edge on D+ (PC1)
|
||||
// It is implemented in assembly to minimize latency
|
||||
// (=> avoid branch from C code to ASM and addition of veneer code)
|
||||
|
||||
// This is called for each received USB data packet. received data is unstuffed.
|
||||
// The data is decoded to R8, R9, R10
|
||||
// Each data byte is in reversed bitorder. For data bytes, the bitorder
|
||||
// needs to be reversed. For PIDs, etc. bitorder reversal is not mandatory
|
||||
// The received bitcount is written to R11
|
||||
// BYTE ORDER:
|
||||
// R8. 24-31 Byte 0
|
||||
// R8. 16-23 Byte 1
|
||||
// R8. 8-15 Byte 2
|
||||
// R8. 0- 7 Byte 3
|
||||
// R9. 24-31 Byte 4
|
||||
// R9. 16-23 Byte 5
|
||||
// R9. 8-15 Byte 6
|
||||
// R9. 0- 7 Byte 7
|
||||
// R10.24-31 Byte 8
|
||||
// R10.16-23 Byte 9
|
||||
// R10. 8-15 Byte 10
|
||||
// R10. 0- 7 Byte 11
|
||||
//
|
||||
// An interupt saves the following register on stack:
|
||||
// - R0-R3, R12
|
||||
// - LR, PC & xPSR
|
||||
GPIO_ODD_IRQHandler:
|
||||
|
||||
NOP
|
||||
NOP
|
||||
|
||||
MOV r0, r8
|
||||
MOV r1, r9
|
||||
MOV r2, r10
|
||||
MOV r3, r11
|
||||
PUSH {r0-r7}
|
||||
MOV r0, LR
|
||||
PUSH {r0}
|
||||
|
||||
|
||||
MOVS r3, #3
|
||||
MOVS r4, #0xff // preload with 0xff to avoid bitunstuffing after start
|
||||
MOVS r5, #0x80
|
||||
LSLS r5, r5, #24
|
||||
MOVS r0, #0
|
||||
MOV r11, r0
|
||||
MOVS r1, #1
|
||||
MOV r12, r1
|
||||
|
||||
// r1 = 1
|
||||
// r3 = 3
|
||||
// r5 = (1<<13)
|
||||
// r7 = &GPIO_PE_DOUTSET
|
||||
|
||||
LDR r7, GPIO_PC_DIN // r7 = address of register GPIO_PC_DIN
|
||||
|
||||
// wait until a 1 is detected. Unfolded loop to be able to detect a timeout condition
|
||||
usb_sync_wait_while_0:
|
||||
LDR r0, [r7] // read port state
|
||||
TST r0, r1
|
||||
BEQ usb_sync_found
|
||||
LDR r0, [r7] // read port state
|
||||
TST r0, r1
|
||||
BEQ usb_sync_found
|
||||
LDR r0, [r7] // read port state
|
||||
TST r0, r1
|
||||
BEQ usb_sync_found
|
||||
LDR r0, [r7] // read port state
|
||||
TST r0, r1
|
||||
BEQ usb_sync_found
|
||||
LDR r0, [r7] // read port state
|
||||
TST r0, r1
|
||||
BEQ usb_sync_found
|
||||
LDR r0, [r7] // read port state
|
||||
TST r0, r1
|
||||
BEQ usb_sync_found
|
||||
LDR r0, [r7] // read port state
|
||||
TST r0, r1
|
||||
BEQ usb_sync_found
|
||||
|
||||
B protocol_handled // State was zero for more than 1 bittime => exit (timeout condition)
|
||||
|
||||
|
||||
usb_sync_found:
|
||||
// delay 1 bittime
|
||||
LDR r0, [r7] // read port state
|
||||
TST r0, r1
|
||||
BNE usb_sync_wait_while_0
|
||||
LDR r0, [r7] // read port state
|
||||
TST r0, r1
|
||||
BNE usb_sync_wait_while_0
|
||||
LDR r0, [r7] // read port state
|
||||
TST r0, r1
|
||||
BNE usb_sync_wait_while_0
|
||||
LDR r0, [r7] // read port state
|
||||
TST r0, r1
|
||||
BNE usb_sync_wait_while_0
|
||||
LDR r0, [r7] // read port state
|
||||
TST r0, r1
|
||||
BNE usb_sync_wait_while_0
|
||||
NOP
|
||||
|
||||
// check, if bitstate is still 1 (=> if 2 consecutive 1 bits received)
|
||||
LDR r2, [r7] // read port state
|
||||
TST r2, r1
|
||||
BNE usb_sync_wait_while_0
|
||||
|
||||
BL _delay_13
|
||||
|
||||
// here: We are in the middle of the very first bit of this packet
|
||||
// r0 = port state current
|
||||
// r1 = 1
|
||||
// r2 = port state old
|
||||
// r3 = 3
|
||||
// r4/5/6 = received data (parallel)
|
||||
// r7 = address of GPIO_PC_DIN
|
||||
// r11 = bitcounter
|
||||
MOVS r1, #0
|
||||
|
||||
rcv_bits: LDR r0, [r7] // read port state
|
||||
ANDS r0, r3 // check for SE0 and mask out unneeded bits
|
||||
BEQ se0_detected // end of receive loop!
|
||||
EORS r2, r0 // NRZ decoding (XOR bitstate with old bitstate) => inverts data, USB uses NRZI!
|
||||
LSRS r2, r2, #1
|
||||
ADCS r4, r4, r4 // Shift carry into receive chain
|
||||
ADCS r5, r5, r5
|
||||
ADCS r6, r6, r6
|
||||
ADD r11, r11, r12 // increment bitcounter
|
||||
MOV r2, r0 // Store old bitstate
|
||||
NOP
|
||||
LSLS r1, r1, #1 // Shift bitunstuffing EOR mask
|
||||
LSLS r0, r4, #26 // Mask out last 6 received bits
|
||||
EORS r0, r0, r1 // check if 6 consecutive 0s have been received
|
||||
BNE rcv_bits
|
||||
|
||||
// here we get when bitunstuffing needs to be done
|
||||
// 15/16 cycles over
|
||||
NOP //16
|
||||
LDR r2, [r7] // 1 // read port state to save it as "old" bitstate
|
||||
BL _delay_11 //12
|
||||
MOVS r1, #1 //13 // save bitunstuffing EOR mask
|
||||
LSLS r1, r1, #26 //14
|
||||
B rcv_bits //16
|
||||
|
||||
|
||||
|
||||
|
||||
se0_detected:
|
||||
// left align data (rough: 32 Bit steps)
|
||||
MOV r0, r11
|
||||
CMP r0, #64
|
||||
BHI se0_detected_align_0
|
||||
|
||||
MOVS r6, r5
|
||||
MOVS r5, r4
|
||||
SUBS r4, r4, r4 // not mandatory
|
||||
|
||||
CMP r0, #32
|
||||
BHI se0_detected_align_0
|
||||
|
||||
MOVS r6, r5
|
||||
MOVS r5, r4
|
||||
SUBS r4, r4, r4 // not mandatory
|
||||
|
||||
// left align data (fine alignment: 0..31 bits)
|
||||
se0_detected_align_0: MOV r0, r11
|
||||
MOVS r1, #31
|
||||
ANDS r1, r1, r0 // r1 = bitcount & 31
|
||||
|
||||
CMP r1, #0
|
||||
BEQ se0_alginment_done
|
||||
|
||||
MOVS r0, #0
|
||||
MVNS r0, r0 // r0 = 0xffffffff
|
||||
LSRS r0, r0, r1 // 8 => 0x00ffffff, 24 => 0x000000ff r0 = Mask of bytes to copy from lower word to upper one
|
||||
|
||||
RORS r6, r6, r1 //
|
||||
BICS r6, r6, r0 // r6 = r6 and not r0 (reset lower bytes to 0)
|
||||
|
||||
RORS r5, r5, r1 //
|
||||
MOVS r2, r5
|
||||
ANDS r2, r2, r0
|
||||
ORRS r6, r6, r2 //
|
||||
BICS r5, r5, r0 // r6 = r6 and not r0 (reset lower bytes to 0)
|
||||
|
||||
RORS r4, r4, r1 //
|
||||
MOVS r2, r4
|
||||
ANDS r2, r2, r0
|
||||
ORRS r5, r5, r2
|
||||
BICS r4, r4, r0 // not mandatory
|
||||
|
||||
|
||||
|
||||
// Invert data (NRZ => NRZI)
|
||||
se0_alginment_done: MVNS r0, r4
|
||||
MOV r10, r0
|
||||
MVNS r0, r5
|
||||
MOV r9, r0
|
||||
MVNS r0, r6
|
||||
MOV r8, r0
|
||||
|
||||
LDR r0, LABEL_USB_PROT_HDL
|
||||
BX r0 // Jump to protocol state machine code located in Flash
|
||||
|
||||
|
||||
protocol_handled:
|
||||
// This was for debugging. enable it, if you want to debug host packets only
|
||||
// MOVS r5, #255
|
||||
//delayloop:
|
||||
// SUBS r5, r5, #1
|
||||
// BNE delayloop
|
||||
|
||||
// acknowledge GPIO interrupt
|
||||
LDR r6, GPIO_IFC
|
||||
MOVS r5, #2
|
||||
STR r5, [r6]
|
||||
|
||||
POP {r0}
|
||||
MOV LR, r0
|
||||
|
||||
POP {r0-r7}
|
||||
MOV r8, r0
|
||||
MOV r9, r1
|
||||
MOV r10, r2
|
||||
MOV r11, r3 // r0-r3 are restored by ISR return
|
||||
BX LR // return
|
||||
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
|
||||
#if defined ( __IAR_SYSTEMS_ASM__ )
|
||||
DATA
|
||||
ALIGNROM 2
|
||||
GPIO_PC_DIN: DC32 0x40006064 ; GPIO_PC_DIN
|
||||
GPIO_PE_DOUTSET DC32 0x400060a0 ; GPIO_PE_DOUTSET.DOUTSET
|
||||
GPIO_IFC: DC32 0x4000611c ; GPIO.IFC
|
||||
LABEL_USB_PROT_HDL: DC32 usb_protocol_handle
|
||||
//GPIO_PB_TOGGLE: DC32 0x4000603C ; REMOVEME
|
||||
|
||||
#else
|
||||
.BALIGN 4
|
||||
GPIO_PC_DIN: .INT 0x40006064 // GPIO_PC_DIN
|
||||
GPIO_PE_DOUTSET: .INT 0x400060a0 // GPIO_PE_DOUTSET.DOUTSET
|
||||
GPIO_IFC: .INT 0x4000611c // GPIO.IFC
|
||||
LABEL_USB_PROT_HDL: .INT usb_protocol_handle
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#if defined ( __IAR_SYSTEMS_ASM__ )
|
||||
CODE
|
||||
THUMB
|
||||
#else
|
||||
.SECTION .functioninRAM
|
||||
.THUMB
|
||||
#endif
|
||||
// This function transmits a USB packet as response to the host
|
||||
// Used for : ACK, NAK, STALL, DATA0 & DATA1 PIDs
|
||||
// Parameters:
|
||||
// r0/r1/r2 = Data to transmit
|
||||
// r5 = Bitcount
|
||||
// The Bitorder of the transmission is the right one (no bitreversal as in receive function)
|
||||
// transmit order:
|
||||
// r0.0-7 => r0.8-15 => r0.16-23 => r0.24-31 =>
|
||||
// r1.0-7 => r1.8-15 => r1.16-23 => r1.24-31 =>
|
||||
// r2.0-7 => r2.8-15 => r2.16-23 => r2.24-31
|
||||
usb_transmit:
|
||||
MOV r7, LR
|
||||
PUSH {r7}
|
||||
// Switch PC0 & PC1 to output
|
||||
LDR r7, GPIO_PC_BASE
|
||||
LDR r3, [r7, #4] // read pin mode low register
|
||||
ADDS r3, r3, #0x33 // mode Input = 0x11, Output = 0x44
|
||||
STR r3, [r7, #4] // writepin mode low register
|
||||
// IO state = push pull & IDLE (D-=1 D+=0)
|
||||
|
||||
// 1.) Send SYNC Byte
|
||||
MOVS r3, #0x03 // bitmask for toggling IO pin
|
||||
MOVS r4, #7
|
||||
usb_tx_syncloop: STR r3, [r7, #24] // Toggle IOs to transmit a 0
|
||||
BL _delay_12
|
||||
SUBS r4, r4, #1
|
||||
BNE usb_tx_syncloop
|
||||
//15
|
||||
// transmit a "1" - last bit of SYNC sequence
|
||||
BL _delay_12
|
||||
|
||||
// 2.) Send data given in registers r0/r1/r2 and bitcount in r5
|
||||
// Here all bits get transmitted. Bitstuffing is also applied
|
||||
// The minimal version of this would only need 6 cycles
|
||||
MOVS r4, #5 // consecutive 1-Bit counter (used for bitstuffing). Last transmitted Bit was 1, so initialize it with 5 rather than 6
|
||||
MOVS r6, #32 // Needed to check if a new 32 Bit word should be transmitted
|
||||
usb_tx_bitloop: LSRS r0, r0, #1 // shift out bit to carry flag for transmitting
|
||||
BCS usb_txbitloop_send1 //do nothing if bit is 1 (only a zero causes toggling
|
||||
usb_txbitloop_send0: STR r3, [r7, #24] // Toggle IOs to transmit a 0
|
||||
MOVS r4, #6 // Reset 1-Bit counter
|
||||
B usb_txbitloop_sent1
|
||||
usb_txbitloop_send1: SUBS r4, #1
|
||||
BEQ usb_tx_sendstuffbit
|
||||
usb_tx_bitstutt_ret: NOP // equalize execution time for 2 branch paths
|
||||
usb_txbitloop_sent1: SUBS r5, r5, #1
|
||||
BEQ usb_tx_send_eop // final word transmitted
|
||||
SUBS r6, r6, #1
|
||||
BEQ usb_txbit_nextword
|
||||
NOP
|
||||
NOP
|
||||
NOP
|
||||
NOP
|
||||
B usb_tx_bitloop
|
||||
|
||||
// select next word for transmission
|
||||
usb_txbit_nextword: MOVS r0, r1
|
||||
MOVS r1, r2
|
||||
MOVS r6, #32
|
||||
B usb_tx_bitloop
|
||||
|
||||
// Send stuffbit
|
||||
// 4 cycles over since last bit
|
||||
usb_tx_sendstuffbit: BL _delay_11
|
||||
MOVS r4, #6 // Reset 1-Bit counter
|
||||
STR r3, [r7, #24] // Toggle IOs to transmit a 0
|
||||
B usb_tx_bitstutt_ret
|
||||
|
||||
// send EOP (2*SE0)
|
||||
// 7 cycles over since last bit
|
||||
usb_tx_send_eop:
|
||||
BL _delay_9
|
||||
STR r3, [r7, #20] // write to GPIO_PC_DOUTCLR to set D+ and D- to LOW
|
||||
BL _delay_10
|
||||
BL _delay_10
|
||||
BL _delay_10
|
||||
|
||||
MOVS r1, #1
|
||||
STR r1, [r7, #16] // Set D- back to HIGH
|
||||
|
||||
// Switch PC0 & PC1 to input
|
||||
LDR r7, GPIO_PC_BASE
|
||||
LDR r0, [r7, #4] // read pin mode low register
|
||||
SUBS r0, r0, #0x33 // set from 0x44 to 0x11 (push pull to input)
|
||||
STR r0, [r7, #4] // writepin mode low register
|
||||
|
||||
// // delay some time for easier debugging
|
||||
// MOVS r5, #255
|
||||
//delayloop_x: MOVS r4, #6 // reset 1-bit counter
|
||||
// SUBS r5, r5, #1
|
||||
// BNE delayloop_x
|
||||
POP {r0}
|
||||
MOV LR, r0
|
||||
BX LR
|
||||
|
||||
// some delay functions:
|
||||
_delay_14: NOP
|
||||
_delay_13: NOP
|
||||
_delay_12: NOP
|
||||
_delay_11: NOP
|
||||
_delay_10: NOP
|
||||
_delay_9: NOP
|
||||
_delay_8: NOP
|
||||
_delay_7: NOP
|
||||
_delay_6: NOP
|
||||
_delay_5: BX LR
|
||||
|
||||
|
||||
#if defined ( __IAR_SYSTEMS_ASM__ )
|
||||
|
||||
DATA
|
||||
ALIGNROM 2
|
||||
GPIO_PC_BASE: DC32 0x40006048 ; GPIO_PC_DIN - This is redundant, has already been defined in the RX function
|
||||
GPIO_PE_DOUTSET_ DC32 0x400060a0 ; GPIO_PE_DOUTSET.DOUTSET
|
||||
|
||||
END
|
||||
|
||||
#else
|
||||
|
||||
.BALIGN 4
|
||||
GPIO_PC_BASE: .INT 0x40006048 // GPIO_PC_DIN - This is redundant, has already been defined in the RX function
|
||||
GPIO_PE_DOUTSET_: .INT 0x400060a0 // GPIO_PE_DOUTSET.DOUTSET
|
||||
|
||||
.END
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
TODO:
|
||||
- Flag endpoint status based on Host reply
|
||||
- interpret CRC5 ??
|
||||
- detect RESET condition on bus (very long SE0 phase, check USB spec. for duration). This should reset the usb address
|
||||
- RESET = SE0 for >= 10ms
|
||||
|
||||
- codesize optimization:
|
||||
* use branches to identical code secitions
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Lemcusb - Firmware USB driver for EFM32 Microcontroller
|
||||
** Copyright (C) 2014 http://lemcu.org
|
||||
**
|
||||
** This library is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License version 3.0 as
|
||||
** published by the Free Software Foundation and appearing in the file
|
||||
** LICENSE.txt included in the packaging of this file.
|
||||
**
|
||||
** In addition, as a special exception, http://lemcu.org gives you certain
|
||||
** additional rights. These rights are described in the lemcu.org GPL
|
||||
** Exception version 1.0, included in the file GPL_EXCEPTION.txt in this
|
||||
** package.
|
||||
**
|
||||
** This library is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* Low level internal functions.
|
||||
* These functions are internal.
|
||||
*/
|
||||
|
||||
//#include "em_device.h"
|
||||
#include <stdint.h>
|
||||
//#include "em_chip.h"
|
||||
//#include "em_int.h"
|
||||
#include "gpio.h"
|
||||
//#include "em_cmu.h"
|
||||
|
||||
#include "usb_config.h"
|
||||
|
||||
/* Endpoint buffers
|
||||
Offset 0: SETUP packets
|
||||
Offset 16: EP0OUT
|
||||
Offset 32: EP0IN
|
||||
(Offset 48: EP1OUT)
|
||||
(Offset 64: EP1IN)
|
||||
|
||||
Offsets within one of theese buffers:
|
||||
0-11: Raw data
|
||||
Offset 12: _STAT Status empty/filled (0x00/0x01)
|
||||
Offset 13: _LEN Length of data in buffer
|
||||
14 & 15 are free for future used - would be added anyway by codegen tools for alignment
|
||||
*/
|
||||
volatile uint8_t usb_ep_buffers[ (3+2*USB_ENABLE_EP1OUT_EP1IN)*16 ];
|
||||
|
||||
/* low level protocol handling state */
|
||||
/* Bit 0- 7 = state machine index*/
|
||||
/* Bit 8-15 = last received USB Address (bitreversed: a0 a1 a2 a3 a4 a5 a6 0) */
|
||||
/* Bit 16-23 = last received USB Endpoint (bitreversed: e0 e1 e2 e3 0 0 0 0) */
|
||||
/* Bit 24-31 = not used yet */
|
||||
uint32_t USB_PROT_STATE;
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/***************************************************************************//*
|
||||
**
|
||||
** Lemcusb - Firmware USB driver for EFM32 Microcontroller
|
||||
** Copyright (C) 2014 http://lemcu.org
|
||||
**
|
||||
** This library is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License version 3.0 as
|
||||
** published by the Free Software Foundation and appearing in the file
|
||||
** LICENSE.txt included in the packaging of this file.
|
||||
**
|
||||
** In addition, as a special exception, http://lemcu.org gives you certain
|
||||
** additional rights. These rights are described in the lemcu.org GPL
|
||||
** Exception version 1.0, included in the file GPL_EXCEPTION.txt in this
|
||||
** package.
|
||||
**
|
||||
** This library is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __USB_INTERNAL_H__
|
||||
#define __USB_INTERNAL_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "usb_config.h"
|
||||
|
||||
#define USB_EPBUF_OFFSET_SETUP_BUF ( 0)
|
||||
#define USB_EPBUF_OFFSET_EP0OUT_BUF (16)
|
||||
#define USB_EPBUF_OFFSET_EP0IN_BUF (32)
|
||||
#define USB_EPBUF_OFFSET_EP1OUT_BUF (48)
|
||||
#define USB_EPBUF_OFFSET_EP1IN_BUF (64)
|
||||
|
||||
#define USB_EPBUF_SUBOFFSET_STAT (12)
|
||||
#define USB_EPBUF_SUBOFFSET_LEN (13)
|
||||
|
||||
|
||||
/* Endpoint buffers
|
||||
Offset 0: SETUP packets
|
||||
Offset 16: EP0OUT
|
||||
Offset 32: EP0IN
|
||||
(Offset 48: EP1OUT)
|
||||
(Offset 64: EP1IN)
|
||||
|
||||
Sub-offsets within one of these buffers:
|
||||
0-11: Raw data
|
||||
Offset 12: _STAT Status empty/filled (0x00/0x01)
|
||||
Offset 13: _LEN Length of data in buffer
|
||||
14 & 15 are free for future used - would be added anyway by codegen tools for alignment
|
||||
*/
|
||||
|
||||
|
||||
/* Endpoint buffers */
|
||||
extern volatile uint8_t usb_ep_buffers[ (3+2*USB_ENABLE_EP1OUT_EP1IN)*16 ];
|
||||
|
||||
extern uint32_t USB_PROT_STATE;
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,329 @@
|
||||
#include "usb_config.h"
|
||||
|
||||
#if defined ( __IAR_SYSTEMS_ASM__ )
|
||||
NAME usb_internal_prot_handling
|
||||
#ifdef USB_PROTOCOL_HANDLING_IN_RAM
|
||||
#define SHT_PROGBITS 0x1
|
||||
#define SHF_WRITE 0x1
|
||||
#define SHF_EXECINSTR 0x4
|
||||
RSEG MYCODE:CODE:NOROOT(2)
|
||||
SECTION_TYPE SHT_PROGBITS, SHF_WRITE | SHF_EXECINSTR
|
||||
THUMB
|
||||
#else
|
||||
section CODE:CODE (2)
|
||||
CODE
|
||||
#endif
|
||||
|
||||
THUMB
|
||||
|
||||
EXTERN usb_dev_address
|
||||
EXTERN USB_PROT_STATE
|
||||
EXTERN usb_ep_buffers
|
||||
EXTERN protocol_handled
|
||||
EXTERN usb_transmit
|
||||
|
||||
|
||||
PUBLIC usb_protocol_handle
|
||||
#else
|
||||
.syntax unified
|
||||
.arch armv6-m
|
||||
#ifdef USB_PROTOCOL_HANDLING_IN_RAM
|
||||
.THUMB
|
||||
.section .functioninRAM
|
||||
#else
|
||||
.BALIGN 4
|
||||
.TEXT
|
||||
#endif
|
||||
.THUMB
|
||||
|
||||
.EXTERN usb_dev_address
|
||||
.EXTERN USB_PROT_STATE
|
||||
.EXTERN usb_ep_buffers
|
||||
.EXTERN protocol_handled
|
||||
.EXTERN usb_transmit
|
||||
|
||||
|
||||
.GLOBAL usb_protocol_handle
|
||||
|
||||
.type usb_protocol_handle, %function // IMPORTANT FOR GCC to get lsb of address set to 1
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
/* Endpoint buffer offsets and suboffsets*/
|
||||
#define USBEP_OFS_SETUP ( 0)
|
||||
#define USBEP_OFS_EP0OUT (16)
|
||||
#define USBEP_OFS_EP0IN (32)
|
||||
#define USBEP_OFS_EP1OUT (48)
|
||||
#define USBEP_OFS_EP1IN (64)
|
||||
#define USBEP_SOFS_STAT (12)
|
||||
#define USBEP_SOFS_LEN (13)
|
||||
|
||||
|
||||
/* some internal C-Style MACROs */
|
||||
#define REV2(x) ((((x)&1)<<1) | (((x)>>1)&1))
|
||||
#define REV4(x) ((REV2(x)<<2) | (REV2((x)>>2)))
|
||||
#define REV8(x) ((REV4(x)<<4) | (REV4((x)>>4)))
|
||||
#define CREATE_PID(x) (x & 0x0F) | (((~x) & 0x0f)<<4)
|
||||
|
||||
/* define Bitreversed PIDs */
|
||||
#define USB_TOKEN_BR_OUT REV8(CREATE_PID( 0x01 ))
|
||||
#define USB_TOKEN_BR_IN REV8(CREATE_PID( 0x09 ))
|
||||
#define USB_TOKEN_BR_SETUP REV8(CREATE_PID( 0x0d ))
|
||||
#define USB_TOKEN_BR_DATA0 REV8(CREATE_PID( 0x03 ))
|
||||
#define USB_TOKEN_BR_DATA1 REV8(CREATE_PID( 0x0b ))
|
||||
#define USB_TOKEN_BR_ACK REV8(CREATE_PID( 0x02 ))
|
||||
#define USB_TOKEN_BR_NAK REV8(CREATE_PID( 0x0a ))
|
||||
|
||||
/* define PIDs used for transmit (not bitreversed) */
|
||||
#define USB_TOKEN_ACK CREATE_PID( 0x02 )
|
||||
#define USB_TOKEN_NAK CREATE_PID( 0x0a )
|
||||
#define USB_TOKEN_STALL CREATE_PID( 0x0e )
|
||||
|
||||
|
||||
|
||||
// The following registers are saved externally on stack:
|
||||
// r0-r11
|
||||
// Registers that are not allowed to be modified:
|
||||
// r12, LR
|
||||
|
||||
// Input data:
|
||||
// -----------
|
||||
// r11 = received bitcount
|
||||
// r8...r10 = received data
|
||||
//
|
||||
|
||||
// Output data:
|
||||
// ------------
|
||||
// none
|
||||
|
||||
// A complete packet was received.
|
||||
// Now do some protocol handling
|
||||
// 1.) Identify PID R8.24-31
|
||||
usb_protocol_handle:
|
||||
|
||||
LDR r7, ASM_USB_PROT_STATE // r7 = pointer to protocol state variable
|
||||
LDRB r6, [r7] // r6 = state machine state
|
||||
LDRB r5, [r7, #1] // r5 = Address from state variable
|
||||
LDRB r4, [r7, #2] // r4 = Endpoint from state variable
|
||||
LDR r3, ASM_USB_DEV_ADDRESS
|
||||
LDRB r3, [r3] // r3 = USB Addresss of this device
|
||||
MOV r0, r8
|
||||
LSRS r0, r0, #24 // r0 now contains the PID only
|
||||
CMP r0, #USB_TOKEN_BR_SETUP // sends address and endpoint as parameter
|
||||
BEQ pid_setup
|
||||
CMP r0, #USB_TOKEN_BR_DATA0
|
||||
BEQ pid_data0
|
||||
CMP r0, #USB_TOKEN_BR_DATA1
|
||||
BEQ pid_data1
|
||||
CMP r0, #USB_TOKEN_BR_IN // sends address and endpoint as parameter
|
||||
BEQ pid_in
|
||||
CMP r0, #USB_TOKEN_BR_OUT // sends address and endpoint as parameter
|
||||
BEQ pid_out
|
||||
|
||||
jump_exit: LDR r0, LBL_PROT_HANDLED
|
||||
BX r0
|
||||
|
||||
|
||||
|
||||
////////////// Protocol handling statemachine
|
||||
// r7 = pointer to protocol state variable
|
||||
// r6 = state machine state (Byte 0)
|
||||
// r5 = Address & endpoint from state variable (Byte 1)
|
||||
pid_setup: MOVS r0, #0
|
||||
STRB r0, [r7] // Flag, that the next data package is a setup packet
|
||||
MOV r0, r8
|
||||
// extract address
|
||||
LSRS r1, r0, #16
|
||||
MOVS r2, #0xfe
|
||||
ANDS r1, r1, r2 // Mask out address bits a0-a6. Order: a0 a1 a2 a3 a4 a5 a6 0
|
||||
STRB r1, [r7, #1] // Store address in protocol state
|
||||
|
||||
// extract endpoint number
|
||||
LSRS r1, r0, #9
|
||||
MOVS r2, #0xf0
|
||||
ANDS r1, r1, r2
|
||||
STRB r1, [r7, #2] // Store endpoint in protocol state => TODO: APPLY MASK! Bitorder e0 e1 e2 e3 0 0 0 0
|
||||
|
||||
B jump_exit
|
||||
|
||||
pid_data0:
|
||||
pid_data1:
|
||||
// Check the usb address
|
||||
CMP r5, r3
|
||||
BNE jump_exit // This device is not addressed => Don't react on DATA PID
|
||||
|
||||
CMP r6, #0 // check if this is data is a setup phase or out phase
|
||||
BEQ pid_data_setup
|
||||
|
||||
// Here: data PID is for OUT phase
|
||||
|
||||
// Create pointer to addressed endpoint buffer
|
||||
LDR r6, ASM_USB_EP_BUFFERS
|
||||
|
||||
LDRB r1, [r7, #2] // Store endpoint in protocol state => TODO: APPLY MASK! Bitorder e0 e1 e2 e3 0 0 0 0
|
||||
CMP r1, #0
|
||||
BEQ pid_da_ep0_addressed
|
||||
ADDS r6, r6, #USBEP_OFS_EP1OUT
|
||||
B pid_da_ep1_addressed
|
||||
pid_da_ep0_addressed: ADDS r6, r6, #USBEP_OFS_EP0OUT
|
||||
pid_da_ep1_addressed:
|
||||
|
||||
LDRB r0, [r6, #USBEP_SOFS_STAT]
|
||||
// check if endpoint is stalled
|
||||
MOVS r2, #2
|
||||
TST r0, r2
|
||||
BNE send_STALL
|
||||
|
||||
// check if endpoint contains data
|
||||
MOVS r1, #1
|
||||
TST r0, r1 // if equal => Endpoint buffer is free
|
||||
BNE send_NAK
|
||||
|
||||
// here: buffer available and endpoint not stalled, so copy data to buffer...
|
||||
MOV r0, r8
|
||||
MOV r1, r9
|
||||
MOV r2, r10
|
||||
MOV r5, r6 // generate address to EP0buffer data
|
||||
STM r5!, {r0, r1, r2} // copy data to EP0OUT buffer
|
||||
MOV r0, r11 // EP0OUT_LEN is filled with the received bitcount (includes PID & CRC)
|
||||
STRB r0, [r6, #USBEP_SOFS_LEN]
|
||||
|
||||
LDRB r1, [r6, #USBEP_SOFS_STAT]
|
||||
MOVS r0, #1
|
||||
ORRS r1, r1, r0
|
||||
STRB r1, [r6, #USBEP_SOFS_STAT] // set "data available" flag for EP0OUT Buffer
|
||||
B send_ACK
|
||||
|
||||
pid_data_setup: LDR r6, ASM_USB_EP_BUFFERS // copy setup data to buffer
|
||||
MOV r0, r8
|
||||
MOV r1, r9
|
||||
MOV r2, r10
|
||||
MOV r5, r6 // generate address to EP0buffer data
|
||||
ADDS r5, r5, #USBEP_OFS_SETUP
|
||||
STM r5!, {r0, r1, r2} // copy data to SETUP buffer
|
||||
LDRB r1, [r6, #(USBEP_OFS_SETUP + USBEP_SOFS_STAT)]
|
||||
MOVS r0, #1
|
||||
ORRS r1, r1, r0
|
||||
STRB r1, [r6, #(USBEP_OFS_SETUP + USBEP_SOFS_STAT)] // set "data available" flag for SETUP BUFFER
|
||||
|
||||
// SEND ACK... This is the only option. NAK is not allowed in a setup phase
|
||||
B send_ACK
|
||||
|
||||
|
||||
pid_in: MOVS r0, #2
|
||||
STRB r0, [r7] // Flag, that an IN PID was received
|
||||
|
||||
// extract address
|
||||
MOV r0, r8
|
||||
LSRS r1, r0, #16
|
||||
MOVS r2, #0xfe
|
||||
ANDS r1, r1, r2 // Mask out address bits a0-a6. Order: a0 a1 a2 a3 a4 a5 a6 0
|
||||
STRB r1, [r7, #1] // Store address in protocol state
|
||||
|
||||
// check if USB Address is for this device
|
||||
CMP r1, r3
|
||||
BNE jump_exit // This device is not addressed => Don't react on DATA PID
|
||||
|
||||
// extract endpoint number
|
||||
LSRS r1, r0, #9
|
||||
MOVS r2, #0xf0
|
||||
ANDS r1, r1, r2
|
||||
STRB r1, [r7, #2] // Store endpoint in protocol state => TODO: APPLY MASK! Bitorder e0 e1 e2 e3 0 0 0 0
|
||||
|
||||
// build pointer to correct endpoint buffer
|
||||
LDR r5, ASM_USB_EP_BUFFERS
|
||||
CMP r1, #0
|
||||
BEQ pid_in_ep0_addressed
|
||||
ADDS r5, r5, #USBEP_OFS_EP1IN
|
||||
B pid_in_ep1_addressed
|
||||
pid_in_ep0_addressed: ADDS r5, r5, #USBEP_OFS_EP0IN
|
||||
pid_in_ep1_addressed:
|
||||
|
||||
// check stall condition
|
||||
LDRB r0, [r5, #USBEP_SOFS_STAT] // Bit0 = 0 = no data available => send NAK, Bit 0 = 1 = data availabe => send data
|
||||
MOVS r2, #2
|
||||
TST r0, r2
|
||||
BNE send_STALL // Check and handle Endpoint STALL condition
|
||||
|
||||
// check if data is available in addressed endpoint
|
||||
MOVS r1, #1
|
||||
TST r0, r1
|
||||
BEQ send_NAK
|
||||
// send Data. Important: First byte contains correct DATA PID (DATA0/DATA1)
|
||||
|
||||
PUSH {r5}
|
||||
LDM r5!, {r0, r1, r2}
|
||||
LDRB r5, [r5, #1] // => USBEP_SOFS_LEN
|
||||
LSLS r5, r5, #3 //Count of bits to transmit
|
||||
BL usb_transmit
|
||||
POP {r5}
|
||||
|
||||
LDRB r1, [r5, #USBEP_SOFS_STAT]
|
||||
MOVS r0, #0xfe
|
||||
ANDS r1, r1, r0
|
||||
STRB r1, [r5, #USBEP_SOFS_STAT] // Flag EP0IN as empty
|
||||
B jump_exit
|
||||
|
||||
|
||||
pid_out: MOVS r0, #1
|
||||
STRB r0, [r7] // Flag, that the next data package is for an endpoint
|
||||
MOV r0, r8
|
||||
// extract address
|
||||
LSRS r1, r0, #16
|
||||
MOVS r2, #0xfe
|
||||
ANDS r1, r1, r2 // Mask out address bits a0-a6. Order: a0 a1 a2 a3 a4 a5 a6 0
|
||||
STRB r1, [r7, #1] // Store address in protocol state
|
||||
|
||||
// extract endpoint number
|
||||
LSRS r1, r0, #9
|
||||
MOVS r2, #0xf0
|
||||
ANDS r1, r1, r2
|
||||
STRB r1, [r7, #2] // Store endpoint in protocol state => TODO: APPLY MASK! Bitorder e0 e1 e2 e3 0 0 0 0
|
||||
B jump_exit
|
||||
|
||||
|
||||
|
||||
// Status return functions (function => host)
|
||||
send_STALL: MOVS r0, #USB_TOKEN_STALL
|
||||
MOVS r5, #8 //Count of bits to transmit
|
||||
BL usb_transmit
|
||||
B jump_exit
|
||||
|
||||
send_NAK: MOVS r0, #USB_TOKEN_NAK
|
||||
MOVS r5, #8 //Count of bits to transmit
|
||||
BL usb_transmit
|
||||
B jump_exit
|
||||
|
||||
send_ACK: MOVS r0, #USB_TOKEN_ACK
|
||||
MOVS r5, #8 //Count of bits to transmit
|
||||
BL usb_transmit
|
||||
B jump_exit
|
||||
|
||||
|
||||
|
||||
#if defined ( __IAR_SYSTEMS_ASM__ )
|
||||
|
||||
DATA
|
||||
ALIGNROM 2
|
||||
ASM_USB_PROT_STATE: DC32 USB_PROT_STATE
|
||||
ASM_USB_EP_BUFFERS: DC32 usb_ep_buffers
|
||||
ASM_USB_DEV_ADDRESS: DC32 usb_dev_address
|
||||
LBL_PROT_HANDLED: DC32 protocol_handled
|
||||
|
||||
END
|
||||
#else
|
||||
|
||||
.BALIGN 4
|
||||
ASM_USB_PROT_STATE: .long USB_PROT_STATE
|
||||
ASM_USB_EP_BUFFERS: .long usb_ep_buffers
|
||||
ASM_USB_DEV_ADDRESS: .long usb_dev_address
|
||||
LBL_PROT_HANDLED: .long protocol_handled
|
||||
.END
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,257 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Lemcusb - Firmware USB driver for EFM32 Microcontroller
|
||||
** Copyright (C) 2014 http://lemcu.org
|
||||
**
|
||||
** This library is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License version 3.0 as
|
||||
** published by the Free Software Foundation and appearing in the file
|
||||
** LICENSE.txt included in the packaging of this file.
|
||||
**
|
||||
** In addition, as a special exception, http://lemcu.org gives you certain
|
||||
** additional rights. These rights are described in the lemcu.org GPL
|
||||
** Exception version 1.0, included in the file GPL_EXCEPTION.txt in this
|
||||
** package.
|
||||
**
|
||||
** This library is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "usb_stack.h"
|
||||
#include "usb.h"
|
||||
#include "usb_descriptors.h"
|
||||
#include "usb_helperfunctions.h"
|
||||
|
||||
#ifdef USB_ENABLE_HID
|
||||
#include "usb_hid.h"
|
||||
#endif
|
||||
|
||||
|
||||
/* Standard Request codes for Control */
|
||||
#define SRQ_GET_STATUS (0x00) /* Standard Request : Get Status */
|
||||
#define SRQ_CLEAR_FEATURE (0x01) /* Standard Request : Clear Feature */
|
||||
#define SRQ_RESERVED1 (0x02) /* Standard Request : Reserved for future use */
|
||||
#define SRQ_SET_FEATURE (0x03) /* Standard Request : Set Feature */
|
||||
#define SRQ_RESERVED2 (0x04) /* Standard Request : Reserved for future use */
|
||||
#define SRQ_SET_ADDRESS (0x05) /* Standard Request : Set Address */
|
||||
#define SRQ_GET_DESCRIPTOR (0x06) /* Standard Request : Get Descriptor */
|
||||
#define SRQ_SET_DESCRIPTOR (0x07) /* Standard Request : Set Descriptor */
|
||||
#define SRQ_GET_CONFIGURATION (0x08) /* Standard Request : Get Configuration */
|
||||
#define SRQ_SET_CONFIGURATION (0x09) /* Standard Request : Set Configuration */
|
||||
#define SRQ_GET_INTERFACE (0x0a) /* Standard Request : Get Interface */
|
||||
#define SRQ_SET_INTERFACE (0x0b) /* Standard Request : Set Interface */
|
||||
#define SRQ_SYNCH_FRAME (0x0c) /* Standard Request : Synch Frame */
|
||||
|
||||
/* Status type codes used in SRQ_GET_STATUS request */
|
||||
#define STATUS_DEVICE (0x80) /* Get Status: Device */
|
||||
#define STATUS_INTERFACE (0x81) /* Get Status: Interface */
|
||||
#define STATUS_ENDPOINT (0x82) /* Get Status: End Point */
|
||||
|
||||
/* Feature type codes used in SRQ_SET_FEATURE request */
|
||||
#define FEATURE_DEVICE (0x00) /* Feature: Device */
|
||||
#define FEATURE_ENDPOINT (0x02) /* Feature: End Point */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
uint8_t usb_dev_address; /* default address is 0x00 TODO: Reset to zero when a reset condition is present on BUS (SE0 long duration) */
|
||||
static uint8_t usb_dev_configuration;
|
||||
static uint8_t usb_dev_alternatesetting;
|
||||
static uint8_t usb_dev_Rwuen;
|
||||
static uint8_t usb_dev_selfpwr;
|
||||
|
||||
|
||||
|
||||
|
||||
void usbstack_init(void)
|
||||
{
|
||||
usb_dev_address = 0x00;
|
||||
usb_dev_configuration = 0;
|
||||
usb_dev_alternatesetting = 0;
|
||||
usb_dev_Rwuen = 0;
|
||||
usb_dev_selfpwr = 0;
|
||||
}
|
||||
|
||||
|
||||
bool usbstack_got_setup_cmd(const setupData_t *psetupdata)
|
||||
{
|
||||
uint8_t response[8];
|
||||
uint16_t clen;
|
||||
bool handled;
|
||||
|
||||
handled = true;
|
||||
|
||||
switch(psetupdata->bRequest)
|
||||
{
|
||||
case SRQ_SET_ADDRESS: /* This needs to be done within 50ms after receiving the setup packet! */
|
||||
usb_control_acknowledge();
|
||||
while (!usb_ep_in_buf_empty(0)); /* Wait until the complete setup transfer is finished, before setting the usb device address */
|
||||
usb_dev_address = bitreverse(psetupdata->wValue);
|
||||
/* set Address does not have an OUT stage */
|
||||
break;
|
||||
case SRQ_GET_DESCRIPTOR: // *** Get Descriptor
|
||||
switch (psetupdata->wValue >> 8)
|
||||
{
|
||||
case DESCRIPTOR_DEVICE: // Device
|
||||
clen = psetupdata->wLength;
|
||||
if (clen > sizeof(device_descriptor)) clen = sizeof(device_descriptor);
|
||||
usb_control_dataIn(device_descriptor, clen);
|
||||
break;
|
||||
case DESCRIPTOR_CONFIGURATION: // Configuration setupdat[2] contains configuration number
|
||||
clen = psetupdata->wLength;
|
||||
if (clen > sizeof(config_0_descriptor))
|
||||
{
|
||||
clen = sizeof(config_0_descriptor);
|
||||
}
|
||||
usb_control_dataIn(config_0_descriptor, clen); /* setupdat[2] specifies configurationnumber, currently fixed to 0 */
|
||||
|
||||
if (clen == 0x09)
|
||||
{
|
||||
volatile int i;
|
||||
i++;
|
||||
}
|
||||
|
||||
break;
|
||||
case DESCRIPTOR_STRING: // String setupdat[2] contains string index
|
||||
switch (psetupdata->wValue & 0xff)
|
||||
{
|
||||
case 0:
|
||||
clen = psetupdata->wLength;
|
||||
if (clen > sizeof(string_0_descriptor)) clen = sizeof(string_0_descriptor);
|
||||
usb_control_dataIn(string_0_descriptor, clen);
|
||||
break;
|
||||
case 1:
|
||||
clen = psetupdata->wLength;
|
||||
if (clen > sizeof(string_1_descriptor)) clen = sizeof(string_1_descriptor);
|
||||
usb_control_dataIn(string_1_descriptor, clen);
|
||||
break;
|
||||
case 2:
|
||||
clen = psetupdata->wLength;
|
||||
if (clen > sizeof(string_2_descriptor)) clen = sizeof(string_2_descriptor);
|
||||
usb_control_dataIn(string_2_descriptor, clen);
|
||||
break;
|
||||
default:
|
||||
usb_control_dataIn(response, 0);
|
||||
break;
|
||||
/* INFO: more/less string descriptors can be used. String descriptors are not mandatory! */
|
||||
}
|
||||
break;
|
||||
#ifdef USB_ENABLE_HID
|
||||
case DESCRIPTOR_REPORT:
|
||||
clen = psetupdata->wLength;
|
||||
if (clen > sizeof(hid_report_descriptor)) clen = sizeof(hid_report_descriptor);
|
||||
usb_control_dataIn(hid_report_descriptor, clen);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
usb_ep_stall(USB_EP0OUT);
|
||||
usb_ep_stall(USB_EP0IN);
|
||||
handled = false;
|
||||
}
|
||||
break;
|
||||
case SRQ_GET_INTERFACE:
|
||||
response[0] = usb_dev_alternatesetting;
|
||||
usb_control_dataIn(response, 1);
|
||||
break;
|
||||
case SRQ_SET_INTERFACE:
|
||||
usb_dev_alternatesetting = psetupdata->wValue;
|
||||
usb_control_acknowledge();
|
||||
break;
|
||||
case SRQ_SET_CONFIGURATION:
|
||||
usb_dev_configuration = psetupdata->wValue;
|
||||
usb_control_acknowledge();
|
||||
break;
|
||||
case SRQ_GET_CONFIGURATION:
|
||||
response[0] = usb_dev_configuration;
|
||||
usb_control_dataIn(response, 1);
|
||||
break;
|
||||
case SRQ_GET_STATUS:
|
||||
switch(psetupdata->bmRequestType)
|
||||
{
|
||||
case STATUS_DEVICE:
|
||||
response[0] = (usb_dev_Rwuen << 1) | usb_dev_selfpwr;
|
||||
response[1] = 0;
|
||||
usb_control_dataIn(response, 2);
|
||||
break;
|
||||
case STATUS_INTERFACE:
|
||||
response[0] = 0;
|
||||
response[1] = 0;
|
||||
usb_control_dataIn(response, 2);
|
||||
break;
|
||||
case STATUS_ENDPOINT:
|
||||
response[0] = 0; /* TODO: return if endpoint is stalled */
|
||||
response[1] = 0;
|
||||
usb_control_dataIn(response, 2);
|
||||
break;
|
||||
default:
|
||||
usb_ep_stall(USB_EP0OUT);
|
||||
usb_ep_stall(USB_EP0IN);
|
||||
handled = false;
|
||||
}
|
||||
break;
|
||||
case SRQ_CLEAR_FEATURE:
|
||||
switch(psetupdata->bmRequestType)
|
||||
{
|
||||
case FEATURE_DEVICE:
|
||||
if(psetupdata->wValue == 1)
|
||||
usb_dev_Rwuen = 0; /* Disable Remote Wakeup */
|
||||
else
|
||||
{
|
||||
usb_ep_stall(USB_EP0OUT);
|
||||
usb_ep_stall(USB_EP0IN);
|
||||
}
|
||||
usb_control_acknowledge();
|
||||
break;
|
||||
case FEATURE_ENDPOINT:
|
||||
if ( (psetupdata->wValue & 0x0f) == 0 )
|
||||
{
|
||||
usb_ep_unstall(USB_EP0OUT);
|
||||
usb_ep_unstall(USB_EP0IN);
|
||||
}
|
||||
else
|
||||
{
|
||||
usb_ep_unstall(USB_EP1OUT);
|
||||
usb_ep_unstall(USB_EP1IN);
|
||||
}
|
||||
usb_control_acknowledge();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SRQ_SET_FEATURE:
|
||||
switch(psetupdata->bmRequestType)
|
||||
{
|
||||
case FEATURE_DEVICE:
|
||||
if (psetupdata->wValue == 1)
|
||||
usb_dev_Rwuen = 1; /* enable remote wakeup */
|
||||
else
|
||||
{
|
||||
usb_ep_stall(USB_EP0OUT);
|
||||
usb_ep_stall(USB_EP0IN);
|
||||
}
|
||||
break;
|
||||
case FEATURE_ENDPOINT:
|
||||
if ( (psetupdata->wValue & 0x0f) == 0 )
|
||||
{
|
||||
usb_ep_stall(USB_EP0OUT);
|
||||
usb_ep_stall(USB_EP0IN);
|
||||
}
|
||||
else
|
||||
{
|
||||
usb_ep_stall(USB_EP1OUT);
|
||||
usb_ep_stall(USB_EP1IN);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
usb_ep_stall(USB_EP0OUT);
|
||||
usb_ep_stall(USB_EP0IN);
|
||||
handled = false;
|
||||
}
|
||||
|
||||
|
||||
return handled;
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Lemcusb - Firmware USB driver for EFM32 Microcontroller
|
||||
** Copyright (C) 2014 http://lemcu.org
|
||||
**
|
||||
** This library is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License version 3.0 as
|
||||
** published by the Free Software Foundation and appearing in the file
|
||||
** LICENSE.txt included in the packaging of this file.
|
||||
**
|
||||
** In addition, as a special exception, http://lemcu.org gives you certain
|
||||
** additional rights. These rights are described in the lemcu.org GPL
|
||||
** Exception version 1.0, included in the file GPL_EXCEPTION.txt in this
|
||||
** package.
|
||||
**
|
||||
** This library is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __USB_STACK_H__
|
||||
#define __USB_STACK_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "usb.h"
|
||||
|
||||
|
||||
/* These defines can be used to mask out the bmRequestType bits */
|
||||
#define USB_SETUP_BM_DIRECTION (0x80)
|
||||
#define USB_SETUP_BM_TYPE (0x60)
|
||||
#define USB_SETUP_BM_RECIPIENT (0x1f)
|
||||
|
||||
#define USB_SETUP_DIR_DEV_TO_HOST (0x80)
|
||||
|
||||
#define USB_SETUP_TYPE_STANDARD (0 << 5)
|
||||
#define USB_SETUP_TYPE_CLASS (1 << 5)
|
||||
#define USB_SETUP_TYPE_VENDOR (2 << 5)
|
||||
|
||||
#define USB_SETUP_DEVICE (0x00)
|
||||
#define USB_SETUP_INTERFACE (0x01)
|
||||
#define USB_SETUP_ENDPOINT (0x02)
|
||||
#define USB_SETUP_OTHER (0x03)
|
||||
|
||||
void usbstack_init(void);
|
||||
|
||||
|
||||
/* call this function when setup data was received
|
||||
TODO: allow user to call this also, when no setup data was received.
|
||||
I think the best way is to let the user only call functions from this file and not from usb.h */
|
||||
bool usbstack_got_setup_cmd(const setupData_t *psetupdata);
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
/*****************************************************************************!
|
||||
* 技术讨论:QQ群 123763203
|
||||
* 官网 :www.navota.com
|
||||
*
|
||||
* @file pmc.c
|
||||
* @brief 电源管理模块(PMC)函数库
|
||||
* @author Navota
|
||||
* @date 2018-3-1
|
||||
*****************************************************************************/
|
||||
|
||||
#include "common.h"
|
||||
#include "pmc.h"
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief PMC模块初始化函数
|
||||
*
|
||||
* @param[in] pPMC_Config PMC 配置结构体.
|
||||
* @param[in] pPMC PMC
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void PMC_Init(PMC_Type *pPMC, PMC_ConfigType *pPMC_Config)
|
||||
{
|
||||
pPMC->SPMSC1 = pPMC_Config->sCtrlstatus.byte;
|
||||
pPMC->SPMSC2 = pPMC_Config->sDetectVoltSelect.byte;
|
||||
if(pPMC_Config->sCtrlstatus.bits.bLvwIrqEn)
|
||||
NVIC_EnableIRQ(LVD_LVW_IRQn);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 复位PMC模块.
|
||||
*
|
||||
* @param[in] pPMC PMC
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void PMC_DeInit(PMC_Type *pPMC)
|
||||
{
|
||||
pPMC->SPMSC1 = 0x1C;
|
||||
pPMC->SPMSC2 = 0;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief MCU工作模式选择函数
|
||||
*
|
||||
* @param[in] u8PmcMode 选择MCU工作模式.
|
||||
* @param[in] pPMC PMC
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void PMC_SetMode(PMC_Type *pPMC,uint8_t u8PmcMode)
|
||||
{
|
||||
switch(u8PmcMode & 0x3)
|
||||
{
|
||||
case PmcModeRun:
|
||||
break;
|
||||
case PmcModeWait: //等待模式
|
||||
wait();
|
||||
break;
|
||||
case PmcModeStop4:
|
||||
/* 停止模式下,使能低压检测*/
|
||||
pPMC->SPMSC1 |= (PMC_SPMSC1_LVDE_MASK | PMC_SPMSC1_LVDSE_MASK);
|
||||
stop();
|
||||
break;
|
||||
case PmcModeStop3:
|
||||
/* 在停止模式下,禁用低压检测*/
|
||||
pPMC->SPMSC1 &= ~(PMC_SPMSC1_LVDE_MASK | PMC_SPMSC1_LVDRE_MASK | PMC_SPMSC1_LVDSE_MASK);
|
||||
stop();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,298 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief PMC 驱动头文件.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef PMC_H_
|
||||
#define PMC_H_
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
/******************************************************************************
|
||||
* PCM系统(MCU工作模式)模式定义
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define PmcModeRun 0 /*!< 运行模式 */
|
||||
#define PmcModeWait 1 /*!< 等到模式 */
|
||||
#define PmcModeStop4 2 /*!< 停止模式4 */
|
||||
#define PmcModeStop3 3 /*!< 停止模式3 */
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* PMC 低压检测和低压报警电压定义
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define PmcLVDTrip_Low 0 /*!< LVD 低电平调变点 */
|
||||
#define PmcLVDTrip_High 1 /*!< LVD 高电平调变点 */
|
||||
|
||||
#define PmcLVWTrip_Low 0 /*!< LVW 低电平跳变点 */
|
||||
#define PmcLVWTrip_Mid1 1 /*!< LVW 中间电平1跳变点 */
|
||||
#define PmcLVWTrip_Mid2 2 /*!< LVW 中间电平2跳变点*/
|
||||
#define PmcLVWTrip_High 3 /*!< LVW 高电平跳变点*/
|
||||
|
||||
/******************************************************************************
|
||||
* PMC 控制结构体
|
||||
*******************************************************************************/
|
||||
/*!
|
||||
* @brief PMC控制结构体类型
|
||||
*
|
||||
*/
|
||||
|
||||
typedef union
|
||||
{
|
||||
uint8_t byte; /*!< 联合体的类型-字节*/
|
||||
struct
|
||||
{
|
||||
uint8_t bBandgapEn :1; /*!< 使能带隙缓冲区 */
|
||||
uint8_t bBandgapDrv :1; /*!< 选择带隙驱动*/
|
||||
uint8_t bLvdEn :1; /*!< 使能低压检测*/
|
||||
uint8_t bLvdStopEn :1; /*!< 低压检测在停止模式下使能*/
|
||||
uint8_t bLvdRstEn :1; /*!< 使能低压检测复位 */
|
||||
uint8_t bLvwIrqEn :1; /*!< 使能低压报警中断 */
|
||||
uint8_t bLvwAck :1; /*!< 低压报警应答 */
|
||||
uint8_t bLvwFlag :1; /*!< 低压报警标志 */
|
||||
}bits; /*!< 联合体类型-位 */
|
||||
}PMC_Ctrl1Type, *PMC_Ctrl1Ptr; /*!< PMC 控制寄存器1结构体 */
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* PMC 控制-- 低压选择.
|
||||
*******************************************************************************/
|
||||
/*!
|
||||
* @brief PMC 控制-- 电压类型选择.
|
||||
*
|
||||
*/
|
||||
typedef union
|
||||
{
|
||||
uint8_t byte; /*!< 联合体类型-字节 */
|
||||
struct
|
||||
{
|
||||
uint8_t :4; /*!< none */
|
||||
uint8_t bLVWV :2; /*!< 低压报警电压选择 */
|
||||
uint8_t bLVDV :1; /*!< 低压复位电压选择 */
|
||||
uint8_t :1; /*!< none */
|
||||
}bits; /*!< 结构体类型——位 */
|
||||
}PMC_Ctrl2Type, *PMC_Ctrl2Ptr; /*!< PMC 控制寄存器2结构体*/
|
||||
|
||||
/******************************************************************************
|
||||
* PMC 配置结构体
|
||||
*******************************************************************************/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PMC_Ctrl1Type sCtrlstatus; /*!< PMC 控制和状态 */
|
||||
PMC_Ctrl2Type sDetectVoltSelect; /*!< 低压报警电压和低压复位电压选择*/
|
||||
}PMC_ConfigType, *PMC_ConfigPtr; /*!< PMC 配置结构体 */
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 在停止模式下使能低压检测.
|
||||
*
|
||||
* @param[in] pPMC 指向PMC模块
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see PMC_DisableLVDInStopMode.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void PMC_EnableLVDInStopMode(PMC_Type *pPMC)
|
||||
{
|
||||
pPMC->SPMSC1 |= PMC_SPMSC1_LVDSE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 在停止模式下禁用低压检测
|
||||
*
|
||||
* @param[in] pPMC 指向PMC模块
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see PMC_EnableLVDInStopMode.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void PMC_DisableLVDInStopMode(PMC_Type *pPMC)
|
||||
{
|
||||
pPMC->SPMSC1 &= ~PMC_SPMSC1_LVDSE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能低压检测复位 注: 复位后该字段仅可写一次
|
||||
*
|
||||
* @param[in] pPMC 指向PMC模块.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see PMC_DisableLVDRst.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void PMC_EnableLVDRst(PMC_Type *pPMC)
|
||||
{
|
||||
pPMC->SPMSC1 |= PMC_SPMSC1_LVDRE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用低压检测复位 注: 复位后该字段仅可写一次
|
||||
*
|
||||
* @param[in] pPMC 指向PMC模块
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see PMC_EnableLVDRst.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void PMC_DisableLVDRst(PMC_Type *pPMC)
|
||||
{
|
||||
pPMC->SPMSC1 &= ~PMC_SPMSC1_LVDRE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能低压检测, 注: 复位后该字段仅可写一次
|
||||
*
|
||||
* @param[in] pPMC 指向PMC模块
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see PMC_DisableLVD.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void PMC_EnableLVD(PMC_Type *pPMC)
|
||||
{
|
||||
pPMC->SPMSC1 |= PMC_SPMSC1_LVDE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用低压检测, 注: 复位后该字段仅可写一次
|
||||
*
|
||||
* @param[in] pPMC 指向PMC模块
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see PMC_EnableLVD.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void PMC_DisableLVD(PMC_Type *pPMC)
|
||||
{
|
||||
pPMC->SPMSC1 &= ~PMC_SPMSC1_LVDE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置低压检测跳变点,
|
||||
*
|
||||
* @param[in] pPMC 指向PMC模块
|
||||
* @param[in] Trippoint 电压检测跳变点选择,1-高电平跳变 0-低电平跳变
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see PMC_SetLVWTripVolt.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void PMC_SetLVDTripVolt(PMC_Type *pPMC, uint8_t Trippoint)
|
||||
{
|
||||
if(Trippoint)
|
||||
pPMC->SPMSC2 |= PMC_SPMSC2_LVDV_MASK;
|
||||
else
|
||||
pPMC->SPMSC2 &= ~PMC_SPMSC2_LVDV_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 选择电压报警跳变点电压
|
||||
*
|
||||
* @param[in] pPMC 指向PMC模块
|
||||
* @param[in] Trippoint 低压报警跳变点电压 0 低电平跳变 1 中间电平1跳变
|
||||
* 2 中间电平2跳变 3 高电平跳变
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see PMC_SetLVDTripVolt.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void PMC_SetLVWTripVolt(PMC_Type *pPMC, uint8_t Trippoint)
|
||||
{
|
||||
pPMC->SPMSC2 &= ~PMC_SPMSC2_LVWV_MASK;
|
||||
pPMC->SPMSC2 |= PMC_SPMSC2_LVWV(Trippoint);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能低压报警中断
|
||||
*
|
||||
* @param[in] pPMC 指向PMC模块
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see PMC_DisableLVWInterrupt.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void PMC_EnableLVWInterrupt(PMC_Type *pPMC)
|
||||
{
|
||||
pPMC->SPMSC1 |= PMC_SPMSC1_LVWIE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用低压报警中断
|
||||
*
|
||||
* @param[in] pPMC 指向PMC模块.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*
|
||||
* @see PMC_EnableLVWInterrupt.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void PMC_DisableLVWInterrupt(PMC_Type *pPMC)
|
||||
{
|
||||
pPMC->SPMSC1 &= ~PMC_SPMSC1_LVWIE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 读取低压报警标志位.
|
||||
*
|
||||
* @param[in] pPMC 指向PMC模块.
|
||||
*
|
||||
* @return 低压报警标志位值
|
||||
*
|
||||
* @see PMC_ClrLVWFlag.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t PMC_GetLVWFlag(PMC_Type *pPMC)
|
||||
{
|
||||
return (pPMC->SPMSC1 & PMC_SPMSC1_LVWF_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 清除低压报警标志位
|
||||
*
|
||||
* @param[in] pPMC 指向PMC模块.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see PMC_GetLVWFlag.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void PMC_ClrLVWFlag(PMC_Type *pPMC)
|
||||
{
|
||||
pPMC->SPMSC1 |= PMC_SPMSC1_LVWACK_MASK;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
void PMC_Init(PMC_Type *pPMC, PMC_ConfigType *pPMC_Config);
|
||||
void PMC_DeInit(PMC_Type *pPMC);
|
||||
void PMC_SetMode(PMC_Type *pPMC,uint8_t u8PmcMode);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,169 @@
|
||||
/**************************************************************************!
|
||||
* 技术讨论:QQ群 123763203
|
||||
* 官网 :www.navota.com
|
||||
*
|
||||
* @file acmp.c
|
||||
* @brief 模拟比较器(ACMP)函数库
|
||||
* @author Navota
|
||||
* @date 2018-3-1
|
||||
****************************************************************************/
|
||||
|
||||
#include "common.h"
|
||||
#include "acmp.h"
|
||||
|
||||
/****************************************************************************!
|
||||
* @ 存放ACMP回调函数接口
|
||||
****************************************************************************/
|
||||
ACMP_CallbackPtr ACMP_Callback[2] = {(ACMP_CallbackPtr)NULL};
|
||||
|
||||
/**************************************************************************/
|
||||
void ACMP0_Isr(void);
|
||||
void ACMP1_Isr(void);
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 初始化ACMP模块
|
||||
*
|
||||
* @param pACMPx 指向ACMP寄存器基址
|
||||
* @param pConfig 控制参数
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see ACMP_DeInit.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ACMP_Init(ACMP_Type *pACMPx, ACMP_ConfigType *pConfig)
|
||||
{
|
||||
if(ACMP0 == pACMPx)
|
||||
{
|
||||
/* 使能ACMP模块的总线时钟 */
|
||||
SIM->SCGC |= SIM_SCGC_ACMP0_MASK;
|
||||
|
||||
/* 使能ACMP中断 */
|
||||
if(pConfig->sCtrlStatus.bits.bIntEn)
|
||||
NVIC_EnableIRQ(ACMP0_IRQn);
|
||||
}
|
||||
else
|
||||
{
|
||||
SIM->SCGC |= SIM_SCGC_ACMP1_MASK;
|
||||
if(pConfig->sCtrlStatus.bits.bIntEn)
|
||||
NVIC_EnableIRQ(ACMP1_IRQn);
|
||||
}
|
||||
/*选择ACMP正输入和负输入,正输入和负输入引脚不同*/
|
||||
pACMPx->C0 = pConfig->sPinSelect.byte;
|
||||
ACMP_ConfigDAC(pACMPx, &pConfig->sDacSet );
|
||||
//pACMPx->C1 = pConfig->sDacSet.byte;
|
||||
pACMPx->C2 = pConfig->sPinEnable.byte;
|
||||
pACMPx->CS = pConfig->sCtrlStatus.byte;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 配置ACMP控制寄存器1.
|
||||
*
|
||||
* @param pACMPx 指向ACMP模块寄存器基地址
|
||||
* @param pDACConfig 指向 ACMP DAC 控制结构体.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ACMP_ConfigDAC(ACMP_Type *pACMPx, ACMP_DACType *pDACConfig)
|
||||
{
|
||||
pACMPx->C1 = pDACConfig->byte;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 复位ACMP模块.
|
||||
*
|
||||
* @param pACMPx 指向ACMP模块寄存器基地址
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see ACMP_Init.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ACMP_DeInit(ACMP_Type *pACMPx)
|
||||
{
|
||||
if(ACMP0 == pACMPx)
|
||||
{
|
||||
if(pACMPx->CS & ACMP_CS_ACIE_MASK)
|
||||
NVIC_DisableIRQ(ACMP0_IRQn);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(pACMPx->CS & ACMP_CS_ACIE_MASK)
|
||||
NVIC_DisableIRQ(ACMP1_IRQn);
|
||||
}
|
||||
|
||||
pACMPx->CS = 0;
|
||||
pACMPx->C0 = 0;
|
||||
pACMPx->C1 = 0;
|
||||
pACMPx->C2 = 0;
|
||||
|
||||
if(ACMP0 == pACMPx)
|
||||
{
|
||||
SIM->SCGC &= ~SIM_SCGC_ACMP0_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
SIM->SCGC &= ~SIM_SCGC_ACMP1_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置ACMP回调函数,通过中断服务函数调用回调函数.
|
||||
*
|
||||
* @param pACMPx 指向ACMP模块寄存器基地址.
|
||||
* @param pfnCallback 回调函数.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ACMP_SetCallback(ACMP_Type *pACMPx, ACMP_CallbackPtr pfnCallback)
|
||||
{
|
||||
if(ACMP0 == pACMPx)
|
||||
{
|
||||
ACMP_Callback[0] = pfnCallback;
|
||||
}
|
||||
else
|
||||
{
|
||||
ACMP_Callback[1] = pfnCallback;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief ACMP0 中断服务函数.
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ACMP0_Isr(void)
|
||||
{
|
||||
if(ACMP_Callback[0])
|
||||
{
|
||||
ACMP_Callback[0](); /*调用回调函数*/
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief ACMP1 中断服务函数
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ACMP1_Isr(void)
|
||||
{
|
||||
if(ACMP_Callback[1])
|
||||
{
|
||||
ACMP_Callback[1](); /* 调用回调函数*/
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,455 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief ACMP 驱动头文件.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef _MY_ACMP_H_
|
||||
#define _MY_ACMP_H_
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
/* 选择DAC基准 */
|
||||
enum
|
||||
{
|
||||
DAC_REF_BANDGAP = 0,
|
||||
DAC_REF_VDDA
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* ACMP 模块数定义
|
||||
******************************************************************************/
|
||||
#define MAX_ACMP_NO 2
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* 定义ACMP 正输入和负输入引脚
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define ACMP_INPUT_P_EXT0 (0<<4) /*!< ACMP正输入选择外部基准0 */
|
||||
#define ACMP_INPUT_P_EXT1 (1<<4) /*!< ACMP正输入选择外部基准1 */
|
||||
#define ACMP_INPUT_P_EXT2 (2<<4) /*!< ACMP正输入选择外部基准2 */
|
||||
#define ACMP_INPUT_P_DAC (3<<4) /*!< ACMP正输入选择DAC输出 */
|
||||
#define ACMP_INPUT_N_EXT0 0 /*!< ACMP负输入选择外部基准0 */
|
||||
#define ACMP_INPUT_N_EXT1 1 /*!< ACMP负输入选择外部基准1 */
|
||||
#define ACMP_INPUT_N_EXT2 2 /*!< ACMP负输入选择外部基准2 */
|
||||
#define ACMP_INPUT_N_DAC 3 /*!< ACMP负输入选择DAC输出 */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义ACMP中断触发器的触发模式
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define ACMP_SENSITIVITYMODE_FALLING 0 /*!< ACMP中断在输出下降沿发生 */
|
||||
#define ACMP_SENSITIVITYMODE_RISING 1 /*!< ACMP中断在输出上升沿发生 */
|
||||
#define ACMP_SENSITIVITYMODE_ANY 3 /*!< ACMP中断在输出上升沿或下降沿触发 */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义ACMP 迟滞
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define ACMP_HYST_20MV (0<<6) /*!< 20mv */
|
||||
#define ACMP_HYST_30MV (1<<6) /*!< 30mv */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义内部DAC参考基准
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define ACMP_DAC_REFERENCE_BANDGAP (0<<6) /*!< 选择带隙为基准 */
|
||||
#define ACMP_DAC_REFERENCE_VDDA (1<<6) /*!< 选择VDDA为基准 */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* ACMP回调函数声明
|
||||
*
|
||||
******************************************************************************/
|
||||
typedef void (*ACMP_CallbackPtr)(void);
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* ACMP 控制和状态字寄存器结构体
|
||||
*
|
||||
*******************************************************************************/
|
||||
typedef union
|
||||
{
|
||||
uint8_t byte; /*!<联合体类型-字节*/
|
||||
struct
|
||||
{
|
||||
uint8_t bMod : 2; /*!< 中断触发模式 */
|
||||
uint8_t bOutEn : 1; /*!< ACMP输出置于外部引脚 */
|
||||
uint8_t bOutState : 1; /*!< 模拟比较强输出的当前值 */
|
||||
uint8_t bIntEn : 1; /*!< 使能ACMP中断 */
|
||||
uint8_t bIntFlag : 1; /*!< ACMP 中断标志位 */
|
||||
uint8_t bHyst : 1; /*!< 选择ACMP迟滞 */
|
||||
uint8_t bEn : 1; /*!< 使能ACMP模块 */
|
||||
}bits; /*!< 联合体类型-位域 */
|
||||
}ACMP_CtrlStatusType, *ACMP_CtrlStatusPtr; /*!< ACMP 控制和状态寄存器结构*/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* ACMP 外部输入引脚控制结构体
|
||||
*
|
||||
*******************************************************************************/
|
||||
typedef union
|
||||
{
|
||||
uint8_t byte; /*!<联合体类型-字节*/
|
||||
struct
|
||||
{
|
||||
uint8_t bNegPin : 2; /*!< 负输入选择*/
|
||||
uint8_t : 2;
|
||||
uint8_t bPosPin : 2; /*!< 正输入选择 */
|
||||
uint8_t : 2;
|
||||
}bits; /*!< 联合体类型-位域 */
|
||||
}ACMP_PinSelType, *ACMP_PinSelPtr; /*!< ACMP 输入选择结构体 */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* ACMP 内部DAC控制结构体
|
||||
*
|
||||
*******************************************************************************/
|
||||
typedef union
|
||||
{
|
||||
uint8_t byte; /*!<联合体类型-字节*/
|
||||
struct
|
||||
{
|
||||
uint8_t bVal : 6; /*!< DAC输出电平选择*/
|
||||
uint8_t bRef : 1; /*!< DAC基准选择 */
|
||||
uint8_t bEn : 1; /*!< DAC使能 */
|
||||
}bits; /*!< 联合体类型-位域 */
|
||||
}ACMP_DACType, *ACMP_DACPtr; /*!< ACMP DAC 控制结构体 */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* ACMP 外部输入引脚使能控制结构体
|
||||
*
|
||||
*******************************************************************************/
|
||||
typedef union
|
||||
{
|
||||
uint8_t byte; /*!<联合体类型-字节*/
|
||||
struct
|
||||
{
|
||||
uint8_t bEn : 3; /*!< ACMP 外部输入引脚使能 */
|
||||
uint8_t bRsvd : 5;
|
||||
}bits; /*!< 联合体类型-位域 */
|
||||
}ACMP_PinEnType, *ACMP_PinEnPtr; /*!< ACMP 引脚使能结构体 */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* ACMP 模块配置结构体
|
||||
*
|
||||
*******************************************************************************/
|
||||
typedef struct
|
||||
{
|
||||
ACMP_CtrlStatusType sCtrlStatus; /*!< ACMP 控制和状体 */
|
||||
ACMP_PinSelType sPinSelect; /*!< ACMP 输入选择 */
|
||||
ACMP_DACType sDacSet; /*!< ACMP 内部DAC控制 */
|
||||
ACMP_PinEnType sPinEnable; /*!< ACMP 外部输入引脚使能控制 */
|
||||
}ACMP_ConfigType, *ACMP_ConfigPtr;
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能ACMP模块
|
||||
*
|
||||
* @param[in] pACMPx 指向ACMP模块
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see ACMP_Disable.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ACMP_Enable(ACMP_Type *pACMPx)
|
||||
{
|
||||
pACMPx->CS |= ACMP_CS_ACE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用ACMP模块
|
||||
*
|
||||
* @param[in] pACMPx 指向ACMP模块
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see ACMP_Enable.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ACMP_Disable(ACMP_Type *pACMPx)
|
||||
{
|
||||
pACMPx->CS &= ~ACMP_CS_ACE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 选择ACMP中断触发器的触发模式.
|
||||
*
|
||||
* @param[in] pACMPx 指向ACMP模块
|
||||
* @param[in] u8EdgeSelect 上升沿或下降沿选择, 0~3.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ACMP_SelectIntMode(ACMP_Type *pACMPx, uint8_t u8EdgeSelect)
|
||||
{
|
||||
pACMPx->CS &= ~ACMP_CS_ACMOD_MASK;
|
||||
pACMPx->CS |= ACMP_CS_ACMOD(u8EdgeSelect & 0x3);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能ACMP输出置于外部引脚上
|
||||
*
|
||||
* @param[in] pACMPx 指向ACMP模块
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see ACMP_DisablePinOut.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ACMP_EnablePinOut(ACMP_Type *pACMPx)
|
||||
{
|
||||
pACMPx->CS |= ACMP_CS_ACOPE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用ACMP输出置于外部引脚上
|
||||
*
|
||||
* @param[in] pACMPx 指向ACMP模块
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see ACMP_EnablePinOut.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ACMP_DisablePinOut(ACMP_Type *pACMPx)
|
||||
{
|
||||
pACMPx->CS &= ~ACMP_CS_ACOPE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 选择ACMP迟滞
|
||||
*
|
||||
* @param[in] pACMPx 指向ACMP模块.
|
||||
* @param[in] u8HystSelect 2mv or 30mv.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ACMP_SelectHyst(ACMP_Type *pACMPx, uint8_t u8HystSelect)
|
||||
{
|
||||
pACMPx->CS &= ~ACMP_CS_HYST_MASK;
|
||||
pACMPx->CS |= u8HystSelect;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能ACMP模块中断
|
||||
*
|
||||
* @param[in] pACMPx 指向ACMP模块.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*
|
||||
* @see ACMP_DisableInterrupt.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ACMP_EnableInterrupt(ACMP_Type *pACMPx)
|
||||
{
|
||||
pACMPx->CS |= ACMP_CS_ACIE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用ACMP模块中断
|
||||
*
|
||||
* @param[in] pACMPx 指向ACMP模块
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see ACMP_EnableInterrupt.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ACMP_DisableInterrupt(ACMP_Type *pACMPx)
|
||||
{
|
||||
pACMPx->CS &= ~ACMP_CS_ACIE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 读取中断标志位
|
||||
*
|
||||
* @param[in] pACMPx 指向ACMP模块.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see ACMP_ClrFlag.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t ACMP_GetFlag(ACMP_Type *pACMPx)
|
||||
{
|
||||
return (pACMPx->CS & ACMP_CS_ACF_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 清除中断标志位
|
||||
*
|
||||
* @param[in] pACMPx 指向ACMP模块
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see ACMP_GetFlag.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ACMP_ClrFlag(ACMP_Type *pACMPx)
|
||||
{
|
||||
pACMPx->CS &= ~ACMP_CS_ACF_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief ACMP正输入选择
|
||||
*
|
||||
* @param[in] pACMPx 指向ACMP模块
|
||||
* @param[in] u8PosPinSel 正输入选择, 外部基准0~2 或DAC输出.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see ACMP_NegativeInputSelect.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ACMP_PositiveInputSelect(ACMP_Type *pACMPx, uint8_t u8PosPinSel)
|
||||
{
|
||||
pACMPx->C0 &= ~ACMP_C0_ACPSEL_MASK;
|
||||
pACMPx->C0 |= u8PosPinSel;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief ACMP负输入选择.
|
||||
*
|
||||
* @param[in] pACMPx 指向ACMP模块
|
||||
* @param[in] u8NegPinSel 负输入选择, 外部基准0~2 或DAC输出.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see ACMP_PositiveInputSelect.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ACMP_NegativeInputSelect(ACMP_Type *pACMPx, uint8_t u8NegPinSel)
|
||||
{
|
||||
pACMPx->C0 &= ~ACMP_C0_ACNSEL_MASK;
|
||||
pACMPx->C0 |= u8NegPinSel;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能内部DAC
|
||||
*
|
||||
* @param[in] pACMPx 指向ACMP模块
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see ACMP_DacDisable.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ACMP_DacEnable(ACMP_Type *pACMPx)
|
||||
{
|
||||
pACMPx->C1 |= ACMP_C1_DACEN_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用内部DAC
|
||||
*
|
||||
* @param[in] pACMPx 指向ACMP模块.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see ACMP_DacEnable.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ACMP_DacDisable(ACMP_Type *pACMPx)
|
||||
{
|
||||
pACMPx->C1 &= ~ACMP_C1_DACEN_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief DAC基准选择
|
||||
*
|
||||
* @param[in] pACMPx 指向ACMP模块.
|
||||
* @param[in] u8RefSelect DAC参考选择: 带隙 or VDDA.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ACMP_DacReferenceSelect(ACMP_Type *pACMPx, uint8_t u8RefSelect)
|
||||
{
|
||||
pACMPx->C1 &= ~ACMP_C1_DACREF_MASK;
|
||||
pACMPx->C1 |= u8RefSelect;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief DAC输出电平选择
|
||||
*
|
||||
* @param[in] pACMPx 指向ACMP模块.
|
||||
* @param[in] u8DacValue DAC输出选择, Voutput= (Vin/64)x(DACVAL[5:0]+1).
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ACMP_DacOutputSet(ACMP_Type *pACMPx, uint8_t u8DacValue)
|
||||
{
|
||||
ASSERT(!(u8DacValue & (~ACMP_C1_DACVAL_MASK)));
|
||||
pACMPx->C1 &= ~ACMP_C1_DACVAL_MASK;
|
||||
pACMPx->C1 |= ACMP_C1_DACVAL(u8DacValue);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能ACMP外部输入引脚.
|
||||
*
|
||||
* @param[in] pACMPx 指向ACMP模块.
|
||||
* @param[in] u8InputPin ACMP 外部输入引脚, 0~2.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ACMP_InputPinEnable(ACMP_Type *pACMPx, uint8_t u8InputPin)
|
||||
{
|
||||
ASSERT(!(u8InputPin & (~ACMP_C2_ACIPE_MASK)));
|
||||
pACMPx->C2 |= ACMP_C2_ACIPE(u8InputPin);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用ACMP外部输入引脚.
|
||||
*
|
||||
* @param[in] pACMPx 指向ACMP模块.
|
||||
* @param[in] u8InputPin ACMP 外部输入引脚, 0~2.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ACMP_InputPinDisable(ACMP_Type *pACMPx, uint8_t u8InputPin)
|
||||
{
|
||||
ASSERT(!(u8InputPin & (~ACMP_C2_ACIPE_MASK)));
|
||||
pACMPx->C2 &= ~ACMP_C2_ACIPE(u8InputPin);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
void ACMP_Init(ACMP_Type *pACMPx, ACMP_ConfigType *pConfig);
|
||||
void ACMP_DeInit(ACMP_Type *pACMPx);
|
||||
void ACMP_ConfigDAC(ACMP_Type *pACMPx, ACMP_DACType *pDACConfig);
|
||||
void ACMP_SetCallback(ACMP_Type *pACMPx, ACMP_CallbackPtr pfnCallback);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,256 @@
|
||||
/**************************************************************************!
|
||||
* 技术讨论:QQ群 123763203
|
||||
* 官网 :www.navota.com
|
||||
*
|
||||
* @file adc.c
|
||||
* @brief 数模转换模块(ADC)库函数��
|
||||
* @author Navota
|
||||
* @date 2018-3-1
|
||||
****************************************************************************/
|
||||
|
||||
#include "common.h"
|
||||
#include "adc.h"
|
||||
|
||||
/****************************************************************************!
|
||||
* @ 存放ACMP回调函数接口
|
||||
****************************************************************************/
|
||||
ADC_CallbackType ADC_Callback[1] = {NULL};
|
||||
|
||||
/*****************************************************************************//**
|
||||
*
|
||||
* @brief 初始化ADC模块.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块类型.
|
||||
* @param[in] pADC_Config 指向ADC模块配置结构体
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ADC_Init(ADC_Type *pADC, ADC_ConfigTypePtr pADC_Config)
|
||||
{
|
||||
if( pADC == ADC)
|
||||
{
|
||||
SIM->SCGC |= SIM_SCGC_ADC_MASK;
|
||||
}
|
||||
/* 选择ADC模块时钟源 */
|
||||
ADC_SelectClock(pADC,pADC_Config->u8ClockSource);
|
||||
/* 设定时钟分频 */
|
||||
ADC_SelectClockDivide(pADC,pADC_Config->u8ClockDiv);
|
||||
/* 设置ADC转换模式 */
|
||||
ADC_SetMode(pADC,pADC_Config->u8Mode);
|
||||
/* 设置FIFO深度 */
|
||||
ADC_SetFifoLevel(pADC,pADC_Config->u8FiFoLevel);
|
||||
/* ADC输入引脚控制 */
|
||||
pADC->APCTL1 = pADC_Config->u16PinControl;
|
||||
if( pADC_Config->sSetting.bCompareEn )
|
||||
{
|
||||
ADC_CompareEnable(pADC); //使能ADC比较功能
|
||||
}
|
||||
if( pADC_Config->sSetting.bCompareGreaterEn )
|
||||
{
|
||||
ADC_CompareGreaterFunction(pADC); //输入大于或等于比较电平时比较触发
|
||||
}
|
||||
if( pADC_Config->sSetting.bContinuousEn )
|
||||
{
|
||||
ADC_ContinuousConversion(pADC); // 使能ADC连续转换.
|
||||
}
|
||||
if( pADC_Config->sSetting.bCompareAndEn )
|
||||
{
|
||||
ADC_CompareFifoAnd(pADC); //对所有比较触发做与运算
|
||||
}
|
||||
if( pADC_Config->sSetting.bFiFoScanModeEn )
|
||||
{
|
||||
ADC_FifoScanModeEnable(pADC); //使能FIFO扫描模式
|
||||
}
|
||||
if( pADC_Config->sSetting.bHardwareTriggerEn )
|
||||
{
|
||||
ADC_SetHardwareTrigger(pADC); // 设置ADC硬件触发.
|
||||
}
|
||||
if( pADC_Config->sSetting.bIntEn ) //使能中断
|
||||
{
|
||||
ADC_IntEnable(pADC);
|
||||
NVIC_EnableIRQ( ADC0_IRQn );
|
||||
}
|
||||
if( pADC_Config->sSetting.bLongSampleEn )
|
||||
{
|
||||
ADC_SetLongSample(pADC); // 设置ADC长采样.
|
||||
}
|
||||
if( pADC_Config->sSetting.bLowPowerEn )
|
||||
{
|
||||
ADC_SetLowPower(pADC); // 设置ADC为低功耗模式
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用ADC模块
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块类型
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ADC_DeInit( ADC_Type *pADC )
|
||||
{
|
||||
ADC_SetChannel(pADC,ADC_CHANNEL_DISABLE);
|
||||
SIM->SCGC &= ~SIM_SCGC_ADC_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 开始转换和读取转换结果
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块
|
||||
* @param[in] u8Channel ADC转换通道
|
||||
*
|
||||
* @return ADC 转换结果.
|
||||
*
|
||||
*****************************************************************************/
|
||||
unsigned int ADC_PollRead( ADC_Type *pADC, uint8_t u8Channel )
|
||||
{
|
||||
ADC_SetChannel(pADC,u8Channel);
|
||||
while( !ADC_IsCOCOFlag(pADC) )
|
||||
{
|
||||
;
|
||||
}
|
||||
return ADC_ReadResultReg(pADC);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 注册 ADC 回调函数,通过中断服务函数调用
|
||||
*
|
||||
* @param[in] pADC_CallBack 指向ADC回调函数地址.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ADC_SetCallBack(ADC_CallbackType pADC_CallBack)
|
||||
{
|
||||
ADC_Callback[0] = pADC_CallBack;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 选择ADC输入通道.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
* @param[in] u8Channel ADC转换通道
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ADC_SetChannel( ADC_Type *pADC, uint8_t u8Channel )
|
||||
{
|
||||
uint32_t u32temp;
|
||||
u32temp = pADC->SC1;
|
||||
u32temp &= ~ADC_SC1_ADCH_MASK;
|
||||
pADC->SC1 = u32temp|ADC_SC1_ADCH(u8Channel);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 选择ADC基准电压.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块
|
||||
* @param[in] u8Vref 选择ADC基准电压.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ADC_VrefSelect( ADC_Type *pADC, uint8_t u8Vref )
|
||||
{
|
||||
uint32_t u32Temp;
|
||||
u32Temp = pADC->SC2;
|
||||
u32Temp &= ~ADC_SC2_REFSEL_MASK;
|
||||
pADC->SC2 = u32Temp|ADC_SC2_REFSEL(u8Vref);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置ADC时钟源分频
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
* @param[in] u8Div 选择分频系数.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ADC_SelectClockDivide( ADC_Type *pADC, uint8_t u8Div )
|
||||
{
|
||||
uint32_t u32Temp;
|
||||
u32Temp = pADC->SC3;
|
||||
u32Temp &= ~ADC_SC3_ADIV_MASK;
|
||||
pADC->SC3 = u32Temp|ADC_SC3_ADIV(u8Div);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置ADC转换模式
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块
|
||||
* @param[in] u8Mode 选择ADC转换参数.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ADC_SetMode( ADC_Type *pADC, uint8_t u8Mode )
|
||||
{
|
||||
uint32_t u32Temp;
|
||||
u32Temp = pADC->SC3;
|
||||
u32Temp &= ~ADC_SC3_MODE_MASK;
|
||||
pADC->SC3 = u32Temp|ADC_SC3_MODE(u8Mode);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置ADC输入时钟.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块
|
||||
* @param[in] u8Clock 选择输入时钟源.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ADC_SelectClock( ADC_Type *pADC, uint8_t u8Clock )
|
||||
{
|
||||
uint32_t u32Temp;
|
||||
u32Temp = pADC->SC3;
|
||||
u32Temp &= ~ADC_SC3_ADICLK_MASK;
|
||||
pADC->SC3 = u32Temp|ADC_SC3_ADICLK(u8Clock);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置FIFO深度
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
* @param[in] u8FifoLevel 选择FIFO深度.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ADC_SetFifoLevel( ADC_Type *pADC, uint8_t u8FifoLevel )
|
||||
{
|
||||
uint32_t u32Temp;
|
||||
u32Temp = pADC->SC4;
|
||||
u32Temp &= ~ADC_SC4_AFDEP_MASK;
|
||||
pADC->SC4 = u32Temp|ADC_SC4_AFDEP(u8FifoLevel);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief ADC 中断服务函数.
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ADC_Isr(void)
|
||||
{
|
||||
if( ADC_Callback[0] )
|
||||
{
|
||||
ADC_Callback[0]();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,655 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief ADC 驱动头文件.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef ADC_H_
|
||||
#define ADC_H_
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
/******************************************************************************
|
||||
*
|
||||
*定义ADC参考电压
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define ADC_VREF_VREFH 0x00 /*!< ADC 参考电压 VREFH*/
|
||||
#define ADC_VREF_VDDA 0x01 /*!< ADC 参考电压 VDDA*/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义ADC时钟源
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define CLOCK_SOURCE_BUS_CLOCK 0x00 /*!< ADC时钟源选择总线时钟*/
|
||||
#define CLOCK_SOURCE_BUS_CLOCK_DIVIDE_2 0x01 /*!< ADC时钟源选择总线时钟2分频*/
|
||||
#define CLOCK_SOURCE_ALTCLK 0x02 /*!< ADC时钟源选择备用时钟*/
|
||||
#define CLOCK_SOURCE_ADACK 0x03 /*!< ADC时钟源选择异步时钟*/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义ADC源分频系数
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define ADC_ADIV_DIVIDE_1 0x00 /*!< ADC时钟源分频系数为1*/
|
||||
#define ADC_ADIV_DIVIDE_2 0x01 /*!< ADC时钟源分频系数为2*/
|
||||
#define ADC_ADIV_DIVIDE_4 0x02 /*!< ADC时钟源分频系数为4*/
|
||||
#define ADC_ADIV_DIVIDE_8 0x03 /*!< ADC时钟源分频系数为8*/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义ADC转换模式
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define ADC_MODE_8BIT 0x00 /*!< 8位转换*/
|
||||
#define ADC_MODE_10BIT 0x01 /*!< 10位转换*/
|
||||
#define ADC_MODE_12BIT 0x02 /*!< 12位转换*/
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* 定义ADC输入通道
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define ADC_CHANNEL_AD0 0x0 /*!< ADC输入通道0*/
|
||||
#define ADC_CHANNEL_AD1 0x1 /*!< ADC输入通道1*/
|
||||
#define ADC_CHANNEL_AD2 0x2 /*!< ADC输入通道2*/
|
||||
#define ADC_CHANNEL_AD3 0x3 /*!< ADC输入通道3*/
|
||||
#define ADC_CHANNEL_AD4 0x4 /*!< ADC输入通道4*/
|
||||
#define ADC_CHANNEL_AD5 0x5 /*!< ADC输入通道5*/
|
||||
#define ADC_CHANNEL_AD6 0x6 /*!< ADC输入通道6*/
|
||||
#define ADC_CHANNEL_AD7 0x7 /*!< ADC输入通道7*/
|
||||
#define ADC_CHANNEL_AD8 0x8 /*!< ADC输入通道8*/
|
||||
#define ADC_CHANNEL_AD9 0x9 /*!< ADC输入通道9*/
|
||||
#define ADC_CHANNEL_AD10 0xa /*!< ADC输入通道10*/
|
||||
#define ADC_CHANNEL_AD11 0xb /*!< ADC输入通道11*/
|
||||
#define ADC_CHANNEL_AD12 0xc /*!< ADC输入通道12*/
|
||||
#define ADC_CHANNEL_AD13 0xd /*!< ADC输入通道13*/
|
||||
#define ADC_CHANNEL_AD14 0xe /*!< ADC输入通道14*/
|
||||
#define ADC_CHANNEL_AD15 0xf /*!< ADC输入通道15*/
|
||||
#define ADC_CHANNEL_AD18_VSS 0x12 /*!< ADC输入通道 VSS */
|
||||
#define ADC_CHANNEL_AD22_TEMPSENSOR 0x16 /*!< ADC输入通道温度传感器 */ //Modify
|
||||
#define ADC_CHANNEL_AD23_BANDGAP 0x17 /*!< ADC输入通道带隙 */
|
||||
#define ADC_CHANNEL_AD29_VREFH 0x1D /*!< ADC输入通道 Vrefh */
|
||||
#define ADC_CHANNEL_AD30_VREFL 0x1E /*!< ADC输入通道 Vrefl */
|
||||
#define ADC_CHANNEL_DISABLE 0x1F /*!< ADC输入通道禁用 */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义 ADC FIFO 深度
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define ADC_FIFO_DISABLE 0 /*!< FIFO禁用*/
|
||||
#define ADC_FIFO_LEVEL2 1 /*!< 2级FIFO */
|
||||
#define ADC_FIFO_LEVEL3 2 /*!< 3级FIFO */
|
||||
#define ADC_FIFO_LEVEL4 3 /*!< 4级FIFO */
|
||||
#define ADC_FIFO_LEVEL5 4 /*!< 5级FIFO */
|
||||
#define ADC_FIFO_LEVEL6 5 /*!< 6级FIFO */
|
||||
#define ADC_FIFO_LEVEL7 6 /*!< 7级FIFO */
|
||||
#define ADC_FIFO_LEVEL8 7 /*!< 8级FIFO */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义ADC转换触发源
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define ADC_HARDWARE_TRIGGER 0x01 /*!< 硬件触发 */
|
||||
#define ADC_SOFTWARE_TRIGGER 0x00 /*!< 软件触发 */
|
||||
#define ADC_TRIGGER_RTC 0x00 /*!< 选择RTC溢出作为硬件触发源*/
|
||||
#define ADC_TRIGGER_PIT 0x01 /*!< 选择PIT0溢出作为硬件触发源*/
|
||||
#define ADC_TRIGGER_ETM2INIT 0x10 /*!< 选择ETM2初始化化作为硬件触发源 */
|
||||
#define ADC_TRIGGER_ETM2MATCH 0x11 /*!< 选择ETM2匹配作为硬件触发源 */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义ADC比较触发模式
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define ADC_COMPARE_LESS 0x00 /*!< 输入小于比较电平时比较触发*/
|
||||
#define ADC_COMPARE_GREATER 0x01 /*!< 输入大于比价电平时比较触发*/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* ADC回调函数声明
|
||||
*
|
||||
******************************************************************************/
|
||||
typedef void (*ADC_CallbackType)(void); /*!< ADC回调函数 */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义ADC结构体变量
|
||||
*
|
||||
*******************************************************************************/
|
||||
typedef struct
|
||||
{
|
||||
uint16_t bIntEn :1; /*!< 1: 中断使能, 0: 禁用中断 */
|
||||
uint16_t bContinuousEn :1; /*!< 1: 使能连续转换模式, 0: 禁用连续转换模式 */
|
||||
uint16_t bHardwareTriggerEn :1; /*!< 1: 硬件触发, 0: 软件触发 */
|
||||
uint16_t bCompareEn :1; /*!< 1: 使能比较模式, 0: 禁用比较模式 */
|
||||
uint16_t bCompareGreaterEn :1; /*!< 1: 输入大于或等于比较电平时比较触发, 0: 输入小于比较电平时比较触发 */
|
||||
uint16_t bLowPowerEn :1; /*!< 1: 低功耗模式, 0: 高速模式 */
|
||||
uint16_t bLongSampleEn :1; /*!< 1: 长采样模式, 0: 短采样模式 */
|
||||
uint16_t bFiFoScanModeEn :1; /*!< 1: 使能FIFO扫描模式, 0: 禁用FIFO扫描模式 */
|
||||
uint16_t bCompareAndEn :1; /*!< 1: 对所有比较触发做与运算, 0: 对所有比较触发做或运算*/
|
||||
#ifdef CPU_NV32
|
||||
uint16_t bReverse :7;
|
||||
#else
|
||||
uint16_t bHTRGMEn :1; /*!< one hardware trigger pulse trigger multiple conversions in fifo mode */
|
||||
uint16_t bHTRGMASKEn :1; /*!< Hardware trigger mask enable. */
|
||||
uint16_t bHTRGMASKSEL :1; /*!< This field selects hardware trigger mask mode. */
|
||||
uint16_t Reserve :4;
|
||||
#endif
|
||||
} ADC_SettingType;
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* ADC配置结构体
|
||||
*
|
||||
*******************************************************************************/
|
||||
typedef struct
|
||||
{
|
||||
ADC_SettingType sSetting; /*!< ADC配置结构体*/
|
||||
uint16_t u16PinControl; /*!< 引脚控制 */
|
||||
uint8_t u8ClockSource; /*!< 选择时钟源 */
|
||||
uint8_t u8ClockDiv; /*!< 设置时钟分频 */
|
||||
uint8_t u8Mode; /*!< 设置转换模式(8/10/12 bit mode) */
|
||||
uint8_t u8FiFoLevel; /*!< 设置FIFO深度 */
|
||||
} ADC_ConfigType,*ADC_ConfigTypePtr;
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能ADC中断.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_IntEnable( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC1 |= ADC_SC1_AIEN_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用ADC中断
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_IntDisable( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC1 &= ~ADC_SC1_AIEN_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能ADC连续转换.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_ContinuousConversion( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC1 |= ADC_SC1_ADCO_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能ADC单次转换
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_SingleConversion( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC1 &= ~ADC_SC1_ADCO_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置ADC硬件触发.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块 .
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_SetHardwareTrigger( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC2 |= ADC_SC2_ADTRG_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置ADC软件触发.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块 .
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_SetSoftwareTrigger( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC2 &= ~ADC_SC2_ADTRG_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能ADC比较功能
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_CompareEnable( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC2 |= ADC_SC2_ACFE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用ADC比较功能.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_CompareDisable( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC2 &= ~ADC_SC2_ACFE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 输入大于或等于比较电平时比较触发
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_CompareGreaterFunction( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC2 |= ADC_SC2_ACFGT_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 输入小于比价电平时比较触发
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_CompareLessFunction( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC2 &= ~ADC_SC2_ACFGT_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置ADC为低功耗模式
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_SetLowPower( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC3 |= ADC_SC3_ADLPC_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置ADC为高速模式.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块..
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_SetHighSpeed( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC3 &= ~ADC_SC3_ADLPC_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置ADC长采样.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_SetLongSample( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC3 |= ADC_SC3_ADLSMP_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置ADC短采样
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_SetShortSample( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC3 &= ~ADC_SC3_ADLSMP_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能FIFO扫描模式
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_FifoScanModeEnable( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC4 |= ADC_SC4_ASCANE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用FIFO扫描模式.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_FifoScanModeDisable( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC4 &= ~ADC_SC4_ASCANE_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 对所有比较触发做或运算.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_CompareFifoOr( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC4 &= ~ADC_SC4_ACFSEL_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 对所有比较触发做与运算
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_CompareFifoAnd( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC4 |= ADC_SC4_ACFSEL_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 对ADC转换结果寄存器.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return ADC result value.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint16_t ADC_ReadResultReg( ADC_Type *pADC )
|
||||
{
|
||||
return (uint16_t)pADC->R;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置比较值.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
* @param[in] u16Compare 比较值
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_SetCompareValue( ADC_Type *pADC, uint16_t u16Compare )
|
||||
{
|
||||
pADC->CV = u16Compare;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能ADC输入引脚.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
* @param[in] u16PinNumber 使能的ADC引脚
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @ Pass/ Fail criteria: none
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_PinControlEnable( ADC_Type *pADC, uint16_t u16PinNumber)
|
||||
{
|
||||
ASSERT((u16PinNumber<16));
|
||||
pADC->APCTL1 &= ~(0x01<<u16PinNumber);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用ADC输入引脚.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
* @param[in] u16PinNumber 禁用的ADC引脚.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_PinControlDisable( ADC_Type *pADC, uint16_t u16PinNumber)
|
||||
{
|
||||
ASSERT((u16PinNumber<16));
|
||||
pADC->APCTL1 |= (0x01<<u16PinNumber);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 查看ADC转换状态
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块..
|
||||
*
|
||||
* @return 1 or 0
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t ADC_IsConversionActiveFlag( ADC_Type *pADC )
|
||||
{
|
||||
return(pADC->SC2 & ADC_SC2_ADACT_MASK);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 读取转换完成标准位
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块..
|
||||
*
|
||||
* @return 1 or 0
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t ADC_IsCOCOFlag( ADC_Type *pADC )
|
||||
{
|
||||
return(pADC->SC1 & ADC_SC1_COCO_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 读取结果FIFO中是否有有效新数据标志位
|
||||
*
|
||||
* @param[in] pADC point to ADC module type.
|
||||
*
|
||||
* @return 1 or 0
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t ADC_IsFIFOEmptyFlag( ADC_Type *pADC )
|
||||
{
|
||||
return(pADC->SC2 & ADC_SC2_FEMPTY_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 读取结果FIFO是否满标志位
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return 1 or 0
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t ADC_IsFIFOFullFlag( ADC_Type *pADC )
|
||||
{
|
||||
return(pADC->SC2 & ADC_SC2_FFULL_MASK);
|
||||
}
|
||||
#ifndef CPU_NV32
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief Hardware Trigger Multiple Conversion Enable
|
||||
*
|
||||
* @param[in] pADC point to ADC module type.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_HardwareTriggerMultiple( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC4 |= ADC_SC4_HTRGME_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief Hardware Trigger Single Conversion
|
||||
*
|
||||
* @param[in] pADC point to ADC module type.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_HardwareTriggerSingle( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC4 &= ~ADC_SC4_HTRGME_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief Hardware Trigger Mask Enable
|
||||
*
|
||||
* @param[in] pADC point to ADC module type.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_HardwareTriggerMaskEnable( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC5 |= ADC_SC5_HTRGMASKE_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief Hardware Trigger Mask Disable
|
||||
*
|
||||
* @param[in] pADC point to ADC module type.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_HardwareTriggerMaskDisable( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC5 &= ~ADC_SC5_HTRGMASKE_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief Hardware Trigger Mask Mode Select Automatic Mode
|
||||
*
|
||||
* @param[in] pADC point to ADC module type.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_HardwareTriggerMaskAuto( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC5 |= ADC_SC5_HTRGMASKSEL_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief Hardware Trigger Mask Mode Select to be with HTRGMASKE
|
||||
*
|
||||
* @param[in] pADC point to ADC module type.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @ Pass/ Fail criteria: none
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_HardwareTriggerMaskNonAuto( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC5 &= ~ADC_SC5_HTRGMASKSEL_MASK;
|
||||
}
|
||||
#endif
|
||||
/******************************************************************************
|
||||
* Global function
|
||||
******************************************************************************/
|
||||
void ADC_SetChannel( ADC_Type *pADC, uint8_t u8Channel );
|
||||
void ADC_IntEnable( ADC_Type *pADC );
|
||||
void ADC_IntDisable( ADC_Type *pADC );
|
||||
void ADC_ContinuousConversion( ADC_Type *pADC );
|
||||
void ADC_SingleConversion( ADC_Type *pADC );
|
||||
void ADC_SetSoftwareTrigger( ADC_Type *pADC );
|
||||
void ADC_SetHardwareTrigger( ADC_Type *pADC );
|
||||
void ADC_VrefSelect( ADC_Type *pADC, uint8_t u8Vref );
|
||||
void ADC_CompareEnable( ADC_Type *pADC );
|
||||
void ADC_CompareDisable( ADC_Type *pADC );
|
||||
void ADC_CompareGreaterFunction( ADC_Type *pADC );
|
||||
void ADC_CompareLessFunction( ADC_Type *pADC );
|
||||
void ADC_SetLowPower( ADC_Type *pADC );
|
||||
void ADC_SetHighSpeed( ADC_Type *pADC );
|
||||
void ADC_SelectClockDivide( ADC_Type *pADC, uint8_t u8Div);
|
||||
void ADC_SetLongSample(ADC_Type *pADC);
|
||||
void ADC_SetShortSample(ADC_Type *pADC);
|
||||
void ADC_SetMode(ADC_Type *pADC, uint8_t u8Mode);
|
||||
void ADC_SelectClock(ADC_Type *pADC, uint8_t u8Clock);
|
||||
void ADC_FifoScanModeEnable(ADC_Type *pADC);
|
||||
void ADC_FifoScanModeDisable(ADC_Type *pADC);
|
||||
void ADC_CompareFifoOr(ADC_Type *pADC);
|
||||
void ADC_CompareFifoAnd(ADC_Type *pADC);
|
||||
void ADC_SetFifoLevel(ADC_Type *pADC, uint8_t u8FifoLevel);
|
||||
uint16_t ADC_ReadResultReg(ADC_Type *pADC );
|
||||
void ADC_SetCompareValue(ADC_Type *pADC, uint16_t u16Compare );
|
||||
void ADC_PinControlEnable(ADC_Type *pADC, uint16_t u16PinNumber);
|
||||
void ADC_PinControlDisable(ADC_Type *pADC, uint16_t u16PinNumber);
|
||||
uint8_t ADC_IsConversionActiveFlag(ADC_Type *pADC);
|
||||
uint8_t ADC_IsCOCOFlag(ADC_Type *pADC);
|
||||
uint8_t ADC_IsFIFOEmptyFlag(ADC_Type *pADC);
|
||||
uint8_t ADC_IsFIFOFullFlag(ADC_Type *pADC);
|
||||
void ADC_HardwareTriggerMaskNonAuto(ADC_Type *pADC);
|
||||
void ADC_HardwareTriggerMaskAuto(ADC_Type *pADC);
|
||||
void ADC_HardwareTriggerMaskDisable( ADC_Type *pADC );
|
||||
void ADC_HardwareTriggerMaskEnable( ADC_Type *pADC );
|
||||
void ADC_HardwareTriggerSingle( ADC_Type *pADC );
|
||||
void ADC_HardwareTriggerMultiple( ADC_Type *pADC );
|
||||
unsigned int ADC_PollRead( ADC_Type *pADC, uint8_t u8Channel);
|
||||
void ADC_SetCallBack(ADC_CallbackType pADC_CallBack);
|
||||
void ADC_DeInit(ADC_Type *pADC);
|
||||
void ADC_Init(ADC_Type *pADC, ADC_ConfigTypePtr pADC_Config);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,655 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief ADC 驱动头文件.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef ADC_H_
|
||||
#define ADC_H_
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
/******************************************************************************
|
||||
*
|
||||
*定义ADC参考电压
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define ADC_VREF_VREFH 0x00 /*!< ADC 参考电压 VREFH*/
|
||||
#define ADC_VREF_VDDA 0x01 /*!< ADC 参考电压 VDDA*/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义ADC时钟源
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define CLOCK_SOURCE_BUS_CLOCK 0x00 /*!< ADC时钟源选择总线时钟*/
|
||||
#define CLOCK_SOURCE_BUS_CLOCK_DIVIDE_2 0x01 /*!< ADC时钟源选择总线时钟2分频*/
|
||||
#define CLOCK_SOURCE_ALTCLK 0x02 /*!< ADC时钟源选择备用时钟*/
|
||||
#define CLOCK_SOURCE_ADACK 0x03 /*!< ADC时钟源选择异步时钟*/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义ADC源分频系数
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define ADC_ADIV_DIVIDE_1 0x00 /*!< ADC时钟源分频系数为1*/
|
||||
#define ADC_ADIV_DIVIDE_2 0x01 /*!< ADC时钟源分频系数为2*/
|
||||
#define ADC_ADIV_DIVIDE_4 0x02 /*!< ADC时钟源分频系数为4*/
|
||||
#define ADC_ADIV_DIVIDE_8 0x03 /*!< ADC时钟源分频系数为8*/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义ADC转换模式
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define ADC_MODE_8BIT 0x00 /*!< 8位转换*/
|
||||
#define ADC_MODE_10BIT 0x01 /*!< 10位转换*/
|
||||
#define ADC_MODE_12BIT 0x02 /*!< 12位转换*/
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* 定义ADC输入通道
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define ADC_CHANNEL_AD0 0x0 /*!< ADC输入通道0*/
|
||||
#define ADC_CHANNEL_AD1 0x1 /*!< ADC输入通道1*/
|
||||
#define ADC_CHANNEL_AD2 0x2 /*!< ADC输入通道2*/
|
||||
#define ADC_CHANNEL_AD3 0x3 /*!< ADC输入通道3*/
|
||||
#define ADC_CHANNEL_AD4 0x4 /*!< ADC输入通道4*/
|
||||
#define ADC_CHANNEL_AD5 0x5 /*!< ADC输入通道5*/
|
||||
#define ADC_CHANNEL_AD6 0x6 /*!< ADC输入通道6*/
|
||||
#define ADC_CHANNEL_AD7 0x7 /*!< ADC输入通道7*/
|
||||
#define ADC_CHANNEL_AD8 0x8 /*!< ADC输入通道8*/
|
||||
#define ADC_CHANNEL_AD9 0x9 /*!< ADC输入通道9*/
|
||||
#define ADC_CHANNEL_AD10 0xa /*!< ADC输入通道10*/
|
||||
#define ADC_CHANNEL_AD11 0xb /*!< ADC输入通道11*/
|
||||
#define ADC_CHANNEL_AD12 0xc /*!< ADC输入通道12*/
|
||||
#define ADC_CHANNEL_AD13 0xd /*!< ADC输入通道13*/
|
||||
#define ADC_CHANNEL_AD14 0xe /*!< ADC输入通道14*/
|
||||
#define ADC_CHANNEL_AD15 0xf /*!< ADC输入通道15*/
|
||||
#define ADC_CHANNEL_AD18_VSS 0x12 /*!< ADC输入通道 VSS */
|
||||
#define ADC_CHANNEL_AD22_TEMPSENSOR 0x15 /*!< ADC输入通道温度传感器 */
|
||||
#define ADC_CHANNEL_AD23_BANDGAP 0x17 /*!< ADC输入通道带隙 */
|
||||
#define ADC_CHANNEL_AD29_VREFH 0x1D /*!< ADC输入通道 Vrefh */
|
||||
#define ADC_CHANNEL_AD30_VREFL 0x1E /*!< ADC输入通道 Vrefl */
|
||||
#define ADC_CHANNEL_DISABLE 0x1F /*!< ADC输入通道禁用 */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义 ADC FIFO 深度
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define ADC_FIFO_DISABLE 0 /*!< FIFO禁用*/
|
||||
#define ADC_FIFO_LEVEL2 1 /*!< 2级FIFO */
|
||||
#define ADC_FIFO_LEVEL3 2 /*!< 3级FIFO */
|
||||
#define ADC_FIFO_LEVEL4 3 /*!< 4级FIFO */
|
||||
#define ADC_FIFO_LEVEL5 4 /*!< 5级FIFO */
|
||||
#define ADC_FIFO_LEVEL6 5 /*!< 6级FIFO */
|
||||
#define ADC_FIFO_LEVEL7 6 /*!< 7级FIFO */
|
||||
#define ADC_FIFO_LEVEL8 7 /*!< 8级FIFO */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义ADC转换触发源
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define ADC_HARDWARE_TRIGGER 0x01 /*!< 硬件触发 */
|
||||
#define ADC_SOFTWARE_TRIGGER 0x00 /*!< 软件触发 */
|
||||
#define ADC_TRIGGER_RTC 0x00 /*!< 选择RTC溢出作为硬件触发源*/
|
||||
#define ADC_TRIGGER_PIT 0x01 /*!< 选择PIT0溢出作为硬件触发源*/
|
||||
#define ADC_TRIGGER_ETM2INIT 0x10 /*!< 选择ETM2初始化化作为硬件触发源 */
|
||||
#define ADC_TRIGGER_ETM2MATCH 0x11 /*!< 选择ETM2匹配作为硬件触发源 */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义ADC比较触发模式
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define ADC_COMPARE_LESS 0x00 /*!< 输入小于比较电平时比较触发*/
|
||||
#define ADC_COMPARE_GREATER 0x01 /*!< 输入大于比价电平时比较触发*/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* ADC回调函数声明
|
||||
*
|
||||
******************************************************************************/
|
||||
typedef void (*ADC_CallbackType)(void); /*!< ADC回调函数 */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义ADC结构体变量
|
||||
*
|
||||
*******************************************************************************/
|
||||
typedef struct
|
||||
{
|
||||
uint16_t bIntEn :1; /*!< 1: 中断使能, 0: 禁用中断 */
|
||||
uint16_t bContinuousEn :1; /*!< 1: 使能连续转换模式, 0: 禁用连续转换模式 */
|
||||
uint16_t bHardwareTriggerEn :1; /*!< 1: 硬件触发, 0: 软件触发 */
|
||||
uint16_t bCompareEn :1; /*!< 1: 使能比较模式, 0: 禁用比较模式 */
|
||||
uint16_t bCompareGreaterEn :1; /*!< 1: 输入大于或等于比较电平时比较触发, 0: 输入小于比较电平时比较触发 */
|
||||
uint16_t bLowPowerEn :1; /*!< 1: 低功耗模式, 0: 高速模式 */
|
||||
uint16_t bLongSampleEn :1; /*!< 1: 长采样模式, 0: 短采样模式 */
|
||||
uint16_t bFiFoScanModeEn :1; /*!< 1: 使能FIFO扫描模式, 0: 禁用FIFO扫描模式 */
|
||||
uint16_t bCompareAndEn :1; /*!< 1: 对所有比较触发做与运算, 0: 对所有比较触发做或运算*/
|
||||
#ifdef CPU_NV32
|
||||
uint16_t bReverse :7;
|
||||
#else
|
||||
uint16_t bHTRGMEn :1; /*!< one hardware trigger pulse trigger multiple conversions in fifo mode */
|
||||
uint16_t bHTRGMASKEn :1; /*!< Hardware trigger mask enable. */
|
||||
uint16_t bHTRGMASKSEL :1; /*!< This field selects hardware trigger mask mode. */
|
||||
uint16_t Reserve :4;
|
||||
#endif
|
||||
} ADC_SettingType;
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* ADC配置结构体
|
||||
*
|
||||
*******************************************************************************/
|
||||
typedef struct
|
||||
{
|
||||
ADC_SettingType sSetting; /*!< ADC配置结构体*/
|
||||
uint16_t u16PinControl; /*!< 引脚控制 */
|
||||
uint8_t u8ClockSource; /*!< 选择时钟源 */
|
||||
uint8_t u8ClockDiv; /*!< 设置时钟分频 */
|
||||
uint8_t u8Mode; /*!< 设置转换模式(8/10/12 bit mode) */
|
||||
uint8_t u8FiFoLevel; /*!< 设置FIFO深度 */
|
||||
} ADC_ConfigType,*ADC_ConfigTypePtr;
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能ADC中断.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_IntEnable( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC1 |= ADC_SC1_AIEN_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用ADC中断
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_IntDisable( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC1 &= ~ADC_SC1_AIEN_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能ADC连续转换.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_ContinuousConversion( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC1 |= ADC_SC1_ADCO_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能ADC单次转换
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_SingleConversion( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC1 &= ~ADC_SC1_ADCO_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置ADC硬件触发.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块 .
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_SetHardwareTrigger( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC2 |= ADC_SC2_ADTRG_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置ADC软件触发.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块 .
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_SetSoftwareTrigger( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC2 &= ~ADC_SC2_ADTRG_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能ADC比较功能
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_CompareEnable( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC2 |= ADC_SC2_ACFE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用ADC比较功能.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_CompareDisable( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC2 &= ~ADC_SC2_ACFE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 输入大于或等于比较电平时比较触发
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_CompareGreaterFunction( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC2 |= ADC_SC2_ACFGT_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 输入小于比价电平时比较触发
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_CompareLessFunction( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC2 &= ~ADC_SC2_ACFGT_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置ADC为低功耗模式
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_SetLowPower( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC3 |= ADC_SC3_ADLPC_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置ADC为高速模式.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块..
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_SetHighSpeed( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC3 &= ~ADC_SC3_ADLPC_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置ADC长采样.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_SetLongSample( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC3 |= ADC_SC3_ADLSMP_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置ADC短采样
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_SetShortSample( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC3 &= ~ADC_SC3_ADLSMP_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能FIFO扫描模式
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_FifoScanModeEnable( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC4 |= ADC_SC4_ASCANE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用FIFO扫描模式.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_FifoScanModeDisable( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC4 &= ~ADC_SC4_ASCANE_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 对所有比较触发做或运算.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_CompareFifoOr( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC4 &= ~ADC_SC4_ACFSEL_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 对所有比较触发做与运算
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_CompareFifoAnd( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC4 |= ADC_SC4_ACFSEL_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 对ADC转换结果寄存器.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return ADC result value.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint16_t ADC_ReadResultReg( ADC_Type *pADC )
|
||||
{
|
||||
return (uint16_t)pADC->R;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置比较值.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
* @param[in] u16Compare 比较值
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_SetCompareValue( ADC_Type *pADC, uint16_t u16Compare )
|
||||
{
|
||||
pADC->CV = u16Compare;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能ADC输入引脚.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
* @param[in] u16PinNumber 使能的ADC引脚
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @ Pass/ Fail criteria: none
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_PinControlEnable( ADC_Type *pADC, uint16_t u16PinNumber)
|
||||
{
|
||||
ASSERT((u16PinNumber<16));
|
||||
pADC->APCTL1 &= ~(0x01<<u16PinNumber);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用ADC输入引脚.
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
* @param[in] u16PinNumber 禁用的ADC引脚.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_PinControlDisable( ADC_Type *pADC, uint16_t u16PinNumber)
|
||||
{
|
||||
ASSERT((u16PinNumber<16));
|
||||
pADC->APCTL1 |= (0x01<<u16PinNumber);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 查看ADC转换状态
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块..
|
||||
*
|
||||
* @return 1 or 0
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t ADC_IsConversionActiveFlag( ADC_Type *pADC )
|
||||
{
|
||||
return(pADC->SC2 & ADC_SC2_ADACT_MASK);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 读取转换完成标准位
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块..
|
||||
*
|
||||
* @return 1 or 0
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t ADC_IsCOCOFlag( ADC_Type *pADC )
|
||||
{
|
||||
return(pADC->SC1 & ADC_SC1_COCO_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 读取结果FIFO中是否有有效新数据标志位
|
||||
*
|
||||
* @param[in] pADC point to ADC module type.
|
||||
*
|
||||
* @return 1 or 0
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t ADC_IsFIFOEmptyFlag( ADC_Type *pADC )
|
||||
{
|
||||
return(pADC->SC2 & ADC_SC2_FEMPTY_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 读取结果FIFO是否满标志位
|
||||
*
|
||||
* @param[in] pADC 指向ADC模块.
|
||||
*
|
||||
* @return 1 or 0
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t ADC_IsFIFOFullFlag( ADC_Type *pADC )
|
||||
{
|
||||
return(pADC->SC2 & ADC_SC2_FFULL_MASK);
|
||||
}
|
||||
#ifndef CPU_NV32
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief Hardware Trigger Multiple Conversion Enable
|
||||
*
|
||||
* @param[in] pADC point to ADC module type.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_HardwareTriggerMultiple( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC4 |= ADC_SC4_HTRGME_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief Hardware Trigger Single Conversion
|
||||
*
|
||||
* @param[in] pADC point to ADC module type.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_HardwareTriggerSingle( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC4 &= ~ADC_SC4_HTRGME_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief Hardware Trigger Mask Enable
|
||||
*
|
||||
* @param[in] pADC point to ADC module type.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_HardwareTriggerMaskEnable( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC5 |= ADC_SC5_HTRGMASKE_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief Hardware Trigger Mask Disable
|
||||
*
|
||||
* @param[in] pADC point to ADC module type.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_HardwareTriggerMaskDisable( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC5 &= ~ADC_SC5_HTRGMASKE_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief Hardware Trigger Mask Mode Select Automatic Mode
|
||||
*
|
||||
* @param[in] pADC point to ADC module type.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_HardwareTriggerMaskAuto( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC5 |= ADC_SC5_HTRGMASKSEL_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief Hardware Trigger Mask Mode Select to be with HTRGMASKE
|
||||
*
|
||||
* @param[in] pADC point to ADC module type.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @ Pass/ Fail criteria: none
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ADC_HardwareTriggerMaskNonAuto( ADC_Type *pADC )
|
||||
{
|
||||
pADC->SC5 &= ~ADC_SC5_HTRGMASKSEL_MASK;
|
||||
}
|
||||
#endif
|
||||
/******************************************************************************
|
||||
* Global function
|
||||
******************************************************************************/
|
||||
void ADC_SetChannel( ADC_Type *pADC, uint8_t u8Channel );
|
||||
void ADC_IntEnable( ADC_Type *pADC );
|
||||
void ADC_IntDisable( ADC_Type *pADC );
|
||||
void ADC_ContinuousConversion( ADC_Type *pADC );
|
||||
void ADC_SingleConversion( ADC_Type *pADC );
|
||||
void ADC_SetSoftwareTrigger( ADC_Type *pADC );
|
||||
void ADC_SetHardwareTrigger( ADC_Type *pADC );
|
||||
void ADC_VrefSelect( ADC_Type *pADC, uint8_t u8Vref );
|
||||
void ADC_CompareEnable( ADC_Type *pADC );
|
||||
void ADC_CompareDisable( ADC_Type *pADC );
|
||||
void ADC_CompareGreaterFunction( ADC_Type *pADC );
|
||||
void ADC_CompareLessFunction( ADC_Type *pADC );
|
||||
void ADC_SetLowPower( ADC_Type *pADC );
|
||||
void ADC_SetHighSpeed( ADC_Type *pADC );
|
||||
void ADC_SelectClockDivide( ADC_Type *pADC, uint8_t u8Div);
|
||||
void ADC_SetLongSample(ADC_Type *pADC);
|
||||
void ADC_SetShortSample(ADC_Type *pADC);
|
||||
void ADC_SetMode(ADC_Type *pADC, uint8_t u8Mode);
|
||||
void ADC_SelectClock(ADC_Type *pADC, uint8_t u8Clock);
|
||||
void ADC_FifoScanModeEnable(ADC_Type *pADC);
|
||||
void ADC_FifoScanModeDisable(ADC_Type *pADC);
|
||||
void ADC_CompareFifoOr(ADC_Type *pADC);
|
||||
void ADC_CompareFifoAnd(ADC_Type *pADC);
|
||||
void ADC_SetFifoLevel(ADC_Type *pADC, uint8_t u8FifoLevel);
|
||||
uint16_t ADC_ReadResultReg(ADC_Type *pADC );
|
||||
void ADC_SetCompareValue(ADC_Type *pADC, uint16_t u16Compare );
|
||||
void ADC_PinControlEnable(ADC_Type *pADC, uint16_t u16PinNumber);
|
||||
void ADC_PinControlDisable(ADC_Type *pADC, uint16_t u16PinNumber);
|
||||
uint8_t ADC_IsConversionActiveFlag(ADC_Type *pADC);
|
||||
uint8_t ADC_IsCOCOFlag(ADC_Type *pADC);
|
||||
uint8_t ADC_IsFIFOEmptyFlag(ADC_Type *pADC);
|
||||
uint8_t ADC_IsFIFOFullFlag(ADC_Type *pADC);
|
||||
void ADC_HardwareTriggerMaskNonAuto(ADC_Type *pADC);
|
||||
void ADC_HardwareTriggerMaskAuto(ADC_Type *pADC);
|
||||
void ADC_HardwareTriggerMaskDisable( ADC_Type *pADC );
|
||||
void ADC_HardwareTriggerMaskEnable( ADC_Type *pADC );
|
||||
void ADC_HardwareTriggerSingle( ADC_Type *pADC );
|
||||
void ADC_HardwareTriggerMultiple( ADC_Type *pADC );
|
||||
unsigned int ADC_PollRead( ADC_Type *pADC, uint8_t u8Channel);
|
||||
void ADC_SetCallBack(ADC_CallbackType pADC_CallBack);
|
||||
void ADC_DeInit(ADC_Type *pADC);
|
||||
void ADC_Init(ADC_Type *pADC, ADC_ConfigTypePtr pADC_Config);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,93 @@
|
||||
|
||||
/******************************************************************************
|
||||
* @brief Provide Bit-band utilities.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __BIT_BAND_H
|
||||
#define __BIT_BAND_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
*
|
||||
*//*! @addtogroup BIT_BandType
|
||||
* @{
|
||||
*******************************************************************************/
|
||||
/*!
|
||||
* @brief bit band type.
|
||||
*
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t bBit0; /*!< aliase to 0th bit */
|
||||
uint32_t bBit1; /*!< aliase to 1th bit */
|
||||
uint32_t bBit2; /*!< aliase to 2th bit */
|
||||
uint32_t bBit3; /*!< aliase to 3th bit */
|
||||
uint32_t bBit4; /*!< aliase to 4th bit */
|
||||
uint32_t bBit5; /*!< aliase to 5th bit */
|
||||
uint32_t bBit6; /*!< aliase to 6th bit */
|
||||
uint32_t bBit7; /*!< aliase to 7th bit */
|
||||
uint32_t bBit8; /*!< aliase to 8th bit */
|
||||
uint32_t bBit9; /*!< aliase to 9th bit */
|
||||
uint32_t bBit10; /*!< aliase to 10th bit */
|
||||
uint32_t bBit11; /*!< aliase to 11th bit */
|
||||
uint32_t bBit12; /*!< aliase to 12th bit */
|
||||
uint32_t bBit13; /*!< aliase to 13th bit */
|
||||
uint32_t bBit14; /*!< aliase to 14th bit */
|
||||
uint32_t bBit15; /*!< aliase to 15th bit */
|
||||
uint32_t bBit16; /*!< aliase to 16th bit */
|
||||
uint32_t bBit17; /*!< aliase to 17th bit */
|
||||
uint32_t bBit18; /*!< aliase to 18th bit */
|
||||
uint32_t bBit19; /*!< aliase to 19th bit */
|
||||
uint32_t bBit20; /*!< aliase to 20th bit */
|
||||
uint32_t bBit21; /*!< aliase to 21th bit */
|
||||
uint32_t bBit22; /*!< aliase to 22th bit */
|
||||
uint32_t bBit23; /*!< aliase to 23th bit */
|
||||
uint32_t bBit24; /*!< aliase to 24th bit */
|
||||
uint32_t bBit25; /*!< aliase to 25th bit */
|
||||
uint32_t bBit26; /*!< aliase to 26th bit */
|
||||
uint32_t bBit27; /*!< aliase to 27th bit */
|
||||
uint32_t bBit28; /*!< aliase to 28th bit */
|
||||
uint32_t bBit29; /*!< aliase to 29th bit */
|
||||
uint32_t bBit30; /*!< aliase to 30th bit */
|
||||
uint32_t bBit31; /*!< aliase to 31th bit */
|
||||
}BIT_BandType,*BIT_BandPtr;
|
||||
/*! @} End of BIT_BandType */
|
||||
|
||||
/******************************************************************************
|
||||
* define API list
|
||||
*
|
||||
*//*! @addtogroup bit_band_api_list
|
||||
* @{
|
||||
*******************************************************************************/
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief bit-band initialize pointer, so that invoke the pointer to access alisaed bitband.
|
||||
*
|
||||
* @param[in] pVariableAddress - point to variable.
|
||||
* @param[in] pBitbandPtr - point to alisaed bitband address.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @ Pass/ Fail criteria: none
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void BIT_BandVariableInit( uint32_t *pVariableAddress,BIT_BandPtr *pBitbandPtr )
|
||||
{
|
||||
#if defined(CPU_NV32M3)
|
||||
ASSERT( ((uint32)pVariableAddress >= 0x20000000)&&((uint32_t)pVariableAddress <= 0x200002FF) );
|
||||
#elif defined(CPU_NV32M4)
|
||||
ASSERT( ((uint32)pVariableAddress >= 0x20000000)&&((uint32_t)pVariableAddress <= (0x20000000+12*1024)));
|
||||
#else
|
||||
#error "don't support this function on this device"
|
||||
#endif
|
||||
*pBitbandPtr = (BIT_BandPtr)(((uint32_t)pVariableAddress-0x20000000)*32+0x22000000);
|
||||
}
|
||||
/*! @} End of bit_band_api_list */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __BIT_BAND_H */
|
||||
|
||||
|
||||
@@ -0,0 +1,559 @@
|
||||
/*************************************************************************!
|
||||
* 技术讨论:QQ群 123763203
|
||||
* 官网 :www.navota.com
|
||||
*
|
||||
* @file bos.h
|
||||
* @brief 位操作存储模块(BOS)函数库
|
||||
* @author Navota
|
||||
* @date 2017-1-1
|
||||
***************************************************************************/
|
||||
/******************************************************************************
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __BOS_H
|
||||
#define __BOS_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/******************************************************************************
|
||||
*
|
||||
* BOS 操作码(opcode)
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#define BOS_OPCODE_AND 1 /*!< AND 操作码 */
|
||||
#define BOS_OPCODE_OR 2 /*!< OR 操作码 */
|
||||
#define BOS_OPCODE_XOR 3 /*!< XOR 操作码 */
|
||||
#define BOS_OPCODE_BITFIELD 4 /*!< 位字段操作码 */
|
||||
|
||||
#define BOS_OPCODE_BIT_CLEAR 2 /*!< 位清零操作码 */
|
||||
#define BOS_OPCODE_BIT_SET 3 /*!< 置位操作码 */
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* BOS宏定义,用来生成BOS硬件编码地址
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
/******************************************************************************
|
||||
* 宏定义,用于生成逻辑与硬件编码地址.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 生成BOS位操作逻辑与操作地址(32位硬件编码地址)
|
||||
*
|
||||
* @param[in] ADDR 32位地址.
|
||||
*
|
||||
* @return hardcoded 32位地址.
|
||||
*
|
||||
*
|
||||
*****************************************************************************/
|
||||
#define BOS_AND(ADDR) (*(volatile uint32_t *)(((uint32_t)ADDR) | (BOS_OPCODE_AND<<26)))
|
||||
|
||||
/******************************************************************************
|
||||
* 宏定义,用于生成逻辑或硬件编码地址.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 生成BOS位操作逻辑或操作地址(32位硬件编码地址)
|
||||
*
|
||||
* @param[in] ADDR 32位地址.
|
||||
*
|
||||
* @return hardcoded 32位地址.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define BOS_OR(ADDR) (*(volatile uint32_t *)(((uint32_t)ADDR) | (BOS_OPCODE_OR<<26)))
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* 宏定义,用于生成逻辑异或硬件编码地址.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 生成BOS位操作逻辑或操作地址(32位硬件编码地址)
|
||||
*
|
||||
* @param[in] ADDR 32位地址.
|
||||
*
|
||||
* @return hardcoded 32位地址.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define BOS_XOR(ADDR) (*(volatile uint32_t *)(((uint32_t)ADDR) | (BOS_OPCODE_XOR<<26)))
|
||||
|
||||
#if !defined(BOS_SANITY_CHECK)
|
||||
/*!
|
||||
* @brief This is fastest way for BOS without sanity check.
|
||||
*/
|
||||
/******************************************************************************
|
||||
* 宏定义,用于生成一位加载-清零(LAC1)硬件编码地址.
|
||||
*
|
||||
*******************************************************************************/
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 生成BOS位操作:1位加载清零操作地址(32位硬件编码地址)
|
||||
*
|
||||
* @param[in] ADDR 32位地址
|
||||
* @param[in] bit 要清零的位, 0-based.
|
||||
*
|
||||
* @return hardcoded 32-bit address.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define BOS_BIT_CLEAR(ADDR,bit) (*(volatile uint32_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BIT_CLEAR <<26) \
|
||||
| ((bit)<<21)))
|
||||
|
||||
/******************************************************************************
|
||||
* 宏定义,用于生成一位加载-置位(LAS1)硬件编码地址.
|
||||
*
|
||||
*******************************************************************************/
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 生成BOS位操作:1位加载置位操作地址(32位硬件编码地址)
|
||||
*
|
||||
* @param[in] ADDR 32位地址.
|
||||
* @param[in] bit 要置1的位, 0-based.
|
||||
*
|
||||
* @return hardcoded 32-bit address.
|
||||
*
|
||||
*****************************************************************************/
|
||||
#define BOS_BIT_SET(ADDR,bit) (*(volatile uint32_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BIT_SET <<26) \
|
||||
| ((bit)<<21)))
|
||||
|
||||
/******************************************************************************
|
||||
*宏定义,用于生成位操作存储字段插入(BFI)硬件编码地址.
|
||||
*
|
||||
*******************************************************************************/
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 生成BOS位操作存储字段插入硬件编码地址 (32位硬件编码地址).
|
||||
*
|
||||
* @param[in] ADDR 32位地址
|
||||
* @param[in] bit 插入字段的起始位, 0-based.
|
||||
* @param[in] width 插入字段的宽度, 1-based.
|
||||
*
|
||||
* @return hardcoded 32-bit address.
|
||||
*
|
||||
*****************************************************************************/
|
||||
#define BOS_BITFIELD_INSERT(ADDR,bit,width) (*(volatile uint32_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BITFIELD <<26) \
|
||||
| ((bit)<<23) | ((width-1))<<19))
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* *宏定义,用于生位操作存储加载无符号字段提取(UBFX)硬件编码地址 .
|
||||
*
|
||||
*******************************************************************************/
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 用于生位操作存储加载无符号字段提取(UBFX)操作地址 (32位硬件编码地址).
|
||||
*
|
||||
* @param[in] ADDR 32位地址.
|
||||
* @param[in] bit 读取起始位, 0-based.
|
||||
* @param[in] width 读取字段宽度, 1-based.
|
||||
*
|
||||
* @return hardcoded 32-bit address.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define BOS_BITFIELD_EXTRACT(ADDR,bit,width) (*(volatile uint32_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BITFIELD <<26) \
|
||||
| ((bit)<<23) | ((width-1))<<19))
|
||||
#else
|
||||
/*!
|
||||
* @brief This is slow way for BOS as it has sanity check.
|
||||
*/
|
||||
/******************************************************************************
|
||||
* 宏定义,用于生成一位加载-清零(LAC1)地址.
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define BOS_BIT_CLEAR(ADDR,bit) (*(volatile uint32_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BIT_CLEAR <<26) \
|
||||
| ((bit & 0x1F)<<21))) /*!< 位清零操作 */
|
||||
|
||||
/*****************************************************************************
|
||||
* 宏定义,用于生成一位加载-置位(LAS1)硬件编码地址.
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define BOS_BIT_SET(ADDR,bit) (*(volatile uint32_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BIT_SET <<26) \
|
||||
| ((bit & 0x1F)<<21))) /*!< 置位操作 */
|
||||
|
||||
/******************************************************************************
|
||||
*宏定义,用于生成位操作存储字段插入(BFI)硬件编码地址.
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define BOS_BITFIELD_INSERT(ADDR,bit,width) (*(volatile uint32_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BITFIELD <<26) \
|
||||
| ((bit & 0x1F)<<23) | ((width-1) & 0xF)<<19)) /*!< 字段插入操作 */
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*宏定义,用于生位操作存储加载无符号字段提取(UBFX)硬件编码地址
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define BOS_BITFIELD_EXTRACT(ADDR,bit,width) (*(volatile uint32_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BITFIELD <<26) \
|
||||
| ((bit & 0x1F)<<23) | ((width-1) & 0xF)<<19)) /*!< 字段提取操作 */
|
||||
#endif
|
||||
/******************************************************************************
|
||||
* BOS宏定义,用来生成BOS硬件编码地址(8位地址)
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
/******************************************************************************
|
||||
* 宏定义,用于生成逻辑或硬件编码地址.(8位地址)
|
||||
*
|
||||
*******************************************************************************/
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 生成BOS位操作逻辑与(AND)操作地址(32位硬件编码地址),对8位数据进行与操作
|
||||
*
|
||||
* @param[in] ADDR 32位地址.
|
||||
*
|
||||
* @return hardcoded 32-bit address.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define BOS_AND_8b(ADDR) (*(volatile uint8_t *)(((uint32_t)ADDR) | (BOS_OPCODE_AND<<26)))
|
||||
|
||||
/******************************************************************************
|
||||
* 宏定义,用于生成逻辑或硬件编码地址.
|
||||
*
|
||||
*******************************************************************************/
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 生成BOS位操作逻辑或(OR)操作地址(32位硬件编码地址),对8位数据进行或操作.
|
||||
*
|
||||
* @param[in] ADDR 32位地址.
|
||||
*
|
||||
* @return hardcoded 32位地址.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define BOS_OR_8b(ADDR) (*(volatile uint8_t *)(((uint32_t)ADDR) | (BOS_OPCODE_OR<<26)))
|
||||
|
||||
/******************************************************************************
|
||||
* 宏定义,用于生成逻辑异或硬件编码地址.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 生成BOS位操作逻辑异或(XOR)操作地址(32位硬件编码地址),对8位数据进行异或操作..
|
||||
*
|
||||
* @param[in] ADDR 32位地址.
|
||||
*
|
||||
* @return hardcoded 32位地址.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define BOS_XOR_8b(ADDR) (*(volatile uint8_t *)(((uint32_t)ADDR) | (BOS_OPCODE_XOR<<26)))
|
||||
|
||||
#if !defined(BOS_SANITY_CHECK)
|
||||
/*!
|
||||
* @brief This is fastest way for BOS without sanity check.
|
||||
*/
|
||||
/******************************************************************************
|
||||
* 宏定义用于生成 1位加载清零(LAC1)硬件编码地址
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 生成BOS位操作:1位加载清零操作地址(32位硬件编码地址)用于8位数据操作.
|
||||
*
|
||||
* @param[in] ADDR 32位地址
|
||||
* @param[in] bit 要清零的位, 0-based.
|
||||
*
|
||||
* @return hardcoded 32位地址.
|
||||
*
|
||||
*****************************************************************************/
|
||||
#define BOS_BIT_CLEAR_8b(ADDR,bit) (*(volatile uint8_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BIT_CLEAR <<26) \
|
||||
| ((bit)<<21)))
|
||||
|
||||
/******************************************************************************
|
||||
* 宏定义用于生成 1位加载置1(LAS1)硬件编码地址
|
||||
*
|
||||
*******************************************************************************/
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 生成BOS位操作1位加载置1(LAS1)操作码(32位硬件编码地址)用于8位数据操作
|
||||
*
|
||||
* @param[in] ADDR 32位地址
|
||||
* @param[in] bit 要置1的位, 0-based.
|
||||
*
|
||||
* @return hardcoded 32位地址.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define BOS_BIT_SET_8b(ADDR,bit) (*(volatile uint8_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BIT_SET <<26) \
|
||||
| ((bit)<<21)))
|
||||
|
||||
/******************************************************************************
|
||||
*宏定义,用于生成位操作存储字段插入(BFI)硬件编码地址.
|
||||
*
|
||||
*******************************************************************************/
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 生成BOS位操作存储字段插入硬件编码地址 (32位硬件编码地址).用于8位数据操作
|
||||
*
|
||||
* @param[in] ADDR 32位地址
|
||||
* @param[in] bit 插入字段的起始位, 0-based.
|
||||
* @param[in] width 插入字段的宽度, 1-based.
|
||||
*
|
||||
* @return hardcoded 32位地址.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define BOS_BITFIELD_INSERT_8b(ADDR,bit,width) (*(volatile uint8_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BITFIELD <<26) \
|
||||
| ((bit)<<23) | ((width-1))<<19))
|
||||
/******************************************************************************
|
||||
*宏定义,用于生位操作存储加载无符号字段提取(UBFX)硬件编码地址 .
|
||||
*
|
||||
*******************************************************************************/
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 用于生位操作存储加载无符号字段提取(UBFX)操作地址 (32位硬件编码地址).用于8位操作
|
||||
*
|
||||
* @param[in] ADDR 32位地址.
|
||||
* @param[in] bit 读取起始位, 0-based.
|
||||
* @param[in] width 读取字段宽度, 1-based.
|
||||
*
|
||||
* @return hardcoded 32-bit address.
|
||||
*
|
||||
*****************************************************************************/
|
||||
#define BOS_BITFIELD_EXTRACT_8b(ADDR,bit,width) (*(volatile uint8_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BITFIELD <<26) \
|
||||
| ((bit<<23) | ((width-1))<<19))
|
||||
#else
|
||||
/*!
|
||||
* @brief This is slow way for BOS as it has sanity check.
|
||||
*/
|
||||
/******************************************************************************
|
||||
* 宏定义,用于生成一位加载-清零(LAC1)地址.
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define BOS_BIT_CLEAR_8b(ADDR,bit) (*(volatile uint8_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BIT_CLEAR <<26) \
|
||||
| ((bit & 0x1F)<<21))) /*!< 位清零操作,8位模式*/
|
||||
|
||||
/******************************************************************************
|
||||
* 宏定义,用于生成一位加载-置位(LAS1)硬件编码地址.
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define BOS_BIT_SET_8b(ADDR,bit) (*(volatile uint8_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BIT_SET <<26) \
|
||||
| ((bit & 0x1F)<<21))) /*!< 位置1操作,8位模式*/
|
||||
|
||||
/******************************************************************************
|
||||
* 宏定义,用于生成位操作存储字段插入(BFI)硬件编码地址.
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define BOS_BITFIELD_INSERT_8b(ADDR,bit,width) (*(volatile uint8_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BITFIELD <<26) \
|
||||
| ((bit & 0x1F)<<23) | ((width-1) & 0xF)<<19)) /*!< 字段插入操作,8位模式 */
|
||||
|
||||
/******************************************************************************
|
||||
*宏定义,用于生位操作存储加载无符号字段提取(UBFX)硬件编码地址
|
||||
*******************************************************************************/
|
||||
|
||||
#define BOS_BITFIELD_EXTRACT_8b(ADDR,bit,width) (*(volatile uint8_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BITFIELD <<26) \
|
||||
| ((bit & 0x1F)<<23) | ((width-1) & 0xF)<<19)) /*!< 字段提取操作,8位 */
|
||||
#endif
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* BOS宏定义,用来生成BOS硬件编码地址(16位地址)
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
/******************************************************************************
|
||||
* 宏定义,用于生成逻辑或硬件编码地址.(16位地址)
|
||||
*
|
||||
*******************************************************************************/
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 生成BOS位操作逻辑与(AND)操作地址(32位硬件编码地址),对8位数据进行与操作
|
||||
*
|
||||
* @param[in] ADDR 32位地址.
|
||||
*
|
||||
* @return hardcoded 32-bit address.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define BOS_AND_16b(ADDR) (*(volatile uint16_t *)(((uint32_t)ADDR) | (BOS_OPCODE_AND<<26)))
|
||||
|
||||
/******************************************************************************
|
||||
* 宏定义,用于生成逻辑或硬件编码地址.
|
||||
*
|
||||
*******************************************************************************/
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 生成BOS位操作逻辑或(OR)操作地址(32位硬件编码地址),对8位数据进行或操作.
|
||||
*
|
||||
* @param[in] ADDR 32位地址.
|
||||
*
|
||||
* @return hardcoded 32位地址.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define BOS_OR_16b(ADDR) (*(volatile uint16_t *)(((uint32_t)ADDR) | (BOS_OPCODE_OR<<26)))
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* 宏定义,用于生成逻辑异或硬件编码地址.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 生成BOS位操作逻辑异或(XOR)操作地址(32位硬件编码地址),对8位数据进行异或操作..
|
||||
*
|
||||
* @param[in] ADDR 32位地址.
|
||||
*
|
||||
* @return hardcoded 32位地址.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#define BOS_XOR_16b(ADDR) (*(volatile uint16_t *)(((uint32_t)ADDR) | (BOS_OPCODE_XOR<<26)))
|
||||
|
||||
|
||||
#if !defined(BOS_SANITY_CHECK)
|
||||
/*!
|
||||
* @brief This is fastest way for BOS without sanity check.
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
* 宏定义用于生成 1位加载清零(LAC1)硬件编码地址
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 生成BOS位操作:1位加载清零操作地址(32位硬件编码地址)用于16位数据操作.
|
||||
*
|
||||
* @param[in] ADDR 32位地址
|
||||
* @param[in] bit 要清零的位, 0-based.
|
||||
*
|
||||
* @return hardcoded 32位地址.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#define BOS_BIT_CLEAR_16b(ADDR,bit) (*(volatile uint16_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BIT_CLEAR <<26) \
|
||||
| ((bit)<<21)))
|
||||
|
||||
/******************************************************************************
|
||||
* 宏定义用于生成 1位加载置1(LAS1)硬件编码地址
|
||||
*
|
||||
*******************************************************************************/
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 生成BOS位操作1位加载置1(LAS1)操作码(32位硬件编码地址)用于8位数据操作
|
||||
*
|
||||
* @param[in] ADDR 32位地址
|
||||
* @param[in] bit 要置1的位, 0-based.
|
||||
*
|
||||
* @return hardcoded 32位地址.
|
||||
*
|
||||
*****************************************************************************/
|
||||
#define BOS_BIT_SET_16b(ADDR,bit) (*(volatile uint16_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BIT_SET <<26) \
|
||||
| ((bit)<<21)))
|
||||
|
||||
/******************************************************************************
|
||||
*宏定义,用于生成位操作存储字段插入(BFI)硬件编码地址.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 生成BOS位操作存储字段插入硬件编码地址 (32位硬件编码地址).用于16位数据操作
|
||||
*
|
||||
* @param[in] ADDR 32位地址
|
||||
* @param[in] bit 插入字段的起始位, 0-based.
|
||||
* @param[in] width 插入字段的宽度, 1-based.
|
||||
*
|
||||
* @return hardcoded 32位地址.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define BOS_BITFIELD_INSERT_16b(ADDR,bit,width) (*(volatile uint16_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BITFIELD <<26) \
|
||||
| ((bit)<<23) | ((width-1))<<19))
|
||||
|
||||
/******************************************************************************
|
||||
*宏定义,用于生位操作存储加载无符号字段提取(UBFX)硬件编码地址 .
|
||||
*
|
||||
*******************************************************************************/
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 用于生位操作存储加载无符号字段提取(UBFX)操作地址 (32位硬件编码地址).用于16位操作
|
||||
*
|
||||
* @param[in] ADDR 32位地址.
|
||||
* @param[in] bit 读取起始位, 0-based.
|
||||
* @param[in] width 读取字段宽度, 1-based.
|
||||
*
|
||||
* @return hardcoded 32-bit address.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define BOS_BITFIELD_EXTRACT_16b(ADDR,bit,width) (*(volatile uint16_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BITFIELD <<26) \
|
||||
| ((bit)<<23) | ((width-1))<<19))
|
||||
#else
|
||||
/*!
|
||||
* @brief This is slow way for BOS as it has sanity check.
|
||||
*/
|
||||
/******************************************************************************
|
||||
* 宏定义,用于生成一位加载-清零(LAC1)地址.
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define BOS_BIT_CLEAR_16b(ADDR,bit) (*(volatile uint16_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BIT_CLEAR <<26) \
|
||||
| ((bit & 0x1F)<<21))) /*!< 位清零操作,16位模式*/
|
||||
|
||||
/******************************************************************************
|
||||
* 宏定义,用于生成一位加载-置位(LAS1)硬件编码地址.
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define BOS_BIT_SET_16b(ADDR,bit) (*(volatile uint16_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BIT_SET <<26) \
|
||||
| ((bit & 0x1F)<<21))) /*!< 位置1操作,16位模式*/
|
||||
|
||||
/******************************************************************************
|
||||
* 宏定义,用于生成位操作存储字段插入(BFI)硬件编码地址.
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define BOS_BITFIELD_INSERT_16b(ADDR,bit,width) (*(volatile uint16_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BITFIELD <<26) \
|
||||
| ((bit & 0x1F)<<23) | ((width-1) & 0xF)<<19)) /*!< 字段插入操作,16位模式 */
|
||||
|
||||
/******************************************************************************
|
||||
*宏定义,用于生位操作存储加载无符号字段提取(UBFX)硬件编码地址
|
||||
*******************************************************************************/
|
||||
#define BOS_BITFIELD_EXTRACT_16b(ADDR,bit,width) (*(volatile uint16_t *)(((uint32_t)ADDR) \
|
||||
| (BOS_OPCODE_BITFIELD <<26) \
|
||||
| ((bit & 0x1F)<<23) | ((width-1) & 0xF)<<19)) /*!< 字段提取操作,16位 */
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,228 @@
|
||||
/**************************************************************************!
|
||||
* 技术讨论:QQ群 123763203
|
||||
* 官网 :www.navota.com
|
||||
*
|
||||
* @file crc.c
|
||||
* @brief 冗余校验模块(CRC)函数库
|
||||
* @author Navota
|
||||
* @date 2018-3-1
|
||||
****************************************************************************/
|
||||
#include "common.h"
|
||||
#include "crc.h"
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 初始化CRC
|
||||
*
|
||||
* @param[in] pConfig 指向CRC配置结构体.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void CRC_Init(CRC_ConfigType *pConfig)
|
||||
{
|
||||
uint32_t u32Sc ;
|
||||
|
||||
u32Sc = 0;
|
||||
|
||||
SIM->SCGC |= SIM_SCGC_CRC_MASK; //使能CRC控制模块时钟
|
||||
|
||||
u32Sc |= ((pConfig->bWidth & 0x01)<<24); //CRC模式选择
|
||||
u32Sc |= CRC_CTRL_TOTR(pConfig->bTransposeReadType & 0x03); //设置数据读取的转置类型
|
||||
u32Sc |= CRC_CTRL_TOT(pConfig->bTransposeWriteType & 0x03); //设置数据写入的转置类型
|
||||
|
||||
if (pConfig->bFinalXOR)
|
||||
{
|
||||
u32Sc |= CRC_CTRL_FXOR_MASK; //对CRC数据寄存的读取值进行异或操作
|
||||
}
|
||||
|
||||
CRC0->CTRL = u32Sc;
|
||||
|
||||
if ( pConfig->bWidth )
|
||||
{
|
||||
CRC0->GPOLY = pConfig->u32PolyData; //写入32位多项式
|
||||
}
|
||||
else
|
||||
{
|
||||
CRC0->GPOLY_ACCESS16BIT.GPOLYL = pConfig->u32PolyData; /*!< 仅允许写16位多项式*/
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 16位模式下CRC计算函数.
|
||||
*
|
||||
* @param[in] seed 种子值
|
||||
* @param[in] msg 指向数据数组
|
||||
* @param[in] sizeBytes 数据大小
|
||||
*
|
||||
* @return data_out convertion result
|
||||
*
|
||||
*****************************************************************************/
|
||||
uint32_t CRC_Cal16(uint32_t seed, uint8_t *msg, uint32_t sizeBytes)
|
||||
{
|
||||
uint32_t ctrl_reg,data_out,data_in;
|
||||
uint8_t *pCRCBytes;
|
||||
uint32_t sizeWords;
|
||||
uint32_t i,j;
|
||||
|
||||
/* 设置WaS=1,写入种子值 */
|
||||
ctrl_reg = CRC0->CTRL;
|
||||
CRC0->CTRL = ctrl_reg | CRC_CTRL_WAS_MASK;
|
||||
CRC0->ACCESS16BIT.DATAL = seed;
|
||||
|
||||
/* Set WaS=0,准备写入数据*/
|
||||
CRC0->CTRL = ctrl_reg & 0xFD000000;
|
||||
|
||||
/*等待计算完成*/
|
||||
sizeWords = sizeBytes>>1;
|
||||
j = 0;
|
||||
for(i=0;i<sizeWords;i++){
|
||||
data_in = (msg[j] << 8) | (msg[j+1]); /*将数据写入CRC数据寄存器,以16位方式写入*/
|
||||
j += 2;
|
||||
CRC0->ACCESS16BIT.DATAL =data_in;
|
||||
}
|
||||
if (j<sizeBytes)
|
||||
{
|
||||
pCRCBytes = (uint8_t*)&CRC0->ACCESS8BIT.DATALL; /*以8位的方式写入剩余的数据*/
|
||||
*pCRCBytes++ = msg[j];
|
||||
}
|
||||
if ((CRC0->CTRL& CRC_CTRL_TOTR_MASK)>1) //Modify
|
||||
{
|
||||
data_out=CRC0->ACCESS16BIT.DATAH; //读出字节转置后16位计算结果
|
||||
}
|
||||
else
|
||||
{
|
||||
data_out=CRC0->ACCESS16BIT.DATAL; //读出16位计算结果
|
||||
}
|
||||
|
||||
return(data_out);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 32位模式下CRC计算.
|
||||
*
|
||||
* @param[in] seed
|
||||
* @param[in] msg 指向数据数组
|
||||
* @param[in] sizeBytes 数据大小
|
||||
*
|
||||
* @return data_out convertion result
|
||||
*
|
||||
*****************************************************************************/
|
||||
uint32_t CRC_Cal32(uint32_t seed, uint8_t *msg, uint32_t sizeBytes)
|
||||
{
|
||||
uint32_t ctrl_reg,data_out,data_in;
|
||||
uint32_t sizeDwords;
|
||||
uint8_t *pCRCBytes;
|
||||
uint32_t i,j;
|
||||
|
||||
/* 设置WaS=1,写入种子值 */
|
||||
ctrl_reg = CRC0->CTRL;
|
||||
CRC0->CTRL = ctrl_reg | 0x02000000;
|
||||
CRC0->DATA = seed;
|
||||
|
||||
/* Set WaS=0,准备写入数据*/
|
||||
CRC0->CTRL = ctrl_reg & 0xFD000000;
|
||||
|
||||
/*等待数据计算完成*/
|
||||
sizeDwords = sizeBytes>>2;
|
||||
j = 0;
|
||||
for(i=0;i<sizeDwords;i++)
|
||||
{
|
||||
data_in = ((msg[j] << 24) | (msg[j+1] << 16) | (msg[j+2] << 8) | msg[j+3]); /*将数据写入CRC数据寄存器,以32方式写入*/
|
||||
j += 4;
|
||||
CRC0->DATA = data_in;
|
||||
}
|
||||
if (j<sizeBytes)
|
||||
{
|
||||
pCRCBytes = (uint8_t*)&CRC0->ACCESS8BIT.DATALL; /*以8位的方式写入剩余的数据*/
|
||||
|
||||
#if defined(BYTE_ENABLES_1_2_4_8)
|
||||
|
||||
/*只写单个字节*/
|
||||
for(;j<sizeBytes;j++)
|
||||
{
|
||||
*pCRCBytes++ = msg[j];
|
||||
}
|
||||
#elif defined(BYTE_ENABLES_3_6_C)
|
||||
|
||||
/*写入两个字节*/
|
||||
data_in = 0;
|
||||
i = 0;
|
||||
for(;j<sizeBytes;j++)
|
||||
{
|
||||
data_in = (data_in <<8) | msg[j];
|
||||
i++;
|
||||
if (i==2)
|
||||
{
|
||||
i = 0;
|
||||
CRC0->ACCESS16BIT.DATAL = data_in;
|
||||
}
|
||||
}
|
||||
if (i==1)
|
||||
{
|
||||
CRC0->ACCESS8BIT.DATALL = data_in; /*!< 写入最后一个字节 */
|
||||
}
|
||||
#elif defined(BYTE_ENABLES_7_E)
|
||||
/*!< 写入三个字节*/
|
||||
data_in = 0;
|
||||
i = 0;
|
||||
for(;j<sizeBytes;j++)
|
||||
{
|
||||
data_in = (data_in <<8) | msg[j];
|
||||
i++;
|
||||
if (i==3)
|
||||
{
|
||||
i = 0;
|
||||
/*写入第一个字符*/
|
||||
CRC0->ACCESS8BIT.DATAHL = (data_in>>16) & 0xff; /*!< 写入高字的低字节 */
|
||||
/*写入最后两个字节*/
|
||||
CRC0->ACCESS16BIT.DATAL = data_in & 0x00ffff; /*!< 写入低字 */
|
||||
}
|
||||
}
|
||||
if ( i == 2)
|
||||
{
|
||||
CRC0->ACCESS16BIT.DATAL = (data_in); /*!< 写最后两个字节 */
|
||||
}
|
||||
else if (i == 1)
|
||||
{
|
||||
CRC0->ACCESS8BIT.DATALL = data_in; /*!< 写最后一个字节 */
|
||||
}
|
||||
#else /*!< 只写低字节 */
|
||||
for(;j<sizeBytes;j++)
|
||||
{
|
||||
*pCRCBytes = msg[j];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
data_out=CRC0->DATA;
|
||||
|
||||
return(data_out); //读出32位计算结果
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 复位CRC模块
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void CRC_DeInit(void)
|
||||
{
|
||||
CRC0->CTRL = 0x3000000; /*!<设置CRC位32位模式*/
|
||||
CRC0->DATA = 0xFFFFFFFF;/*!< 写32位种子值到CRC数据寄存器*/
|
||||
while(!(CRC0->DATA == 0xFFFFFFFF));
|
||||
CRC0->GPOLY = 0x00001021;
|
||||
CRC0->CTRL = 0; /*!<CRC控制寄存器清零*/
|
||||
SIM->SCGC &= ~SIM_SCGC_CRC_MASK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief CRC 驱动头文件.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef CRC_H_
|
||||
#define CRC_H_
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
/**********************************************************************!
|
||||
* @brief CRC控制寄存器位定义
|
||||
*
|
||||
*******************************************************************/
|
||||
|
||||
#define CRC_WIDTH_16BIT 0 /*!< 选择16位CRC协议 */
|
||||
#define CRC_WIDTH_32BIT 1 /*!< 选择32位CRC协议 */
|
||||
#define CRC_DATA_SEED 1 /*!< 写入CRC数据寄存器的值为种子值 */
|
||||
#define CRC_DATA_DATA 0 /*!< 写入CRC数据寄存器的值为数据值 */
|
||||
#define CRC_READ_COMPLETE 1 /*!< 反转或补充CRC数据寄存器的读取值 */
|
||||
#define CRC_READ_NONE 0 /*!< 读取数据寄存器时不执行异或运算*/
|
||||
#define CRC_READ_TRANSPOSE_NONE 0 /*!< 读取数据寄存器的值无转置 */
|
||||
#define CRC_READ_TRANSPOSE_BIT 1 /*!< 读取数据寄存器的值,字节中的位转置,字不转置*/
|
||||
#define CRC_READ_TRANSPOSE_ALL 2 /*!< 读取数据寄存器的值,字节中的位和字节均转置 */
|
||||
#define CRC_READ_TRANSPOSE_BYTE 3 /*!< 读取数据寄存器的值,仅字节转置,字节中的位不转置 */
|
||||
#define CRC_WRITE_TRANSPOSE_NONE 0 /*!< 写数据时无转置 */
|
||||
#define CRC_WRITE_TRANSPOSE_BIT 1 /*!< 写数据时,字节中的位转置,字节不转置 */
|
||||
#define CRC_WRITE_TRANSPOSE_ALL 2 /*!< 写数据时,字节中的位和字节均转置 */
|
||||
#define CRC_WRITE_TRANSPOSE_BYTE 3 /*!< 写数据时,仅字节转置,字节中的位不转置 */
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* CRC 配置结构体类型.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t bWidth : 1; /*!< 1: 32位CRC协议 0: 16位CRC协议 */
|
||||
uint8_t bDataType : 1; /*!< 1: 写入种子值 , 0: 写入数据 */
|
||||
uint8_t bFinalXOR : 1; /*!< 1: 读数据是反转或补充 , 0: 读数据时不执行异或*/
|
||||
uint8_t bRESERVED : 1; /*!< 保留位 */
|
||||
uint8_t bTransposeReadType : 2; /*!< 读取数据时的转置类型, 参阅参考手册 */
|
||||
uint8_t bTransposeWriteType : 2; /*!< 写数据时的转置类型, 参阅参考手册 */
|
||||
uint32_t u32PolyData ; /*!< 32位或16位多项式*/
|
||||
} CRC_ConfigType, *CRC_ConfigPtr ;
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void CRC_Init(CRC_ConfigType *pConfig);
|
||||
uint32_t CRC_Cal16(uint32_t u32Seed, uint8_t *msg, uint32_t u32SizeBytes);
|
||||
uint32_t CRC_Cal32(uint32_t u32Seed, uint8_t *msg, uint32_t u32SizeBytes);
|
||||
void CRC_DeInit(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/***********************************************************************!
|
||||
* 技术讨论:QQ群 123763203
|
||||
* 官网 :www.navota.com
|
||||
*
|
||||
* @file delay.c
|
||||
* @brief systic函数库
|
||||
* @author Navota
|
||||
* @date 2018-3-1
|
||||
************************************************************************/
|
||||
#include "delay.h"
|
||||
|
||||
//延时驱动C 文件
|
||||
|
||||
/***********************************************************************************************
|
||||
功能:初始化延时模块
|
||||
形参:0
|
||||
返回:0
|
||||
详解:此函数用于初始化延时模块,使用函数时必须调用。否则会造成延时函数出错
|
||||
************************************************************************************************/
|
||||
void DelayInit(void)
|
||||
{
|
||||
SysTick->CTRL = 0;//选取systick的时钟为内核时钟/16
|
||||
}
|
||||
/***********************************************************************************************
|
||||
功能:US级延时函数
|
||||
形参:US 需要延时多少US
|
||||
返回:0
|
||||
详解:裸机下的延时US
|
||||
************************************************************************************************/
|
||||
void DelayUs(uint32_t us)
|
||||
{
|
||||
uint32_t temp;
|
||||
SysTick->LOAD = (us*BUS_CLK_HZ/10000)/(1600); //时间加载
|
||||
SysTick->VAL = 0x00; //清空计数器
|
||||
SysTick->CTRL |= 0x01 ; //开始倒数
|
||||
do
|
||||
{
|
||||
temp = SysTick->CTRL;
|
||||
}while(temp & 0x01 && !(temp & (1<<16))); //等待时间到达
|
||||
SysTick->CTRL &= ~0x01; //关闭计数器
|
||||
}
|
||||
/***********************************************************************************************
|
||||
功能:MS级延时函数
|
||||
形参:MS需要延时多少MS
|
||||
返回:0
|
||||
详解:裸机下的延时MS
|
||||
************************************************************************************************/
|
||||
void DelayMs(uint32_t ms)
|
||||
{
|
||||
uint32_t temp;
|
||||
uint16_t i;
|
||||
for(i = 0;i < ms;i++) //延时 MS
|
||||
{
|
||||
SysTick->LOAD = (BUS_CLK_HZ/1000)/16; //时间加载1ms
|
||||
SysTick->VAL = 0x00; //清空计数器
|
||||
SysTick->CTRL |= 0x01; //开始倒数
|
||||
do
|
||||
{
|
||||
temp = SysTick->CTRL;
|
||||
}while(temp & 0x01 && !(temp & (1<<16))); //等待时间到达
|
||||
SysTick->CTRL &= ~0x01; //关闭计数器
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#ifndef __DELAY_H__
|
||||
#define __DELAY_H__
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include "sysinit.h"
|
||||
#include "common.h"
|
||||
#include "core_cm0plus.h"
|
||||
//本构件实现的接口函数列表
|
||||
void DelayInit(void); //延时初始化
|
||||
void DelayUs(uint32_t us); //延时us
|
||||
void DelayMs(uint32_t ms); //延时ms
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,270 @@
|
||||
/*****************************************************************************!
|
||||
* 技术讨论:QQ群 123763203
|
||||
* 官网 :www.navota.com
|
||||
*
|
||||
* @file eeprom.c
|
||||
* @brief flash模拟eeprom库函数
|
||||
* @author Navota
|
||||
* @date 2018-1-1
|
||||
***************************************************************************/
|
||||
#include "flash.h"
|
||||
#include "eeprom.h"
|
||||
#include <string.h>
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* EEPROM 擦除命令,擦掉eeprom
|
||||
*输入参数:地址,函数将会擦除adr所在的扇区(512字节)
|
||||
*
|
||||
******************************************************************************/
|
||||
uint16_t Adress_Js(uint32_t adr)
|
||||
{
|
||||
uint16_t err = EEPROM_ERR_SUCCESS;
|
||||
|
||||
if (adr & 0x03)
|
||||
{
|
||||
err = EEPROM_ERR_INVALID_PARAM;
|
||||
return (err);
|
||||
}
|
||||
|
||||
if (adr > 1024)
|
||||
{
|
||||
err = EEPROM_ADR_OverFlow;
|
||||
return (err);
|
||||
}
|
||||
return (err);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* EEPROM 擦除命令,擦掉eeprom
|
||||
*输入参数:地址,函数将会擦除adr所在的512bytes eeprom
|
||||
*
|
||||
******************************************************************************/
|
||||
uint16_t EEPROM_Erase(uint32_t adr)
|
||||
{
|
||||
uint16_t err = EEPROM_ERR_SUCCESS;
|
||||
uint32_t e_adr;
|
||||
|
||||
if (adr & 0x03)
|
||||
{
|
||||
err = EEPROM_ERR_INVALID_PARAM;
|
||||
return (err);
|
||||
}
|
||||
|
||||
if (adr > 1024)
|
||||
{
|
||||
err = EEPROM_ADR_OverFlow;
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
||||
e_adr = adr + EEPROM_START_ADR;
|
||||
err = Flash_EraseSector(e_adr);
|
||||
return (err);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* EEPROM 读取函数,读取地址所在的eeprom
|
||||
*输入参数:地址
|
||||
*
|
||||
******************************************************************************/
|
||||
uint32_t EEPROM_Read(uint32_t adr)
|
||||
{
|
||||
uint16_t err = EEPROM_ERR_SUCCESS;
|
||||
uint32_t e_adr;
|
||||
uint32_t data;
|
||||
|
||||
if (adr & 0x03)
|
||||
{
|
||||
err = EEPROM_ERR_INVALID_PARAM;
|
||||
return (err);
|
||||
}
|
||||
|
||||
if (adr > 1024)
|
||||
{
|
||||
err = EEPROM_ADR_OverFlow;
|
||||
return (err);
|
||||
}
|
||||
|
||||
e_adr = adr + EEPROM_START_ADR;
|
||||
data = M32(e_adr);
|
||||
return (data);
|
||||
}
|
||||
/******************************************************************************
|
||||
*
|
||||
* EEPROM 写函数,写地址所在的eeprom
|
||||
* 写之前读取出来,判断eeprom是否为空,如果为空,则直接写
|
||||
* 如果非空,则先把整个512bytes sector读取到sram,修改要写的位置
|
||||
* 然后再写入到flash,模拟一个eeprom的写过程
|
||||
* 输入参数:地址
|
||||
*
|
||||
******************************************************************************/
|
||||
uint16_t EEPROM_Write(uint32_t adr, uint32_t Data)
|
||||
{
|
||||
|
||||
uint32_t err = EEPROM_ERR_SUCCESS;
|
||||
uint32_t e_adr;
|
||||
uint32_t r_data;
|
||||
uint16_t i;
|
||||
uint32_t start_adr;
|
||||
// uint32_t modify_adr;
|
||||
uint32_t EEPROM_DATA[128];
|
||||
|
||||
if (adr & 0x03)
|
||||
{
|
||||
err = EEPROM_ERR_INVALID_PARAM;
|
||||
return (err);
|
||||
}
|
||||
|
||||
if (adr > 1024)
|
||||
{
|
||||
err = EEPROM_ADR_OverFlow;
|
||||
return (err);
|
||||
}
|
||||
|
||||
r_data = EEPROM_Read(adr);
|
||||
|
||||
e_adr = adr + EEPROM_START_ADR;
|
||||
|
||||
if (r_data == EEPROM_BLANK) //如果要写的位置是空的,则直接写
|
||||
{
|
||||
err = Flash_Program1LongWord(e_adr, Data);
|
||||
}
|
||||
else if ((r_data & Data) == Data) //如果要写的位置对应的bit,和要写的数据一致,或者是1,也是可以直接写
|
||||
{
|
||||
err = Flash_Program1LongWord(e_adr, Data);
|
||||
}
|
||||
else if (r_data == Data) //如果要写的数据和现有的数据一致,就不进行任何操作,直接返回
|
||||
{
|
||||
return (err);
|
||||
}
|
||||
else
|
||||
{
|
||||
start_adr = e_adr & EEPROM_SECTOR_MASK; //计算出sector的头地址
|
||||
|
||||
for (i = 0; i < 128; i++) //如果要写的位置不为空,则先把flash内容读取出来,放在sram中,修改
|
||||
{
|
||||
EEPROM_DATA[i] = M32(start_adr + 4 * i);
|
||||
}
|
||||
|
||||
EEPROM_DATA[(adr & EEPROM_ARRAY_ADR_MASK) >> 2] = Data; //修改SRAM 中的数据
|
||||
|
||||
err = EEPROM_Erase(adr);
|
||||
|
||||
err = Flash_Program(start_adr, (uint8_t *)EEPROM_DATA, 512); //然后写入flash
|
||||
}
|
||||
return (err);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
*Byte 写函数
|
||||
*
|
||||
******************************************************************************/
|
||||
uint16_t EEPROM_WriteByte(uint32_t adr, uint8_t Data)
|
||||
{
|
||||
uint32_t err = EEPROM_ERR_SUCCESS;
|
||||
uint32_t data_mask;
|
||||
uint32_t r_data;
|
||||
uint32_t data_m0;
|
||||
uint32_t data_m1;
|
||||
uint32_t word_adr = adr & 0x3fc;
|
||||
uint32_t b_sit = adr & 0x3;
|
||||
|
||||
//先让高位为FF
|
||||
data_m0 = Data << b_sit * 8;
|
||||
data_mask = 0xFFFFFFFF << (b_sit + 1) * 8;
|
||||
//然后让低位为FF
|
||||
data_m1 = 0xFFFFFFFF >> (32 - b_sit * 8);
|
||||
data_m1 = data_m1 | data_m0 | data_mask;
|
||||
|
||||
r_data = EEPROM_Read(word_adr);
|
||||
r_data |= 0xFF << b_sit * 8;
|
||||
|
||||
data_m1 = data_m1 & r_data;
|
||||
|
||||
err = EEPROM_Write(word_adr, data_m1);
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
*Byte 读函数
|
||||
*
|
||||
******************************************************************************/
|
||||
uint8_t EEPROM_ReadByte(uint32_t adr)
|
||||
{
|
||||
uint32_t r_data;
|
||||
uint32_t word_adr = adr & 0x3fc;
|
||||
uint32_t b_sit = adr & 0x3;
|
||||
uint8_t data;
|
||||
|
||||
r_data = EEPROM_Read(word_adr);
|
||||
data = (r_data >> b_sit * 8) & 0xff;
|
||||
return (data);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
*写函数,写一个长度为bytesize,到eeprom
|
||||
*先把1k的eeprom读取放入sram,然后修改要写的位置,
|
||||
*这个函数是还可以再优化的
|
||||
******************************************************************************/
|
||||
uint16_t EERPOM_Writeup4byte(uint32_t adr, uint8_t *pData, uint32_t length)
|
||||
{
|
||||
uint8_t buf[512];
|
||||
uint8_t *pbuf;
|
||||
uint32_t e_adr;
|
||||
uint32_t e_sec;
|
||||
uint32_t e_offset;
|
||||
uint32_t a;
|
||||
uint32_t err = EEPROM_ERR_SUCCESS;
|
||||
|
||||
#ifdef IAR
|
||||
if (adr & 0x03)
|
||||
{
|
||||
err = EEPROM_ERR_INVALID_PARAM;
|
||||
return (err);
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((adr + length) > 1024)
|
||||
{
|
||||
err = EEPROM_ADR_OverFlow;
|
||||
return (err);
|
||||
}
|
||||
|
||||
e_adr = adr + EEPROM_START_ADR;
|
||||
e_sec = e_adr & EEPROM_SECTOR_MASK;
|
||||
e_offset = e_adr & 0x1ff;
|
||||
|
||||
while (length > 0)
|
||||
{
|
||||
//如果起始地址不等于0,或者长度小于512 都进入这个循环
|
||||
if (e_offset || (length < 512))
|
||||
{
|
||||
pbuf = buf;
|
||||
a = 512 - e_offset;
|
||||
a = (length > a ? a : length);
|
||||
|
||||
memcpy(buf, (uint8_t *)e_sec, 512);
|
||||
memcpy(&buf[e_offset], pData, a);
|
||||
pData += a;
|
||||
length -= a;
|
||||
e_offset = 0;
|
||||
}
|
||||
else
|
||||
{ //如果起始地址等于0且长度大于512
|
||||
pbuf = pData;
|
||||
pData += 512;
|
||||
length -= 512;
|
||||
}
|
||||
err = Flash_EraseSector(e_sec);
|
||||
err = Flash_Program(e_sec, (uint8_t *)pbuf, 512); //然后写入flash
|
||||
e_sec += 0x200;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief eeprom Çý¶¯Í·Îļþ.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef EEPROM_H_
|
||||
#define EEPROM_H_
|
||||
|
||||
/******************************************************************************
|
||||
* Includes
|
||||
******************************************************************************/
|
||||
#include "common.h"
|
||||
|
||||
#define EERPOM_SIZE 1024 // in bytes
|
||||
#define EEPROM_START_ADR 0x00401000
|
||||
#define EEPROM_ERR_SUCCESS 0x01
|
||||
#define EEPROM_ADR_OverFlow 0x02
|
||||
#define EEPROM_ERR_INVALID_PARAM 0x04
|
||||
#define EEPROM_BLANK 0xffffffff
|
||||
#define EEPROM_SECTOR_MASK 0x00401200
|
||||
#define EEPROM_ARRAY_ADR_MASK 0x1ff
|
||||
|
||||
|
||||
uint16_t Adress_Js(uint32_t adr);
|
||||
uint16_t EEPROM_Erase(uint32_t adr);
|
||||
uint32_t EEPROM_Read(uint32_t adr);
|
||||
uint8_t EEPROM_ReadByte(uint32_t adr);
|
||||
|
||||
|
||||
uint16_t EEPROM_Write(uint32_t adr, uint32_t Data);
|
||||
uint16_t EEPROM_WriteByte(uint32_t adr, uint8_t Data);
|
||||
uint16_t EERPOM_Writeup4byte(uint32_t adr, uint8_t *pData,uint32_t length);
|
||||
#endif
|
||||
@@ -0,0 +1,852 @@
|
||||
/*****************************************************************************!
|
||||
* 技术讨论:QQ群 123763203
|
||||
* 官网 :www.navota.com
|
||||
*
|
||||
* @file etm.c
|
||||
* @brief etm定时器函数库
|
||||
* @author Navota
|
||||
* @date 2018-3-1
|
||||
***************************************************************************/
|
||||
|
||||
#include "common.h"
|
||||
#include "etm.h"
|
||||
|
||||
|
||||
/*!
|
||||
* @brief 存放回调入口
|
||||
*
|
||||
*/
|
||||
ETM_CallbackPtr ETM_Callback[3] = {(ETM_CallbackPtr)NULL};
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* 定义ETM的接口函数
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************//*!
|
||||
*
|
||||
* @brief 设置ETM模块时钟资源及分频系数.
|
||||
*
|
||||
* @param[in] pETM 指向三个ETM定时器其中一个的基址.
|
||||
* @param[in] ClockSource ETM 选择的时钟源 : 禁用(ETM_CLOCK_NOCLOCK)、系统时钟(ETM_CLOCK_SYSTEMCLOCK)、固定频率时钟/2(ETM_CLOCK_FIXEDFREQCLOCK)、外接时钟(ETM_CLOCK_EXTERNALCLOCK).
|
||||
* @param[in] ClockPrescale 分频系数.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*********************************************************************************/
|
||||
void ETM_ClockSet(ETM_Type *pETM, uint8_t u8ClockSource, uint8_t u8ClockPrescale)
|
||||
{
|
||||
uint8_t u8Temp;
|
||||
u8Temp = (pETM->SC & 0xE0);//pETM指向的SC寄存器低5位清0,即未选择时钟,时钟输入采取1分频
|
||||
u8Temp |= (ETM_SC_CLKS(u8ClockSource & 0x3) | ETM_SC_PS(u8ClockPrescale & 0x7));
|
||||
pETM->SC = u8Temp;//配置该ETM的状态与控制寄存器ETMx_SC
|
||||
}
|
||||
|
||||
/*********************************************************************************//*!
|
||||
*
|
||||
* @brief ETM中PWM的初始化函数
|
||||
*
|
||||
* @param[in] pETM 指向三个ETM定时器其中一个的基址.
|
||||
* @param[in] PWMModeSelect 居中对齐CPWM(10)、边沿对齐EPWM(01)以及级联模式PWM(11).
|
||||
* @param[in] PWMEdgeSelect 高真脉冲(01)、低真脉冲(10).
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*********************************************************************************/
|
||||
void ETM_PWMInit(ETM_Type *pETM, uint8_t u8PWMModeSelect, uint8_t u8PWMEdgeSelect)
|
||||
{
|
||||
uint8_t channels, i;
|
||||
|
||||
ASSERT((ETM0== pETM) || (ETM1== pETM) || (ETM2== pETM));//断言来检测ETM通道是否正确
|
||||
|
||||
/* 选用ETM时钟 */
|
||||
if (ETM0 == pETM)
|
||||
{
|
||||
channels = 2;
|
||||
SIM->SCGC |= SIM_SCGC_ETM0_MASK; //ETM0共有两个通道
|
||||
}
|
||||
else if(ETM1 == pETM)
|
||||
{
|
||||
channels = 2;
|
||||
SIM->SCGC |= SIM_SCGC_ETM1_MASK; //ETM1共有两个通道
|
||||
}
|
||||
else
|
||||
{
|
||||
channels = 6;
|
||||
SIM->SCGC |= SIM_SCGC_ETM2_MASK; //ETM2共有六个通道
|
||||
}
|
||||
|
||||
pETM->SC = 0x0; //关闭计数器
|
||||
pETM->MOD = ETM_MOD_INIT;
|
||||
|
||||
if(ETM_PWMMODE_CENTERALLIGNED == u8PWMModeSelect) //打开CPWM
|
||||
{
|
||||
pETM->SC |= ETM_SC_CPWMS_MASK;
|
||||
}
|
||||
else if(ETM_PWMMODE_COMBINE == u8PWMModeSelect)
|
||||
{
|
||||
ASSERT(ETM2 == pETM);
|
||||
pETM->MODE |= ETM_MODE_WPDIS_MASK | ETM_MODE_ETMEN_MASK;
|
||||
pETM->COMBINE = ETM_COMBINE_COMBINE0_MASK | ETM_COMBINE_COMP0_MASK | ETM_COMBINE_SYNCEN0_MASK | ETM_COMBINE_DTEN0_MASK |
|
||||
ETM_COMBINE_COMBINE1_MASK | ETM_COMBINE_COMP1_MASK | ETM_COMBINE_SYNCEN1_MASK | ETM_COMBINE_DTEN1_MASK |
|
||||
ETM_COMBINE_COMBINE2_MASK | ETM_COMBINE_COMP2_MASK | ETM_COMBINE_SYNCEN2_MASK | ETM_COMBINE_DTEN2_MASK
|
||||
; // 打开通道级联模式
|
||||
pETM->SC &= ~ETM_SC_CPWMS_MASK;
|
||||
}
|
||||
if(ETM_PWM_HIGHTRUEPULSE == u8PWMEdgeSelect)
|
||||
{
|
||||
/* 配置通道寄存器,设置通道状态及通道计数值 */
|
||||
for(i=0; i<channels; i++)
|
||||
{
|
||||
pETM->CONTROLS[i].CnSC = ETM_CnSC_MSB_MASK | ETM_CnSC_ELSB_MASK;
|
||||
pETM->CONTROLS[i].CnV = ETM_C0V_INIT + i*100;
|
||||
}
|
||||
}
|
||||
else if(ETM_PWM_LOWTRUEPULSE == u8PWMEdgeSelect)
|
||||
{
|
||||
for(i=0; i<channels; i++)
|
||||
{
|
||||
pETM->CONTROLS[i].CnSC = ETM_CnSC_MSB_MASK | ETM_CnSC_ELSA_MASK;
|
||||
pETM->CONTROLS[i].CnV = ETM_C0V_INIT + i*100 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用ETM的通道功能,用于GPIO或其他功能
|
||||
*
|
||||
* @param[in] pETM 指向三个ETM定时器其中一个的基址.
|
||||
* @param[in] u8ETM_Channel 通道号.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*********************************************************************************/
|
||||
|
||||
void ETM_disblechannel(ETM_Type *pETM, uint8_t u8ETM_Channel)
|
||||
{
|
||||
uint8_t i;
|
||||
i= u8ETM_Channel;
|
||||
pETM->CONTROLS[i].CnSC &= ~ (ETM_CnSC_ELSB_MASK| ETM_CnSC_ELSA_MASK);
|
||||
}
|
||||
|
||||
/*********************************************************************************//*!
|
||||
*
|
||||
* @brief 输入捕捉初始化函数.
|
||||
*
|
||||
* @param[in] pETM 指向三个ETM定时器其中一个的基址.
|
||||
* @param[in] Channel 配置通道号.
|
||||
* @param[in] CaptureMode 选择捕捉方式:上升沿, 下降沿或跳变沿.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*********************************************************************************/
|
||||
void ETM_InputCaptureInit(ETM_Type *pETM, uint8_t u8ETM_Channel, uint8_t u8CaptureMode)
|
||||
{
|
||||
ASSERT(((ETM0 == pETM) && (u8ETM_Channel < 2)) ||
|
||||
((ETM1 == pETM) && (u8ETM_Channel < 2)) ||
|
||||
((ETM2 == pETM) && (u8ETM_Channel < 6))
|
||||
);
|
||||
|
||||
|
||||
/* 选用ETM时钟 */
|
||||
if ((ETM0 == pETM) && (u8ETM_Channel < 2))
|
||||
{
|
||||
SIM->SCGC |= SIM_SCGC_ETM0_MASK;
|
||||
NVIC_EnableIRQ(ETM0_IRQn);
|
||||
}
|
||||
else if((ETM1 == pETM) && (u8ETM_Channel < 2))
|
||||
{
|
||||
SIM->SCGC |= SIM_SCGC_ETM1_MASK;
|
||||
NVIC_EnableIRQ(ETM1_IRQn);
|
||||
}
|
||||
else
|
||||
{
|
||||
SIM->SCGC |= SIM_SCGC_ETM2_MASK;
|
||||
NVIC_EnableIRQ(ETM2_IRQn);
|
||||
}
|
||||
|
||||
pETM->SC = 0x0; //关闭计数器
|
||||
pETM->MOD = 0xFFFF;
|
||||
|
||||
if(ETM_INPUTCAPTURE_RISINGEDGE == u8CaptureMode) //开启中断,捕获上升沿
|
||||
{
|
||||
pETM->CONTROLS[u8ETM_Channel].CnSC = ETM_CnSC_CHIE_MASK | ETM_CnSC_ELSA_MASK;
|
||||
}
|
||||
else if(ETM_INPUTCAPTURE_FALLINGEDGE == u8CaptureMode) //捕获下降沿
|
||||
{
|
||||
pETM->CONTROLS[u8ETM_Channel].CnSC = ETM_CnSC_CHIE_MASK | ETM_CnSC_ELSB_MASK;
|
||||
}
|
||||
else if(ETM_INPUTCAPTURE_BOTHEDGE == u8CaptureMode) //捕获跳变沿
|
||||
{
|
||||
pETM->CONTROLS[u8ETM_Channel].CnSC = ETM_CnSC_CHIE_MASK | ETM_CnSC_ELSA_MASK | ETM_CnSC_ELSB_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************//*!
|
||||
*
|
||||
* @brief 对ETM配置双边捕获模式来测量一个脉冲的宽度或周期(ETM2).
|
||||
*
|
||||
* @param[in] pETM ETM2.
|
||||
* @param[in] ChannelPair 频道配对数的配置为: 0, 2, 4.
|
||||
* @param[in] CaptureMode 选择单周期捕捉(4),和连续捕捉方式(5).
|
||||
* @param[in] Channel_N_Edge 频道N边沿检测:无(0),上升沿(1)下降沿(2)双沿(3).
|
||||
* @param[in] Channel_Np1_Edge 频道N+1边沿检测.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*********************************************************************************/
|
||||
void ETM_DualEdgeCaptureInit(ETM_Type *pETM, uint8_t u8ChannelPair, uint8_t u8CaptureMode,
|
||||
uint8_t u8Channel_N_Edge, uint8_t u8Channel_Np1_Edge)
|
||||
{
|
||||
ASSERT((ETM2 == pETM) && (u8ChannelPair < 6) && !(u8ChannelPair & 1) );
|
||||
|
||||
SIM->SCGC |= SIM_SCGC_ETM2_MASK;
|
||||
if((0 == u8ChannelPair) || (2== u8ChannelPair))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
pETM->SC = 0x0; /* 关闭计数器 */
|
||||
pETM->MOD = 0xFFFF;
|
||||
pETM->MODE |= ETM_MODE_ETMEN_MASK; /* ETMEN = 1 */
|
||||
|
||||
pETM->COMBINE |= ((ETM_COMBINE_DECAPEN0_MASK) << (u8ChannelPair * 4));
|
||||
|
||||
pETM->CONTROLS[u8ChannelPair].CnSC &= ~ETM_CnSC_CHF_MASK; /* CH(n)F 和 CH(n+1)F 位必须要先清除 */
|
||||
pETM->CONTROLS[u8ChannelPair + 1].CnSC &= ~ETM_CnSC_CHF_MASK;
|
||||
|
||||
if(ETM_INPUTCAPTURE_DUALEDGE_ONESHOT == u8CaptureMode) /* 单次模式 */
|
||||
{
|
||||
pETM->CONTROLS[u8ChannelPair].CnSC &= ~ETM_CnSC_MSA_MASK;
|
||||
pETM->CONTROLS[u8ChannelPair+1].CnSC &= ~ETM_CnSC_MSA_MASK;
|
||||
}
|
||||
else if(ETM_INPUTCAPTURE_DUALEDGE_CONTINUOUS == u8CaptureMode) /* 连续模式 */
|
||||
{
|
||||
pETM->CONTROLS[u8ChannelPair].CnSC |= ETM_CnSC_MSA_MASK;
|
||||
pETM->CONTROLS[u8ChannelPair+1].CnSC |= ETM_CnSC_MSA_MASK;
|
||||
}
|
||||
|
||||
pETM->CONTROLS[u8ChannelPair].CnSC |= (u8Channel_N_Edge << 2); /* 选择检测边沿 */
|
||||
pETM->CONTROLS[u8ChannelPair + 1].CnSC |= (u8Channel_Np1_Edge << 2);
|
||||
|
||||
pETM->COMBINE |= (ETM_COMBINE_DECAP0_MASK << (u8ChannelPair * 4));
|
||||
}
|
||||
|
||||
/*********************************************************************************//*!
|
||||
*
|
||||
* @brief 输出对比初始化.
|
||||
*
|
||||
* @param[in] pETM 指向三个ETM定时器其中一个的基址.
|
||||
* @param[in] Channel 配置通道即通道号.
|
||||
* @param[in] CompareMode 选择模式:翻转(01)、置位(11)、清0(10).
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*********************************************************************************/
|
||||
void ETM_OutputCompareInit(ETM_Type *pETM, uint8_t u8ETM_Channel, uint8_t u8CompareMode)
|
||||
{
|
||||
ASSERT(((ETM0 == pETM) && (u8ETM_Channel < 2)) ||
|
||||
((ETM1 == pETM) && (u8ETM_Channel < 2)) ||
|
||||
((ETM2 == pETM) && (u8ETM_Channel < 6))
|
||||
);
|
||||
|
||||
/* 选用ETM模块时钟 */
|
||||
if(ETM0 == pETM)
|
||||
{
|
||||
SIM->SCGC |= SIM_SCGC_ETM0_MASK;
|
||||
}
|
||||
else if(ETM1 == pETM)
|
||||
{
|
||||
SIM->SCGC |= SIM_SCGC_ETM1_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
SIM->SCGC |= SIM_SCGC_ETM2_MASK;
|
||||
}
|
||||
|
||||
pETM->SC = 0x0; //关闭计数器
|
||||
pETM->MOD = ETM_MOD_INIT;
|
||||
pETM->CONTROLS[u8ETM_Channel].CnSC = (ETM_CnSC_MSA_MASK | (u8CompareMode << 2));
|
||||
pETM->CONTROLS[u8ETM_Channel].CnV = ETM_C0V_INIT;
|
||||
}
|
||||
|
||||
/*********************************************************************************//*!
|
||||
*
|
||||
* @brief 实现软件同步触发(ETM2).
|
||||
*
|
||||
* @param[in] pETM ETM2.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*********************************************************************************/
|
||||
void ETM_SoftwareSync(ETM_Type *pETM)
|
||||
{
|
||||
ASSERT(ETM2 == pETM);
|
||||
|
||||
pETM->SYNCONF |= ETM_SYNCONF_SYNCMODE_MASK;
|
||||
pETM->SYNC |= ETM_SYNC_SWSYNC_MASK;
|
||||
}
|
||||
|
||||
/*********************************************************************************//*!
|
||||
*
|
||||
* @brief ETM中配置ETMx_SYNC 寄存器来选择硬件触发(ETM2).
|
||||
*
|
||||
* @param[in] pETM ETM2.
|
||||
* @param[in] u8TriggerN 选择硬件触发资源.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*********************************************************************************/
|
||||
void ETM_HardwareSync(ETM_Type *pETM, uint8_t u8TriggerN)
|
||||
{
|
||||
ASSERT(ETM2 == pETM);
|
||||
|
||||
pETM->SYNCONF |= ETM_SYNCONF_SYNCMODE_MASK;
|
||||
|
||||
switch(u8TriggerN)
|
||||
{
|
||||
case ETM_SYNC_TRIGGER_TRIGGER2:
|
||||
pETM->SYNC |= ETM_SYNC_TRIG2_MASK;
|
||||
break;
|
||||
case ETM_SYNC_TRIGGER_TRIGGER1:
|
||||
pETM->SYNC |= ETM_SYNC_TRIG1_MASK;
|
||||
break; /* 需要先配置ETM0CH0 */
|
||||
case ETM_SYNC_TRIGGER_TRIGGER0:
|
||||
pETM->SYNC |= ETM_SYNC_TRIG0_MASK;
|
||||
break; /* 需要先配置ACMP0 */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************//*!
|
||||
*
|
||||
* @brief 通过配置ETM保证硬件同步,产生触发(可有多个触发)(ETM2).
|
||||
*
|
||||
* @param[in] pETM ETM2.
|
||||
* @param[in] u8TriggerMask 硬件触发资源标志号.联合TRIG0~TREG2.(x000xxxx~x111xxxx)
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*********************************************************************************/
|
||||
void ETM_HardwareSyncCombine(ETM_Type *pETM, uint8_t u8TriggerMask)
|
||||
{
|
||||
ASSERT(ETM2 == pETM);
|
||||
|
||||
pETM->SYNCONF |= ETM_SYNCONF_SYNCMODE_MASK;
|
||||
pETM->SYNC &= 0x8F;
|
||||
pETM->SYNC |= (u8TriggerMask & 0x70);
|
||||
}
|
||||
|
||||
/*********************************************************************************//*!
|
||||
*
|
||||
* @brief 硬件触发2产生ETM2的PWM同步触发(ETM2)
|
||||
*
|
||||
* @param[in] pETM ETM2.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*********************************************************************************/
|
||||
void ETM_GenerateTrig2(ETM_Type *pETM)
|
||||
{
|
||||
ASSERT(ETM2 == pETM);
|
||||
|
||||
if(pETM->SYNC & ETM_SYNC_TRIG2_MASK)
|
||||
{
|
||||
#if defined(CPU_NV32)
|
||||
SIM->SOPT |= SIM_SOPT_ETMSYNC_MASK;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************************//*!
|
||||
*
|
||||
* @brief ETM死区时间设置(ETM2).
|
||||
*
|
||||
* @param[in] pETM ETM2.
|
||||
* @param[in] PrescalerValue 总线时钟分频值, 0 to 3.
|
||||
* @param[in] DeadETMeValue 时钟数值插入, 0 to 63.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*********************************************************************************/
|
||||
void ETM_PWMDeadETMeSet(ETM_Type *pETM, uint8_t u8PrescalerValue, uint8_t u8DeadETMeValue)
|
||||
{
|
||||
ASSERT(ETM2 == pETM);
|
||||
|
||||
pETM->COMBINE |= 0x101010; /* 使能死区时间插入 */
|
||||
|
||||
if(!(pETM->MODE & ETM_MODE_WPDIS_MASK)) /* 判断是否使能写保护 */
|
||||
{
|
||||
pETM->MODE |= ETM_MODE_WPDIS_MASK; /* 禁止写保护 */
|
||||
pETM->DEADETME = (ETM_DEADETME_DTVAL(u8DeadETMeValue & 0x3F) | ETM_DEADETME_DTPS(u8PrescalerValue & 0x3));
|
||||
pETM->MODE &= ~ETM_MODE_WPDIS_MASK; /* 使能写保护 */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 若无写保护 */
|
||||
pETM->DEADETME = (ETM_DEADETME_DTVAL(u8DeadETMeValue & 0x3F) | ETM_DEADETME_DTPS(u8PrescalerValue & 0x3));
|
||||
}
|
||||
pETM->SYNC |= ETM_SYNC_SWSYNC_MASK; /* 设置软件同步 */
|
||||
}
|
||||
|
||||
/*********************************************************************************//*!
|
||||
*
|
||||
* @brief 设置输出屏蔽(ETM2).
|
||||
*
|
||||
* @param[in] pETM ETM2.
|
||||
* @param[in] Channel 需要屏蔽的通道号.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*********************************************************************************/
|
||||
void ETM_OutputMaskSet(ETM_Type *pETM, uint8_t u8ETM_Channel)
|
||||
{
|
||||
ASSERT((ETM2 == pETM) && (u8ETM_Channel < 6));
|
||||
|
||||
pETM->OUTMASK |= (1 << u8ETM_Channel);
|
||||
|
||||
if(pETM->SYNC & ETM_SYNC_SYNCHOM_MASK) /* 通过PWM同步更新 */
|
||||
{
|
||||
pETM->SYNCONF |= ETM_SYNCONF_SYNCMODE_MASK;
|
||||
if(pETM->SYNCONF & ETM_SYNCONF_SWOM_MASK) /* 软件触发激活 */
|
||||
{
|
||||
pETM->SYNC |= ETM_SYNC_SWSYNC_MASK;
|
||||
}
|
||||
else if(pETM->SYNCONF & ETM_SYNCONF_HWOM_MASK) /* 硬件触发激活 */
|
||||
{
|
||||
pETM->SYNC |= ETM_SYNC_TRIG2_MASK;
|
||||
|
||||
#if defined(CPU_NV32)
|
||||
SIM->SOPT |= SIM_SOPT_ETMSYNC_MASK; /* 使能硬件同步 */
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
}
|
||||
else /* 若无软件同步, 在系统时钟的上升沿对其更新 */
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************//*!
|
||||
*
|
||||
* @brief 配置软件输出控制SWOCTRL寄存器的同步是否由软件触发(ETM2).
|
||||
*
|
||||
* @param[in] pETM ETM2.
|
||||
* @param[in] Channel 软件触发PWM波的通道选择.
|
||||
* @param[in] ChannelValue 0或1,0不触发;1触发.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*********************************************************************************/
|
||||
void ETM_SWOutputControlSet(ETM_Type *pETM, uint8_t u8ETM_Channel, uint8_t u8ChannelValue)
|
||||
{
|
||||
ASSERT((ETM2 == pETM) && (u8ETM_Channel < 6));
|
||||
|
||||
if(ETM_SWOCTRL_HIGH == u8ChannelValue)
|
||||
{
|
||||
pETM->SWOCTRL |= (0x0101 << u8ETM_Channel);
|
||||
}
|
||||
else if(ETM_SWOCTRL_LOW == u8ChannelValue)
|
||||
{
|
||||
pETM->SWOCTRL |= (1 << u8ETM_Channel);
|
||||
pETM->SWOCTRL &= ~(0x100 << u8ETM_Channel);
|
||||
}
|
||||
if(pETM->SYNCONF & ETM_SYNCONF_SWOC_MASK)
|
||||
{
|
||||
pETM->SYNCONF |= ETM_SYNCONF_SYNCMODE_MASK;
|
||||
if(pETM->SYNCONF & ETM_SYNCONF_SWSOC_MASK)
|
||||
{
|
||||
pETM->SYNC |= ETM_SYNC_SWSYNC_MASK;
|
||||
}
|
||||
else if(pETM->SYNCONF & ETM_SYNCONF_HWSOC_MASK)
|
||||
{
|
||||
pETM->SYNC |= ETM_SYNC_TRIG2_MASK;
|
||||
|
||||
#if defined(CPU_NV32)
|
||||
SIM->SOPT |= SIM_SOPT_ETMSYNC_MASK;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************//*!
|
||||
*
|
||||
* @brief 设置通道输出极性(ETM2).
|
||||
*
|
||||
* @param[in] pETM ETM2.
|
||||
* @param[in] Channel PWM波的通道选择.
|
||||
* @param[in] ActiveValue 极性的选择,0为高电平,1为低电平.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*********************************************************************************/
|
||||
void ETM_PolaritySet(ETM_Type *pETM, uint8_t u8ETM_Channel, uint8_t u8ActiveValue)
|
||||
{
|
||||
ASSERT((ETM2 == pETM) && (u8ETM_Channel < 6));
|
||||
|
||||
if(ETM_POLARITY_HIGHACTIVE == u8ActiveValue)
|
||||
{
|
||||
pETM->POL &= ~(1 << u8ETM_Channel);
|
||||
}
|
||||
else if(ETM_POLARITY_LOWACTIVE == u8ActiveValue)
|
||||
{
|
||||
pETM->POL |= (1 << u8ETM_Channel);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************//*!
|
||||
*
|
||||
* @brief 设置ETM模块在debug模式下的行为(ETM2).
|
||||
*
|
||||
* @param[in] pETM ETM2.
|
||||
* @param[in] u8DebugMode debug 的模式从00-11之间选择.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*********************************************************************************/
|
||||
void ETM_SetDebugModeBehavior(ETM_Type *pETM, uint8_t u8DebugMode)
|
||||
{
|
||||
ASSERT((ETM2 == pETM));
|
||||
pETM->CONF &= ~ETM_CONF_BDMMODE_MASK;
|
||||
pETM->CONF |= ETM_CONF_BDMMODE(u8DebugMode);
|
||||
}
|
||||
|
||||
/*********************************************************************************//*!
|
||||
*
|
||||
* @brief ETM中TOF频率大小的设置(ETM2).
|
||||
*
|
||||
* @param[in] pETM ETM2.
|
||||
* @param[in] u8TOFNUM TOF频率数,大小0和31之间.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*********************************************************************************/
|
||||
void ETM_SetTOFFrequency(ETM_Type *pETM, uint8_t u8TOFNUM)
|
||||
{
|
||||
ASSERT((ETM2 == pETM));
|
||||
pETM->CONF &= ~ETM_CONF_NUMTOF_MASK;
|
||||
pETM->CONF |= ETM_CONF_NUMTOF(u8TOFNUM);
|
||||
}
|
||||
|
||||
/*********************************************************************************//*!
|
||||
*
|
||||
* @brief 交换通道CH(n)和通道CH(n+1)的输出结果(ETM2).
|
||||
*
|
||||
* @param[in] pETM ETM2.
|
||||
* @param[in] ChannelPair 要被交换的通道数号,即n可为0,1,2.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*********************************************************************************/
|
||||
void ETM_InvertChannel(ETM_Type *pETM, uint8_t u8ChannelPair)
|
||||
{
|
||||
ASSERT((ETM2 == pETM) && u8ChannelPair <= 2);
|
||||
|
||||
pETM->INVCTRL |= 1<<u8ChannelPair;
|
||||
if(pETM->SYNCONF & ETM_SYNCONF_INVC_MASK)
|
||||
{
|
||||
pETM->SYNCONF |= ETM_SYNCONF_SYNCMODE_MASK;
|
||||
if(pETM->SYNCONF & ETM_SYNCONF_SWINVC_MASK)
|
||||
{
|
||||
pETM->SYNC |= ETM_SYNC_SWSYNC_MASK;
|
||||
}
|
||||
else if(pETM->SYNCONF & ETM_SYNCONF_HWINVC_MASK)
|
||||
{
|
||||
pETM->SYNC |= ETM_SYNC_TRIG2_MASK;
|
||||
|
||||
#if defined(CPU_NV32)
|
||||
SIM->SOPT |= SIM_SOPT_ETMSYNC_MASK;
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief ETM模块初始化函数.
|
||||
*
|
||||
* @param[in] pETM 指向三个ETM定时器其中一个的基址.
|
||||
* @param[in] pConfig 配置ETM模块的结构体.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ETM_Init(ETM_Type *pETM, ETM_ConfigType *pConfig)
|
||||
{
|
||||
ASSERT((ETM0 == pETM) || (ETM1 == pETM) || (ETM2 == pETM));
|
||||
if(ETM0 == pETM)
|
||||
{
|
||||
SIM->SCGC |= SIM_SCGC_ETM0_MASK;
|
||||
}
|
||||
else if(ETM1 == pETM)
|
||||
{
|
||||
SIM->SCGC |= SIM_SCGC_ETM1_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
SIM->SCGC |= SIM_SCGC_ETM2_MASK;
|
||||
}
|
||||
|
||||
/*关闭计数器*/
|
||||
pETM->SC = 0;
|
||||
pETM->MODE = pConfig->mode;
|
||||
pETM->MOD = pConfig->modulo;
|
||||
pETM->CNT = pConfig->cnt;
|
||||
|
||||
if( pETM->MODE & ETM_MODE_ETMEN_MASK )
|
||||
{
|
||||
/* 当 ETMEN = 1时, 下列寄存器可以写入 */
|
||||
pETM->COMBINE = pConfig->combine;
|
||||
pETM->CNTIN = pConfig->cntin;
|
||||
pETM->SYNC = pConfig->sync;
|
||||
pETM->OUTINIT = pConfig->outinit;
|
||||
pETM->OUTMASK = pConfig->outmask;
|
||||
pETM->DEADETME = pConfig->deadETMe;
|
||||
pETM->EXTTRIG = pConfig->exttrig;
|
||||
pETM->POL = pConfig->pol;
|
||||
pETM->FMS = pConfig->fms;
|
||||
pETM->FILTER = pConfig->filter;
|
||||
pETM->FLTCTRL = pConfig->fltctrl;
|
||||
pETM->FLTPOL = pConfig->fltpol;
|
||||
pETM->CONF = pConfig->conf;
|
||||
pETM->SYNCONF = pConfig->synconf;
|
||||
pETM->SWOCTRL = pConfig->swoctrl;
|
||||
pETM->PWMLOAD = pConfig->pwmload;
|
||||
}
|
||||
/* 写入状态控制寄存器来使能时钟*/
|
||||
pETM->SC = pConfig->sc;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 复位ETM模块.
|
||||
*
|
||||
* @param[in] pETM 指向三个ETM定时器其中一个的基址.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ETM_DeInit(ETM_Type *pETM)
|
||||
{
|
||||
ASSERT((ETM0 == pETM) || (ETM1 == pETM) || (ETM2 == pETM));
|
||||
pETM->SC = 0;
|
||||
pETM->MOD = 0;
|
||||
pETM->CNT = 0;
|
||||
if(ETM2 == pETM)
|
||||
{
|
||||
pETM->MODE = 0x4;
|
||||
pETM->COMBINE = 0;
|
||||
pETM->CNTIN = 0;
|
||||
pETM->SYNC = 0;
|
||||
pETM->OUTINIT = 0;
|
||||
pETM->OUTMASK = 0;
|
||||
pETM->DEADETME = 0;
|
||||
pETM->EXTTRIG = 0;
|
||||
pETM->POL = 0;
|
||||
pETM->FMS = 0;
|
||||
pETM->FILTER = 0;
|
||||
pETM->FLTCTRL = 0;
|
||||
pETM->FLTPOL = 0;
|
||||
pETM->CONF = 0;
|
||||
pETM->SYNCONF = 0;
|
||||
pETM->SWOCTRL = 0;
|
||||
pETM->PWMLOAD = 0;
|
||||
}
|
||||
/* 禁止ETM模块的时钟 */
|
||||
if (ETM0 == pETM)
|
||||
{
|
||||
SIM->SCGC &= ~SIM_SCGC_ETM0_MASK;
|
||||
NVIC_DisableIRQ(ETM0_IRQn);
|
||||
}
|
||||
else if(ETM1 == pETM)
|
||||
{
|
||||
SIM->SCGC &= ~SIM_SCGC_ETM1_MASK;
|
||||
NVIC_DisableIRQ(ETM1_IRQn);
|
||||
}
|
||||
else if (ETM2 == pETM)
|
||||
{
|
||||
SIM->SCGC &= ~SIM_SCGC_ETM2_MASK;
|
||||
NVIC_DisableIRQ(ETM2_IRQn);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 配置ETM通道, 包括通道状态及控制寄存器CnSC和通道计数值寄存器CnV.
|
||||
*
|
||||
* @param[in] pETM 指向三个ETM定时器其中一个的基址.
|
||||
* @param[in] ETM_Channel ETM的通道号.
|
||||
* @param[in] pTETMCH_Params 配置ETM通道参数的结构体.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ETM_ChannelInit(ETM_Type *pETM, uint8_t u8ETM_Channel, ETM_ChParamsType *pTETMCH_Params)
|
||||
{
|
||||
ASSERT((ETM0 == pETM) || (ETM1 == pETM) || (ETM2 == pETM)); //断言检测通道的正确性
|
||||
|
||||
if (ETM0 == pETM)
|
||||
{
|
||||
ASSERT(u8ETM_Channel < 2);
|
||||
SIM->SCGC |= SIM_SCGC_ETM0_MASK;
|
||||
}
|
||||
else if(ETM1 == pETM)
|
||||
{
|
||||
ASSERT(u8ETM_Channel < 2);
|
||||
SIM->SCGC |= SIM_SCGC_ETM1_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(u8ETM_Channel < 6);
|
||||
SIM->SCGC |= SIM_SCGC_ETM2_MASK;
|
||||
}
|
||||
|
||||
pETM->CONTROLS[u8ETM_Channel].CnSC = pTETMCH_Params->u8CnSC;
|
||||
pETM->CONTROLS[u8ETM_Channel].CnV = pTETMCH_Params->u16CnV;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 配置级联模式及占空比(ETM2).
|
||||
*
|
||||
* @param[in] pETM ETM2.
|
||||
* @param[in] ETM_Channel 奇通道数:1、3、5.
|
||||
* @param[in] dutyCycle 设置占空比,若DutyCycle为10,那么占空比就为10%.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ETM_SetDutyCycleCombine(ETM_Type *pETM, uint8_t u8ETM_Channel, uint8_t u8DutyCycle)
|
||||
{
|
||||
uint16_t cnv = pETM->CONTROLS[u8ETM_Channel-1].CnV;
|
||||
uint16_t modulo = pETM->MOD;
|
||||
|
||||
ASSERT((1 == u8ETM_Channel) || (3 == u8ETM_Channel) || (5 == u8ETM_Channel));
|
||||
|
||||
cnv += (u8DutyCycle * (modulo+1)) / 100;
|
||||
if(cnv > modulo)
|
||||
{
|
||||
cnv = modulo - 1;
|
||||
}
|
||||
pETM->CONTROLS[u8ETM_Channel].CnV = cnv ;
|
||||
|
||||
pETM->PWMLOAD |= ETM_PWMLOAD_LDOK_MASK | (1<<u8ETM_Channel);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 配置寄存器 ETMx_SYNCONF部分位置位,其中里面包含了软件输出的控制是否由硬件触发HW或是否有软件出发SW(ETM2)
|
||||
*
|
||||
* @param[in] pETM ETM2.
|
||||
* @param[in] u32ConfigValue 用来配置SYNCONF寄存器.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ETM_SyncConfigActivate(ETM_Type *pETM, uint32_t u32ConfigValue)
|
||||
{
|
||||
ASSERT((ETM2 == pETM));
|
||||
pETM->SYNCONF |= u32ConfigValue;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 配置寄存器 ETMx_SYNCONF部分位清除,其中里面包含了软件输出的控制是否由硬件触发HW或是否有软件出发SW(ETM2)
|
||||
*
|
||||
* @param[in] pETM ETM2.
|
||||
* @param[in] u32ConfigValue 用来配置SYNCONF寄存器.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ETM_SyncConfigDeactivate(ETM_Type *pETM, uint32_t u32ConfigValue)
|
||||
{
|
||||
ASSERT((ETM2 == pETM));
|
||||
pETM->SYNCONF &= ~u32ConfigValue;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置回调函数入口.
|
||||
*
|
||||
* @param[in] pETM 指向三个ETM定时器其中一个的基址.
|
||||
* @param[in] pfnCallback 回调函数地址.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ETM_SetCallback(ETM_Type *pETM, ETM_CallbackPtr pfnCallback)
|
||||
{
|
||||
ETM_Callback[((uint32_t)pETM - (uint32_t)ETM0_BASE)>>12] = pfnCallback;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief ETM0通道中断服务函数.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ETM0_Isr(void)
|
||||
{
|
||||
if(ETM_Callback[0])
|
||||
{
|
||||
ETM_Callback[0]();
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief ETM1通道中断服务函数.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ETM1_Isr(void)
|
||||
{
|
||||
if(ETM_Callback[1])
|
||||
{
|
||||
ETM_Callback[1]();
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief ETM2通道中断服务函数.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void ETM2_Isr(void)
|
||||
{
|
||||
if(ETM_Callback[2])
|
||||
{
|
||||
ETM_Callback[2]();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,376 @@
|
||||
/**************************************************************************!
|
||||
* 技术讨论:QQ群 123763203
|
||||
* 官网 :www.navota.com
|
||||
*
|
||||
* @file gpio.c
|
||||
* @brief 通用输入输出模块(GPIO)函数库
|
||||
* @author Navota
|
||||
* @date 2018-3-1
|
||||
**************************************************************************/
|
||||
#include "gpio.h"
|
||||
|
||||
//GPIOA | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
|
||||
// Px | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | C7 | C6 | C5 | C4 | C3 | C2 | C1 | C0 | B7 | B6 | B5 | B4 | B3 | B2 | B1 | B0 | A7 | A6 | A5 | A4 | A3 | A2 | A1 | A0 |
|
||||
|
||||
//GPIOB | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
|
||||
// Px | H7 | H6 | -- | -- | -- | H2 | H1 | H0 | -- | -- | -- | -- | G3 | G2 | G1 | C0 | F7 | F6 | F5 | F4 | F3 | F2 | F1 | F0 | E7 | E6 | E5 | E4 | E3 | E2 | E1 | E0 |
|
||||
|
||||
/*****************************************************************************/ /*!
|
||||
* @brief 复位GPIO模块.
|
||||
*
|
||||
* @param[in] pGPIO GPIOA/GPIOB.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void GPIO_DeInit(GPIO_Type *pGPIO)
|
||||
{
|
||||
/* Sanity check */
|
||||
#if defined(CPU_NV32)
|
||||
ASSERT((pGPIO == GPIOA) || (pGPIO == GPIOB));
|
||||
#endif
|
||||
pGPIO->PCOR = 0x00000000; /* 端口清零输出寄存器 */
|
||||
pGPIO->PDDR = 0x00000000; /* 端口数据方向寄存器 */
|
||||
//pGPIO->PDIR = 0x00000000; /* 端口数据输入寄存器 */
|
||||
pGPIO->PDOR = 0x00000000; /* 端口数据输出寄存器 */
|
||||
pGPIO->PIDR = 0xFFFFFFFF; /* 端口输入禁用寄存器 */
|
||||
pGPIO->PSOR = 0x00000000; /* 端口置位输出寄存器 */
|
||||
pGPIO->PTOR = 0x00000000; /* 端口切换输出寄存器 */
|
||||
}
|
||||
|
||||
/*****************************************************************************/ /*!
|
||||
* @brief 初始化GPIO引脚属性
|
||||
*
|
||||
* @param[in] pGPIO GPIOA/GPIOB.
|
||||
* @param[in] u32PinMask 32位引脚掩码(GPIO_PTA0_MASK, GPIO_PTA1_MASK...)
|
||||
* @param[in] sGpioType 引脚属性(输入GPIO_PinInput、输出GPIO_PinOutput、输出高电流驱动GPIO_PinOutput_HighCurrent、输入并开启上拉GPIO_PinInput_InternalPullup)
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @ 注:
|
||||
* . 如果引脚配置为输入,禁用高电流驱动
|
||||
* . 如果引脚配置为输出,禁用内部上拉,内部上拉仅为输入模式使用
|
||||
* 仅PTH1/0, PTE1/0, PTD1/0, PTB5/4 支持高电流驱动.
|
||||
*****************************************************************************/
|
||||
void GPIO_Init(GPIO_Type *pGPIO, uint32_t u32PinMask, GPIO_PinConfigType sGpioType)
|
||||
{
|
||||
ASSERT((pGPIO == GPIOA) || (pGPIO == GPIOB));
|
||||
|
||||
/* 配置GPIO为输入或者输出 */
|
||||
if ((sGpioType == GPIO_PinOutput) || (sGpioType == GPIO_PinOutput_HighCurrent))
|
||||
{
|
||||
pGPIO->PDDR |= u32PinMask; /* 引脚配置为通用输出*/
|
||||
pGPIO->PIDR |= u32PinMask; /* 置位端口输入禁用寄存器*/
|
||||
}
|
||||
else if ((sGpioType == GPIO_PinInput) || (sGpioType == GPIO_PinInput_InternalPullup))
|
||||
{
|
||||
pGPIO->PDDR &= ~u32PinMask; /* 引脚配置为通用输入 */
|
||||
pGPIO->PIDR &= ~u32PinMask; /* 清零端口输入禁用寄存器 */
|
||||
}
|
||||
/* 设置GPIO端口输入上拉 */
|
||||
switch ((uint32_t)pGPIO)
|
||||
{
|
||||
case GPIOA_BASE:
|
||||
(sGpioType == GPIO_PinInput_InternalPullup) ? (PORT->PUEL |= u32PinMask) : (PORT->PUEL &= ~u32PinMask);
|
||||
break;
|
||||
case GPIOB_BASE:
|
||||
(sGpioType == GPIO_PinInput_InternalPullup) ? (PORT->PUEH |= u32PinMask) : (PORT->PUEH &= ~u32PinMask);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/* 设置GPIO端口为高电流驱动输出 */
|
||||
if (pGPIO == GPIOA)
|
||||
{
|
||||
if (u32PinMask & GPIO_PTB4_MASK)
|
||||
{
|
||||
PORT->HDRVE |= PORT_HDRVE_PTB4_MASK;
|
||||
}
|
||||
if (u32PinMask & GPIO_PTB5_MASK)
|
||||
{
|
||||
PORT->HDRVE |= PORT_HDRVE_PTB5_MASK;
|
||||
}
|
||||
if (u32PinMask & GPIO_PTD0_MASK)
|
||||
{
|
||||
PORT->HDRVE |= PORT_HDRVE_PTD0_MASK;
|
||||
}
|
||||
if (u32PinMask & GPIO_PTD1_MASK)
|
||||
{
|
||||
PORT->HDRVE |= PORT_HDRVE_PTD1_MASK;
|
||||
}
|
||||
}
|
||||
if (pGPIO == GPIOB)
|
||||
{
|
||||
if (u32PinMask & GPIO_PTE0_MASK)
|
||||
{
|
||||
PORT->HDRVE |= PORT_HDRVE_PTE0_MASK;
|
||||
}
|
||||
if (u32PinMask & GPIO_PTE1_MASK)
|
||||
{
|
||||
PORT->HDRVE |= PORT_HDRVE_PTE1_MASK;
|
||||
}
|
||||
if (u32PinMask & GPIO_PTH0_MASK)
|
||||
{
|
||||
PORT->HDRVE |= PORT_HDRVE_PTH0_MASK;
|
||||
}
|
||||
if (u32PinMask & GPIO_PTH1_MASK)
|
||||
{
|
||||
PORT->HDRVE |= PORT_HDRVE_PTH1_MASK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/ /*!
|
||||
* @brief 切换GPIO端口数据输出
|
||||
*
|
||||
* @param[in] pGPIO GPIOA/GPIOB.
|
||||
* @param[in] u32PinMask 32位引脚掩码(GPIO_PTA0_MASK, GPIO_PTA1_MASK...)
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void GPIO_Toggle(GPIO_Type *pGPIO, uint32_t u32PinMask)
|
||||
{
|
||||
ASSERT((pGPIO == GPIOA) || (pGPIO == GPIOB));
|
||||
|
||||
pGPIO->PTOR = u32PinMask; /* 32位引脚掩码确定要切换输出的引脚 */
|
||||
}
|
||||
|
||||
/*****************************************************************************/ /*!
|
||||
* @brief 读取端口输入数据寄存器
|
||||
*
|
||||
* @param[in] pGPIO GPIOA/GPIOB.
|
||||
*
|
||||
* @return GPIOx->PDIR端口输入寄存器32位数值
|
||||
*
|
||||
*****************************************************************************/
|
||||
uint32_t GPIO_Read(GPIO_Type *pGPIO)
|
||||
{
|
||||
ASSERT((pGPIO == GPIOA) || (pGPIO == GPIOB));
|
||||
|
||||
return (pGPIO->PDIR); /* 读端口数据输入寄存器 */
|
||||
}
|
||||
|
||||
/*****************************************************************************/ /*!
|
||||
* @brief 读取某个引脚的电平
|
||||
*
|
||||
* @param[in] pGPIO 指向GPIO模块 GPIOA/GPIOB.
|
||||
* @param[in] GPIO_Pin GPIO引脚名 (GPIO_PTA0�PIO_PTA1...)
|
||||
*
|
||||
* @return 端口数据寄存器某一位的值
|
||||
*
|
||||
*****************************************************************************/
|
||||
uint8_t GPIO_BitRead(GPIO_PinType GPIO_Pin)
|
||||
{
|
||||
uint8_t data = 0;
|
||||
|
||||
ASSERT(GPIO_Pin < GPIO_PIN_MAX);
|
||||
|
||||
if (GPIO_Pin < GPIO_PTE0)
|
||||
{
|
||||
if (((1 << GPIO_Pin) & GPIOA->PDIR) > 0) /*判断要读取的位,对应的数值是1还是0*/
|
||||
data = 0x1; /* 如果是1返回1,是0则返回0 */
|
||||
else
|
||||
data = 0x0;
|
||||
}
|
||||
|
||||
else if (GPIO_Pin < GPIO_PIN_MAX)
|
||||
{
|
||||
GPIO_Pin = (GPIO_PinType)(GPIO_Pin - 32);
|
||||
|
||||
if (((1 << GPIO_Pin) & GPIOB->PDIR) > 0) /*判断要读取的位,对应的数值是1还是0*/
|
||||
data = 0x1; /* 如果是1返回1,是0则返回0 */
|
||||
else
|
||||
data = 0x0;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/*****************************************************************************/ /*!
|
||||
* @brief 写数据到端口数据输出寄存器
|
||||
*
|
||||
* @param[in] pGPIO GPIOA/GPIOB.
|
||||
* @param[in] u32Value 写入到端口数据输出寄存器GPIOx->PDOR的值
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void GPIO_Write(GPIO_Type *pGPIO, uint32_t u32Value)
|
||||
{
|
||||
ASSERT((pGPIO == GPIOA) || (pGPIO == GPIOB));
|
||||
|
||||
pGPIO->PDOR = u32Value; /* 写数据到端口数据输出寄存器 */
|
||||
}
|
||||
|
||||
/*****************************************************************************/ /*!
|
||||
* @brief 初始化GPIO引脚属性
|
||||
*
|
||||
* @param[in] GPIO_Pin GPIO引脚名 (GPIO_PTA0、PIO_PTA1...)
|
||||
* @param[in] GPIO_PinConfig 引脚属性(输入GPIO_PinInput、输出GPIO_PinOutput、输出高电流驱动GPIO_PinOutput_HighCurrent、输入并开启上拉GPIO_PinInput_InternalPullup)
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void GPIO_PinInit(GPIO_PinType GPIO_Pin, GPIO_PinConfigType GPIO_PinConfig)
|
||||
{
|
||||
/* Sanity check */
|
||||
ASSERT(GPIO_Pin < GPIO_PIN_MAX);
|
||||
|
||||
if (GPIO_Pin < GPIO_PTE0)
|
||||
{
|
||||
switch (GPIO_PinConfig)
|
||||
{
|
||||
case GPIO_PinOutput:
|
||||
GPIOA->PDDR |= (1 << GPIO_Pin); /* 引脚配置为通用输出 */
|
||||
GPIOA->PIDR |= (1 << GPIO_Pin); /* 端口输入禁用寄存器置一*/
|
||||
PORT->PUEL &= ~(1 << GPIO_Pin); /* 禁用内部上拉 */
|
||||
break;
|
||||
case GPIO_PinInput:
|
||||
GPIOA->PDDR &= ~(1 << GPIO_Pin); /* 引脚配置为通用输入 */
|
||||
GPIOA->PIDR &= ~(1 << GPIO_Pin); /* 端口输入禁用寄存器清零 */
|
||||
PORT->PUEL &= ~(1 << GPIO_Pin); /* 禁用内部上拉*/
|
||||
break;
|
||||
case GPIO_PinInput_InternalPullup:
|
||||
GPIOA->PDDR &= ~(1 << GPIO_Pin); /* 引脚配置为通用输入 */
|
||||
GPIOA->PIDR &= ~(1 << GPIO_Pin); /* 端口输入禁用寄存器清零 */
|
||||
PORT->PUEL |= (1 << GPIO_Pin); /* 使能内部上拉 */
|
||||
break;
|
||||
case GPIO_PinOutput_HighCurrent:
|
||||
GPIOA->PDDR |= (1 << GPIO_Pin); /* 引脚配置为通用输出 */
|
||||
GPIOA->PIDR |= (1 << GPIO_Pin); /* 端口输入禁用寄存器置一 */
|
||||
PORT->PUEL &= ~(1 << GPIO_Pin); /* 禁用内部上拉*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (GPIO_Pin < GPIO_PIN_MAX)
|
||||
{
|
||||
GPIO_Pin = (GPIO_PinType)(GPIO_Pin - 32);
|
||||
switch (GPIO_PinConfig)
|
||||
{
|
||||
case GPIO_PinOutput:
|
||||
GPIOB->PDDR |= (1 << GPIO_Pin); /* 引脚配置为通用输出 */
|
||||
GPIOB->PIDR |= (1 << GPIO_Pin); /* 端口输入禁用寄存器置一 */
|
||||
PORT->PUEH &= ~(1 << GPIO_Pin); /* 禁用内部上拉*/
|
||||
break;
|
||||
case GPIO_PinInput:
|
||||
GPIOB->PDDR &= ~(1 << GPIO_Pin); /* 引脚配置为通用输入 */
|
||||
GPIOB->PIDR &= ~(1 << GPIO_Pin); /* 端口输入禁用寄存器清零 */
|
||||
PORT->PUEH &= ~(1 << GPIO_Pin); /* 禁用内部上拉*/
|
||||
break;
|
||||
case GPIO_PinInput_InternalPullup:
|
||||
GPIOB->PDDR &= ~(1 << GPIO_Pin); /* 引脚配置为通用输入 */
|
||||
GPIOB->PIDR &= ~(1 << GPIO_Pin); /* 端口输入禁用寄存器清零 */
|
||||
PORT->PUEH |= (1 << GPIO_Pin); /* 使能内部上拉*/
|
||||
break;
|
||||
case GPIO_PinOutput_HighCurrent:
|
||||
GPIOA->PDDR |= (1 << GPIO_Pin); /* 引脚配置为通用输出 */
|
||||
GPIOA->PIDR |= (1 << GPIO_Pin); /* 端口输入禁用寄存器置一 */
|
||||
PORT->PUEL &= ~(1 << GPIO_Pin); /* 禁用内部上拉*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* 配置GPIO输出高电流驱动 */
|
||||
if (GPIO_PinConfig == GPIO_PinOutput_HighCurrent)
|
||||
{
|
||||
switch (GPIO_Pin)
|
||||
{
|
||||
case GPIO_PTB4:
|
||||
PORT->HDRVE |= PORT_HDRVE_PTB4_MASK;
|
||||
break;
|
||||
case GPIO_PTB5:
|
||||
PORT->HDRVE |= PORT_HDRVE_PTB5_MASK;
|
||||
break;
|
||||
case GPIO_PTD0:
|
||||
PORT->HDRVE |= PORT_HDRVE_PTD0_MASK;
|
||||
break;
|
||||
case GPIO_PTD1:
|
||||
PORT->HDRVE |= PORT_HDRVE_PTD1_MASK;
|
||||
break;
|
||||
case GPIO_PTE0:
|
||||
PORT->HDRVE |= PORT_HDRVE_PTE0_MASK;
|
||||
break;
|
||||
case GPIO_PTE1:
|
||||
PORT->HDRVE |= PORT_HDRVE_PTE1_MASK;
|
||||
break;
|
||||
case GPIO_PTH0:
|
||||
PORT->HDRVE |= PORT_HDRVE_PTH0_MASK;
|
||||
break;
|
||||
case GPIO_PTH1:
|
||||
PORT->HDRVE |= PORT_HDRVE_PTH1_MASK;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/ /*!
|
||||
* @brief 切换GPIO端口数据切换输出
|
||||
*
|
||||
* @param[in] GPIO_Pin GPIO引脚名 (GPIO_PTA0�PIO_PTA1...)
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void GPIO_PinToggle(GPIO_PinType GPIO_Pin)
|
||||
{
|
||||
ASSERT(GPIO_Pin <= GPIO_PIN_MAX);
|
||||
|
||||
if (GPIO_Pin < GPIO_PTE0)
|
||||
{
|
||||
GPIOA->PTOR = (1 << GPIO_Pin);
|
||||
}
|
||||
else if (GPIO_Pin < GPIO_PIN_MAX)
|
||||
{
|
||||
GPIO_Pin = (GPIO_PinType)(GPIO_Pin - GPIO_PTE0);
|
||||
GPIOB->PTOR = (1 << GPIO_Pin);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/ /*!
|
||||
* @brief GPIO端口数据输出置1
|
||||
*
|
||||
* @param[in] GPIO_Pin GPIO引脚名 (GPIO_PTA0�PIO_PTA1...)
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void GPIO_PinSet(GPIO_PinType GPIO_Pin)
|
||||
{
|
||||
ASSERT(GPIO_Pin <= GPIO_PIN_MAX);
|
||||
|
||||
if (GPIO_Pin < GPIO_PTE0)
|
||||
{
|
||||
GPIOA->PSOR = (1 << GPIO_Pin);
|
||||
}
|
||||
else if (GPIO_Pin < GPIO_PIN_MAX)
|
||||
{
|
||||
GPIO_Pin = (GPIO_PinType)(GPIO_Pin - GPIO_PTE0);
|
||||
GPIOB->PSOR = (1 << GPIO_Pin);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/ /*!
|
||||
* @brief GPIO端口数据输出清零
|
||||
*
|
||||
* @param[in] GPIO_Pin GPIO引脚名 (GPIO_PTA0�PIO_PTA1...)
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void GPIO_PinClear(GPIO_PinType GPIO_Pin)
|
||||
{
|
||||
ASSERT(GPIO_Pin <= GPIO_PIN_MAX);
|
||||
|
||||
if (GPIO_Pin < GPIO_PTE0)
|
||||
{
|
||||
GPIOA->PCOR = (1 << GPIO_Pin);
|
||||
}
|
||||
else if (GPIO_Pin < GPIO_PIN_MAX)
|
||||
{
|
||||
GPIO_Pin = (GPIO_PinType)(GPIO_Pin - GPIO_PTE0);
|
||||
GPIOB->PCOR = (1 << GPIO_Pin);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,583 @@
|
||||
#ifndef _GPIO_H_
|
||||
#define _GPIO_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
#include "stdint.h"
|
||||
#include "core_cm0plus.h"
|
||||
#include "bos.h"
|
||||
/******************************************************************************
|
||||
*宏定义,用于生位操作存储加载无符号字段提取(UBFX)硬件编码地址
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define GPIO_ALIAS_OFF 0x000F0000L
|
||||
#define BOS_BIT_EXTRACT(ADDR,bit,width) (*(volatile uint32_t *)(((uint32_t) (((uint32_t)&ADDR)-GPIO_ALIAS_OFF)) \
|
||||
| (BOS_OPCODE_BITFIELD <<26) \
|
||||
| ((bit & 0x1F)<<23) | ((width-1) & 0xF)<<19))
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* GPIO位带操作宏定义
|
||||
*
|
||||
******************************************************************************/
|
||||
#define PTA0_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,0) //PTA0端口数据输出为高
|
||||
#define PTA0_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,0) //PTA0端口数据输出为低
|
||||
#define PTA0_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,0) //PTA0端口输出切换
|
||||
|
||||
#define PTA1_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,1)
|
||||
#define PTA1_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,1)
|
||||
#define PTA1_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,1)
|
||||
|
||||
#define PTA2_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,2)
|
||||
#define PTA2_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,2)
|
||||
#define PTA2_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,2)
|
||||
|
||||
#define PTA3_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,3)
|
||||
#define PTA3_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,3)
|
||||
#define PTA3_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,3)
|
||||
|
||||
#define PTA4_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,4)
|
||||
#define PTA4_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,4)
|
||||
#define PTA4_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,4)
|
||||
|
||||
#define PTA5_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,5)
|
||||
#define PTA5_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,5)
|
||||
#define PTA5_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,5)
|
||||
|
||||
#define PTA6_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,6)
|
||||
#define PTA6_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,6)
|
||||
#define PTA6_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,6)
|
||||
|
||||
#define PTA7_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,7)
|
||||
#define PTA7_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,7)
|
||||
#define PTA7_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,7)
|
||||
|
||||
#define PTB0_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,8) //PTB0端口数据输出为高
|
||||
#define PTB0_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,8) //PTB0端口数据输出为低
|
||||
#define PTB0_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,8) //PTB0端口数据输出切换
|
||||
|
||||
#define PTB1_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,9)
|
||||
#define PTB1_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,9)
|
||||
#define PTB1_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,9)
|
||||
|
||||
#define PTB2_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,10)
|
||||
#define PTB2_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,10)
|
||||
#define PTB2_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,10)
|
||||
|
||||
#define PTB3_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,11)
|
||||
#define PTB3_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,11)
|
||||
#define PTB3_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,11)
|
||||
|
||||
#define PTB4_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,12)
|
||||
#define PTB4_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,12)
|
||||
#define PTB4_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,12)
|
||||
|
||||
#define PTB5_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,13)
|
||||
#define PTB5_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,13)
|
||||
#define PTB5_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,13)
|
||||
|
||||
#define PTB6_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,14)
|
||||
#define PTB6_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,14)
|
||||
#define PTB6_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,14)
|
||||
|
||||
#define PTB7_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,15)
|
||||
#define PTB7_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,15)
|
||||
#define PTB7_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,15)
|
||||
|
||||
#define PTC0_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,16) //PTC0端口数据输出为高
|
||||
#define PTC0_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,16) //PTC0端口数据输出为低
|
||||
#define PTC0_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,16) //PTC0端口数据输出切换
|
||||
|
||||
#define PTC1_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,17)
|
||||
#define PTC1_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,17)
|
||||
#define PTC1_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,17)
|
||||
|
||||
#define PTC2_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,18)
|
||||
#define PTC2_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,18)
|
||||
#define PTC2_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,18)
|
||||
|
||||
#define PTC3_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,19)
|
||||
#define PTC3_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,19)
|
||||
#define PTC3_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,19)
|
||||
|
||||
#define PTC4_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,20)
|
||||
#define PTC4_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,20)
|
||||
#define PTC4_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,20)
|
||||
|
||||
#define PTC5_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,21)
|
||||
#define PTC5_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,21)
|
||||
#define PTC5_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,21)
|
||||
|
||||
#define PTC6_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,22)
|
||||
#define PTC6_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,22)
|
||||
#define PTC6_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,22)
|
||||
|
||||
#define PTC7_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,23)
|
||||
#define PTC7_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,23)
|
||||
#define PTC7_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,23)
|
||||
|
||||
#define PTD0_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,24) //PTD0端口数据输出为高
|
||||
#define PTD0_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,24) //PTD0端口数据输出为低
|
||||
#define PTD0_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,24) //PTD0端口数据输出切换
|
||||
|
||||
#define PTD1_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,25)
|
||||
#define PTD1_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,25)
|
||||
#define PTD1_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,25)
|
||||
|
||||
#define PTD2_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,26)
|
||||
#define PTD2_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,26)
|
||||
#define PTD2_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,26)
|
||||
|
||||
#define PTD3_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,27)
|
||||
#define PTD3_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,27)
|
||||
#define PTD3_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,27)
|
||||
|
||||
#define PTD4_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,28)
|
||||
#define PTD4_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,28)
|
||||
#define PTD4_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,28)
|
||||
|
||||
#define PTD5_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,29)
|
||||
#define PTD5_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,29)
|
||||
#define PTD5_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,29)
|
||||
|
||||
#define PTD6_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,30)
|
||||
#define PTD6_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,30)
|
||||
#define PTD6_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,30)
|
||||
|
||||
#define PTD7_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,31)
|
||||
#define PTD7_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,31)
|
||||
#define PTD7_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,31)
|
||||
|
||||
#define PTE0_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,0)
|
||||
#define PTE0_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,0)
|
||||
#define PTE0_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,0)
|
||||
|
||||
#define PTE1_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,1) //PTE0端口数据输出为高
|
||||
#define PTE1_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,1) //PTE0端口数据输出为低
|
||||
#define PTE1_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,1) //PTE0端口数据输出切换
|
||||
|
||||
#define PTE2_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,2)
|
||||
#define PTE2_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,2)
|
||||
#define PTE2_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,2)
|
||||
|
||||
#define PTE3_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,3)
|
||||
#define PTE3_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,3)
|
||||
#define PTE3_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,3)
|
||||
|
||||
#define PTE4_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,4)
|
||||
#define PTE4_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,4)
|
||||
#define PTE4_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,4)
|
||||
|
||||
#define PTE5_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,5)
|
||||
#define PTE5_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,5)
|
||||
#define PTE5_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,5)
|
||||
|
||||
#define PTE6_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,6)
|
||||
#define PTE6_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,6)
|
||||
#define PTE6_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,6)
|
||||
|
||||
#define PTE7_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,7)
|
||||
#define PTE7_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,7)
|
||||
#define PTE7_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,7)
|
||||
|
||||
#define PTF0_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,8) //PTF0端口数据输出为高
|
||||
#define PTF0_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,8) //PTF0端口数据输出为低
|
||||
#define PTF0_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,8) //PTF0端口数据输出切换
|
||||
|
||||
#define PTF1_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,9)
|
||||
#define PTF1_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,9)
|
||||
#define PTF1_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,9)
|
||||
|
||||
#define PTF2_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,10)
|
||||
#define PTF2_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,10)
|
||||
#define PTF2_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,10)
|
||||
|
||||
#define PTF3_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,11)
|
||||
#define PTF3_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,11)
|
||||
#define PTF3_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,11)
|
||||
|
||||
#define PTF4_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,12)
|
||||
#define PTF4_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,12)
|
||||
#define PTF4_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,12)
|
||||
|
||||
#define PTF5_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,13)
|
||||
#define PTF5_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,13)
|
||||
#define PTF5_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,13)
|
||||
|
||||
#define PTF6_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,14)
|
||||
#define PTF6_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,14)
|
||||
#define PTF6_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,14)
|
||||
|
||||
#define PTF7_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,15)
|
||||
#define PTF7_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,15)
|
||||
#define PTF7_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,15)
|
||||
|
||||
#define PTG0_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,16) //PTG0端口数据输出为高
|
||||
#define PTG0_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,16) //PTG0端口数据输出为低
|
||||
#define PTG0_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,16) //PTG0端口数据输出切换
|
||||
|
||||
#define PTG1_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,17)
|
||||
#define PTG1_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,17)
|
||||
#define PTG1_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,17)
|
||||
|
||||
#define PTG2_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,18)
|
||||
#define PTG2_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,18)
|
||||
#define PTG2_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,18)
|
||||
|
||||
#define PTG3_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,19)
|
||||
#define PTG3_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,19)
|
||||
#define PTG3_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,19)
|
||||
|
||||
#define PTG4_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,20)
|
||||
#define PTG4_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,20)
|
||||
#define PTG4_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,20)
|
||||
|
||||
#define PTG5_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,21)
|
||||
#define PTG5_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,21)
|
||||
#define PTG5_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,21)
|
||||
|
||||
#define PTG6_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,22)
|
||||
#define PTG6_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,22)
|
||||
#define PTG6_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,22)
|
||||
|
||||
#define PTG7_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,23)
|
||||
#define PTG7_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,23)
|
||||
#define PTG7_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,23)
|
||||
|
||||
#define PTH0_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,24) //PTH0端口数据输出为高
|
||||
#define PTH0_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,24) //PTH0端口数据输出为低
|
||||
#define PTH0_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,24) //PTH0端口数据输出切换
|
||||
|
||||
#define PTH1_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,25)
|
||||
#define PTH1_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,25)
|
||||
#define PTH1_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,25)
|
||||
|
||||
#define PTH2_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,26)
|
||||
#define PTH2_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,26)
|
||||
#define PTH2_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,26)
|
||||
|
||||
#define PTH3_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,27)
|
||||
#define PTH3_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,27)
|
||||
#define PTH3_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,27)
|
||||
|
||||
#define PTH4_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,28)
|
||||
#define PTH4_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,28)
|
||||
#define PTH4_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,28)
|
||||
|
||||
#define PTH5_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,29)
|
||||
#define PTH5_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,29)
|
||||
#define PTH5_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,29)
|
||||
|
||||
#define PTH6_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,30)
|
||||
#define PTH6_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,30)
|
||||
#define PTH6_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,30)
|
||||
|
||||
#define PTH7_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,31)
|
||||
#define PTH7_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,31)
|
||||
#define PTH7_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,31)
|
||||
|
||||
#define PTA0_IN BOS_BIT_EXTRACT(GPIOA->PDIR,0,1) //读取PA0端口输入数据
|
||||
#define PTA1_IN BOS_BIT_EXTRACT(GPIOA->PDIR,1,1)
|
||||
#define PTA2_IN BOS_BIT_EXTRACT(GPIOA->PDIR,2,1)
|
||||
#define PTA3_IN BOS_BIT_EXTRACT(GPIOA->PDIR,3,1)
|
||||
#define PTA4_IN BOS_BIT_EXTRACT(GPIOA->PDIR,4,1)
|
||||
#define PTA5_IN BOS_BIT_EXTRACT(GPIOA->PDIR,5,1)
|
||||
#define PTA6_IN BOS_BIT_EXTRACT(GPIOA->PDIR,6,1)
|
||||
#define PTA7_IN BOS_BIT_EXTRACT(GPIOA->PDIR,7,1)
|
||||
|
||||
#define PTB0_IN BOS_BIT_EXTRACT(GPIOA->PDIR,8,1) //读取PB0端口输入数据
|
||||
#define PTB1_IN BOS_BIT_EXTRACT(GPIOA->PDIR,9,1)
|
||||
#define PTB2_IN BOS_BIT_EXTRACT(GPIOA->PDIR,10,1)
|
||||
#define PTB3_IN BOS_BIT_EXTRACT(GPIOA->PDIR,11,1)
|
||||
#define PTB4_IN BOS_BIT_EXTRACT(GPIOA->PDIR,12,1)
|
||||
#define PTB5_IN BOS_BIT_EXTRACT(GPIOA->PDIR,13,1)
|
||||
#define PTB6_IN BOS_BIT_EXTRACT(GPIOA->PDIR,14,1)
|
||||
#define PTB7_IN BOS_BIT_EXTRACT(GPIOA->PDIR,15,1)
|
||||
|
||||
#define PTC0_IN BOS_BIT_EXTRACT(GPIOA->PDIR,16,1) //读取PC0端口输入数据
|
||||
#define PTC1_IN BOS_BIT_EXTRACT(GPIOA->PDIR,17,1)
|
||||
#define PTC2_IN BOS_BIT_EXTRACT(GPIOA->PDIR,18,1)
|
||||
#define PTC3_IN BOS_BIT_EXTRACT(GPIOA->PDIR,19,1)
|
||||
#define PTC4_IN BOS_BIT_EXTRACT(GPIOA->PDIR,20,1)
|
||||
#define PTC5_IN BOS_BIT_EXTRACT(GPIOA->PDIR,21,1)
|
||||
#define PTC6_IN BOS_BIT_EXTRACT(GPIOA->PDIR,22,1)
|
||||
#define PTC7_IN BOS_BIT_EXTRACT(GPIOA->PDIR,23,1)
|
||||
|
||||
#define PTD0_IN BOS_BIT_EXTRACT(GPIOA->PDIR,24,1) //读取PD0端口输入数据
|
||||
#define PTD1_IN BOS_BIT_EXTRACT(GPIOA->PDIR,25,1)
|
||||
#define PTD2_IN BOS_BIT_EXTRACT(GPIOA->PDIR,26,1)
|
||||
#define PTD3_IN BOS_BIT_EXTRACT(GPIOA->PDIR,27,1)
|
||||
#define PTD4_IN BOS_BIT_EXTRACT(GPIOA->PDIR,28,1)
|
||||
#define PTD5_IN BOS_BIT_EXTRACT(GPIOA->PDIR,29,1)
|
||||
#define PTD6_IN BOS_BIT_EXTRACT(GPIOA->PDIR,30,1)
|
||||
#define PTD7_IN BOS_BIT_EXTRACT(GPIOA->PDIR,31,1)
|
||||
|
||||
#define PTE0_IN BOS_BIT_EXTRACT(GPIOB->PDIR,0,1) //读取PE0端口输入数据
|
||||
#define PTE1_IN BOS_BIT_EXTRACT(GPIOB->PDIR,1,1)
|
||||
#define PTE2_IN BOS_BIT_EXTRACT(GPIOB->PDIR,2,1)
|
||||
#define PTE3_IN BOS_BIT_EXTRACT(GPIOB->PDIR,3,1)
|
||||
#define PTE4_IN BOS_BIT_EXTRACT(GPIOB->PDIR,4,1)
|
||||
#define PTE5_IN BOS_BIT_EXTRACT(GPIOB->PDIR,5,1)
|
||||
#define PTE6_IN BOS_BIT_EXTRACT(GPIOB->PDIR,6,1)
|
||||
#define PTE7_IN BOS_BIT_EXTRACT(GPIOB->PDIR,7,1)
|
||||
|
||||
#define PTF0_IN BOS_BIT_EXTRACT(GPIOB->PDIR,8,1) //读取PF0端口输入数据
|
||||
#define PTF1_IN BOS_BIT_EXTRACT(GPIOB->PDIR,9,1)
|
||||
#define PTF2_IN BOS_BIT_EXTRACT(GPIOB->PDIR,10,1)
|
||||
#define PTF3_IN BOS_BIT_EXTRACT(GPIOB->PDIR,11,1)
|
||||
#define PTF4_IN BOS_BIT_EXTRACT(GPIOB->PDIR,12,1)
|
||||
#define PTF5_IN BOS_BIT_EXTRACT(GPIOB->PDIR,13,1)
|
||||
#define PTF6_IN BOS_BIT_EXTRACT(GPIOB->PDIR,14,1)
|
||||
#define PTF7_IN BOS_BIT_EXTRACT(GPIOB->PDIR,15,1)
|
||||
|
||||
#define PTG0_IN BOS_BIT_EXTRACT(GPIOB->PDIR,16,1) //读取PG0端口输入数据 Modify
|
||||
#define PTG1_IN BOS_BIT_EXTRACT(GPIOB->PDIR,17,1)
|
||||
#define PTG2_IN BOS_BIT_EXTRACT(GPIOB->PDIR,18,1)
|
||||
#define PTG3_IN BOS_BIT_EXTRACT(GPIOB->PDIR,19,1)
|
||||
#define PTG4_IN BOS_BIT_EXTRACT(GPIOB->PDIR,20,1)
|
||||
#define PTG5_IN BOS_BIT_EXTRACT(GPIOB->PDIR,21,1)
|
||||
#define PTG6_IN BOS_BIT_EXTRACT(GPIOB->PDIR,22,1)
|
||||
#define PTG7_IN BOS_BIT_EXTRACT(GPIOB->PDIR,23,1)
|
||||
|
||||
#define PTH0_IN BOS_BIT_EXTRACT(GPIOB->PDIR,24,1) //读取PH0端口输入数据
|
||||
#define PTH1_IN BOS_BIT_EXTRACT(GPIOB->PDIR,25,1)
|
||||
#define PTH2_IN BOS_BIT_EXTRACT(GPIOB->PDIR,26,1)
|
||||
#define PTH3_IN BOS_BIT_EXTRACT(GPIOB->PDIR,27,1)
|
||||
#define PTH4_IN BOS_BIT_EXTRACT(GPIOB->PDIR,28,1)
|
||||
#define PTH5_IN BOS_BIT_EXTRACT(GPIOB->PDIR,29,1)
|
||||
#define PTH6_IN BOS_BIT_EXTRACT(GPIOB->PDIR,30,1)
|
||||
#define PTH7_IN BOS_BIT_EXTRACT(GPIOB->PDIR,31,1)
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义GPIO引脚名
|
||||
*
|
||||
*******************************************************************************/
|
||||
typedef enum
|
||||
{
|
||||
/* 用于GPIO */
|
||||
GPIO_PTA0 = 0, /*!< GPIO Pin PTA0 */
|
||||
GPIO_PTA1, /*!< GPIO Pin PTA1 */
|
||||
GPIO_PTA2, /*!< GPIO Pin PTA2 */
|
||||
GPIO_PTA3, /*!< GPIO Pin PTA3 */
|
||||
GPIO_PTA4, /*!< GPIO Pin PTA4 */
|
||||
GPIO_PTA5, /*!< GPIO Pin PTA5 */
|
||||
GPIO_PTA6, /*!< GPIO Pin PTA6 */
|
||||
GPIO_PTA7, /*!< GPIO Pin PTA7 */
|
||||
GPIO_PTB0, /*!< GPIO Pin PTB0 */
|
||||
GPIO_PTB1, /*!< GPIO Pin PTB1 */
|
||||
GPIO_PTB2, /*!< GPIO Pin PTB2 */
|
||||
GPIO_PTB3, /*!< GPIO Pin PTB3 */
|
||||
GPIO_PTB4, /*!< GPIO Pin PTB4 */
|
||||
GPIO_PTB5, /*!< GPIO Pin PTB5 */
|
||||
GPIO_PTB6, /*!< GPIO Pin PTB6 */
|
||||
GPIO_PTB7, /*!< GPIO Pin PTB7 */
|
||||
GPIO_PTC0, /*!< GPIO Pin PTC0 */
|
||||
GPIO_PTC1, /*!< GPIO Pin PTC1 */
|
||||
GPIO_PTC2, /*!< GPIO Pin PTC2 */
|
||||
GPIO_PTC3, /*!< GPIO Pin PTC3 */
|
||||
GPIO_PTC4, /*!< GPIO Pin PTC4 */
|
||||
GPIO_PTC5, /*!< GPIO Pin PTC5 */
|
||||
GPIO_PTC6, /*!< GPIO Pin PTC6 */
|
||||
GPIO_PTC7, /*!< GPIO Pin PTC7 */
|
||||
GPIO_PTD0, /*!< GPIO Pin PTD0 */
|
||||
GPIO_PTD1, /*!< GPIO Pin PTD1 */
|
||||
GPIO_PTD2, /*!< GPIO Pin PTD2 */
|
||||
GPIO_PTD3, /*!< GPIO Pin PTD3 */
|
||||
GPIO_PTD4, /*!< GPIO Pin PTD4 */
|
||||
GPIO_PTD5, /*!< GPIO Pin PTD5 */
|
||||
GPIO_PTD6, /*!< GPIO Pin PTD6 */
|
||||
GPIO_PTD7, /*!< GPIO Pin PTD7 */
|
||||
/* in GPIOB register */
|
||||
GPIO_PTE0, /*!< GPIO Pin PTE0 */
|
||||
GPIO_PTE1, /*!< GPIO Pin PTE1 */
|
||||
GPIO_PTE2, /*!< GPIO Pin PTE2 */
|
||||
GPIO_PTE3, /*!< GPIO Pin PTE3 */
|
||||
GPIO_PTE4, /*!< GPIO Pin PTE4 */
|
||||
GPIO_PTE5, /*!< GPIO Pin PTE5 */
|
||||
GPIO_PTE6, /*!< GPIO Pin PTE6 */
|
||||
GPIO_PTE7, /*!< GPIO Pin PTE7 */
|
||||
GPIO_PTF0, /*!< GPIO Pin PTF0 */
|
||||
GPIO_PTF1, /*!< GPIO Pin PTF1 */
|
||||
GPIO_PTF2, /*!< GPIO Pin PTF2 */
|
||||
GPIO_PTF3, /*!< GPIO Pin PTF3 */
|
||||
GPIO_PTF4, /*!< GPIO Pin PTF4 */
|
||||
GPIO_PTF5, /*!< GPIO Pin PTF5 */
|
||||
GPIO_PTF6, /*!< GPIO Pin PTF6 */
|
||||
GPIO_PTF7, /*!< GPIO Pin PTF7 */
|
||||
GPIO_PTG0, /*!< GPIO Pin PTG0 */
|
||||
GPIO_PTG1, /*!< GPIO Pin PTG1 */
|
||||
GPIO_PTG2, /*!< GPIO Pin PTG2 */
|
||||
GPIO_PTG3, /*!< GPIO Pin PTG3 */
|
||||
GPIO_PTG4, /*!< GPIO Pin PTG4 */
|
||||
GPIO_PTG5, /*!< GPIO Pin PTG5 */
|
||||
GPIO_PTG6, /*!< GPIO Pin PTG6 */
|
||||
GPIO_PTG7, /*!< GPIO Pin PTG7 */
|
||||
GPIO_PTH0, /*!< GPIO Pin PTH0 */
|
||||
GPIO_PTH1, /*!< GPIO Pin PTH1 */
|
||||
GPIO_PTH2, /*!< GPIO Pin PTH2 */
|
||||
GPIO_PTH3, /*!< GPIO Pin PTH3 */
|
||||
GPIO_PTH4, /*!< GPIO Pin PTH4 */
|
||||
GPIO_PTH5, /*!< GPIO Pin PTH5 */
|
||||
GPIO_PTH6, /*!< GPIO Pin PTH6 */
|
||||
GPIO_PTH7, /*!< GPIO Pin PTH7 */
|
||||
GPIO_PIN_MAX,
|
||||
} GPIO_PinType;
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义GPIO引脚掩码
|
||||
*
|
||||
*******************************************************************************/
|
||||
typedef enum
|
||||
{
|
||||
/* in GPIOA register */
|
||||
GPIO_PTA0_MASK = (1<<0), /*!< GPIO Pin PTA0 bit mask */
|
||||
GPIO_PTA1_MASK = (1<<1), /*!< GPIO Pin PTA1 bit mask */
|
||||
GPIO_PTA2_MASK = (1<<2), /*!< GPIO Pin PTA2 bit mask */
|
||||
GPIO_PTA3_MASK = (1<<3), /*!< GPIO Pin PTA3 bit mask */
|
||||
GPIO_PTA4_MASK = (1<<4), /*!< GPIO Pin PTA4 bit mask */
|
||||
GPIO_PTA5_MASK = (1<<5), /*!< GPIO Pin PTA5 bit mask */
|
||||
GPIO_PTA6_MASK = (1<<6), /*!< GPIO Pin PTA6 bit mask */
|
||||
GPIO_PTA7_MASK = (1<<7), /*!< GPIO Pin PTA7 bit mask */
|
||||
GPIO_PTB0_MASK = (1<<8), /*!< GPIO Pin PTB0 bit mask */
|
||||
GPIO_PTB1_MASK = (1<<9), /*!< GPIO Pin PTB1 bit mask */
|
||||
GPIO_PTB2_MASK = (1<<10), /*!< GPIO Pin PTB2 bit mask */
|
||||
GPIO_PTB3_MASK = (1<<11), /*!< GPIO Pin PTB3 bit mask */
|
||||
GPIO_PTB4_MASK = (1<<12), /*!< GPIO Pin PTB4 bit mask */
|
||||
GPIO_PTB5_MASK = (1<<13), /*!< GPIO Pin PTB5 bit mask */
|
||||
GPIO_PTB6_MASK = (1<<14), /*!< GPIO Pin PTB6 bit mask */
|
||||
GPIO_PTB7_MASK = (1<<15), /*!< GPIO Pin PTB7 bit mask */
|
||||
GPIO_PTC0_MASK = (1<<16), /*!< GPIO Pin PTC0 bit mask */
|
||||
GPIO_PTC1_MASK = (1<<17), /*!< GPIO Pin PTC1 bit mask */
|
||||
GPIO_PTC2_MASK = (1<<18), /*!< GPIO Pin PTC2 bit mask */
|
||||
GPIO_PTC3_MASK = (1<<19), /*!< GPIO Pin PTC3 bit mask */
|
||||
GPIO_PTC4_MASK = (1<<20), /*!< GPIO Pin PTC4 bit mask */
|
||||
GPIO_PTC5_MASK = (1<<21), /*!< GPIO Pin PTC5 bit mask */
|
||||
GPIO_PTC6_MASK = (1<<22), /*!< GPIO Pin PTC6 bit mask */
|
||||
GPIO_PTC7_MASK = (1<<23), /*!< GPIO Pin PTC7 bit mask */
|
||||
GPIO_PTD0_MASK = (1<<24), /*!< GPIO Pin PTD0 bit mask */
|
||||
GPIO_PTD1_MASK = (1<<25), /*!< GPIO Pin PTD1 bit mask */
|
||||
GPIO_PTD2_MASK = (1<<26), /*!< GPIO Pin PTD2 bit mask */
|
||||
GPIO_PTD3_MASK = (1<<27), /*!< GPIO Pin PTD3 bit mask */
|
||||
GPIO_PTD4_MASK = (1<<28), /*!< GPIO Pin PTD4 bit mask */
|
||||
GPIO_PTD5_MASK = (1<<29), /*!< GPIO Pin PTD5 bit mask */
|
||||
GPIO_PTD6_MASK = (1<<30), /*!< GPIO Pin PTD6 bit mask */
|
||||
GPIO_PTD7_MASK = (int)(0x80000000), /*!< GPIO Pin PTD7 bit mask */
|
||||
/* in GPIOB register */
|
||||
GPIO_PTE0_MASK = (1<<0), /*!< GPIO Pin PTE0 bit mask */
|
||||
GPIO_PTE1_MASK = (1<<1), /*!< GPIO Pin PTE1 bit mask */
|
||||
GPIO_PTE2_MASK = (1<<2), /*!< GPIO Pin PTE2 bit mask */
|
||||
GPIO_PTE3_MASK = (1<<3), /*!< GPIO Pin PTE3 bit mask */
|
||||
GPIO_PTE4_MASK = (1<<4), /*!< GPIO Pin PTE4 bit mask */
|
||||
GPIO_PTE5_MASK = (1<<5), /*!< GPIO Pin PTE5 bit mask */
|
||||
GPIO_PTE6_MASK = (1<<6), /*!< GPIO Pin PTE6 bit mask */
|
||||
GPIO_PTE7_MASK = (1<<7), /*!< GPIO Pin PTE7 bit mask */
|
||||
GPIO_PTF0_MASK = (1<<8), /*!< GPIO Pin PTF0 bit mask */
|
||||
GPIO_PTF1_MASK = (1<<9), /*!< GPIO Pin PTF1 bit mask */
|
||||
GPIO_PTF2_MASK = (1<<10), /*!< GPIO Pin PTF2 bit mask */
|
||||
GPIO_PTF3_MASK = (1<<11), /*!< GPIO Pin PTF3 bit mask */
|
||||
GPIO_PTF4_MASK = (1<<12), /*!< GPIO Pin PTF4 bit mask */
|
||||
GPIO_PTF5_MASK = (1<<13), /*!< GPIO Pin PTF5 bit mask */
|
||||
GPIO_PTF6_MASK = (1<<14), /*!< GPIO Pin PTF6 bit mask */
|
||||
GPIO_PTF7_MASK = (1<<15), /*!< GPIO Pin PTF7 bit mask */
|
||||
GPIO_PTG0_MASK = (1<<16), /*!< GPIO Pin PTG0 bit mask */
|
||||
GPIO_PTG1_MASK = (1<<17), /*!< GPIO Pin PTG1 bit mask */
|
||||
GPIO_PTG2_MASK = (1<<18), /*!< GPIO Pin PTG2 bit mask */
|
||||
GPIO_PTG3_MASK = (1<<19), /*!< GPIO Pin PTG3 bit mask */
|
||||
GPIO_PTG4_MASK = (1<<20), /*!< GPIO Pin PTG4 bit mask */
|
||||
GPIO_PTG5_MASK = (1<<21), /*!< GPIO Pin PTG5 bit mask */
|
||||
GPIO_PTG6_MASK = (1<<22), /*!< GPIO Pin PTG6 bit mask */
|
||||
GPIO_PTG7_MASK = (1<<23), /*!< GPIO Pin PTG7 bit mask */
|
||||
GPIO_PTH0_MASK = (1<<24), /*!< GPIO Pin PTH0 bit mask */
|
||||
GPIO_PTH1_MASK = (1<<25), /*!< GPIO Pin PTH1 bit mask */
|
||||
GPIO_PTH2_MASK = (1<<26), /*!< GPIO Pin PTH2 bit mask */
|
||||
GPIO_PTH3_MASK = (1<<27), /*!< GPIO Pin PTH3 bit mask */
|
||||
GPIO_PTH4_MASK = (1<<28), /*!< GPIO Pin PTH4 bit mask */
|
||||
GPIO_PTH5_MASK = (1<<29), /*!< GPIO Pin PTH5 bit mask */
|
||||
GPIO_PTH6_MASK = (1<<30), /*!< GPIO Pin PTH6 bit mask */
|
||||
GPIO_PTH7_MASK = (int)(0x80000000), /*!< GPIO Pin PTH7 bit mask */
|
||||
} GPIO_PinMaskType;
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
*定义GPIO引脚配置类型
|
||||
*
|
||||
*******************************************************************************/
|
||||
/*
|
||||
* . 如果引脚配置为输入,禁用高电流驱动
|
||||
* . 如果引脚配置为输出,禁用内部上拉
|
||||
* 仅PTH1/0, PTE1/0, PTD1/0, PTB5/4 支持高电流驱动.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
GPIO_PinOutput = 0, /*!< 设置引脚为输出 */
|
||||
GPIO_PinInput, /*!< 设置引脚为输出*/
|
||||
GPIO_PinInput_InternalPullup, /*!< 设置引脚为输入且内部上拉 */
|
||||
GPIO_PinOutput_HighCurrent, /*!< 设置引脚为输出,高电流驱动*/
|
||||
} GPIO_PinConfigType;
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
* @brief 切换FGPIO端口数据输出
|
||||
*
|
||||
* @param[in] pGPIO FGPIOA/FGPIOB.
|
||||
* @param[in] u32PinMask 32位引脚掩码 ( GPIO_PTA0_MASK, GPIO_PTA1_MASK...)
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void FGPIO_Toggle(FGPIO_Type *pFGPIO, uint32_t u32PinMask)
|
||||
{
|
||||
pFGPIO->PTOR = u32PinMask; /* 切换GPIO端口数据输出 */
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
* @brief 读取FGPIO端口数据输入寄存器
|
||||
*
|
||||
* @param[in] pGPIO FGPIOA/FGPIOB.
|
||||
*
|
||||
* @return FGPIO端口数据输入寄存器32值
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint32_t FGPIO_Read(FGPIO_Type *pFGPIO)
|
||||
{
|
||||
return (pFGPIO->PDIR); /*读端口数据输入寄存器*/
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
* @brief 写数据到FGPIO端口数据输出寄存
|
||||
*
|
||||
* @param[in] pGPIO FGPIOA/FGPIOB.
|
||||
* @param[in] u32Value 写入的数值
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void FGPIO_Write(FGPIO_Type *pFGPIO, uint32_t u32Value)
|
||||
{
|
||||
pFGPIO->PDOR = u32Value; /*写数据到端口数据输出寄存器*/
|
||||
}
|
||||
|
||||
void GPIO_DeInit(GPIO_Type *pGPIO);
|
||||
void GPIO_Init(GPIO_Type *pGPIO, uint32_t u32PinMask, GPIO_PinConfigType sGpioType);
|
||||
void GPIO_Toggle(GPIO_Type *pGPIO, uint32_t u32PinMask);
|
||||
void GPIO_Write(GPIO_Type *pGPIO, uint32_t u32Value);
|
||||
void GPIO_PinInit(GPIO_PinType GPIO_Pin, GPIO_PinConfigType GPIO_PinConfig);
|
||||
void GPIO_PinToggle(GPIO_PinType GPIO_Pin);
|
||||
void GPIO_PinSet(GPIO_PinType GPIO_Pin);
|
||||
void GPIO_PinClear(GPIO_PinType GPIO_Pin);
|
||||
uint32_t GPIO_Read(GPIO_Type *pGPIO);
|
||||
uint8_t GPIO_BitRead(GPIO_PinType GPIO_Pin);
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,601 @@
|
||||
#ifndef _GPIO_H_
|
||||
#define _GPIO_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
#include "stdint.h"
|
||||
#include "core_cm0plus.h"
|
||||
#include "bos.h"
|
||||
/******************************************************************************
|
||||
*宏定义,用于生位操作存储加载无符号字段提取(UBFX)硬件编码地址
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define GPIO_ALIAS_OFF 0x000F0000L
|
||||
#define BOS_BIT_EXTRACT(ADDR,bit,width) (*(volatile uint32_t *)(((uint32_t) (((uint32_t)&ADDR)-GPIO_ALIAS_OFF)) \
|
||||
| (BOS_OPCODE_BITFIELD <<26) \
|
||||
| ((bit & 0x1F)<<23) | ((width-1) & 0xF)<<19))
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* GPIO位带操作宏定义
|
||||
*
|
||||
******************************************************************************/
|
||||
#define PTA0_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,0) //PTA0端口数据输出为高
|
||||
#define PTA0_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,0) //PTA0端口数据输出为低
|
||||
#define PTA0_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,0) //PTA0端口输出切换
|
||||
|
||||
#define PTA1_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,1)
|
||||
#define PTA1_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,1)
|
||||
#define PTA1_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,1)
|
||||
|
||||
#define PTA2_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,2)
|
||||
#define PTA2_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,2)
|
||||
#define PTA2_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,2)
|
||||
|
||||
#define PTA3_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,3)
|
||||
#define PTA3_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,3)
|
||||
#define PTA3_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,3)
|
||||
|
||||
#define PTA4_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,4)
|
||||
#define PTA4_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,4)
|
||||
#define PTA4_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,4)
|
||||
|
||||
#define PTA5_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,5)
|
||||
#define PTA5_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,5)
|
||||
#define PTA5_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,5)
|
||||
|
||||
#define PTA6_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,6)
|
||||
#define PTA6_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,6)
|
||||
#define PTA6_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,6)
|
||||
|
||||
#define PTA7_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,7)
|
||||
#define PTA7_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,7)
|
||||
#define PTA7_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,7)
|
||||
|
||||
#define PTB0_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,8) //PTB0端口数据输出为高
|
||||
#define PTB0_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,8) //PTB0端口数据输出为低
|
||||
#define PTB0_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,8) //PTB0端口数据输出切换
|
||||
|
||||
#define PTB1_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,9)
|
||||
#define PTB1_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,9)
|
||||
#define PTB1_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,9)
|
||||
|
||||
#define PTB2_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,10)
|
||||
#define PTB2_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,10)
|
||||
#define PTB2_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,10)
|
||||
|
||||
#define PTB3_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,11)
|
||||
#define PTB3_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,11)
|
||||
#define PTB3_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,11)
|
||||
|
||||
#define PTB4_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,12)
|
||||
#define PTB4_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,12)
|
||||
#define PTB4_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,12)
|
||||
|
||||
#define PTB5_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,13)
|
||||
#define PTB5_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,13)
|
||||
#define PTB5_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,13)
|
||||
|
||||
#define PTB6_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,14)
|
||||
#define PTB6_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,14)
|
||||
#define PTB6_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,14)
|
||||
|
||||
#define PTB7_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,15)
|
||||
#define PTB7_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,15)
|
||||
#define PTB7_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,15)
|
||||
|
||||
#define PTC0_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,16) //PTC0端口数据输出为高
|
||||
#define PTC0_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,16) //PTC0端口数据输出为低
|
||||
#define PTC0_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,16) //PTC0端口数据输出切换
|
||||
|
||||
#define PTC1_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,17)
|
||||
#define PTC1_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,17)
|
||||
#define PTC1_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,17)
|
||||
|
||||
#define PTC2_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,18)
|
||||
#define PTC2_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,18)
|
||||
#define PTC2_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,18)
|
||||
|
||||
#define PTC3_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,19)
|
||||
#define PTC3_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,19)
|
||||
#define PTC3_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,19)
|
||||
|
||||
#define PTC4_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,20)
|
||||
#define PTC4_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,20)
|
||||
#define PTC4_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,20)
|
||||
|
||||
#define PTC5_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,21)
|
||||
#define PTC5_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,21)
|
||||
#define PTC5_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,21)
|
||||
|
||||
#define PTC6_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,22)
|
||||
#define PTC6_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,22)
|
||||
#define PTC6_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,22)
|
||||
|
||||
#define PTC7_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,23)
|
||||
#define PTC7_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,23)
|
||||
#define PTC7_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,23)
|
||||
|
||||
#define PTD0_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,24) //PTD0端口数据输出为高
|
||||
#define PTD0_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,24) //PTD0端口数据输出为低
|
||||
#define PTD0_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,24) //PTD0端口数据输出切换
|
||||
|
||||
#define PTD1_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,25)
|
||||
#define PTD1_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,25)
|
||||
#define PTD1_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,25)
|
||||
|
||||
#define PTD2_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,26)
|
||||
#define PTD2_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,26)
|
||||
#define PTD2_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,26)
|
||||
|
||||
#define PTD3_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,27)
|
||||
#define PTD3_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,27)
|
||||
#define PTD3_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,27)
|
||||
|
||||
#define PTD4_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,28)
|
||||
#define PTD4_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,28)
|
||||
#define PTD4_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,28)
|
||||
|
||||
#define PTD5_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,29)
|
||||
#define PTD5_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,29)
|
||||
#define PTD5_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,29)
|
||||
|
||||
#define PTD6_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,30)
|
||||
#define PTD6_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,30)
|
||||
#define PTD6_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,30)
|
||||
|
||||
#define PTD7_OUT_HIGH BOS_BIT_SET(&GPIOA->PDOR,31)
|
||||
#define PTD7_OUT_LOW BOS_BIT_CLEAR(&GPIOA->PDOR,31)
|
||||
#define PTD7_OUT_TOGGLE BOS_BIT_SET(&GPIOA->PTOR,31)
|
||||
|
||||
#define PTE0_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,0)
|
||||
#define PTE0_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,0)
|
||||
#define PTE0_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,0)
|
||||
|
||||
#define PTE1_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,1) //PTE0端口数据输出为高
|
||||
#define PTE1_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,1) //PTE0端口数据输出为低
|
||||
#define PTE1_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,1) //PTE0端口数据输出切换
|
||||
|
||||
#define PTE2_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,2)
|
||||
#define PTE2_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,2)
|
||||
#define PTE2_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,2)
|
||||
|
||||
#define PTE3_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,3)
|
||||
#define PTE3_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,3)
|
||||
#define PTE3_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,3)
|
||||
|
||||
#define PTE4_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,4)
|
||||
#define PTE4_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,4)
|
||||
#define PTE4_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,4)
|
||||
|
||||
#define PTE5_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,5)
|
||||
#define PTE5_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,5)
|
||||
#define PTE5_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,5)
|
||||
|
||||
#define PTE6_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,6)
|
||||
#define PTE6_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,6)
|
||||
#define PTE6_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,6)
|
||||
|
||||
#define PTE7_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,7)
|
||||
#define PTE7_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,7)
|
||||
#define PTE7_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,7)
|
||||
|
||||
#define PTF0_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,8) //PTF0端口数据输出为高
|
||||
#define PTF0_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,8) //PTF0端口数据输出为低
|
||||
#define PTF0_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,8) //PTF0端口数据输出切换
|
||||
|
||||
#define PTF1_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,9)
|
||||
#define PTF1_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,9)
|
||||
#define PTF1_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,9)
|
||||
|
||||
#define PTF2_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,10)
|
||||
#define PTF2_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,10)
|
||||
#define PTF2_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,10)
|
||||
|
||||
#define PTF3_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,11)
|
||||
#define PTF3_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,11)
|
||||
#define PTF3_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,11)
|
||||
|
||||
#define PTF4_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,12)
|
||||
#define PTF4_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,12)
|
||||
#define PTF4_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,12)
|
||||
|
||||
#define PTF5_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,13)
|
||||
#define PTF5_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,13)
|
||||
#define PTF5_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,13)
|
||||
|
||||
#define PTF6_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,14)
|
||||
#define PTF6_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,14)
|
||||
#define PTF6_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,14)
|
||||
|
||||
#define PTF7_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,15)
|
||||
#define PTF7_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,15)
|
||||
#define PTF7_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,15)
|
||||
|
||||
#define PTG0_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,16) //PTG0端口数据输出为高
|
||||
#define PTG0_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,16) //PTG0端口数据输出为低
|
||||
#define PTG0_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,16) //PTG0端口数据输出切换
|
||||
|
||||
#define PTG1_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,17)
|
||||
#define PTG1_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,17)
|
||||
#define PTG1_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,17)
|
||||
|
||||
#define PTG2_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,18)
|
||||
#define PTG2_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,18)
|
||||
#define PTG2_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,18)
|
||||
|
||||
#define PTG3_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,19)
|
||||
#define PTG3_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,19)
|
||||
#define PTG3_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,19)
|
||||
|
||||
#define PTG4_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,20)
|
||||
#define PTG4_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,20)
|
||||
#define PTG4_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,20)
|
||||
|
||||
#define PTG5_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,21)
|
||||
#define PTG5_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,21)
|
||||
#define PTG5_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,21)
|
||||
|
||||
#define PTG6_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,22)
|
||||
#define PTG6_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,22)
|
||||
#define PTG6_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,22)
|
||||
|
||||
#define PTG7_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,23)
|
||||
#define PTG7_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,23)
|
||||
#define PTG7_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,23)
|
||||
|
||||
#define PTH0_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,24) //PTH0端口数据输出为高
|
||||
#define PTH0_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,24) //PTH0端口数据输出为低
|
||||
#define PTH0_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,24) //PTH0端口数据输出切换
|
||||
|
||||
#define PTH1_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,25)
|
||||
#define PTH1_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,25)
|
||||
#define PTH1_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,25)
|
||||
|
||||
#define PTH2_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,26)
|
||||
#define PTH2_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,26)
|
||||
#define PTH2_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,26)
|
||||
|
||||
#define PTH3_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,27)
|
||||
#define PTH3_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,27)
|
||||
#define PTH3_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,27)
|
||||
|
||||
#define PTH4_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,28)
|
||||
#define PTH4_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,28)
|
||||
#define PTH4_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,28)
|
||||
|
||||
#define PTH5_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,29)
|
||||
#define PTH5_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,29)
|
||||
#define PTH5_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,29)
|
||||
|
||||
#define PTH6_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,30)
|
||||
#define PTH6_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,30)
|
||||
#define PTH6_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,30)
|
||||
|
||||
#define PTH7_OUT_HIGH BOS_BIT_SET(&GPIOB->PDOR,31)
|
||||
#define PTH7_OUT_LOW BOS_BIT_CLEAR(&GPIOB->PDOR,31)
|
||||
#define PTH7_OUT_TOGGLE BOS_BIT_SET(&GPIOB->PTOR,31)
|
||||
|
||||
#define PTA0_IN BOS_BIT_EXTRACT(GPIOA->PDIR,0,1) //读取PA0端口输入数据
|
||||
#define PTA1_IN BOS_BIT_EXTRACT(GPIOA->PDIR,1,1)
|
||||
#define PTA2_IN BOS_BIT_EXTRACT(GPIOA->PDIR,2,1)
|
||||
#define PTA3_IN BOS_BIT_EXTRACT(GPIOA->PDIR,3,1)
|
||||
#define PTA4_IN BOS_BIT_EXTRACT(GPIOA->PDIR,4,1)
|
||||
#define PTA5_IN BOS_BIT_EXTRACT(GPIOA->PDIR,5,1)
|
||||
#define PTA6_IN BOS_BIT_EXTRACT(GPIOA->PDIR,6,1)
|
||||
#define PTA7_IN BOS_BIT_EXTRACT(GPIOA->PDIR,7,1)
|
||||
|
||||
#define PTB0_IN BOS_BIT_EXTRACT(GPIOA->PDIR,8,1) //读取PB0端口输入数据
|
||||
#define PTB1_IN BOS_BIT_EXTRACT(GPIOA->PDIR,9,1)
|
||||
#define PTB2_IN BOS_BIT_EXTRACT(GPIOA->PDIR,10,1)
|
||||
#define PTB3_IN BOS_BIT_EXTRACT(GPIOA->PDIR,11,1)
|
||||
#define PTB4_IN BOS_BIT_EXTRACT(GPIOA->PDIR,12,1)
|
||||
#define PTB5_IN BOS_BIT_EXTRACT(GPIOA->PDIR,13,1)
|
||||
#define PTB6_IN BOS_BIT_EXTRACT(GPIOA->PDIR,14,1)
|
||||
#define PTB7_IN BOS_BIT_EXTRACT(GPIOA->PDIR,15,1)
|
||||
|
||||
#define PTC0_IN BOS_BIT_EXTRACT(GPIOA->PDIR,16,1) //读取PC0端口输入数据
|
||||
#define PTC1_IN BOS_BIT_EXTRACT(GPIOA->PDIR,17,1)
|
||||
#define PTC2_IN BOS_BIT_EXTRACT(GPIOA->PDIR,18,1)
|
||||
#define PTC3_IN BOS_BIT_EXTRACT(GPIOA->PDIR,19,1)
|
||||
#define PTC4_IN BOS_BIT_EXTRACT(GPIOA->PDIR,20,1)
|
||||
#define PTC5_IN BOS_BIT_EXTRACT(GPIOA->PDIR,21,1)
|
||||
#define PTC6_IN BOS_BIT_EXTRACT(GPIOA->PDIR,22,1)
|
||||
#define PTC7_IN BOS_BIT_EXTRACT(GPIOA->PDIR,23,1)
|
||||
|
||||
#define PTD0_IN BOS_BIT_EXTRACT(GPIOA->PDIR,24,1) //读取PD0端口输入数据
|
||||
#define PTD1_IN BOS_BIT_EXTRACT(GPIOA->PDIR,25,1)
|
||||
#define PTD2_IN BOS_BIT_EXTRACT(GPIOA->PDIR,26,1)
|
||||
#define PTD3_IN BOS_BIT_EXTRACT(GPIOA->PDIR,27,1)
|
||||
#define PTD4_IN BOS_BIT_EXTRACT(GPIOA->PDIR,28,1)
|
||||
#define PTD5_IN BOS_BIT_EXTRACT(GPIOA->PDIR,29,1)
|
||||
#define PTD6_IN BOS_BIT_EXTRACT(GPIOA->PDIR,30,1)
|
||||
#define PTD7_IN BOS_BIT_EXTRACT(GPIOA->PDIR,31,1)
|
||||
|
||||
#define PTE0_IN BOS_BIT_EXTRACT(GPIOB->PDIR,0,1) //读取PE0端口输入数据
|
||||
#define PTE1_IN BOS_BIT_EXTRACT(GPIOB->PDIR,1,1)
|
||||
#define PTE2_IN BOS_BIT_EXTRACT(GPIOB->PDIR,2,1)
|
||||
#define PTE3_IN BOS_BIT_EXTRACT(GPIOB->PDIR,3,1)
|
||||
#define PTE4_IN BOS_BIT_EXTRACT(GPIOB->PDIR,4,1)
|
||||
#define PTE5_IN BOS_BIT_EXTRACT(GPIOB->PDIR,5,1)
|
||||
#define PTE6_IN BOS_BIT_EXTRACT(GPIOB->PDIR,6,1)
|
||||
#define PTE7_IN BOS_BIT_EXTRACT(GPIOB->PDIR,7,1)
|
||||
|
||||
#define PTF0_IN BOS_BIT_EXTRACT(GPIOB->PDIR,8,1) //读取PF0端口输入数据
|
||||
#define PTF1_IN BOS_BIT_EXTRACT(GPIOB->PDIR,9,1)
|
||||
#define PTF2_IN BOS_BIT_EXTRACT(GPIOB->PDIR,10,1)
|
||||
#define PTF3_IN BOS_BIT_EXTRACT(GPIOB->PDIR,11,1)
|
||||
#define PTF4_IN BOS_BIT_EXTRACT(GPIOB->PDIR,12,1)
|
||||
#define PTF5_IN BOS_BIT_EXTRACT(GPIOB->PDIR,13,1)
|
||||
#define PTF6_IN BOS_BIT_EXTRACT(GPIOB->PDIR,14,1)
|
||||
#define PTF7_IN BOS_BIT_EXTRACT(GPIOB->PDIR,15,1)
|
||||
|
||||
#define PTG0_IN BOS_BIT_EXTRACT(GPIOB->PDIR,16,1) //读取PG0端口输入数据 Modify
|
||||
#define PTG1_IN BOS_BIT_EXTRACT(GPIOB->PDIR,17,1)
|
||||
#define PTG2_IN BOS_BIT_EXTRACT(GPIOB->PDIR,18,1)
|
||||
#define PTG3_IN BOS_BIT_EXTRACT(GPIOB->PDIR,19,1)
|
||||
#define PTG4_IN BOS_BIT_EXTRACT(GPIOB->PDIR,20,1)
|
||||
#define PTG5_IN BOS_BIT_EXTRACT(GPIOB->PDIR,21,1)
|
||||
#define PTG6_IN BOS_BIT_EXTRACT(GPIOB->PDIR,22,1)
|
||||
#define PTG7_IN BOS_BIT_EXTRACT(GPIOB->PDIR,23,1)
|
||||
|
||||
#define PTH0_IN BOS_BIT_EXTRACT(GPIOB->PDIR,24,1) //读取PH0端口输入数据
|
||||
#define PTH1_IN BOS_BIT_EXTRACT(GPIOB->PDIR,25,1)
|
||||
#define PTH2_IN BOS_BIT_EXTRACT(GPIOB->PDIR,26,1)
|
||||
#define PTH3_IN BOS_BIT_EXTRACT(GPIOB->PDIR,27,1)
|
||||
#define PTH4_IN BOS_BIT_EXTRACT(GPIOB->PDIR,28,1)
|
||||
#define PTH5_IN BOS_BIT_EXTRACT(GPIOB->PDIR,29,1)
|
||||
#define PTH6_IN BOS_BIT_EXTRACT(GPIOB->PDIR,30,1)
|
||||
#define PTH7_IN BOS_BIT_EXTRACT(GPIOB->PDIR,31,1)
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义GPIO引脚名
|
||||
*
|
||||
*******************************************************************************/
|
||||
typedef enum
|
||||
{
|
||||
/* 用于GPIO */
|
||||
GPIO_PTA0 = 0, /*!< GPIO Pin PTA0 */
|
||||
GPIO_PTA1, /*!< GPIO Pin PTA1 */
|
||||
GPIO_PTA2, /*!< GPIO Pin PTA2 */
|
||||
GPIO_PTA3, /*!< GPIO Pin PTA3 */
|
||||
GPIO_PTA4, /*!< GPIO Pin PTA4 */
|
||||
GPIO_PTA5, /*!< GPIO Pin PTA5 */
|
||||
GPIO_PTA6, /*!< GPIO Pin PTA6 */
|
||||
GPIO_PTA7, /*!< GPIO Pin PTA7 */
|
||||
GPIO_PTB0, /*!< GPIO Pin PTB0 */
|
||||
GPIO_PTB1, /*!< GPIO Pin PTB1 */
|
||||
GPIO_PTB2, /*!< GPIO Pin PTB2 */
|
||||
GPIO_PTB3, /*!< GPIO Pin PTB3 */
|
||||
GPIO_PTB4, /*!< GPIO Pin PTB4 */
|
||||
GPIO_PTB5, /*!< GPIO Pin PTB5 */
|
||||
GPIO_PTB6, /*!< GPIO Pin PTB6 */
|
||||
GPIO_PTB7, /*!< GPIO Pin PTB7 */
|
||||
GPIO_PTC0, /*!< GPIO Pin PTC0 */
|
||||
GPIO_PTC1, /*!< GPIO Pin PTC1 */
|
||||
GPIO_PTC2, /*!< GPIO Pin PTC2 */
|
||||
GPIO_PTC3, /*!< GPIO Pin PTC3 */
|
||||
GPIO_PTC4, /*!< GPIO Pin PTC4 */
|
||||
GPIO_PTC5, /*!< GPIO Pin PTC5 */
|
||||
GPIO_PTC6, /*!< GPIO Pin PTC6 */
|
||||
GPIO_PTC7, /*!< GPIO Pin PTC7 */
|
||||
GPIO_PTD0, /*!< GPIO Pin PTD0 */
|
||||
GPIO_PTD1, /*!< GPIO Pin PTD1 */
|
||||
GPIO_PTD2, /*!< GPIO Pin PTD2 */
|
||||
GPIO_PTD3, /*!< GPIO Pin PTD3 */
|
||||
GPIO_PTD4, /*!< GPIO Pin PTD4 */
|
||||
GPIO_PTD5, /*!< GPIO Pin PTD5 */
|
||||
GPIO_PTD6, /*!< GPIO Pin PTD6 */
|
||||
GPIO_PTD7, /*!< GPIO Pin PTD7 */
|
||||
/* in GPIOB register */
|
||||
GPIO_PTE0, /*!< GPIO Pin PTE0 */
|
||||
GPIO_PTE1, /*!< GPIO Pin PTE1 */
|
||||
GPIO_PTE2, /*!< GPIO Pin PTE2 */
|
||||
GPIO_PTE3, /*!< GPIO Pin PTE3 */
|
||||
GPIO_PTE4, /*!< GPIO Pin PTE4 */
|
||||
GPIO_PTE5, /*!< GPIO Pin PTE5 */
|
||||
GPIO_PTE6, /*!< GPIO Pin PTE6 */
|
||||
GPIO_PTE7, /*!< GPIO Pin PTE7 */
|
||||
GPIO_PTF0, /*!< GPIO Pin PTF0 */
|
||||
GPIO_PTF1, /*!< GPIO Pin PTF1 */
|
||||
GPIO_PTF2, /*!< GPIO Pin PTF2 */
|
||||
GPIO_PTF3, /*!< GPIO Pin PTF3 */
|
||||
GPIO_PTF4, /*!< GPIO Pin PTF4 */
|
||||
GPIO_PTF5, /*!< GPIO Pin PTF5 */
|
||||
GPIO_PTF6, /*!< GPIO Pin PTF6 */
|
||||
GPIO_PTF7, /*!< GPIO Pin PTF7 */
|
||||
GPIO_PTG0, /*!< GPIO Pin PTG0 */
|
||||
GPIO_PTG1, /*!< GPIO Pin PTG1 */
|
||||
GPIO_PTG2, /*!< GPIO Pin PTG2 */
|
||||
GPIO_PTG3, /*!< GPIO Pin PTG3 */
|
||||
GPIO_PTG4, /*!< GPIO Pin PTG4 */
|
||||
GPIO_PTG5, /*!< GPIO Pin PTG5 */
|
||||
GPIO_PTG6, /*!< GPIO Pin PTG6 */
|
||||
GPIO_PTG7, /*!< GPIO Pin PTG7 */
|
||||
GPIO_PTH0, /*!< GPIO Pin PTH0 */
|
||||
GPIO_PTH1, /*!< GPIO Pin PTH1 */
|
||||
GPIO_PTH2, /*!< GPIO Pin PTH2 */
|
||||
GPIO_PTH3, /*!< GPIO Pin PTH3 */
|
||||
GPIO_PTH4, /*!< GPIO Pin PTH4 */
|
||||
GPIO_PTH5, /*!< GPIO Pin PTH5 */
|
||||
GPIO_PTH6, /*!< GPIO Pin PTH6 */
|
||||
GPIO_PTH7, /*!< GPIO Pin PTH7 */
|
||||
/* the following pins are not in NV322 */
|
||||
GPIO_PTI0, /*!< GPIO Pin PTI0 */
|
||||
GPIO_PTI1, /*!< GPIO Pin PTI1 */
|
||||
GPIO_PTI2, /*!< GPIO Pin PTI2 */
|
||||
GPIO_PTI3, /*!< GPIO Pin PTI3 */
|
||||
GPIO_PTI4, /*!< GPIO Pin PTI4 */
|
||||
GPIO_PTI5, /*!< GPIO Pin PTI5 */
|
||||
GPIO_PTI6, /*!< GPIO Pin PTI6 */
|
||||
GPIO_PTI7, /*!< GPIO Pin PTI7 */
|
||||
GPIO_PIN_MAX,
|
||||
} GPIO_PinType;
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义GPIO引脚掩码
|
||||
*
|
||||
*******************************************************************************/
|
||||
typedef enum
|
||||
{
|
||||
/* in GPIOA register */
|
||||
GPIO_PTA0_MASK = (1<<0), /*!< GPIO Pin PTA0 bit mask */
|
||||
GPIO_PTA1_MASK = (1<<1), /*!< GPIO Pin PTA1 bit mask */
|
||||
GPIO_PTA2_MASK = (1<<2), /*!< GPIO Pin PTA2 bit mask */
|
||||
GPIO_PTA3_MASK = (1<<3), /*!< GPIO Pin PTA3 bit mask */
|
||||
GPIO_PTA4_MASK = (1<<4), /*!< GPIO Pin PTA4 bit mask */
|
||||
GPIO_PTA5_MASK = (1<<5), /*!< GPIO Pin PTA5 bit mask */
|
||||
GPIO_PTA6_MASK = (1<<6), /*!< GPIO Pin PTA6 bit mask */
|
||||
GPIO_PTA7_MASK = (1<<7), /*!< GPIO Pin PTA7 bit mask */
|
||||
GPIO_PTB0_MASK = (1<<8), /*!< GPIO Pin PTB0 bit mask */
|
||||
GPIO_PTB1_MASK = (1<<9), /*!< GPIO Pin PTB1 bit mask */
|
||||
GPIO_PTB2_MASK = (1<<10), /*!< GPIO Pin PTB2 bit mask */
|
||||
GPIO_PTB3_MASK = (1<<11), /*!< GPIO Pin PTB3 bit mask */
|
||||
GPIO_PTB4_MASK = (1<<12), /*!< GPIO Pin PTB4 bit mask */
|
||||
GPIO_PTB5_MASK = (1<<13), /*!< GPIO Pin PTB5 bit mask */
|
||||
GPIO_PTB6_MASK = (1<<14), /*!< GPIO Pin PTB6 bit mask */
|
||||
GPIO_PTB7_MASK = (1<<15), /*!< GPIO Pin PTB7 bit mask */
|
||||
GPIO_PTC0_MASK = (1<<16), /*!< GPIO Pin PTC0 bit mask */
|
||||
GPIO_PTC1_MASK = (1<<17), /*!< GPIO Pin PTC1 bit mask */
|
||||
GPIO_PTC2_MASK = (1<<18), /*!< GPIO Pin PTC2 bit mask */
|
||||
GPIO_PTC3_MASK = (1<<19), /*!< GPIO Pin PTC3 bit mask */
|
||||
GPIO_PTC4_MASK = (1<<20), /*!< GPIO Pin PTC4 bit mask */
|
||||
GPIO_PTC5_MASK = (1<<21), /*!< GPIO Pin PTC5 bit mask */
|
||||
GPIO_PTC6_MASK = (1<<22), /*!< GPIO Pin PTC6 bit mask */
|
||||
GPIO_PTC7_MASK = (1<<23), /*!< GPIO Pin PTC7 bit mask */
|
||||
GPIO_PTD0_MASK = (1<<24), /*!< GPIO Pin PTD0 bit mask */
|
||||
GPIO_PTD1_MASK = (1<<25), /*!< GPIO Pin PTD1 bit mask */
|
||||
GPIO_PTD2_MASK = (1<<26), /*!< GPIO Pin PTD2 bit mask */
|
||||
GPIO_PTD3_MASK = (1<<27), /*!< GPIO Pin PTD3 bit mask */
|
||||
GPIO_PTD4_MASK = (1<<28), /*!< GPIO Pin PTD4 bit mask */
|
||||
GPIO_PTD5_MASK = (1<<29), /*!< GPIO Pin PTD5 bit mask */
|
||||
GPIO_PTD6_MASK = (1<<30), /*!< GPIO Pin PTD6 bit mask */
|
||||
GPIO_PTD7_MASK = (int)(0x80000000), /*!< GPIO Pin PTD7 bit mask ** thanks to @homeyou */
|
||||
/* in GPIOB register */
|
||||
GPIO_PTE0_MASK = (1<<0), /*!< GPIO Pin PTE0 bit mask */
|
||||
GPIO_PTE1_MASK = (1<<1), /*!< GPIO Pin PTE1 bit mask */
|
||||
GPIO_PTE2_MASK = (1<<2), /*!< GPIO Pin PTE2 bit mask */
|
||||
GPIO_PTE3_MASK = (1<<3), /*!< GPIO Pin PTE3 bit mask */
|
||||
GPIO_PTE4_MASK = (1<<4), /*!< GPIO Pin PTE4 bit mask */
|
||||
GPIO_PTE5_MASK = (1<<5), /*!< GPIO Pin PTE5 bit mask */
|
||||
GPIO_PTE6_MASK = (1<<6), /*!< GPIO Pin PTE6 bit mask */
|
||||
GPIO_PTE7_MASK = (1<<7), /*!< GPIO Pin PTE7 bit mask */
|
||||
GPIO_PTF0_MASK = (1<<8), /*!< GPIO Pin PTF0 bit mask */
|
||||
GPIO_PTF1_MASK = (1<<9), /*!< GPIO Pin PTF1 bit mask */
|
||||
GPIO_PTF2_MASK = (1<<10), /*!< GPIO Pin PTF2 bit mask */
|
||||
GPIO_PTF3_MASK = (1<<11), /*!< GPIO Pin PTF3 bit mask */
|
||||
GPIO_PTF4_MASK = (1<<12), /*!< GPIO Pin PTF4 bit mask */
|
||||
GPIO_PTF5_MASK = (1<<13), /*!< GPIO Pin PTF5 bit mask */
|
||||
GPIO_PTF6_MASK = (1<<14), /*!< GPIO Pin PTF6 bit mask */
|
||||
GPIO_PTF7_MASK = (1<<15), /*!< GPIO Pin PTF7 bit mask */
|
||||
GPIO_PTG0_MASK = (1<<16), /*!< GPIO Pin PTG0 bit mask */
|
||||
GPIO_PTG1_MASK = (1<<17), /*!< GPIO Pin PTG1 bit mask */
|
||||
GPIO_PTG2_MASK = (1<<18), /*!< GPIO Pin PTG2 bit mask */
|
||||
GPIO_PTG3_MASK = (1<<19), /*!< GPIO Pin PTG3 bit mask */
|
||||
GPIO_PTG4_MASK = (1<<20), /*!< GPIO Pin PTG4 bit mask */
|
||||
GPIO_PTG5_MASK = (1<<21), /*!< GPIO Pin PTG5 bit mask */
|
||||
GPIO_PTG6_MASK = (1<<22), /*!< GPIO Pin PTG6 bit mask */
|
||||
GPIO_PTG7_MASK = (1<<23), /*!< GPIO Pin PTG7 bit mask */
|
||||
GPIO_PTH0_MASK = (1<<24), /*!< GPIO Pin PTH0 bit mask */
|
||||
GPIO_PTH1_MASK = (1<<25), /*!< GPIO Pin PTH1 bit mask */
|
||||
GPIO_PTH2_MASK = (1<<26), /*!< GPIO Pin PTH2 bit mask */
|
||||
GPIO_PTH3_MASK = (1<<27), /*!< GPIO Pin PTH3 bit mask */
|
||||
GPIO_PTH4_MASK = (1<<28), /*!< GPIO Pin PTH4 bit mask */
|
||||
GPIO_PTH5_MASK = (1<<29), /*!< GPIO Pin PTH5 bit mask */
|
||||
GPIO_PTH6_MASK = (1<<30), /*!< GPIO Pin PTH6 bit mask */
|
||||
GPIO_PTH7_MASK = (int)(0x80000000), /*!< GPIO Pin PTH7 bit mask ** thanks to @homeyou */
|
||||
/* in GPIOC register */
|
||||
GPIO_PTI0_MASK = (1<<0), /*!< GPIO Pin PTI0 bit mask */
|
||||
GPIO_PTI1_MASK = (1<<1), /*!< GPIO Pin PTI1 bit mask */
|
||||
GPIO_PTI2_MASK = (1<<2), /*!< GPIO Pin PTI2 bit mask */
|
||||
GPIO_PTI3_MASK = (1<<3), /*!< GPIO Pin PTI3 bit mask */
|
||||
GPIO_PTI4_MASK = (1<<4), /*!< GPIO Pin PTI4 bit mask */
|
||||
GPIO_PTI5_MASK = (1<<5), /*!< GPIO Pin PTI5 bit mask */
|
||||
GPIO_PTI6_MASK = (1<<6), /*!< GPIO Pin PTI6 bit mask */
|
||||
GPIO_PTI7_MASK = (1<<7), /*!< GPIO Pin PTI7 bit mask */
|
||||
} GPIO_PinMaskType;
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
*定义GPIO引脚配置类型
|
||||
*
|
||||
*******************************************************************************/
|
||||
/*
|
||||
* . 如果引脚配置为输入,禁用高电流驱动
|
||||
* . 如果引脚配置为输出,禁用内部上拉
|
||||
* 仅PTH1/0, PTE1/0, PTD1/0, PTB5/4 支持高电流驱动.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
GPIO_PinOutput = 0, /*!< 设置引脚为输出 */
|
||||
GPIO_PinInput, /*!< 设置引脚为输出*/
|
||||
GPIO_PinInput_InternalPullup, /*!< 设置引脚为输入且内部上拉 */
|
||||
GPIO_PinOutput_HighCurrent, /*!< 设置引脚为输出,高电流驱动*/
|
||||
} GPIO_PinConfigType;
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
* @brief 切换FGPIO端口数据输出----通过32位掩码确定要切换输出的引脚
|
||||
*
|
||||
* @param[in] pGPIO 指向FGPIO模块, FGPIOA/FGPIOB.
|
||||
* @param[in] u32PinMask 32位引脚掩码 ( GPIO_PTA0_MASK, GPIO_PTA1_MASK ............)
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void FGPIO_Toggle(FGPIO_Type *pFGPIO, uint32_t u32PinMask)
|
||||
{
|
||||
pFGPIO->PTOR = u32PinMask; /* 切换GPIO端口数据输出 */
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
* @brief 读取FGPIO端口数据输入寄存器
|
||||
*
|
||||
* @param[in] pGPIO 指向FGPIO模块, FGPIOA/FGPIOB.
|
||||
*
|
||||
* @return FGPIO端口数据输入寄存器32值
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint32_t FGPIO_Read(FGPIO_Type *pFGPIO)
|
||||
{
|
||||
return (pFGPIO->PDIR); /*读端口数据输入寄存器*/
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
* @brief 写数据到FGPIO端口数据输出寄存
|
||||
*
|
||||
* @param[in] pGPIO 指向FGPIO模块, FGPIOA/FGPIOB.
|
||||
* @param[in] u32Value 写入的数值
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void FGPIO_Write(FGPIO_Type *pFGPIO, uint32_t u32Value)
|
||||
{
|
||||
pFGPIO->PDOR = u32Value; /*写数据到端口数据输出寄存器*/
|
||||
}
|
||||
|
||||
void GPIO_DeInit(GPIO_Type *pGPIO);
|
||||
void GPIO_Init(GPIO_Type *pGPIO, uint32_t u32PinMask, GPIO_PinConfigType sGpioType);
|
||||
void GPIO_Toggle(GPIO_Type *pGPIO, uint32_t u32PinMask);
|
||||
uint32_t GPIO_Read(GPIO_Type *pGPIO);
|
||||
void GPIO_Write(GPIO_Type *pGPIO, uint32_t u32Value);
|
||||
void GPIO_PinInit(GPIO_PinType GPIO_Pin, GPIO_PinConfigType GPIO_PinConfig);
|
||||
void GPIO_PinToggle(GPIO_PinType GPIO_Pin);
|
||||
void GPIO_PinSet(GPIO_PinType GPIO_Pin);
|
||||
void GPIO_PinClear(GPIO_PinType GPIO_Pin);
|
||||
uint8_t GPIO_BitRead(GPIO_PinType GPIO_Pin);
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,347 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief ICS 驱动头文件.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef ICS_H_
|
||||
#define ICS_H_
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
/****************************************************************************!
|
||||
* @brief 时钟模式常量定义
|
||||
*
|
||||
***************************************************************************/
|
||||
enum
|
||||
{
|
||||
ICS_CLK_MODE_FEI = 1, /*!< FEI 模式 */
|
||||
ICS_CLK_MODE_FEE, /*!< FEE 模式 */
|
||||
ICS_CLK_MODE_FEE_OSC, /*!< FEE 模式 OSC输出时钟源选择来自EXTAL引脚的外部时钟源 */
|
||||
ICS_CLK_MODE_FBE, /*!< FBE 模式 */
|
||||
ICS_CLK_MODE_FBE_OSC, /*!< FBE 模式 OSC输出时钟源选择来自EXTAL引脚的外部时钟源 */
|
||||
ICS_CLK_MODE_FBI, /*!< FBI 模式 */
|
||||
ICS_CLK_MODE_FBILP, /*!< FBILP 模式 */
|
||||
ICS_CLK_MODE_FBELP, /*!< FBELP 模式 */
|
||||
};
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 将时钟模式从当前模式切换到另一个时钟模式.
|
||||
*
|
||||
* 时钟模式宏观定义如下:
|
||||
* FEI, FBI, FEE, FBE, FBILP, FBELP, FEE_OSC, FBE_OSC
|
||||
* 注:FEE_OSC, FBE_OSC 不能用作当前时钟模式. 当前时钟模式和要切换到的时钟模式组合如下:
|
||||
* < 当前时钟模式,要切换到的时钟模式>
|
||||
* <FEI,FEE>, <FEI,FBI>, <FEI,FBE>, <FEI,FBE_OSC>, <FEI,FEE_OSC>, <FEE,FEI>,
|
||||
* <FEE,FBI>, <FEE,FBE>, <FBI,FBE>, <FBI,FEE>, <FBI,FBILP>, <FBI,FEI>,
|
||||
* <FBE,FBI>, <FBE,FEE>, <FBE,FEI>, <FBE,FBELP>, <FBELP,FBE>, <FBILP,FBI>.
|
||||
*
|
||||
* @param[in] CurMode 当前时钟模式
|
||||
* @param[in] NewMode 要切换到的时钟模式
|
||||
* @param[in] clkFreq 参考时钟频率
|
||||
*
|
||||
* @return none
|
||||
* @warning FEE_OSC, FBE_OSC 不能用作当前时钟模式.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define ICS_SwitchMode(CurMode, NewMode, clkFreq) CurMode##_to_##NewMode(clkFreq)
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* 定义 OSC 配置结构体
|
||||
*
|
||||
*******************************************************************************/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t bRange : 1; /*!< 1: 高频范围, 0: 低频范围 */
|
||||
uint8_t bGain : 1; /*!< 1: 高增益, 0:低增益 */
|
||||
uint8_t bEnable : 1; /*!< 1: 使能OSC, 0: 禁用OSC */
|
||||
uint8_t bStopEnable : 1; /*!< 1: 停止模式下OSC使能, 0: 停止模式下OSC禁用 */
|
||||
uint8_t bIsCryst : 1; /*!< 1: OSC输出选择振荡器时钟, 0: OSC输出选择来自extal引脚的外部时钟 */
|
||||
uint8_t bWaitInit : 1; /*!< 1: 等待振荡器初始化完成, 0: 不等待 */
|
||||
} OSC_ConfigType, *OSC_ConfigPtr;
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* ICS配置结构体
|
||||
*
|
||||
*******************************************************************************/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t u8ClkMode; /*!< 选择时钟模式*/
|
||||
uint8_t bLPEnable; /*!< 低功耗模式下使能 */
|
||||
uint32_t u32ClkFreq; /*!< 参考时钟频率 */
|
||||
OSC_ConfigType oscConfig; /*!< OSC 配置 */
|
||||
} ICS_ConfigType ;
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能中断.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @see ICS_DisableInt
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ICS_EnableInt(void)
|
||||
{
|
||||
ICS->C4 |= (ICS_C4_LOLIE_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用中断
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @see ICS_EnableInt
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ICS_DisableInt(void)
|
||||
{
|
||||
ICS->C4 &= ~(ICS_C4_LOLIE_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能时钟监控
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @see ICS_DisableClockMonitor
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ICS_EnableClockMonitor(void)
|
||||
{
|
||||
ICS->C4 |= (ICS_C4_CME_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用时钟监控
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @see ICS_EnableClockMonitor
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ICS_DisableClockMonitor(void)
|
||||
{
|
||||
ICS->C4 &= ~(ICS_C4_CME_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置ICS输出时钟源分频
|
||||
*
|
||||
* @param[in] busDivide -- 分频值
|
||||
*
|
||||
* @return depends on commands
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void ICS_SetBusDivider(uint8_t u8BusDivide)
|
||||
{
|
||||
ICS->C2 = (ICS->C2 & ~(ICS_C2_BDIV_MASK)) | ICS_C2_BDIV(u8BusDivide);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能OSC
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void OSC_Enable(void)
|
||||
{
|
||||
OSC->CR |= (OSC_CR_OSCEN_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用OSC
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void OSC_Disable(void)
|
||||
{
|
||||
OSC->CR &= ~(OSC_CR_OSCEN_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置OSC模块的频率范围为低频范围
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void OSC_SetLowRange(void)
|
||||
{
|
||||
OSC->CR &= ~(OSC_CR_RANGE_MASK);
|
||||
}
|
||||
|
||||
/*!***************************************************************************//*!
|
||||
+FUNCTION----------------------------------------------------------------
|
||||
*
|
||||
* @brief 设置OSC模块的频率范围为高频范围
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void OSC_SetHighRange(void)
|
||||
{
|
||||
OSC->CR |= (OSC_CR_RANGE_MASK);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置OSC的工作模式为高增益模式
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void OSC_SetHighGain(void)
|
||||
{
|
||||
OSC->CR |= (OSC_CR_HGO_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置OSC的工作模式为低功耗模式
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void OSC_SetLowGain(void)
|
||||
{
|
||||
OSC->CR &= ~(OSC_CR_HGO_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 选择OSC模块的输出时钟源为振荡器时钟源
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void OSC_SelectCrystal(void)
|
||||
{
|
||||
OSC->CR |= (OSC_CR_OSCOS_MASK);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief OSC输出选择来自extal引脚的外部时钟
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void OSC_SelectClock(void)
|
||||
{
|
||||
OSC->CR &= ~(OSC_CR_OSCOS_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 在停止模式下OSC模块使能
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void OSC_ActiveInStop(void)
|
||||
{
|
||||
OSC->CR |= (OSC_CR_OSCSTEN_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 在停止模式下OSC模块禁用
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void OSC_InactiveInStop(void)
|
||||
{
|
||||
OSC->CR &= ~(OSC_CR_OSCSTEN_MASK);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void ICS_Init(ICS_ConfigType *pConfig);
|
||||
void ICS_DeInit(void);
|
||||
void ICS_SetClkDivider(uint32_t u32ClkFreqKHz);
|
||||
void ICS_Trim(uint16 u16TrimValue);
|
||||
void OSC_Init(OSC_ConfigType *pConfig);
|
||||
void OSC_DeInit(void);
|
||||
|
||||
/************** 内联函数 ******************/
|
||||
void ICS_DisableClockMonitor(void);
|
||||
void ICS_DisableInt(void);
|
||||
void ICS_EnableClockMonitor(void);
|
||||
void ICS_EnableInt(void);
|
||||
void ICS_SetBusDivider(uint8_t u8BusDivide);
|
||||
void OSC_ActiveInStop(void);
|
||||
void OSC_Enable(void);
|
||||
void OSC_Disable(void);
|
||||
void OSC_InactiveInStop(void);
|
||||
void OSC_SelectClock(void);
|
||||
void OSC_SelectCrystal(void);
|
||||
void OSC_SetHighGain(void);
|
||||
void OSC_SetHighRange(void);
|
||||
void OSC_SetLowGain(void);
|
||||
void OSC_SetLowRange(void);
|
||||
|
||||
/* do not touch the following functions */
|
||||
void FEI_to_FEE(ICS_ConfigType *pConfig);
|
||||
void FEI_to_FBI(ICS_ConfigType *pConfig);
|
||||
void FEI_to_FBE(ICS_ConfigType *pConfig);
|
||||
void FEE_to_FBI(ICS_ConfigType *pConfig);
|
||||
void FEE_to_FEI(ICS_ConfigType *pConfig);
|
||||
void FEE_to_FBE(ICS_ConfigType *pConfig);
|
||||
void FBE_to_FEE(ICS_ConfigType *pConfig);
|
||||
void FBE_to_FEI(ICS_ConfigType *pConfig);
|
||||
void FBE_to_FBI(ICS_ConfigType *pConfig);
|
||||
void FBE_to_FBELP(ICS_ConfigType *pConfig);
|
||||
void FBI_to_FEI(ICS_ConfigType *pConfig);
|
||||
void FBI_to_FBE(ICS_ConfigType *pConfig);
|
||||
void FBI_to_FEE(ICS_ConfigType *pConfig);
|
||||
void FBI_to_FBILP(ICS_ConfigType *pConfig);
|
||||
void FBILP_to_FBI(ICS_ConfigType *pConfig);
|
||||
void FBELP_to_FBE(ICS_ConfigType *pConfig);
|
||||
void FEI_to_FBE_OSC(ICS_ConfigType *pConfig);
|
||||
void FEI_to_FEE_OSC(ICS_ConfigType *pConfig);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,577 @@
|
||||
/*********************************************************************!
|
||||
* 技术讨论:QQ群 123763203
|
||||
* 官网 :www.navota.com
|
||||
*
|
||||
* @file i2c.c
|
||||
* @brief i2c通讯接口函数库
|
||||
* @author Navota
|
||||
* @date 2017-1-1
|
||||
************************************************************************/
|
||||
#include "common.h"
|
||||
#include "i2c.h"
|
||||
|
||||
|
||||
/*!
|
||||
* @brief 存放回调入口
|
||||
*
|
||||
*/
|
||||
static I2C_CallbackType I2C_Callback[2] = {(I2C_CallbackType)NULL};
|
||||
|
||||
void I2C0_Isr( void );
|
||||
|
||||
/******************************************************************************
|
||||
* 定义I2C的接口函数
|
||||
*******************************************************************************/
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 初始化I2C模块.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
* @param[in] pI2CConfig 配置I2C的结构体.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
void I2C_Init(I2C_Type *pI2Cx,I2C_ConfigPtr pI2CConfig)
|
||||
{
|
||||
uint8_t u8Temp;
|
||||
|
||||
#if defined(CPU_NV32)
|
||||
SIM->SCGC |= SIM_SCGC_IIC_MASK;
|
||||
#endif
|
||||
|
||||
I2C_SetBaudRate(pI2Cx,pI2CConfig->u16F);
|
||||
I2C_SetSlaveAddress(pI2Cx,pI2CConfig->u16OwnA1);
|
||||
pI2Cx->FLT = (uint8_t)pI2CConfig->u16Filt;
|
||||
pI2Cx->RA = (uint8_t)pI2CConfig->u16RangeA & 0xfe;
|
||||
I2C_SetSCLLowETMeout(pI2Cx,pI2CConfig->u16Slt);
|
||||
|
||||
/* 配置控制寄存器C2 */
|
||||
u8Temp = 0;
|
||||
if( pI2CConfig->sSetting.bGCAEn )
|
||||
{
|
||||
u8Temp |= I2C_C2_GCAEN_MASK;
|
||||
}
|
||||
if( pI2CConfig->sSetting.bAddressExt )
|
||||
{
|
||||
u8Temp |= I2C_C2_ADEXT_MASK;
|
||||
}
|
||||
if( pI2CConfig->sSetting.bRangeAddEn )
|
||||
{
|
||||
u8Temp |= I2C_C2_RMEN_MASK;
|
||||
}
|
||||
pI2Cx->C2 |= u8Temp;
|
||||
|
||||
/* 配置寄存器SMB */
|
||||
u8Temp = 0;
|
||||
if( pI2CConfig->sSetting.bFackEn )
|
||||
{
|
||||
u8Temp |= I2C_SMB_FACK_MASK;
|
||||
}
|
||||
if( pI2CConfig->sSetting.bSMB_AlertEn )
|
||||
{
|
||||
u8Temp |= I2C_SMB_ALERTEN_MASK;
|
||||
}
|
||||
if( pI2CConfig->sSetting.bSecondAddressEn )
|
||||
{
|
||||
u8Temp |= I2C_SMB_SIICAEN_MASK;
|
||||
}
|
||||
if( pI2CConfig->sSetting.bSHTF2IntEn )
|
||||
{
|
||||
u8Temp |= I2C_SMB_SHTF2IE_MASK;
|
||||
}
|
||||
pI2Cx->SMB = u8Temp;
|
||||
|
||||
/* 配置寄存器C1 */
|
||||
u8Temp = 0;
|
||||
if( pI2CConfig->sSetting.bIntEn )
|
||||
{
|
||||
u8Temp |= I2C_C1_IICIE_MASK;
|
||||
if(pI2Cx == I2C0)
|
||||
{
|
||||
NVIC_EnableIRQ(I2C0_IRQn);
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
if( pI2CConfig->sSetting.bWakeUpEn )
|
||||
{
|
||||
u8Temp |= I2C_C1_WUEN_MASK;
|
||||
}
|
||||
if( pI2CConfig->sSetting.bI2CEn )
|
||||
{
|
||||
u8Temp |= I2C_C1_IICEN_MASK;
|
||||
}
|
||||
pI2Cx->C1 = u8Temp;
|
||||
|
||||
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 发送I2C起始信号(启动传输).
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return 错误状态
|
||||
*
|
||||
*****************************************************************************/
|
||||
uint8_t I2C_Start(I2C_Type *pI2Cx)
|
||||
{
|
||||
uint32_t u32ETMeout;
|
||||
uint8_t u8ErrorStatus;
|
||||
|
||||
u32ETMeout = 0;
|
||||
u8ErrorStatus = 0x00;
|
||||
|
||||
I2C_TxEnable(pI2Cx);//将 I2C 配置成 TX 发送模式
|
||||
pI2Cx->C1 |= I2C_C1_MST_MASK;//将 I2C 配置成主机模式
|
||||
|
||||
//持续监测起始位有没有发送成功
|
||||
while( (!I2C_IsBusy(pI2Cx)) && ( u32ETMeout < I2C_WAIT_STATUS_ETMEOUT))
|
||||
{
|
||||
u32ETMeout ++;
|
||||
}
|
||||
|
||||
if( u32ETMeout == I2C_WAIT_STATUS_ETMEOUT )
|
||||
{
|
||||
u8ErrorStatus |= I2C_ERROR_START_NO_BUSY_FLAG;
|
||||
}
|
||||
|
||||
return u8ErrorStatus;//返回错误标志,为0x10即起始信号没有发送成功
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 发送停止信号.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return 错误状态
|
||||
*
|
||||
*****************************************************************************/
|
||||
uint8_t I2C_Stop(I2C_Type *pI2Cx)
|
||||
{
|
||||
uint32_t u32ETMeout;
|
||||
uint8_t u8ErrorStatus;
|
||||
|
||||
u32ETMeout = 0;
|
||||
u8ErrorStatus = 0x00;
|
||||
|
||||
pI2Cx->C1 &= ~I2C_C1_MST_MASK;
|
||||
//持续监测 I2C 停止位是否发送成功
|
||||
while( (I2C_IsBusy(pI2Cx) ) && ( u32ETMeout < I2C_WAIT_STATUS_ETMEOUT))
|
||||
{
|
||||
u32ETMeout ++;
|
||||
}
|
||||
|
||||
if( u32ETMeout == I2C_WAIT_STATUS_ETMEOUT )
|
||||
{
|
||||
u8ErrorStatus |= I2C_ERROR_STOP_BUSY_FLAG;
|
||||
}
|
||||
|
||||
return u8ErrorStatus;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 发送重复起始位.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return 错误状态.
|
||||
*
|
||||
*****************************************************************************/
|
||||
uint8_t I2C_RepeatStart(I2C_Type *pI2Cx)
|
||||
{
|
||||
uint32_t u32ETMeout;
|
||||
uint8_t u8ErrorStatus;
|
||||
|
||||
u32ETMeout = 0;
|
||||
u8ErrorStatus = 0x00;
|
||||
|
||||
pI2Cx->C1 |= I2C_C1_RSTA_MASK;
|
||||
//持续监测起始位是否发送成功
|
||||
while( (!I2C_IsBusy(I2C0) ) && ( u32ETMeout < I2C_WAIT_STATUS_ETMEOUT))
|
||||
{
|
||||
u32ETMeout ++;
|
||||
}
|
||||
|
||||
if( u32ETMeout == I2C_WAIT_STATUS_ETMEOUT )
|
||||
{
|
||||
u8ErrorStatus |= I2C_ERROR_START_NO_BUSY_FLAG;
|
||||
}
|
||||
|
||||
return u8ErrorStatus;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置从机地址.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
* @param[in] u16SlaveAddress 从机地址.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void I2C_SetSlaveAddress(I2C_Type *pI2Cx,uint16_t u16SlaveAddress)
|
||||
{
|
||||
/* 写入8位地址 */
|
||||
pI2Cx->A1 = (uint8_t)u16SlaveAddress;
|
||||
|
||||
/* 如果支持十位从机地址, 写入高三位地址 */
|
||||
pI2Cx->C2 &= ~I2C_C2_AD_MASK;
|
||||
pI2Cx->C2 |= (uint8_t)(u16SlaveAddress>>8)&0x03;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用I2C中断.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void I2C_IntDisable(I2C_Type *pI2Cx)
|
||||
{
|
||||
pI2Cx->C1 &= ~I2C_C1_IICIE_MASK;
|
||||
if(pI2Cx == I2C0)
|
||||
{
|
||||
NVIC_DisableIRQ(I2C0_IRQn);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能I2C中断.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void I2C_IntEnable(I2C_Type *pI2Cx)
|
||||
{
|
||||
pI2Cx->C1 |= I2C_C1_IICIE_MASK;
|
||||
if(pI2Cx == I2C0)
|
||||
{
|
||||
NVIC_EnableIRQ(I2C0_IRQn);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置SCL低超时周期.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void I2C_SetSCLLowETMeout(I2C_Type *pI2Cx, uint16_t u16ETMeout)
|
||||
{
|
||||
pI2Cx->SLTL = (uint8_t)u16ETMeout;
|
||||
pI2Cx->SLTH = (uint8_t)(u16ETMeout>>8);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 复位I2C模块.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void I2C_Deinit(I2C_Type *pI2Cx)
|
||||
{
|
||||
pI2Cx->C1 &= ~I2C_C1_IICEN_MASK;
|
||||
#if defined(CPU_NV32)
|
||||
SIM->SCGC &= ~SIM_SCGC_IIC_MASK;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 发送单字节数据.
|
||||
*
|
||||
* @param[in] pI2Cx I2C模块的基址.
|
||||
* @param[in] u8WrBuff 要写的数据缓冲区.
|
||||
*
|
||||
* @return 错误状态
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
uint8_t I2C_WriteOneByte(I2C_Type *pI2Cx, uint8_t u8WrBuff)
|
||||
{
|
||||
uint32_t u32ETMeout;
|
||||
uint8_t u8ErrorStatus;
|
||||
|
||||
u32ETMeout = 0;
|
||||
u8ErrorStatus = 0x00;
|
||||
while (((I2C_GetStatus(pI2Cx)&I2C_S_TCF_MASK) != I2C_S_TCF_MASK)
|
||||
&& (u32ETMeout<I2C_WAIT_STATUS_ETMEOUT))
|
||||
{
|
||||
u32ETMeout ++;
|
||||
}
|
||||
if (u32ETMeout >= I2C_WAIT_STATUS_ETMEOUT)
|
||||
{
|
||||
u8ErrorStatus |= I2C_ERROR_NO_WAIT_TCF_FLAG;
|
||||
return u8ErrorStatus;
|
||||
}
|
||||
|
||||
I2C_TxEnable(pI2Cx); //将 I2C 配置成 TX 输出模式
|
||||
I2C_WriteDataReg(pI2Cx,u8WrBuff); //写数据寄存器发送数据
|
||||
|
||||
u32ETMeout = 0;
|
||||
while (((I2C_GetStatus(pI2Cx)&I2C_S_IICIF_MASK) != I2C_S_IICIF_MASK)
|
||||
&& (u32ETMeout<I2C_WAIT_STATUS_ETMEOUT))
|
||||
{
|
||||
u32ETMeout ++;
|
||||
}
|
||||
if (u32ETMeout >= I2C_WAIT_STATUS_ETMEOUT)
|
||||
{
|
||||
u8ErrorStatus |= I2C_ERROR_NO_WAIT_IICIF_FLAG;
|
||||
return u8ErrorStatus;
|
||||
}
|
||||
|
||||
/* 清除中断标志位 */
|
||||
I2C_ClearStatus(pI2Cx,I2C_S_IICIF_MASK);
|
||||
if (I2C_GetStatus(pI2Cx) & I2C_S_RXAK_MASK)
|
||||
{
|
||||
u8ErrorStatus |= I2C_ERROR_NO_GET_ACK;
|
||||
}
|
||||
return u8ErrorStatus;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 读取单字节数据.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
* @param[out] pRdBuff 所要从从机读的地址.
|
||||
* @param[out] u8Ack 发送 ack or nack.
|
||||
*
|
||||
* @return 错误状态
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
uint8_t I2C_ReadOneByte(I2C_Type *pI2Cx, uint8_t *pRdBuff, uint8_t u8Ack)
|
||||
{
|
||||
uint32_t u32ETMeout;
|
||||
uint8_t u8ErrorStatus;
|
||||
|
||||
u32ETMeout = 0;
|
||||
u8ErrorStatus = 0x00;
|
||||
while (((I2C_GetStatus(pI2Cx)&I2C_S_TCF_MASK) != I2C_S_TCF_MASK)
|
||||
&& (u32ETMeout<I2C_WAIT_STATUS_ETMEOUT))
|
||||
{
|
||||
u32ETMeout ++;
|
||||
}
|
||||
if (u32ETMeout >= I2C_WAIT_STATUS_ETMEOUT)
|
||||
{
|
||||
u8ErrorStatus |= I2C_ERROR_NO_WAIT_TCF_FLAG;
|
||||
return u8ErrorStatus;
|
||||
}
|
||||
|
||||
I2C_RxEnable(pI2Cx); //将 I2C 配置为输入模式
|
||||
|
||||
if( u8Ack )
|
||||
{
|
||||
/* 发送 nack */
|
||||
I2C_SendNack(pI2Cx);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 发送 ack */
|
||||
I2C_SendAck(pI2Cx);
|
||||
}
|
||||
*pRdBuff = I2C_ReadDataReg(pI2Cx); //将读到的数据存放到参数里头
|
||||
|
||||
u32ETMeout = 0;
|
||||
//持续监测中断标志
|
||||
while (((I2C_GetStatus(pI2Cx)&I2C_S_IICIF_MASK) != I2C_S_IICIF_MASK)
|
||||
&& (u32ETMeout<I2C_WAIT_STATUS_ETMEOUT))
|
||||
{
|
||||
u32ETMeout ++;
|
||||
}
|
||||
if (u32ETMeout >= I2C_WAIT_STATUS_ETMEOUT)
|
||||
{
|
||||
u8ErrorStatus |= I2C_ERROR_NO_WAIT_IICIF_FLAG;
|
||||
return u8ErrorStatus;
|
||||
}
|
||||
|
||||
/*清除 IIC 中断标志位 */
|
||||
I2C_ClearStatus(pI2Cx,I2C_S_IICIF_MASK);
|
||||
|
||||
return u8ErrorStatus;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 发送数据到I2C,然后等待数据传送完成.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
* @param[in] u16SlaveAddress 16位从机地址.
|
||||
* @param[in] pWrBuff 需要发送数据的缓冲数组.
|
||||
* @param[in] u32Length 发送字节的数目.
|
||||
*
|
||||
* @return 错误状态
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
uint8_t I2C_MasterSendWait(I2C_Type *pI2Cx,uint16_t u16SlaveAddress,uint8_t *pWrBuff,uint32_t u32Length)
|
||||
{
|
||||
uint32_t i;
|
||||
uint8_t u8ErrorStatus;
|
||||
|
||||
/* 发送起始信号 */
|
||||
u8ErrorStatus = I2C_Start(pI2Cx);
|
||||
|
||||
/* 给从机发送从机地址 */
|
||||
u8ErrorStatus = I2C_WriteOneByte(pI2Cx,((uint8_t)u16SlaveAddress<<1) | I2C_WRITE);
|
||||
|
||||
/* 如果没有错误发生, 则继续发送字节*/
|
||||
if( u8ErrorStatus == I2C_ERROR_NULL )
|
||||
{
|
||||
for(i=0;i<u32Length;i++)
|
||||
{
|
||||
u8ErrorStatus = I2C_WriteOneByte(pI2Cx,pWrBuff[i]);
|
||||
if( u8ErrorStatus != I2C_ERROR_NULL )
|
||||
{
|
||||
return u8ErrorStatus;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*发送 I2C 停止位 */
|
||||
u8ErrorStatus = I2C_Stop(pI2Cx);
|
||||
|
||||
return u8ErrorStatus;
|
||||
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 读取多个字节并等待完成.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
* @param[in] u16SlaveAddress 从机地址.
|
||||
* @param[in] pRdBuff 用于接收数据的缓冲区.
|
||||
* @param[in] u32Length 接收数据的字节数.
|
||||
*
|
||||
* @return 错误状态
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
uint8_t I2C_MasterReadWait(I2C_Type *pI2Cx,uint16_t u16SlaveAddress,uint8_t *pRdBuff,uint32_t u32Length)
|
||||
{
|
||||
uint32_t i;
|
||||
uint8_t u8ErrorStatus;
|
||||
|
||||
/* 发送起始信号到总线 */
|
||||
u8ErrorStatus = I2C_Start(pI2Cx);
|
||||
|
||||
/* 给从机发送器件地址 */
|
||||
u8ErrorStatus = I2C_WriteOneByte(pI2Cx,((uint8_t)u16SlaveAddress<<1) | I2C_READ);
|
||||
|
||||
/* 如果没有错误发生, 则继续接收字节*/
|
||||
I2C_ReadOneByte(pI2Cx,&pRdBuff[0],I2C_SEND_ACK);
|
||||
|
||||
if( u8ErrorStatus == I2C_ERROR_NULL )
|
||||
{
|
||||
for(i=0;i<u32Length-1;i++)
|
||||
{
|
||||
u8ErrorStatus = I2C_ReadOneByte(pI2Cx,&pRdBuff[i],I2C_SEND_ACK);
|
||||
if( u8ErrorStatus != I2C_ERROR_NULL )
|
||||
{
|
||||
return u8ErrorStatus;
|
||||
}
|
||||
}
|
||||
u8ErrorStatus = I2C_ReadOneByte(pI2Cx,&pRdBuff[i],I2C_SEND_NACK);
|
||||
}
|
||||
/*发送停止信号 */
|
||||
u8ErrorStatus = I2C_Stop(pI2Cx);
|
||||
|
||||
return u8ErrorStatus;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置I2C模块的中断回调函数
|
||||
*
|
||||
* @param[in] pfnCallback 回调函数的地址
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
void I2C1_SetCallBack( I2C_CallbackType pCallBack )
|
||||
{
|
||||
I2C_Callback[1] = pCallBack;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置RTC模块的中断回调函数
|
||||
*
|
||||
* @param[in] pfnCallback 回调函数的地址
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
void I2C0_SetCallBack( I2C_CallbackType pCallBack )
|
||||
{
|
||||
I2C_Callback[0] = pCallBack;
|
||||
}
|
||||
/*! @} */
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief I2C0 中断服务函数.
|
||||
*
|
||||
* @param
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void I2C0_Isr( void )
|
||||
{
|
||||
if( I2C_Callback[0] )
|
||||
{
|
||||
I2C_Callback[0]();
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief I2C1 中断服务函数.
|
||||
*
|
||||
* @param
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void I2C1_Isr( void )
|
||||
{
|
||||
if( I2C_Callback[1] )
|
||||
{
|
||||
I2C_Callback[1]();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,503 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief I2C 驱动头文件.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef _I2C_H__
|
||||
#define _I2C_H__
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
/******************************************************************************
|
||||
* 定义I2C的读和写
|
||||
*
|
||||
*//*!
|
||||
* @{
|
||||
*******************************************************************************/
|
||||
#define I2C_READ 0x01 /*!< I2C 读 */
|
||||
#define I2C_WRITE 0x0 /*!< I2C 写 */
|
||||
/*! @} */
|
||||
|
||||
#define I2C_SEND_ACK 0 /*!< I2C 发送 ACK */
|
||||
#define I2C_SEND_NACK 1 /*!< I2C 发送 NACK */
|
||||
|
||||
#define I2C_WAIT_STATUS_ETMEOUT 200000
|
||||
|
||||
/******************************************************************************
|
||||
* 定义I2C错误状态
|
||||
*
|
||||
*//*!
|
||||
* @{
|
||||
*******************************************************************************/
|
||||
#define I2C_ERROR_NULL 0x00 /*!< I2C 工作成功*/
|
||||
#define I2C_ERROR_NO_WAIT_TCF_FLAG 0x01 /*!< I2C 等待传输完成超时*/
|
||||
#define I2C_ERROR_NO_WAIT_IICIF_FLAG 0x02 /*!< I2C 等待中断超时 */
|
||||
#define I2C_ERROR_NO_GET_ACK 0x04 /*!< I2C 没有得到 ACK */
|
||||
#define I2C_ERROR_START_NO_BUSY_FLAG 0x10 /*!< I2C 没有成功发送起始信号 */
|
||||
#define I2C_ERROR_STOP_BUSY_FLAG 0x20 /*!< I2C 没有成功发送停止信号 */
|
||||
#define I2C_ERROR_BUS_BUSY 0x80 /*!< I2C 总线繁忙错误 */
|
||||
/*! @} End of i2c_error_state_list */
|
||||
|
||||
/******************************************************************************
|
||||
* 定义I2C总线状态
|
||||
*
|
||||
*//*!
|
||||
* @{
|
||||
*******************************************************************************/
|
||||
#define I2C_BUS_NORMAL 0x00 /*!< I2C 总线正常 */
|
||||
#define I2C_BUS_SLTF 0x01 /*!< I2C 总线偏移一个FLAG */
|
||||
#define I2C_BUS_SHTF2 0x02 /*!< I2C 总线偏移两个FLAG */
|
||||
/*! @} */
|
||||
|
||||
|
||||
#define I2C_MODE_MASTER 1
|
||||
#define I2C_MODE_SLAVE 0
|
||||
#define I2C_ADDRESS_7BIT 0
|
||||
#define I2C_ADDRESS_10BIT 1
|
||||
#define I2C_ETMEOUT_BUS_CLOCK_DIV64 0
|
||||
#define I2C_ETMEOUT_BUS_CLOCK 1
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
*//*! @I2C控制参数结构体
|
||||
* @{
|
||||
*******************************************************************************/
|
||||
/*!
|
||||
* @I2C控制参数结构体.
|
||||
*
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint16_t bI2CEn :1; /*!< 使能I2C模块 */
|
||||
uint16_t bIntEn :1; /*!< 使能I2C中断 */
|
||||
uint16_t bWakeUpEn :1; /*!< I2C唤醒使能 */
|
||||
uint16_t bGCAEn :1; /*!< I2C通用启动地址使能 */
|
||||
uint16_t bAddressExt :1; /*!< I2C地址扩展选择 */
|
||||
uint16_t bRangeAddEn :1; /*!< 使能范围地址匹配 */
|
||||
uint16_t bFackEn :1; /*!< 使能快速ack */
|
||||
uint16_t bSMB_AlertEn :1; /*!< SMB 报警响应地址使能 */
|
||||
uint16_t bSecondAddressEn:1; /*!< 启用第二I2C地址 */
|
||||
uint16_t bETMeoutCountClockSelect:1; /*!< 超时计数器时钟选择 */
|
||||
uint16_t bSHTF2IntEn :1; /*!< SHTF2 中断使能 */
|
||||
uint16_t Reserve :5;
|
||||
}I2C_SettingType;
|
||||
/*! @} */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
*//*! @I2C配置结构体
|
||||
* @{
|
||||
*******************************************************************************/
|
||||
/*!
|
||||
* @I2C配置结构体.
|
||||
*
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
I2C_SettingType sSetting;
|
||||
uint16_t u16F; /*!< 设置I2C模块的波特率 */
|
||||
uint16_t u16OwnA1; /*!< 从机地址 */
|
||||
uint16_t u16OwnA2; /*!< SMBus使用的从机地址 */
|
||||
uint16_t u16RangeA; /*!< 范围地址 */
|
||||
uint16_t u16Filt; /*!< I2C输入干扰滤波器 */
|
||||
uint16_t u16Slt; /*!< SCL低超时周期 */
|
||||
|
||||
}I2C_ConfigType, *I2C_ConfigPtr;
|
||||
/*! @} */
|
||||
|
||||
/*!
|
||||
* @brief I2C 回调类型.
|
||||
*
|
||||
*/
|
||||
|
||||
typedef void (*I2C_CallbackType)(void);
|
||||
/*! @} */
|
||||
|
||||
/******************************************************************************
|
||||
******************************************************************************/
|
||||
|
||||
/*!
|
||||
* 内联函数
|
||||
*/
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 配置I2C发送模式.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void I2C_TxEnable(I2C_Type *pI2Cx)
|
||||
{
|
||||
pI2Cx->C1 |= I2C_C1_TX_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 配置I2C接收模式.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void I2C_RxEnable(I2C_Type *pI2Cx)
|
||||
{
|
||||
pI2Cx->C1 &= ~I2C_C1_TX_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置I2C波特率.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void I2C_SetBaudRate(I2C_Type *pI2Cx,uint32_t u32Bps)
|
||||
{
|
||||
pI2Cx->F = (uint8_t)u32Bps;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能通用地址启动.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void I2C_GeneralCallEnable(I2C_Type *pI2Cx)
|
||||
{
|
||||
pI2Cx->C2 |= I2C_C2_GCAEN_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief SMBus 报警响应地址使能.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void I2C_SMBusAlertEnable(I2C_Type *pI2Cx)
|
||||
{
|
||||
pI2Cx->SMB|= I2C_SMB_ALERTEN_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 范围地址匹配使能.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void I2C_RangeAddressEnable(I2C_Type *pI2Cx)
|
||||
{
|
||||
pI2Cx->C2 |= I2C_C2_RMEN_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief SHTF2 中断使能.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void I2C_SHTF2IntEnable(I2C_Type *pI2Cx)
|
||||
{
|
||||
pI2Cx->SMB |= I2C_SMB_SHTF2IE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 超时计数器时钟选择.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void I2C_ETMeoutCounterClockSelect(I2C_Type *pI2Cx, uint8_t u8Clock)
|
||||
{
|
||||
if( u8Clock )
|
||||
{
|
||||
pI2Cx->SMB |= I2C_SMB_TCKSEL_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
pI2Cx->SMB &= ~I2C_SMB_TCKSEL_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 获取I2C的状态.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return I2C的状态
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t I2C_GetStatus(I2C_Type *pI2Cx)
|
||||
{
|
||||
return pI2Cx->S;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 清除特定的状态.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void I2C_ClearStatus(I2C_Type *pI2Cx, uint8_t u8ClearFlag)
|
||||
{
|
||||
pI2Cx->S |= u8ClearFlag;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 写数据到数据寄存器.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void I2C_WriteDataReg(I2C_Type *pI2Cx, uint8_t u8DataBuff)
|
||||
{
|
||||
pI2Cx->D = u8DataBuff;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 从数据寄存器读取数据.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return I2C数据寄存器值
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t I2C_ReadDataReg(I2C_Type *pI2Cx )
|
||||
{
|
||||
return pI2Cx->D;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 检查I2C模式是否为发送.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return 是/否
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t I2C_IsTxMode(I2C_Type *pI2Cx )
|
||||
{
|
||||
return(pI2Cx->C1 & I2C_C1_TX_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 检查总线是否繁忙.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return 是/否
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t I2C_IsBusy(I2C_Type *pI2Cx )
|
||||
{
|
||||
return (pI2Cx->S & I2C_S_BUSY_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 确认信号是否被接收.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return 是/否
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t I2C_IsReceivedAck(I2C_Type *pI2Cx )
|
||||
{
|
||||
return (pI2Cx->S & I2C_S_RXAK_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 检查I2C是否为主机模式.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return 是/否.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t I2C_IsMasterMode(I2C_Type *pI2Cx )
|
||||
{
|
||||
return(pI2Cx->C1 & I2C_C1_MST_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 检查有无低超时发生.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return 是/否.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t I2C_IsSMB_SLTF(I2C_Type *pI2Cx )
|
||||
{
|
||||
return (pI2Cx->SMB & I2C_SMB_SLTF_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 检查有无高超时发生.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return 是/否.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t I2C_IsSMB_SHTF2(I2C_Type *pI2Cx )
|
||||
{
|
||||
return(pI2Cx->SMB & I2C_SMB_SHTF2_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 清除SCL低超时标志.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void I2C_ClearSLTF(I2C_Type *pI2Cx )
|
||||
{
|
||||
pI2Cx->SMB |= I2C_SMB_SLTF_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 清除高超时标志位2.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void I2C_ClearSHTF2(I2C_Type *pI2Cx )
|
||||
{
|
||||
pI2Cx->SMB |= I2C_SMB_SHTF2_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 发送信号ACK.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void I2C_SendAck(I2C_Type *pI2Cx )
|
||||
{
|
||||
pI2Cx->C1 &= ~I2C_C1_TXAK_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 发送信号NACK.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void I2C_SendNack(I2C_Type *pI2Cx )
|
||||
{
|
||||
pI2Cx->C1 |= I2C_C1_TXAK_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能第二I2C地址.
|
||||
*
|
||||
* @param[in] pI2Cx I2C的基址.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void I2C_SecondAddressEnable(I2C_Type *pI2Cx)
|
||||
{
|
||||
pI2Cx->SMB |= I2C_SMB_SIICAEN_MASK;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
******************************************************************************/
|
||||
void I2C_Init(I2C_Type *pI2Cx,I2C_ConfigPtr pI2CConfig);
|
||||
uint8_t I2C_Start(I2C_Type *pI2Cx);
|
||||
uint8_t I2C_Stop(I2C_Type *pI2Cx);
|
||||
uint8_t I2C_RepeatStart(I2C_Type *pI2Cx);
|
||||
uint8_t I2C_IsTxMode(I2C_Type *pI2Cx );
|
||||
uint8_t I2C_IsBusy(I2C_Type *pI2Cx );
|
||||
uint8_t I2C_IsReceivedAck(I2C_Type *pI2Cx );
|
||||
uint8_t I2C_IsMasterMode(I2C_Type *pI2Cx );
|
||||
void I2C_ClearSHTF2(I2C_Type *pI2Cx );
|
||||
void I2C_ClearSLTF(I2C_Type *pI2Cx );
|
||||
uint8_t I2C_IsSMB_SHTF2(I2C_Type *pI2Cx );
|
||||
uint8_t I2C_IsSMB_SLTF(I2C_Type *pI2Cx );
|
||||
void I2C_TxEnable(I2C_Type *pI2Cx);
|
||||
void I2C_RxEnable(I2C_Type *pI2Cx);
|
||||
void I2C_IntEnable(I2C_Type *pI2Cx);
|
||||
void I2C_IntDisable(I2C_Type *pI2Cx);
|
||||
void I2C_SetBaudRate(I2C_Type *pI2Cx,uint32_t u32Bps);
|
||||
void I2C_SetSlaveAddress(I2C_Type *pI2Cx,uint16_t u16SlaveAddress);
|
||||
void I2C_GeneralCallEnable(I2C_Type *pI2Cx);
|
||||
void I2C_SMBusAlertEnable(I2C_Type *pI2Cx);
|
||||
void I2C_RangeAddressEnable(I2C_Type *pI2Cx);
|
||||
void I2C_SHTF2IntEnable(I2C_Type *pI2Cx);
|
||||
void I2C_ETMeoutCounterClockSelect(I2C_Type *pI2Cx, uint8_t u8Clock);
|
||||
void I2C_SetSCLLowETMeout(I2C_Type *pI2Cx, uint16_t u16ETMeout);
|
||||
uint8_t I2C_GetStatus(I2C_Type *pI2Cx);
|
||||
void I2C_ClearStatus(I2C_Type *pI2Cx, uint8_t u8ClearFlag);
|
||||
void I2C_SendAck(I2C_Type *pI2Cx );
|
||||
void I2C_SendNack(I2C_Type *pI2Cx );
|
||||
void I2C_SecondAddressEnable(I2C_Type *pI2Cx);
|
||||
void I2C_ClearStatus(I2C_Type *pI2Cx, uint8_t u8ClearFlag);
|
||||
void I2C_WriteDataReg(I2C_Type *pI2Cx, uint8_t u8DataBuff);
|
||||
uint8_t I2C_ReadDataReg(I2C_Type *pI2Cx );
|
||||
void I2C_Deinit(I2C_Type *pI2Cx);
|
||||
uint8_t I2C_WriteOneByte(I2C_Type *pI2Cx, uint8_t u8WrBuff);
|
||||
uint8_t I2C_ReadOneByte(I2C_Type *pI2Cx, uint8_t *pRdBuff, uint8_t u8Ack);
|
||||
uint8_t I2C_MasterSendWait(I2C_Type *pI2Cx,uint16_t u16SlaveAddress,uint8_t *pWrBuff,uint32_t u32Length);
|
||||
uint8_t I2C_MasterReadWait(I2C_Type *pI2Cx,uint16_t u16SlaveAddress,uint8_t *pRdBuff,uint32_t u32Length);
|
||||
void I2C0_SetCallBack( I2C_CallbackType pCallBack );
|
||||
void I2C1_SetCallBack( I2C_CallbackType pCallBack );
|
||||
|
||||
/*! @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif //
|
||||
|
||||
|
||||
@@ -0,0 +1,252 @@
|
||||
/**************************************************************************!
|
||||
* 技术讨论:QQ群 123763203
|
||||
* 官网 :www.navota.com
|
||||
*
|
||||
* @file kbi.c
|
||||
* @brief 键盘中断(KBI)函数库
|
||||
* @author Navota
|
||||
* @date 2017-1-1
|
||||
****************************************************************************/
|
||||
#include "common.h"
|
||||
#include "kbi.h"
|
||||
|
||||
/****************************************************************************!
|
||||
* @ 存放KBI回调函数接口
|
||||
****************************************************************************/
|
||||
KBI_CallbackType KBI_Callback[KBI_MAX_NO] = {(KBI_CallbackType)NULL};
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 初始化KBI模块.
|
||||
*
|
||||
* @param[in] pKBI 指向KBI模块.
|
||||
* @param[in] pConfig 指向KBI配置结构体
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see KBI_DeInit.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void KBI_Init(KBI_Type *pKBI, KBI_ConfigType *pConfig)
|
||||
{
|
||||
#if defined(CPU_NV32)
|
||||
uint16_t i;
|
||||
uint8_t sc = 0;
|
||||
uint8_t u8Port;
|
||||
uint8_t u8PinPos;
|
||||
uint16_t u16PinMapping[KBI_MAX_NO][8] =
|
||||
{
|
||||
{
|
||||
0, 1, 2, 3, 8, 9, 10, 11 /* KBI0中断输入引脚在GPIOA寄存器中的位置*/
|
||||
},
|
||||
{
|
||||
24, 25, 26, 27, 28, 29, 30, 31 /*KBI1中断输入引脚在GPIOA寄存器中的位置*/
|
||||
}
|
||||
};
|
||||
#elif defined(CPU_NV32M3)
|
||||
uint16_t i;
|
||||
uint8_t sc = 0;
|
||||
uint8_t u8Port;
|
||||
uint8_t u8PinPos;
|
||||
uint16_t u16PinMapping[KBI_MAX_NO][8] =
|
||||
{
|
||||
{
|
||||
0, 1, 2, 3, 8, 9, 10, 11 /* KBI0中断输入引脚在GPIOA寄存器中的位置*/
|
||||
},
|
||||
{
|
||||
20, 21, 16, 17, 18, 19, 12, 13 /* KBI1中断输入引脚在GPIOA寄存器中的位置*/
|
||||
}
|
||||
};
|
||||
#elif defined(CPU_NV32M4)
|
||||
uint32_t i;
|
||||
uint32_t sc = 0;
|
||||
uint32_t u8Port;
|
||||
uint32_t u8PinPos;
|
||||
|
||||
uint32_t u16PinMapping[KBI_MAX_NO][KBI_MAX_PINS_PER_PORT] =
|
||||
{
|
||||
{/* KBI0P0~KBI0P31 中断输入引脚在GPIOA寄存器中的位置 */
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
|
||||
},
|
||||
{/* KBI1P0~KBI1P31中断输入引脚在GPIOA寄存器中的位置 */
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
if(KBI0 == pKBI)
|
||||
{
|
||||
SIM->SCGC |= SIM_SCGC_KBI0_MASK; /* 使能KBI0模块的总线时钟 */
|
||||
u8Port = 0;
|
||||
}
|
||||
else if (KBI1 == pKBI)
|
||||
{
|
||||
SIM->SCGC |= SIM_SCGC_KBI1_MASK; /* 使能KBI1模块的总线时钟 */
|
||||
u8Port = 1;
|
||||
}
|
||||
|
||||
/*设定KBI中断检测模式*/
|
||||
sc = pConfig->sBits.bMode;
|
||||
pKBI->SC = sc;
|
||||
|
||||
/* 配置KBI中断输入引脚 */
|
||||
for (i = 0; i < KBI_MAX_PINS_PER_PORT; i++)
|
||||
{
|
||||
if(pConfig->sPin[i].bEn)
|
||||
{
|
||||
pKBI->PE |= (1<<i); /* 使能I/O引脚为KBI中断输入引脚*/
|
||||
pKBI->ES = (pKBI->ES & ~(1<<i)) | (pConfig->sPin[i].bEdge << i);
|
||||
u8PinPos = u16PinMapping[u8Port][i];
|
||||
ASSERT(!(u8PinPos & 0x80));
|
||||
#if defined(CPU_NV32)|| defined(CPU_NV32M3)
|
||||
FGPIOA->PIDR &= ~(1<<u8PinPos); /* 使能GPIO输入*/
|
||||
FGPIOA->PDDR &= ~(1<<u8PinPos); /* 引脚配置为通用输入 */
|
||||
PORT->PUEL |= (1<<u8PinPos); /* 使能内部上拉*/
|
||||
#elif defined(CPU_NV32M4)
|
||||
if (u8Port == 0) /* KBI0 */
|
||||
{
|
||||
FGPIOA->PIDR &= ~(1<<u8PinPos); /* 使能GPIO输入*/
|
||||
FGPIOA->PDDR &= ~(1<<u8PinPos); /* 引脚配置为通用输入 */
|
||||
PORT->PUE0 |= (1<<u8PinPos); /* 使能内部上拉*/
|
||||
}
|
||||
else if (u8Port == 1) /* KBI1 */
|
||||
{
|
||||
FGPIOB->PIDR &= ~(1<<u8PinPos); /* 使能GPIO输入*/
|
||||
FGPIOB->PDDR &= ~(1<<u8PinPos); /* 引脚配置为通用输入 */
|
||||
PORT->PUE1 |= (1<<u8PinPos); /* 使能内部上拉*/
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CPU_NV32M4)
|
||||
/*Reset KBI_SP register*/
|
||||
sc = pConfig->sBits.bRstKbsp<<KBI_SC_RSTKBSP_SHIFT;
|
||||
pKBI->SC |= sc;
|
||||
|
||||
/*Real KBI_SP register enable*/
|
||||
sc = pConfig->sBits.bKbspEn<<KBI_SC_KBSPEN_SHIFT;
|
||||
pKBI->SC |= sc;
|
||||
#endif
|
||||
|
||||
/*清除中断标志位*/
|
||||
pKBI->SC = sc;
|
||||
|
||||
/* 使能KBI中断 */
|
||||
if(pConfig->sBits.bIntEn)
|
||||
{
|
||||
pKBI->SC |= KBI_SC_KBIE_MASK;
|
||||
|
||||
if(KBI0 == pKBI)
|
||||
{
|
||||
NVIC_EnableIRQ(KBI0_IRQn);
|
||||
}
|
||||
else
|
||||
{
|
||||
NVIC_EnableIRQ(KBI1_IRQn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置KBI回调函数,通过中断服务函数调用
|
||||
*
|
||||
* @param[in] pKBI 指向KBI模块.
|
||||
* @param[in] pfnCallback 指向回调函数.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @ Pass/ Fail criteria: none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void KBI_SetCallback(KBI_Type *pKBI, KBI_CallbackType pfnCallback)
|
||||
{
|
||||
if(KBI0 == pKBI)
|
||||
{
|
||||
KBI_Callback[0] = pfnCallback;
|
||||
}
|
||||
else
|
||||
{
|
||||
KBI_Callback[1] = pfnCallback;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 复位KBI模块.
|
||||
*
|
||||
* @param[in] pKBI 指向KBI模块.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see KBI_Init.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void KBI_DeInit(KBI_Type *pKBI)
|
||||
{
|
||||
if(KBI0 == pKBI)
|
||||
{
|
||||
NVIC_DisableIRQ(KBI0_IRQn);
|
||||
}
|
||||
else
|
||||
{
|
||||
NVIC_DisableIRQ(KBI1_IRQn);
|
||||
}
|
||||
|
||||
pKBI->PE = 0;
|
||||
pKBI->SC = 0;
|
||||
pKBI->ES = 0;
|
||||
|
||||
if(KBI0 == pKBI)
|
||||
{
|
||||
SIM->SCGC &= ~SIM_SCGC_KBI0_MASK; /* 禁用KBI0模块总线时钟 */
|
||||
}
|
||||
else
|
||||
{
|
||||
SIM->SCGC &= ~SIM_SCGC_KBI1_MASK; /* 禁用KBI1模块总线时钟 */
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief KBI0模块中断服务函数.
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
void KBI0_Isr(void)
|
||||
{
|
||||
KBI0->SC |= KBI_SC_KBACK_MASK; /*清除中断标志位 */
|
||||
|
||||
if(KBI_Callback[0])
|
||||
{
|
||||
KBI_Callback[0]();
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief KBI1模块中断服务函数
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
void KBI1_Isr(void)
|
||||
{
|
||||
KBI1->SC |= KBI_SC_KBACK_MASK; /*清除中断标志位*/
|
||||
|
||||
if(KBI_Callback[1])
|
||||
{
|
||||
KBI_Callback[1]();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,372 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief KBI 驱动头文件.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef _KBI_H_
|
||||
#define _KBI_H_
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
/********************************************************!
|
||||
*
|
||||
* @brief KBI模块中断输入信号检测模式选择
|
||||
*
|
||||
***********************************************************/
|
||||
typedef enum
|
||||
{
|
||||
KBI_MODE_EDGE_ONLY = 0, /*!< 选择 边沿检测 */
|
||||
KBI_MODE_EDGE_LEVEL /*!< 选择 边沿和电平检测*/
|
||||
}KBI_ModeType;
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
KBI_FALLING_EDGE_LOW_LEVEL = 0, /*!< 选择 下降沿或低电平 */
|
||||
KBI_RISING_EDGE_HIGH_LEVEL /*!< 选择 上升沿或高电平 */
|
||||
}KBI_EdgeType;
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义KBI模块个数和中断输入引脚个数
|
||||
*
|
||||
*******************************************************************************/
|
||||
#define KBI_MAX_NO 2 /*!< KBI模块个数 */
|
||||
|
||||
#if defined(CPU_NV32)|| defined(CPU_NV32M3)
|
||||
#define KBI_MAX_PINS_PER_PORT 8 /*!< KBI中断输入引脚个数 */
|
||||
#elif defined(CPU_NV32M4)
|
||||
#define KBI_MAX_PINS_PER_PORT 32 /*!< KBI中断输入引脚个数 */
|
||||
#endif
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* KBI回调函数声明
|
||||
******************************************************************************/
|
||||
typedef void (*KBI_CallbackType)(void);
|
||||
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* KBI引脚配置结构体
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t bEdge : 1; /*!< 边沿/电平选择为*/
|
||||
uint8_t bEn : 1; /*!< 引脚使能位*/
|
||||
uint8_t bRsvd : 6; /*!< 保留 */
|
||||
} KBI_PinConfigType;
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* KBI配置结构体
|
||||
*
|
||||
*******************************************************************************/
|
||||
/*!
|
||||
* @brief KBI状态和控制寄存器结构体.
|
||||
*
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
#if defined(CPU_NV32)|| defined(CPU_NV32M3)
|
||||
struct
|
||||
{
|
||||
uint8_t bMode : 1; /*!< 选择KBI检测模式 */
|
||||
uint8_t bIntEn : 1; /*!< 使能KBI中断位 */
|
||||
uint8_t bRsvd : 6; /*!< 保留 */
|
||||
} sBits;
|
||||
#elif defined(CPU_NV32M4)
|
||||
struct
|
||||
{
|
||||
uint32_t bMode : 1; /*!< 选择KBI检测模式 */
|
||||
uint32_t bIntEn : 1; /*!< 使能KBI中断位 */
|
||||
uint32_t bRsvd2 : 2; /*!< 保留 */
|
||||
uint32_t bKbspEn : 1; /*!<Real KBI_SP register enable*/
|
||||
uint32_t bRstKbsp: 1; /*!<Reset KBI_SP register*/
|
||||
uint32_t bRsvd26 : 26; /*!< reserved */
|
||||
} sBits;
|
||||
#endif
|
||||
KBI_PinConfigType sPin[KBI_MAX_PINS_PER_PORT];
|
||||
} KBI_ConfigType, *KBI_ConfigTypePtr;
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置仅下降沿检测.
|
||||
*
|
||||
* @param[in] pKBI 指向KBI模块.
|
||||
* @param[in] PinMasks KBI中断输入引脚号.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see KBI_DetectRisingEdge.
|
||||
*
|
||||
*****************************************************************************/
|
||||
#if defined(CPU_NV32)|| defined(CPU_NV32M3)
|
||||
__STATIC_INLINE void KBI_DetectFallingEdge(KBI_Type *pKBI, uint8_t PinMasks)
|
||||
#elif defined(CPU_NV32M4)
|
||||
__STATIC_INLINE void KBI_DetectFallingEdge(KBI_Type *pKBI, uint32_t PinMasks)
|
||||
#endif
|
||||
{
|
||||
pKBI->SC &= ~KBI_SC_KBMOD_MASK;
|
||||
pKBI->ES &= ~(PinMasks);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置仅高电平检测
|
||||
*
|
||||
* @param[in] pKBI 指向KBI模块.
|
||||
* @param[in] PinMasks KBI中断输入引脚号.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see KBI_DetectFallingEdge.
|
||||
*
|
||||
*****************************************************************************/
|
||||
#if defined(CPU_NV32)|| defined(CPU_NV32M3)
|
||||
__STATIC_INLINE void KBI_DetectRisingEdge(KBI_Type *pKBI, uint8_t PinMasks)
|
||||
#elif defined(CPU_NV32M4)
|
||||
__STATIC_INLINE void KBI_DetectRisingEdge(KBI_Type *pKBI, uint32_t PinMasks)
|
||||
#endif
|
||||
{
|
||||
pKBI->SC &= ~KBI_SC_KBMOD_MASK;
|
||||
pKBI->ES |= (PinMasks);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置上升沿和高电平检测
|
||||
*
|
||||
* @param[in] pKBI 指向KBI模块.
|
||||
* @param[in] PinMasks KBI中断输入引脚号.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see KBI_DetectFallingEdgeLowLevel.
|
||||
*
|
||||
*****************************************************************************/
|
||||
#if defined(CPU_NV32)|| defined(CPU_NV32M3)
|
||||
__STATIC_INLINE void KBI_DetectRisingEdgeHighLevel(KBI_Type *pKBI, uint8_t PinMasks)
|
||||
#elif defined(CPU_NV32M4)
|
||||
__STATIC_INLINE void KBI_DetectRisingEdgeHighLevel(KBI_Type *pKBI, uint32_t PinMasks)
|
||||
#endif
|
||||
{
|
||||
pKBI->SC |= KBI_SC_KBMOD_MASK;
|
||||
pKBI->ES |= (PinMasks);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置下降沿和低电平检测
|
||||
*
|
||||
* @param[in] pKBI 指向KBI模块.
|
||||
* @param[in] PinMasks KBI中断输入引脚号.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @ Pass/ Fail criteria: none.
|
||||
*
|
||||
* @see KBI_DetectRisingEdgeHighLevel.
|
||||
*
|
||||
*****************************************************************************/
|
||||
#if defined(CPU_NV32)|| defined(CPU_NV32M3)
|
||||
__STATIC_INLINE void KBI_DetectFallingEdgeLowLevel(KBI_Type *pKBI, uint8_t PinMasks)
|
||||
#elif defined(CPU_NV32M4)
|
||||
__STATIC_INLINE void KBI_DetectFallingEdgeLowLevel(KBI_Type *pKBI, uint32_t PinMasks)
|
||||
#endif
|
||||
{
|
||||
pKBI->SC |= KBI_SC_KBMOD_MASK;
|
||||
pKBI->ES &= ~(PinMasks);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能KBI中断输入引脚
|
||||
*
|
||||
* @param[in] pKBI 指向KBI模块..
|
||||
* @param[in] PinMasks KBI中断输入引脚号.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see KBI_Disable.
|
||||
*
|
||||
*****************************************************************************/
|
||||
#if defined(CPU_NV32)|| defined(CPU_NV32M3)
|
||||
__STATIC_INLINE void KBI_Enable(KBI_Type *pKBI, uint8_t PinMasks)
|
||||
#elif defined(CPU_NV32M4)
|
||||
__STATIC_INLINE void KBI_Enable(KBI_Type *pKBI, uint32_t PinMasks)
|
||||
#endif
|
||||
{
|
||||
pKBI->PE |= (PinMasks);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用KBI中断输入引脚.
|
||||
*
|
||||
* @param[in] pKBI 指向KBI模块..
|
||||
* @param[in] PinMasks KBI中断输入引脚号.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @see KBI_Enable.
|
||||
*
|
||||
*****************************************************************************/
|
||||
#if defined(CPU_NV32)|| defined(CPU_NV32M3)
|
||||
__STATIC_INLINE void KBI_Disable(KBI_Type *pKBI, uint8_t PinMasks)
|
||||
#elif defined(CPU_NV32M4)
|
||||
__STATIC_INLINE void KBI_Disable(KBI_Type *pKBI, uint32_t PinMasks)
|
||||
#endif
|
||||
{
|
||||
pKBI->PE &= ~(PinMasks);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能KBI中断
|
||||
*
|
||||
* @param[in] pKBI 指向KBI模块..
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*
|
||||
* @see KBI_DisableInt.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void KBI_EnableInt(KBI_Type *pKBI)
|
||||
{
|
||||
pKBI->SC |= KBI_SC_KBIE_MASK;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用KBI中断
|
||||
*
|
||||
* @param[in] pKBI 指向KBI模块.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*
|
||||
* @see KBI_EnableInt.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void KBI_DisableInt(KBI_Type *pKBI)
|
||||
{
|
||||
pKBI->SC &= ~KBI_SC_KBIE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 获取中断标志位
|
||||
*
|
||||
* @param[in] pKBI 指向KBI模块.
|
||||
*
|
||||
* @return uint8_t.
|
||||
*
|
||||
* @see KBI_ClrFlags.
|
||||
*
|
||||
*****************************************************************************/
|
||||
#if defined(CPU_NV32)|| defined(CPU_NV32M3)
|
||||
__STATIC_INLINE uint8_t KBI_GetFlags(KBI_Type *pKBI)
|
||||
#elif defined(CPU_NV32M4)
|
||||
__STATIC_INLINE uint32_t KBI_GetFlags(KBI_Type *pKBI)
|
||||
#endif
|
||||
{
|
||||
return (pKBI->SC & KBI_SC_KBF_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 清除中断标志位.
|
||||
*
|
||||
* @param[in] pKBI 指向KBI模块.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*
|
||||
* @see KBI_GetFlags.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void KBI_ClrFlags(KBI_Type *pKBI)
|
||||
{
|
||||
pKBI->SC |= KBI_SC_KBACK_MASK;
|
||||
}
|
||||
|
||||
#if defined(CPU_NV32M4)
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief Real KBI_SP register enable.
|
||||
*
|
||||
* @param[in] pKBI pointer to KBI module
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @ Pass/ Fail criteria: none
|
||||
*
|
||||
* @see The real ETMe value of Keyboard source pin to be read.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void KBI_SPEnable(KBI_Type *pKBI)
|
||||
{
|
||||
pKBI->SC |= KBI_SC_KBSPEN_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief Get KBI source pin register fields.
|
||||
*
|
||||
* @param[in] pKBI pointer to KBI module.
|
||||
*
|
||||
* @return uint32_t.
|
||||
*
|
||||
* @ Pass/ Fail criteria: none.
|
||||
*
|
||||
* @see KBI_GetSP.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint32_t KBI_GetSP(KBI_Type *pKBI)
|
||||
{
|
||||
return (pKBI->SP & KBI_SP_SP_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief Reset KBI_SP register.
|
||||
*
|
||||
* @param[in] pKBI pointer to KBI module
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
* @ Pass/ Fail criteria: none
|
||||
*
|
||||
* @see KBI_RstSP.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void KBI_RstSP(KBI_Type *pKBI)
|
||||
{
|
||||
pKBI->SC |= KBI_SC_RSTKBSP_MASK;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Global functions
|
||||
******************************************************************************/
|
||||
|
||||
void KBI_Init(KBI_Type *pKBI, KBI_ConfigType *pConfig);
|
||||
void KBI_SetCallback(KBI_Type *pKBI, KBI_CallbackType pfnCallback);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,317 @@
|
||||
/*!
|
||||
* 技术讨论:QQ群 123763203
|
||||
* 官网 :www.navota.com
|
||||
*
|
||||
* @file flash.c
|
||||
* @brief flash函数库
|
||||
* @author Navota
|
||||
* @date 2018-6-19
|
||||
*/
|
||||
|
||||
|
||||
#include "flash.h"
|
||||
|
||||
#define FLASH_ENABLE_STALLING_FLASH_CONTROLLER
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
+FUNCTION----------------------------------------------------------------
|
||||
* @function name: Flash_Init
|
||||
*
|
||||
* @brief 初始化FLASH
|
||||
*
|
||||
* @param
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
uint16_t Flash_Init(void)
|
||||
{
|
||||
uint16_t err = FLASH_ERR_SUCCESS;
|
||||
uint32_t clkDIV = BUS_CLK_HZ/1000000L - 1;
|
||||
uint32_t Tpgs =(285 *(BUS_CLK_HZ/100))/1000000L; //update 2016.8.4 by 光脚板のGG
|
||||
uint32_t Tprog =(675*(BUS_CLK_HZ/100))/1000000L; //by 光脚板のGG
|
||||
|
||||
|
||||
EFMCR=(clkDIV<<24) + 0x00000001; //divide to 1M hz
|
||||
EFMETM0=(Tpgs<<16) + 0x00001194; //0x00281194; //
|
||||
EFMETM1=(Tprog<<16) + 0x000088B8; //
|
||||
|
||||
return(err);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
+FUNCTION----------------------------------------------------------------
|
||||
* @function name: FlashProgram
|
||||
*
|
||||
* @brief flash加载编程:总的过程就是,给出字节长度,先写入满足两个字的个数,
|
||||
* 再写入剩余满足一个字的个数,最后写入剩余的字节数。
|
||||
*
|
||||
* @param[in] wNVMTargetAddress 所要存放的FLASH首地址
|
||||
* @param[in] *pData 所要存放的数据
|
||||
* @param[in] sizeBytes 字节长度
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
__ramfunc uint16_t Flash_Program(uint32_t wNVMTargetAddress, uint8_t *pData, uint16_t sizeBytes)
|
||||
{
|
||||
uint16_t err = FLASH_ERR_SUCCESS;
|
||||
uint16_t w2LongWordCount = sizeBytes>>3;//处理一下,得到2个字的个数
|
||||
uint8_t wLeftBytes = (sizeBytes & 0x07);//低位三个字节的个数
|
||||
uint16_t wLeftLongWords = wLeftBytes>>2;//低位中满一个字个数
|
||||
uint32_t wTargetAddress = wNVMTargetAddress;
|
||||
uint32_t dwData0,dwData1;
|
||||
uint32_t *pdwData = (uint32_t*)pData;//传参
|
||||
int i;
|
||||
//判断是否字对齐
|
||||
if(wNVMTargetAddress & 0x03)
|
||||
{
|
||||
err = FLASH_ERR_INVALID_PARAM;
|
||||
return (err);//返回无效的参数
|
||||
}
|
||||
//循环写入两个长字(即8个字节),共写入w2LongWordCount * 8个字节
|
||||
for(i = 0; i < w2LongWordCount; i++)
|
||||
{
|
||||
dwData0 = *pdwData++;
|
||||
dwData1 = *pdwData++;
|
||||
err = Flash_Program2LongWords(wTargetAddress, dwData0, dwData1);//加载两个字的编程
|
||||
if(err) //地址不为4个字节对齐,则直接跳转
|
||||
{
|
||||
goto EndP;
|
||||
//break;
|
||||
}
|
||||
wTargetAddress += 8;//循环一次写入8个字节,即2个字,NV32的flash是字对齐的
|
||||
}
|
||||
// 一个字的编程,即4bytes
|
||||
for(i = 0; i < wLeftLongWords; i++)
|
||||
{
|
||||
dwData0 = *pdwData++;
|
||||
err = Flash_Program1LongWord(wTargetAddress, dwData0);
|
||||
if(err)
|
||||
{
|
||||
goto EndP;
|
||||
//break;
|
||||
}
|
||||
wTargetAddress += 4;
|
||||
}
|
||||
wLeftBytes = (wLeftBytes-(wLeftLongWords<<2)); //在两字和一字的编程都处理完后剩余的低两位字节数
|
||||
if(!wLeftBytes){ //若无剩余字节数,返回成功
|
||||
return (err);
|
||||
}
|
||||
|
||||
#if defined(BIG_ENDIAN)
|
||||
dwData0 = 0;
|
||||
pData = (uint8_t*)pdwData;
|
||||
for(i = wLeftBytes; i >0; i--)
|
||||
{
|
||||
dwData0 <<= 8;
|
||||
dwData0 |= *pData++;
|
||||
}
|
||||
|
||||
wLeftBytes = 4 - wLeftBytes;
|
||||
for(i = wLeftBytes; i >0; i--)
|
||||
{
|
||||
dwData0 <<= 8;
|
||||
dwData0 |= 0xFF;
|
||||
}
|
||||
#else
|
||||
dwData0 = 0xFFFFFFFFL;
|
||||
pData = (uint8_t*)pdwData+wLeftBytes-1;
|
||||
for(i = wLeftBytes; i >0; i--)
|
||||
{
|
||||
dwData0 <<= 8;
|
||||
dwData0 |= *pData--;
|
||||
}
|
||||
#endif
|
||||
err = Flash_Program1LongWord(wTargetAddress, dwData0);
|
||||
EndP:
|
||||
return (err);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
|
||||
* @function name: FlashProgram1LongWord
|
||||
*
|
||||
* @brief 加载一个字的大小,编程到FLASH中(也就是四个字节)
|
||||
*
|
||||
* @param[in] wNVMTargetAddress 所要存放的FLASH首地址
|
||||
* @param[in] dwData 所要存放的数据
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__ramfunc uint16_t Flash_Program1LongWord(uint32_t wNVMTargetAddress, uint32_t dwData)
|
||||
{
|
||||
uint16_t err = FLASH_ERR_SUCCESS;
|
||||
|
||||
//判断是否为字对齐
|
||||
if(wNVMTargetAddress & 0x03)
|
||||
{
|
||||
err = FLASH_ERR_INVALID_PARAM;
|
||||
return (err);
|
||||
}
|
||||
// 清除错误标志
|
||||
EFMCMD = FLASH_CMD_CLEAR;
|
||||
//写入数据到对应的地址中
|
||||
DisableInterrupts;
|
||||
M32(wNVMTargetAddress) = dwData;
|
||||
//加载编程命令
|
||||
EFM_LaunchCMD(FLASH_CMD_PROGRAM);
|
||||
EnableInterrupts;
|
||||
return (err);//返回状态
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
|
||||
* @function name: FlashProgram2LongWords
|
||||
*
|
||||
* @brief 加载两个字的大小,编程到FLASH中(也就是八个字节)
|
||||
*
|
||||
* @param[in] wNVMTargetAddress 所要存放的FLASH首地址
|
||||
* @param[in] dwData0 低4个字节
|
||||
* @param[in] dwData1 高4个字节
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__ramfunc uint16_t Flash_Program2LongWords(uint32_t wNVMTargetAddress, uint32_t dwData0, uint32_t dwData1)
|
||||
{
|
||||
uint16_t err = FLASH_ERR_SUCCESS;
|
||||
|
||||
|
||||
//判断是否为字对齐
|
||||
if(wNVMTargetAddress & 0x03)
|
||||
{
|
||||
err = FLASH_ERR_INVALID_PARAM;
|
||||
return (err);
|
||||
}
|
||||
// 清除错误标志
|
||||
|
||||
EFMCMD = FLASH_CMD_CLEAR;
|
||||
DisableInterrupts;
|
||||
M32(wNVMTargetAddress) = dwData0;//存放数据到以目标地址为起始的4个字节的空间中
|
||||
EFM_LaunchCMD(FLASH_CMD_PROGRAM);//0x20000000,加载编程命令
|
||||
EnableInterrupts;
|
||||
wNVMTargetAddress = wNVMTargetAddress +4;//地址是字对齐的,地址向后移一个字
|
||||
|
||||
EFMCMD = FLASH_CMD_CLEAR;
|
||||
DisableInterrupts;
|
||||
M32(wNVMTargetAddress) = dwData1;//第二个数据放入处理后的地址的4个字节的空间中
|
||||
EFM_LaunchCMD(FLASH_CMD_PROGRAM);//加载编程命令
|
||||
EnableInterrupts;
|
||||
return (err);//返回处理状态
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
+FUNCTION----------------------------------------------------------------
|
||||
* @function name: Flash_EraseSector
|
||||
*
|
||||
* @brief 擦除目标地址的一个扇区(512字节),.
|
||||
*
|
||||
* @param[in] wNVMTargetAddress 擦除扇区的首地址
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__ramfunc uint16_t Flash_EraseSector(uint32_t wNVMTargetAddress)
|
||||
{
|
||||
uint16_t err = FLASH_ERR_SUCCESS;
|
||||
// 判断是否字对齐
|
||||
if(wNVMTargetAddress & 0x03)
|
||||
{
|
||||
err = FLASH_ERR_INVALID_PARAM;
|
||||
return (err);
|
||||
}
|
||||
// 清除错误标志
|
||||
EFMCMD = FLASH_CMD_CLEAR;
|
||||
DisableInterrupts;
|
||||
M32(wNVMTargetAddress) = 0xffffffff;
|
||||
EFM_LaunchCMD(FLASH_CMD_ERASE_SECTOR);//加载擦除命令
|
||||
EnableInterrupts;
|
||||
return (err);
|
||||
}
|
||||
|
||||
|
||||
__ramfunc uint16_t Flash_VerifyBackdoorKey()
|
||||
{
|
||||
uint16_t err = FLASH_ERR_SUCCESS;
|
||||
|
||||
// Clear error flags
|
||||
EFMCMD = FLASH_CMD_CLEAR;
|
||||
// Write index to specify the command code to be loaded
|
||||
Custombkd = FLASH_FACTORY_KEY;
|
||||
return (err);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
+FUNCTION----------------------------------------------------------------
|
||||
* @function name: NVM_EraseAll
|
||||
*
|
||||
* @brief 整片擦除FLASH(慎用,注意0X40E这个地址,在调试阶段写入0XFE)
|
||||
*
|
||||
* @param
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__ramfunc uint16_t NVM_EraseAll(void)
|
||||
{
|
||||
uint16_t err = FLASH_ERR_SUCCESS;
|
||||
EFMCMD = FLASH_CMD_CLEAR;
|
||||
EFM_LaunchCMD(FLASH_CMD_ERASE_ALL);
|
||||
// Clear error flags
|
||||
return err;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
+FUNCTION----------------------------------------------------------------
|
||||
* @function name: NVM_Unsecure
|
||||
*
|
||||
* @brief unsecure
|
||||
*
|
||||
* @param
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__ramfunc uint16_t NVM_Unsecure(void)
|
||||
{
|
||||
uint16_t err = FLASH_ERR_SUCCESS;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
+FUNCTION----------------------------------------------------------------
|
||||
* @function name: EFM_LaunchCMD
|
||||
*
|
||||
* @brief 命令加载函数(注:此函数须放入SRAM中运行)
|
||||
*
|
||||
* @param
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifdef IAR
|
||||
void __ramfunc EFM_LaunchCMD(uint32_t EFM_CMD)
|
||||
#else
|
||||
__ramfunc void EFM_LaunchCMD(uint32_t EFM_CMD)
|
||||
#endif
|
||||
{
|
||||
DisableInterrupts;
|
||||
if((EFMCMD&EFM_DONE_MASK)== EFM_STATUS_READY)
|
||||
{
|
||||
EFMCMD = EFM_CMD;
|
||||
}
|
||||
while(1)
|
||||
{
|
||||
if((EFMCMD&EFM_DONE_MASK) == EFM_STATUS_DONE) break;
|
||||
}
|
||||
EnableInterrupts;
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief FLASH Çý¶¯Í·Îļþ.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef FLASH_H_
|
||||
#define FLASH_H_
|
||||
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define ETMRH_FSTAT_MGSTAT0_MASK (1)
|
||||
#define ETMRH_FSTAT_MGSTAT1_MASK (1<<1)
|
||||
|
||||
#define FLASH_SECTOR_SIZE 512 // in bytes
|
||||
|
||||
#define FLASH_ERR_BASE 0x3000
|
||||
#define FLASH_ERR_SUCCESS 0
|
||||
#define FLASH_ERR_INVALID_PARAM (FLASH_ERR_BASE+1)
|
||||
#define EEPROM_ERR_SINGLE_BIT_FAULT (FLASH_ERR_BASE+2)
|
||||
#define EEPROM_ERR_DOUBLE_BIT_FAULT (FLASH_ERR_BASE+4)
|
||||
#define FLASH_ERR_ACCESS (FLASH_ERR_BASE+8)
|
||||
#define FLASH_ERR_PROTECTION (FLASH_ERR_BASE+0x10)
|
||||
#define FLASH_ERR_MGSTAT0 (FLASH_ERR_BASE+0x11)
|
||||
#define FLASH_ERR_MGSTAT1 (FLASH_ERR_BASE+0x12)
|
||||
#define FLASH_ERR_INIT_CCIF (FLASH_ERR_BASE+0x14)
|
||||
#define FLASH_ERR_INIT_FDIV (FLASH_ERR_BASE+0x18)
|
||||
|
||||
/*********************************/
|
||||
|
||||
#define FLASH_CMD_PROGRAM 0x20000000
|
||||
#define FLASH_CMD_CLEAR 0x00005000
|
||||
#define FLASH_CMD_ERASE_ALL 0x41000000
|
||||
#define FLASH_CMD_ERASE_SECTOR 0x40000000
|
||||
#define FLASH_FACTORY_KEY 0x00cfbdbe
|
||||
|
||||
#define EFM_DONE_MASK 0x00006000
|
||||
#define EFM_STATUS_DONE 0x00006000
|
||||
#define EFM_STATUS_READY 0x00002000
|
||||
|
||||
#define FLASH_ACCERR_MASK 0x10
|
||||
|
||||
#define M8(adr) (*((volatile unsigned char *) (adr)))
|
||||
#define M16(adr) (*((volatile unsigned short *) (adr)))
|
||||
#define M32(adr) (*((volatile unsigned long *) (adr)))
|
||||
|
||||
#define __ramfunc __attribute__ ((long_call, section (".ramfunctions")))
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
******************************************************************************/
|
||||
typedef uint16_t (*TFlash_Fun1)(uint32_t wNVMTargetAddress, uint8_t *pbData, uint8_t bByteCount);
|
||||
typedef uint16_t (*TFlash_Fun2)(uint32_t wNVMTargetAddress, uint32_t dwData0, uint32_t dwData1);
|
||||
typedef uint16_t (*TFlash_Fun3)(uint32_t wNVMTargetAddress, uint32_t dwData);
|
||||
|
||||
/******************************************************************************
|
||||
******************************************************************************/
|
||||
__ramfunc uint16_t Flash_Program(uint32_t wNVMTargetAddress, uint8_t *pData, uint16_t sizeBytes);
|
||||
__ramfunc uint16_t Flash_Program1LongWord(uint32_t wNVMTargetAddress, uint32_t dwData);
|
||||
__ramfunc uint16_t Flash_Program2LongWords(uint32_t wNVMTargetAddress, uint32_t dwData0, uint32_t dwData1);
|
||||
|
||||
__ramfunc uint16_t Flash_EraseSector(uint32_t wNVMTargetAddress);
|
||||
|
||||
__ramfunc uint16_t Flash_VerifyBackdoorKey(void);
|
||||
|
||||
__ramfunc uint16_t NVM_EraseAll(void);
|
||||
|
||||
__ramfunc uint16_t NVM_Unsecure(void);
|
||||
|
||||
uint16_t Flash_Init(void);
|
||||
|
||||
#ifdef IAR
|
||||
void __ramfunc EFM_LaunchCMD(uint32_t EFM_CMD);
|
||||
#else
|
||||
__ramfunc void EFM_LaunchCMD(uint32_t EFM_CMD);
|
||||
#endif
|
||||
|
||||
|
||||
void Flash_CopyInRAM(void);
|
||||
void Flash_CopyRouinte2RAM(char *func, uint16_t sizeFunc);
|
||||
/********************************************************************/
|
||||
|
||||
#endif /* FLASH_H_ */
|
||||
@@ -0,0 +1,41 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Navota Microelectronics Inc. Navota Camels 32 Bit MCU
|
||||
* (c) Copyright 2015-2016 Navota Microelectronics, Inc.
|
||||
* ALL RIGHTS RESERVED.
|
||||
*
|
||||
******************************************************************************
|
||||
*
|
||||
* @file flash_cmd.c
|
||||
*
|
||||
* @brief application entry point which performs application specific tasks.
|
||||
*
|
||||
*******************************************************************************
|
||||
*
|
||||
* provide a demo for how to initialize the NV32, output messages via SCI,
|
||||
* flash operations, etc.
|
||||
* NOTE:
|
||||
* printf call may occupy a lot of memory (around 1924 bytes), so please
|
||||
* consider your code size before using printf.
|
||||
******************************************************************************
|
||||
*
|
||||
* provide FLASH driver
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include "flash.h"
|
||||
|
||||
void EFM_LaunchCMD(uint32_t EFM_CMD)
|
||||
{
|
||||
#define DisableInterrupts£»
|
||||
if((EFMCMD&EFM_DONE_MASK)== EFM_STATUS_READY)
|
||||
{
|
||||
EFMCMD = EFM_CMD;
|
||||
}
|
||||
while(1)
|
||||
{
|
||||
if((EFMCMD&EFM_DONE_MASK) == EFM_STATUS_DONE) break;
|
||||
}
|
||||
#define EnableInterrupts;
|
||||
__asm("nop");
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
/************************************************************************!
|
||||
* 技术讨论:QQ群 123763203
|
||||
* 官网 :www.navota.com
|
||||
*
|
||||
* @file pit.c
|
||||
* @brief pit定时器函数库
|
||||
* @author Navota
|
||||
* @date 2018-3-1
|
||||
************************************************************************/
|
||||
|
||||
#include "common.h"
|
||||
#include "pit.h"
|
||||
|
||||
/*!
|
||||
* @brief 存放回调入口
|
||||
*
|
||||
*/
|
||||
PIT_CallbackType PIT_Callback[2] = {(PIT_CallbackType)NULL};
|
||||
|
||||
void PIT_Ch0Isr(void);
|
||||
void PIT_Ch1Isr(void);
|
||||
|
||||
/******************************************************************************
|
||||
* 定义PIT的接口函数
|
||||
*******************************************************************************/
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 初始化PIT模块.
|
||||
*
|
||||
* @param[in] u8Channel_No 通道号
|
||||
* @param[in] pConfig 配置模块的结构体指针
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void PIT_Init(uint8_t u8Channel_No, PIT_ConfigType *pConfig)
|
||||
{
|
||||
SIM->SCGC |= SIM_SCGC_PIT_MASK; /*!< 选通PIT模块门控时钟 */
|
||||
|
||||
if (pConfig->bFreeze)
|
||||
{
|
||||
PIT_SetDebugFreeze();
|
||||
}
|
||||
|
||||
if (pConfig->bModuleDis == 0)
|
||||
{
|
||||
PIT_Enable(); /*!< 标准PIT定时器的时钟使能 */
|
||||
}
|
||||
|
||||
PIT_SetLoadVal(u8Channel_No, pConfig->u32LoadValue); //加载对应通道的定时器起始值
|
||||
|
||||
if (pConfig->bInterruptEn)
|
||||
{
|
||||
if (u8Channel_No)
|
||||
{
|
||||
NVIC_EnableIRQ(PIT_CH1_IRQn); //开启对应通道IRQ中断
|
||||
}
|
||||
else
|
||||
{
|
||||
NVIC_EnableIRQ(PIT_CH0_IRQn);
|
||||
}
|
||||
PIT_ChannelEnableInt(u8Channel_No); //开启对应通道的中断请求
|
||||
}
|
||||
else
|
||||
{
|
||||
NVIC_DisableIRQ(PIT_CH0_IRQn); //禁止通道0的IRQ中断
|
||||
}
|
||||
|
||||
if (pConfig->bChainMode)
|
||||
{
|
||||
PIT_ChannelEnableChain(u8Channel_No); //定时器链接到前一定时器
|
||||
}
|
||||
|
||||
if (pConfig->bETMerEn)
|
||||
{
|
||||
PIT_ChannelEnable(u8Channel_No); //定时器通道使能
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 装载定时器起始值到加载值寄存器中.
|
||||
*
|
||||
* @param[in] u8Channel_No 通道号
|
||||
* @param[in] u32loadvalue 所有加载的数值
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void PIT_SetLoadVal(uint8_t u8Channel, uint32_t u32loadvalue)
|
||||
|
||||
{
|
||||
PIT->CHANNEL[u8Channel].LDVAL = u32loadvalue;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置PIT模块回调函数.
|
||||
*
|
||||
* @param[in] u8Channel_No 通道号.
|
||||
* @param[in] pfnCallback 指向回调函数.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void PIT_SetCallback(uint8_t u8Channel_No, PIT_CallbackType pfnCallback)
|
||||
{
|
||||
PIT_Callback[u8Channel_No] = pfnCallback;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 复位PIT模块
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void PIT_DeInit(void)
|
||||
{
|
||||
NVIC_DisableIRQ(PIT_CH0_IRQn);
|
||||
NVIC_DisableIRQ(PIT_CH1_IRQn);
|
||||
PIT_SetLoadVal(0,0);
|
||||
PIT_SetLoadVal(1,0);
|
||||
PIT_ChannelDisable(0);
|
||||
PIT_ChannelDisable(1);
|
||||
PIT_ChannelDisableInt(0);
|
||||
PIT_ChannelDisableInt(1);
|
||||
PIT_ChannelDisableChain(0);
|
||||
PIT_ChannelDisableChain(1);
|
||||
PIT_ChannelClrFlags(0);
|
||||
PIT_ChannelClrFlags(1);
|
||||
PIT_SetDebugOn();
|
||||
PIT_Disable();
|
||||
SIM->SCGC &= ~SIM_SCGC_PIT_MASK;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief PIT0通道中断服务函数.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void PIT_Ch0Isr(void)
|
||||
{
|
||||
PIT_ChannelClrFlags(0); //清除中断标志位
|
||||
|
||||
if (PIT_Callback[0])
|
||||
{
|
||||
PIT_Callback[0]();
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief PIT0通道中断服务函数.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void PIT_Ch1Isr(void)
|
||||
{
|
||||
PIT_ChannelClrFlags(1); //清除中断标志位
|
||||
if (PIT_Callback[1])
|
||||
{
|
||||
PIT_Callback[1]();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,275 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief PIT 驱动头文件.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef PIT_H_
|
||||
#define PIT_H_
|
||||
#include"common.h"
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* PIT 通道号列表
|
||||
*
|
||||
*//*!
|
||||
*******************************************************************************/
|
||||
enum
|
||||
{
|
||||
PIT_CHANNEL0 = 0, /*!< PIT 通道 0 */
|
||||
PIT_CHANNEL1 /*!< PIT 通道 1 */
|
||||
};
|
||||
|
||||
/*! */
|
||||
|
||||
|
||||
/*!
|
||||
* @brief PIT 回调类型.
|
||||
*
|
||||
*/
|
||||
|
||||
typedef void (*PIT_CallbackType)(void);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* PIT 配置结构体体
|
||||
*/
|
||||
/*!
|
||||
* @brief PIT 配置参数.
|
||||
*
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t bFreeze : 1; /*!< 1: 在调试模式时冻结, 0: 在调试模式时仍然运行 */
|
||||
uint8_t bModuleDis : 1; /*!< 1: 禁用PIT模块, 0: 使能PIT模块 */
|
||||
uint8_t bReserved0 : 1; /*!< 保留 */
|
||||
uint8_t bReserved1 : 5; /*!< 保留 */
|
||||
uint8_t bETMerEn : 1; /*!< 1: 使能PIT通道, 0: 禁止PIT通道 */
|
||||
uint8_t bInterruptEn : 1; /*!< 1: 使能PIT通道中断, 0: 禁止PIT通道中断 */
|
||||
uint8_t bChainMode : 1; /*!< 1: 使能链模式, 0: 禁止链模式 */
|
||||
uint8_t bReserved2 : 5; /*!< 保留 */
|
||||
uint8_t bFlag : 1; /*!< 1: PIT中断标志位置位,写1清0, 0: PIT中断标志位没有置位 */
|
||||
uint8_t bReserved3 : 7; /*!< 保留 */
|
||||
uint32_t u32LoadValue ; /*!< 32位通道加载模值 */
|
||||
} PIT_ConfigType, *PIT_ConfigPtr;
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
******************************************************************************/
|
||||
|
||||
/*!
|
||||
* 内联函数
|
||||
*/
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能PIT模块.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void PIT_Enable(void)
|
||||
{
|
||||
|
||||
PIT->MCR &= ~PIT_MCR_MDIS_MASK;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用PIT模块.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void PIT_Disable(void)
|
||||
{
|
||||
|
||||
PIT->MCR |= PIT_MCR_MDIS_MASK;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置PIT在调试模式下禁止运行.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void PIT_SetDebugFreeze(void)
|
||||
{
|
||||
|
||||
PIT->MCR |= PIT_MCR_FRZ_MASK;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置PIT在调试模式下继续运行.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void PIT_SetDebugOn(void)
|
||||
{
|
||||
|
||||
PIT->MCR &= ~PIT_MCR_FRZ_MASK;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief PIT定时器通道使能.
|
||||
*
|
||||
* @param[in] u8Channel 通道号.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void PIT_ChannelEnable(uint8_t u8Channel)
|
||||
|
||||
{
|
||||
|
||||
PIT->CHANNEL[u8Channel].TCTRL |= PIT_TCTRL_TEN_MASK;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用PIT定时器通道.
|
||||
*
|
||||
* @param[in] u8Channel 通道号.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void PIT_ChannelDisable(uint8_t u8Channel)
|
||||
{
|
||||
|
||||
PIT->CHANNEL[u8Channel].TCTRL &= ~PIT_TCTRL_TEN_MASK;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能PIT定时器通道中断.
|
||||
*
|
||||
* @param[in] u8Channel 通道号.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void PIT_ChannelEnableInt(uint8_t u8Channel)
|
||||
|
||||
{
|
||||
|
||||
PIT->CHANNEL[u8Channel].TCTRL |= PIT_TCTRL_TIE_MASK;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用PIT定时器通道中断.
|
||||
*
|
||||
* @param[in] u8Channel 通道号.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void PIT_ChannelDisableInt(uint8_t u8Channel)
|
||||
|
||||
{
|
||||
|
||||
PIT->CHANNEL[u8Channel].TCTRL &= ~PIT_TCTRL_TIE_MASK;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能PIT定时器通道链模式.
|
||||
*
|
||||
* @param[in] u8Channel 通道号.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void PIT_ChannelEnableChain(uint8_t u8Channel)
|
||||
{
|
||||
PIT->CHANNEL[u8Channel].TCTRL |= PIT_TCTRL_CHN_MASK;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用PIT定时器通道链模式.
|
||||
*
|
||||
* @param[in] u8Channel 通道号.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void PIT_ChannelDisableChain(uint8_t u8Channel)
|
||||
|
||||
{
|
||||
PIT->CHANNEL[u8Channel].TCTRL &= ~PIT_TCTRL_CHN_MASK;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 获取PIT通道中断标志位.
|
||||
*
|
||||
* @param[in] u8Channel 通道号.
|
||||
*
|
||||
* @return PIT通道中断标志位.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t PIT_ChannelGetFlags(uint8_t u8Channel)
|
||||
|
||||
{
|
||||
uint8_t bflag;
|
||||
|
||||
bflag = (PIT->CHANNEL[u8Channel].TFLG & PIT_TFLG_TIF_MASK);
|
||||
|
||||
return bflag;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 清除PIT通道中断标志位.
|
||||
*
|
||||
* @param[in] u8Channel 通道号.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void PIT_ChannelClrFlags(uint8_t u8Channel)
|
||||
{
|
||||
PIT->CHANNEL[u8Channel].TFLG |= PIT_TFLG_TIF_MASK;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
******************************************************************************/
|
||||
void PIT_Init(uint8_t u8Channel_No, PIT_ConfigType *pConfig);
|
||||
void PIT_SetLoadVal(uint8_t u8Channel, uint32_t u32loadvalue);
|
||||
void PIT_SetCallback(uint8_t u8Channel_No, PIT_CallbackType pfnCallback);
|
||||
void PIT_DeInit(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* PIT_H_ */
|
||||
@@ -0,0 +1,137 @@
|
||||
/************************************************************************!
|
||||
* 技术讨论:QQ群 123763203
|
||||
* 官网 :www.navota.com
|
||||
*
|
||||
* @file rtc.c
|
||||
* @brief rtc定时器函数库
|
||||
* @author Navota
|
||||
* @date 2018-3-1
|
||||
***************************************************************************/
|
||||
|
||||
#include "common.h"
|
||||
#include "rtc.h"
|
||||
|
||||
/*!
|
||||
* @brief 存放中断回调入口
|
||||
*
|
||||
*/
|
||||
RTC_CallbackType RTC_Callback[1] = {(RTC_CallbackType)NULL};
|
||||
|
||||
|
||||
|
||||
void RTC_Isr(void);
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* 定义RTC的接口函数
|
||||
*******************************************************************************/
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 初始化RTC模块
|
||||
*
|
||||
* @param[in] pConfig 配置RTC模块的结构体
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void RTC_Init(RTC_ConfigType *pConfig)
|
||||
{
|
||||
uint16_t u16Clocksource, u16Prescler;
|
||||
uint16_t u16ModVal;
|
||||
|
||||
u16Clocksource =0;
|
||||
u16Prescler =0;
|
||||
u16ModVal =0;
|
||||
|
||||
SIM->SCGC |= SIM_SCGC_RTC_MASK;
|
||||
|
||||
u16ModVal = pConfig->u16ModuloValue;
|
||||
RTC_SetModulo(u16ModVal);
|
||||
|
||||
if (pConfig->bRTCOut)
|
||||
{
|
||||
RTC->SC= RTC_SC_RTCO_MASK;
|
||||
}
|
||||
|
||||
if (pConfig->bInterruptEn)
|
||||
{
|
||||
NVIC_EnableIRQ(RTC_IRQn);
|
||||
RTC_EnableInt();
|
||||
}
|
||||
else
|
||||
{
|
||||
NVIC_DisableIRQ(RTC_IRQn);
|
||||
}
|
||||
|
||||
if (pConfig->bFlag)
|
||||
{
|
||||
RTC_ClrFlags();
|
||||
}
|
||||
|
||||
u16Clocksource = pConfig->bClockSource;
|
||||
u16Prescler = pConfig->bClockPresaler;
|
||||
|
||||
RTC_SetClock(u16Clocksource,u16Prescler );
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置RTC模块的中断回调函数
|
||||
*
|
||||
* @param[in] pfnCallback 回调函数的地址
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void RTC_SetCallback(RTC_CallbackType pfnCallback)
|
||||
{
|
||||
RTC_Callback[0] = pfnCallback;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 复位RTC模块
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void RTC_DeInit(void)
|
||||
{
|
||||
NVIC_DisableIRQ(RTC_IRQn);
|
||||
RTC->MOD = 0;
|
||||
while(RTC->MOD);
|
||||
|
||||
if(RTC_GetFlags())
|
||||
{
|
||||
RTC_ClrFlags();
|
||||
}
|
||||
|
||||
RTC->SC = 0;
|
||||
while(RTC->SC);
|
||||
SIM->SCGC &= ~SIM_SCGC_RTC_MASK;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief RTC中断服务函数
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void RTC_Isr(void)
|
||||
{
|
||||
RTC_ClrFlags(); //清除中断标志位
|
||||
if (RTC_Callback[0])
|
||||
{
|
||||
RTC_Callback[0]();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,182 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief RTC 驱动头文件.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef RTC_H_
|
||||
#define RTC_H_
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
/******************************************************************************
|
||||
* RTC控制位定义
|
||||
*
|
||||
*//*!
|
||||
* @{
|
||||
*******************************************************************************/
|
||||
|
||||
#define RTC_OUTPUT_ENABLE 1 /*!< 使能RTC输出引脚 */
|
||||
#define RTC_INTERRUPT_ENABLE 1 /*!< 使能RTC中断 */
|
||||
#define RTC_CLKSRC_EXTERNAL 0 /*!< 选择外部时钟作为RTC时钟源 */
|
||||
#define RTC_CLKSRC_1KHZ 1 /*!< 选择LPO时钟作为RTC时钟源 */
|
||||
#define RTC_CLKSRC_IREF 2 /*!< 选择内部参考时钟ICSIRCLK作为RTC时钟源 */
|
||||
#define RTC_CLKSRC_BUS 3 /*!< 选择总线时钟作为RTC时钟源 */
|
||||
#define RTC_CLK_PRESCALER_128 1 /*!< 根据RTCLKS位选择是1还是128分频 */
|
||||
#define RTC_CLK_PRESCALER_256 2 /*!< 根据RTCLKS位选择是2还是256分频 */
|
||||
#define RTC_CLK_PRESCALER_512 3 /*!< 根据RTCLKS位选择是4还是512分频 */
|
||||
#define RTC_CLK_PRESCALER_1024 4 /*!< 根据RTCLKS位选择是8还是1024分频 */
|
||||
#define RTC_CLK_PRESCALER_2048 5 /*!< 根据RTCLKS位选择是16还是2048分频 */
|
||||
#define RTC_CLK_PRESCALER_100 6 /*!< 根据RTCLKS位选择是32还是100分频 */
|
||||
#define RTC_CLK_PRESCALER_1000 7 /*!< 根据RTCLKS位选择是64还是1000分频 */
|
||||
|
||||
|
||||
/*! @} */
|
||||
|
||||
|
||||
/*!
|
||||
* @brief RTC 回调类型.
|
||||
*
|
||||
*/
|
||||
|
||||
typedef void (*RTC_CallbackType)(void);
|
||||
|
||||
|
||||
|
||||
/* RTC 配置结构体体
|
||||
*/
|
||||
/*!
|
||||
* @brief RTC 配置参数.
|
||||
*
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint16_t bReserved : 4; /*!< 保留 */
|
||||
uint16_t bRTCOut : 1; /*!< 1: 使能RTC输出, 0: 禁止RTC输出 */
|
||||
uint16_t bReserved1 : 1; /*!< 保留 */
|
||||
uint16_t bInterruptEn : 1; /*!< 1: 使能RTC中断, 0: RTC 禁止RTC中断 */
|
||||
uint16_t bFlag : 1; /*!< 1: RTC实时中断标志 */
|
||||
uint16_t bClockPresaler : 3; /*!< 3: RTC分频系数选择 */
|
||||
uint16_t bReserved2 : 3; /*!< 保留*/
|
||||
uint16_t bClockSource : 2; /*!< 2:RTC时钟源选择 */
|
||||
uint16_t u16ModuloValue ; /*!< 16位RTC模值 */
|
||||
} RTC_ConfigType, *RTC_ConfigPtr;
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
******************************************************************************/
|
||||
|
||||
/*!
|
||||
* 内联函数
|
||||
*/
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能RTC中断.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void RTC_EnableInt(void)
|
||||
{
|
||||
RTC->SC |= RTC_SC_RTIE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁止RTC中断.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return non
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void RTC_DisableInt(void)
|
||||
{
|
||||
RTC->SC &= ~RTC_SC_RTIE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置16位RTC模值.
|
||||
*
|
||||
* @param[in] u16Mod_Value 16位模值
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void RTC_SetModulo(uint16_t u16Mod_Value)
|
||||
{
|
||||
|
||||
RTC->MOD = u16Mod_Value;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置RTC时钟以及分频系数.
|
||||
*
|
||||
* @param[in] u16Clock_Number 选择时钟源
|
||||
* @param[in] u16Presalcer 分频系数
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void RTC_SetClock(uint16_t u16Clock_Number, uint16_t u16Presalcer)
|
||||
{
|
||||
uint32_t u32rtc_sc;
|
||||
|
||||
u32rtc_sc = RTC->SC;
|
||||
u32rtc_sc &= ~(RTC_SC_RTCLKS_MASK | RTC_SC_RTCPS_MASK);
|
||||
u32rtc_sc |= RTC_SC_RTCLKS(u16Clock_Number) | RTC_SC_RTCPS(u16Presalcer);
|
||||
RTC->SC = u32rtc_sc;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 获取RTC中断标志位.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return RTC中断标志位.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t RTC_GetFlags(void)
|
||||
{
|
||||
uint8_t bflag;
|
||||
|
||||
bflag = RTC->SC & RTC_SC_RTIF_MASK;
|
||||
|
||||
return bflag;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 清除RTC中断标志位.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void RTC_ClrFlags(void)
|
||||
{
|
||||
RTC->SC |= RTC_SC_RTIF_MASK;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
void RTC_Init(RTC_ConfigType *pConfig);
|
||||
void RTC_SetCallback(RTC_CallbackType pfnCallback);
|
||||
void RTC_DeInit(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* RTC_H_ */
|
||||
@@ -0,0 +1,164 @@
|
||||
/*************************************************************************!
|
||||
* 技术讨论:QQ群 123763203
|
||||
* 官网 :www.navota.com
|
||||
*
|
||||
* @file sim.c
|
||||
* @brief 系统集成模块(SIM)函数库
|
||||
* @author Navota
|
||||
* @date 2018-3-1
|
||||
*************************************************************************/
|
||||
|
||||
#include "common.h"
|
||||
#include "sim.h"
|
||||
|
||||
|
||||
#if defined(CPU_NV32)
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @ 初始化SIM寄存器.
|
||||
*
|
||||
* @ 输入 pConfig 指向SIM配置结构体.
|
||||
*
|
||||
* @ 无返回
|
||||
*
|
||||
* @ 参看 SIM_ConfigType
|
||||
*
|
||||
*****************************************************************************/
|
||||
void SIM_Init(SIM_ConfigType *pConfig)
|
||||
{
|
||||
uint32_t u32Sopt;
|
||||
uint32_t u32PinSel;
|
||||
uint32_t u32Scgc;
|
||||
uint32_t u32BusDiv;
|
||||
/*
|
||||
* 初始化SIM寄存器
|
||||
*/
|
||||
u32Sopt = 0x0010000E; /*使能SWD、RESET、NMI引脚 */
|
||||
u32PinSel = 0;
|
||||
u32Scgc = 0x00003000; /* 使能SWD、FLASH模块的总线时钟 */
|
||||
u32BusDiv = 0;
|
||||
u32BusDiv = pConfig->sBits.bBusDiv; /*总线时钟分频值*/
|
||||
if(pConfig->sBits.bDisableNMI) /*禁用NMI引脚*/
|
||||
{
|
||||
u32Sopt &= ~SIM_SOPT_NMIE_MASK;
|
||||
}
|
||||
if(pConfig->sBits.bDisableRESET) /*禁用RSTPE引脚*/
|
||||
{
|
||||
u32Sopt &= ~SIM_SOPT_RSTPE_MASK;
|
||||
}
|
||||
if(pConfig->sBits.bDisableSWD) /*禁用SWDE引脚*/
|
||||
{
|
||||
u32Sopt &= ~SIM_SOPT_SWDE_MASK;
|
||||
}
|
||||
if(pConfig->sBits.bEnableCLKOUT) /*使能总线时钟*/
|
||||
{
|
||||
u32Sopt |= SIM_SOPT_CLKOE_MASK;
|
||||
}
|
||||
if(pConfig->sBits.bETMSYNC) /*ETM2同步选择*/
|
||||
{
|
||||
u32Sopt |= SIM_SOPT_ETMSYNC_MASK; /*生成ETM2模块的PWM同步触发*/
|
||||
}
|
||||
if(pConfig->sBits.bRXDCE) /*UAT0_RX捕捉选择*/
|
||||
{
|
||||
u32Sopt |= SIM_SOPT_RXDCE_MASK; /*UAT0_RX输入信号接到UART0模块和ETM0通道1*/
|
||||
}
|
||||
if(pConfig->sBits.bTXDME) /*URAT0_TX捕捉选择*/
|
||||
{
|
||||
u32Sopt |= SIM_SOPT_TXDME_MASK; /*URAT0_TX输出映射到引出线前由ETM0通道调制*/
|
||||
}
|
||||
if(pConfig->sBits.bACIC) /*模拟比较器至输入捕获使能*/
|
||||
{
|
||||
u32Sopt |= SIM_SOPT_ACIC_MASK; /* ACMP0输出连接到ETM1输出通道0*/
|
||||
}
|
||||
if(pConfig->sBits.bRTCC)
|
||||
{
|
||||
u32Sopt |= SIM_SOPT_RTCC_MASK; /*RTC溢出连接到ETM1输入通道*/
|
||||
}
|
||||
if(pConfig->sBits.bRXDFE) /*URT0 RxD滤波器选择*/
|
||||
{
|
||||
u32Sopt |= SIM_SOPT_RXDFE_MASK; /*RXD0输入信号由ACMP0滤波,然后注入UART0*/
|
||||
}
|
||||
u32Sopt |= ((pConfig->u8BusRef & 0x07) << 16); /*总线时钟128分频*/
|
||||
u32Sopt |= ((pConfig->u8Delay) << 24); /*设置从ETM2初始化/匹配到触发ADC转换的延时时间*/
|
||||
u32Sopt |= ((pConfig->sBits.u8ADHWT & 0x03) << 8); /*选择ETM2匹配作为ADC转换的硬件触发源*/
|
||||
u32PinSel = pConfig->u32PinSel;
|
||||
u32Scgc = pConfig->u32SCGC;
|
||||
|
||||
/*写数据到SIM模块寄存器 */
|
||||
SIM->SOPT = u32Sopt;
|
||||
SIM->PINSEL = u32PinSel;
|
||||
SIM->SCGC = u32Scgc;
|
||||
SIM->BUSDIV = u32BusDiv;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************//*!
|
||||
*
|
||||
* @ 设置SIM时钟选通控制寄存器,使能或者禁用外设门控时钟
|
||||
*
|
||||
* @ 输入 u32PeripheralMask 外设时钟掩码
|
||||
* @ 输入 u8GateOn 1:开启, 0:关闭.
|
||||
*
|
||||
* @ 无返回
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
void SIM_SetClockGating(uint32_t u32PeripheralMask, uint8_t u8GateOn)
|
||||
{
|
||||
uint32_t u32Scgc;
|
||||
|
||||
u32Scgc = SIM->SCGC;
|
||||
|
||||
if(u8GateOn)
|
||||
{
|
||||
u32Scgc |= u32PeripheralMask;
|
||||
}
|
||||
else
|
||||
{
|
||||
u32Scgc &= ~u32PeripheralMask;
|
||||
}
|
||||
|
||||
SIM->SCGC = u32Scgc;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @ 读取相应的状态标志位.
|
||||
*
|
||||
* @ 输入 u32StatusMask 指示要被读取的状态
|
||||
*
|
||||
* @ 返回状态.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
uint32_t SIM_GetStatus(uint32_t u32StatusMask)
|
||||
{
|
||||
uint32_t u32Status;
|
||||
|
||||
u32Status = SIM->SRSID & u32StatusMask; //读取状态标志位
|
||||
|
||||
return (u32Status);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @ 读相应的ID寄存器.
|
||||
*
|
||||
* @ 输入 u8ID ID的类型.
|
||||
*
|
||||
* @ 返回 ID
|
||||
*
|
||||
* 参看 IDType
|
||||
*
|
||||
*****************************************************************************/
|
||||
uint8_t SIM_ReadID(IDType sID)
|
||||
{
|
||||
uint32_t u32ID;
|
||||
uint8_t u8IDOffset[4] =
|
||||
{
|
||||
28, 24, 20,16
|
||||
};
|
||||
u32ID = (SIM->SRSID >> u8IDOffset[sID]) & 0x0F; //读取ID
|
||||
return (u32ID);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,472 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief SIM 驱动头文件.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef SIM_H_
|
||||
#define SIM_H_
|
||||
|
||||
typedef enum {
|
||||
ID_TYPE_FAMID, /*!< NV32F100x系列 ID */
|
||||
ID_TYPE_SUBFAMID, /*!< NV32F100x子系列 ID */
|
||||
ID_TYPE_REVID, /*!< 器件版本 ID */
|
||||
ID_TYPE_PINID /*!< 器件引脚 ID */
|
||||
} IDType;
|
||||
|
||||
|
||||
#if defined(CPU_NV32)
|
||||
typedef struct{
|
||||
struct{
|
||||
uint32_t bEnableCLKOUT : 1; /*!< 1: 使能 , 0: 禁用 */
|
||||
uint32_t bTXDME : 1; /*!< 1: 使能 TXDME, 0: 禁用 */
|
||||
uint32_t bETMSYNC : 1; /*!< 1: 使能 ETM SYNC, 0: 未触发任何同步 */
|
||||
uint32_t bRXDFE : 1; /*!< 1: 使能 RXD 滤波, 0: 无滤波 */
|
||||
uint32_t bRXDCE : 1; /*!< 1: 使能 RXD 捕捉, 0: 无捕捉 */
|
||||
uint32_t bACIC : 1; /*!< 1: ACMP0的输出通道连接到ETM1的输入通道0, 0: 无连接 */
|
||||
uint32_t bRTCC : 1; /*!< 1: RTC溢出连接到ETM1输入通道1, 0: 无连接 */
|
||||
uint32_t u8ADHWT : 2; /*!< 选择ADC转换硬件触发源 */
|
||||
uint32_t bDisableSWD : 1; /*!< 1: 禁用SWD, 0: 使能 */
|
||||
uint32_t bDisableRESET : 1; /*!< 1: 禁用复位引脚, 0: 使能 */
|
||||
uint32_t bDisableNMI : 1; /*!< 1: 禁用NMI中断输入引脚, 0:使能 */
|
||||
uint32_t bBusDiv : 1; /*!< 总线分频系数 */
|
||||
} sBits;
|
||||
uint8_t u8Delay; /*!< ETM触发ADC转换延时值 */
|
||||
uint8_t u8BusRef; /*!< 总线参考 */
|
||||
uint32_t u32PinSel; /*!< 引脚选择寄存器的值*/
|
||||
uint32_t u32SCGC; /*!< 时钟选通寄存器的值 */
|
||||
} SIM_ConfigType, *SIM_ConfigPtr; /*!< SIM模块配置结构体类型 */
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(CPU_NV32)
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置ETM2触发ADC转换的延时时间
|
||||
*
|
||||
* @param[in] u8Delay 延时时间模数值,参考时钟采用总线时钟分频
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @ Pass/ Fail criteria: none
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_DelayETM2Trig2ADC(uint8_t u8Delay)
|
||||
{
|
||||
SIM->SOPT = (SIM->SOPT & ~(SIM_SOPT_DELAY_MASK)) | SIM_SOPT_DELAY(u8Delay);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能总线时钟在PH2上
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @ 参看 SIM_DisableClockOutput
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_EnableClockOutput(void)
|
||||
{
|
||||
SIM->SOPT |= (SIM_SOPT_CLKOE_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用总线时钟输出在PH2上
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @参看 SIM_EnableClockOutput
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_DisableClockOutput(void)
|
||||
{
|
||||
SIM->SOPT &= ~(SIM_SOPT_CLKOE_MASK);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置总线时钟输出分频.
|
||||
*
|
||||
* @param[in] u8Divide 分频系数 (3-bits)
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_SetClockOutputDivide(uint8_t u8Divide)
|
||||
{
|
||||
SIM->SOPT = (SIM->SOPT & ~(SIM_SOPT_BUSREF_MASK)) | SIM_SOPT_BUSREF(u8Divide & 0x07);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief UART0_RX输入信号连接到UART0模块和ETM0通道1
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_EnableUART0RXDConnectETMOCH1(void)
|
||||
{
|
||||
SIM->SOPT |= (SIM_SOPT_RXDCE_MASK);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief UART0_TX输出在映射到引出线前由ETM0通道0调制
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_EnableUART0Modulation(void)
|
||||
{
|
||||
SIM->SOPT |= (SIM_SOPT_TXDME_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief UART0_TX输出直接连接到引出线上
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_DisableUART0Modulation(void)
|
||||
{
|
||||
SIM->SOPT &= ~(SIM_SOPT_TXDME_MASK);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 生成ETM2模块的PWM同步触发
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @ Pass/ Fail criteria: none
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_GenerateSoftwareTrig2ETM2(void)
|
||||
{
|
||||
SIM->SOPT |= (SIM_SOPT_ETMSYNC_MASK);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief ETM2_CH3通道映射到PD1上
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @ Pass/ Fail criteria: none
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_RemapETM2CH3Pin(void)
|
||||
{
|
||||
SIM->PINSEL |= SIM_PINSEL_ETM2PS3_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief ETM2_CH2通道映射到PD0上
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @ Pass/ Fail criteria: none
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_RemapETM2CH2Pin(void)
|
||||
{
|
||||
SIM->PINSEL |= SIM_PINSEL_ETM2PS2_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief ETM0_CH1通道映射到PB3上
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_RemapETM0CH1Pin(void)
|
||||
{
|
||||
SIM->PINSEL |= SIM_PINSEL_ETM0PS1_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief ETM0_CH0通道映射到PB2上
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_RemapETM0CH0Pin(void)
|
||||
{
|
||||
SIM->PINSEL |= SIM_PINSEL_ETM0PS0_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief UART0_RX和UART0_TX映射到PA2和PA3上
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_RemapUART0Pin(void)
|
||||
{
|
||||
SIM->PINSEL |= SIM_PINSEL_UART0PS_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief SPI0_SCK SPI0_MOSI SPI0_MISO和SPI0_PCS映射到PE0、PE1、PE2、PE3上
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_RemapSPI0Pin(void)
|
||||
{
|
||||
SIM->PINSEL |= SIM_PINSEL_SPI0PS_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief I2C0_SCL和I2C_SDA分别映射到PB7、PB6上
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_RemapI2CPin(void)
|
||||
{
|
||||
SIM->PINSEL |= SIM_PINSEL_IICPS_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief RXD0输入信号由ACPM0滤波,然后注入UART0
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_EnableUART0Filter(void)
|
||||
{
|
||||
SIM->SOPT |= (SIM_SOPT_RXDFE_MASK);
|
||||
}
|
||||
/******************************************************************************!
|
||||
*
|
||||
* @brief RXD0输入信号直接连接到UARTO模块
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_DisableUART0Filter(void)
|
||||
{
|
||||
SIM->SOPT &= ~(SIM_SOPT_RXDFE_MASK);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 选择RTC溢出作为ADC硬件触发源
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_TriggerADCByRTC(void)
|
||||
{
|
||||
SIM->SOPT &= ~(SIM_SOPT_ADHWT_MASK);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 选择PIT溢出作为ADC硬件触发源
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_TriggerADCByPIT(void)
|
||||
{
|
||||
SIM->SOPT = (SIM->SOPT & ~(SIM_SOPT_ADHWT_MASK)) | SIM_SOPT_ADHWT(1);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置ETM2初始化作为ADC硬件触发源.ETM2初始化后经过一段时间延时触发ADC转换
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_TriggerADCByETM2Init(void)
|
||||
{
|
||||
SIM->SOPT = (SIM->SOPT & ~(SIM_SOPT_ADHWT_MASK)) | SIM_SOPT_ADHWT(2);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置ETM2匹配作为ADC硬件触发源,ETM2匹配后经过一段时间的延时触发ADC转换
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_TriggerADCByETM2Match(void)
|
||||
{
|
||||
SIM->SOPT = (SIM->SOPT & ~(SIM_SOPT_ADHWT_MASK)) | SIM_SOPT_ADHWT(3);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief RTC溢出连接到ETM1输入通道1
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_EnableRTCCapture(void)
|
||||
{
|
||||
SIM->SOPT |= (SIM_SOPT_RTCC_MASK);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief RTC溢出未连接到ETM1输入通道1
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_DisableRTCCapture(void)
|
||||
{
|
||||
SIM->SOPT &= ~(SIM_SOPT_RTCC_MASK);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief ACMP0输出连接到ETM1输入通道0
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_EnableACMP0InputCapture(void)
|
||||
{
|
||||
SIM->SOPT |= (SIM_SOPT_ACIC_MASK);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief ACMP0输出未连接到ETM1输入通道0
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_DisableACMP0InputCapture(void)
|
||||
{
|
||||
SIM->SOPT &= ~(SIM_SOPT_ACIC_MASK);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief RTC0映射到PC5上
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_RemapRTCPin(void)
|
||||
{
|
||||
SIM->PINSEL |= SIM_PINSEL_RTCPS_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置总线时钟频率
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_SetBusDivide(uint8_t u8Divide)
|
||||
{
|
||||
SIM->BUSDIV = u8Divide;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief ETM2_CH1通道映射到PH1上
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_RemapETM2CH1Pin(void)
|
||||
{
|
||||
SIM->PINSEL |= SIM_PINSEL_ETM2PS1_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief ETM2_CH0通道映射到PH0上
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_RemapETM2CH0Pin(void)
|
||||
{
|
||||
SIM->PINSEL |= SIM_PINSEL_ETM2PS0_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief ETM1_CH1通道映射到PE7上
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_RemapETM1CH1Pin(void)
|
||||
{
|
||||
SIM->PINSEL |= SIM_PINSEL_ETM1PS1_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief ETM1_CH0映射到PH2上
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SIM_RemapETM1CH0Pin(void)
|
||||
{
|
||||
SIM->PINSEL |= SIM_PINSEL_ETM1PS0_MASK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void SIM_Init(SIM_ConfigType *pConfig);
|
||||
void SIM_SetClockGating(uint32_t u32PeripheralMask, uint8_t u8GateOn);
|
||||
uint32_t SIM_GetStatus(uint32_t u32StatusMask);
|
||||
uint8_t SIM_ReadID(IDType sID);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,297 @@
|
||||
/**************************************************************************!
|
||||
* 技术讨论:QQ群 123763203
|
||||
* 官网 :www.navota.com
|
||||
*
|
||||
* @file spi.c
|
||||
* @brief 串行外设接口模块(SPI)函数库
|
||||
* @author Navota
|
||||
* @date 2017-1-1
|
||||
****************************************************************************/
|
||||
#include "common.h"
|
||||
#include "spi.h"
|
||||
|
||||
/****************************************************************************!
|
||||
* @ 存放SPI回调函数接口
|
||||
****************************************************************************/
|
||||
|
||||
SPI_CallbackType SPI_Callback[MAX_SPI_NO] = {(SPI_CallbackType)NULL};
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 初始化SPI模块
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块.
|
||||
* @param[in] pConfig 指向SPI配置参数.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void SPI_Init(SPI_Type *pSPI, SPI_ConfigType *pConfig)
|
||||
{
|
||||
#if defined(CPU_NV32M3)
|
||||
/* sanity check */
|
||||
ASSERT((pSPI == SPI0));
|
||||
SIM->SCGC |= SIM_SCGC_SPI0_MASK;
|
||||
#else
|
||||
/* sanity check */
|
||||
ASSERT((pSPI == SPI0) || (pSPI == SPI1));
|
||||
|
||||
/*使能SPI模块总线时钟*/
|
||||
if( pSPI == SPI0)
|
||||
{
|
||||
SIM->SCGC |= SIM_SCGC_SPI0_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
SIM->SCGC |= SIM_SCGC_SPI1_MASK;
|
||||
}
|
||||
#endif
|
||||
/*配置SPI控制寄存器 */
|
||||
if( pConfig->sSettings.bIntEn) //使能SPI中断
|
||||
{
|
||||
SPI_IntEnable(pSPI);
|
||||
#if defined(CPU_NV32M3)
|
||||
NVIC_EnableIRQ(SPI0_IRQn);
|
||||
#else
|
||||
if( pSPI == SPI0 )
|
||||
{
|
||||
NVIC_EnableIRQ(SPI0_IRQn);
|
||||
}
|
||||
else
|
||||
{
|
||||
NVIC_EnableIRQ(SPI1_IRQn);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if( pConfig->sSettings.bTxIntEn) //使能SPI发送中断
|
||||
{
|
||||
SPI_TxIntEnable(pSPI);
|
||||
#if defined(CPU_NV32M3)
|
||||
NVIC_EnableIRQ(SPI0_IRQn);
|
||||
#else
|
||||
if( pSPI == SPI0 )
|
||||
{
|
||||
NVIC_EnableIRQ(SPI0_IRQn);
|
||||
}
|
||||
else
|
||||
{
|
||||
NVIC_EnableIRQ(SPI1_IRQn);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if( pConfig->sSettings.bMasterMode) //主/从机选择
|
||||
{
|
||||
SPI_SetMasterMode(pSPI); //SPI设置为主机模式
|
||||
}
|
||||
else
|
||||
{
|
||||
SPI_SetSlaveMode(pSPI); //SPI设置为从机模式
|
||||
}
|
||||
|
||||
if( pConfig->sSettings.bClkPolarityLow) //时钟极性配置
|
||||
{
|
||||
SPI_SetClockPol(pSPI,1);
|
||||
}
|
||||
if( pConfig->sSettings.bClkPhase1) //时钟相位配置
|
||||
{
|
||||
SPI_SetClockPhase(pSPI,1);
|
||||
}
|
||||
if( pConfig->sSettings.bShiftLSBFirst) //设置SPI串行数据传输开始位
|
||||
{
|
||||
SPI_SetLSBFirst(pSPI); // SPI串行数据传输从最低位开始(LSB)
|
||||
}
|
||||
if( pConfig->sSettings.bMatchIntEn)
|
||||
{
|
||||
SPI_MatchIntEnable(pSPI); //使能SPI匹配中断
|
||||
}
|
||||
if( pConfig->sSettings.bModeFaultEn)
|
||||
{
|
||||
SPI_ModfEnable(pSPI); //使能主机模式模式错误功能.
|
||||
}
|
||||
if( pConfig->sSettings.bMasterAutoDriveSS)
|
||||
{
|
||||
/*设置SSOE和MODFEN位,从机模式中SS引脚为从机输出,自动驱动从机SS引脚使能*/
|
||||
SPI_SSOutputEnable(pSPI);
|
||||
SPI_ModfEnable(pSPI);
|
||||
}
|
||||
|
||||
if( pConfig->sSettings.bPinAsOuput)
|
||||
{
|
||||
SPI_BidirPinEnable(pSPI); //使能双向引脚配置.
|
||||
}
|
||||
|
||||
if( pConfig->sSettings.bBidirectionModeEn)
|
||||
{
|
||||
SPI_BidirOutEnable(pSPI); //使能双向模式输出.
|
||||
}
|
||||
if( pConfig->sSettings.bStopInWaitMode)
|
||||
{
|
||||
SPI_ClockStopEnable(pSPI); //SPI时钟在等待模式下关闭
|
||||
}
|
||||
|
||||
if(pConfig->sSettings.bMasterMode) //设置波特率
|
||||
{
|
||||
SPI_SetBaudRate(pSPI,pConfig->u32BusClkHz,pConfig->u32BitRate);
|
||||
}
|
||||
|
||||
/*使能SPI模块*/
|
||||
if( pConfig->sSettings.bModuleEn)
|
||||
{
|
||||
SPI_Enable(pSPI);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置SPI波特率.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块
|
||||
* @param[in] u32BusClock 总线时钟.
|
||||
* @param[in] u32Bps SPI波特率.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void SPI_SetBaudRate(SPI_Type *pSPI,uint32_t u32BusClock,uint32_t u32Bps)
|
||||
{
|
||||
uint32_t u32BitRateDivisor;
|
||||
uint8_t u8Sppr;
|
||||
uint8_t u8Spr;
|
||||
uint8_t u8ReadFlag;
|
||||
u32BitRateDivisor = u32BusClock/u32Bps; /* 计算波特率因子 */
|
||||
|
||||
u8ReadFlag = 0;
|
||||
/* 计算最适合的 SPPR 和 SPR */
|
||||
for (u8Spr = 0; u8Spr <= 8; u8Spr++)
|
||||
{
|
||||
for(u8Sppr = 0; u8Sppr <= 7; u8Sppr++)
|
||||
{
|
||||
if((u32BitRateDivisor>>(u8Spr+1))<=(u8Sppr+1))
|
||||
{
|
||||
u8ReadFlag = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(u8ReadFlag)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(u8Sppr >=8)
|
||||
{
|
||||
u8Sppr = 7;
|
||||
}
|
||||
if(u8Spr >8)
|
||||
{
|
||||
u8Spr = 8;
|
||||
}
|
||||
/* 设置波特率 */
|
||||
pSPI->BR = SPI_BR_SPPR(u8Sppr) | SPI_BR_SPR(u8Spr);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 读/写数据寄存器.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块.
|
||||
* @param[in] pWrBuff -- 发送(写)数组指针
|
||||
* @param[in] uiLength -- 读/写数据长度.
|
||||
* @param[out] pRdBuff -- 接收(读)数组指针.
|
||||
*
|
||||
* @return if <0, means error, 0: success.
|
||||
*
|
||||
*****************************************************************************/
|
||||
ResultType SPI_TransferWait(SPI_Type *pSPI, SPI_WidthType* pRdBuff, SPI_WidthType *pWrBuff,uint32 uiLength)
|
||||
{
|
||||
ResultType err = SPI_ERR_SUCCESS;
|
||||
uint32_t i;
|
||||
|
||||
if(!uiLength)
|
||||
{
|
||||
return (err);
|
||||
}
|
||||
for(i = 0; i < uiLength; i++)
|
||||
{
|
||||
while(!SPI_IsSPTEF(pSPI));
|
||||
SPI_WriteDataReg(pSPI,pWrBuff[i]);
|
||||
while(!SPI_IsSPRF(pSPI));
|
||||
pRdBuff[i] = SPI_ReadDataReg(pSPI);
|
||||
}
|
||||
return (err);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 复位SPI模块
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void SPI_DeInit(SPI_Type *pSPI)
|
||||
{
|
||||
int16 i;
|
||||
pSPI->C1 = SPI_C1_DEFAULT;
|
||||
pSPI->C2 = SPI_C2_DEFAULT;
|
||||
pSPI->BR = SPI_BR_DEFAULT;
|
||||
pSPI->M = SPI_M_DEFAULT;
|
||||
for(i = 0; i<100; i++); /*延时一段时间,等待SPI退出中断 */
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置SPI回调函数,在中断服务函数中调用
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块
|
||||
* @param[in] pfnCallback 回调函数.
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
void SPI_SetCallback(SPI_Type *pSPI,SPI_CallbackType pfnCallback)
|
||||
{
|
||||
uint32_t u32Port = ((uint32_t)pSPI-(uint32_t)SPI0)>>12;
|
||||
ASSERT(u32Port <2);
|
||||
SPI_Callback[u32Port] = pfnCallback;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief SPI0 中断服务函数.
|
||||
*
|
||||
* @param none.
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
void SPI0_Isr(void)
|
||||
{
|
||||
if( SPI_Callback[0] )
|
||||
{
|
||||
SPI_Callback[0]();
|
||||
}
|
||||
}
|
||||
#ifndef CPU_NV32M3
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief SPI1 中断服务函数
|
||||
*
|
||||
* @param none.
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
void SPI1_Isr(void)
|
||||
{
|
||||
if( SPI_Callback[1] )
|
||||
{
|
||||
SPI_Callback[1]();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,567 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief SPI 驱动头文件.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef SPI_H_
|
||||
#define SPI_H_
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
/******************************************************************************
|
||||
* 定义SPI模块个数
|
||||
******************************************************************************/
|
||||
#define MAX_SPI_NO 2
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义SPI寄存复位值
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#define SPI_C1_DEFAULT 0x04 /*!< SPI 控制寄存器1 */
|
||||
#define SPI_C2_DEFAULT 0x00 /*!< SPI 控制寄存器2 */
|
||||
#define SPI_BR_DEFAULT 0x00 /*!< SPI 波特率寄存器 */
|
||||
#define SPI_S_DEFAULT 0x20 /*!< SPI 状态寄存器 */
|
||||
#define SPI_M_DEFAULT 0x00 /*!< SPI 匹配寄存器 */
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 定义SPI传输状态
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#define SPI_ERR_SUCCESS 0 /*!< 成功 */
|
||||
#define SPI_ERR_CODE_BASE ((uint32)SPI0 - 0x40000000L) /*!< SPI基地址错误 */
|
||||
#define SPI_ERR_TXBUF_NOT_EMPTY (SPI_ERR_CODE_BASE+1) /*!< 失败由于发送缓冲区空时,标志位没有置位*/
|
||||
#define SPI_ERR_RXBUF_NOT_FULL (SPI_ERR_CODE_BASE+2) /*!< 失败由于接收缓冲区满时,标志位没有置位 */
|
||||
|
||||
/******************************************************************************
|
||||
* 数据类型别名定义
|
||||
******************************************************************************/
|
||||
|
||||
typedef uint8_t SPI_WidthType; /* SPI 发送数据宽度类型 */
|
||||
typedef uint32_t ResultType; /* SPI 收发返回状态数据类型 */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* SPI回调函数声明
|
||||
*
|
||||
*******************************************************************************/
|
||||
typedef void (*SPI_CallbackType)(void);
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* SPI 结构体类型
|
||||
*
|
||||
*******************************************************************************/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t bIntEn : 1; /*!< 1: 使能中断, 0: 禁用中断*/
|
||||
uint32_t bModuleEn : 1; /*!< 1: 使能SPI模块, 0: 禁用SPI模块 */
|
||||
uint32_t bTxIntEn : 1; /*!< 1: 使能发送中断, 0: 禁用发送中断 */
|
||||
uint32_t bMasterMode : 1; /*!< 1: 主机模式, 0: 从机模式 */
|
||||
uint32_t bClkPolarityLow : 1; /*!< 设置时钟极性 */
|
||||
uint32_t bClkPhase1 : 1; /*!< 设置时钟相位 */
|
||||
uint32_t bMasterAutoDriveSS : 1; /*!< 从机选择输出使能 */
|
||||
uint32_t bShiftLSBFirst : 1; /*!< 1: LSB, 0: MSB */
|
||||
uint32_t bMatchIntEn : 1; /*!< 1: 使能匹配中断, 0: 禁用匹配中断 */
|
||||
uint32_t bModeFaultEn : 1; /*!< 使能主机模式错误功能 */
|
||||
uint32_t bBidirectionModeEn : 1; /*!< 双向模式输出控制 */
|
||||
uint32_t bPinAsOuput : 1; /*!< SPI引脚控制 */
|
||||
uint32_t bStopInWaitMode : 1; /*!< 配置SPI时钟在等待模式下的工作状态 */
|
||||
uint32_t bRsvd : 19;
|
||||
} SPI_SettingType;
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* SPI配置结构体类型
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SPI_SettingType sSettings; /*!< SPI 结构体 */
|
||||
uint32_t u32BitRate; /*!< 设置波特率 */
|
||||
uint32_t u32BusClkHz; /*!< 输入总线时钟 */
|
||||
} SPI_ConfigType; /*!< SPI配置结构体 */
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief SPI串行数据传输从最低位开始(LSB)
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
__STATIC_INLINE void SPI_SetLSBFirst(SPI_Type *pSPI)
|
||||
{
|
||||
pSPI->C1 |= SPI_C1_LSBFE_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief SPI串行数据传输从最高位开始(MSB)
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
__STATIC_INLINE void SPI_SetMSBFirst(SPI_Type *pSPI)
|
||||
{
|
||||
pSPI->C1 &= ~SPI_C1_LSBFE_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置SPI时钟极性.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块 .
|
||||
* @param[in] u8PolLow 设置时钟极性. 1-SCK时钟有效状态为高(无效状态为低)
|
||||
* 0-SCK时钟有效状态为低(无效状态为高)
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
__STATIC_INLINE void SPI_SetClockPol(SPI_Type *pSPI,uint8_t u8PolLow)
|
||||
{
|
||||
if( u8PolLow )
|
||||
{
|
||||
pSPI->C1 |= SPI_C1_CPOL_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
pSPI->C1 &= ~SPI_C1_CPOL_MASK;
|
||||
}
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置SPI时钟相位.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块
|
||||
* @param[in] u8Phase 设置时钟相位, 1 - 数据在SCK下降沿输出,在上升沿采样.
|
||||
* 0 - 数据在SCK上升沿采样,在下降沿输出
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
__STATIC_INLINE void SPI_SetClockPhase(SPI_Type *pSPI,uint8_t u8Phase)
|
||||
{
|
||||
if( u8Phase )
|
||||
{
|
||||
pSPI->C1 |= SPI_C1_CPHA_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
pSPI->C1 &= ~SPI_C1_CPHA_MASK;
|
||||
}
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能SPI模块.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
__STATIC_INLINE void SPI_Enable(SPI_Type *pSPI)
|
||||
{
|
||||
pSPI->C1 |= SPI_C1_SPE_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用SPI模块
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
__STATIC_INLINE void SPI_Disable(SPI_Type *pSPI)
|
||||
{
|
||||
pSPI->C1 &= ~SPI_C1_SPE_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能SPI中断.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
__STATIC_INLINE void SPI_IntEnable(SPI_Type *pSPI)
|
||||
{
|
||||
pSPI->C1 |= SPI_C1_SPIE_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用SPI中断.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SPI_IntDisable(SPI_Type *pSPI)
|
||||
{
|
||||
pSPI->C1 &= ~SPI_C1_SPIE_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置SPI为主机模式.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SPI_SetMasterMode(SPI_Type *pSPI)
|
||||
{
|
||||
pSPI->C1 |= SPI_C1_MSTR_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置SPI为从机模式.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块 .
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SPI_SetSlaveMode(SPI_Type *pSPI)
|
||||
{
|
||||
pSPI->C1 &= ~SPI_C1_MSTR_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能SPI发送中断.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块 .
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SPI_TxIntEnable(SPI_Type *pSPI)
|
||||
{
|
||||
pSPI->C1 |= SPI_C1_SPTIE_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用SPI发送中断.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块 .
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @ Pass/ Fail criteria: none
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SPI_TxIntDisable(SPI_Type *pSPI)
|
||||
{
|
||||
pSPI->C1 &= ~SPI_C1_SPTIE_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能从机选择输出.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块 .
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SPI_SSOutputEnable(SPI_Type *pSPI )
|
||||
{
|
||||
pSPI->C1 |= SPI_C1_SSOE_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用从机选择输出.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块 .
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SPI_SSOutputDisable(SPI_Type *pSPI )
|
||||
{
|
||||
pSPI->C1 &= ~SPI_C1_SSOE_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能SPI匹配中断.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块 .
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SPI_MatchIntEnable(SPI_Type *pSPI )
|
||||
{
|
||||
pSPI->C2 |= SPI_C2_SPMIE_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用SPI匹配中断.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SPI_MatchIntDisable(SPI_Type *pSPI )
|
||||
{
|
||||
pSPI->C2 &= ~SPI_C2_SPMIE_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用主机模式错误功能
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块 .
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SPI_ModfDisable(SPI_Type *pSPI )
|
||||
{
|
||||
pSPI->C2 &= ~SPI_C2_MODFEN_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
|
||||
*
|
||||
* @brief 使能主机模式模式错误功能.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SPI_ModfEnable(SPI_Type *pSPI )
|
||||
{
|
||||
pSPI->C2 |= SPI_C2_MODFEN_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能双向模式输出.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块 .
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SPI_BidirOutEnable(SPI_Type *pSPI )
|
||||
{
|
||||
pSPI->C2 |= SPI_C2_BIDIROE_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用双向模式输出
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SPI_BidirOutDisable(SPI_Type *pSPI )
|
||||
{
|
||||
pSPI->C2 &= ~SPI_C2_BIDIROE_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief SPI时钟在等待模式下一直运行
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块 .
|
||||
*
|
||||
* @return none.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SPI_ClockStopDisable(SPI_Type *pSPI )
|
||||
{
|
||||
pSPI->C2 &= ~SPI_C2_SPISWAI_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief SPI时钟在等待模式下关闭
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SPI_ClockStopEnable(SPI_Type *pSPI )
|
||||
{
|
||||
pSPI->C2 |= SPI_C2_SPISWAI_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能双向引脚配置.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SPI_BidirPinEnable(SPI_Type *pSPI)
|
||||
{
|
||||
pSPI->C2 |= SPI_C2_SPC0_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief SPI使用独立的引脚用作数据的输入输出.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SPI_BidirPinDisable(SPI_Type *pSPI)
|
||||
{
|
||||
pSPI->C2 &= ~SPI_C2_SPC0_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 读取接收数据缓冲区满标准位.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块 .
|
||||
*
|
||||
* @return TRUE or FALSE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t SPI_IsSPRF(SPI_Type *pSPI )
|
||||
{
|
||||
return(pSPI->S & SPI_S_SPRF_MASK);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 读取SPI匹配标志位
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块 .
|
||||
*
|
||||
* @return TRUE or FALSE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t SPI_IsSPMF(SPI_Type *pSPI )
|
||||
{
|
||||
return(pSPI->S & SPI_S_SPMF_MASK);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 读取SPI发送数据缓冲区空标志位.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块 .
|
||||
*
|
||||
* @return TRUE or FALSE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t SPI_IsSPTEF(SPI_Type *pSPI )
|
||||
{
|
||||
return(pSPI->S & SPI_S_SPTEF_MASK);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 读取主机模式错误标志位
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块
|
||||
*
|
||||
* @return TRUE or FALSE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t SPI_IsMODF(SPI_Type *pSPI )
|
||||
{
|
||||
return(pSPI->S & SPI_S_MODF_MASK);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 读取SPI数据寄存器.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块
|
||||
*
|
||||
* @return 数据寄存器的值
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t SPI_ReadDataReg(SPI_Type *pSPI )
|
||||
{
|
||||
return pSPI->D;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 写数据到SPI数据寄存器.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块
|
||||
* @param[in] u8WrBuff 写到SPI数据寄存器的数据缓冲区
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SPI_WriteDataReg(SPI_Type *pSPI, uint8_t u8WrBuff )
|
||||
{
|
||||
pSPI->D = u8WrBuff;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 写数据到SPI匹配寄存器.
|
||||
*
|
||||
* @param[in] pSPI 指向SPI模块
|
||||
* @param[in] u8WrBuff 写到SPI匹配寄存器的数据缓冲区
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void SPI_WriteMatchValue(SPI_Type *pSPI, uint8_t u8WrBuff )
|
||||
{
|
||||
pSPI->M = u8WrBuff;
|
||||
}
|
||||
/******************************************************************************/
|
||||
|
||||
void SPI_Enable(SPI_Type *pSPI);
|
||||
void SPI_Disable(SPI_Type *pSPI);
|
||||
void SPI_SetLSBFirst(SPI_Type *pSPI);
|
||||
void SPI_SetMSBFirst(SPI_Type *pSPI);
|
||||
void SPI_IntEnable(SPI_Type *pSPI);
|
||||
void SPI_IntDisable(SPI_Type *pSPI);
|
||||
void SPI_SetMasterMode(SPI_Type *pSPI);
|
||||
void SPI_SetSlaveMode(SPI_Type *pSPI);
|
||||
void SPI_TxIntEnable(SPI_Type *pSPI);
|
||||
void SPI_TxIntDisable(SPI_Type *pSPI);
|
||||
void SPI_SSOutputEnable(SPI_Type *pSPI );
|
||||
void SPI_SSOutputDisable(SPI_Type *pSPI );
|
||||
void SPI_MatchIntEnable(SPI_Type *pSPI );
|
||||
void SPI_MatchIntDisable(SPI_Type *pSPI );
|
||||
void SPI_ModfDisable(SPI_Type *pSPI );
|
||||
void SPI_ModfEnable(SPI_Type *pSPI );
|
||||
void SPI_BidirOutEnable(SPI_Type *pSPI );
|
||||
void SPI_BidirOutDisable(SPI_Type *pSPI );
|
||||
void SPI_ClockStopDisable(SPI_Type *pSPI );
|
||||
void SPI_ClockStopEnable(SPI_Type *pSPI );
|
||||
void SPI_BidirPinEnable(SPI_Type *pSPI );
|
||||
void SPI_BidirPinDisable(SPI_Type *pSPI );
|
||||
void SPI_SetClockPol(SPI_Type *pSPI,uint8_t u8PolLow);
|
||||
void SPI_SetClockPhase(SPI_Type *pSPI,uint8_t u8Phase);
|
||||
void SPI_SetBaudRate(SPI_Type *pSPI,uint32_t u32BusClock,uint32_t u32Bps );
|
||||
uint8_t SPI_IsSPRF(SPI_Type *pSPI );
|
||||
uint8_t SPI_IsSPMF(SPI_Type *pSPI );
|
||||
uint8_t SPI_IsSPTEF(SPI_Type *pSPI );
|
||||
uint8_t SPI_IsMODF(SPI_Type *pSPI );
|
||||
uint8_t SPI_ReadDataReg(SPI_Type *pSPI );
|
||||
void SPI_WriteDataReg(SPI_Type *pSPI, uint8_t u8WrBuff );
|
||||
void SPI_WriteMatchValue(SPI_Type *pSPI, uint8_t u8WrBuff );
|
||||
void SPI_Init(SPI_Type *pSPI, SPI_ConfigType *pConfig);
|
||||
void SPI_DeInit(SPI_Type *pSPI);
|
||||
ResultType SPI_TransferWait(SPI_Type *pSPI, SPI_WidthType* pRdBuff, SPI_WidthType *pWrBuff,uint32 uiLength);
|
||||
void SPI_SetCallback(SPI_Type *pSPI,SPI_CallbackType pfnCallback);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,437 @@
|
||||
/*************************************************************************!
|
||||
* 技术讨论:QQ群 123763203
|
||||
* 官网 :www.navota.com
|
||||
*
|
||||
* @file uart.c
|
||||
* @brief uart通讯接口函数库
|
||||
* @author Navota
|
||||
* @date 2017-1-1
|
||||
*************************************************************************/
|
||||
#include "uart.h"
|
||||
|
||||
|
||||
/*!
|
||||
* @brief 存放回调入口
|
||||
*
|
||||
*/
|
||||
UART_CallbackType UART_Callback = NULL;
|
||||
|
||||
/******************************************************************************
|
||||
* 定义UART的接口函数
|
||||
*******************************************************************************/
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 初始化UART,关中断,无硬件流控制.
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
* @param[in] pConfig 配置UART的结构体
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void UART_Init(UART_Type *pUART, UART_ConfigType *pConfig)
|
||||
{
|
||||
uint16_t u16Sbr;
|
||||
uint8_t u8Temp;
|
||||
uint32_t u32SysClk = pConfig->u32SysClkHz;//定义系统时钟
|
||||
uint32_t u32Baud = pConfig->u32Baudrate;//定义波特率
|
||||
|
||||
/* 合法性检查 */
|
||||
ASSERT((pUART == UART0) || (pUART == UART1) || (pUART == UART2));
|
||||
|
||||
/* 设置时钟选通控制用来选择相应的 UART 口 */
|
||||
if (pUART == UART0)
|
||||
{
|
||||
SIM->SCGC |= SIM_SCGC_UART0_MASK;//使能相应功能位, 选通对应 UART
|
||||
}
|
||||
#if defined(CPU_NV32)
|
||||
else if (pUART == UART1)
|
||||
{
|
||||
SIM->SCGC |= SIM_SCGC_UART1_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
SIM->SCGC |= SIM_SCGC_UART2_MASK;
|
||||
}
|
||||
#endif
|
||||
/*确保在我们进行配置时, 禁止发送和接收*/
|
||||
pUART->C2 &= ~(UART_C2_TE_MASK | UART_C2_RE_MASK );
|
||||
|
||||
/* 配置 UART 为 8 位模式, 无奇偶校验位 */
|
||||
pUART->C1 = 0;
|
||||
|
||||
/* 波特率计算 */
|
||||
u16Sbr = (((u32SysClk)>>4) + (u32Baud>>1))/u32Baud;
|
||||
|
||||
/*把当前数据存放在串口波特率寄存器中, 且SBR位清0,即波特率发生器被禁止*/
|
||||
u8Temp = pUART->BDH & ~(UART_BDH_SBR_MASK);
|
||||
|
||||
pUART->BDH = u8Temp | UART_BDH_SBR(u16Sbr >> 8);
|
||||
pUART->BDL = (uint8_t)(u16Sbr & UART_BDL_SBR_MASK);
|
||||
|
||||
/*使能 UART 接收和发送 */
|
||||
pUART->C2 |= (UART_C2_TE_MASK | UART_C2_RE_MASK );
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 接收一个字符.
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return 接收到的字符
|
||||
*
|
||||
*****************************************************************************/
|
||||
uint8_t UART_GetChar(UART_Type *pUART)
|
||||
{
|
||||
|
||||
/* 合法性检测 */
|
||||
ASSERT((pUART == UART0) || (pUART == UART1) || (pUART == UART2));
|
||||
|
||||
/* 等待直到一个字符被接收 */
|
||||
while (!(pUART->S1 & UART_S1_RDRF_MASK));
|
||||
|
||||
/* 返回接收到的8位数据 */
|
||||
return pUART->D;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 发送一个字符.
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
* @param[in] u8Char 要发送的字符
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void UART_PutChar(UART_Type *pUART, uint8_t u8Char)
|
||||
{
|
||||
/* 一直等待, 直到缓冲区为空 */
|
||||
while (!(pUART->S1 & UART_S1_TDRE_MASK));
|
||||
|
||||
/* 发送字符到数据寄存器 */
|
||||
pUART->D = (uint8_t)u8Char;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 波特率设置.
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
* @param[in] pConfig 波特率相关配置结构体
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void UART_SetBaudrate(UART_Type *pUART, UART_ConfigBaudrateType *pConfig)
|
||||
{
|
||||
uint8_t u8Temp;
|
||||
uint16_t u16Sbr;
|
||||
uint32_t u32SysClk = pConfig->u32SysClkHz;
|
||||
uint32_t u32baud = pConfig->u32Baudrate;
|
||||
|
||||
/* 合法性检测 */
|
||||
ASSERT((pUART == UART0) || (pUART == UART1) || (pUART == UART2));
|
||||
|
||||
/*计算波特率,四舍五入提高精度 */
|
||||
u16Sbr = (((u32SysClk)>>4) + (u32baud>>1))/u32baud;
|
||||
|
||||
|
||||
u8Temp = pUART->BDH & ~(UART_BDH_SBR_MASK);
|
||||
|
||||
pUART->BDH = u8Temp | UART_BDH_SBR(u16Sbr >> 8);
|
||||
pUART->BDL = (uint8_t)(u16Sbr & UART_BDL_SBR_MASK);
|
||||
|
||||
|
||||
pUART->C2 |= (UART_C2_TE_MASK | UART_C2_RE_MASK );
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能UART中断.
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
* @param[in] InterruptType 中断的类型
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void UART_EnableInterrupt(UART_Type *pUART, UART_InterruptType InterruptType)
|
||||
{
|
||||
|
||||
/* 通道合法性检查 */
|
||||
ASSERT((pUART == UART0) || (pUART == UART1) || (pUART == UART2));
|
||||
|
||||
if (InterruptType == UART_TxBuffEmptyInt) //发送中断使能
|
||||
{
|
||||
pUART->C2 |= UART_C2_TIE_MASK;
|
||||
}
|
||||
else if (InterruptType == UART_TxCompleteInt) //传输完成中断使能
|
||||
{
|
||||
pUART->C2 |= UART_C2_TCIE_MASK;
|
||||
}
|
||||
else if (InterruptType == UART_RxBuffFullInt) //接收器中断使能
|
||||
{
|
||||
pUART->C2 |= UART_C2_RIE_MASK;
|
||||
}
|
||||
else if (InterruptType == UART_IdleLineInt) //空闲线中断使能
|
||||
{
|
||||
pUART->C2 |= UART_C2_ILIE_MASK;
|
||||
}
|
||||
else if (InterruptType == UART_RxOverrunInt) //过载中断使能
|
||||
{
|
||||
pUART->C3 |= UART_C3_ORIE_MASK;
|
||||
}
|
||||
else if (InterruptType == UART_NoiseErrorInt) //噪声错误中断使能
|
||||
{
|
||||
pUART->C3 |= UART_C3_NEIE_MASK;
|
||||
}
|
||||
else if (InterruptType == UART_FramingErrorInt) //帧错误中断使能
|
||||
{
|
||||
pUART->C3 |= UART_C3_FEIE_MASK;
|
||||
}
|
||||
else if (InterruptType == UART_ParityErrorInt) //奇偶校验中断使能
|
||||
{
|
||||
pUART->C3 |= UART_C3_FEIE_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
//其他暂不支持类型的中断
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用UART中断.
|
||||
*
|
||||
* @param[in] 指向三个UART其中一个的基址
|
||||
* @param[in] 中断的类型
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void UART_DisableInterrupt(UART_Type *pUART, UART_InterruptType InterruptType)
|
||||
{
|
||||
/* 通道合法性检查 */
|
||||
ASSERT((pUART == UART0) || (pUART == UART1) || (pUART == UART2));
|
||||
|
||||
|
||||
if (InterruptType == UART_TxBuffEmptyInt) //发送中断禁用
|
||||
{
|
||||
pUART->C2 &= (~UART_C2_TIE_MASK);
|
||||
}
|
||||
else if (InterruptType == UART_TxCompleteInt) //传输完成中断禁用
|
||||
{
|
||||
pUART->C2 &= (~UART_C2_TCIE_MASK);
|
||||
}
|
||||
else if (InterruptType == UART_RxBuffFullInt) //接收器中断禁用
|
||||
{
|
||||
pUART->C2 &= (~UART_C2_RIE_MASK);
|
||||
}
|
||||
else if (InterruptType == UART_IdleLineInt) //空闲线中断禁用
|
||||
{
|
||||
pUART->C2 &= (~UART_C2_ILIE_MASK);
|
||||
}
|
||||
else if (InterruptType == UART_RxOverrunInt) //过载中断禁用
|
||||
{
|
||||
pUART->C3 &= (~UART_C3_ORIE_MASK);
|
||||
}
|
||||
else if (InterruptType == UART_NoiseErrorInt) //噪声错误中断禁用
|
||||
{
|
||||
pUART->C3 &= (~UART_C3_NEIE_MASK);
|
||||
}
|
||||
else if (InterruptType == UART_FramingErrorInt) //帧错误中断禁用
|
||||
{
|
||||
pUART->C3 &= (~UART_C3_FEIE_MASK);
|
||||
}
|
||||
else if (InterruptType == UART_ParityErrorInt) //奇偶校验中断禁用
|
||||
{
|
||||
pUART->C3 &= (~UART_C3_FEIE_MASK);
|
||||
}
|
||||
else
|
||||
{
|
||||
//其他暂不支持类型的中断
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 从两个状态寄存器获取UART状态
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return 16位的状态
|
||||
*
|
||||
*****************************************************************************/
|
||||
uint16_t UART_GetFlags(UART_Type *pUART)
|
||||
{
|
||||
uint16_t u16StatusFlags = 0;//先清空标志位
|
||||
|
||||
u16StatusFlags = pUART->S2; //将状态寄存器 2 的值赋给标志参数
|
||||
u16StatusFlags = (u16StatusFlags<<8)| pUART->S1; //两个状态寄存器拼接赋给标志参数
|
||||
|
||||
return u16StatusFlags;//返回标志参数的值
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 检查特定的位是否置位.
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
* @param[in] FlagType 位的类型
|
||||
*
|
||||
* @return
|
||||
* 1, 标志置位
|
||||
* 0, 标志清零
|
||||
*
|
||||
*****************************************************************************/
|
||||
uint8_t UART_CheckFlag(UART_Type *pUART, UART_FlagType FlagType)
|
||||
{
|
||||
uint16_t u16StatusFlags = 0;
|
||||
|
||||
u16StatusFlags = UART_GetFlags(pUART);
|
||||
|
||||
return (u16StatusFlags & (1<<FlagType));
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 用查询模式发送字符串.
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
* @param[in] pSendBuff 字符串首地址
|
||||
* @param[in] u32Length 字符串的长度
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void UART_SendWait(UART_Type *pUART, uint8_t *pSendBuff, uint32_t u32Length)
|
||||
{
|
||||
uint8_t u8TxChar;
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < u32Length; i++)
|
||||
{
|
||||
u8TxChar = pSendBuff[i];
|
||||
while (!UART_IsTxBuffEmpty(pUART))
|
||||
{
|
||||
#if defined(ENABLE_WDOG)
|
||||
WDOG_Feed();
|
||||
#endif
|
||||
}
|
||||
UART_WriteDataReg(pUART, u8TxChar);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 用查询模式接收字符串.
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
* @param[in] pReceiveBuff 定义接收字符串的首地址
|
||||
* @param[in] u32Length 所要接收字符串的长度
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void UART_ReceiveWait(UART_Type *pUART, uint8_t *pReceiveBuff, uint32_t u32Length)
|
||||
{
|
||||
uint8_t u8RxChar;
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < u32Length; i++)
|
||||
{
|
||||
while (!UART_IsRxBuffFull(pUART))
|
||||
{
|
||||
#if defined(ENABLE_WDOG)
|
||||
WDOG_Feed();
|
||||
#endif
|
||||
}
|
||||
u8RxChar = UART_ReadDataReg(pUART);
|
||||
pReceiveBuff[i] = u8RxChar;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 等待发送完成.
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void UART_WaitTxComplete(UART_Type *pUART)
|
||||
{
|
||||
while (!UART_IsTxComplete(pUART));//一直等待直到发送完成
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置UART模块的中断回调函数.
|
||||
*
|
||||
* @param[in] pfnCallback 回调函数的地址
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void UART_SetCallback(UART_CallbackType pfnCallback)
|
||||
{
|
||||
UART_Callback = pfnCallback;
|
||||
}
|
||||
|
||||
|
||||
/*! @} */
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief uart0 中断服务函数.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void UART0_Isr(void)
|
||||
{
|
||||
UART_Callback(UART0);
|
||||
}
|
||||
|
||||
|
||||
#if defined(CPU_NV32)
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief uart0 中断服务函数.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void UART1_Isr(void)
|
||||
{
|
||||
UART_Callback(UART1);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief uart0 中断服务函数.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void UART2_Isr(void)
|
||||
{
|
||||
UART_Callback(UART2);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,461 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief UART 驱动头文件.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef _UART_H_
|
||||
#define _UART_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
#include "wdog.h"
|
||||
|
||||
#define MAX_UART_NO 3
|
||||
|
||||
|
||||
/*!
|
||||
* @brief UART 设置类型.
|
||||
*
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t bEnable : 1; /*!< 1: 使能, 0: 禁用 */
|
||||
uint32_t resvd : 31; /*!< 1: 保留位域 */
|
||||
} UART_SettingType;
|
||||
/*! @} */
|
||||
|
||||
/*!
|
||||
* @brief UART 配置结构体.
|
||||
*
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
UART_SettingType sSettings; /*!< UART 设置 */
|
||||
uint32_t u32SysClkHz; /*!< 系统时钟 */
|
||||
uint32_t u32Baudrate; /*!< UART 波特率 */
|
||||
} UART_ConfigType;
|
||||
/*! @} */
|
||||
|
||||
/*!
|
||||
* @brief UART 波特率配置结构体.
|
||||
*
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t u32SysClkHz; /*!< 系统时钟 */
|
||||
uint32_t u32Baudrate; /*!< UART 波特率 */
|
||||
} UART_ConfigBaudrateType;
|
||||
/*! @} */
|
||||
|
||||
/******************************************************************************
|
||||
*define uart配置模式列表
|
||||
*
|
||||
*//*! @uart配置模式列表
|
||||
* @{
|
||||
******************************************************************************/
|
||||
typedef enum
|
||||
{
|
||||
UART_Mode8Bit, /*!< 8位模式 */
|
||||
UART_Mode9Bit, /*!< 9位模式 */
|
||||
UART_ModeEnableLoopback, /*!< 使能环回模式 */
|
||||
UART_ModeDisableLoopback, /*!< 禁用环回模式*/
|
||||
UART_ModeEnableSingleWire, /*!< 使能UART单线模式 */
|
||||
UART_ModeDisableSingleWire, /*!< 禁用UART单线模式 */
|
||||
} UART_ModeType;
|
||||
/*! @} */
|
||||
|
||||
/******************************************************************************
|
||||
*define uart中断类型
|
||||
*
|
||||
*//*! @uart中断类型列表
|
||||
* @{
|
||||
******************************************************************************/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
UART_TxBuffEmptyInt, /*!< 发送中断 */
|
||||
UART_TxCompleteInt, /*!< 传输完成中断 */
|
||||
UART_RxBuffFullInt, /*!< 接收器中断 */
|
||||
|
||||
UART_IdleLineInt, /*!< 空闲线中断 */
|
||||
|
||||
UART_RxOverrunInt, /*!< 过载中断 */
|
||||
UART_NoiseErrorInt, /*!< 噪声错误中断 */
|
||||
UART_FramingErrorInt, /*!< /帧错误中断 */
|
||||
UART_ParityErrorInt, /*!< 奇偶校验中断 */
|
||||
} UART_InterruptType;
|
||||
/*! @} */
|
||||
|
||||
/******************************************************************************
|
||||
*define uart标志类型定义
|
||||
*
|
||||
*//*! @uart标志类型定义列表
|
||||
* @{
|
||||
******************************************************************************/
|
||||
typedef enum
|
||||
{
|
||||
UART_FlagPF = 0, /*!< 奇数 */
|
||||
UART_FlagFE, /*!< 帧错误标志 */
|
||||
UART_FlagNF, /*!< 噪声标志 */
|
||||
UART_FlagOR, /*!< 接收过载 */
|
||||
UART_FlagIDLE, /*!< 空闲线标志 */
|
||||
UART_FlagRDRF, /*!< 接收数据满标志 */
|
||||
UART_FlagTC, /*!< 发送完成标志 */
|
||||
UART_FlagTDRE, /*!< 发送寄存器空标志 */
|
||||
|
||||
UART_FlagRAF, /*!< 有效接收器标志 */
|
||||
UART_FlagLBKDE, /*!< LIN间隔检测使能 */
|
||||
UART_FlagBRK13, /*!< 间隔字符长度 */
|
||||
UART_FlagRWUID, /*!< 接收唤醒空闲检测 */
|
||||
UART_FlagRXINV, /*!< 接收数据反转 */
|
||||
UART_FlagRev1, /*!< 保留 */
|
||||
UART_FlagRXEDGIF, /*!< RXD引脚的有效边沿中断标志 */
|
||||
UART_FlagLBKDIF, /*!< LIN终止检测中断标志 */
|
||||
} UART_FlagType;
|
||||
/*! @} */
|
||||
|
||||
/*!
|
||||
* @brief UART 回调类型.
|
||||
*
|
||||
*/
|
||||
typedef void (*UART_CallbackType)(UART_Type *pUART);
|
||||
|
||||
/******************************************************************************
|
||||
******************************************************************************/
|
||||
|
||||
/*!
|
||||
* 内联函数
|
||||
*/
|
||||
/******************************************************************************
|
||||
*******************************************************************************/
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 读取接收数据
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return 接收到的字符
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t UART_ReadDataReg(UART_Type *pUART)
|
||||
{
|
||||
return pUART->D;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 写发送字符
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
* @param[in] u8Char 需要发送的字符
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void UART_WriteDataReg(UART_Type *pUART, uint8_t u8Char)
|
||||
{
|
||||
pUART->D = (uint8_t)u8Char;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 检测接收数据寄存器是否满
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return 0, 没有字符接收; 非0, 有字符接收到
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t UART_CharPresent(UART_Type *pUART)
|
||||
{
|
||||
return (pUART->S1 & UART_S1_RDRF_MASK);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能发送器
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void UART_EnableTx(UART_Type *pUART)
|
||||
{
|
||||
|
||||
pUART->C2 |= UART_C2_TE_MASK;
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用发送器
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void UART_DisableTx(UART_Type *pUART)
|
||||
{
|
||||
pUART->C2 &= (~UART_C2_TE_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能接收器
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void UART_EnableRx(UART_Type *pUART)
|
||||
{
|
||||
pUART->C2 |= UART_C2_RE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用接收器
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void UART_DisableRx(UART_Type *pUART)
|
||||
{
|
||||
pUART->C2 &= (~UART_C2_RE_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能循环模式
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void UART_EnableLoopback(UART_Type *pUART)
|
||||
{
|
||||
pUART->C1 |= UART_C1_LOOPS_MASK;
|
||||
pUART->C1 &= (~UART_C1_RSRC_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能单线模式
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void UART_EnableSingleWire(UART_Type *pUART)
|
||||
{
|
||||
pUART->C1 |= UART_C1_LOOPS_MASK;
|
||||
pUART->C1 |= UART_C1_RSRC_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置8位模式
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void UART_Set8BitMode(UART_Type *pUART)
|
||||
{
|
||||
pUART->C1 &= (~UART_C1_M_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置9位模式
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void UART_Set9BitMode(UART_Type *pUART)
|
||||
{
|
||||
pUART->C1 |= UART_C1_M_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能发送空中断
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void UART_EnableTxBuffEmptyInt(UART_Type *pUART)
|
||||
{
|
||||
pUART->C2 |= UART_C2_TIE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能发送完成中断
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void UART_EnableTxCompleteInt(UART_Type *pUART)
|
||||
{
|
||||
pUART->C2 |= UART_C2_TCIE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能接收满中断
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void UART_EnableRxBuffFullInt(UART_Type *pUART)
|
||||
{
|
||||
pUART->C2 |= UART_C2_RIE_MASK;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用发送空中断
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void UART_DisableTxBuffEmptyInt(UART_Type *pUART)
|
||||
{
|
||||
pUART->C2 &= (~UART_C2_TIE_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用传输完成中断
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void UART_DisableTxCompleteInt(UART_Type *pUART)
|
||||
{
|
||||
pUART->C2 &= (~UART_C2_TCIE_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用接收满中断
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void UART_DisableRxBuffFullInt(UART_Type *pUART)
|
||||
{
|
||||
pUART->C2 &= (~UART_C2_RIE_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 发送间隔字符
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE void UART_PutBreak(UART_Type *pUART)
|
||||
{
|
||||
pUART->C2 |= UART_C2_SBK_MASK;
|
||||
pUART->C2 &= (~UART_C2_SBK_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 检测发送完成标志.
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return
|
||||
* 1, 发送标志置位
|
||||
* 0, 发送标志清除
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t UART_IsTxComplete(UART_Type *pUART)
|
||||
{
|
||||
return (pUART->S1 & UART_S1_TC_MASK);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 检测发送寄存器是否空
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return
|
||||
* 1, 发送寄存器空
|
||||
* 0, 发送寄存器不为空
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t UART_IsTxBuffEmpty(UART_Type *pUART)
|
||||
{
|
||||
return (pUART->S1 & UART_S1_TDRE_MASK);
|
||||
}
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 检测接收数据寄存器是否满
|
||||
*
|
||||
* @param[in] pUART 指向三个UART其中一个的基址
|
||||
*
|
||||
* @return
|
||||
* 1, 接收数据寄存器满
|
||||
* 0, 接收数据寄存器不为满
|
||||
*
|
||||
*****************************************************************************/
|
||||
__STATIC_INLINE uint8_t UART_IsRxBuffFull(UART_Type *pUART)
|
||||
{
|
||||
return (pUART->S1 & UART_S1_RDRF_MASK);
|
||||
}
|
||||
/*! @} */
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
******************************************************************************/
|
||||
void UART_Init(UART_Type *pUART, UART_ConfigType *pConfig);
|
||||
uint8_t UART_GetChar(UART_Type *pUART);
|
||||
void UART_PutChar(UART_Type *pUART, uint8_t u8Char);
|
||||
void UART_SetBaudrate(UART_Type *pUART, UART_ConfigBaudrateType *pConfig);
|
||||
void UART_EnableInterrupt(UART_Type *pUART, UART_InterruptType InterruptType);
|
||||
void UART_DisableInterrupt(UART_Type *pUART, UART_InterruptType InterruptType);
|
||||
uint16_t UART_GetFlags(UART_Type *pUART);
|
||||
uint8_t UART_CheckFlag(UART_Type *pUART, UART_FlagType FlagType);
|
||||
void UART_SendWait(UART_Type *pUART, uint8_t *pSendBuff, uint32_t u32Length);
|
||||
void UART_ReceiveWait(UART_Type *pUART, uint8_t *pReceiveBuff, uint32_t u32Length);
|
||||
void UART_WaitTxComplete(UART_Type *pUART);
|
||||
void UART_SetCallback(UART_CallbackType pfnCallback);
|
||||
void UART0_Isr(void);
|
||||
void UART1_Isr(void);
|
||||
void UART2_Isr(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* #ifndef _UART_H_ */
|
||||
@@ -0,0 +1,265 @@
|
||||
/****************************************************************************!
|
||||
* 技术讨论:QQ群 123763203
|
||||
* 官网 :www.navota.com
|
||||
*
|
||||
* @file wdg.c
|
||||
* @brief wdg定时器函数库
|
||||
* @author Navota
|
||||
* @date 2018-3-1
|
||||
*******************************************************************************/
|
||||
#include "common.h"
|
||||
#include "wdog.h"
|
||||
|
||||
/******************************************************************************
|
||||
*******************************************************************************/
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用看门狗定时器
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
void WDOG_Disable(void)
|
||||
{
|
||||
uint8_t u8Cs1 = WDOG->CS1;
|
||||
uint8_t u8Cs2 = WDOG->CS2;
|
||||
uint16_t u16TOVAL = WDOG->TOVAL;
|
||||
uint16_t u16WIN = WDOG->WIN;
|
||||
|
||||
u8Cs1 &= ~WDOG_CS1_EN_MASK;
|
||||
|
||||
/* 首先要解锁unlock看门狗,才可以往寄存器写数据 */
|
||||
WDOG_Unlock();
|
||||
WDOG->CS2 = u8Cs2;
|
||||
WDOG->TOVAL = u16TOVAL;
|
||||
WDOG->WIN = u16WIN;
|
||||
WDOG->CS1 = u8Cs1;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用看门狗但允许其重新配置.
|
||||
*
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void WDOG_DisableWDOGEnableUpdate(void)
|
||||
{
|
||||
uint8_t u8Cs1 = WDOG->CS1;
|
||||
uint8_t u8Cs2 = WDOG->CS2;
|
||||
uint16_t u16TOVAL = WDOG->TOVAL;
|
||||
uint16_t u16WIN = WDOG->WIN;
|
||||
|
||||
u8Cs1 &= ~WDOG_CS1_EN_MASK;
|
||||
u8Cs1 |= WDOG_CS1_UPDATE_MASK;
|
||||
|
||||
|
||||
WDOG_Unlock(); //Modify
|
||||
WDOG->CS2 = u8Cs2;
|
||||
WDOG->TOVAL = u16TOVAL;
|
||||
WDOG->WIN = u16WIN;
|
||||
WDOG->CS1 = u8Cs1;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能看门狗定时器.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void WDOG_Enable(void)
|
||||
{
|
||||
uint8_t u8Cs1 = WDOG->CS1;
|
||||
|
||||
u8Cs1 |= WDOG_CS1_EN_MASK;
|
||||
|
||||
/* 首先要解锁unlock看门狗,才可以往寄存器写数据 */
|
||||
WDOG_Unlock();
|
||||
WDOG->CS1 = u8Cs1;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 初始化看门狗.
|
||||
*
|
||||
* @param[in] pConfig 配置看门狗的结构体.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @warning make sure that WDOG is not initialized after reset or WDOG update is enabled
|
||||
* after reset by calling WDOG_EnableUpdate / WDOG_DisableWDOGEnableUpdate.
|
||||
*
|
||||
* @see WDOG_EnableUpdate, WDOG_DisableWDOGEnableUpdate
|
||||
*
|
||||
*************************************************************************/
|
||||
void WDOG_Init(WDOG_ConfigPtr pConfig)
|
||||
{
|
||||
uint8_t u8Cs1;
|
||||
uint8_t u8Cs2;
|
||||
uint16_t u16Toval;
|
||||
uint16_t u16Win;
|
||||
|
||||
u8Cs1 = 0x80; /* CS1寄存器的默认值 */
|
||||
u8Cs2 = 0;
|
||||
u16Toval = pConfig->u16ETMeOut;
|
||||
u16Win = pConfig->u16WinETMe;
|
||||
|
||||
if(pConfig->sBits.bDisable)
|
||||
{
|
||||
u8Cs1 &= ~WDOG_CS1_EN_MASK;
|
||||
}
|
||||
if(pConfig->sBits.bIntEnable)
|
||||
{
|
||||
u8Cs1 |= WDOG_CS1_INT_MASK;
|
||||
}
|
||||
if(pConfig->sBits.bStopEnable)
|
||||
{
|
||||
u8Cs1 |= WDOG_CS1_STOP_MASK;
|
||||
}
|
||||
if(pConfig->sBits.bDbgEnable)
|
||||
{
|
||||
u8Cs1 |= WDOG_CS1_DBG_MASK;
|
||||
}
|
||||
if(pConfig->sBits.bWaitEnable)
|
||||
{
|
||||
u8Cs1 |= WDOG_CS1_WAIT_MASK;
|
||||
}
|
||||
if(pConfig->sBits.bUpdateEnable)
|
||||
{
|
||||
u8Cs1 |= WDOG_CS1_UPDATE_MASK;
|
||||
}
|
||||
if(pConfig->sBits.bWinEnable)
|
||||
{
|
||||
u8Cs2 |= WDOG_CS2_WIN_MASK;
|
||||
}
|
||||
if(pConfig->sBits.bPrescaler)
|
||||
{
|
||||
u8Cs2 |= WDOG_CS2_PRES_MASK;
|
||||
}
|
||||
u8Cs2 |= (pConfig->sBits.bClkSrc & 0x03);
|
||||
|
||||
/* 首先要解锁unlock看门狗,才可以往寄存器写数据 */
|
||||
WDOG_Unlock();
|
||||
WDOG->CS2 = u8Cs2;
|
||||
|
||||
WDOG->TOVAL8B.TOVALL = u16Toval;
|
||||
WDOG->TOVAL8B.TOVALH = u16Toval >> 8;
|
||||
|
||||
WDOG->WIN8B.WINL = u16Win;
|
||||
WDOG->WIN8B.WINH = u16Win >> 8;
|
||||
|
||||
WDOG->CS1 = u8Cs1;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 复位看门狗.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void WDOG_DeInit(void)
|
||||
{
|
||||
WDOG_Unlock();
|
||||
|
||||
WDOG->CS2 = WDOG_CS2_DEFAULT_VALUE;
|
||||
WDOG->TOVAL = WDOG_TOVAL_DEFAULT_VALUE;
|
||||
WDOG->WIN = WDOG_WIN_DEFAULT_VALUE;
|
||||
WDOG->CS1 = WDOG_CS1_DEFAULT_VALUE;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 喂狗-刷新看门狗.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void WDOG_Feed(void)
|
||||
{
|
||||
//在喂狗期间,总中断需要关闭
|
||||
DisableInterrupts;
|
||||
WDOG->CNT = 0x02A6;//喂狗的两条指令,必须跟随在128个总线时钟周期内执行
|
||||
WDOG->CNT = 0x80B4;
|
||||
EnableInterrupts;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 使能更新看门狗.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void WDOG_EnableUpdate(void)
|
||||
{
|
||||
uint8_t u8Cs1 = WDOG->CS1;
|
||||
uint8_t u8Cs2 = WDOG->CS2;
|
||||
uint16_t u16TOVAL = WDOG->TOVAL;
|
||||
uint16_t u16WIN = WDOG->WIN;
|
||||
|
||||
u8Cs1 |= WDOG_CS1_UPDATE_MASK;
|
||||
|
||||
/* 首先要解锁unlock看门狗,才可以往寄存器写数据 */
|
||||
WDOG_Unlock();
|
||||
WDOG->CS2 = u8Cs2;
|
||||
WDOG->TOVAL = u16TOVAL;
|
||||
WDOG->WIN = u16WIN;
|
||||
WDOG->CS1 = u8Cs1;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 禁用更新看门狗.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
void WDOG_DisableUpdate(void)
|
||||
{
|
||||
uint8_t u8Cs1 = WDOG->CS1;
|
||||
uint8_t u8Cs2 = WDOG->CS2;
|
||||
uint16_t u16TOVAL = WDOG->TOVAL;
|
||||
uint16_t u16WIN = WDOG->WIN;
|
||||
|
||||
u8Cs1 &= ~WDOG_CS1_UPDATE_MASK;
|
||||
|
||||
/* 首先要解锁unlock看门狗,才可以往寄存器写数据 */
|
||||
WDOG_Unlock();
|
||||
WDOG->CS2 = u8Cs2;
|
||||
WDOG->TOVAL = u16TOVAL;
|
||||
WDOG->WIN = u16WIN;
|
||||
WDOG->CS1 = u8Cs1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
/*! @} */
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @brief WDG 驱动头文件.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __WDOG_H__
|
||||
#define __WDOG_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
#include "sim.h"
|
||||
/*****************************************************************************/
|
||||
/******************************************************************************
|
||||
* 定义WDG时钟源
|
||||
*
|
||||
*//*! @WDG时钟源
|
||||
* @{
|
||||
*******************************************************************************/
|
||||
|
||||
#define WDOG_CLK_BUS 0 /*!< 总线时钟 */
|
||||
#define WDOG_CLK_INTERNAL_32KHZ 2 /*!< 内部 32 kHz (ICSIRCLK) */
|
||||
#define WDOG_CLK_INTERNAL_1KHZ 1 /*!< 内部 LPO 1 KHz */
|
||||
#define WDOG_CLK_EXTERNAL 3 /*!< 外部时钟 */
|
||||
/*! @} */
|
||||
|
||||
/* 看门狗时钟源选择 */
|
||||
#define WDOG_CLK (WDOG_CLK_INTERNAL_1KHZ)
|
||||
|
||||
/* 看门狗寄存器默认值设置 */
|
||||
#define WDOG_CS1_DEFAULT_VALUE 0x80
|
||||
#define WDOG_CS2_DEFAULT_VALUE 0x01
|
||||
#define WDOG_TOVAL_DEFAULT_VALUE 0x0400
|
||||
#define WDOG_WIN_DEFAULT_VALUE 0x0000
|
||||
|
||||
|
||||
/*!
|
||||
* @brief 看门狗解锁.
|
||||
*/
|
||||
#define WDOG_Unlock() DisableInterrupts; WDOG->CNT = 0x20C5; WDOG->CNT = 0x28D9; EnableInterrupts //Modify
|
||||
/*! @} */
|
||||
|
||||
/******************************************************************************
|
||||
* define 看门狗配置结构体
|
||||
*
|
||||
*//*! @看门狗配置结构体
|
||||
* @{
|
||||
*******************************************************************************/
|
||||
typedef struct {
|
||||
struct {
|
||||
uint16_t bIntEnable : 1; /*!< 看门狗中断使能 */
|
||||
uint16_t bDisable : 1; /*!< 禁用看门狗 */
|
||||
uint16_t bWaitEnable : 1; /*!< 使能看门狗等待模式 */
|
||||
uint16_t bStopEnable : 1; /*!< 使能看门狗停止模式 */
|
||||
uint16_t bDbgEnable : 1; /*!< 使能看门狗调试模式 */
|
||||
uint16_t bWinEnable : 1; /*!< 使能看门狗窗口模式 */
|
||||
uint16_t bUpdateEnable : 1; /*!< 使能允许看门狗更新 */
|
||||
uint16_t bClkSrc : 2; /*!< 看门狗时钟源选择 */
|
||||
uint16_t bPrescaler : 1; /*!< 预分频系数 */
|
||||
}sBits; /*!< 位域结构体 */
|
||||
uint16_t u16ETMeOut; /*!< 看门狗超时值 */
|
||||
uint16_t u16WinETMe; /*!< 看门狗窗口值 */
|
||||
} WDOG_ConfigType, *WDOG_ConfigPtr; /*!< 看门狗配置结构体类型 */
|
||||
/*! @} */
|
||||
|
||||
/******************************************************************************
|
||||
******************************************************************************/
|
||||
|
||||
/*!
|
||||
* 内联函数
|
||||
*/
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置看门狗超时值.
|
||||
*
|
||||
* @param[in] u16ETMeOut 超时值.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
__STATIC_INLINE void WDOG_SetETMeOut(uint16_t u16ETMeOut)
|
||||
{
|
||||
WDOG->CNT = 0x20C5;
|
||||
WDOG->CNT = 0x28D9;
|
||||
WDOG->TOVAL8B.TOVALL = u16ETMeOut;
|
||||
WDOG->TOVAL8B.TOVALH = u16ETMeOut >> 8;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 设置看门狗窗口.
|
||||
*
|
||||
* @param[in] u16WinETMe 看门狗窗口值.
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
__STATIC_INLINE void WDOG_SetWindow(uint16_t u16WinETMe)
|
||||
{
|
||||
WDOG->CNT = 0x20C5;
|
||||
WDOG->CNT = 0x28D9;
|
||||
WDOG->WIN8B.WINL = u16WinETMe;
|
||||
WDOG->WIN8B.WINH = u16WinETMe >> 8;
|
||||
}
|
||||
|
||||
/*****************************************************************************//*!
|
||||
*
|
||||
* @brief 检查看门狗是否复位.
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @return TRUE 当看门狗复位发生, FALSE 无.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
__STATIC_INLINE uint8_t WDOG_IsReset(void)
|
||||
{
|
||||
if(SIM_GetStatus(SIM_SRSID_WDOG_MASK))
|
||||
{
|
||||
return (TRUE);
|
||||
}
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/*! @} */
|
||||
|
||||
|
||||
void WDOG_Init(WDOG_ConfigPtr pConfig);
|
||||
void WDOG_DeInit(void);
|
||||
void WDOG_Disable(void);
|
||||
void WDOG_DisableWDOGEnableUpdate(void);
|
||||
void WDOG_Enable(void);
|
||||
void WDOG_Feed(void);
|
||||
void WDOG_SetETMeOut(uint16_t u16ETMeOut);
|
||||
void WDOG_SetWindow(uint16_t u16WinETMe);
|
||||
void WDOG_EnableUpdate(void);
|
||||
void WDOG_DisableUpdate(void);
|
||||
uint8_t WDOG_IsReset(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/********************************************************************/
|
||||
#endif /* __WDOG_H__ */
|
||||
|
||||
Reference in New Issue
Block a user