打印

IDLE模式和 UART的疑问

[复制链接]
3979|20
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
David_ming|  楼主 | 2010-10-21 16:34 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 David_ming 于 2010-10-27 20:49 编辑

碰到问两个问题:

1. M0的timer和cpu的时钟都是用外部12M的时候,如果关掉内部的22M,进IDLE模式不能唤醒,打开22M后才可以正常工作。
2. M0的UART和CPU的时钟都是外部12M的时候,如果关闭内部的22M,会printf不出来数据,打开22M后可以正常工作。

这是软件的bug还是硬件就这样做的??3Q。

备注,我的UART的时钟源的确有进行切换动作  SYSCLK->CLKSEL1.UART_S = 0

相关帖子

沙发
David_ming|  楼主 | 2010-10-21 16:48 | 只看该作者
单独跑timer也不成,IP的clock都需要22M的支持??

使用特权

评论回复
板凳
X-Hawk| | 2010-10-21 17:27 | 只看该作者
22M不是必须。
这个可能要结合代码看才能界定问题。楼主方便秀一下代码?

使用特权

评论回复
地板
yybj| | 2010-10-21 18:20 | 只看该作者
把代码贴出来看一下吧

使用特权

评论回复
5
David_ming|  楼主 | 2010-10-21 20:35 | 只看该作者
代码很简单,就在芯唐的demo里面的UNLOCKREG()后面加两句
SYSCLK->CLKSEL0.HCLK_S = 0;
SYSCLK->PWRCON.OSC22M_EN = 0;

明天早上我上最精简化可以直接编译的代码

使用特权

评论回复
6
X-Hawk| | 2010-10-21 20:39 | 只看该作者
CLKSEL1.UART_S 的设定,选用哪个clock当UART的clock呢?
如果关掉了22M, 又拿22M给UART用的话。。。。

使用特权

评论回复
7
金鱼木鱼| | 2010-10-21 23:00 | 只看该作者
看看数据手册上有没有说的

使用特权

评论回复
8
David_ming|  楼主 | 2010-10-22 09:30 | 只看该作者
本帖最后由 David_ming 于 2010-10-22 09:36 编辑

/*---------------------------------------------------------------------------------------------------------*/
/*                                                                                                         */
/* Copyright(c) 2009 Nuvoton Technology Corp. All rights reserved.                                         */
/*                                                                                                         */
/*---------------------------------------------------------------------------------------------------------*/
#include <stdio.h>
#include "NUC1xx.h"
#include "Driver/DrvUART.h"
#include "Driver/DrvRTC.h"
#include "Driver/DrvGPIO.h"
#include "Driver/DrvSYS.h"
/*---------------------------------------------------------------------------------------------------------*/
/* Global variables                                                                                        */
/*---------------------------------------------------------------------------------------------------------*/
volatile uint32_t  g_u32TICK = FALSE;
volatile int32_t   g_bAlarm  = FALSE;

/*---------------------------------------------------------------------------------------------------------*/
/* RTC Tick Callback function                                                                              */
/*---------------------------------------------------------------------------------------------------------*/
void DrvRTC_TickISR(void)
{
S_DRVRTC_TIME_DATA_T sCurTime;

/* Get the currnet time */
DrvRTC_Read(DRVRTC_CURRENT_TIME, &sCurTime);  

printf("Current Time:%d/%02d/%02d %02d:%02d:%02d\n",sCurTime.u32Year,sCurTime.u32cMonth,sCurTime.u32cDay,sCurTime.u32cHour,sCurTime.u32cMinute,sCurTime.u32cSecond);   

g_u32TICK++;
}


/*---------------------------------------------------------------------------------------------------------*/
/* RTC Alarm Callback function                                                                             */
/*---------------------------------------------------------------------------------------------------------*/
void DrvRTC_AlarmISR(void)
{

printf("Alarm!!\n");

g_bAlarm = TRUE;
}

static void TestItem (void)
{
    printf("\n\n");
    printf("+-----------------------------------------------------------+\n");
    printf("|                    RTC Sample Program                     |\n");
    printf("+-----------------------------------------------------------+\n");
    printf("| [0] Time Display Test                                     | \n");
    printf("| [1] Alarm Test                                            | \n");
    printf("+-----------------------------------------------------------+\n");
    printf("| [2] Quit                                                  |\n");
    printf("+-----------------------------------------------------------+\n");
    printf("Select key : \n");
}

void SysTimerDelay(uint32_t us)
{
    SysTick->LOAD = us * 22; /* Assume the internal 22MHz RC used */
    SysTick->VAL   =  (0x00);
    SysTick->CTRL = (1 << SYSTICK_CLKSOURCE) | (1<<SYSTICK_ENABLE);
    /* Waiting for down-count to zero */
    while((SysTick->CTRL & (1 << 16)) == 0);
}

