[DemoCode下载] I2C从机都可以唤醒系统

[复制链接]
231|16
 楼主 | 2020-1-23 21:44 | 显示全部楼层 |阅读模式
  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: 16 $
  5. * $Date: 16/06/21 7:44p $
  6. * @brief
  7. *           Demonstrate how to set I2C to wake-up MCU from power-down mode.
  8. *           Needs to work with I2C_Wakeup_Master sample code.
  9. * @note
  10. * Copyright (C) 2014~2015 Nuvoton Technology Corp. All rights reserved.
  11. *
  12. ******************************************************************************/
  13. #include <stdio.h>
  14. #include "NUC123.h"

  15. #define PLLCON_SETTING      CLK_PLLCON_72MHz_HXT
  16. #define PLL_CLOCK           72000000

  17. /*---------------------------------------------------------------------------------------------------------*/
  18. /* Global variables                                                                                        */
  19. /*---------------------------------------------------------------------------------------------------------*/
  20. volatile uint32_t slave_buff_addr;
  21. volatile uint8_t g_au8SlvData[256];
  22. volatile uint8_t g_au8SlvRxData[3];
  23. volatile uint8_t g_u8SlvPWRDNWK, g_u8SlvI2CWK;
  24. volatile uint8_t g_u8DeviceAddr;
  25. volatile uint8_t g_u8SlvDataLen;

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

  27. static I2C_FUNC s_I2C0HandlerFn = NULL;

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

  34.     /* Check I2C Wake-up interrupt flag set or not */
  35.     if(I2C_GET_WAKEUP_FLAG(I2C0))
  36.     {
  37.         /* Clear I2C Wake-up interrupt flag */
  38.         I2C_CLEAR_WAKEUP_FLAG(I2C0);
  39.                        
  40.         g_u8SlvI2CWK = 1;               
  41.                        
  42.         return;
  43.     }

  44.     u32Status = I2C_GET_STATUS(I2C0);

  45.     if(I2C_GET_TIMEOUT_FLAG(I2C0))
  46.     {
  47.         /* Clear I2C0 Timeout Flag */
  48.         I2C_ClearTimeoutFlag(I2C0);
  49.     }
  50.     else
  51.     {
  52.         if(s_I2C0HandlerFn != NULL)
  53.             s_I2C0HandlerFn(u32Status);
  54.     }
  55. }

  56. /*---------------------------------------------------------------------------------------------------------*/
  57. /*  Power Wake-up IRQ Handler                                                                              */
  58. /*---------------------------------------------------------------------------------------------------------*/
  59. void PWRWU_IRQHandler(void)
  60. {
  61.     /* Check system power down mode wake-up interrupt flag */
  62.     if(((CLK->PWRCON) & CLK_PWRCON_PD_WU_STS_Msk) != 0)
  63.     {
  64.         /* Clear system power down wake-up interrupt flag */
  65.         CLK->PWRCON |= CLK_PWRCON_PD_WU_STS_Msk;

  66.         g_u8SlvPWRDNWK = 1;
  67.     }
  68. }

  69. /*---------------------------------------------------------------------------------------------------------*/
  70. /*  I2C Slave Transmit/Receive Callback Function                                                           */
  71. /*---------------------------------------------------------------------------------------------------------*/
  72. void I2C_SlaveTRx(uint32_t u32Status)
  73. {
  74.     if(u32Status == 0x60)                       /* Own SLA+W has been receive; ACK has been return */
  75.     {
  76.         g_u8SlvDataLen = 0;
  77.         I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);
  78.     }
  79.     else if(u32Status == 0x80)                 /* Previously address with own SLA address
  80.                                                    Data has been received; ACK has been returned*/
  81.     {
  82.         g_au8SlvRxData[g_u8SlvDataLen] = (unsigned char)I2C_GET_DATA(I2C0);
  83.         g_u8SlvDataLen++;

  84.         if(g_u8SlvDataLen == 2)
  85.         {
  86.             slave_buff_addr = (g_au8SlvRxData[0] << 8) + g_au8SlvRxData[1];
  87.         }
  88.         if(g_u8SlvDataLen == 3)
  89.         {
  90.             g_au8SlvData[slave_buff_addr] = g_au8SlvRxData[2];
  91.             g_u8SlvDataLen = 0;
  92.         }
  93.         I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);
  94.     }
  95.     else if(u32Status == 0xA8)                  /* Own SLA+R has been receive; ACK has been return */
  96.     {
  97.         I2C_SET_DATA(I2C0, g_au8SlvData[slave_buff_addr]);
  98.         slave_buff_addr++;
  99.         I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);
  100.     }
  101.     else if(u32Status == 0xC0)                 /* Data byte or last data in I2CDAT has been transmitted
  102.                                                    Not ACK has been received */
  103.     {
  104.         I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);
  105.     }
  106.     else if(u32Status == 0x88)                 /* Previously addressed with own SLA address; NOT ACK has
  107.                                                    been returned */
  108.     {
  109.         g_u8SlvDataLen = 0;
  110.         I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);
  111.     }
  112.     else if(u32Status == 0xA0)                 /* A STOP or repeated START has been received while still
  113.                                                    addressed as Slave/Receiver*/
  114.     {
  115.         g_u8SlvDataLen = 0;
  116.         I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);
  117.     }
  118.     else
  119.     {
  120.         /* TO DO */
  121.         printf("Status 0x%x is NOT processed\n", u32Status);
  122.     }
  123. }

  124. /*---------------------------------------------------------------------------------------------------------*/
  125. /*  System initial function                                                                                */
  126. /*---------------------------------------------------------------------------------------------------------*/
  127. void SYS_Init(void)
  128. {
  129.     /*---------------------------------------------------------------------------------------------------------*/
  130.     /* Init System Clock                                                                                       */
  131.     /*---------------------------------------------------------------------------------------------------------*/

  132.     /* Enable XT1_OUT (PF0) and XT1_IN (PF1) */
  133.     SYS->GPF_MFP |= SYS_GPF_MFP_PF0_XT1_OUT | SYS_GPF_MFP_PF1_XT1_IN;

  134.     /* Enable Internal RC 22.1184MHz clock */
  135.     CLK_EnableXtalRC(CLK_PWRCON_OSC22M_EN_Msk);

  136.     /* Waiting for Internal RC clock ready */
  137.     CLK_WaitClockReady(CLK_CLKSTATUS_OSC22M_STB_Msk);

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

  140.     /* Enable external XTAL 12MHz clock */
  141.     CLK_EnableXtalRC(CLK_PWRCON_XTL12M_EN_Msk);

  142.     /* Waiting for external XTAL clock ready */
  143.     CLK_WaitClockReady(CLK_CLKSTATUS_XTL12M_STB_Msk);

  144.     /* Set core clock as PLL_CLOCK from PLL */
  145.     CLK_SetCoreClock(PLL_CLOCK);

  146.     /* Enable UART module clock */
  147.     CLK_EnableModuleClock(UART0_MODULE);

  148.     /* Enable I2C0 module clock */
  149.     CLK_EnableModuleClock(I2C0_MODULE);

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

  152.     /*---------------------------------------------------------------------------------------------------------*/
  153.     /* Init I/O Multi-function                                                                                 */
  154.     /*---------------------------------------------------------------------------------------------------------*/

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

  157.     /* Set GPF multi-function pins for I2C0 SDA and SCL */
  158.     SYS->GPF_MFP |= (SYS_GPF_MFP_PF2_I2C0_SDA | SYS_GPF_MFP_PF3_I2C0_SCL);
  159.     SYS->ALT_MFP1 &= ~(SYS_ALT_MFP1_PF2_Msk | SYS_ALT_MFP1_PF3_Msk);
  160.     SYS->ALT_MFP1 |= (SYS_ALT_MFP1_PF2_I2C0_SDA | SYS_ALT_MFP1_PF3_I2C0_SCL);
  161. }

  162. void UART0_Init()
  163. {
  164.     /*---------------------------------------------------------------------------------------------------------*/
  165.     /* Init UART                                                                                               */
  166.     /*---------------------------------------------------------------------------------------------------------*/
  167.     /* Reset IP */
  168.     SYS_ResetModule(UART0_RST);

  169.     /* Configure UART0 and set UART0 Baudrate */
  170.     UART_Open(UART0, 115200);
  171. }

  172. void I2C0_Init(void)
  173. {
  174.     /* Open I2C module and set bus clock */
  175.     I2C_Open(I2C0, 100000);

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

  178.     /* Set I2C 4 Slave Addresses */
  179.     I2C_SetSlaveAddr(I2C0, 0, 0x15, 0);   /* Slave Address : 0x15 */
  180.     I2C_SetSlaveAddr(I2C0, 1, 0x35, 0);   /* Slave Address : 0x35 */
  181.     I2C_SetSlaveAddr(I2C0, 2, 0x55, 0);   /* Slave Address : 0x55 */
  182.     I2C_SetSlaveAddr(I2C0, 3, 0x75, 0);   /* Slave Address : 0x75 */

  183.     /* Set I2C 4 Slave Addresses Mask */
  184.     I2C_SetSlaveAddrMask(I2C0, 0, 0x01);
  185.     I2C_SetSlaveAddrMask(I2C0, 1, 0x04);
  186.     I2C_SetSlaveAddrMask(I2C0, 2, 0x01);
  187.     I2C_SetSlaveAddrMask(I2C0, 3, 0x04);

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

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

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

  201. /*---------------------------------------------------------------------------------------------------------*/
  202. /*  Main Function                                                                                          */
  203. /*---------------------------------------------------------------------------------------------------------*/
  204. int32_t main(void)
  205. {
  206.     uint32_t i;

  207.     /* Unlock protected registers */
  208.     SYS_UnlockReg();

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

  211.     /* Init UART0 for printf */
  212.     UART0_Init();

  213.     /* Lock protected registers */
  214.     SYS_LockReg();;

  215.     /*
  216.         This sample code is I2C SLAVE mode and it simulates EEPROM function
  217.     */
  218.     printf("\n");
  219.     printf("+-----------------------------------------------------------------------+\n");
  220.     printf("| NUC123 I2C Driver Sample Code (Slave) for wake-up & access Slave test |\n");
  221.     printf("| Needs to work with I2C_Wakeup_Master sample code.                     |\n");
  222.     printf("|      I2C Master (I2C0) <---> I2C Slave (I2C0)                         |\n");
  223.     printf("| !! This sample code requires two borads to test !!                    |\n");
  224.     printf("+-----------------------------------------------------------------------+\n");

  225.     printf("Configure I2C0 as a slave.\n");
  226.     printf("The I/O connection for I2C0:\n");
  227.     printf("I2C0_SDA(PF.2), I2C0_SCL(PF.3)\n");

  228.     /* Init I2C0 */
  229.     I2C0_Init();

  230.     for(i = 0; i < 0x100; i++)
  231.     {
  232.         g_au8SlvData[i] = 0;
  233.     }

  234.     /* I2C function to Transmit/Receive data as slave */
  235.     s_I2C0HandlerFn = I2C_SlaveTRx;
  236.                
  237.     /* Set I2C0 enter Not Address SLAVE mode */
  238.     I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);

  239.     /* Unlock protected registers */
  240.     SYS_UnlockReg();

  241.     /* Enable power wake-up interrupt */
  242.     CLK->PWRCON |= CLK_PWRCON_PD_WU_INT_EN_Msk;
  243.     NVIC_EnableIRQ(PWRWU_IRQn);

  244.     /* Enable I2C wake-up */
  245.     I2C_EnableWakeup(I2C0);

  246.     printf("\n");
  247.     printf("Enter PD 0x%x 0x%x\n", I2C0->I2CON , I2C0->I2CSTATUS);
  248.     printf("\n");
  249.     printf("CHIP enter power down status.\n");
  250.     /* Waiting for UART printf finish*/
  251.     while(((UART0->FSR) & UART_FSR_TE_FLAG_Msk) == 0);

  252.     if(((I2C0->I2CON)&I2C_I2CON_SI_Msk) != 0)
  253.     {
  254.         I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI);
  255.     }
  256.    
  257.     /*  Use WFI instruction to idle the CPU. NOTE:
  258.         If ICE is attached, system will wakeup immediately because ICE is a wakeup event. */
  259.     CLK_PowerDown();

  260.     while((g_u8SlvPWRDNWK & g_u8SlvI2CWK) == 0);   
  261.     printf("Power-down Wake-up INT 0x%x\n", ((CLK->PWRCON) & CLK_PWRCON_PD_WU_STS_Msk));               
  262.     printf("I2C0 WAKE INT 0x%x\n", I2C0->I2CWKUPSTS);
  263.                
  264.     /* Disable power wake-up interrupt */
  265.     CLK->PWRCON &= ~CLK_PWRCON_PD_WU_INT_EN_Msk;
  266.     NVIC_DisableIRQ(PWRWU_IRQn);

  267.     /* Lock protected registers */
  268.     SYS_LockReg();

  269.     printf("\n");
  270.     printf("Slave wake-up from power down status.\n");

  271.     printf("\n");
  272.     printf("Slave Waiting for receiving data.\n");

  273.     while(1);
  274. }



