zoukankan      html  css  js  c++  java
  • TKStudioLPC1220_GPIO_LED工程后记

    2013年3月29日 23:42:24

    • 工程的main.c函数如下.
       1: /*
       2:     头文件包含
       3: */
       4: #include "lpc12xx_libcfg.h"
       5:  
       6: /*********************************************************************************************************
       7:   宏定义
       8: *********************************************************************************************************/
       9: #define LED_PORT    LPC_GPIO1                                           /* LED引脚端口P1                */
      10: #define LED_PINS    2                                                   /* LED引脚P1.2                  */
      11:  
      12: /*********************************************************************************************************
      13:   全局变量定义
      14: *********************************************************************************************************/
      15: static uint16_t GusGPIO1Port[7] = {                                     /* GPIO1端口引脚类型            */
      16:     IOCON_PIO_1_0,
      17:     IOCON_PIO_1_1,
      18:     IOCON_PIO_1_2,
      19:     IOCON_PIO_1_3,
      20:     IOCON_PIO_1_4,
      21:     IOCON_PIO_1_5,
      22:     IOCON_PIO_1_6
      23: };
      24:  
      25: void myDelay (uint32_t ulTime)    //软件延时
      26: {
      27:     uint32_t i = 0;
      28:     
      29:     while (ulTime--) {
      30:         for (i = 0; i < 5000; i++);
      31:     }
      32: }
      33:  
      34: void ledOn (void) // 点亮LED(输出低电平)
      35: {
      36:     GPIO_SetLowLevel(LED_PORT, LED_PINS, ENABLE);                       /* 输出低电平,点亮LED          */
      37: }
      38:  
      39:  
      40: void ledOff (void)//Descriptions:        熄灭LED(输出高电平)
      41: {
      42:     GPIO_SetHighLevel(LED_PORT, LED_PINS, ENABLE);                      /* 输出高电平,熄灭LED          */
      43: }
      44:  
      45:  
      46: void ledInit (void)        //Descriptions:        LED初始化
      47: {
      48:     IOCON_PIO_CFG_Type PIO_mode;
      49:  
      50:     IOCON_StructInit(&PIO_mode);                                        /* 初始化端口模式               */
      51:     PIO_mode.type = GusGPIO1Port[LED_PINS];
      52:     IOCON_SetFunc(&PIO_mode);                                           /* 设置LED引脚为GPIO功能        */
      53:  
      54:     GPIO_SetDir(LED_PORT, LED_PINS, GPIO_DIR_OUTPUT);                   /* 设置LED引脚为输出            */
      55:     
      56:     ledOff();                                                           /* 熄灭LED                      */
      57: }
      58:  
      59:  
      60: int main (void)                // 运行程序,观察LED1状态.LED1以约200ms为周期闪烁
      61: {
      62:     SystemInit();                                                       /* 系统时钟初始化               */
      63:     SYS_ConfigAHBCLK(SYS_AHBCLKCTRL_IOCON, ENABLE);                     /* IOCON模块使能                */
      64:     SYS_ConfigAHBCLK(SYS_AHBCLKCTRL_GPIO1, ENABLE);                     /* GPIO1时钟使能                */
      65:  
      66:     ledInit();                                                          /* LED初始化                    */
      67:  
      68:     while(1) {
      69:         ledOn();
      70:         myDelay(100);
      71:         ledOff();
      72:         myDelay(200); 
      73:     } 
      74: }
      75:  
      76: #ifdef  DEBUG
      77: /*********************************************************************************************************
      78: ** Function name:       check_failed
      79: ** Descriptions:
      80: ** input parameters:    无
      81: ** output parameters:   无
      82: ** Returned value:      无
      83: *********************************************************************************************************/
      84: void check_failed (uint8_t *file, uint32_t line)
      85: {
      86:     while(1);                                                           /* Infinite loop                */
      87: }
      88: #endif

    一.程序总体流程:

    • 系统时钟初始化:
    • IOCON模块使能
    • GPIO1时钟使能
    • LED初始化
    • 死循环:灯闪烁(一亮一灭)

    二.硬件实物图:

    image

    三.硬件原理图

    文件位置(E:\kpan\Desktop\LPC\硬件原理图TinyM0_T12_ku\TinyM0 T12M原理图与器件封装库\TinyM0 T12M原理图)

    (原理图下载地址:【硬件资料】TinyM0 T12(M)原理图与器件封装库 [出处 2-25 2418次])

    imageimageimageimageimage

    LED引脚的定义:

    在main.c中有,

    #define LED_PORT    LPC_GPIO1                                   /* LED引脚端口P1                */
    #define LED_PINS    2                                                   /* LED引脚P1.2                  */

    在lpc12xx.h中有,

    #define LPC_GPIO1             ((LPC_GPIO_TypeDef   *) LPC_GPIO1_BASE )

    #define LPC_GPIO2_BASE        (LPC_AHB_BASE  + 0x20000)

    #define LPC_AHB_BASE          (0x50000000UL)

    这样就可以对引脚P1.2进行寻址了.


    附:

    在,(0x50000000UL) 中UL的意思是: unsigned long int.


    四.部分程序解释

    (1)全局变量的定义.


    static uint16_t GusGPIO1Port[7] = {                                     /* GPIO1端口引脚类型            */
        IOCON_PIO_1_0,
        IOCON_PIO_1_1,
        IOCON_PIO_1_2,
        IOCON_PIO_1_3,
        IOCON_PIO_1_4,
        IOCON_PIO_1_5,
        IOCON_PIO_1_6
    };


    在lpc_12xxiocon.h中有,

    #define IOCON_PIO_1_0     ((uint16_t)0x0BC1 )   /* PIO port1 type definition */

    2013年3月30日 00:30:12


    2013年3月30日 10:49:59

    (2)


    SystemInit();

    系统初始化函数,在system_lpc12xx.c中

    (3)


        SYS_ConfigAHBCLK(SYS_AHBCLKCTRL_IOCON, ENABLE);     /* IOCON模块使能                */
        SYS_ConfigAHBCLK(SYS_AHBCLKCTRL_GPIO1, ENABLE);      /* GPIO1时钟使能                */


    系统_配置外围模块时钟的使能,在Lpc12xx_syscrtl.c中

       1: /**
       2:   * @brief  使能或者禁止系统和外围时钟.
       3:                 Disable or enable system and peripheral clock.
       4:   *
       5:   * @param  AHBClk_Type: 外围模块时钟类型,AHB clock type.
       6:   * @param  CmdState:使能/禁止 Enable or disable the clock for System or 
       7:   *                      peripheral blocks.  
       8:   *         This parameter can be ENABLE or DISABLE.  
       9:   * @retval None.
      10:   */                
      11: void SYS_ConfigAHBCLK(uint32_t AHBClk_Type, FunctionalState CmdState)
      12: {
      13:     if(CmdState) LPC_SYSCON->SYSAHBCLKCTRL |= AHBClk_Type;
      14:     else LPC_SYSCON->SYSAHBCLKCTRL &= ~(AHBClk_Type);
      15: }

    (4)


    GPIO_SetLowLevel(LED_PORT, LED_PINS, ENABLE);                       /* 输出低电平,点亮LED          */

      GPIO_SetHighLevel(LED_PORT, LED_PINS, ENABLE);                      /* 输出高电平,熄灭LED          */


    设置GPIO口为高电平还是低电平,(根据原理图,低电平点亮LED)

    在Lpc12xx_gpio.c中,

       1: /**
       2:   * @brief       Set Value for bits that have output direction on GPIO port.
       3:                    设置GPIO端口的输出值.
       4:   * @param pGPIO      LPC_GPIOn 哪个GPIO
       5:                           Port Number selection, should be LPC_GPIO0, LPC_GPIO1, LPC_GPIO2
       6:   * @param bitPosi    n 哪个引脚号
       7:                           bit position value, should be from 0 to 31, if it is oxff, set 'value'
       8:   * @param value        值:0/1
       9:                                    if bitPosi is from 0 to 31, Direction value, should be:
      10:   *                              - 0: no effect
      11:   *                              - 1: high level.
      12:   *                             if bitPosi is oxff, set the all 32-bits of register
      13:   * @return                  None
      14:   *
      15:   * Note:
      16:   * - For all bits that has been set as input direction, this function will
      17:   * not effect.
      18:   * - For all remaining bits that are not activated in bitValue (value '0')
      19:   * will not be effected by this function.
      20:   */
      21: void GPIO_SetHighLevel(LPC_GPIO_TypeDef* pGPIO, uint8_t bitPosi, uint32_t value)
      22: {
      23:     CHECK_PARAM(PARAM_GPIOx(pGPIO));
      24:  
      25:     gpio_setvalue((uint32_t *)&pGPIO->SET, bitPosi, value);
      26: }
      27:  
      28: /**
      29:   * @brief    Clear Value for bits that have output direction on GPIO port.
      30:   * @param pGPIO       Port Number selection, should be LPC_GPIO0, LPC_GPIO1, LPC_GPIO2
      31:   * @param bitPosi       bit position value, should be from 0 to 31, if it is oxff, set 'value'
      32:   * @param value        if bitPosi is from 0 to 31, Direction value, should be:
      33:   *                              - 0: No effect.
      34:   *                              - 1: low level.
      35:   *                             if bitPosi is oxff, set the all 32-bits of register
      36:   * @return  None
      37:   *
      38:   * Note:
      39:   * - For all bits that has been set as input direction, this function will
      40:   * not effect.
      41:   * - For all remaining bits that are not activated in bitValue (value '0')
      42:   * will not be effected by this function.
      43:   */
      44: void GPIO_SetLowLevel(LPC_GPIO_TypeDef* pGPIO, uint8_t bitPosi, uint32_t value)
      45: {
      46:     CHECK_PARAM(PARAM_GPIOx(pGPIO));
      47:  
      48:     gpio_setvalue((uint32_t *)&pGPIO->CLR, bitPosi, value);   
      49: }
    • 在这里的CHECK_PARM用于检查某个函数的参数检查,在Lpc12xx_libcfg.h中有,
       1: #ifdef  DEBUG
       2: /*******************************************************************************
       3: * @brief  这个函数用于某个函数的参数检查,只在DEBUG模式下编译时使用.
       4: *         The CHECK_PARAM macro is used for function's parameters check.
       5: *                 It is used only if the library is compiled in DEBUG mode.
       6: * @param[in]   表达式,如果表达式为假,调用参数检查失败(check_failed.)函数
       7: *  expr - If expr is false, it calls check_failed() function
       8: *                        which reports the name of the source file and the source
       9: *                        line number of the call that failed.
      10: *                    - If expr is true, it returns no value.
      11: * @return        None
      12: *******************************************************************************/
      13: #define CHECK_PARAM(expr) ((expr) ? (void)0 : check_failed((uint8_t *)__FILE__, __LINE__))
      14: #else
      15: #define CHECK_PARAM(expr)

    16: #endif /* DEBUG */

       1: #define PARAM_GPIOx(n)  ((((uint32_t *)n)==((uint32_t *)LPC_GPIO0)) || \
       2:                          (((uint32_t *)n)==((uint32_t *)LPC_GPIO1)) || \
       3:                          (((uint32_t *)n)==((uint32_t *)LPC_GPIO2)))
       4:  
       5: volatile uint32_t GPIOShadowPort[3];

    这里的关键是调用了这个函数:

       1:  
       2: /**
       3:   * @brief    Set GPIO register.
       4:   * @param pGPIO         LPC_GPIOn     Port Number selection, should be LPC_GPIO0, LPC_GPIO1, LPC_GPIO2
       5:   * @param offset        寄存器的偏移值    Register offset value.  
       6:   * @param bitPosi       操作比特位/直接设置值    bit position value, should be from 0 to 31, if it is oxff, set 'value'
       7:   * @param value        如果操作比特位,那么值为0/1
       8:   *                                      if bitPosi is from 0 to 31, Direction value, should be:
       9:   *                              - 0: no mask.
      10:   *                              - 1: mask.
      11:   *                             if bitPosi is oxff, set the all 32-bits of register
      12:   * @return  None
      13:   *
      14:   * Note: All remaining bits that are not activated in bitValue (value '0')
      15:   * will not be effected by this function.
      16:   */
      17: static void gpio_setvalue(uint32_t *p, uint8_t bitPosi, uint32_t value)
      18: {
      19:     CHECK_PARAM(( bitPosi < 0x20 ) || ( bitPosi == 0xFF )); 
      20:     CHECK_PARAM(( value == 0 ) || ( value == 1 ));
      21:     
      22:     if(bitPosi < 0x20){
      23:         if (value) {
      24:             *(uint32_t *)p |= (0x1<<bitPosi);
      25:         }
      26:         else {
      27:             *(uint32_t *)p &= ~(0x1<<bitPosi);
      28:         }
      29:     }
      30:     else if(bitPosi == 0xFF){
      31:         *(uint32_t *)p = value;
      32:     }
      33: }

    调用关系:

    GPIO_SetLowLevel(LED_PORT, LED_PINS, ENABLE);                  LedOn()            main.c

       |-CHECK_PARAM(PARAM_GPIOx(pGPIO));                                   

       |-gpio_setvalue((uint32_t *)&pGPIO->CLR, bitPosi, value);  

    (5)设置IOCON_PIOn_m的值

    LED引脚的寄存器 在 E:\kpan\Desktop\LPC\LPC1200系列微控制器产品数据手册(英) LPC1200_ds_en page112页.

    6.4.48 PIO1_2 register

    image

    (6)LED初始化函数


    void ledInit (void)
    {
    IOCON_PIO_CFG_Type PIO_mode;

    IOCON_StructInit(&PIO_mode); /* 初始化端口模式 */
    PIO_mode.type = GusGPIO1Port[LED_PINS];
    IOCON_SetFunc(&PIO_mode); /* 设置LED引脚为GPIO功能 */

    GPIO_SetDir(LED_PORT, LED_PINS, GPIO_DIR_OUTPUT); /* 设置LED引脚为输出 */

    ledOff(); /* 熄灭LED */
    }


    分析:

    第一句,IOCON_PIO_CFG_Type PIO_mode;定义了一个IO引脚配置的结构体,描述了上面的  6.4.48 PIO1_2 register 的值.

    typedef struct {
        uint16_t    type;     /*!< low 8 bits is address offset, other is func >
                                                     This parameter can be a value of @ref PIO_type */
        uint8_t     pinmode;  /*!<  Pin mode >
                                                     This parameter can be a value of @ref PIO_pin_mode */
        uint8_t     invert;   /*!<  Inverted function >
                                                     This parameter can be a value of @ref Invert_input_mode */
        uint8_t     ad;       /*!<  analog/digital mode >
                                                     This parameter can be a value of @ref Analog_digital_mode */
        uint16_t    pmode;    /*!<  Push/pull mode for I2C >
                                                     This parameter can be a value of @ref Push_Pull_mode */
        uint16_t    od;       /*!<  Open drive >
                                                     This parameter can be a value of @ref Open_drain_mode */
        uint16_t    drive;    /*!<  Pin driver function >
                                                     This parameter can be a value of @ref Drive_current_mode */
        uint16_t    sm;       /*!<  Sample mode >
                                                     This parameter can be a value of @ref Sample_mode */
        uint32_t    cd;       /*!<  Clock Divider >
                                                     This parameter can be a value of @ref clock_divider_num */
    } IOCON_PIO_CFG_Type;

    第二句,IOCON_StructInit(&PIO_mode);  使用默认值来初始化了结构体.

    void IOCON_StructInit ( IOCON_PIO_CFG_Type *mode)
    {
       mode->type = 0x0;
       mode->pinmode = IOCON_PIO_MODE_PULLUP;
       mode->invert = IOCON_PIO_INV_NOT;
       mode->pmode = IOCON_PIO_PMODE_DISABLE;
       mode->od = IOCON_PIO_OD_DISABLE;
       mode->drive = IOCON_PIO_DRV_2MA_12MA;
       mode->ad = IOCON_PIO_AD_DIGITAL;
       mode->sm = IOCON_PIO_SMODE_BYPASS;
       mode->cd = IOCON_PIO_CLKDIV_0;
    }

    第三句,PIO_mode.type = GusGPIO1Port[LED_PINS];设置结构体的type成员的值

    PIO_mode.type = GusGPIO1Port[LED_PINS];

    LED_PINS=2,那么根据定义的数组

    static uint16_t GusGPIO1Port[7] = {                                     /* GPIO1端口引脚类型            */
        IOCON_PIO_1_0,
        IOCON_PIO_1_1,
        IOCON_PIO_1_2,
        IOCON_PIO_1_3,
        IOCON_PIO_1_4,
        IOCON_PIO_1_5,
        IOCON_PIO_1_6
    };

    有PIO_mode.type =IOCON_PIO_1_2  ,

    根据宏定义

    #define IOCON_PIO_1_2 ((uint16_t)0x0C40 )

    所以,最后有,IO引脚结构体type成员变量为

    PIO_mode.type=0x0C40

    第四句,IOCON_SetFunc(&PIO_mode); /* 设置LED引脚为GPIO功能 */

    根据结构体指针来设置引脚的功能

    void IOCON_SetFunc ( IOCON_PIO_CFG_Type *mode)
    {
        uint32_t offset;
        uint32_t func; 
        uint32_t tmp;
        uint32_t *p = (uint32_t *)&LPC_IOCON->PIO2_28;

        CHECK_PARAM( PARAM_IOCON_PIO_TYPE(mode->type) );
        CHECK_PARAM( PARAM_IOCON_PIO_MODE(mode->pinmode));
        CHECK_PARAM( PARAM_IOCON_PIO_DRV(mode->drive) );
        CHECK_PARAM( PARAM_IOCON_PIO_AD(mode->ad) );
        CHECK_PARAM( PARAM_IOCON_PIO_OD(mode->od));  
        CHECK_PARAM( PARAM_IOCON_PIO_INV(mode->invert) );
        CHECK_PARAM( PARAM_IOCON_PIO_SMODE(mode->sm));
        CHECK_PARAM( PARAM_IOCON_PIO_CLKDIV(mode->cd));

        offset = (mode->type >> 6);
        func = (mode->type & 0xf);

        if(offset == 0x24 || offset == 0x25){ //0x90, 0x94 right shift 2 bit
           tmp = (uint32_t)(func|(mode->pmode)|(mode->od)|(mode->invert)|(mode->sm)|(mode->cd));

        }else{
           tmp = (uint32_t)(func|(mode->pinmode)|(mode->drive)|(mode->ad)|(mode->od)|(mode->invert)|(mode->sm)|(mode->cd));
        }
        *(uint32_t *)(p + offset) = tmp;
    }

    第五句,GPIO_SetDir(LED_PORT, LED_PINS, GPIO_DIR_OUTPUT);     设置端口方向,输出

    /**
      * @brief       Set Direction for GPIO port.
      * @param pGPIO    Port Number selection, should be LPC_GPIO0, LPC_GPIO1, LPC_GPIO2
      * @param bitPosi       bit position value, should be from 0 to 31, if it is oxff, set 'value'
      * @param value        if bitPosi is from 0 to 31, Direction value, should be:
      *                             - 0: Input.
      *                             - 1: Output.
      *                             if bitPosi is oxff, set the all 32-bits of register
      * @return      None
      *
      * Note: All remaining bits that are not activated in bitValue (value '0')
      * will not be effected by this function.
      */
    void GPIO_SetDir(LPC_GPIO_TypeDef* pGPIO, uint8_t bitPosi, uint32_t value)
    {
        CHECK_PARAM(PARAM_GPIOx(pGPIO));

        gpio_setvalue((uint32_t *)&pGPIO->DIR, bitPosi, value);      
     
    }

    第六句,LedOff(),灯灭.

    2013年3月30日 17:13:44


  • 相关阅读:
    CentOS系统一键部署jdk,maven,tomcat,mysql
    使用sed在源文件上直接替换某一行的内容,只替换第一次找到的那行
    MLPerf 机器学习基准测试实战入门(一)NAVIDA-GNMT
    SpringBoot Controller接收参数的几种常用方式(转)
    使用延时队列DelayQueue
    Oracle、MySql、SQLServer 数据分页查询(转)
    SqlServer收缩日志
    防火墙升级导致产环境服务中止20小时的问题
    NFS相关
    jquery.validate不使用submit提交,而是使用button按钮提交
  • 原文地址:https://www.cnblogs.com/xilifeng/p/2989914.html
Copyright © 2011-2022 走看看