打印
[DemoCode下载]

寄存器操作M051实现IO中断

[复制链接]
1667|15
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
heisexingqisi|  楼主 | 2016-4-28 21:09 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
寄存器操作M051实现IO中断
/**************************************************************************//**
* @file     main.c
* @version  V3.00
* $Revision: 3 $
* $Date: 14/04/03 9:18a $
* @brief    M051 Series GPIO Driver Sample Code
*
* @note
* Copyright (C) 2013 Nuvoton Technology Corp. All rights reserved.
******************************************************************************/
#include <stdio.h>
#include "M051Series.h"


#define PLLCON_SETTING      CLK_PLLCON_50MHz_HXT
#define PLL_CLOCK           50000000


/**
* @brief       Port0/Port1 IRQ
*
* @param       None
*
* @return      None
*
* @Details     The Port0/Port1 default IRQ, declared in startup_M051Series.s.
*/
void GPIOP0P1_IRQHandler(void)
{
    /* To check if P1.3 interrupt occurred */
    if(P1->ISRC & BIT3)
    {
        P1->ISRC = BIT3;
        printf("P1.3 INT occurred.\n");
    }
    else
    {
        /* Un-expected interrupt. Just clear all PORT0, PORT1 interrupts */
        P0->ISRC = P0->ISRC;
        P1->ISRC = P1->ISRC;
        printf("Un-expected interrupts.\n");
    }
}

/**
* @brief       Port2/Port3/Port4 IRQ
*
* @param       None
*
* @return      None
*
* @details     The Port2/Port3/Port4 default IRQ, declared in startup_M051Series.s.
*/
void GPIOP2P3P4_IRQHandler(void)
{
    /* To check if P4.5 interrupt occurred */
    if(P4->ISRC & BIT5)
    {
        P4->ISRC = BIT5;
        printf("P4.5 INT occurred.\n");
    }
    else
    {
        /* Un-expected interrupt. Just clear all PORT2, PORT3 and PORT4 interrupts */
        P2->ISRC = P2->ISRC;
        P3->ISRC = P3->ISRC;
        P4->ISRC = P4->ISRC;
        printf("Un-expected interrupts.\n");
    }
}

void SYS_Init(void)
{
    /*---------------------------------------------------------------------------------------------------------*/
    /* Init System Clock                                                                                       */
    /*---------------------------------------------------------------------------------------------------------*/

    /* Enable Internal RC 22.1184MHz clock */
    CLK->PWRCON |= CLK_PWRCON_OSC22M_EN_Msk;

    /* Waiting for Internal RC clock ready */
    while(!(CLK->CLKSTATUS & CLK_CLKSTATUS_OSC22M_STB_Msk));

    /* Switch HCLK clock source to Internal RC and and HCLK source divide 1 */
    CLK->CLKSEL0 &= ~CLK_CLKSEL0_HCLK_S_Msk;
    CLK->CLKSEL0 |= CLK_CLKSEL0_HCLK_S_HIRC;
    CLK->CLKDIV &= ~CLK_CLKDIV_HCLK_N_Msk;
    CLK->CLKDIV |= CLK_CLKDIV_HCLK(1);

    /* Enable external XTAL 12MHz clock */
    CLK->PWRCON |= CLK_PWRCON_XTL12M_EN_Msk;

    /* Waiting for external XTAL clock ready */
    while(!(CLK->CLKSTATUS & CLK_CLKSTATUS_XTL12M_STB_Msk));

    /* Set core clock as PLL_CLOCK from PLL */
    CLK->PLLCON = PLLCON_SETTING;
    while(!(CLK->CLKSTATUS & CLK_CLKSTATUS_PLL_STB_Msk));
    CLK->CLKSEL0 &= (~CLK_CLKSEL0_HCLK_S_Msk);
    CLK->CLKSEL0 |= CLK_CLKSEL0_HCLK_S_PLL;

    /* Update System Core Clock */
    /* User can use SystemCoreClockUpdate() to calculate PllClock, SystemCoreClock and CycylesPerUs automatically. */
    //SystemCoreClockUpdate();
    PllClock        = PLL_CLOCK;            // PLL
    SystemCoreClock = PLL_CLOCK / 1;        // HCLK
    CyclesPerUs     = PLL_CLOCK / 1000000;  // For SYS_SysTickDelay()

    /* Enable UART module clock */
    CLK->APBCLK |= CLK_APBCLK_UART0_EN_Msk;

    /* Select UART module clock source */
    CLK->CLKSEL1 &= ~CLK_CLKSEL1_UART_S_Msk;
    CLK->CLKSEL1 |= CLK_CLKSEL1_UART_S_PLL;

    /*---------------------------------------------------------------------------------------------------------*/
    /* Init I/O Multi-function                                                                                 */
    /*---------------------------------------------------------------------------------------------------------*/

    /* Set P3 multi-function pins for UART0 RXD and TXD */
    SYS->P3_MFP &= ~(SYS_MFP_P30_Msk | SYS_MFP_P31_Msk);
    SYS->P3_MFP |= (SYS_MFP_P30_RXD0 | SYS_MFP_P31_TXD0);

}