复制代码


使用特权

评论回复
 楼主 | 2020-1-23 21:45 | 显示全部楼层
通过从机都可以唤醒休眠的系统也是非常非常牛的。

使用特权

评论回复
 楼主 | 2020-1-23 21:45 | 显示全部楼层
这种方法非常实用于低功耗系统。

使用特权

评论回复
| 2020-1-24 13:58 | 显示全部楼层
所有的唤醒,均来自中断。

使用特权

评论回复
| 2020-1-24 14:39 | 显示全部楼层
一般的中断都可以唤醒休眠

使用特权

评论回复
| 2020-1-24 15:10 | 显示全部楼层
硬件收发器用好了非常棒

使用特权

评论回复
| 2020-1-24 15:26 | 显示全部楼层
例子中使用了大量的printf

使用特权

评论回复
| 2020-1-24 15:26 | 显示全部楼层
会不会影响系统的速度。另外I2C的速度由什么控制的

使用特权

评论回复
| 2020-1-25 15:46 | 显示全部楼层
中断应用十分广泛。

使用特权

评论回复
| 2020-1-25 22:21 | 显示全部楼层
我要找个I2C的文档看看。

使用特权

评论回复
| 2020-1-26 11:29 | 显示全部楼层
volatile关键字用的好

使用特权

评论回复
| 2020-1-26 11:29 | 显示全部楼层
全局变量在地址里,用这个关键字可以保证每次从原来地址读取

使用特权

评论回复
| 2020-1-26 19:18 | 显示全部楼层
太赞了。

使用特权

评论回复
| 2020-1-31 22:05 | 显示全部楼层
SPI也可以唤醒吧

使用特权

评论回复
| 2020-1-31 22:06 | 显示全部楼层
查看了一下,SPI不可以唤醒。

使用特权

评论回复
| 2020-1-31 22:15 | 显示全部楼层
分享的资料不错。

使用特权

评论回复
| 2020-2-2 21:04 | 显示全部楼层
中断系统的强大,低功耗设计的高级。

使用特权

评论回复
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

我要发帖 投诉建议 创建版块 申请版主

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式

论坛热帖

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