[技术问答] M051的I2C从机地址设置问题

[复制链接]
6742|7
 楼主| antusheng 发表于 2021-9-22 22:40 | 显示全部楼层 |阅读模式
I2c, se, slave, TI, AD, TE
  1. /**************************************************************************//**
  2. * [url=home.php?mod=space&uid=288409]@file[/url]     main.c
  3. * [url=home.php?mod=space&uid=895143]@version[/url]  V3.00
  4. * $Revision: 2 $
  5. * $Date: 14/12/25 10:24a $
  6. * @brief
  7. *           Show how to set I2C in Slave mode and receive the data from Master.
  8. *           This sample code needs to work with I2C_Master.
  9. * @note
  10. * Copyright (C) 2014 Nuvoton Technology Corp. All rights reserved.
  11. *
  12. ******************************************************************************/
  13. #include <stdio.h>
  14. #include "M0518.h"

  15. #define PLLCON_SETTING      SYSCLK_PLLCON_50MHz_XTAL
  16. #define PLL_CLOCK           50000000

  17. uint32_t slave_buff_addr;
  18. uint8_t g_u8SlvData[256];
  19. uint8_t g_au8RxData[3];
  20. /*---------------------------------------------------------------------------------------------------------*/
  21. /* Global variables                                                                                        */
  22. /*---------------------------------------------------------------------------------------------------------*/
  23. volatile uint8_t g_u8DeviceAddr;
  24. volatile uint8_t g_au8TxData[3];
  25. volatile uint8_t g_u8RxData;
  26. volatile uint8_t g_u8DataLen;

  27. typedef void (*I2C_FUNC)(uint32_t u32Status);

  28. static I2C_FUNC s_I2C0HandlerFn = NULL;

  29. /*---------------------------------------------------------------------------------------------------------*/
  30. /*  I2C0 IRQ Handler                                                                                       */
  31. /*---------------------------------------------------------------------------------------------------------*/
  32. void I2C0_IRQHandler(void)
  33. {
  34.     uint32_t u32Status;

  35.     u32Status = I2C_GET_STATUS(I2C0);

  36.     if(I2C_GET_TIMEOUT_FLAG(I2C0))
  37.     {
  38.         /* Clear I2C0 Timeout Flag */
  39.         I2C_ClearTimeoutFlag(I2C0);
  40.     }
  41.     else
  42.     {
  43.         if(s_I2C0HandlerFn != NULL)
  44.             s_I2C0HandlerFn(u32Status);
  45.     }
  46. }

  47. /*---------------------------------------------------------------------------------------------------------*/
  48. /*  I2C TRx Callback Function                                                                               */
  49. /*---------------------------------------------------------------------------------------------------------*/
  50. void I2C_SlaveTRx(uint32_t u32Status)
  51. {
  52.     if(u32Status == 0x60)                       /* Own SLA+W has been receive; ACK has been return */
  53.     {
  54.         g_u8DataLen = 0;
  55.         I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);
  56.     }
  57.     else if(u32Status == 0x80)                 /* Previously address with own SLA address
  58.                                                    Data has been received; ACK has been returned*/
  59.     {
  60.         g_au8RxData[g_u8DataLen] = (unsigned char) I2C_GET_DATA(I2C0);
  61.         g_u8DataLen++;

  62.         if(g_u8DataLen == 2)
  63.         {
  64.             slave_buff_addr = (g_au8RxData[0] << 8) + g_au8RxData[1];
  65.         }
  66.         if(g_u8DataLen == 3)
  67.         {
  68.             g_u8SlvData[slave_buff_addr] = g_au8RxData[2];
  69.             g_u8DataLen = 0;
  70.         }

  71.         I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);
  72.     }
  73.     else if(u32Status == 0xA8)                  /* Own SLA+R has been receive; ACK has been return */
  74.     {
  75.         I2C_SET_DATA(I2C0, g_u8SlvData[slave_buff_addr]);
  76.         slave_buff_addr++;
  77.         I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);
  78.     }
  79.     else if(u32Status == 0xC0)                 /* Data byte or last data in I2CDAT has been transmitted
  80.                                                    Not ACK has been received */
  81.     {
  82.         I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);
  83.     }
  84.     else if(u32Status == 0x88)                 /* Previously addressed with own SLA address; NOT ACK has
  85.                                                    been returned */
  86.     {
  87.         g_u8DataLen = 0;
  88.         I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);
  89.     }
  90.     else if(u32Status == 0xA0)                 /* A STOP or repeated START has been received while still
  91.                                                    addressed as Slave/Receiver*/
  92.     {
  93.         g_u8DataLen = 0;
  94.         I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);
  95.     }
  96.     else
  97.     {
  98.         /* TO DO */
  99.         printf("Status 0x%x is NOT processed\n", u32Status);
  100.     }
  101. }

  102. void SYS_Init(void)
  103. {
  104.     /*---------------------------------------------------------------------------------------------------------*/
  105.     /* Init System Clock                                                                                       */
  106.     /*---------------------------------------------------------------------------------------------------------*/

  107.     /* Enable Internal RC 22.1184MHz clock */
  108.     CLK_EnableXtalRC(CLK_PWRCON_OSC22M_EN_Msk);

  109.     /* Waiting for Internal RC clock ready */
  110.     CLK_WaitClockReady(CLK_CLKSTATUS_OSC22M_STB_Msk);

  111.     /* Switch HCLK clock source to Internal RC and HCLK source divide 1 */
  112.     CLK_SetHCLK(CLK_CLKSEL0_HCLK_S_HIRC, CLK_CLKDIV_HCLK(1));

  113.     /* Enable external XTAL 12MHz clock */
  114.     CLK_EnableXtalRC(CLK_PWRCON_XTL12M_EN_Msk);

  115.     /* Waiting for external XTAL clock ready */
  116.     CLK_WaitClockReady(CLK_CLKSTATUS_XTL12M_STB_Msk);

  117.     /* Set core clock as PLL_CLOCK from PLL */
  118.     CLK_SetCoreClock(PLL_CLOCK);

  119.     /* Enable UART module clock */
  120.     CLK_EnableModuleClock(UART0_MODULE);

  121.     /* Enable I2C0 module clock */
  122.     CLK_EnableModuleClock(I2C0_MODULE);

  123.     /* Select UART module clock source */
  124.     CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART_S_HXT, CLK_CLKDIV_UART(1));


  125.     /*---------------------------------------------------------------------------------------------------------*/
  126.     /* Init I/O Multi-function                                                                                 */
  127.     /*---------------------------------------------------------------------------------------------------------*/

  128.     /* Set GPB multi-function pins for UART0 RXD and TXD */
  129.     SYS->GPB_MFP = SYS_GPB_MFP_PB0_UART0_RXD | SYS_GPB_MFP_PB1_UART0_TXD;

  130.     /* Set GPA multi-function pins for I2C0 SDA and SCL */
  131.     SYS->GPA_MFP = SYS_GPA_MFP_PA8_I2C0_SDA | SYS_GPA_MFP_PA9_I2C0_SCL;
  132. }

  133. void UART0_Init()
  134. {
  135.     /*---------------------------------------------------------------------------------------------------------*/
  136.     /* Init UART                                                                                               */
  137.     /*---------------------------------------------------------------------------------------------------------*/
  138.     /* Reset IP */
  139.     SYS_ResetModule(UART0_RST);

  140.     /* Configure UART0 and set UART0 Baudrate */
  141.     UART_Open(UART0, 115200);
  142. }


  143. void I2C0_Init(void)
  144. {
  145.     /* Open I2C module and set bus clock */
  146.     I2C_Open(I2C0, 100000);

  147.     /* Get I2C0 Bus Clock */
  148.     printf("I2C clock %d Hz\n", I2C_GetBusClockFreq(I2C0));

  149.     /* Set I2C 4 Slave Addresses */
  150.     I2C_SetSlaveAddr(I2C0, 0, 0x15, 0);   /* Slave Address : 0x15 */
  151.     I2C_SetSlaveAddr(I2C0, 1, 0x35, 0);   /* Slave Address : 0x35 */
  152.     I2C_SetSlaveAddr(I2C0, 2, 0x55, 0);   /* Slave Address : 0x55 */
  153.     I2C_SetSlaveAddr(I2C0, 3, 0x75, 0);   /* Slave Address : 0x75 */

  154.     /* Set I2C 4 Slave Addresses Mask */
  155.     I2C_SetSlaveAddrMask(I2C0, 0, 0x01);
  156.     I2C_SetSlaveAddrMask(I2C0, 1, 0x04);
  157.     I2C_SetSlaveAddrMask(I2C0, 2, 0x01);
  158.     I2C_SetSlaveAddrMask(I2C0, 3, 0x04);

  159.     /* Enable I2C interrupt */
  160.     I2C_EnableInt(I2C0);
  161.     NVIC_EnableIRQ(I2C0_IRQn);
  162. }

  163. void I2C0_Close(void)
  164. {
  165.     /* Disable I2C0 interrupt and clear corresponding NVIC bit */
  166.     I2C_DisableInt(I2C0);
  167.     NVIC_DisableIRQ(I2C0_IRQn);

  168.     /* Disable I2C0 and close I2C0 clock */
  169.     I2C_Close(I2C0);
  170.     CLK_DisableModuleClock(I2C0_MODULE);

  171. }

  172. /*---------------------------------------------------------------------------------------------------------*/
  173. /*  Main Function                                                                                          */
  174. /*---------------------------------------------------------------------------------------------------------*/
  175. int32_t main(void)
  176. {
  177.     uint32_t i;

  178.     /* Unlock protected registers */
  179.     SYS_UnlockReg();

  180.     /* Init System, IP clock and multi-function I/O */
  181.     SYS_Init();

  182.     /* Init UART0 for printf */
  183.     UART0_Init();

  184.     /* Lock protected registers */
  185.     SYS_LockReg();

  186.     /*
  187.         This sample code sets I2C bus clock to 100kHz. Then, Master accesses Slave with Byte Write
  188.         and Byte Read operations, and check if the read data is equal to the programmed data.
  189.     */

  190.     printf("+------------------------------------------------------_-+\n");
  191.     printf("|  M0518 I2C Driver Sample Code(Slave) for access Slave |\n");
  192.     printf("|                                                        |\n");
  193.     printf("| I2C Master (I2C0) <---> I2C Slave(I2C0)                |\n");
  194.     printf("+-------------------------------------------------------_+\n");

  195.     printf("Configure I2C0 as a slave.\n");
  196.     printf("The I/O connection for I2C0:\n");
  197.     printf("I2C0_SDA(PA.8), I2C0_SCL(PA.9)\n");

  198.     /* Init I2C0 */
  199.     I2C0_Init();

  200.     /* I2C enter no address SLV mode */
  201.     I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);

  202.     for(i = 0; i < 0x100; i++)
  203.     {
  204.         g_u8SlvData[i] = 0;
  205.     }

  206.     /* I2C function to Slave receive/transmit data */
  207.     s_I2C0HandlerFn = I2C_SlaveTRx;

  208.     printf("\n");
  209.     printf("I2C Slave Mode is Running.\n");

  210.     while(1);
  211. }