void UART0_Init()
{
    /*---------------------------------------------------------------------------------------------------------*/
    /* Init UART                                                                                               */
    /*---------------------------------------------------------------------------------------------------------*/
    /* Reset UART IP */
    SYS->IPRSTC2 |=  SYS_IPRSTC2_UART0_RST_Msk;
    SYS->IPRSTC2 &= ~SYS_IPRSTC2_UART0_RST_Msk;

    /* Configure UART0 and set UART0 Baudrate */
    UART0->BAUD = UART_BAUD_MODE2 | UART_BAUD_MODE2_DIVIDER(PLL_CLOCK, 115200);
    UART0->LCR = UART_WORD_LEN_8 | UART_PARITY_NONE | UART_STOP_BIT_1;
}

/*---------------------------------------------------------------------------------------------------------*/
/* MAIN function                                                                                           */
/*---------------------------------------------------------------------------------------------------------*/
int main(void)
{
    /* Unlock protected registers */
    SYS->REGWRPROT = 0x59;
    SYS->REGWRPROT = 0x16;
    SYS->REGWRPROT = 0x88;

    /* Init System, peripheral clock and multi-function I/O */
    SYS_Init();

    /* Lock protected registers */
    SYS->REGWRPROT = 0x0;

    /* Init UART0 for printf */
    UART0_Init();

    printf("\n\nCPU @ %d Hz\n", SystemCoreClock);
    printf("+------------------------------------------------+\n");
    printf("|    GPIO P1.3 and P4.5 Interrupt Sample Code    |\n");
    printf("+------------------------------------------------+\n\n");

    /*-----------------------------------------------------------------------------------------------------*/
    /* GPIO Interrupt Function Test                                                                        */
    /*-----------------------------------------------------------------------------------------------------*/
    printf("P1.3 and P4.5 are used to test interrupt ......\n");

    /* Configure P1.3 as Input mode and enable interrupt by rising edge trigger */
    P1->PMD = P1->PMD & (~GPIO_PMD_PMD3_Msk) | (GPIO_PMD_INPUT << GPIO_PMD_PMD3_Pos);
    P1->IMD |= (GPIO_IMD_EDGE << 3);
    P1->IEN |= (BIT3 << GPIO_IEN_IR_EN_Pos);
    NVIC_EnableIRQ(GPIO_P0P1_IRQn);

    /*  Configure P4.5 as Quasi-bidirection mode and enable interrupt by falling edge trigger */
    P4->PMD = P1->PMD & (~GPIO_PMD_PMD5_Msk) | (GPIO_PMD_QUASI << GPIO_PMD_PMD5_Pos);
    P4->IMD |= (GPIO_IMD_EDGE << 5);
    P4->IEN |= (BIT5 << GPIO_IEN_IF_EN_Pos);
    NVIC_EnableIRQ(GPIO_P2P3P4_IRQn);

    /* Waiting for interrupts */
    while(1);
}

/*** (C) COPYRIGHT 2013 Nuvoton Technology Corp. ***/




沙发
heisexingqisi|  楼主 | 2016-4-28 21:11 | 只看该作者
实际上就是把库函数内容展开来实现的。

使用特权

评论回复
板凳
heisexingqisi|  楼主 | 2016-4-28 21:12 | 只看该作者
对于一些固定的函数,可以通过宏的形式来实现,而且更加高效。避免了函数调用。

使用特权

评论回复
地板
zhuotuzi| | 2016-4-28 23:34 | 只看该作者
  /* Select UART module clock source */
    CLK->CLKSEL1 &= ~CLK_CLKSEL1_UART_S_Msk;
    CLK->CLKSEL1 |= CLK_CLKSEL1_UART_S_PLL;
设置时钟,怎么还需要两行啊,看前面的部分是同一个寄存器啊。

使用特权