/*---------------------------------------------------------------------------------------------------------*/
/* RTC Test Sample                                                                                */
/* Test Item                                                                                */
/*  1. Time Display Test                       */
/*    Use RTC Tick interrupt to display time every one second.                              */
/*  2. Alarm Test                         */
/*     Get the current and alarm after 10 seconds                 */
/*---------------------------------------------------------------------------------------------------------*/
int32_t main()           
{
unsigned int i;
S_DRVRTC_TIME_DATA_T sInitTime;
int32_t bLoop = TRUE;
uint8_t u8Item;

STR_UART_T sParam;

UNLOCKREG();
    SYSCLK->PWRCON.XTL12M_EN = 1;



for(i = 0; i < 0xffff; i++);
SYSCLK->CLKSEL0.HCLK_S = 0;
SYSCLK->PWRCON.OSC22M_EN = 0; //有这句就完蛋了






   /* Waiting for Xtal stalble */
    SysTimerDelay(5000);
/* UART Setting */
    sParam.u32BaudRate = 115200;
    sParam.u8cDataBits = DRVUART_DATABITS_8;
    sParam.u8cStopBits = DRVUART_STOPBITS_1;
    sParam.u8cParity   = DRVUART_PARITY_NONE;
    sParam.u8cRxTriggerLevel = DRVUART_FIFO_1BYTES;
/* Set UART Pin */
DrvGPIO_InitFunction(FUNC_UART0);
/* Set UART Configuration */
if(DrvUART_Open(UART_PORT0,&sParam) == E_SUCCESS)
{  
  /* RTC Initialize */
  DrvRTC_Init();
  
  /* Time Setting */
  sInitTime.u32Year   = 2009;
  sInitTime.u32cMonth  = 1;
  sInitTime.u32cDay   = 19;
  sInitTime.u32cHour   = 13;
  sInitTime.u32cMinute  = 20;
  sInitTime.u32cSecond  = 0;
  sInitTime.u32cDayOfWeek = DRVRTC_MONDAY;
  sInitTime.u8cClockDisplay = DRVRTC_CLOCK_24;   
  /* Initialization the RTC timer */
  if(DrvRTC_Open(&sInitTime) !=E_SUCCESS)
  {
   printf("RTC Open Fail!!\n");
   return FALSE;
  }  
  
  while(bLoop)
  {
   TestItem();
   u8Item = getchar();
   
   switch(u8Item)
   {
    case '0':
    {
     S_DRVRTC_TICK_T sTick;
     
     printf("\n0. RTC Time Display Test (Exit after 5 seconds)\n");
      
     /* Set Tick property */
     sTick.ucMode = DRVRTC_TICK_1_SEC;
     sTick.pfnTickCallBack = DrvRTC_TickISR;  
     
     /* Set Tick setting */
     DrvRTC_Ioctl(0,DRVRTC_IOC_SET_TICK_MODE, (uint32_t)&sTick,0);
     /* Enable RTC Tick Interrupt and install tick call back function */
     DrvRTC_Ioctl(0,DRVRTC_IOC_ENABLE_INT, (uint32_t)DRVRTC_TICK_INT,0);
     g_u32TICK = 0;
   
     NVIC_EnableIRQ(RTC_IRQn);
     while(g_u32TICK < 5);
     /* Disable RTC Tick Interrupt */
     DrvRTC_Ioctl(0,DRVRTC_IOC_DISABLE_INT, (uint32_t)DRVRTC_TICK_INT,0);      
     break;
    }
    case '1':
    {
     S_DRVRTC_TIME_DATA_T sCurTime;
     
     printf("\n1. DrvRTC Alarm Test (Alarm after 10 seconds)\n");
      
     g_bAlarm = FALSE;
   
     /* Get the currnet time */
     DrvRTC_Read(DRVRTC_CURRENT_TIME, &sCurTime);
   
     /* Set Alarm call back function */
     sCurTime.pfnAlarmCallBack = DrvRTC_AlarmISR;
     printf("Current Time:%d/%02d/%02d %02d:%02d:%02d\n",sCurTime.u32Year,sCurTime.u32cMonth,sCurTime.u32cDay,sCurTime.u32cHour,sCurTime.u32cMinute,sCurTime.u32cSecond);
     
     /* The alarm time setting */
     sCurTime.u32cSecond = sCurTime.u32cSecond + 10;  
     
     /* Set the alarm time (Install the call back function and enable the alarm interrupt)*/
     DrvRTC_Write(DRVRTC_ALARM_TIME,&sCurTime);
      
     NVIC_EnableIRQ(RTC_IRQn);
     
     while(!g_bAlarm);
     
     printf("Current Time:%d/%02d/%02d %02d:%02d:%02d\n",sCurTime.u32Year,sCurTime.u32cMonth,sCurTime.u32cDay,sCurTime.u32cHour,sCurTime.u32cMinute,sCurTime.u32cSecond);
        
     break;   
    }
    case '2':
     bLoop = FALSE;
     break;
    default:
     printf("Wrong Item\n");
     break;   
   }
   
  }
  
  /* Disable RTC Clock */  
  DrvRTC_Close();
  
  /* Disable UART Clock */
  DrvUART_Close(UART_PORT0);
  
  return TRUE;
}
else
  return FALSE;
}

