[STM32]Implémentation afficheur oled NHD0420CW en I²C

Implémentation afficheur oled NHD0420CW en I²C [STM32] - C - Programmation

Marsh Posté le 09-02-2018 à 12:46:04    

Bonjour,
 
Je dois réaliser un travail ou l'objectif est d'effectuer le comptage de place de parking, et dans ce module je dois implémenter un afficheur permettant d'afficher tel ou tel message.
 
Spécification :
Afficheur oled Alphanumérique :
 
Le module dispose d’un afficheur OLED alphanumérique jaune de quatre lignes de vingt caractères (NHD-0420CW-AY3 de Newhaven Display).
 
Cet afficheur est connecté sur le bus I²C du microcontrôleur (voir documentation pour le protocole de pilotage).
 
Je dois donc piloter cette afficheur en I²C, voici la doc :
 
https://www.newhavendisplay.com/spe [...] CW-AY3.pdf
 
 
Sur mon schéma de l'afficheur (on peut voir que toute les sorties qui ont besoin d'être à la masse pour un fonctionnement en I²C sont bien à la masse).
 
 
On peut également remarquer que BS0 BS1 et BS2 sont configuré de tel manière à ce quel'I²C soit activé :
 
J'ai récupérer le code de la doc et j'ai voulue l'implémenter.
 
Bien évidemment j'utilise des variables non reconnues etc.. J'ai donc demander à mon supérieur la possibilité de récuperer les biblothèques de l'afficheur afin d'appeler les fonctions directement et de m'en servir comme je l'entend, mais voilà il m'a répondu : "tu n'en a pas besoin tu le pilote en I²C", je ne comprend donc pas comment je peut faire pour gérer mon afficheur en I²C ?
 
Je gère l'I²C sur mon µC STM32F10x de cette manière :
 
 

Code :
  1. GPIO_InitTypeDef initStruct;
  2.     GPIO_DeInit(GPIOA);
  3.     GPIO_DeInit(GPIOB);
  4.       ...
  5. // I2C SCL / SDA
  6.     initStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
  7.     initStruct.GPIO_Mode = GPIO_Mode_Out_PP;


      ...
 

Code :
  1. void gpio_i2cIoStopCondition(void)
  2. {
  3.     // B6 -> SCL / B7 -> SDA
  4.     // Stop condition is SDA rising edge while SCL = 1
  5.     GPIO_WriteBit(GPIOB,GPIO_Pin_7, Bit_RESET);
  6.     fnop();
  7.     GPIO_WriteBit(GPIOB,GPIO_Pin_6, Bit_SET);
  8.     fnop();
  9.     GPIO_WriteBit(GPIOB,GPIO_Pin_7, Bit_SET);
  10.     fnop();
  11. }


 
Pensez vous que je dois utiliser les fonctions des bibliothèques I²C ?
 
Je vous avoue être perdue quant à la façon d'aborder cette tâche :/ !
 
 
Il y a également toute la partie I2C codé par mon collège :
 