评论回复
5
heisexingqisi|  楼主 | 2016-4-29 17:01 | 只看该作者
zhuotuzi 发表于 2016-4-28 23:34
/* Select UART module clock source */
    CLK->CLKSEL1 &= ~CLK_CLKSEL1_UART_S_Msk;
    CLK->CLKSEL ...

是的啊,需要看看数据手册关于这个寄存器的就知道了。

使用特权

评论回复
6
gejigeji521| | 2016-4-29 21:56 | 只看该作者
/* Unlock protected registers */
    SYS->REGWRPROT = 0x59;
    SYS->REGWRPROT = 0x16;
    SYS->REGWRPROT = 0x88;

    /* Init System, peripheral clock and multi-function I/O */
    SYS_Init();
这两句其实直接写到一个里面就像了。

使用特权

评论回复
7
huangcunxiake| | 2016-4-29 22:23 | 只看该作者
/* Enable external XTAL 12MHz clock */
    CLK->PWRCON |= CLK_PWRCON_XTL12M_EN_Msk;
这个是意思外部接了个12MHz的晶振吗

使用特权

评论回复
8
玛尼玛尼哄| | 2016-4-30 11:07 | 只看该作者
/* Init System, peripheral clock and multi-function I/O */
    SYS_Init();
这个里面就是配置系统时钟还有管脚的功能选择。

使用特权

评论回复
9
玛尼玛尼哄| | 2016-4-30 11:07 | 只看该作者
好多如果可以通过预编译指令,写的形象化点就好了,总是看到一堆的寄存器头晕

使用特权

评论回复
10
天灵灵地灵灵| | 2016-4-30 12:30 | 只看该作者
SYS->REGWRPROT = 0x59;
    SYS->REGWRPROT = 0x16;
    SYS->REGWRPROT = 0x88;
这三个我没有看错的话,前面是一样的,难道一直写三个数字,就OK?

使用特权

评论回复
11
捉虫天师| | 2016-4-30 14:13 | 只看该作者
IO中断一般只要配置好方向和中断使能就可以了。

使用特权

评论回复
12
捉虫天师| | 2016-4-30 15:00 | 只看该作者
时钟控制器为整个芯片提供时钟,包括系统时钟和所有外设时钟。时钟控制器还利用独立的时钟
ON/OFF控制、时钟源选择和4位时钟分频器,实现电源控制功能。在CPU置位掉电模式使能位
(PWR_DOWN_EN)且Cortex-M0核执行WFI指令之前,芯片不会进入掉电模式,在那之后,芯片进入掉
电模式并等待唤醒中断源被触发以离开掉电模式。在掉电模式下,控制器关闭外部高速晶振和内部
22.1184MHz高速振荡器,以降低整体系统功耗。

使用特权

评论回复
13
捉虫天师| | 2016-4-30 15:01 | 只看该作者
时钟发生器由如下4个时钟源组成:
„  一个外部  4~24 MHz 高速晶振
„  一个内部 22.1184 MHz RC高速 振荡器
„  一个可编程的 PLL FOUT(PLL由外部4~24MHz高速晶振和内部22.1184MHz高速振荡器组成)
„  一个内部 10KHz 低速振荡器

使用特权

评论回复
14
捉虫天师| | 2016-4-30 15:01 | 只看该作者
掉电模式 时钟
当芯片进入掉电模式后,大部分时钟源、外设时钟和系统时钟将会被禁用,也有一些时钟源与外设时钟
仍处于激活状态。
如下这些时钟仍然保持激活:  
z  时钟发生器
„  内部 10K 低速振荡器时钟
z  外设时钟 (当这些IP采用内部10KHz低速振荡器作时钟源时)
„  看门狗时钟
„ Timer 0/1/2/3 时钟
„ PWM 时钟

使用特权

评论回复
15
捉虫天师| | 2016-4-30 15:02 | 只看该作者
分频器输出
该设备包含一个由16级2分频移位寄存器组成的分频器。其中哪一级的值被输出由一个16选1的多路转
换器选择,并被映射到P3.6。所以有16种以2为幂的时钟分频选择,频率从 Fin/21 到Fin/217,其中 Fin
为输入到时钟分频器的时钟频率。

使用特权

评论回复
16
heisexingqisi|  楼主 | 2016-5-11 23:29 | 只看该作者
NVIC_EnableIRQ(GPIO_P0P1_IRQn);
NVIC_EnableIRQ(GPIO_P2P3P4_IRQn);
这两个是最后启动中断用的吗

使用特权

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

本版积分规则

128

主题

2581

帖子

2

粉丝