使用特权

评论回复
9
David_ming|  楼主 | 2010-10-22 09:33 | 只看该作者
本帖最后由 David_ming 于 2010-10-22 09:34 编辑

上面一段是官方的RTC demo,其它的地方我没动,只是加上了中间那点,不知道是哪里出了问题:(

使用特权

评论回复
10
X-Hawk| | 2010-10-22 09:48 | 只看该作者
嗯,确定问题就是改了系统 clock, 没有告诉UART要用另外的clock,
请参考6楼

使用特权

评论回复
11
David_ming|  楼主 | 2010-10-22 09:54 | 只看该作者
我原来试过,加上也不行

        UNLOCKREG();
    SYSCLK->PWRCON.XTL12M_EN = 1;
        for(i = 0; i < 0xffff; i++);
        SYSCLK->CLKSEL0.HCLK_S = 0;
        __nop();
        __nop();
        SYSCLK->PWRCON.OSC22M_EN = 0;
        SYSCLK->CLKSEL1.UART_S = 0;

使用特权

评论回复
12
静默| | 2010-10-22 09:55 | 只看该作者
6楼是正解.....
   UNLOCKREG();
   SYSCLK->PWRCON.XTL12M_EN = 0;
   SYSCLK->CLKSEL1.UART_S = 0x03;

使用特权

评论回复
13
David_ming|  楼主 | 2010-10-22 09:57 | 只看该作者
各位大仙们能否也试试,我试了确实不行呀:(

使用特权

评论回复
14
David_ming|  楼主 | 2010-10-22 19:59 | 只看该作者
似乎BOD也需要内震10K的支持。。。。

使用特权

评论回复
15
David_ming|  楼主 | 2010-10-27 20:46 | 只看该作者
楼主把我的帖子删了吧,问了也白问:(

使用特权

评论回复
16
行不改名| | 2010-10-28 00:18 | 只看该作者
楼主不要太泄气了.如有人试过一定会说的,我改天试一下.

使用特权

评论回复
17
X-Hawk| | 2010-10-28 13:46 | 只看该作者
我试了一下,完全可以的。
楼主的SysTimerDelay的实现,依赖于SysTick,
SysTick要运行依赖于一个时钟。。。。就是22M, 然而楼主把22M关了。
所以加了一句将SysTick切换到12M的代码。

int32_t main()           
{
        unsigned int i;
        S_DRVRTC_TIME_DATA_T sInitTime;
        int32_t bLoop = TRUE;
        uint8_t u8Item;

        STR_UART_T sParam;

        UNLOCKREG();
    SYSCLK->PWRCON.XTL12M_EN = 1;
       
        for(i = 0; i < 0xffff; i++);
        SYSCLK->CLKSEL0.HCLK_S = 0;
        SYSCLK->CLKSEL0.STCLK_S = 0;
        SYSCLK->CLKSEL1.UART_S = 0;

        SYSCLK->PWRCON.OSC22M_EN = 0; //有这句也不会完蛋了

        /* Waiting for Xtal stalble */
    SysTimerDelay(5000);
        /* UART Setting */
    sParam.u32BaudRate = 115200;
    sParam.u8cDataBits = DRVUART_DATABITS_8;
    sParam.u8cStopBits = DRVUART_STOPBITS_1;
    sParam.u8cParity   = DRVUART_PARITY_NONE;
    sParam.u8cRxTriggerLevel = DRVUART_FIFO_1BYTES;
        /* Set UART Pin */
        DrvGPIO_InitFunction(E_FUNC_UART0);
        /* Set UART Configuration */
        if(DrvUART_Open(UART_PORT0,&sParam) == E_SUCCESS)
        {  
                printf("DrvUART_Open OK!!\n");
        }
        while(1);
}

使用特权

评论回复
18
金鱼木鱼| | 2010-10-29 18:30 | 只看该作者
学习了,我也试下

使用特权

评论回复
19
David_ming|  楼主 | 2010-10-30 12:04 | 只看该作者
多谢斑竹的提醒,经过“无数”次的折腾,问题确定了------即:切换UART的时钟源操作一定要在关闭22M内震之前完成,即使是已经将HCLK切换到12M外震而且外震已经稳定。

使用特权

评论回复
20
即时生效| | 2010-10-30 17:11 | 只看该作者
哦,学习了

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名::“哥洒脱如此”

22

主题

762

帖子

2

粉丝