zoukankan      html  css  js  c++  java
  • CC2530学习路线-基础实验-GPIO 按键控制LED灯亮灭(2)



    1.前期预备知识


    1.1 新大陆Zigbee模块按键电路图

    image_1bq9qhq7u5b6g1od316api579.png-35.8kB

    由上图可知,Zigbee模块的SW1按钮连接在P1.2端口上,当SW1导通,P1.2电平从3.3V被拉低接地。所以P1.2输入模式为下拉输入.

    1.2 CC2530相关寄存器


    寄存器名称 寄存器作用 寄存器描述
    P1 (0x90) *控制端口1的高低电平 端口1.通用I/O。可以通过SFR位寻址
    P1SEL (0xF4) 端口1 8个子端口的功能选择 P1SEL的8个bit分别代表 => P1.7~P1.0的功能选择.
    值为 0:代表通用I/0(GPIO)功能.
    值为 1 : 代表外设功能
    P1DIR (0xFE) 端口1 输入输出选择 P1DIR的bit定义同P1SEL;
    值为 0:代表从外部输入信号至CC2530;
    值为 1:代表从CC2530输出信号至外部
    P1INP (0xF6) 端口1 输入模式选择 P1INP定义为P1.7~P1.2的I/O输入模式。其中P1.0和P1.1是没有上拉/下拉功能
    值为 0:上拉/下拉。
    值为 1:三态(高电平、低电平、高阻态)
    P2INP (0xINP) 端口2 输入模式及其它端口选择 P2INP比较特殊,因为P2端口引出的引脚只有3个,所以P2INP还有其它功能。
    bit 0 ~ 4 : P2.4~P2.0的输入模式。 0 : 上拉/下拉; 1:三态
    bit 5 : 设置端口0上拉/下拉选择。对端口P0上面的所有引脚设置为上拉/下拉输入 0 : 上拉; 1 : 下拉
    bit 6 : 同bit 5功能,但是是设置端口1上所有引脚
    bit 7 : 同bit5功能,但是是设置端口2上的所有引脚
    P1IEN (0x8D) 端口1 中断屏蔽 端口P1.7~P1.0的中断使能(也就是说中断是否Enable*(打开))
    0 : 中断禁用
    1 : 中断使能
    PICTL (0x8C) 端口中断控制 P0ICON(bit0) 端口0、1、2输入模式下的中断配置。
    0 : 输入的上升沿引起中断
    1 : 输入的下降沿引起中断
    P1IFG (0x8A) 端口0 中断状态标志 端口0,bit7 ~ 0输入中断状态标志。当输入端口中断请求后,其相应的标志位将会被置为1.
    IEN2 (0x9A) 中断使能1 P0IE(bit5) 端口1中断使能
    0 : 中断禁止
    1 : 中断使能
    EA 中断的总开关 只有打开该开关,中断才能传入51芯片
    0 : 中断禁止
    1 : 中断使能

    1.3 CC2530中断走向图

    image_1bq9vkesqg0q1av8nqi14477hq9.png-423.6kB
    如上图所示,如果P1端口发生中断,需要传入51内核中,流程如下图所示.

    7

    所以,我们对中断进行初始化的一个流程也和上图一样,一层一层的将中断使能开关打开。

    1.4 使用C语言为51单片机编写中断程序

    使用C语言为51单片机编写中断程序,有一个特殊的函数声明形式。如以下代码所示:

    #pragma vector = 中断向量地址
    __interrupt void P01_ISR(void)
    {
        /*Do something*/
    }
    

    其中中断向量地址,可以在ioCC2530.h头文件中找到,可以直接使用宏定义字符替换。

    /* --------------------------------------------------------------------------
     *                          Interrupt Vectors
     * --------------------------------------------------------------------------
     */
    #define  RFERR_VECTOR   VECT(  0, 0x03 )   /*  RF TX FIFO下溢和RX FIFO溢出*/
    #define  ADC_VECTOR     VECT(  1, 0x0B )   /*  ADC转换结束*/
    #define  URX0_VECTOR    VECT(  2, 0x13 )   /*  USART0 RX完成*/
    #define  URX1_VECTOR    VECT(  3, 0x1B )   /*  USART1 RX完成*/
    #define  ENC_VECTOR     VECT(  4, 0x23 )   /*  AES加密/解密完成*/
    #define  ST_VECTOR      VECT(  5, 0x2B )   /*  睡眠定时器比较*/
    #define  P2INT_VECTOR   VECT(  6, 0x33 )   /*  端口2输入*/
    #define  UTX0_VECTOR    VECT(  7, 0x3B )   /*  USART0 TX完成*/
    #define  DMA_VECTOR     VECT(  8, 0x43 )   /*  DMA传输完成*/
    #define  T1_VECTOR      VECT(  9, 0x4B )   /*  定时器1(16位)捕捉/比较/溢出 */
    #define  T2_VECTOR      VECT( 10, 0x53 )   /*  定时器2(MAC定时器)*/
    #define  T3_VECTOR      VECT( 11, 0x5B )   /*  定时器3(8位)捕捉/比较/溢出*/
    #define  T4_VECTOR      VECT( 12, 0x63 )   /*  定时器4(8位)捕捉/比较/溢出*/
    #define  P0INT_VECTOR   VECT( 13, 0x6B )   /*  端口0输入*/
    #define  UTX1_VECTOR    VECT( 14, 0x73 )   /*  USART1 TX完成*/
    #define  P1INT_VECTOR   VECT( 15, 0x7B )   /*  端口1输入*/
    #define  RF_VECTOR      VECT( 16, 0x83 )   /*  射频通用中断*/
    #define  WDT_VECTOR     VECT( 17, 0x8B )   /*  定时器模式下看门狗溢出*/
    

    1.5 *函数指针

    本节为选择学习内容,是笔者在学习按键中断时,思考的一个问题。想实现高级语言中事件机制,在高级语言中事件主要是靠方法指针和观察者设计模式一并完成。方法指针就是一个指向方法的指针。而C语言中的指针一样可以指向一个函数。如:

    例1,简单的事件实现,函数指针。
    
    #include <ioCC2530.h>
    typedef unsigned int uint;
    /************************/
    void (*timer_ow)(); // 定义一个返回值为void参数为空的函数指针
    int (*timer_ow1)(); // 定义一个返回值为int参数为void的函数指针
    int (*timer_ow2)(int); // 定义一个返回值为int参数为int的函数指针
    /************************/
    void timer_Overflow(void)
    {
        /*Do something*/
    }
    int timer_Overflow1(void)
    {
        /*Do something*/
    }
    int timer_Overflow2(int z)
    {
        /*Do something*/
    }
    void main(void)
    {
        // 将函数timer_Overflow赋值给函数指针timer_ow
        timer_ow = timer_Overflow;
        // 调用函数指针
        (*timer_ow)();
        
        timer_ow1 = timer_Overflow1;
        int result = (*timer_ow1)();
        
        timer_ow2 = timer_Overflow2;
        result = (*timer_ow2)(result);
    }
    

    2. 程序代码

    #include <ioCC2530.h>
    
    // 初始化通用端口
    void init_gpio(void)
    {
      // 将p1_0,1,2设置成GPIO
      P1SEL &=~ 0x07;
      // 将p1_0,1设置成输出
      P1DIR |= 0x03;
      // 将p1_2设置成输入
      P1DIR &=~ 0x04;
      // 下拉P1全部端口,使LED全灭
      P1 = 0x00;
      // 设置端口1为上下拉功能
      P1INP &=~ 0x04;
      // 设置端口1输入模式为上拉
      P2INP &=~ 0x40;
    }
    
    // 初始化通用端口中断
    void init_gpio_interrupt(void)
    {
      // 将P1设置为输入下降沿引起中断
      PICTL |= 0x02;
      // 设置P1引脚2为中断使能
      P1IEN |= 0x04;
      // 设置端口P1为中断使能
      IEN2 |= 0x10;
      // 打开中断总开关
      EA = 1;
      
      //清空中断标志
      P1IFG = 0;
      P1IF = 0;
    }
    
    #pragma vector = P1INT_VECTOR
    __interrupt void P1_ISR(void)
    {
      // 判断中断信号是否从P1.2 SW1引脚发生
      if(P1IFG == 0x04)
      {
          // 让LED翻转
          P1_0 = ~P1_0;
          P1_1 = ~P1_1;
      }
      // 清空中断标志
      P1IFG = 0;
      P1IF = 0;
    }
    
    void main()
    {
      init_gpio();
      init_gpio_interrupt();
      while(1){;}
    }
    

    代码并没有特别困难的地方,根据前面的预备知识和流程图基本可以看得懂。

    THE END

  • 相关阅读:
    angular多个控制器如何共享数据
    $q服务的使用
    $sanitize和$sce服务的使用方法
    json对象与json字符串互转方法
    css语法和JS语法的对比
    让低版本IE也能正常运行HTML5+CSS3网站的3种解决方案
    HTML中的IE条件注释
    区块链是什么,如何评价区块链
    编写Python脚本把sqlAlchemy对象转换成dict的教程
    编写Python脚本把sqlAlchemy对象转换成dict的教程
  • 原文地址:https://www.cnblogs.com/InCerry/p/9397851.html
Copyright © 2011-2022 走看看