Code :
  1. /**********************/
  2. /****** includes ******/
  3. /**********************/
  4. #include "i2cMaster.h"
  5. /*******************/
  6. /***** globals *****/
  7. /*******************/
  8. /** @brief Buffer used to store I2C frames */
  9. uint8_t i2cBuffer[I2CM_BUFFER_SIZE];
  10. /** @brief I2C error flag */
  11. uint8_t i2cIsError;
  12. /*********************************/
  13. /****** Function definition ******/
  14. /*********************************/
  15. /**
  16. * @brief Initialize the I2C master
  17. */
  18. void i2cmInit(void)
  19. {
  20.     I2C_InitTypeDef initStruct;
  21.     I2C_DeInit(I2CM_MODULE);
  22.     I2C_StructInit(&initStruct);
  23.     initStruct.I2C_ClockSpeed = 100000;
  24.     I2C_Init(I2CM_MODULE,&initStruct);
  25.     i2cIsError = FALSE;
  26.     I2C_Cmd(I2CM_MODULE,ENABLE);
  27. }
  28. /**
  29. * @brief       Write data on the I2C bus
  30. *
  31. * @param[in]   address     The slave address in the 7 least significants bits
  32. * @param[in]   count       The number of bytes to write
  33. * @param[in]   bufI2C      An byte array containing the data to send
  34. */
  35. uint8_t i2cmWrite(uint8_t address, uint16_t count, uint8_t * bufI2C)
  36. {
  37.     uint32_t temp;
  38.     uint32_t timeout;
  39.     I2C_GenerateSTART(I2CM_MODULE, ENABLE); // Send START condition
  40.     timeout = I2CM_EVENT_TIMEOUT;           // Reset timeout
  41.     // Wait until SB flag is set: EV5
  42.     while ((I2CM_MODULE->SR1&I2C_SR1_SB) != I2C_SR1_SB)
  43.     {
  44.         if (timeout-- == 0)
  45.         {
  46. #ifdef I2C_DEBUG
  47.             debugSendLine("W - Start timeout" );
  48. #endif
  49.             i2cm_fixFailure();
  50.             return FALSE;
  51.         }
  52.     }
  53.     I2C_Send7bitAddress(I2CM_MODULE, address, I2C_Direction_Transmitter); // Send slave address
  54.     timeout = I2CM_EVENT_TIMEOUT;           // Reset timeout
  55.     // Wait until ADDR is set: EV6
  56.     while ((I2CM_MODULE->SR1&I2C_SR1_ADDR) != I2C_SR1_ADDR)
  57.     {
  58.         if (timeout-- == 0)
  59.         {
  60. #ifdef I2C_DEBUG
  61.             debugSendLine("W - ADDR timeout" );
  62. #endif
  63.             i2cm_fixFailure();
  64.             return FALSE;
  65.         }
  66.     }
  67.     temp = I2CM_MODULE->SR2;                 // Clear ADDR flag by reading SR2 register
  68.     I2C_SendData(I2CM_MODULE, *bufI2C);     // Write the first data in DR register (EV8_1)
  69.     bufI2C++;                               // Increment the data
  70.     count--;                                // Decrement the number of bytes to be written
  71.     while (count--)                         // While there is data to be written
  72.     {
  73.         /*
  74.          * Poll on BTF to receive data because in polling mode we can not guarantee the
  75.          * EV8 software sequence is managed before the current byte transfer completes
  76.          */
  77.         i2cm_waitBtfSet();
  78.         I2C_SendData(I2CM_MODULE, *bufI2C); // Send the current byte
  79.         bufI2C++;                           // Point to the next byte to be written
  80.     }
  81.     i2cm_waitBtfSet();// EV8_2: Wait until BTF is set before programming the STOP
  82.     I2C_GenerateSTOP(I2CM_MODULE, ENABLE);  // Send STOP condition
  83.     // Make sure that the STOP bit is cleared by Hardware
  84.     while ((I2CM_MODULE->CR1&I2C_CR1_STOP) == I2C_CR1_STOP)
  85.         ;
  86.     temp++;                                 // For avoid compiler warning
  87.     return TRUE;
  88. }
  89. /**
  90. * @brief       Read data on the I2C bus
  91. *
  92. * @param[in]   address     The slave address in the 7 least significants bits
  93. * @param[in]   count       The number of bytes to read
  94. * @param[out]  bufI2C      An byte array in which store read data
  95. */
  96. uint8_t i2cmRead(uint8_t address, uint16_t count, uint8_t *bufI2C)
  97. {
  98.     uint32_t temp = 0;
  99.     uint32_t timeout = 0;
  100.     // Enable I2C errors interrupts (used in all modes: Polling, DMA and Interrupts
  101.     I2C_ITConfig(I2CM_MODULE, I2C_IT_ERR,ENABLE);
  102.     if (count == 1)
  103.     {
  104.         I2C_GenerateSTART(I2CM_MODULE, ENABLE);     // Send START condition
  105.         timeout = I2CM_EVENT_TIMEOUT;               // Reset timeout
  106.         // Wait until SB flag is set: EV5
  107.         while ((I2CM_MODULE->SR1&0x0001) != 0x0001)
  108.         {
  109.             if (timeout-- == 0)
  110.             {
  111. #ifdef I2C_DEBUG
  112.                 debugSendLine("R-1 - Start timeout" );
  113. #endif
  114.                 i2cm_fixFailure();
  115.                 return FALSE;
  116.             }
  117.         }
  118.         // Send slave address
  119.         I2C_Send7bitAddress(I2CM_MODULE, address, I2C_Direction_Receiver);
  120.         /*
  121.          * Wait until ADDR is set: EV6_3, then program ACK = 0, clear ADDR
  122.          * and program the STOP just after ADDR is cleared. The EV6_3
  123.          * software sequence must complete before the current byte end of transfer.
  124.          */
  125.         timeout = I2CM_EVENT_TIMEOUT;               // Reset timeout
  126.         // Wait until ADDR is set
  127.         while ((I2CM_MODULE->SR1&0x0002) != 0x0002)
  128.         {
  129.             if (timeout-- == 0)
  130.             {
  131. #ifdef I2C_DEBUG
  132.                 debugSendLine("R-1 - ADDR timeout" );
  133. #endif
  134.                 i2cm_fixFailure();
  135.                 return FALSE;
  136.             }
  137.         }
  138.         I2C_AcknowledgeConfig(I2CM_MODULE, DISABLE); // Clear ACK bit
  139.         /*
  140.          * Disable all active IRQs around ADDR clearing and STOP programming because the EV6_3
  141.          * software sequence must complete before the current byte end of transfer
  142.          */
  143.         __disable_irq();
  144.         temp = I2CM_MODULE->SR2;                     // Clear ADDR flag by reading SR2 register
  145.         I2C_GenerateSTOP(I2CM_MODULE, ENABLE);      // Program the STOP
  146.         __enable_irq();                             // Re-enable IRQs
  147.         i2cm_waitRxneSet(); // Wait until a data is received in DR register (RXNE = 1) EV7
  148.         *bufI2C = I2C_ReceiveData(I2CM_MODULE);     // Read the data
  149.         // Make sure that the STOP bit is cleared by Hardware before CR1 write access
  150.         while ((I2CM_MODULE->CR1&0x200) == 0x200)
  151.             ;
  152.     }
  153.     // ------ For send two bytes
  154.     else if (count == 2)
  155.     {
  156.         I2CM_MODULE->CR1 |= CR1_POS_Set;             // Set POS bit
  157.         I2C_GenerateSTART(I2CM_MODULE, ENABLE);     // Send START condition
  158.         timeout = I2CM_EVENT_TIMEOUT;               // Reset timeout
  159.         // Wait until SB flag is set: EV5
  160.         while ((I2CM_MODULE->SR1&0x0001) != 0x0001)
  161.         {
  162.             if( timeout-- == 0)
  163.             {
  164. #ifdef I2C_DEBUG
  165.                 debugSendLine("R-2 - Start timeout" );
  166. #endif
  167.                 i2cm_fixFailure();
  168.                 return FALSE;
  169.             }
  170.         }
  171.         // Send slave address
  172.         I2C_Send7bitAddress(I2CM_MODULE, address, I2C_Direction_Receiver);
  173.         timeout = I2CM_EVENT_TIMEOUT;            // Reset timeout
  174.         // Wait until ADDR is set: EV6
  175.         while ((I2CM_MODULE->SR1&0x0002) != 0x0002)
  176.         {
  177.             if (timeout-- == 0)
  178.             {
  179. #ifdef I2C_DEBUG
  180.                 debugSendLine("R-2 - ADDR timeout" );
  181. #endif
  182.                 i2cm_fixFailure();
  183.                 return FALSE;
  184.             }
  185.         }
  186.         /*
  187.          * EV6_1: The acknowledge disable should be done just after EV6,
  188.          * that is after ADDR is cleared, so disable all active IRQs around ADDR clearing and
  189.          * ACK clearing
  190.          */
  191.         __disable_irq();
  192.         temp = I2CM_MODULE->SR2;                     // Clear ADDR by reading SR2 register
  193.         I2C_AcknowledgeConfig(I2CM_MODULE,DISABLE); // Clear ACK bit
  194.         __enable_irq();                             //Re-enable IRQs
  195.         i2cm_waitBtfSet();                          // Wait until BTF is set
  196.         // Disable IRQs around STOP programming and data reading because of the limitation ?
  197.         __disable_irq();
  198.         I2C_GenerateSTOP(I2CM_MODULE,ENABLE);       // Program the STOP
  199.         *bufI2C = I2C_ReceiveData(I2CM_MODULE);     // Read first data
  200.         __enable_irq();                             // Re-enable IRQs
  201.         bufI2C++;
  202.         *bufI2C = I2C_ReceiveData(I2CM_MODULE);     // Read second data
  203.         /* Make sure that the STOP bit is cleared by Hardware before CR1 write access */
  204.         while ((I2CM_MODULE->CR1&0x200) == 0x200)
  205.             ;
  206.         I2CM_MODULE->CR1  &= CR1_POS_Reset;          // Clear POS bit
  207.     }
  208.     // ------ For send more than two bytes
  209.     else
  210.     {
  211.         I2C_GenerateSTART(I2CM_MODULE, ENABLE);     // Send START condition
  212.         timeout = I2CM_EVENT_TIMEOUT;               // Reset timeout
  213.         // Wait until SB flag is set: EV5
  214.         while ((I2CM_MODULE->SR1&0x0001) != 0x0001)
  215.         {
  216.             if (timeout-- == 0)
  217.             {
  218. #ifdef I2C_DEBUG
  219.                 debugSendLine("R>2 - Start timeout" );
  220. #endif
  221.                 i2cm_fixFailure();
  222.                 return FALSE;
  223.             }
  224.         }
  225.         // Send slave address
  226.         I2C_Send7bitAddress(I2CM_MODULE,address,I2C_Direction_Receiver);
  227.         timeout = I2CM_EVENT_TIMEOUT;               // Reset timeout
  228.         // Wait until ADDR is set: EV6
  229.         while ((I2CM_MODULE->SR1&0x0002) != 0x0002)
  230.         {
  231.             if (timeout-- == 0)
  232.             {
  233. #ifdef I2C_DEBUG
  234.                 debugSendLine("R>2 - ADDR timeout" );
  235. #endif
  236.                 i2cm_fixFailure();
  237.                 return FALSE;
  238.             }
  239.         }
  240.         temp = I2CM_MODULE->SR2; // Clear ADDR by reading SR2 status register
  241.         while (count)               // While there is data to be read
  242.         {
  243.             if (count != 3)         // Receive bytes from first byte until byte N-3
  244.             {
  245.                 /*
  246.                  * Poll on BTF to receive data because in polling mode we can not guarantee the
  247.                  * EV7 software sequence is managed before the current byte transfer completes
  248.                  */
  249.                 i2cm_waitBtfSet();
  250.                 *bufI2C = I2C_ReceiveData(I2CM_MODULE); // Read data
  251.                 bufI2C++;
  252.                 count--;                                // Decrement the read bytes counter
  253.             }
  254.             /* it remains to read three data: data N-2, data N-1, Data N */
  255.             if (count == 3)
  256.             {
  257.                 // Wait until BTF is set: Data N-2 in DR and data N -1 in shift register
  258.                 i2cm_waitBtfSet();
  259.                 I2C_AcknowledgeConfig(I2CM_MODULE,DISABLE); // Clear ACK bit
  260.                 /*
  261.                  * Disable IRQs around data reading and STOP programming because of the
  262.                  * limitation ?
  263.                  */
  264.                 __disable_irq();
  265.                 *bufI2C = I2C_ReceiveData(I2CM_MODULE); // Read Data N-2
  266.                 bufI2C++;                               // Increment
  267.                 I2C_GenerateSTOP(I2CM_MODULE,ENABLE);   // Program the STOP
  268.                 *bufI2C = I2C_ReceiveData(I2CM_MODULE); // Read Data N-1
  269.                 __enable_irq();                         // Re-enable IRQs
  270.                 bufI2C++;                               // Increment
  271.                 i2cm_waitRxneSet(); // Wait until RXNE is set (DR contains the last data)
  272.                 *bufI2C = I2C_ReceiveData(I2CM_MODULE); // Read DataN
  273.                 count = 0;          // Reset the number of bytes to be read by master
  274.             }
  275.         }
  276.         /* Make sure that the STOP bit is cleared by Hardware before CR1 write access */
  277.         while((I2CM_MODULE->CR1&0x200) == 0x200)
  278.             ;
  279.     }
  280.     I2C_AcknowledgeConfig(I2CM_MODULE, ENABLE); // Enable Acknowledgment to be ready for another reception
  281.     temp++;                                     // For avoid compiler warning
  282.     return TRUE;
  283. }
  284. /**
  285. * @brief           Write and read data on the I2C bus
  286. *
  287. * @param[in]       address         The slave address in the 7 least significants bits
  288. * @param[in]       countWrite      The number of bytes to write
  289. * @param[in]       countRead       The number of bytes to read
  290. * @param[in, out]  bufI2C          An byte array in which store read data
  291. *
  292. * @return 1 if there is a problem during write operation, 0 otherwise
  293. *
  294. * In a first time, this function write the <tt>writeCount</tt> first bytes of bufI2C array.<br>
  295. * Then, in a second time, this function read <tt>readCount</tt> bytes on I2C and store them in bufI2C.
  296. */
  297. uint8_t i2cmWriteAndRead(uint8_t address, uint16_t countWrite, uint16_t countRead, uint8_t *bufI2C)
  298. {
  299.     if (i2cmWrite(address, countWrite, bufI2C))
  300.     {
  301.         if (i2cmRead(address, countRead, bufI2C))
  302.             return TRUE;
  303.     }
  304.     return FALSE;
  305. }
  306. /**
  307. * @brief  This function handles I2C1 Error interrupt request.
  308. */
  309. void I2C1_ER_IRQHandler(void)
  310. {
  311.     __IO uint32_t SR1Register = 0;
  312.     // Read the I2C1 status register
  313.     SR1Register = I2C1->SR1;
  314.     // If AF = 1
  315.     if ((SR1Register & 0x0400) == 0x0400)
  316.     {
  317.         I2C1->SR1 &= 0xFBFF;
  318.         SR1Register = 0;
  319.     }
  320.     // If ARLO = 1
  321.     if((SR1Register & 0x0200) == 0x0200)
  322.     {
  323.         I2C1->SR1 &= 0xFBFF;
  324.         SR1Register = 0;
  325.     }
  326.     // If BERR = 1
  327.     if((SR1Register & 0x0100) == 0x0100)
  328.     {
  329.         I2C1->SR1 &= 0xFEFF;
  330.         SR1Register = 0;
  331.     }
  332.     // If OVR = 1
  333.     if((SR1Register & 0x0800) == 0x0800)
  334.     {
  335.         I2C1->SR1 &= 0xF7FF;
  336.         SR1Register = 0;
  337.     }
  338.     i2cIsError = TRUE;
  339. }
  340. /**
  341. * @brief Wait for the end of the byte transfer (bit BTF of register SR1)
  342. */
  343. void i2cm_waitBtfSet(void)
  344. {
  345.     i2cm_waitSr1BitSet(I2C_SR1_BTF); // Wait until BTF is set
  346. }
  347. /**
  348. * @brief Wait for the reception of a byte (bit RxNE of register SR1)
  349. */
  350. void i2cm_waitRxneSet(void)
  351. {
  352.     i2cm_waitSr1BitSet(I2C_SR1_RXNE); // Wait until RXNE is set
  353. }
  354. /**
  355. * @brief       Wait until the bit <tt>bitToWait</tt> is set in register SR1
  356. *
  357. * @param[in]   bitToWait   The bit to wait
  358. */
  359. void i2cm_waitSr1BitSet(uint8_t bitToWait)
  360. {
  361.     while ((I2C_ReadRegister(I2CM_MODULE,I2C_Register_SR1)&bitToWait) != bitToWait)
  362.         ;
  363.     //softDelay(1);
  364. }
  365. /**
  366. * @brief Fix an I2C failure
  367. */
  368. void i2cm_fixFailure(void)
  369. {
  370.     GPIO_InitTypeDef initStruct;
  371.     I2C_SoftwareResetCmd(I2CM_MODULE, ENABLE);
  372.     initStruct.GPIO_Speed = GPIO_Speed_50MHz;
  373.     initStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
  374.     initStruct.GPIO_Mode = GPIO_Mode_Out_PP;
  375.     GPIO_Init(GPIOB, &initStruct);
  376.     GPIO_WriteBit(GPIOB, initStruct.GPIO_Pin, Bit_RESET);
  377.     softDelay(20);
  378.     I2C_SoftwareResetCmd(I2CM_MODULE, DISABLE);
  379.     //initStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
  380.     initStruct.GPIO_Mode = GPIO_Mode_AF_OD;
  381.     GPIO_Init(GPIOB, &initStruct);
  382.     softDelay(20);
  383.     i2cmInit();
  384. }


 
 
Merci à vous d'avoir pris le temps, je vous souhaite une excellente journée ! Merci !

Reply

Marsh Posté le 09-02-2018 à 12:46:04   

Reply

Marsh Posté le 09-02-2018 à 21:09:42    

Mauvaise cat', si un modérateur peut déplacer...
 
Je suis pas sûr d'avoir compris où est ton problème... Vu ton code tu sembles faire du I2C en pure software, c'est possible mais chiant et inutile si ton µC a un module hardware I2C. Dans ce dernier cas il suffit de lire la doc du µC pour savoir comment faire fonctionner ce module et la doc de l'afficheur pour savoir quoi lui envoyer. Après le mieux c'est de faire une petite bibliothèque avec des fonctions genre effacer_lcd(), afficher_texte() ou semblable pour que l'utilisation soit simple et confortable.

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed