一、 cc2530最小系统

image-20210525142548926

二、GPIO概述

image-20210525143732557

三、IO口的输入输出配置

image-20210525143800845

上拉输入:有上拉电阻

​ 按键未按下时端口接高电平,即高电平 1 状态---3.3v

​ 按键按下时端口接低电平,即低电平 0 状态-------0

下拉输入:有下拉电阻

​ 按键未按下时端口接低电平,即低电平 0 状态---0v

​ 按键按下时端口接高电平,即高电平 1 状态------3.3v

image-20210525143939066

四、外部中断

1.什么是外部中断

外部中断是单片机实时地处理外部事件的一种内部机制。当某种外部事件发生时,单片机的中断系统将迫使CPU暂停正在执行的程序,转而去进行中断事件的处理;中断处理完毕后.又返回被中断的程序处,继续执行下去。

2.外部中断的作用

(1)实时处理功能

在实时控制中,现场的各种参数、信息均随时问和现场而变化。这些外界变量可根据要求随时向CPU发出中断申请.请求CPU及时处珲中断请求,如中断条件

(2)故障处理功能

针对难以预料的情况或故障,如掉电、存储出错、运算溢出等,可通过中断系统由故障源向CPU发出中断请求,再由CPU转到相应的故障处理程序进行处理。

3.cc2530的外部中断原理

CC2530 有 21 个数字 I/O 引脚,可以配置为通用数字 I/O 或外设 I/O 信号,配置为连接到 ADC、定时器或 USART 外设。这些 I/O 口的用途可以通过一系列寄存器配置,由用户软件加以实现。

​ I/O 端口具备如下重要特性:

  • ​ 21 个数字 I/O 引脚
  • ​ 可以配置为通用 I/O 或外部设备 I/O
  • ​ 输入口具备上拉或下拉能力
  • ​ 具有外部中断能力

​ 21 个 I/O 引脚都可以用作于外部中断源输入口。因此如果需要外部设备可以产生中断。外部中断功能也可以从睡眠模式唤醒设备。

​ 通用 I/O 引脚设置为输入后,可以用于产生中断。中断可以设置在外部信号的上升或下降沿触发。 P0、 P1 或 P2 端口都有中断使能位,对位于 IENl-2 寄存器内的端口所有的位都是公共的,如下:

  • IENI.P0IE: P0 中断使能

  • IEN2.PIIE: P1 中断使能

  • IEN2.P2IE: P2 中断使能

除了这些公共中断使能之外,每个端口的位都有位于 SFR 寄存器 P0IEN、P1IEN 和 P2IEN 的单独的中断使能。即使配置为外设 I/O 或通用输出的 I/O 引脚使能时都有中断产生。

当中断条件发生在 I/O 引脚之一上面,P0-P2 中断标志寄存器 P0IFG、P1IFG或 P2IFG 中相应的中断状态标志将设置为 1。不管引脚是否设置了它的中断使能位,中断状态标志都被设置。当中断已经执行,中断状态标志被清除,该标志写入 0。这个标志必须在清除 CPU 端口中断标志( PxIF)之前被清除。

image-20210525164054625
image-20210525164314863

用于中断的 SFR 寄存器描述在下一节。寄存器总结如下:

  • P0IEN: P0 中断使能
  • P1IEN: P1 中断使能
  • P2IEN: P2 中断使能
  • PICTL: P0、 P1 和 P2 触发沿设置
  • P0FG: P0 中断标志
  • P1IFG: P1 中断标志
  • P2IFG: P2 中断标志

4.外部中断配置步骤

image-20210525170345047

(1)初始化IO口工作在普通IO模式,上拉输入状态

(2)首先打开IO口组中断允许位===>PxIE

  • ​ P0IE 是 IEN1(0xB8)的第5位
  • ​ P1IE 是 IEN2(0x9A)的第4位
  • ​ P2IE 是 IEN2(0X9A)的第1位

(3)打开组内对应的具体某IO口中断====>PxIEN

(4)设置是上升沿还是下降沿触发===>PICTL(0,代表上升沿触发;1,代表下降沿触发)

(5)打开CPU总中断 EA=1;

