21ic电子技术开发论坛

标题: 函数指针在I2C收发上的应用 [打印本页]

作者: 小明的同学    时间: 2024-6-16 16:04
标题: 函数指针在I2C收发上的应用
看到了NANO130的一个示例,操作I2C读写一个传感器芯片的。在中断中执行读或者写作业,通过函数指针传递进来,实现中断函数执行读或者写。
复制
  1. /**************************************************************************//**
  2. * [url=home.php?mod=space&uid=288409]@file[/url]     CJMCU116.c
  3. * [url=home.php?mod=space&uid=895143]@version[/url]  V1.00
  4. * $Revision: 1 $
  5. * $Date: 14/05/13 7:20p $
  6. * [url=home.php?mod=space&uid=247401]@brief[/url]    CJMCU116 Library
  7. *
  8. * @note
  9. * Copyright (C) 2014 Nuvoton Technology Corp. All rights reserved.
  10. *
  11. ******************************************************************************/
  12. #include <stdio.h>
  13. #include "CJMCU116.h"

  14. __INLINE void I2C_PIN_Init(void)
  15. {
  16.                 /* Set GPA8,9 multi-function pins for I2C0 SDA and SCL */
  17.                 SYS->PA_H_MFP |= (SYS_PA_H_MFP_PA8_MFP_I2C0_SDA | SYS_PA_H_MFP_PA9_MFP_I2C0_SCL);
  18.        
  19.           /* Enable I2C0 clock */        
  20.    // CLK->APBCLK |= CLK_APBCLK_I2C0_EN;
  21.                 CLK->APBCLK |= CLK_APBCLK_I2C0_EN_Msk;//CLK_APBCLK_I2C0_EN_Pos
  22.     /* Reset I2C0 */
  23.     SYS->IPRST_CTL2 |=  SYS_IPRST_CTL2_I2C0_RST_Msk;
  24.     SYS->IPRST_CTL2 &= ~SYS_IPRST_CTL2_I2C0_RST_Msk;       
  25. }

  26. /*---------------------------------------------------------------------------------------------------------*/
  27. /* Global variables                                                                                        */
  28. /*---------------------------------------------------------------------------------------------------------*/
  29. uint8_t g_au8TxData[3];
  30. uint8_t g_u8RxData;
  31. uint8_t g_u8DataLen;
  32. volatile uint8_t g_u8EndFlag = 0;
  33. typedef void (*I2C_FUNC)(uint32_t u32Status);
  34. static I2C_FUNC s_I2CHandlerFn = NULL;

  35. /*---------------------------------------------------------------------------------------------------------*/
  36. /*  I2C IRQ Handler                                                                                       */
  37. /*---------------------------------------------------------------------------------------------------------*/
  38. void I2C0_IRQHandler(void)
  39. {
  40.     uint32_t u32Status;

  41.     // clear interrupt flag
  42.     I2C0->INTSTS = I2C_INTSTS_INTSTS_Msk;       
  43.        
  44.     u32Status = I2C0->STATUS;

  45.     if (I2C0->INTSTS & I2C_INTSTS_TIF_Msk)
  46.     {
  47.         /* Clear I2C Timeout Flag */
  48.         I2C0->INTSTS = I2C_INTSTS_TIF_Msk;                  
  49.     }   
  50.     else
  51.     {
  52.         if (s_I2CHandlerFn != NULL)
  53.             s_I2CHandlerFn(u32Status);
  54.     }
  55. }

  56. /*---------------------------------------------------------------------------------------------------------*/
  57. /*  I2C Initial Function                                                                                       */
  58. /*---------------------------------------------------------------------------------------------------------*/
  59. void I2C0_Init(uint8_t u8Freg)
  60. {
  61.                 uint8_t u8Divider;
  62.                 I2C_PIN_Init();
  63.     /* Enable I2C Controller */
  64.     I2C0->CON |= I2C_CON_IPEN_Msk;
  65.    
  66.     /* I2C clock divider, I2C Bus Clock = PCLK / (4*120) = 100kHz */
  67.     u8Divider = SystemCoreClock/(u8Freg*4000)-1;
  68.                 I2C0->DIV = u8Divider;

  69.     /* Enable I2C interrupt and set corresponding NVIC bit */
  70.     I2C0->CON |= I2C_CON_INTEN_Msk;
  71.     NVIC_EnableIRQ(I2C0_IRQn);
  72. }

  73. /*---------------------------------------------------------------------------------------------------------*/
  74. /*  I2C Rx Callback Function                                                                               */
  75. /*---------------------------------------------------------------------------------------------------------*/
  76. void I2C_MasterRx(uint32_t u32Status)
  77. {
  78.     if (u32Status == 0x08)                      /* START has been transmitted and prepare SLA+W */
  79.     {
  80.         I2C0->DATA = g_au8TxData[g_u8DataLen++] << 1;     /* Write SLA+W to Register I2CDAT */
  81.         I2C_SET_CONTROL_REG(I2C0, I2C_SI);
  82.     }   
  83.     else if (u32Status == 0x18)                 /* SLA+W has been transmitted and ACK has been received */
  84.     {
  85.         I2C0->DATA = g_au8TxData[g_u8DataLen++];
  86.         I2C_SET_CONTROL_REG(I2C0, I2C_SI);
  87.     }
  88.     else if (u32Status == 0x20)                 /* SLA+W has been transmitted and NACK has been received */
  89.     {
  90.         I2C_SET_CONTROL_REG(I2C0, I2C_STA | I2C_STO | I2C_SI);
  91.     }
  92.     else if (u32Status == 0x28)                 /* DATA has been transmitted and ACK has been received */
  93.     {
  94.         I2C_SET_CONTROL_REG(I2C0, I2C_STA | I2C_SI);
  95.     }
  96.                
  97.     else if (u32Status == 0x10)                 /* Repeat START has been transmitted and prepare SLA+R */
  98.     {
  99.         I2C0->DATA = ((g_au8TxData[0] << 1) | 0x01);   /* Write SLA+R to Register I2CDAT */
  100.         I2C_SET_CONTROL_REG(I2C0, I2C_SI);
  101.     }
  102.     else if (u32Status == 0x40)                 /* SLA+R has been transmitted and ACK has been received */
  103.     {
  104.         I2C_SET_CONTROL_REG(I2C0, I2C_SI);
  105.     }      
  106.     else if (u32Status == 0x58)                 /* DATA has been received and NACK has been returned */
  107.     {
  108.         g_u8RxData = I2C0->DATA;
  109.         I2C_SET_CONTROL_REG(I2C0, I2C_STO | I2C_SI);
  110.         g_u8EndFlag = 1;
  111.     }
  112.     else if (u32Status == 0xF8)    /*I2C wave keeps going*/
  113.     {

  114.     }                
  115.     else
  116.     {
  117.         /* TO DO */
  118.         //printf("Status 0x%x is NOT processed\n", u32Status);
  119.                                 while(1);
  120.     }           
  121. }

  122. /*---------------------------------------------------------------------------------------------------------*/
  123. /*  I2C Tx Callback Function                                                                               */
  124. /*---------------------------------------------------------------------------------------------------------*/
  125. void I2C_MasterTx(uint32_t u32Status)
  126. {
  127.     if (u32Status == 0x08)                      /* START has been transmitted */
  128.     {
  129.         I2C0->DATA = g_au8TxData[g_u8DataLen++] << 1;     /* Write SLA+W to Register I2CDAT */
  130.         I2C_SET_CONTROL_REG(I2C0, I2C_SI);
  131.     }   
  132.     else if (u32Status == 0x18)                 /* SLA+W has been transmitted and ACK has been received */
  133.     {
  134.         I2C0->DATA = g_au8TxData[g_u8DataLen++];
  135.         I2C_SET_CONTROL_REG(I2C0, I2C_SI);
  136.     }
  137.     else if (u32Status == 0x20)                 /* SLA+W has been transmitted and NACK has been received */
  138.     {
  139.         I2C_SET_CONTROL_REG(I2C0, I2C_STA | I2C_STO | I2C_SI);
  140.     }   
  141.     else if (u32Status == 0x28)                 /* DATA has been transmitted and ACK has been received */
  142.     {
  143.         if (g_u8DataLen != 3)
  144.         {
  145.             I2C0->DATA = g_au8TxData[g_u8DataLen++];
  146.             I2C_SET_CONTROL_REG(I2C0, I2C_SI);
  147.         }
  148.         else
  149.         {
  150.             I2C_SET_CONTROL_REG(I2C0, I2C_STO | I2C_SI);
  151.             g_u8EndFlag = 1;
  152.         }      
  153.     }
  154.     else if (u32Status == 0xF8)    /*I2C wave keeps going*/
  155.     {

  156.     }                
  157.     else
  158.     {
  159.         /* TO DO */
  160.         //printf("Status 0x%x is NOT processed\n", u32Status);
  161.                                 while(1);
  162.     }      
  163. }

  164. /*---------------------------------------------------------------------------------------------------------*/
  165. /*  Write I2C                                                                                     */
  166. /*---------------------------------------------------------------------------------------------------------*/
  167. void I2C0_Write(uint8_t u8Address,uint8_t u8Reg, uint8_t u8Data)
  168. {
  169.                 g_au8TxData[0] = u8Address;
  170.                 g_au8TxData[1] = u8Reg;
  171.                 g_au8TxData[2] = u8Data;       
  172.        
  173.                 g_u8DataLen = 0;
  174.                 g_u8EndFlag = 0;
  175.                
  176.                 /* I2C function to write data to slave */
  177.                 s_I2CHandlerFn = (I2C_FUNC)I2C_MasterTx;
  178.                
  179.                 /* I2C as master sends START signal */
  180.                 I2C_SET_CONTROL_REG(I2C0, I2C_STA);

  181.                 /* Wait I2C Tx Finish */
  182.                 while (g_u8EndFlag == 0);       
  183. }

  184. /*---------------------------------------------------------------------------------------------------------*/
  185. /*  Read I2C                                                                                */
  186. /*---------------------------------------------------------------------------------------------------------*/
  187. uint8_t I2C0_Read(uint8_t u8Address, uint8_t u8Reg)
  188. {
  189.                 g_au8TxData[0] = u8Address;
  190.                 g_au8TxData[1] = u8Reg;       
  191.        
  192.                 g_u8DataLen = 0;
  193.                 g_u8EndFlag = 0;
  194.                
  195.                 /* I2C function to write data to slave */
  196.                 s_I2CHandlerFn = (I2C_FUNC)I2C_MasterRx;
  197.                
  198.                 /* I2C as master sends START signal */
  199.                 I2C_SET_CONTROL_REG(I2C0, I2C_STA);

  200.                 /* Wait I2C Tx Finish */
  201.                 while (g_u8EndFlag == 0);       
  202.        
  203.                 return g_u8RxData;
  204. }







