qei.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619
  1. //*****************************************************************************
  2. //
  3. // qei.c - Driver for the Quadrature Encoder with Index.
  4. //
  5. // Copyright (c) 2005-2009 Luminary Micro, Inc. All rights reserved.
  6. // Software License Agreement
  7. //
  8. // Luminary Micro, Inc. (LMI) is supplying this software for use solely and
  9. // exclusively on LMI's microcontroller products.
  10. //
  11. // The software is owned by LMI and/or its suppliers, and is protected under
  12. // applicable copyright laws. All rights are reserved. You may not combine
  13. // this software with "viral" open-source software in order to form a larger
  14. // program. Any use in violation of the foregoing restrictions may subject
  15. // the user to criminal sanctions under applicable laws, as well as to civil
  16. // liability for the breach of the terms and conditions of this license.
  17. //
  18. // THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
  19. // OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
  20. // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
  21. // LMI SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
  22. // CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
  23. //
  24. // This is part of revision 4694 of the Stellaris Peripheral Driver Library.
  25. //
  26. //*****************************************************************************
  27. //*****************************************************************************
  28. //
  29. //! \addtogroup qei_api
  30. //! @{
  31. //
  32. //*****************************************************************************
  33. #include "inc/hw_ints.h"
  34. #include "inc/hw_memmap.h"
  35. #include "inc/hw_qei.h"
  36. #include "inc/hw_types.h"
  37. #include "driverlib/debug.h"
  38. #include "driverlib/interrupt.h"
  39. #include "driverlib/qei.h"
  40. //*****************************************************************************
  41. //
  42. //! Enables the quadrature encoder.
  43. //!
  44. //! \param ulBase is the base address of the quadrature encoder module.
  45. //!
  46. //! This will enable operation of the quadrature encoder module. It must be
  47. //! configured before it is enabled.
  48. //!
  49. //! \sa QEIConfigure()
  50. //!
  51. //! \return None.
  52. //
  53. //*****************************************************************************
  54. void
  55. QEIEnable(unsigned long ulBase)
  56. {
  57. //
  58. // Check the arguments.
  59. //
  60. ASSERT((ulBase == QEI0_BASE) || (ulBase == QEI1_BASE));
  61. //
  62. // Enable the QEI module.
  63. //
  64. HWREG(ulBase + QEI_O_CTL) |= QEI_CTL_ENABLE;
  65. }
  66. //*****************************************************************************
  67. //
  68. //! Disables the quadrature encoder.
  69. //!
  70. //! \param ulBase is the base address of the quadrature encoder module.
  71. //!
  72. //! This will disable operation of the quadrature encoder module.
  73. //!
  74. //! \return None.
  75. //
  76. //*****************************************************************************
  77. void
  78. QEIDisable(unsigned long ulBase)
  79. {
  80. //
  81. // Check the arguments.
  82. //
  83. ASSERT((ulBase == QEI0_BASE) || (ulBase == QEI1_BASE));
  84. //
  85. // Disable the QEI module.
  86. //
  87. HWREG(ulBase + QEI_O_CTL) &= ~(QEI_CTL_ENABLE);
  88. }
  89. //*****************************************************************************
  90. //
  91. //! Configures the quadrature encoder.
  92. //!
  93. //! \param ulBase is the base address of the quadrature encoder module.
  94. //! \param ulConfig is the configuration for the quadrature encoder. See below
  95. //! for a description of this parameter.
  96. //! \param ulMaxPosition specifies the maximum position value.
  97. //!
  98. //! This will configure the operation of the quadrature encoder. The
  99. //! \e ulConfig parameter provides the configuration of the encoder and is the
  100. //! logical OR of several values:
  101. //!
  102. //! - \b QEI_CONFIG_CAPTURE_A or \b QEI_CONFIG_CAPTURE_A_B to specify if edges
  103. //! on channel A or on both channels A and B should be counted by the
  104. //! position integrator and velocity accumulator.
  105. //! - \b QEI_CONFIG_NO_RESET or \b QEI_CONFIG_RESET_IDX to specify if the
  106. //! position integrator should be reset when the index pulse is detected.
  107. //! - \b QEI_CONFIG_QUADRATURE or \b QEI_CONFIG_CLOCK_DIR to specify if
  108. //! quadrature signals are being provided on ChA and ChB, or if a direction
  109. //! signal and a clock are being provided instead.
  110. //! - \b QEI_CONFIG_NO_SWAP or \b QEI_CONFIG_SWAP to specify if the signals
  111. //! provided on ChA and ChB should be swapped before being processed.
  112. //!
  113. //! \e ulMaxPosition is the maximum value of the position integrator, and is
  114. //! the value used to reset the position capture when in index reset mode and
  115. //! moving in the reverse (negative) direction.
  116. //!
  117. //! \return None.
  118. //
  119. //*****************************************************************************
  120. void
  121. QEIConfigure(unsigned long ulBase, unsigned long ulConfig,
  122. unsigned long ulMaxPosition)
  123. {
  124. //
  125. // Check the arguments.
  126. //
  127. ASSERT((ulBase == QEI0_BASE) || (ulBase == QEI1_BASE));
  128. //
  129. // Write the new configuration to the hardware.
  130. //
  131. HWREG(ulBase + QEI_O_CTL) = ((HWREG(ulBase + QEI_O_CTL) &
  132. ~(QEI_CTL_CAPMODE | QEI_CTL_RESMODE |
  133. QEI_CTL_SIGMODE | QEI_CTL_SWAP)) |
  134. ulConfig);
  135. //
  136. // Set the maximum position.
  137. //
  138. HWREG(ulBase + QEI_O_MAXPOS) = ulMaxPosition;
  139. }
  140. //*****************************************************************************
  141. //
  142. //! Gets the current encoder position.
  143. //!
  144. //! \param ulBase is the base address of the quadrature encoder module.
  145. //!
  146. //! This returns the current position of the encoder. Depending upon the
  147. //! configuration of the encoder, and the incident of an index pulse, this
  148. //! value may or may not contain the expected data (that is, if in reset on
  149. //! index mode, if an index pulse has not been encountered, the position
  150. //! counter will not be aligned with the index pulse yet).
  151. //!
  152. //! \return The current position of the encoder.
  153. //
  154. //*****************************************************************************
  155. unsigned long
  156. QEIPositionGet(unsigned long ulBase)
  157. {
  158. //
  159. // Check the arguments.
  160. //
  161. ASSERT((ulBase == QEI0_BASE) || (ulBase == QEI1_BASE));
  162. //
  163. // Return the current position counter.
  164. //
  165. return(HWREG(ulBase + QEI_O_POS));
  166. }
  167. //*****************************************************************************
  168. //
  169. //! Sets the current encoder position.
  170. //!
  171. //! \param ulBase is the base address of the quadrature encoder module.
  172. //! \param ulPosition is the new position for the encoder.
  173. //!
  174. //! This sets the current position of the encoder; the encoder position will
  175. //! then be measured relative to this value.
  176. //!
  177. //! \return None.
  178. //
  179. //*****************************************************************************
  180. void
  181. QEIPositionSet(unsigned long ulBase, unsigned long ulPosition)
  182. {
  183. //
  184. // Check the arguments.
  185. //
  186. ASSERT((ulBase == QEI0_BASE) || (ulBase == QEI1_BASE));
  187. //
  188. // Set the position counter.
  189. //
  190. HWREG(ulBase + QEI_O_POS) = ulPosition;
  191. }
  192. //*****************************************************************************
  193. //
  194. //! Gets the current direction of rotation.
  195. //!
  196. //! \param ulBase is the base address of the quadrature encoder module.
  197. //!
  198. //! This returns the current direction of rotation. In this case, current
  199. //! means the most recently detected direction of the encoder; it may not be
  200. //! presently moving but this is the direction it last moved before it stopped.
  201. //!
  202. //! \return Returns 1 if moving in the forward direction or -1 if moving in the
  203. //! reverse direction.
  204. //
  205. //*****************************************************************************
  206. long
  207. QEIDirectionGet(unsigned long ulBase)
  208. {
  209. //
  210. // Check the arguments.
  211. //
  212. ASSERT((ulBase == QEI0_BASE) || (ulBase == QEI1_BASE));
  213. //
  214. // Return the direction of rotation.
  215. //
  216. return((HWREG(ulBase + QEI_O_STAT) & QEI_STAT_DIRECTION) ? -1 : 1);
  217. }
  218. //*****************************************************************************
  219. //
  220. //! Gets the encoder error indicator.
  221. //!
  222. //! \param ulBase is the base address of the quadrature encoder module.
  223. //!
  224. //! This returns the error indicator for the quadrature encoder. It is an
  225. //! error for both of the signals of the quadrature input to change at the same
  226. //! time.
  227. //!
  228. //! \return Returns \b true if an error has occurred and \b false otherwise.
  229. //
  230. //*****************************************************************************
  231. tBoolean
  232. QEIErrorGet(unsigned long ulBase)
  233. {
  234. //
  235. // Check the arguments.
  236. //
  237. ASSERT((ulBase == QEI0_BASE) || (ulBase == QEI1_BASE));
  238. //
  239. // Return the error indicator.
  240. //
  241. return((HWREG(ulBase + QEI_O_STAT) & QEI_STAT_ERROR) ? true : false);
  242. }
  243. //*****************************************************************************
  244. //
  245. //! Enables the velocity capture.
  246. //!
  247. //! \param ulBase is the base address of the quadrature encoder module.
  248. //!
  249. //! This will enable operation of the velocity capture in the quadrature
  250. //! encoder module. It must be configured before it is enabled. Velocity
  251. //! capture will not occur if the quadrature encoder is not enabled.
  252. //!
  253. //! \sa QEIVelocityConfigure() and QEIEnable()
  254. //!
  255. //! \return None.
  256. //
  257. //*****************************************************************************
  258. void
  259. QEIVelocityEnable(unsigned long ulBase)
  260. {
  261. //
  262. // Check the arguments.
  263. //
  264. ASSERT((ulBase == QEI0_BASE) || (ulBase == QEI1_BASE));
  265. //
  266. // Enable the velocity capture.
  267. //
  268. HWREG(ulBase + QEI_O_CTL) |= QEI_CTL_VELEN;
  269. }
  270. //*****************************************************************************
  271. //
  272. //! Disables the velocity capture.
  273. //!
  274. //! \param ulBase is the base address of the quadrature encoder module.
  275. //!
  276. //! This will disable operation of the velocity capture in the quadrature
  277. //! encoder module.
  278. //!
  279. //! \return None.
  280. //
  281. //*****************************************************************************
  282. void
  283. QEIVelocityDisable(unsigned long ulBase)
  284. {
  285. //
  286. // Check the arguments.
  287. //
  288. ASSERT((ulBase == QEI0_BASE) || (ulBase == QEI1_BASE));
  289. //
  290. // Disable the velocity capture.
  291. //
  292. HWREG(ulBase + QEI_O_CTL) &= ~(QEI_CTL_VELEN);
  293. }
  294. //*****************************************************************************
  295. //
  296. //! Configures the velocity capture.
  297. //!
  298. //! \param ulBase is the base address of the quadrature encoder module.
  299. //! \param ulPreDiv specifies the predivider applied to the input quadrature
  300. //! signal before it is counted; can be one of \b QEI_VELDIV_1,
  301. //! \b QEI_VELDIV_2, \b QEI_VELDIV_4, \b QEI_VELDIV_8, \b QEI_VELDIV_16,
  302. //! \b QEI_VELDIV_32, \b QEI_VELDIV_64, or \b QEI_VELDIV_128.
  303. //! \param ulPeriod specifies the number of clock ticks over which to measure
  304. //! the velocity; must be non-zero.
  305. //!
  306. //! This will configure the operation of the velocity capture portion of the
  307. //! quadrature encoder. The position increment signal is predivided as
  308. //! specified by \e ulPreDiv before being accumulated by the velocity capture.
  309. //! The divided signal is accumulated over \e ulPeriod system clock before
  310. //! being saved and resetting the accumulator.
  311. //!
  312. //! \return None.
  313. //
  314. //*****************************************************************************
  315. void
  316. QEIVelocityConfigure(unsigned long ulBase, unsigned long ulPreDiv,
  317. unsigned long ulPeriod)
  318. {
  319. //
  320. // Check the arguments.
  321. //
  322. ASSERT((ulBase == QEI0_BASE) || (ulBase == QEI1_BASE));
  323. ASSERT(!(ulPreDiv & ~(QEI_CTL_VELDIV_M)));
  324. ASSERT(ulPeriod != 0);
  325. //
  326. // Set the velocity predivider.
  327. //
  328. HWREG(ulBase + QEI_O_CTL) = ((HWREG(ulBase + QEI_O_CTL) &
  329. ~(QEI_CTL_VELDIV_M)) | ulPreDiv);
  330. //
  331. // Set the timer period.
  332. //
  333. HWREG(ulBase + QEI_O_LOAD) = ulPeriod - 1;
  334. }
  335. //*****************************************************************************
  336. //
  337. //! Gets the current encoder speed.
  338. //!
  339. //! \param ulBase is the base address of the quadrature encoder module.
  340. //!
  341. //! This returns the current speed of the encoder. The value returned is the
  342. //! number of pulses detected in the specified time period; this number can be
  343. //! multiplied by the number of time periods per second and divided by the
  344. //! number of pulses per revolution to obtain the number of revolutions per
  345. //! second.
  346. //!
  347. //! \return Returns the number of pulses captured in the given time period.
  348. //
  349. //*****************************************************************************
  350. unsigned long
  351. QEIVelocityGet(unsigned long ulBase)
  352. {
  353. //
  354. // Check the arguments.
  355. //
  356. ASSERT((ulBase == QEI0_BASE) || (ulBase == QEI1_BASE));
  357. //
  358. // Return the speed capture value.
  359. //
  360. return(HWREG(ulBase + QEI_O_SPEED));
  361. }
  362. //*****************************************************************************
  363. //
  364. //! Registers an interrupt handler for the quadrature encoder interrupt.
  365. //!
  366. //! \param ulBase is the base address of the quadrature encoder module.
  367. //! \param pfnHandler is a pointer to the function to be called when the
  368. //! quadrature encoder interrupt occurs.
  369. //!
  370. //! This sets the handler to be called when a quadrature encoder interrupt
  371. //! occurs. This will enable the global interrupt in the interrupt controller;
  372. //! specific quadrature encoder interrupts must be enabled via QEIIntEnable().
  373. //! It is the interrupt handler's responsibility to clear the interrupt source
  374. //! via QEIIntClear().
  375. //!
  376. //! \sa IntRegister() for important information about registering interrupt
  377. //! handlers.
  378. //!
  379. //! \return None.
  380. //
  381. //*****************************************************************************
  382. void
  383. QEIIntRegister(unsigned long ulBase, void (*pfnHandler)(void))
  384. {
  385. unsigned long ulInt;
  386. //
  387. // Check the arguments.
  388. //
  389. ASSERT((ulBase == QEI0_BASE) || (ulBase == QEI1_BASE));
  390. //
  391. // Determine the interrupt number based on the QEI module.
  392. //
  393. ulInt = (ulBase == QEI0_BASE) ? INT_QEI0 : INT_QEI1;
  394. //
  395. // Register the interrupt handler, returning an error if an error occurs.
  396. //
  397. IntRegister(ulInt, pfnHandler);
  398. //
  399. // Enable the quadrature encoder interrupt.
  400. //
  401. IntEnable(ulInt);
  402. }
  403. //*****************************************************************************
  404. //
  405. //! Unregisters an interrupt handler for the quadrature encoder interrupt.
  406. //!
  407. //! \param ulBase is the base address of the quadrature encoder module.
  408. //!
  409. //! This function will clear the handler to be called when a quadrature encoder
  410. //! interrupt occurs. This will also mask off the interrupt in the interrupt
  411. //! controller so that the interrupt handler no longer is called.
  412. //!
  413. //! \sa IntRegister() for important information about registering interrupt
  414. //! handlers.
  415. //!
  416. //! \return None.
  417. //
  418. //*****************************************************************************
  419. void
  420. QEIIntUnregister(unsigned long ulBase)
  421. {
  422. unsigned long ulInt;
  423. //
  424. // Check the arguments.
  425. //
  426. ASSERT((ulBase == QEI0_BASE) || (ulBase == QEI1_BASE));
  427. //
  428. // Determine the interrupt number based on the QEI module.
  429. //
  430. ulInt = (ulBase == QEI0_BASE) ? INT_QEI0 : INT_QEI1;
  431. //
  432. // Disable the interrupt.
  433. //
  434. IntDisable(ulInt);
  435. //
  436. // Unregister the interrupt handler.
  437. //
  438. IntUnregister(ulInt);
  439. }
  440. //*****************************************************************************
  441. //
  442. //! Enables individual quadrature encoder interrupt sources.
  443. //!
  444. //! \param ulBase is the base address of the quadrature encoder module.
  445. //! \param ulIntFlags is a bit mask of the interrupt sources to be enabled.
  446. //! Can be any of the \b QEI_INTERROR, \b QEI_INTDIR, \b QEI_INTTIMER, or
  447. //! \b QEI_INTINDEX values.
  448. //!
  449. //! Enables the indicated quadrature encoder interrupt sources. Only the
  450. //! sources that are enabled can be reflected to the processor interrupt;
  451. //! disabled sources have no effect on the processor.
  452. //!
  453. //! \return None.
  454. //
  455. //*****************************************************************************
  456. void
  457. QEIIntEnable(unsigned long ulBase, unsigned long ulIntFlags)
  458. {
  459. //
  460. // Check the arguments.
  461. //
  462. ASSERT((ulBase == QEI0_BASE) || (ulBase == QEI1_BASE));
  463. //
  464. // Enable the specified interrupts.
  465. //
  466. HWREG(ulBase + QEI_O_INTEN) |= ulIntFlags;
  467. }
  468. //*****************************************************************************
  469. //
  470. //! Disables individual quadrature encoder interrupt sources.
  471. //!
  472. //! \param ulBase is the base address of the quadrature encoder module.
  473. //! \param ulIntFlags is a bit mask of the interrupt sources to be disabled.
  474. //! Can be any of the \b QEI_INTERROR, \b QEI_INTDIR, \b QEI_INTTIMER, or
  475. //! \b QEI_INTINDEX values.
  476. //!
  477. //! Disables the indicated quadrature encoder interrupt sources. Only the
  478. //! sources that are enabled can be reflected to the processor interrupt;
  479. //! disabled sources have no effect on the processor.
  480. //!
  481. //! \return None.
  482. //
  483. //*****************************************************************************
  484. void
  485. QEIIntDisable(unsigned long ulBase, unsigned long ulIntFlags)
  486. {
  487. //
  488. // Check the arguments.
  489. //
  490. ASSERT((ulBase == QEI0_BASE) || (ulBase == QEI1_BASE));
  491. //
  492. // Disable the specified interrupts.
  493. //
  494. HWREG(ulBase + QEI_O_INTEN) &= ~(ulIntFlags);
  495. }
  496. //*****************************************************************************
  497. //
  498. //! Gets the current interrupt status.
  499. //!
  500. //! \param ulBase is the base address of the quadrature encoder module.
  501. //! \param bMasked is false if the raw interrupt status is required and true if
  502. //! the masked interrupt status is required.
  503. //!
  504. //! This returns the interrupt status for the quadrature encoder module.
  505. //! Either the raw interrupt status or the status of interrupts that are
  506. //! allowed to reflect to the processor can be returned.
  507. //!
  508. //! \return Returns the current interrupt status, enumerated as a bit field of
  509. //! \b QEI_INTERROR, \b QEI_INTDIR, \b QEI_INTTIMER, and \b QEI_INTINDEX.
  510. //
  511. //*****************************************************************************
  512. unsigned long
  513. QEIIntStatus(unsigned long ulBase, tBoolean bMasked)
  514. {
  515. //
  516. // Check the arguments.
  517. //
  518. ASSERT((ulBase == QEI0_BASE) || (ulBase == QEI1_BASE));
  519. //
  520. // Return either the interrupt status or the raw interrupt status as
  521. // requested.
  522. //
  523. if(bMasked)
  524. {
  525. return(HWREG(ulBase + QEI_O_ISC));
  526. }
  527. else
  528. {
  529. return(HWREG(ulBase + QEI_O_RIS));
  530. }
  531. }
  532. //*****************************************************************************
  533. //
  534. //! Clears quadrature encoder interrupt sources.
  535. //!
  536. //! \param ulBase is the base address of the quadrature encoder module.
  537. //! \param ulIntFlags is a bit mask of the interrupt sources to be cleared.
  538. //! Can be any of the \b QEI_INTERROR, \b QEI_INTDIR, \b QEI_INTTIMER, or
  539. //! \b QEI_INTINDEX values.
  540. //!
  541. //! The specified quadrature encoder interrupt sources are cleared, so that
  542. //! they no longer assert. This must be done in the interrupt handler to keep
  543. //! it from being called again immediately upon exit.
  544. //!
  545. //! \note Since there is a write buffer in the Cortex-M3 processor, it may take
  546. //! several clock cycles before the interrupt source is actually cleared.
  547. //! Therefore, it is recommended that the interrupt source be cleared early in
  548. //! the interrupt handler (as opposed to the very last action) to avoid
  549. //! returning from the interrupt handler before the interrupt source is
  550. //! actually cleared. Failure to do so may result in the interrupt handler
  551. //! being immediately reentered (since NVIC still sees the interrupt source
  552. //! asserted).
  553. //!
  554. //! \return None.
  555. //
  556. //*****************************************************************************
  557. void
  558. QEIIntClear(unsigned long ulBase, unsigned long ulIntFlags)
  559. {
  560. //
  561. // Check the arguments.
  562. //
  563. ASSERT((ulBase == QEI0_BASE) || (ulBase == QEI1_BASE));
  564. //
  565. // Clear the requested interrupt sources.
  566. //
  567. HWREG(ulBase + QEI_O_ISC) = ulIntFlags;
  568. }
  569. //*****************************************************************************
  570. //
  571. // Close the Doxygen group.
  572. //! @}
  573. //
  574. //*****************************************************************************