[DemoCode下载] 【新唐资料分享月】M0518基于库函数的I2C主机模式

[复制链接]
5048|4
 楼主| 734774645 发表于 2016-12-18 21:02 | 显示全部楼层 |阅读模式
  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 a Master how to access Slave.
  8. *           This sample code needs to work with I2C_Slave.
  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. /*---------------------------------------------------------------------------------------------------------*/
  18. /* Global variables                                                                                        */
  19. /*---------------------------------------------------------------------------------------------------------*/
  20. volatile uint8_t g_u8DeviceAddr;
  21. volatile uint8_t g_au8TxData[3];
  22. volatile uint8_t g_u8RxData;
  23. volatile uint8_t g_u8DataLen;
  24. volatile uint8_t g_u8EndFlag = 0;

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

  26. static volatile I2C_FUNC s_I2C0HandlerFn = NULL;

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

  33.     u32Status = I2C_GET_STATUS(I2C0);

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

  45. /*---------------------------------------------------------------------------------------------------------*/
  46. /*  I2C Rx Callback Function                                                                               */
  47. /*---------------------------------------------------------------------------------------------------------*/
  48. void I2C_MasterRx(uint32_t u32Status)
  49. {
  50.     if(u32Status == 0x08)                       /* START has been transmitted and prepare SLA+W */
  51.     {
  52.         I2C_SET_DATA(I2C0, (g_u8DeviceAddr << 1));    /* Write SLA+W to Register I2CDAT */
  53.         I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI);
  54.     }
  55.     else if(u32Status == 0x18)                  /* SLA+W has been transmitted and ACK has been received */
  56.     {
  57.         I2C_SET_DATA(I2C0, g_au8TxData[g_u8DataLen++]);
  58.         I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI);
  59.     }
  60.     else if(u32Status == 0x20)                  /* SLA+W has been transmitted and NACK has been received */
  61.     {
  62.         I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_STA_STO_SI);
  63.     }
  64.     else if(u32Status == 0x28)                  /* DATA has been transmitted and ACK has been received */
  65.     {
  66.         if(g_u8DataLen != 2)
  67.         {
  68.             I2C_SET_DATA(I2C0, g_au8TxData[g_u8DataLen++]);
  69.             I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI);
  70.         }
  71.         else
  72.         {
  73.             I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_STA_SI);
  74.         }
  75.     }
  76.     else if(u32Status == 0x10)                  /* Repeat START has been transmitted and prepare SLA+R */
  77.     {
  78.         I2C_SET_DATA(I2C0, ((g_u8DeviceAddr << 1) | 0x01));   /* Write SLA+R to Register I2CDAT */
  79.         I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI);
  80.     }
  81.     else if(u32Status == 0x40)                  /* SLA+R has been transmitted and ACK has been received */
  82.     {
  83.         I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI);
  84.     }
  85.     else if(u32Status == 0x58)                  /* DATA has been received and NACK has been returned */
  86.     {
  87.         g_u8RxData = (unsigned char) I2C_GET_DATA(I2C0);
  88.         I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_STO_SI);
  89.         g_u8EndFlag = 1;
  90.     }
  91.     else
  92.     {
  93.         /* TO DO */
  94.         printf("Status 0x%x is NOT processed\n", u32Status);
  95.     }
  96. }
  97. /*---------------------------------------------------------------------------------------------------------*/
  98. /*  I2C Tx Callback Function                                                                               */
  99. /*---------------------------------------------------------------------------------------------------------*/
  100. void I2C_MasterTx(uint32_t u32Status)
  101. {
  102.     if(u32Status == 0x08)                       /* START has been transmitted */
  103.     {
  104.         I2C_SET_DATA(I2C0, g_u8DeviceAddr << 1);    /* Write SLA+W to Register I2CDAT */
  105.         I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI);
  106.     }
  107.     else if(u32Status == 0x18)                  /* SLA+W has been transmitted and ACK has been received */
  108.     {
  109.         I2C_SET_DATA(I2C0, g_au8TxData[g_u8DataLen++]);
  110.         I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI);
  111.     }
  112.     else if(u32Status == 0x20)                  /* SLA+W has been transmitted and NACK has been received */
  113.     {
  114.         I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_STA_STO_SI);
  115.     }
  116.     else if(u32Status == 0x28)                  /* DATA has been transmitted and ACK has been received */
  117.     {
  118.         if(g_u8DataLen != 3)
  119.         {
  120.             I2C_SET_DATA(I2C0, g_au8TxData[g_u8DataLen++]);
  121.             I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI);
  122.         }
  123.         else
  124.         {
  125.             I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_STO_SI);
  126.             g_u8EndFlag = 1;
  127.         }
  128.     }
  129.     else
  130.     {
  131.         /* TO DO */
  132.         printf("Status 0x%x is NOT processed\n", u32Status);
  133.     }
  134. }

  135. void SYS_Init(void)
  136. {
  137.     /*---------------------------------------------------------------------------------------------------------*/
  138.     /* Init System Clock                                                                                       */
  139.     /*---------------------------------------------------------------------------------------------------------*/

  140.     /* Enable Internal RC 22.1184MHz clock */
  141.     CLK_EnableXtalRC(CLK_PWRCON_OSC22M_EN_Msk);

  142.     /* Waiting for Internal RC clock ready */
  143.     CLK_WaitClockReady(CLK_CLKSTATUS_OSC22M_STB_Msk);

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

  146.     /* Enable external XTAL 12MHz clock */
  147.     CLK_EnableXtalRC(CLK_PWRCON_XTL12M_EN_Msk);

  148.     /* Waiting for external XTAL clock ready */
  149.     CLK_WaitClockReady(CLK_CLKSTATUS_XTL12M_STB_Msk);

  150.     /* Set core clock as PLL_CLOCK from PLL */
  151.     CLK_SetCoreClock(PLL_CLOCK);

  152.     /* Enable UART module clock */
  153.     CLK_EnableModuleClock(UART0_MODULE);

  154.     /* Enable I2C0 module clock */
  155.     CLK_EnableModuleClock(I2C0_MODULE);

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


  158.     /*---------------------------------------------------------------------------------------------------------*/
  159.     /* Init I/O Multi-function                                                                                 */
  160.     /*---------------------------------------------------------------------------------------------------------*/

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

  163.     /* Set GPA multi-function pins for I2C0 SDA and SCL */
  164.     SYS->GPA_MFP = SYS_GPA_MFP_PA8_I2C0_SDA | SYS_GPA_MFP_PA9_I2C0_SCL;
  165. }

  166. void UART0_Init()
  167. {
  168.     /*---------------------------------------------------------------------------------------------------------*/
  169.     /* Init UART                                                                                               */
  170.     /*---------------------------------------------------------------------------------------------------------*/
  171.     /* Reset IP */
  172.     SYS_ResetModule(UART0_RST);

  173.     /* Configure UART0 and set UART0 Baudrate */
  174.     UART_Open(UART0, 115200);
  175. }

  176. void I2C0_Init(void)
  177. {
  178.     /* Open I2C module and set bus clock */
  179.     I2C_Open(I2C0, 100000);

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

  182.     /* Set I2C 4 Slave Addresses */
  183.     I2C_SetSlaveAddr(I2C0, 0, 0x15, 0);   /* Slave Address : 0x15 */
  184.     I2C_SetSlaveAddr(I2C0, 1, 0x35, 0);   /* Slave Address : 0x35 */
  185.     I2C_SetSlaveAddr(I2C0, 2, 0x55, 0);   /* Slave Address : 0x55 */
  186.     I2C_SetSlaveAddr(I2C0, 3, 0x75, 0);   /* Slave Address : 0x75 */

  187.     /* Enable I2C interrupt */
  188.     I2C_EnableInt(I2C0);
  189.     NVIC_EnableIRQ(I2C0_IRQn);
  190. }

  191. void I2C0_Close(void)
  192. {
  193.     /* Disable I2C0 interrupt and clear corresponding NVIC bit */
  194.     I2C_DisableInt(I2C0);
  195.     NVIC_DisableIRQ(I2C0_IRQn);

  196.     /* Disable I2C0 and close I2C0 clock */
  197.     I2C_Close(I2C0);
  198.     CLK_DisableModuleClock(I2C0_MODULE);

  199. }

  200. int32_t I2C0_Read_Write_SLAVE(uint8_t slvaddr)
  201. {
  202.     uint32_t i;

  203.     g_u8DeviceAddr = slvaddr;

  204.     for(i = 0; i < 0x100; i++)
  205.     {
  206.         g_au8TxData[0] = (uint8_t)((i & 0xFF00) >> 8);
  207.         g_au8TxData[1] = (uint8_t)(i & 0x00FF);
  208.         g_au8TxData[2] = (uint8_t)(g_au8TxData[1] + 3);

  209.         g_u8DataLen = 0;
  210.         g_u8EndFlag = 0;

  211.         /* I2C function to write data to slave */
  212.         s_I2C0HandlerFn = (I2C_FUNC)I2C_MasterTx;

  213.         /* I2C as master sends START signal */
  214.         I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_STA);

  215.         /* Wait I2C Tx Finish */
  216.         while(g_u8EndFlag == 0);
  217.         g_u8EndFlag = 0;

  218.         /* I2C function to read data from slave */
  219.         s_I2C0HandlerFn = (I2C_FUNC)I2C_MasterRx;

  220.         g_u8DataLen = 0;
  221.         g_u8DeviceAddr = slvaddr;

  222.         I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_STA);

  223.         /* Wait I2C Rx Finish */
  224.         while(g_u8EndFlag == 0);

  225.         /* Compare data */
  226.         if(g_u8RxData != g_au8TxData[2])
  227.         {
  228.             printf("I2C Byte Write/Read Failed, Data 0x%x\n", g_u8RxData);
  229.             return -1;
  230.         }
  231.     }
  232.     printf("Master Access Slave (0x%X) Test OK\n", slvaddr);
  233.     return 0;
  234. }
  235. /*---------------------------------------------------------------------------------------------------------*/
  236. /*  Main Function                                                                                          */
  237. /*---------------------------------------------------------------------------------------------------------*/
  238. int32_t main(void)
  239. {
  240.     /* Unlock protected registers */
  241.     SYS_UnlockReg();

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

  244.     /* Init UART0 for printf */
  245.     UART0_Init();

  246.     /* Lock protected registers */
  247.     SYS_LockReg();

  248.     /*
  249.         This sample code sets I2C bus clock to 100kHz. Then, Master accesses Slave with Byte Write
  250.         and Byte Read operations, and check if the read data is equal to the programmed data.
  251.     */
  252.     printf("\n");
  253.     printf("+--------------------------------------------------------+\n");
  254.     printf("| M0518 I2C Driver Sample Code(Master) for access Slave |\n");
  255.     printf("|                                                        |\n");
  256.     printf("| I2C Master (I2C0) <---> I2C Slave(I2C0)                |\n");
  257.     printf("+--------------------------------------------------------+\n");

  258.     printf("Configure I2C0 as a master.\n");
  259.     printf("The I/O connection for I2C0:\n");
  260.     printf("I2C0_SDA(PA.8), I2C0_SCL(PA.9)\n");

  261.     /* Init I2C0 */
  262.     I2C0_Init();

  263.     printf("\n");
  264.     printf("Check I2C Slave(I2C0) is running first!\n");
  265.     printf("Press any key to continue.\n");
  266.     getchar();

  267.     /* Access Slave with no address */
  268.     printf("\n");
  269.     printf(" == No Mask Address ==\n");
  270.     I2C0_Read_Write_SLAVE(0x15);
  271.     I2C0_Read_Write_SLAVE(0x35);
  272.     I2C0_Read_Write_SLAVE(0x55);
  273.     I2C0_Read_Write_SLAVE(0x75);
  274.     printf("SLAVE Address test OK.\n");

  275.     /* Access Slave with address mask */
  276.     printf("\n");
  277.     printf(" == Mask Address ==\n");
  278.     I2C0_Read_Write_SLAVE(0x15 & ~0x01);
  279.     I2C0_Read_Write_SLAVE(0x35 & ~0x04);
  280.     I2C0_Read_Write_SLAVE(0x55 & ~0x01);
  281.     I2C0_Read_Write_SLAVE(0x75 & ~0x04);
  282.     printf("SLAVE Address Mask test OK.\n");

  283.     s_I2C0HandlerFn = NULL;

  284.     /* Close I2C0 */
  285.     I2C0_Close();

  286.     return 0;
  287. }




 楼主| 734774645 发表于 2016-12-18 21:11 | 显示全部楼层
