cc2530定时器

cc2530定时器,第1张

  CC2530 具有一个IEEE 802.15.4 兼容无线收发器RF 内核控制模拟无线模块。另外,它提供了MCU 和无线设备之间的一个接口,这使得可以发出命令,读取状态,自动 *** 作和确定无线设备事件的顺序。无线设备还包括一个数据包过滤和地址识别模块。

  CC2530 包括许多不同的外设,允许应用程序设计者开发先进的应用。

  调试接口执行一个专有的两线串行接口,用于内电路调试。通过这个调试接口,可以执行整个闪存存储器的擦除、控制使能哪个振荡器、停止和开始执行用户程序、执行8051 内核提供的指令、设置代码断点,以及内核中全部指令的单步调试。使用这些技术,可以很好地执行内电路的调试和外部闪存的编程。

  设备含有闪存存储器以存储程序代码。闪存存储器可通过用户软件和调试接口编程。闪存控制器处理写入和擦除嵌入式闪存存储器。闪存控制器允许页面擦除和4 字节编程。

  cc2530定时器

  CC2530的时钟模块

  振荡器和时钟

  CC2530设备有一个内部系统时钟,或者主时钟。系统时钟源可以是从16MHz RC振荡器或一个32M晶体振荡器中的一个提供。系统时钟源是由CLKCONCMD SRF控制寄存器。

  还有一个32KHz的时钟源,来源可以是从RC 振荡器或者32KHz的晶体振荡器中过来,同样是由CLKCONCMD寄存器控制。

  CLKCONSTA寄存器是一个制度寄存器,用来获得当前系统时钟的状态。

  时钟源可以在一个精度高的晶体振荡器和一个功耗低的RC振荡器中交替选择使用。注意一点:RF的收发 *** 作是要以32MHz的晶体振荡器为时钟源才行。

  振荡器

  图中给出了时钟系统中可用的时钟源的一个全貌图。

  设备中存在的两个高频振荡器:

  * 32MHz晶体振荡器

  * 16MHz的RC振荡器

  32MHz的晶体振荡器启动时间对于某些应用来说可能太长了;因此设备可以先运行在16MHz的RC振荡器中运行直到晶体振荡器稳定后在使用32MHz晶体振荡器。16MHz的RC振

  荡器功耗低但是不是很准,所以不能为RF模块提供服务,只能用32MHz的晶体振荡器。

  设备中存在的两个低频振荡器:

  * 32 KHz晶体振荡器

  * 32 KHz RC振荡器

  32KHz的XOSC被设计的工作频率频率是32.768KHz并且可以为一些要求时钟准确子系统提供一个稳定的时钟信号。32KHz的RCOSC当校准后可以运行在32.753KHz频率下。校准

  只能发生在当32MHz XOSC使能的情况下,可以通过使能SLEEPCMD.OSC32K_CALDIS位来关闭校准。32KHz RC振荡器相对于32KHz XOSC晶体振荡器功耗低,应该用在可以降

  低成本情况下。两个振荡器不能同时工作。

  系统时钟

  系统时钟是由32MHz XOSC或者16MHz RCOSC两个时钟源驱动的。CLKCONCMD.OSC位用来选择系统时钟源。注意:使用RF模块时,32MHz晶体振荡器必须被选上并且运行稳定。

  注意:改变CLKCONCMD.OSC位并不能立即导致系统时钟源的改变。当CLKCONSTA.OSC = CLKCONCMD.OSC时时钟源的改变才会发挥作用。这是因为设备在实际改变时钟源之前

  需要稳定的时钟。还有就是注意CLKCONCMD.CLKSPD位反应着系统时钟频率,因此是CLKACONCMD.OSC位的镜子。一旦32MHz的XOSC被选中和稳定,例如,当CLKCONSTA.OSC

  位从1切换到0时。

  注意:从16MHz到32MHz时钟源的改变符合CLKCONCMD.TICKSPD设置。CLKCONCMD.TICKSPD设置的缓慢一些的话,当CLKCONCMD.OSC改变的话会导致实际的时钟源起作用的

  时间会很长。当CLKCONCMD.TICKSPD

  等于000时会获得最快的切换速度。

  32KHz的振荡器

  默认的或者复位后32KHz RCOSC使能并且被设置作为32KHz的时钟源。其功耗低,但是相对于32KHz晶体振荡器而言精度不高,32KHz时钟源用来驱动睡眠定时器,产生看门狗的滴答值

  和作为TImer 2计算睡眠定时器的一个闸门。32KHz时钟源被寄存器CLKCONCMD.OSC32K位用来作为选择振荡器。CLKCONCMD.OSC32K寄存器可以在任意时间写入,但是在16MHz RC

  振荡器是活跃的系统时钟源之前是不会起作用的。当系统时钟从16MHz改变为32MHz的晶体振荡器(CLKCONCMD.OSC从1到0)一旦32KHz RC振荡器被选中了它的的校验就启动了并且被执行。在校准期间,32MHz晶体振荡器的一个分频量会被使用。32KHzRCOSC振荡器校准后的结果是它会工作在32.753kHz上。32kHz RC振荡器校准时间可能要2ms时间来完成。可以设置SLEEPCMD.OSC32K_CALDIS位设置为1的话,会关闭校准。在校准结束时,会在32KHz时钟源上产生一个额外的脉冲,会导致睡眠定时器增加1。

  注意:当切换到32KHz晶体振荡器后和从32KHz晶体振荡器被设置的PM3模式唤醒时,振荡器稳定到准确频率的时间在500 ms以上。睡眠定时器、看门狗定时器和时钟损失探测器在32KHz

  晶体振荡器稳定之前不能使用。

  振荡器和时钟寄存器

  下面是振荡器和时钟寄存器的描述,所有寄存器的位会在进入PM2和PM3时保持不变,除非有异常情况发生。

  定时器滴答值产生器

  CLKCONCMD.TICKSPD寄存器控制timer1、timer3和timer4的全局预分频。预分频的值设置范围在0.25MHz和32MHz之间。

  需要注意的是如果CLKCONCMD.TICKSPD显示的频率高于系统时钟,则在CLKCONSTA.TICKSPD中的实际的预分频值表明是和系统时钟的值是一样的。

  数据滞留

  在PM2和PM3电源模式中,绝大多数的内部电路关闭了,然而,SRAM中任保留它的内容,内部寄存器的值也会保留。

  保留数据的寄存器是CPU的寄存器、外部寄存器和RF寄存器,除非另一些位域值设置的比较特殊。切换到PM2和PM3模式的现象对于软件而已是透明的。

  注意在PM3模式下睡眠定时器的值不会保存。

  ******************************************************************

  /**********************************************************************************************************

  * 功 能:实验一 系统时钟源的选择

  *

  * CC2530有1个内部的系统时钟。时钟源可以是1个16MHz的RC振荡器,也可以是1个32MHz的晶体

  * 振荡器。时钟控制是通过使用CLKCON特殊功能寄

  存器来执行的。系统时钟也提供给所有的8051

  * 外设。

  *

  * 32MHz晶体振荡器的启动时间对于某些应用而言太长了,因此CC2530可以运行在16MHz RC振荡器

  * 直到晶体振荡器稳定。16MHz RC振荡器的功耗要少于晶体振荡器,但是由于它没有晶体振荡器

  * 精确,因此它不适用于射频收发器。

  *

  * CLKCONCMD.OSC位被用来选择系统时钟源。注意:要使用射频收发器,32MHz晶体振荡器必须被选择

  * 并且稳定。

  *

  * 注意:改变CLKCON.OSC位并不即刻生效。这是因为在实际改变时钟源之前,被选择的时钟源要

  * 首先达到稳定。还要注意:CLKCONSTA.CLKSPD位将反映系统时钟频率,因此它是CLKCON.OSC位的

  * “镜子”。

  *

  * 当SLEEPSTA.XOSC_STB为1时,表示系统报告32MHz晶体振荡器稳定。然而,这可能并不是实际情况,

  × 在选择32MHz时钟作为系统时钟源之前,应该等待一个额外的64us的安全时间,可以通过增加一

  * 条空指令“NOP”来实现。如果不等待,可能会造成系统崩溃。

  *

  * 未被选择作为系统时钟源的振荡器,通过设置SLEEP.OSC_PD为1(默认状态)将被设置为掉电模式。

  * 因此,当32MHz晶体振荡器被选择作为系统时钟源后,16MHz RC振荡器可能被关闭,反之亦然。

  * 当SLEEPCMD.OSC_PD为0时,这2个振荡器都被上电并运行。

  * 当32MHz晶体振荡器被选择作为系统时钟源并且16MHz RC振荡器也被上电时,根据供电电压和运

  * 行温度,16MHZ RC振荡器将被不断校准以确保时钟稳定。当16MHz RC振荡器被选择作为系统时钟

  * 源时,该校准不被执行。

  *

  * 本实验将向用户演示选择不同的振荡器作为系统时钟源。本文件中有led闪烁的子程序,用户

  * 可以观察在不同系统时钟源下led的闪烁情况。

  *

  * 在hal.h文件中包含了和系统时钟相关的一些宏,用户使用这些宏可以简化对系统时钟的控制,

  * 提高代码的可读性,本实验中就使用了其中的一些宏。

  *

  * 注 意:本实验可在以下目标板上进行:

  *

  *

  *

  *

  *

  * 版 本:V1.0  **************************************************************************************************/

  #include “hal.h”

  #define ON 0x01 //LED状态

  #define OFF 0x00

  extern void ctrPCA9554LED(UINT8 led,UINT8 operation);

  extern void PCA9554ledInit();

  /**************************************************************************************************

  * 函数名称:halWait

  *

  * 功能描述:延时

  *

  * 参 数:wait - 延时时间

  *

  * 返 回 值:无

  **************************************************************************************************/

  void halWait(BYTE wait){

  UINT32 largeWait;

  if(wait == 0)

  {return;}

  largeWait = ((UINT16) (wait 《《 7));

  largeWait += 114*wait;

  largeWait = (largeWait 》》 CLKSPD);

  while(largeWait--);

  return;

  }

  /**************************************************************************************************

  * 函数名称:main

  *

  * 功能描述:反复选择不同的振荡器作为系统时钟源,并调用led控制程序,闪烁LED灯。

  *

  * 参 数:无

  *

  * 返 回 值:无

  **************************************************************************************************/

  void main(void)

  {

  UINT8 i;

  PCA9554ledInit();

  while(1)

  {

  SET_MAIN_CLOCK_SOURCE(CRYSTAL); // 设置系统时钟源为32MHz晶体振荡器(大约用时150us),关闭16MHz RC振荡器

  for (i=0;i《10;i++)

  {

  ctrPCA9554LED(0,ON);

  halWait(200);

  ctrPCA9554LED(0,OFF);

  halWait(200);

  }

  SET_MAIN_CLOCK_SOURCE(RC); // 选择16MHz RC振荡器,关闭32MHz晶体振荡器

  PCA9554ledInit();

  halWait(200);

  for (i=0;i《10;i++)

  {

  ctrPCA9554LED(1,ON);

  halWait(200);

  ctrPCA9554LED(1,OFF);

  halWait(200);

  }

  }

  }

  /**********************************************************************************************************

  * 文 件 名:iic.C

  * 功 能:实验二 GPIO控制实验

  * PCA9554,最后通过扩展的IO来控制LED的亮灭。

  *

  * 硬件连接:将OURS的CC2530RF模块插入到普通电池板或智能电池板上。

  *

  * P1.0 ------ SCL

  * P1.1 ------ SDA

  *

  * 版 本:V1.0

  **************************************************************************************************************/

  #include “ioCC2530.h”

  #include “hal_mcu.h”

  #define SCL P1_0 //IIC时钟线

  #define SDA P1_1 //IIC数据线

  //定义IO方向控制函数

  #define IO_DIR_PORT_PIN(port, pin, dir) \

  do { \

  if (dir == IO_OUT) \

  P##port##DIR |= (0x01《《(pin)); \

  else \

  P##port##DIR &= ~(0x01《《(pin)); \

  }while(0)

  #define OSC_32KHZ 0x00 //使用外部32K晶体振荡器

  //时钟设置函数

  #define HAL_BOARD_I

  NIT() \

  { \

  uint16 i; \

  \

  SLEEPCMD &= ~OSC_PD; /* 开启 16MHz RC 和32MHz XOSC */ \

  while (!(SLEEPSTA & XOSC_STB)); /* 等待 32MHz XOSC 稳定 */ \

  asm(“NOP”); \

  for (i=0; i《504; i++) asm(“NOP”); /* 延时63us*/ \

  CLKCONCMD = (CLKCONCMD_32MHZ | OSC_32KHZ); /* 设置 32MHz XOSC 和 32K 时钟 */ \

  while (CLKCONSTA != (CLKCONCMD_32MHZ | OSC_32KHZ)); /* 等待时钟生效*/ \

  SLEEPCMD |= OSC_PD; /* 关闭 16MHz RC */ \

  }

  #define IO_IN 0 //输入

  #define IO_OUT 1 //输出

  uint8 ack; //应答标志位

  uint8 PCA9554ledstate = 0; //所有LED当前状态

  /******************************************************************************

  * 函数名称:QWait

  *

  * 功能描述:1us的延时

  *

  * 参 数:无

  *

  * 返 回 值:无

  *****************************************************************************/

  void QWait()

  {

  asm(“NOP”);asm(“NOP”);

  asm(“NOP”);asm(“NOP”);

  asm(“NOP”);asm(“NOP”);

  asm(“NOP”);asm(“NOP”);

  asm(“NOP”);asm(“NOP”);

  asm(“NOP”);

  }

  /******************************************************************************

  * 函数名称:Wait

  *

  * 功能描述:ms的延时

  *

  * 参 数:ms - 延时时间

  *

  * 返 回 值:无

  *****************************************************************************/

  void Wait(unsigned int ms)

  {

  unsigned char g,k;

  while(ms)

  {

  for(g=0;g《=167;g++)

  {

  for(k=0;k《=48;k++);

  }

  ms--;

  }

  }

  /******************************************************************************

  * 函数名称:Start_I2c

  *

  * 功能描述:启动I2C总线,即发送I2C起始条件。

  *

  * 参 数:无

  *

  * 返 回 值:无

  *****************************************************************************/

  void Start_I2c()

  {

  IO_DIR_PORT_PIN(1, 0, IO_OUT); //设置P1.0为输出

  IO_DIR_PORT_PIN(1, 1, IO_OUT); //设置P1.1为输出

  SDA=1; /*发送起始条件的数据信号*/

  asm(“NOP”);

  SCL=1;

  QWait(); /*起始条件建立时间大于4.7us,延时*/

  QWait();

  QWait();

  QWait();

  QWait();

  SDA=0; /*发送起始信号*/

  QWait(); /* 起始条件锁定时间大于4μs*/

  QWait();

  QWait();

  QWait();

  QWait();

  SCL=0; /*钳住I2C总线,准备发送或接收数据 */

  asm(“NOP”);

  asm(“NOP”);

  }

  /******************************************************************************

  * 函数名称:Stop_I2c

  *

  * 功能描述:结束I2C总线,即发送I2C结束条件。

  *

  * 参 数:无

  *

  * 返 回 值:无

  *****************************************************************************/

  void Stop_I2c()

  {

  IO_DIR_PORT_PIN(1, 0, IO_OUT); //设置P1.0为输出

  IO_DIR_PORT_PIN(1, 1, IO_OUT); //设置P1.1为输出

  SDA=0; /*发送结束条件的数据信号*/

  asm(“NOP”); /*发送结束条件的时钟信号*/

  SCL=1; /*结束条件建立时间大于4μs*/

  QWait();

  QWait();

  QWait();

  QWait();

  QWait();

  SDA=1; /*发送I2C总线结束信号*/

  QWait();

  QWait();

  QWait();

  QWait();

  }

  /******************************************************************************

  * 函数名称:SendByte

  *

  * 功能描述:将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对

  * 此状态位进行 *** 作。(不应答或非应答都使ack=0 假)

  * 发送数据正常,ack=1; ack=0表示被控器无应答或损坏。

  *

  * 参 数:c - 需发送的数据

  *

  * 返 回 值:无

  *****************************************************************************/

  void SendByte(uint8 c)

  {

  uint8 BitCnt;

  IO_DIR_PORT_PIN(1, 0, IO_OUT); //设置P1.0为输出

  IO_DIR_PORT_PIN(1, 1, IO_OUT); //设置P1.1为输出

  for(BitCnt=0;BitCnt《8;BitCnt++) /*要传送的数据长度为8位*/

  {

  if((c《《BitCnt)&0x80)SDA=1; /*判断发送位*/

  else SDA=0;

  asm(“NOP”);

  SCL=1; /*置时钟线为高,通知被控器开始接收数据位*/

  QWait();

  QWait(); /*保证时钟高电平周期大于4μs*/

  QWait();

  QWait();

  QWait();

  SCL=0;

  }

  QWait();

  QWait();

  QWait();

  SDA=1; /*8位发送完后释放数据线,准备接收应答位*/

  asm(“NOP”);

  IO_DIR_PORT_PIN(1, 1, IO_IN);

  SCL=1;

  QWait();

  QWait();

  QWait();

  QWait();

  if(SDA==1)ack=0;

  else ack=1; /*判断是否接收到应答信号*/

  SCL=0;

  QWait();

  QWait();

  IO_DIR_PORT_PIN(1, 1, IO_OUT);

  }

  /******************************************************************************

  * 函数名称:RcvByte

  *

  * 功能描述:用来接收从器件传来的数据,并判断总线错误(不发应答信号),

  * 发完后请用应答函数。

  *

  * 参 数:无

  *

  * 返 回 值:retc - 从器件传来的数据

  *****************************************************************************/

  uint8 RcvByte()

  {

  uint8 retc;

  uint8 BitCnt;

  IO_DIR_PORT_PIN(1, 0, IO_OUT); //设置P1.0为输出

  IO_DIR_P

  ORT_PIN(1, 1, IO_OUT); //设置P1.1为输出

  retc=0;

  SDA=1; /*置数据线为输入方式*/

  IO_DIR_PORT_PIN(1, 1, IO_IN);

  for(BitCnt=0;BitCnt《8;BitCnt++)

  {

  asm(“NOP”);

  SCL=0; /*置时钟线为低,准备接收数据位*/

  QWait();

  QWait(); /*时钟低电平周期大于4.7μs*/

  QWait();

  QWait();

  QWait();

  SCL=1; /*置时钟线为高使数据线上数据有效*/

  QWait();

  QWait();

  retc=retc《《1;

  if(SDA==1)retc=retc+1; /*读数据位,接收的数据位放入retc中 */

  QWait();

  QWait();

  }

  SCL=0;

  QWait();

  QWait();

  IO_DIR_PORT_PIN(1, 1, IO_OUT);

  return(retc);

  }

  /******************************************************************************

  * 函数名称:Ack_I2c

  *

  * 功能描述:主控器进行应答信号,(可以是应答或非应答信号)

  *

  *

  * 参 数:无

  *

  * 返 回 值:无

  *****************************************************************************/

  void Ack_I2c(uint8 a)

  {

  IO_DIR_PORT_PIN(1, 0, IO_OUT); //设置P1.0为输出

  IO_DIR_PORT_PIN(1, 1, IO_OUT); //设置P1.1为输出

  if(a==0)SDA=0; /*在此发出应答或非应答信号 */

  else SDA=1;

  QWait();

  //QWait();

  //QWait();

  SCL=1;

  QWait();

  QWait(); /*时钟低电平周期大于4μs*/

  QWait();

  QWait();

  QWait();

  SCL=0; /*清时钟线,钳住I2C总线以便继续接收*/

  QWait();

  //QWait();

  }

  /******************************************************************************

  * 函数名称:ISendByte

  *

  * 功能描述:从启动总线到发送地址,数据,结束总线的全过程,从器件地址sla.

  * 如果返回1表示 *** 作成功,否则 *** 作有误。

  *

  *

  * 参 数:sla - 从器件地址

  * c - 需发送的数据

  *

  * 返 回 值:0 -- 失败

  * 1 -- 成功

  *****************************************************************************/

  uint8 ISendByte(uint8 sla,uint8 c)

  {

  Start_I2c(); /*启动总线*/

  SendByte(sla); /*发送器件地址*/

  if(ack==0)return(0);

  SendByte(c); /*发送数据*/

  if(ack==0)return(0);

  Stop_I2c(); /*结束总线*/

  return(1);

  }

  /******************************************************************************

  * 函数名称:ISendStr

  *

  * 功能描述:从启动总线到发送地址,子地址,数据,结束总线的全过程,从器件

  * 地址sla,子地址suba,发送内容是s指向的内容,发送no个字节。

  * 如果返回1表示 *** 作成功,否则 *** 作有误。

  *

  *

  * 参 数:sla - 从器件地址

  * suba - 从器件子地址

  * *s - 数据

  * no - 数据字节数目

  *

  * 返 回 值:0 -- 失败

  * 1 -- 成功

  *

  * 注 意:使用前必须已结束总线。

  *****************************************************************************/

  uint8 ISendStr(uint8 sla,uint8 suba,uint8 *s,uint8 no)

  {

  uint8 i;

  Start_I2c(); /*启动总线*/

  SendByte(sla); /*发送器件地址*/

  if(ack==0)return(0);

  SendByte(suba); /*发送器件子地址*/

  if(ack==0)return(0);

  for(i=0;i《no;i++)

  {

  SendByte(*s); /*发送数据*/

  if(ack==0)return(0);

  s++;

  }

  Stop_I2c(); /*结束总线*/

  return(1);

  }

  /******************************************************************************

  * 函数名称:IRcvByte

  *

  * 功能描述:从启动总线到发送地址,读数据,结束总线的全过程,从器件地

  * 址sla,返回值在c. 如果返回1表示 *** 作成功,否则 *** 作有误。

  *

  *

  * 参 数:sla - 从器件地址

  * *c - 需发送的数据

  *

  * 返 回 值:0 -- 失败

  * 1 -- 成功

  *

  *注 意:使用前必须已结束总线。

  *****************************************************************************/

  uint8 IRcvByte(uint8 sla,uint8 *c)

  {

  Start_I2c(); /*启动总线*/

  SendByte(sla+1); /*发送器件地址*/

  //SendByte(sla);

  if(ack==0)return(0);

  *c=RcvByte(); /*读取数据*/

  Ack_I2c(1); /*发送非就答位*/

  Stop_I2c(); /*结束总线*/

  return(1);

  }

  /******************************************************************************

  * 函数名称:IRcvStr

  *

  * 功能描述:从启动总线到发送地址,子地址,读数据,结束总线的全过程,从器件

  * 地址sla,子地址suba,读出的内容放入s指向的存储区,读no个字节。

  * 如果返回1表示 *** 作成功,否则 *** 作有误。

  *

  *

  * 参 数:sla - 从器件地址

  * suba - 从器件子地址

  * *s - 数据

  * no - 数据字节数目

  *

  * 返 回 值:0 -- 失败

  * 1 -- 成功

  *

  * 注 意:使用前必须已结束总线。

  *****************************************************************************/

  uint8 IRcvStr(uint8 sla,uint8 suba,uint8 *s,uint8 no)

  {

  Start_I2c(); /*启动总线*/

  SendByte(sla); /*发送器件地址*/

  if(ack==0)return(0);

  SendByte(suba); /*发送器件子地址*/

  // if(ack==0)return(0);

  // SendByte(sla+1);

  if(ack==0)return(0);

  while(no 》 0)

  {

  *s++ = RcvByte();

  if(no 》 1) Ack_I2c(0); /*发送就答位*/

  else Ack_I2c(1); /*发送非应位*/

  no--;

  }

  Stop_I2c();

  /*结束总线*/

  return(1);

  }

  /******************************************************************************

  * 函数名称:ctrPCA9554LED

  *

  * 功能描述:通过IIC总线控制PCA9554的输出,进而控制相应的LED。

  *

  *

  * 参 数:LED - 所控制的LED

  * operation - 开或关 *** 作

  *

  * 返 回 值:无

  *

  *

  * 注 意:PCA9554的地址为:0x40

  *****************************************************************************/

  void ctrPCA9554LED(uint8 led,uint8 operation)

  {

  uint8 output = 0x00;

  uint8 *data = 0;

  if(ISendStr(0x40,0x03,&output,1)) //配置PCA9554寄存器

  {

  switch(led)

  {

  case 0: //LED0控制

  if (operation)

  {

  output = PCA9554ledstate & 0xfe;

  }

  else

  {

  output = PCA9554ledstate | 0x01;

  }

  break;

  case 1: //LED1控制

  if (operation)

  {

  output = PCA9554ledstate & 0xfd;

  }

  else

  {

  output = PCA9554ledstate | 0x02;

  }

  break;

  case 2: //LED2控制

  if (operation)

  {

  output = PCA9554ledstate & 0xf7;

  }

  else

  {

  output = PCA9554ledstate | 0x08;

  }

  break;

  case 3: //LED3控制

  if (operation)

  {

  output = PCA9554ledstate & 0xfb;

  }

  else

  {

  output = PCA9554ledstate | 0x04;

  }

  break;

  case 4: //LED4控制

  if (operation)

  {

  output = PCA9554ledstate & 0xdf;

  }

  else

  {

  output = PCA9554ledstate | 0x20;

  }

  break;

  case 5: //LED5控制

  if (operation)

  {

  output = PCA9554ledstate & 0xef;

  }

  else

  {

  output = PCA9554ledstate | 0x10;

  }

  break;

  default:break;

  }

  if(ISendStr(0x40,0x01,&output,1)) //写PCA9554输出寄存器

  {

  if(IRcvByte(0x40,data)) //读PCA9554输出寄存器

  {

  PCA9554ledstate = *data;

  }

  }

  }

  }

  /******************************************************************************

  * 函数名称:PCA9554ledInit

  *

  * 功能描述:初始化6个LED,即关闭所有的LED

  *

  * 参 数:无

  *

  * 返 回 值:无

  *

  *****************************************************************************/

  void PCA9554ledInit()

  {

  uint8 output = 0x00;

  uint8 *data = 0;

  if(ISendStr(0x40,0x03,&output,1)) //配置PCA9554寄存器

  {

  output = 0xbf;

  if(ISendStr(0x40,0x01,&output,1)) //写输出寄存器

  {

  if(IRcvByte(0x40,data)) //读输出寄

  存器

  {

  PCA9554ledstate = *data;

  }

  }

  }

  }

  cc2530-按键控制时钟启动与停止

  2012-07-26 16:24:35| 分类: zigbee 2007 |举报|字号 订阅

  /*功能:

  1. 每隔0.065536秒(65536*32/32000000)切换LED显示

  2. S1控制计时器开始和暂停

  */

  #include 《ioCC2530.h》

  #define LED1 P1_0 //定义LED1为P1.0

  #define S1 P0_1 //定义S1为P0.1

  //函数实现

  void INIT_LED(void)

  {

  P1SEL &= ~0x01; //设P1.0为普通I/O功能

  P1DIR |= 0x01; //设P1.0为输出方向

  LED1 = 0; //将LED1点亮

  }

  void INIT_IO(void)

  {

  P0SEL &= ~0x02; //设P0.1(S1)为普通I/O功能

  P0DIR &= ~0x02; //设P0.1(S1)为输入

  P0INP &= ~0x02; //设P0.1(S1)为上拉/下拉

  P0IFG &= ~0x02; //设P0.1(S1)状态标志寄存器清零

  P0IEN |= 0x02; //设P0.1(S1)中断使能

  P2INP |= 0x60; //P0、P1的下拉

  EA = 1; //总中断EA为中断使能

  IEN1 |= 0x20; //开P0中断

  IEN2 |= 0x10; //开P1中断

  PICTL |= 0x07; //P0、P1下降沿触发

  }

  void INIT_Timer1()

  {

  T1CTL = 0x0C; //128分频、停止运行

  T1STAT = 0x21; //通道0 本句可以取消

  IRCON &= ~0x02;

  }

  //P0.1(S1)中断处理函数

  #pragma vector = P0INT_VECTOR

  __interrupt void P0_ISR(void)

  {

  if((P0IFG&0x02) == 0x02) //P0.1(S1)状态标志寄存器触发 (P0IFG的值为0XFF,不解)

  {

  for(int i =0 ;i《8000 ;i++);

  P0IFG &= ~0x02; //P0.1(S1)状态标志寄存器清零

  if(T1CTL == 0x09)

  T1CTL = 0x0C; //128分频 暂停运行

  else

  T1CTL = 0x09; //32分频 自由运行

  }

  }

  void main( void )

  {

  INIT_IO();

  INIT_LED();

  INIT_Timer1();

  LED1 = 1 ;

  while(1)

  {

  if(IRCON &= 0x02) //约0.065536秒切换LED灯闪烁

  {

  LED1 = !LED1;

  IRCON &= ~0x02 ;

  }

  }

  }

  dongfangnh

  采纳率:51% 10级 2013.12.14 检举

  #ifndef ULTRASOUND_H

  #define ULTRASOUND_H

  #define uchar unsigned char

  #define uint unsigned int

  #define TRIG P1_3 //P1_2

  #define ECHO P0_7 //P0_1

  extern uchar RG;

  extern uchar H1;

  extern uchar L1;

  extern uchar H2;

  extern uchar L2;

  extern uchar H3;

  extern uchar L3;

  extern uint data;

  extern float distance;

  extern uchar LoadRegBuf[4];

  //void Delay(uint n);

  void Delay_1us(uint microSecs);

  void Delay_10us(uint n);

  void Delay_1s(uint n);

  void SysClkSet32M();

  void Init_UltrasoundRanging();

  void UltrasoundRanging(uchar *ulLoadBufPtr);

  __interrupt void P0_ISR(void);

  #endif

  ××××××××××××××××××××××××××××××××××

  ×××××××××

  //×××××××××××Ultrasound.c****************************

  #include 《ioCC2530.h》

  #include “Ultrasound.h”

  uchar RG;

  uchar H1;

  uchar L1;

  uchar H2;

  uchar L2;

  uchar H3;

  uchar L3;

  uint data;

  float distance;

  uchar LoadRegBuf[4];//全局数据,用以存储定时计数器的值。

  void Delay_1us(uint microSecs)

  { while(microSecs--)

  { /* 32 NOPs == 1 usecs 因为延时还有计算的缘故,用了31个nop*/

  asm(“nop”); asm(“nop”); asm(“nop”); asm(“nop”); asm(“nop”);

  asm(“nop”); asm(“nop”); asm(“nop”); asm(“nop”); asm(“nop”);

  asm(“nop”); asm(“nop”); asm(“nop”); asm(“nop”); asm(“nop”);

  asm(“nop”); asm(“nop”); asm(“nop”); asm(“nop”); asm(“nop”);

  asm(“nop”); asm(“nop”); asm(“nop”); asm(“nop”); asm(“nop”);

  asm(“nop”); asm(“nop”); asm(“nop”); asm(“nop”); asm(“nop”);

  asm(“nop”);

  }

  }

  void Delay_10us(uint n)

  { /* 320NOPs == 10usecs 因为延时还有计算的缘故,用了310个nop*/

  uint tt,yy;

  for(tt = 0;tt《n;tt++);

  for(yy = 310;yy》0;yy--);

  {asm(“NOP”);}

  }

  void Delay_1s(uint n)

  { uint ulloop=1000;

  uint tt;

  for(tt =n ;tt》0;tt--);

  for( ulloop=1000;ulloop》0;ulloop--)

  {

  Delay_10us(100);

  }

  }

  void SysClkSet32M()

  {

  CLKCONCMD &= ~0x40; //设置系统时钟源为32MHZ晶振

  while(CLKCONSTA & 0x40); //等待晶振稳定

  CLKCONCMD &= ~0x47; //设置系统主时钟频率为32MHZ

  //此时的CLKCONSTA为0x88。即普通时钟和定时器时钟都是32M。

  }

  void Init_UltrasoundRanging()

  {

  P1DIR = 0x08; //0为输入1为输出 00001000 设置TRIG P1_3为输出模式

  TRIG=0; //将TRIG 设置为低电平

  P0INP &= ~0x80; //有上拉、下拉 有初始化的左右

  P0IEN |= 0x80; //P0_7 中断使能

  PICTL |= 0x01; //设置P0_7引脚,下降沿触发中断

  IEN1 |= 0x20; // P0IE = 1;

  P0IFG = 0;

  }

  void UltrasoundRanging(uchar *ulLoadBufPtr)

  {

  SysClkSet32M();

  Init_UltrasoundRanging();

  EA = 0;

  TRIG =1;

  Delay_1us(10); //需要延时10us以上的高电平

  TRIG =0;

  T1CNTL=0;

  T1CNTH=0;

  while(!ECHO);

  T1CTL = 0x09; //通道0,中断有效,32分频;自动重装模式(0x0000-》0xffff);

  L1=T1CNTL;

  H1=T1CNTH;

  *ulLoadBufPtr++=T1CNTL;

  *ulLoadBufPtr++=T1CNTH;

  EA = 1;

  Delay_10us(60000);

  Delay_10us(60000);

  }

  #pragma vector = P0INT_VECTOR

  __interrupt void P0_ISR(void)

  {

  EA=0;

  T1CTL = 0x00;

  LoadRegBuf[2]=T1CNTL;

  LoadRegBuf[3]=T1CNTH;

  L2=T1CNTL;

  H2=T1CNTH;

  if(P0IFG&0x080) //外部ECHO反馈信号

  {

  P0IFG = 0;

  }

  T1CTL = 0x09;

  T1CNTL=0;

  T1CNTH=0;

  P0IF = 0; //清中断标志

  EA=1;

  }

  ××××××××××××××××××××××××××××××××××××××

  #include 《ioCC2530.h》

  #include “Ultrasound.h”

  void main(void)

  {

  while(1)

  {

  UltrasoundRanging(LoadRegBuf);

  Delay_1s(1);

  data=256*H2+L2-L1-256*H1;

  distance=(float)data*340/10000;

  Delay

  _1s(2);

  };

  }

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/dianzi/2601459.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-08-09
下一篇 2022-08-09

发表评论

登录后才能评论

评论列表(0条)

保存