06_Z-Stack硬件驱动移植

06_Z-Stack硬件驱动移植

LED移植

​ 在hal_borad.h文件中,打开其包含的hal_board.h文件。Z-Stack协议中,默认给了四个LED的配置,将其与自己开发板的LED一一对应起来。

/* 1 - Green */
#define LED1_BV           BV(0) 
#define LED1_SBIT         P1_0
#define LED1_DDR          P1DIR
#define LED1_POLARITY     ACTIVE_LOW // 低电平驱动

#if defined (HAL_BOARD_CC2530EB_REV17)
  /* 2 - Red */
  #define LED2_BV           BV(1)
  #define LED2_SBIT         P1_1
  #define LED2_DDR          P1DIR
  #define LED2_POLARITY     ACTIVE_LOW

  /* 3 - Yellow */
  #define LED3_BV           BV(4)
  #define LED3_SBIT         P0_4
  #define LED3_DDR          P0DIR
  #define LED3_POLARITY     ACTIVE_LOW

#ifdef ENABLE_LED4_DISABLE_S1
  /* 4 - Orange */
  #define LED4_BV             BV(1)
  #define LED4_SBIT           P0_1
  #define LED4_DDR            P0DIR
  #define LED4_POLARITY       ACTIVE_HIGH
  #define LED4_SET_DIR()      do {LED4_DDR |= LED4_BV;} while (0)
#else
  #define LED4_SET_DIR()
#endif
#endif

​ 在编译选项的预编译中,添加HAL_LED=TRUE,对应在hal_drivers.c文件中的HalDrvierInit函数中,有:

  /* LED */
#if (defined HAL_LED) && (HAL_LED == TRUE)
  HalLedInit();
#endif

在这里插入图片描述

​ 在hal_led.h中提供相关API,常用的有:

  • HalLedSet( uint8 led, uint8 mode)

    HalLedSet(HAL_LED_1, HAL_LED_MODE_ON); // 开启LED1
    
  • HalLedBlink( uint8 leds, uint8 cnt, uint8 duty, uint16 time )

     HalLedBlink(HAL_LED_2, //指定LED
                            2, // 闪烁次数
                            40, //占空比
                            200); //闪烁时间c
    

按键移植

​ 在hal_borad.h文件中,默认有两个按键,S1Joystick Center Press,分别作为普通按键遥感按钮的中心按钮。可以直接将Joystick当做普通按键使用。将引脚配置与自己开发板对应。

/* ------------------------------------------------------------------------------------------------
 *                                    Push Button Configuration
 * ------------------------------------------------------------------------------------------------
 */

#define ACTIVE_LOW        !
#define ACTIVE_HIGH       !!    /* double negation forces result to be '1' */

/* S1 */
#define PUSH1_BV          BV(1)
#define PUSH1_SBIT        P0_1

#if defined (HAL_BOARD_CC2530EB_REV17)
  #define PUSH1_POLARITY    ACTIVE_LOW
#elif defined (HAL_BOARD_CC2530EB_REV13)
  #define PUSH1_POLARITY    ACTIVE_LOW
#else
  #define PUSH1_POLARITY    ACTIVE_LOW
  #error Unknown Board Indentifier
#endif

/* Joystick Center Press */
#define PUSH2_BV          BV(0)
#define PUSH2_SBIT        P2_0
#define PUSH2_POLARITY    ACTIVE_LOW

​ 在编译选项的预编译中,添加HAL_KEY=TRUE

​ 在hal_key.h中定义了一些按键事件, 这些很多是遥感按钮的,大多用不着

/* Interrupt option - Enable or disable */
#define HAL_KEY_INTERRUPT_DISABLE    0x00
#define HAL_KEY_INTERRUPT_ENABLE     0x01

/* Key state - shift or nornal */
#define HAL_KEY_STATE_NORMAL          0x00
#define HAL_KEY_STATE_SHIFT           0x01

#define HAL_KEY_SW_1 0x01  // Joystick up
#define HAL_KEY_SW_2 0x02  // Joystick right
#define HAL_KEY_SW_5 0x04  // Joystick center
#define HAL_KEY_SW_4 0x08  // Joystick left
#define HAL_KEY_SW_3 0x10  // Joystick down

#define HAL_KEY_SW_6 0x20  // Button S1 if available  
#define HAL_KEY_SW_7 0x40  // Button S2 if available  