根据代码分析,还是先设置这种外设的时钟模块。比如使能I2C0模块的时钟
    /* Enable I2C0 module clock */
    CLK_EnableModuleClock(I2C0_MODULE);

然后就是初始化管脚
    /* Set GPA multi-function pins for I2C0 SDA and SCL */
    SYS->GPA_MFP = SYS_GPA_MFP_PA8_I2C0_SDA | SYS_GPA_MFP_PA9_I2C0_SCL;

根据这个也可以看出来使用了哪个管脚。
 楼主| 734774645 发表于 2016-12-18 21:22 | 显示全部楼层
void I2C0_Init(void)
{
    /* Open I2C module and set bus clock */
    I2C_Open(I2C0, 100000);

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

    /* 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 */

    /* Enable I2C interrupt */
    I2C_EnableInt(I2C0);
    NVIC_EnableIRQ(I2C0_IRQn);
}
————————————————————————
完成了时钟配置和管脚配置后,就是配置协议层次的内容了,
如上所示,打开I2C 功能模块,初始化波特率。上面的代码实现后,就是通过串口打印出配置成功后的
I2C雄县的时钟频率。接下来就是设置从机的地址了,大家都知道吧,I2C是通过地址来区分从机的。

 楼主| 734774645 发表于 2016-12-18 21:22 | 显示全部楼层
设置完从机,就是启动中断了,启动中断在库函数下都是需要两条语句的。
先使能对应的串口,然后加入NVIC。。。
 楼主| 734774645 发表于 2016-12-18 21:23 | 显示全部楼层
然后完成这些就可以收发数据了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

211

主题

3588

帖子

15

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