打印
[DemoCode下载]

基于寄存器操作的IO输出

[复制链接]
397|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
xixi2017|  楼主 | 2019-9-26 23:53 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
/**************************************************************************//**
* [url=home.php?mod=space&uid=288409]@file[/url]     main.c
* [url=home.php?mod=space&uid=895143]@version[/url]  V3.00
* $Revision: 7 $
* $Date: 15/07/13 1:27p $
* [url=home.php?mod=space&uid=247401]@brief[/url]    Show how to set GPIO pin mode and use pin data input/output control.
*
* @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


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 HCLK source divide 1 */
    CLK->CLKSEL0 = (CLK->CLKSEL0 & (~CLK_CLKSEL0_HCLK_S_Msk)) | CLK_CLKSEL0_HCLK_S_HIRC;
    CLK->CLKDIV = (CLK->CLKDIV & (~CLK_CLKDIV_HCLK_N_Msk)) | CLK_CLKDIV_HCLK(1);

    /* Set PLL to Power down mode and HW will also clear PLL_STB bit in CLKSTATUS register */
    CLK->PLLCON |= CLK_PLLCON_PD_Msk;   
   
    /* 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 & (~CLK_CLKSEL0_HCLK_S_Msk)) | 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 CLK_SysTickDelay()

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

    /* Select UART module clock source */
    CLK->CLKSEL1 = (CLK->CLKSEL1 & (~CLK_CLKSEL1_UART_S_Msk)) | 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 UART0 */
    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)
{
    int32_t i32Err;

    /* Unlock protected registers */
    SYS_UnlockReg();

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

    /* Lock protected registers */
    SYS_LockReg();

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

    printf("\n\nCPU [url=home.php?mod=space&uid=72445]@[/url] %d Hz\n", SystemCoreClock);
    printf("+-------------------------------------------------+\n");
    printf("|    P1.2(Output) and P4.1(Input) Sample Code     |\n");
    printf("+-------------------------------------------------+\n\n");

    /* Configure P1.2 as Output mode and P4.1 as Input mode then close it */
    P1->PMD = (P1->PMD & (~GPIO_PMD_PMD2_Msk)) | (GPIO_PMD_OUTPUT << GPIO_PMD_PMD2_Pos);
    P4->PMD = (P4->PMD & (~GPIO_PMD_PMD1_Msk)) | (GPIO_PMD_INPUT << GPIO_PMD_PMD1_Pos);

    i32Err = 0;
    printf("GPIO P1.2(output mode) connect to P4.1(input mode) ......");

    /* Use Pin Data Input/Output Control to pull specified I/O or get I/O pin status */
    P12 = 0;
    if(P41 != 0)
    {
        i32Err = 1;
    }

    P12 = 1;
    if(P41 != 1)
    {
        i32Err = 1;
    }

    if(i32Err)
    {
        printf("  [FAIL].\n");
    }
    else
    {
        printf("  [OK].\n");
    }

    /* Configure P1.2 and P4.1 to default Quasi-bidirectional mode */
    P1->PMD = (P1->PMD & (~GPIO_PMD_PMD2_Msk)) | (GPIO_PMD_QUASI << GPIO_PMD_PMD2_Pos);
    P4->PMD = (P4->PMD & (~GPIO_PMD_PMD1_Msk)) | (GPIO_PMD_QUASI << GPIO_PMD_PMD1_Pos);

    while(1);
}

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


使用特权

评论回复
沙发
xixi2017|  楼主 | 2019-9-26 23:53 | 只看该作者
ARM单片机的IO操作其实非常简单。

使用特权

评论回复
板凳
幸福小强| | 2019-9-27 21:42 | 只看该作者
很好懂的样子。新唐的库函数和头文件都做的很好。

使用特权

评论回复
地板
598330983| | 2019-9-28 18:27 | 只看该作者
多功能选择配置。

使用特权

评论回复
5
小灵通2018| | 2019-9-28 21:03 | 只看该作者
好多的逻辑位操作。

使用特权

评论回复
6
eyu66| | 2019-9-29 08:56 | 只看该作者
我是寄存器名称都不用,直接粗爆的操作寄存器地址,是不是没救了
比如类似下面这一句:
CLK->CLKSEL0 = (CLK->CLKSEL0 & (~CLK_CLKSEL0_HCLK_S_Msk)) | CLK_CLKSEL0_HCLK_S_HIRC;

我的写法基本是:
unsigned int *pCLK_CLKSEL0 = (unsigned int *)(0x40000200 + 0x10);
*pCLK_CLKSEL0 &= ~0x00000100;   *pCLK_CLKSEL0 |= 0x00000100;

使用特权

评论回复
7
xixi2017|  楼主 | 2019-9-29 10:21 | 只看该作者
eyu66 发表于 2019-9-29 08:56
我是寄存器名称都不用,直接粗爆的操作寄存器地址,是不是没救了?
比如类似下面这一句:
CLK->CLKS ...

这种才是原生态,比较生猛。你太牛了。

使用特权

评论回复
8
john_lee| | 2019-9-29 13:29 | 只看该作者
我对位操作比较来气,就这样写了:
  RCC.CR().HSION(true);                         // Set HSION bit
  RCC.CFGR().SW(rcc::sw_t::HSI)                 // HSI Selected as System Clock source
            .HPRE(rcc::hpre_t::DIV1)            // HCLK = SYSCLK
            .PPRE1(rcc::ppre_t::DIV1)           // PCLK1 = HCLK
            .PPRE2(rcc::ppre_t::DIV1)           // PCLK2 = HCLK
            .ADCPRE(rcc::adcpre_t::DIV2)        // Reset ADCPRE bit
            .MCO(rcc::mco_t::NONE);             // Reset MCO bit
  RCC.CR().HSEON(false)                         // Reset HSEON bit
          .HSEBYP(false)                        // Reset HSEBYP bit
          .CSSON(false)                         // Reset CSSON bit
          .PLLON(false);                        // Reset PLLON bit

使用特权

评论回复
评论
xixi2017 2019-9-29 18:28 回复TA
这是高手。 
9
xixi2017|  楼主 | 2019-9-29 18:28 | 只看该作者
john_lee 发表于 2019-9-29 13:29
我对位操作比较来气,就这样写了:

这种写法我还真不会,是定义的宏还是C语言本身的功能?

使用特权

评论回复
10
john_lee| | 2019-9-30 12:01 | 只看该作者
xixi2017 发表于 2019-9-29 18:28
这种写法我还真不会,是定义的宏还是C语言本身的功能?

C++

使用特权

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

本版积分规则

115

主题

1700

帖子

1

粉丝