为何可以设置这么多地址。
jasontu 发表于 2021-9-23 09:10 | 显示全部楼层
硬件的设计,可以多组的i2c slave address
/* Set I2C 4 Slave Addresses */

    I2C_SetSlaveAddr(I2C0, 0, 0x15, 0);   /* Slave Address : 0x15 */

    I2C_SetSlaveAddr(I2C0, 1, 0x35, 0);   /* Slave Address : 0x35 */

    I2C_SetSlaveAddr(I2C0, 2, 0x55, 0);   /* Slave Address : 0x55 */

    I2C_SetSlaveAddr(I2C0, 3, 0x75, 0);   /* Slave Address : 0x75 */



    /* Set I2C 4 Slave Addresses Mask */

    I2C_SetSlaveAddrMask(I2C0, 0, 0x01);

    I2C_SetSlaveAddrMask(I2C0, 1, 0x04);

    I2C_SetSlaveAddrMask(I2C0, 2, 0x01);

    I2C_SetSlaveAddrMask(I2C0, 3, 0x04);
 楼主| antusheng 发表于 2021-9-27 19:20 | 显示全部楼层
jasontu 发表于 2021-9-23 09:10
硬件的设计,可以多组的i2c slave address
/* Set I2C 4 Slave Addresses */

意思是一个物理上的从机可以有多个从机地址?
wakayi 发表于 2021-10-14 17:15 | 显示全部楼层
不是啊 地址是唯一的
labasi 发表于 2021-10-14 17:16 | 显示全部楼层
iic的代码这么多吗
paotangsan 发表于 2021-10-14 17:18 | 显示全部楼层
楼主的理解有误
renzheshengui 发表于 2021-10-14 17:18 | 显示全部楼层
每个设备的物理地址都唯一
wowu 发表于 2021-10-14 17:19 | 显示全部楼层
试一试不就知道了吗
您需要登录后才可以回帖 登录 | 注册

本版积分规则

86

主题

1521

帖子

5

粉丝
快速回复 在线客服 返回列表 返回顶部