作者: 小明的同学    时间: 2024-6-16 16:09
不过这种没有直接写成函数式的好理解,或者说更方便使用。
作者: 小明的同学    时间: 2024-6-16 16:09
这是需要多个函数配合才实现的收发。
作者: 小明的同学    时间: 2024-6-16 16:09
这是以前的系列都是这样的,看了最近几年出的型号的BSP已经提供了相关单个函数实现收发了。
作者: 小明的同学    时间: 2024-6-16 16:33
复制
  1. uint8_t I2C_WriteByte(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t data);
  2. uint32_t I2C_WriteMultiBytes(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t data[], uint32_t u32wLen);
  3. uint8_t I2C_WriteByteOneReg(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t u8DataAddr, uint8_t data);
  4. uint32_t I2C_WriteMultiBytesOneReg(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t u8DataAddr, uint8_t data[], uint32_t u32wLen);
  5. uint8_t I2C_WriteByteTwoRegs(I2C_T *i2c, uint8_t u8SlaveAddr, uint16_t u16DataAddr, uint8_t data);
  6. uint32_t I2C_WriteMultiBytesTwoRegs(I2C_T *i2c, uint8_t u8SlaveAddr, uint16_t u16DataAddr, uint8_t data[], uint32_t u32wLen);
  7. uint8_t I2C_ReadByte(I2C_T *i2c, uint8_t u8SlaveAddr);
  8. uint32_t I2C_ReadMultiBytes(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t rdata[], uint32_t u32rLen);
  9. uint8_t I2C_ReadByteOneReg(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t u8DataAddr);
  10. uint32_t I2C_ReadMultiBytesOneReg(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t u8DataAddr, uint8_t rdata[], uint32_t u32rLen);
  11. uint8_t I2C_ReadByteTwoRegs(I2C_T *i2c, uint8_t u8SlaveAddr, uint16_t u16DataAddr);
  12. uint32_t I2C_ReadMultiBytesTwoRegs(I2C_T *i2c, uint8_t u8SlaveAddr, uint16_t u16DataAddr, uint8_t rdata[], uint32_t u32rLen);

M487系列提供的新函数,更加好用了。




欢迎光临 21ic电子技术开发论坛 (https://bbs.21ic.com/) Powered by Discuz! X3.5