/* Joystick */
#define HAL_KEY_UP     0x01  // Joystick up
#define HAL_KEY_RIGHT  0x02  // Joystick right
#define HAL_KEY_CENTER 0x04  // Joystick center
#define HAL_KEY_LEFT   0x08  // Joystick left
#define HAL_KEY_DOWN   0x10  // Joystick down

/* Buttons */  
#define HAL_PUSH_BUTTON_RIGHT  0x01  // Button right
#define HAL_PUSH_BUTTON_LEFT   0x02  // Button left
#define HAL_PUSH_BUTTON_SELECT 0x04  // Button select
#define HAL_KEY_BUTTON_UP      0x40  // Button up
#define HAL_KEY_BUTTON_DOWN    0x80  // Button down

​ 在hal_key.chalProcessKeyInterrupt函数中,Z-Stack原本的流程是先进入中断, 再轮询看是哪个按键按下, 但可能会出现一些问题,因此我们直接在中断函数中,保存按下的按键在keys变量中,并通过pHalKeyProcessFunction最终将其传给Onboard.c文件中的OnBoard_KeyCallback函数

/**************************************************************************************************
 * @fn      halProcessKeyInterrupt
 *
 * @brief   Checks to see if it's a valid key interrupt, saves interrupt driven key states for
 *          processing by HalKeyRead(), and debounces keys by scheduling HalKeyRead() 25ms later.
 *
 * @param
 *
 * @return
 **************************************************************************************************/
void halProcessKeyInterrupt (void)
{
  bool valid=FALSE;
  uint8 keys = 0; 
  if (HAL_KEY_SW_6_PXIFG & HAL_KEY_SW_6_BIT)  /* Interrupt Flag has been set */
  {
    HAL_KEY_SW_6_PXIFG = ~(HAL_KEY_SW_6_BIT); /* Clear Interrupt Flag */
	keys = HAL_KEY_SW_6;  // S1按下 added
    valid = TRUE;
  }

  if (HAL_KEY_JOY_MOVE_PXIFG & HAL_KEY_JOY_MOVE_BIT)  /* Interrupt Flag has been set */
  {
    HAL_KEY_JOY_MOVE_PXIFG = ~(HAL_KEY_JOY_MOVE_BIT); /* Clear Interrupt Flag */
	keys |= HAL_KEY_SW_7;  // S2按下 added
    valid = TRUE;
  }
  /* Invoke Callback if new keys were depressed */
  if (pHalKeyProcessFunction
#ifdef HAL_LEGACY_KEYS
    && keys //in legacy modes, only report key presses and do not report when a key is released
#endif
    )
  {
    (pHalKeyProcessFunction) (keys, HAL_KEY_STATE_NORMAL);
  } // added
  if (valid)
  {
    osal_start_timerEx (Hal_TaskID, HAL_KEY_EVENT, HAL_KEY_DEBOUNCE_VALUE);
  }
}

​ 将OnBorad.c文件中的OnBorad_KeyCallBack函数的shift变量修改如下,使其在S1S2其中一个触发时为true,然后OnBoard_SendKeys发送按键事件(KEY_CHANGE)和被触发按键的信息

void OnBoard_KeyCallback ( uint8 keys, uint8 state )
{
  uint8 shift;
  (void)state;

  shift = ((keys & HAL_KEY_SW_6)||(keys & HAL_KEY_SW_7)) ? true : false; // 需修改这里
	
  if ( OnBoard_SendKeys( keys, shift ) != ZSuccess ) // 发送按键事件
  {	
      ...
  }
}

​ 最后,编写应用层(zcl_samplexxx.c文件中)的按键处理函数zclSampleLight_HandleKeys完成相应的功能即可

static void zclSampleLight_HandleKeys( byte shift, byte keys )
{
  if(keys & HAL_KEY_SW_6)  // 按键S1被按下
  {
  	HalLedBlink(HAL_LED_1, 10, 50, 400);
	return;
  }
  if(keys & HAL_KEY_SW_7)  // 按键S2被按下
  {
	HalLedBlink(HAL_LED_2, 10, 50, 400);
  	return;
  }
}

​ 由于Z-Stack协议栈默认只用S1一个按键,若要用多个按键,则需根据以上步骤一步步修改代码(否则只需在zclSampleLight_HandleKeys完成S1处理事件即可),还是比较不方便的。

Uart移植

Z-Stack中,Uart的移植非常方便,只需在应用层写好初始化函数回调函数,即可使用串口功能。若习惯使用printf函数,则需重写putchar()函数,本文选择重写方式。

