twi.c
上传用户:jnhtjd
上传日期:2022-07-16
资源大小:403k
文件大小:14k
源码类别:

微处理器开发

开发平台:

C/C++

  1. /* ----------------------------------------------------------------------------
  2.  *         ATMEL Microcontroller Software Support
  3.  * ----------------------------------------------------------------------------
  4.  * Copyright (c) 2008, Atmel Corporation
  5.  *
  6.  * All rights reserved.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions are met:
  10.  *
  11.  * - Redistributions of source code must retain the above copyright notice,
  12.  * this list of conditions and the disclaimer below.
  13.  *
  14.  * Atmel's name may not be used to endorse or promote products derived from
  15.  * this software without specific prior written permission.
  16.  *
  17.  * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  19.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
  20.  * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  22.  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
  23.  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  24.  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  25.  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  26.  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  * ----------------------------------------------------------------------------
  28.  */
  29. //------------------------------------------------------------------------------
  30. /// unit
  31. ///
  32. /// !Purpose
  33. ///
  34. /// Interface for configuration the Two Wire Interface (TWI) peripheral.
  35. ///
  36. /// !Usage
  37. ///
  38. /// -# Configures a TWI peripheral to operate in master mode, at the given
  39. /// frequency (in Hz) using TWI_Configure().
  40. /// -# Sends a STOP condition on the TWI using TWI_Stop().
  41. /// -# Starts a read operation on the TWI bus with the specified slave using
  42. /// TWI_StartRead(). Data must then be read using TWI_ReadByte() whenever
  43. /// a byte is available (poll using TWI_ByteReceived()).
  44. /// -# Starts a write operation on the TWI to access the selected slave using
  45. /// TWI_StartWrite(). A byte of data must be provided to start the write;
  46. /// other bytes are written next.
  47. /// -# Sends a byte of data to one of the TWI slaves on the bus using TWI_WriteByte().
  48. /// This function must be called once before TWI_StartWrite() with the first byte of data
  49. /// to send, then it shall be called repeatedly after that to send the remaining bytes.
  50. /// -# Check if a byte has been received and can be read on the given TWI
  51. /// peripheral using TWI_ByteReceived().
  52. /// Check if a byte has been sent using TWI_ByteSent().
  53. /// -# Check if the current transmission is complete (the STOP has been sent)
  54. /// using TWI_TransferComplete().
  55. /// -# Enables & disable the selected interrupts sources on a TWI peripheral
  56. /// using TWI_EnableIt() and TWI_DisableIt().
  57. /// -# Get current status register of the given TWI peripheral using
  58. /// TWI_GetStatus(). Get current status register of the given TWI peripheral, but
  59. /// masking interrupt sources which are not currently enabled using
  60. /// TWI_GetMaskedStatus().
  61. //------------------------------------------------------------------------------
  62. //------------------------------------------------------------------------------
  63. //         Headers
  64. //------------------------------------------------------------------------------
  65. #include "twi.h"
  66. #include <utility/math.h>
  67. #include <utility/assert.h>
  68. #include <utility/trace.h>
  69. //------------------------------------------------------------------------------
  70. //         Global functions
  71. //------------------------------------------------------------------------------
  72. //------------------------------------------------------------------------------
  73. /// Configures a TWI peripheral to operate in master mode, at the given
  74. /// frequency (in Hz). The duty cycle of the TWI clock is set to 50%.
  75. /// param pTwi  Pointer to an AT91S_TWI instance.
  76. /// param twck  Desired TWI clock frequency.
  77. /// param mck  Master clock frequency.
  78. //------------------------------------------------------------------------------
  79. void TWI_ConfigureMaster(AT91S_TWI *pTwi, unsigned int twck, unsigned int mck)
  80. {
  81.     unsigned int ckdiv = 0;
  82.     unsigned int cldiv;
  83.     unsigned char ok = 0;
  84.     TRACE_DEBUG("TWI_ConfigureMaster()nr");
  85.     SANITY_CHECK(pTwi);
  86. #ifdef AT91C_TWI_SVEN  // TWI slave
  87.     // SVEN: TWI Slave Mode Enabled
  88.     pTwi->TWI_CR = AT91C_TWI_SVEN;
  89. #endif
  90.     // Reset the TWI
  91.     pTwi->TWI_CR = AT91C_TWI_SWRST;
  92.     pTwi->TWI_RHR;
  93.     // TWI Slave Mode Disabled, TWI Master Mode Disabled
  94. #ifdef AT91C_TWI_SVEN  // TWI slave
  95.     pTwi->TWI_CR = AT91C_TWI_SVDIS;
  96. #endif
  97.     pTwi->TWI_CR = AT91C_TWI_MSDIS;
  98.     // Set master mode
  99.     pTwi->TWI_CR = AT91C_TWI_MSEN;
  100.     // Configure clock
  101.     while (!ok) {
  102. #if defined(__ARMCC_VERSION)
  103.         cldiv = ((mck / (2 * twck)) - 3) / pow(2, ckdiv);
  104. #else
  105.         cldiv = ((mck / (2 * twck)) - 3) / power(2, ckdiv);
  106. #endif        
  107.         if (cldiv <= 255) {
  108.             ok = 1;
  109.         }
  110.         else {
  111.             ckdiv++;
  112.         }
  113.     }
  114.     ASSERT(ckdiv < 8, "-F- Cannot find valid TWI clock parametersnr");
  115.     TRACE_DEBUG("Using CKDIV = %u and CLDIV/CHDIV = %unr", ckdiv, cldiv);
  116.     pTwi->TWI_CWGR = 0;
  117.     pTwi->TWI_CWGR = (ckdiv << 16) | (cldiv << 8) | cldiv;
  118. }
  119. #ifdef AT91C_TWI_SVEN  // TWI slave
  120. //------------------------------------------------------------------------------
  121. /// Configures a TWI peripheral to operate in slave mode
  122. /// param pTwi  Pointer to an AT91S_TWI instance.
  123. //------------------------------------------------------------------------------
  124. void TWI_ConfigureSlave(AT91S_TWI *pTwi, unsigned char slaveAddress)
  125. {
  126.     unsigned int i;
  127.     // TWI software reset
  128.     pTwi->TWI_CR = AT91C_TWI_SWRST;
  129.     pTwi->TWI_RHR;
  130.     // Wait at least 10 ms
  131.     for (i=0; i < 1000000; i++);
  132.     // TWI Slave Mode Disabled, TWI Master Mode Disabled
  133.     pTwi->TWI_CR = AT91C_TWI_SVDIS | AT91C_TWI_MSDIS;
  134.     // Slave Address
  135.     pTwi->TWI_SMR = 0;
  136.     pTwi->TWI_SMR = (slaveAddress << 16) & AT91C_TWI_SADR;
  137.     // SVEN: TWI Slave Mode Enabled
  138.     pTwi->TWI_CR = AT91C_TWI_SVEN;
  139.     // Wait at least 10 ms
  140.     for (i=0; i < 1000000; i++);
  141.     ASSERT( (pTwi->TWI_CR & AT91C_TWI_SVDIS)!=AT91C_TWI_SVDIS, "Problem slave mode");
  142. }
  143. #endif
  144. //------------------------------------------------------------------------------
  145. /// Sends a STOP condition on the TWI.
  146. /// param pTwi  Pointer to an AT91S_TWI instance.
  147. //------------------------------------------------------------------------------
  148. void TWI_Stop(AT91S_TWI *pTwi)
  149. {
  150.     SANITY_CHECK(pTwi);
  151.     pTwi->TWI_CR = AT91C_TWI_STOP;
  152. }
  153. //------------------------------------------------------------------------------
  154. /// Starts a read operation on the TWI bus with the specified slave, and returns
  155. /// immediately. Data must then be read using TWI_ReadByte() whenever a byte is
  156. /// available (poll using TWI_ByteReceived()).
  157. /// param pTwi  Pointer to an AT91S_TWI instance.
  158. /// param address  Slave address on the bus.
  159. /// param iaddress  Optional internal address bytes.
  160. /// param isize  Number of internal address bytes.
  161. //-----------------------------------------------------------------------------
  162. void TWI_StartRead(
  163.     AT91S_TWI *pTwi,
  164.     unsigned char address,
  165.     unsigned int iaddress,
  166.     unsigned char isize)
  167. {
  168.     //TRACE_DEBUG("TWI_StartRead()nr");
  169.     SANITY_CHECK(pTwi);
  170.     SANITY_CHECK((address & 0x80) == 0);
  171.     SANITY_CHECK((iaddress & 0xFF000000) == 0);
  172.     SANITY_CHECK(isize < 4);
  173.     // Set slave address and number of internal address bytes
  174.     pTwi->TWI_MMR = 0;
  175.     pTwi->TWI_MMR = (isize << 8) | AT91C_TWI_MREAD | (address << 16);
  176.     // Set internal address bytes
  177.     pTwi->TWI_IADR = 0;
  178.     pTwi->TWI_IADR = iaddress;
  179.     // Send START condition
  180.     pTwi->TWI_CR = AT91C_TWI_START;
  181. }
  182. //-----------------------------------------------------------------------------
  183. /// Reads a byte from the TWI bus. The read operation must have been started
  184. /// using TWI_StartRead() and a byte must be available (check with
  185. /// TWI_ByteReceived()).
  186. /// Returns the byte read.
  187. /// param pTwi  Pointer to an AT91S_TWI instance.
  188. //-----------------------------------------------------------------------------
  189. unsigned char TWI_ReadByte(AT91S_TWI *pTwi)
  190. {
  191.     SANITY_CHECK(pTwi);
  192.     return pTwi->TWI_RHR;
  193. }
  194. //-----------------------------------------------------------------------------
  195. /// Sends a byte of data to one of the TWI slaves on the bus. This function
  196. /// must be called once before TWI_StartWrite() with the first byte of data
  197. /// to send, then it shall be called repeatedly after that to send the
  198. /// remaining bytes.
  199. /// param pTwi  Pointer to an AT91S_TWI instance.
  200. /// param byte  Byte to send.
  201. //-----------------------------------------------------------------------------
  202. void TWI_WriteByte(AT91S_TWI *pTwi, unsigned char byte)
  203. {
  204.     SANITY_CHECK(pTwi);
  205.     pTwi->TWI_THR = byte;
  206. }
  207. //-----------------------------------------------------------------------------
  208. /// Starts a write operation on the TWI to access the selected slave, then
  209. /// returns immediately. A byte of data must be provided to start the write;
  210. /// other bytes are written next.
  211. /// param pTwi  Pointer to an AT91S_TWI instance.
  212. /// param address  Address of slave to acccess on the bus.
  213. /// param iaddress  Optional slave internal address.
  214. /// param isize  Number of internal address bytes.
  215. /// param byte  First byte to send.
  216. //-----------------------------------------------------------------------------
  217. void TWI_StartWrite(
  218.     AT91S_TWI *pTwi,
  219.     unsigned char address,
  220.     unsigned int iaddress,
  221.     unsigned char isize,
  222.     unsigned char byte)
  223. {
  224.     //TRACE_DEBUG("TWI_StartWrite()nr");
  225.     SANITY_CHECK(pTwi);
  226.     SANITY_CHECK((address & 0x80) == 0);
  227.     SANITY_CHECK((iaddress & 0xFF000000) == 0);
  228.     SANITY_CHECK(isize < 4);
  229.     // Set slave address and number of internal address bytes
  230.     pTwi->TWI_MMR = 0;
  231.     pTwi->TWI_MMR = (isize << 8) | (address << 16);
  232.     // Set internal address bytes
  233.     pTwi->TWI_IADR = 0;
  234.     pTwi->TWI_IADR = iaddress;
  235.     // Write first byte to send
  236.     TWI_WriteByte(pTwi, byte);
  237. }
  238. //-----------------------------------------------------------------------------
  239. /// Returns 1 if a byte has been received and can be read on the given TWI
  240. /// peripheral; otherwise, returns 0. This function resets the status register
  241. /// of the TWI.
  242. /// param pTwi  Pointer to an AT91S_TWI instance.
  243. //-----------------------------------------------------------------------------
  244. unsigned char TWI_ByteReceived(AT91S_TWI *pTwi)
  245. {
  246.     return ((pTwi->TWI_SR & AT91C_TWI_RXRDY) == AT91C_TWI_RXRDY);
  247. }
  248. //-----------------------------------------------------------------------------
  249. /// Returns 1 if a byte has been sent, so another one can be stored for
  250. /// transmission; otherwise returns 0. This function clears the status register
  251. /// of the TWI.
  252. /// param pTwi  Pointer to an AT91S_TWI instance.
  253. //-----------------------------------------------------------------------------
  254. unsigned char TWI_ByteSent(AT91S_TWI *pTwi)
  255. {
  256.     return ((pTwi->TWI_SR & AT91C_TWI_TXRDY) == AT91C_TWI_TXRDY);
  257. }
  258. //-----------------------------------------------------------------------------
  259. /// Returns 1 if the current transmission is complete (the STOP has been sent);
  260. /// otherwise returns 0.
  261. /// param pTwi  Pointer to an AT91S_TWI instance.
  262. //-----------------------------------------------------------------------------
  263. unsigned char TWI_TransferComplete(AT91S_TWI *pTwi)
  264. {
  265.     return ((pTwi->TWI_SR & AT91C_TWI_TXCOMP) == AT91C_TWI_TXCOMP);
  266. }
  267. //-----------------------------------------------------------------------------
  268. /// Enables the selected interrupts sources on a TWI peripheral.
  269. /// param pTwi  Pointer to an AT91S_TWI instance.
  270. /// param sources  Bitwise OR of selected interrupt sources.
  271. //-----------------------------------------------------------------------------
  272. void TWI_EnableIt(AT91S_TWI *pTwi, unsigned int sources)
  273. {
  274.     SANITY_CHECK(pTwi);
  275.     SANITY_CHECK((sources & 0xFFFFF088) == 0);
  276.     pTwi->TWI_IER = sources;
  277. }
  278. //-----------------------------------------------------------------------------
  279. /// Disables the selected interrupts sources on a TWI peripheral.
  280. /// param pTwi  Pointer to an AT91S_TWI instance.
  281. /// param sources  Bitwise OR of selected interrupt sources.
  282. //-----------------------------------------------------------------------------
  283. void TWI_DisableIt(AT91S_TWI *pTwi, unsigned int sources)
  284. {
  285.     SANITY_CHECK(pTwi);
  286.     SANITY_CHECK((sources & 0xFFFFF088) == 0);
  287.     pTwi->TWI_IDR = sources;
  288. }
  289. //-----------------------------------------------------------------------------
  290. /// Returns the current status register of the given TWI peripheral. This
  291. /// resets the internal value of the status register, so further read may yield
  292. /// different values.
  293. /// param pTwi  Pointer to an AT91S_TWI instance.
  294. //-----------------------------------------------------------------------------
  295. unsigned int TWI_GetStatus(AT91S_TWI *pTwi)
  296. {
  297.     SANITY_CHECK(pTwi);
  298.     return pTwi->TWI_SR;
  299. }
  300. //-----------------------------------------------------------------------------
  301. /// Returns the current status register of the given TWI peripheral, but
  302. /// masking interrupt sources which are not currently enabled.
  303. /// This resets the internal value of the status register, so further read may
  304. /// yield different values.
  305. /// param pTwi  Pointer to an AT91S_TWI instance.
  306. //-----------------------------------------------------------------------------
  307. unsigned int TWI_GetMaskedStatus(AT91S_TWI *pTwi)
  308. {
  309.     unsigned int status;
  310.     SANITY_CHECK(pTwi);
  311.     status = pTwi->TWI_SR;
  312.     status &= pTwi->TWI_IMR;
  313.     return status;
  314. }
  315. //-----------------------------------------------------------------------------
  316. /// Sends a STOP condition. STOP Condition is sent just after completing
  317. /// the current byte transmission in master read mode.
  318. /// param pTwi  Pointer to an AT91S_TWI instance.
  319. //-----------------------------------------------------------------------------
  320. void TWI_SendSTOPCondition(AT91S_TWI *pTwi)
  321. {
  322.     SANITY_CHECK(pTwi);
  323.     pTwi->TWI_CR |= AT91C_TWI_STOP;
  324. }