void exti_init()
{
  //(1)初始化IO口工作在普通IO模式,上拉输入状态
    key_init();
    //(2)首先打开IO口组中断允许位===>PxIE
    IEN2 |= 1<<4;   //0001 0000 0x10
    //(3)打开组内对应的具体某IO口中断====>PxIEN
    P1IEN |= 1<<2;  //0000 0100 0x40
    //(4)设置是上升沿还是下降沿触发===>PICTL(0,代表上升沿触发;1,代表下降沿触发)
    PICTL |= 1<<1;  //0000 0010 0x02 设置为下降沿触发
    //(5)打开CPU总中断 EA=1;
    EA = 1;
}

5.外部中断服务程序示例

led_key.c

#include "iocc2530.h"
#include "led_key.h"

/*
@led init:对LED进行初始化
@retval:none 
@note:LED对应的引脚是P10和P11,初始化为普通IO,输出模式
*/
void led_init(void)
{
    P1SEL &= 0xfc;  //1111 1100  把P1_0和P1_1设置为通IO模式
    P1DIR |= 0x03;  //0000 0011  把P1_0和P1_1设置为输出模式
    P1_0 = 0;
    P1_1 = 0;
}

/*
@led ctr1:对LED的状态进行控的函数
@led num:指定对哪一盏LED等进行控制,可选择为LEDO,LED1
@led state:指定LED的状态,可选择为 LED ON, LED OFF 
@retval:none
*/
void led_ctrl(int led_num,int led_state)
{
    switch(led_num)
    {
    case LED0:
        P1_0 = led_state;
        break;
    case LED1:
        P1_1 = led_state;
        break;
    }
}

/*
@key init:按键的初始化函数
@retval none 
@note:按键应的引是P12,应初始化为普通IO,上拉输入模式
*/
void key_init(void)
{
    P1SEL &= 0xFB;   // 1111 1011 把P12设置为普通IO模式
    P1DIR &= 0xFB;   // 1111 1011 把P12设置为输入模式
    P1INP &= 0xFB;   // 1111 1011 把P12设置为上下拉模式
    P2INP &= 0xBF;   // 1011 1111 把P1组设置为上拉模式
}

int key_status(void)
{
    return P1_2;
}

/*
@exti_init:中断初始化函数
@retval none 
@note:none
*/
void exti_init()
{
  //(1)初始化IO口工作在普通IO模式,上拉输入状态
    key_init();
    //(2)首先打开IO口组中断允许位===>PxIE
    IEN2 |= 1<<4;   //0001 0000 0x10
    //(3)打开组内对应的具体某IO口中断====>PxIEN
    P1IEN |= 1<<2;  //0000 0100 0x40
    //(4)设置是上升沿还是下降沿触发===>PICTL(0,代表上升沿触发;1,代表下降沿触发)
    PICTL |= 1<<1;  //0000 0010 0x02 设置为下降沿触发
    //(5)打开CPU总中断 EA=1;
    EA = 1;
}

void delay_ms(int n)
{
     int i;
     while(n--)
         for(i=0;i<587;i++);
}

#pragma optimize=none       //不进行编译优化
#pragma vector=P1INT_VECTOR //P1组引发中断,vector中断矢量表,下面这段代码必须放在这个地方
__interrupt void exint(void)//P1组
{
      if(P1IFG & 0X04)//0000 0100
      {//确定是P1_2产生了外部中断
             delay_ms(20); //按键消抖
             if(P1_2 == 0)
            {
	        //中断要做的事情
                P1_0 = !P1_0;
                P1_1 = !P1_1;
            }
		
      }
      P1IFG = 0;//把中断状态标志位清0
      P1IF = 0; //组中断标志位清0
}

led_key.h

#ifndef __LED_KEY_H__
#define __LED_KEY_H__
#include "iocc2530.h"
enum LED_NUM{LED0,LED1};
enum LED_STATE{LED_OFF,LED_ON};
enum KEY_STATUS{KEY_DOWN,KEY_UP};
extern void led_init(void);
extern void led_ctrl(int led_num,int led_state);
extern void key_init(void);
extern int key_status(void);
extern void exti_init();
extern void delay_ms(int n);
#endif

main.c

#include "iocc2530.h"
#include "led_key.h"

void main(void)
{
    led_init();
    exti_init();
    while(1);
}