文章目录
- 7、仿真调试与下载
- 8、CC254基础开发(通用I/O)
- 示例:LED流水灯
- 9、独立按键开发
7、仿真调试与下载
仿真调试下钱器驱动的安装
程序仿真调试
结合smartRF Flash Programmer软件实现程序下载
设置
F:\IOT\blud_prj\test\Debug\Exe
获取CC2540蓝牙设备的IEEE地址
8、CC254基础开发(通用I/O)
引自:CC2540数据手册
7.3General-Purpose I/O
When used as general-purpose I/O, the pins are organized as three 8-bit ports, Port 0, Port 1, and Port 2;denoted PO, P1, and P2.P0 and P1 are complete 8-bit-wide ports, whereas P2 has only five usable bits.All ports are both bit- and byte-addressable through the SFR registers P0, P1, and P2.Each port pin canindividually be set to operate as a general-purpose l/o or as a peripheral l/O.
The output drive strength is 4 mA on all outputs, except for the two high-drive outputs, P1.0 and P1.1which each have 20-mA output drive strength.
The registers PxSEL, where x is the port number O-2, are used to configure each pin in a port as either ageneral-purpose l/O pin or as a peripheral l/O signal.By default, after a reset, all digital input/output pinsare configured as general-purpose input pins.
To change the direction of a port pin, at any time, the registers PxDIR are used to set each port pin to beeither an input or an output.Thus by setting the appropriate bit within PxDIR to 1, the corresponding pinbecomes an output.
When reading the port registers p0, P1, and P2, the logic values on the input pins are returned regardlessof the pin configuration. This does not apply during the execution of read-modify-write instructions. Theread-modify-write instructions are: ANL,ORL,XRL,JBC,CPL,INC, DEC,DUNZ,MOV,CLR, and SETB.
Operating on a port register, the following is true: When the destination is an individual bit in a port registerP0,P1, or P2, the value of the register, not the value on the pin, is read, modified, and written back to theport register.
When used as an input, the general-purpose l/O port pins can be configured to have a pullup, pulldown orthree-state mode of operation.By default, after a reset, inputs are configured as inputs with pullup.Todeselect the pullup or pulldown function on an input, the appropriate bit within the PxINP must be set to 1.The l0 port pins P1.0 and P1.1 do not have pullup/pulldown capability. Note that pins configured as
peripheral l/O signals do not have pullup/pulldown capability, even if the peripheral function is an input.In power modes PM1, PM2 and PM3, the l/O pins retain the l/O mode and output value (if applicable) thatwas set when PM1/PM2/PM3 was entered.
用作通用I/O时,引脚可以组成3个8位端口,端口0、端口1和端口2,表示为PO、P1和P2。其中,PO和P1是完全的8位端口,而P2,仅有5位可用。所有的端口均可以通过SFR寄存器PO、P1和P2位寻址和字节寻址。每个端口引脚都可以单独设置为通用vO或外部设备LO。
险了两个高驱动输出口P1_0和P1_1各且备20mA的输出驱动能力之外,所有的输出均具备4mA的驱动能力。
寄存器PxSEL,其中x为端口的标号0~2,用来设置端口的每个引脚为通用I/O或者是外部设备I/O信号.作为缺省的情况。每当复位之后,所有的数字输入/输出引脚都设置为通用输入引脚。
在任何时候,要改变一个端口引脚的方向,就使用寄存器PxDIR来设置每个端口引脚为输入或输出。因此首先设置PxDIP中的指示位为1,其对应的引脚口就被设置为输出了。
当读取端口寄存器P0、P1和P2的值,不管引脚配置如何,输入引脚上的逻辑值都被返回。这在执行读-修改-写指令期间不适用。读-修改-写指令是: ANL,ORL,XRL,JBC,CPL,NC,DEC,DNZ,MOV,CLR和SETB。在一个端口寄存器上操作,以下是正确的:当目标是端口寄存器PO、P1或P2中一个独立的位,寄存器的值,而不是引脚上的值,被读取、修改并写回端口寄存器。
用作输入时,通用IO端口引脚可以设置为上拉、下拉或三态操作模式。作为缺省的情况,复位之后,所有的端口均设置为带上拉的输入。要取消输入的上拉或下拉功能,就要将 PxINP中的对应位设置为I、I/O端口引脚P1.0和P1.1没有上拉/下拉功能。注意配置为外设I/O信号的引脚没有上拉/下拉功能,即使外设功能是一个输入。
在电源模式PM1、PM2 和PM3下I/O引脚保留当进入PM1/PM2/PM3时设置的I/O模式和输出值(如果可用的话)。
7.4 General-Purpose I/o Interrupts
General-purpose I/O pins configured as inputs can be used to generate interrupts.The interrupts can beconfigured to trigger on either a rising or falling edge of the external signal. Each of the Po, P1, and P2ports have port interrupt enable bits common for all bits within the port located in the IEN1-2 registers asfollows:
IEN1.POIE: P0 interrupt enable
IEN2.P1IE: P1 interrupt enable
IEN2.P2IE: P2 interrupt enable
In addition to these common interrupt enables, the bits within each port have individual interrupt enableslocated in SFR registers POIEN,,P1IEN and P2IEN.Even l/O pins configured as peripheral l/O or
general-purpose outputs have interupts generated when enabled.
When an interrupt condition occurs on one of the l/0 pins, the corresponding interrupt status flag in thePO-P2 interrupt flag registers, PoIFG,P1IFG, or P2IFG is set to 1.The interrupt status flag is set
regardless of whether the pin has its interrupt enable set. When an interrupt is serviced, the interruptstatus flag is cleared by writing a 0 to that flag.This flag must be cleared prior to clearing the CPU portinterrupt flag (PxlF).
The SFR registers used for interrupts are described later in this section.The registers are summarized asfollows:
P0IEN: P0 interrupt enables
P1IEN:P1 interrupt enables·
P2IEN: P2 interrupt enables
PICTL: PO,P1,and P2 edge configuration
P0IFG: P0 interrupt flags
P1IFG: P1 interrupt flags
P2IFG: P2 interrupt flags
7.4通用I/O中断
通用I/O引脚设置为输入后,可以用于产生中断。中断可以设置在外部信号的上升或下降沿触发。PO、P1或P2端口都有中断使能位,对位于IEN1-2寄存器内的端口所有的位都是公共的,如下:
IEN1.P0IE:P0中断使能
IEN2.P1IE:P1中断使能
IEN2.P2IE:P2中断使能
除了这些公共中断使能之外,每个端口的位都有位于SFR寄存器P0IEN、 P1IEN和P2IEN的单独的中断使能。即使配置为外设IO或通用输出的IO引脚使能时都有中断产生。
示例:LED流水灯
原理图
main.c
#include <ioCC2540.h>
//typedef unsigned char uchar;
//typedef unsigned int uint;
#define uint unsigned int
#define uchar unsigned char
//定义控制灯的端口
#define LED1 P1_0 //定义LED1为P1.0口控制
#define LED2 P1_1 //定义LED2为P1.1口控制
#define LED3 P1_4 //定义LED3为P1.4口控制
#define LED4 P0_1 //定义LED4为P0.1口控制
//函数声明
void LedOnOrOff(uchar); //点亮或熄灭所有灯
void Delay(uint); //延时函数
void DelayMS(uint); //延时MS函数
void InitLed(void); //初始化LED控制IO口函数
/**********************
名 称:LedOnOrOff()
功能:点亮或绝灭所有LED灯
入口参数:mode为1时LED灯亮 mode为0时LED灯灭,共阴极
出口多数:无
*********************/
void LedOnOrOff(uchar mode)
{
LED1 = mode;
LED2 = mode;
LED3 = mode;
LED4 = mode;
}
/****************************
//普通延时
*****************************/
void Delay(uint n)
{
uint i;
for(i = 0;i<n;i++);
for(i = 0;i<n;i++);
for(i = 0;i<n;i++);
for(i = 0;i<n;i++);
for(i = 0;i<n;i++);
}
/****************************
//MS延时
*****************************/
void DelayMS(uint msec)
{
uint i,j;
for (i=0;i<msec;i++)
for (j=0;j<535;j++);
}
/****************************
//初始化IO口程序
*****************************/
void InitLed(void)
{
P1DIR |= 0x13; //P10、P11、P14定义为输出 1101
P0DIR |= 0x02; //P0.1定义为输出 0010
LedOnOrOff(0); //使所有LED灯默认为熄灭状态
}
/***************************
//主函数
***************************/
void main(void)
{
uchar i;
InitLed(); //初始化LED灯控制IO口
while(1) //死循环
{
LED1 = !LED1; //流水灯,初始化时LED1为熄灭,执行后点亮
DelayMS(200);
LED2 = !LED2; //流水灯,初始化时LED2为熄灭,执行后点亮
DelayMS(200);
LED3 = !LED3; //流水灯,初始化时LED3为熄灭,执行后点亮
DelayMS(200);
LED4 = !LED4; //流水灯,初始化时LED4为熄灭,执行后点亮
DelayMS(200);
for (i = 0; i<2; i++) //所有灯闪烁2次
{
LedOnOrOff(0); //关闭所有灯
DelayMS(200);
LedOnOrOff(1); //打开所有灯
DelayMS(200);
}
LedOnOrOff(0); //关闭所有灯
DelayMS(200);
}
}
9、独立按键开发
按键连接在P0_1脚:
POSEL:Port 0 function-select register
选项:0:General-purpose I/O,1: Peripheral function
P0SEL &= ~0X02; //设置P0.1为普通IO口 02为二进制0010,取反为1101,即P0.1设置为普通I/O
P0.7 to PO.0 I/O direction 0:Input;1:Output
设置为输入模式,采用二进制1为输出,0为输入
P0DIR &= ~0X02;
打开上拉模式:
完整代码:
#include <ioCC2540.h>
typedef unsigned char uchar;
typedef unsigned int uint;
//定义控制灯的端口
#define LED1 P1_0 //定义LED1为P1.0口控制
#define LED2 P1_1 //定义LED2为P1.1口控制
#define LED3 P1_4 //定义LED3为P1.4口控制
#define KEY1 P0_1 //定义P0.1口为S1控制端
#define ON 1
#define OFF 0
//函数声明
void LedOnOrOff(uchar); //点亮或熄灭所有灯
void DelayMS(uint); //延时MS函数
void InitLed(void); //初始化LED控制IO口函数
/****************************
//MS延时
*****************************/
void DelayMS(uint msec)
{
uint i,j;
for (i=0;i<msec;i++)
for (j=0;j<535;j++);
}
/**********************
名 称:LedOnOrOff()
功能:点亮或绝灭所有LED灯
入口参数:mode为1时LED灯亮 mode为0时LED灯灭,共阴极
出口多数:无
*********************/
void LedOnOrOff(uchar mode)
{
LED1 = mode;
LED2 = mode;
LED3 = mode;
}
/****************************
//初始化IO口程序
*****************************/
void InitLed(void)
{
P1DIR |= 0x13; //P10、P11、P14定义为输出 1101
LedOnOrOff(0); //使所有LED灯默认为熄灭状态
}
/****************************
//初始化KEY程序
*****************************/
void InitKey(void)
{
P0SEL &= ~0X02; //设置P0.1为普通IO口 02为二进制0010,取反为1101,即P0.1设置为普通I/O
P0DIR &= ~0X02; //按键接在P0.1上,设P0.1为输入模式为普通IO口
P0INP &= ~0X02; //打开P0.1的上拉电阻
}
/**********************
名 称:KeyScan()
功能:读取按键状态
入口参数:无
出口多数:0为抬起, 1为按键按下
*********************/
uchar KeyScan(void)
{
if(KEY1 == 0) //高电平有效
{
DelayMS(10); //检测到按键,延时10MS防抖
if(KEY1 == 0)
{
while(!KEY1); //直到松开按键 松手检测
return(1); //有按键按下
}
}
return(0); //无按键按下
}
/***************************
//程序入口函数
***************************/
void main(void)
{
InitLed(); //初始化LED灯控制IO口
InitKey(); //初始化按键控制IO口
while(1)
{
DelayMS(2);
if(KeyScan()) //扫描按键当前状态,按下按时执行流水灯闪烁效果
{
LED1 = ON; //流水灯,初始化时LED1为熄灭,执行后点亮
DelayMS(500);
LED1 = OFF; //熄灭LED1
LED2 = ON; //流水灯,初始化时LED2为熄灭,执行后点亮
DelayMS(500);
LED2 = OFF;
LED3 = ON; //流水灯,初始化时LED3为熄灭,执行后点亮
DelayMS(500);
LED3 = OFF;
}
}
}
长短按的处理思路(伪代码)
u8 Keypresstime;
#define keypresslong 0x56;
#define keypressshort 0x20;
keyflag;
#define keypresslongflag 0x11
#define keypresshortflag 0x22
cold_imstask()
{
keyscan();
}
void keyscan(void)
{
if(!key1)
{
Keypresstime++;
if(Keypresstime == keypresslong)
{
keyflag = keyresslongflag;
}
else if(Keypresstime > keypresslong)
{
Keypresstime = keypresslong+1;
}
}
else if(Keypresstime > keypresslong)
{
Keypresstime = 0;
}
else if(Keypresstime < keypressshort)
{
Keypresstime = 0;
}
else if(Keypresstime < keypresslong)
{
keyflag = keypresshortflag;
}
}
void keytask(void)
{
switch(keyflag)
{
case keypressshotflag;
break;
case keypresslongflag;
break;
default:break;
}
keyflag = 0;
}