qei.c 20 KB

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