TKStudio-LPC1220_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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值