/* ==============  UART0 ==============*/
/**
* @brief 重写 putchar函数 UART0   Rx: P0_2  Tx: P0_3
*/
__near_func int putchar(int c)
{
    UTX0IF = 0;   // 清除发送标志位
    U0DBUF = (char)c;
    while(UTX0IF == 0);  // 等待发送成功  发送成功时 发送标志位复位
    return(c);
}

/**  
 * @fn      zclSampleSw_UartCB  
 *  
 * @brief   Uart Callback  
 */    
static void zclSampleLight_UartCB(uint8 port, uint8 event)    
{   
	unsigned char idx=0;
	memset(&UART_RxData, 0, sizeof(UART_RxData)); // 清空接收缓存
	while(Hal_UART_RxBufLen(HAL_UART_PORT_0))
	{
		HalUARTRead(HAL_UART_PORT_0, &UART_RxBuf, 1);
		if((UART_RxState == 0) && (idx == 0))  // 等待包头
		{
			if(UART_RxBuf == '@')
			{
				UART_RxState = 1;
			}
			else  // 清除接收缓存
			{
			  	U0UCR |= 0x80; // 清除 UART RX FIFO
				U0CSR &= ~0x40; // 关闭 UART 模块
				U0CSR |= 0x40;  // 重新启用 UART 模块  
				return;
			}
		}
		else if(UART_RxState == 1)  // 接收数据
		{
		  	if((UART_RxBuf != '\n') && (idx < ZCLSAMPLELIGHT_UART_BUF_LEN))
			{
				UART_RxData[idx++] = UART_RxBuf;  // 接收数据
			}
			else   // 收到包尾或超过最大
			{
				UART_RxState = 0;
				printf("Get Info:%s", UART_RxData);
			}
		}
	}
}

/**
* @brief Uart初始化
*/
void zclSampleLight_InitUart(void)
{    
	halUARTCfg_t uartConfig;    
	/* UART Configuration */  
	uartConfig.configured          = TRUE;//允许配置  
	uartConfig.baudRate            = HAL_UART_BR_19200;//波特率  
	uartConfig.flowControl         = FALSE;//关闭硬件流控  
	uartConfig.flowControlThreshold= 0;//和流控相关  
	uartConfig.rx.maxBufSize       = ZCLSAMPLELIGHT_UART_BUF_LEN;//接收缓冲区大小
	uartConfig.tx.maxBufSize      = 0;//发送缓冲区大小
	uartConfig.idleTimeout        = 10;//默认超时时间  
	uartConfig.intEnable          = TRUE;// 使能中断  
	uartConfig.callBackFunc       = zclSampleLight_UartCB;//设置回调函数
	/* Start UART */    
	HalUARTOpen(HAL_UART_PORT_0, &uartConfig);// 根据配置打开串口0  
}

​ 还需定义接收缓存和最大接收长度

#define ZCLSAMPLELIGHT_UART_BUF_LEN 128
unsigned char UART_RxBuf;   // 接收缓存
unsigned char UART_RxData[ZCLSAMPLELIGHT_UART_BUF_LEN];  // 数据保存
unsigned char UART_RxState = 0;  // 接收状态  0 等待包头'@'   1 接收数据
  • Note:
    • 值得注意的是,移植到Z-Stack后,若波特率设置为9600,则接收数据时可能出现乱码,丢包等情况,这时尝试用更高的波特率
    • 通过HalUARTOpen只能配置一个串口,若需要同时配置两个串口,另一个串口直接采用寄存器配置的方式Z-Stack默认不支持两个串口同时使用,修改协议栈很麻烦,直接用寄存器重新配置即可。后续我们CC2530ESP8266的通信会提供参考案例

LCD移植

​ 不同商家选用的LCD不同,一般情况下,将商家提供的驱动代码hal_lcd.hhal_lcd.c替换即可,根据自己开发板的教程来。

​ 常用API:

  • HalLcdWriteString ( char *str, uint8 option)

    HalLcdWriteString( "End-Device", HAL_LCD_LINE_1 );
    
  • HalLcdWriteStringValue( char *title, uint16 value, uint8 format, uint8 line )

    HalLcdWriteStringValue((char *)MSGpkt->cmd.Data,p2pCnt,10,3);
    

_lcd.c`替换即可,根据自己开发板的教程来。

​ 常用API:

  • HalLcdWriteString ( char *str, uint8 option)

    HalLcdWriteString( "End-Device", HAL_LCD_LINE_1 );
    
  • HalLcdWriteStringValue( char *title, uint16 value, uint8 format, uint8 line )

    HalLcdWriteStringValue((char *)MSGpkt->cmd.Data,p2pCnt,10,3);
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值