This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hi Guys,
I´m working with custom board to implement two switch buttons, S1 (P0.4) and S2 (P0.1), I cloned S1 (SW6) to S2 to implement it. I see in the HAL_ISR_FUNCTION( halKeyPort0Isr, P0INT_VECTOR ) and special registers also (with IAR Registers Panel) that when I pressed S1 and S2 the respective code associated with each works (hits) to some extent in the code.
I observing, using breakpoints, that in the HalKeyPoll for both buttons the lines HAL_PUSH_BUTTON1() and HAL_PUSH_BUTTON2() are reached. Its cause the Key values 0x20 (correct value) and 0x60 (0x20 + 0x040). After it both buttons provoke the same effects in the application, the lines are simultaneous reached keys & HAL_KEY_SW_6 and keys & HAL_KEY_SW_7.
I no have idea how to fix it. Someone, please can help me?
Note: I using Z-Stack Home 1.2.2a.44539, after implement it I´ll upgrade to Z-Stack 3.0.1.
Bellow I including all those configuration that have correlation on the S1 and S2 (hal_board_cfg.h, hal_key.c, hal_key.h and OnBoard.c)
hal_board_cfg.h /* S1 */ #define PUSH1_BV BV(4) #define PUSH1_SBIT P0_4 /* S2 */ #define PUSH2_BV BV(1) #define PUSH2_SBIT P0_1 #define PUSH1_POLARITY ACTIVE_HIGH #define PUSH2_POLARITY ACTIVE_HIGH 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 0x10 // Joystick left #define HAL_KEY_SW_3 0x08 // Joystick down ant 10 #define HAL_KEY_SW_6 0x20 // Button S2 #define HAL_KEY_SW_7 0x40 // Button S1 hal_key.c /************************************************************************************************** * @fn HalKeyConfig * * @brief Configure the Key serivce * * @param interruptEnable - TRUE/FALSE, enable/disable interrupt * cback - pointer to the CallBack function * * @return None **************************************************************************************************/ void HalKeyConfig (bool interruptEnable, halKeyCBack_t cback) { /* Enable/Disable Interrupt or */ Hal_KeyIntEnable = interruptEnable; /* Register the callback fucntion */ pHalKeyProcessFunction = cback; /* Determine if interrupt is enable or not */ if (Hal_KeyIntEnable) { /* Rising/Falling edge configuratinn */ PICTL &= ~(HAL_KEY_SW_6_EDGEBIT); /* Clear the edge bit */ /* For falling edge, the bit must be set. */ #if (HAL_KEY_SW_6_EDGE == HAL_KEY_FALLING_EDGE) PICTL |= HAL_KEY_SW_6_EDGEBIT; #endif /* Interrupt configuration: * - Enable interrupt generation at the port * - Enable CPU interrupt * - Clear any pending interrupt */ HAL_KEY_SW_6_ICTL |= HAL_KEY_SW_6_ICTLBIT; HAL_KEY_SW_6_IEN |= HAL_KEY_SW_6_IENBIT; HAL_KEY_SW_6_PXIFG = ~(HAL_KEY_SW_6_BIT); /* Rising/Falling edge configuratinn */ PICTL &= ~(HAL_KEY_SW_7_EDGEBIT); /* Clear the edge bit */ /* For falling edge, the bit must be set. */ #if (HAL_KEY_SW_7_EDGE == HAL_KEY_FALLING_EDGE) PICTL |= HAL_KEY_SW_7_EDGEBIT; #endif HAL_KEY_SW_7_ICTL |= HAL_KEY_SW_7_ICTLBIT; HAL_KEY_SW_7_IEN |= HAL_KEY_SW_7_IENBIT; HAL_KEY_SW_7_PXIFG = ~(HAL_KEY_SW_7_BIT); /* Rising/Falling edge configuratinn */ /* Interrupt configuration: * - Enable interrupt generation at the port * - Enable CPU interrupt * - Clear any pending interrupt */ /* Do this only after the hal_key is configured - to work with sleep stuff */ if (HalKeyConfigured == TRUE) { osal_stop_timerEx(Hal_TaskID, HAL_KEY_EVENT); /* Cancel polling if active */ } } else /* Interrupts NOT enabled */ { //HAL_KEY_SW_6_ICTL &= ~(HAL_KEY_SW_6_ICTLBIT); /* don't generate interrupt */ HAL_KEY_SW_6_IEN &= ~(HAL_KEY_SW_6_IENBIT); /* Clear interrupt enable bit */ osal_set_event(Hal_TaskID, HAL_KEY_EVENT); //HAL_KEY_SW_7_ICTL &= ~(HAL_KEY_SW_7_ICTLBIT); /* don't generate interrupt */ HAL_KEY_SW_7_IEN &= ~(HAL_KEY_SW_7_IENBIT); /* Clear interrupt enable bit */ osal_set_event(Hal_TaskID, HAL_KEY_EVENT); } /* Key now is configured */ HalKeyConfigured = TRUE; } /************************************************************************************************** * @fn HalKeyRead * * @brief Read the current value of a key * * @param None * * @return keys - current keys status **************************************************************************************************/ uint8 HalKeyRead ( void ) { uint8 keys = 0; if (HAL_PUSH_BUTTON1()) { keys |= HAL_KEY_SW_6; } if (HAL_PUSH_BUTTON2()) { keys |= HAL_KEY_SW_7; } return keys; } /************************************************************************************************** * @fn HalKeyPoll * * @brief Called by hal_driver to poll the keys * * @param None * * @return None **************************************************************************************************/ void HalKeyPoll (void) { uint8 keys = 0; /* If interrupts are not enabled, previous key status and current key status * are compared to find out if a key has changed status. */ if (!Hal_KeyIntEnable) { if (keys == halKeySavedKeys) { /* Exit - since no keys have changed */ return; } /* Store the current keys for comparation next time */ halKeySavedKeys = keys; } else { /* Key interrupt handled here */ } if (HAL_PUSH_BUTTON1()) { keys |= HAL_KEY_SW_6; } if (HAL_PUSH_BUTTON2()) { keys |= HAL_KEY_SW_7; } /* Invoke Callback if new keys were depressed */ if (keys && (pHalKeyProcessFunction)) { (pHalKeyProcessFunction) (keys, HAL_KEY_STATE_NORMAL); } } /************************************************************************************************** * @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; 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 */ valid = TRUE; } if (HAL_KEY_SW_7_PXIFG & HAL_KEY_SW_7_BIT) /* Interrupt Flag has been set */ { HAL_KEY_SW_7_PXIFG = ~(HAL_KEY_SW_7_BIT); /* Clear Interrupt Flag */ valid = TRUE; } if (valid) { osal_start_timerEx (Hal_TaskID, HAL_KEY_EVENT, HAL_KEY_DEBOUNCE_VALUE); } } OnBoard.c void OnBoard_KeyCallback ( uint8 keys, uint8 state ) { uint8 shift; (void)state; shift = (keys & HAL_KEY_SW_6) ? true : false; // shift = (keys & HAL_KEY_SW_7) ? true : false; if ( OnBoard_SendKeys( keys, shift ) != ZSuccess ) { // Process SW1 here if ( keys & HAL_KEY_SW_1 ) // Switch 1 { } // Process SW2 here if ( keys & HAL_KEY_SW_2 ) // Switch 2 { } // Process SW3 here if ( keys & HAL_KEY_SW_3 ) // Switch 3 { } // Process SW4 here if ( keys & HAL_KEY_SW_4 ) // Switch 4 { } // Process SW5 here if ( keys & HAL_KEY_SW_5 ) // Switch 5 { } // Process SW6 here if ( keys & HAL_KEY_SW_6 ) // Switch 6 { } // Process SW7 here if ( keys & HAL_KEY_SW_7 ) // Switch 7 { } } }
Hi Alexander,
HAL_PUSH_BUTTON1 should return HAL_KEY_SW_6 (0x20) and HAL_PUSH_BUTTON2 should return HAL_KEY_SW_7 (0x40). HAL_KEY_SW_6 | HAL_KEY_SW_7 (0x60) should not be returned unless both HAL_PUSH_BUTTON1 and HAL_PUSH_BUTTON2 return true. You should check your hardware lines to confirm that pushing one button does not somehow change the state of both input pins. Make sure to remove all joystick/joykey code (since it is not being used) and modify zclSample*_HandleKeys in zcl_sample*.c accordingly.
As the UI has changed between Z-Stack HA 1.2.2a and 3.0.x, I recommend you upgrade and evaluate whether behavior changes on the newer stack.
Regards,
Ryan
Hi Ryan, I´m happy to hear you!
I´ll make two external physical button, inspired by SmartRF05EB to connect to my custom board to do exhaustive tests today. But I would like to explain better What exaclty I have see.
I have use currently optocoupler to interface with CC2530, and two ways (PUSH1_SBIT/ P0_4 and PUSH2_SBIT/ P0_1) are completely isolated.
I thinks there is something wrong with my code, the breakpoint hits correctly when I pressed S1 and S2, HAL_ISR_Function is reached when pressed S2 HAL_KEY_SW_6_PXIFG & HAL_KEY_SW_6_BIT and HAL_KEY_SW_7_PXIFG & HAL_KEY_SW_7_BIT when I pressed S1.
The stranger behavior occurs in the HalKeyPoll. For each one S1 or S2 buttons are pressed the BUTTON1 and BUTTON 2 are reached sequentially, and it causes incorrect Key values. As you can see in the PICs bellow:
HalKeyPoll uses HAL_PUSH_BUTTONX to determine if the pin states are active or not based on the determined polarity. Given your register values and the hal_board_cfg.h configuration I would expect both to return true at any time. This could be some issue involving optimization from the IAR compiler. I recommend working around the issue by using an if else statement or remove the need for polling entirely and depend solely on interrupt operation.
Regards,
Ryan
Can you attach your hal_key.c and what you define “HAL_PUSH_BUTTON1” and “HAL_PUSH_BUTTON2”?
Hi Ryan,
I totally Igree with you about some issue involving IAR compiler.
I tried to use interrupt register as working around, but after the interrupt is reached ( HAL_ISR_FUNCTION) for P0_4 or P0_1, in the hal_key.c, the register HAL_KEY_SW_6_PXIFG clear this interrupt, I made some test to comment out it and include the clear procedure inside the hallKeyPool function but I didn´t have success.
I used also else statement as working aroud but, when i included after this always the Button1 is reached for SW6 or SW7 interrupts.
if (HAL_PUSH_BUTTON1())
{
keys |= HAL_KEY_SW_6;
} else if (HAL_PUSH_BUTTON2())
{
keys |= HAL_KEY_SW_7;
}
Note: I changed the Sx and SWx correlation, right now S1 is triggering SW6 and S2 triggering SW7.
Hi Mr YK, as you requested me cloud you see attached the hal_key.c
Note: When I cloned the SW6 code lines to include the SW7 I have some doubts if i need to clone this line in the OnBoard.c (OnBoard_KeyCallback function):
shift = (keys & HAL_KEY_SW_6) ? true : false;
Unfortunately I do not have any further suggestions at the moment.
Regards,
Ryan
Sorry mr YK. I Forgot to include the file!
/************************************************************************************************** Filename: hal_key.c Revised: $Date: 2010-09-15 19:02:45 -0700 (Wed, 15 Sep 2010) $ Revision: $Revision: 23815 $ Description: This file contains the interface to the HAL KEY Service. Copyright 2006-2010 Texas Instruments Incorporated. All rights reserved. IMPORTANT: Your use of this Software is limited to those specific rights granted under the terms of a software license agreement between the user who downloaded the software, his/her employer (which must be your employer) and Texas Instruments Incorporated (the "License"). You may not use this Software unless you agree to abide by the terms of the License. The License limits your use, and you acknowledge, that the Software may not be modified, copied or distributed unless embedded on a Texas Instruments microcontroller or used solely and exclusively in conjunction with a Texas Instruments radio frequency transceiver, which is integrated into your product. Other than for the foregoing purpose, you may not use, reproduce, copy, prepare derivative works of, modify, distribute, perform, display or sell this Software and/or its documentation for any purpose. YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE PROVIDED �AS IS� WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS. Should you have any questions regarding your right to use this Software, contact Texas Instruments Incorporated at www.TI.com. **************************************************************************************************/ /********************************************************************* NOTE: If polling is used, the hal_driver task schedules the KeyRead() to occur every 100ms. This should be long enough to naturally debounce the keys. The KeyRead() function remembers the key state of the previous poll and will only return a non-zero value if the key state changes. NOTE: If interrupts are used, the KeyRead() function is scheduled 25ms after the interrupt occurs by the ISR. This delay is used for key debouncing. The ISR disables any further Key interrupt until KeyRead() is executed. KeyRead() will re-enable Key interrupts after executing. Unlike polling, when interrupts are enabled, the previous key state is not remembered. This means that KeyRead() will return the current state of the keys (not a change in state of the keys). NOTE: If interrupts are used, the KeyRead() fucntion is scheduled by the ISR. Therefore, the joystick movements will only be detected during a pushbutton interrupt caused by S1 or the center joystick pushbutton. NOTE: When a switch like S1 is pushed, the S1 signal goes from a normally high state to a low state. This transition is typically clean. The duration of the low state is around 200ms. When the signal returns to the high state, there is a high likelihood of signal bounce, which causes a unwanted interrupts. Normally, we would set the interrupt edge to falling edge to generate an interrupt when S1 is pushed, but because of the signal bounce, it is better to set the edge to rising edge to generate an interrupt when S1 is released. The debounce logic can then filter out the signal bounce. The result is that we typically get only 1 interrupt per button push. This mechanism is not totally foolproof because occasionally, signal bound occurs during the falling edge as well. A similar mechanism is used to handle the joystick pushbutton on the DB. For the EB, we do not have independent control of the interrupt edge for the S1 and center joystick pushbutton. As a result, only one or the other pushbuttons work reasonably well with interrupts. The default is the make the S1 switch on the EB work more reliably. *********************************************************************/ /************************************************************************************************** * INCLUDES **************************************************************************************************/ #include "hal_mcu.h" #include "hal_defs.h" #include "hal_types.h" #include "hal_board.h" #include "hal_drivers.h" #include "hal_adc.h" #include "hal_key.h" #include "osal.h" #if (defined HAL_KEY) && (HAL_KEY == TRUE) /************************************************************************************************** * MACROS **************************************************************************************************/ /************************************************************************************************** * CONSTANTS **************************************************************************************************/ #define HAL_KEY_RISING_EDGE 0 #define HAL_KEY_FALLING_EDGE 1 #define HAL_KEY_DEBOUNCE_VALUE 100 /* CPU port interrupt */ #define HAL_KEY_CPU_PORT_0_IF P0IF #define HAL_KEY_CPU_PORT_2_IF P2IF /* edge interrupt */ #define HAL_KEY_SW_6_EDGEBIT BV(0) #define HAL_KEY_SW_6_EDGE HAL_KEY_RISING_EDGE #define HAL_KEY_SW_7_EDGEBIT BV(0) #define HAL_KEY_SW_7_EDGE HAL_KEY_RISING_EDGE /* SW_6 - S1 settings at P0.1 */ // - Definitions #define HAL_KEY_SW_6_ENABLE #define HAL_KEY_SW_6_PORT P0 #define HAL_KEY_SW_6_BIT BV(1) #define HAL_KEY_SW_6_SEL P0SEL #define HAL_KEY_SW_6_DIR P0DIR /* SW_6 interrupts */ #define HAL_KEY_SW_6_IEN IEN1 /* CPU interrupt mask register */ #define HAL_KEY_SW_6_IENBIT BV(5) /* IEN1/P0IE Mask bit for all of Port_0 */ #define HAL_KEY_SW_6_ICTL P0IEN /* Port Interrupt Control register */ #define HAL_KEY_SW_6_ICTLBIT BV(1) /* P0IEN - P0.1 enable/disable bit */ #define HAL_KEY_SW_6_PXIFG P0IFG /* Interrupt flag at source */ /* SW_7 - S2 settings at P0.4 */ //- Definitions #define HAL_KEY_SW_7_ENABLE #define HAL_KEY_SW_7_PORT P0 #define HAL_KEY_SW_7_BIT BV(4) #define HAL_KEY_SW_7_SEL P0SEL #define HAL_KEY_SW_7_DIR P0DIR /* SW_7 interrupts */ #define HAL_KEY_SW_7_IEN IEN1 /* CPU interrupt mask register */ #define HAL_KEY_SW_7_IENBIT BV(5) /* IEN1/P0IE Mask bit for all of Port_0 */ #define HAL_KEY_SW_7_ICTL P0IEN /* Port Interrupt Control register */ #define HAL_KEY_SW_7_ICTLBIT BV(4) /* P0IEN - P0.4 enable/disable bit */ #define HAL_KEY_SW_7_PXIFG P0IFG /* Interrupt flag at source */ /* Joy stick move at P2.0 */ /* edge interrupt */ /* Joy move interrupts */ /************************************************************************************************** * TYPEDEFS **************************************************************************************************/ /************************************************************************************************** * GLOBAL VARIABLES **************************************************************************************************/ static uint8 halKeySavedKeys; /* used to store previous key state in polling mode */ static halKeyCBack_t pHalKeyProcessFunction; static uint8 HalKeyConfigured; bool Hal_KeyIntEnable; /* interrupt enable/disable flag */ /************************************************************************************************** * FUNCTIONS - Local **************************************************************************************************/ void halProcessKeyInterrupt(void); uint8 halGetJoyKeyInput(void); uint8 halGetSWKeyInput(void); /************************************************************************************************** * FUNCTIONS - API **************************************************************************************************/ /************************************************************************************************** * @fn HalKeyInit * * @brief Initilize Key Service * * @param none * * @return None **************************************************************************************************/ void HalKeyInit( void ) { /* Initialize previous key to 0 */ halKeySavedKeys = 0; HAL_KEY_SW_6_SEL &= ~(HAL_KEY_SW_6_BIT); /* Set pin function to GPIO */ HAL_KEY_SW_6_DIR &= ~(HAL_KEY_SW_6_BIT); /* Set pin direction to Input */ HAL_KEY_SW_7_SEL &= ~(HAL_KEY_SW_7_BIT); /* Set pin function to GPIO */ HAL_KEY_SW_7_DIR &= ~(HAL_KEY_SW_7_BIT); /* Set pin direction to Input */ /* Initialize callback function */ pHalKeyProcessFunction = NULL; /* Start with key is not configured */ HalKeyConfigured = FALSE; } /************************************************************************************************** * @fn HalKeyConfig * * @brief Configure the Key serivce * * @param interruptEnable - TRUE/FALSE, enable/disable interrupt * cback - pointer to the CallBack function * * @return None **************************************************************************************************/ void HalKeyConfig (bool interruptEnable, halKeyCBack_t cback) { /* Enable/Disable Interrupt or */ Hal_KeyIntEnable = interruptEnable; /* Register the callback fucntion */ pHalKeyProcessFunction = cback; /* Determine if interrupt is enable or not */ if (Hal_KeyIntEnable) { /* Rising/Falling edge configuratinn */ PICTL &= ~(HAL_KEY_SW_6_EDGEBIT); /* Clear the edge bit */ /* For falling edge, the bit must be set. */ #if (HAL_KEY_SW_6_EDGE == HAL_KEY_FALLING_EDGE) PICTL |= HAL_KEY_SW_6_EDGEBIT; #endif /* Interrupt configuration: * - Enable interrupt generation at the port * - Enable CPU interrupt * - Clear any pending interrupt */ HAL_KEY_SW_6_ICTL |= HAL_KEY_SW_6_ICTLBIT; HAL_KEY_SW_6_IEN |= HAL_KEY_SW_6_IENBIT; HAL_KEY_SW_6_PXIFG = ~(HAL_KEY_SW_6_BIT); /* Rising/Falling edge configuratinn */ PICTL &= ~(HAL_KEY_SW_7_EDGEBIT); /* Clear the edge bit */ /* For falling edge, the bit must be set. */ #if (HAL_KEY_SW_7_EDGE == HAL_KEY_FALLING_EDGE) PICTL |= HAL_KEY_SW_7_EDGEBIT; #endif HAL_KEY_SW_7_ICTL |= HAL_KEY_SW_7_ICTLBIT; HAL_KEY_SW_7_IEN |= HAL_KEY_SW_7_IENBIT; HAL_KEY_SW_7_PXIFG = ~(HAL_KEY_SW_7_BIT); /* Rising/Falling edge configuratinn */ /* Interrupt configuration: * - Enable interrupt generation at the port * - Enable CPU interrupt * - Clear any pending interrupt */ /* Do this only after the hal_key is configured - to work with sleep stuff */ if (HalKeyConfigured == TRUE) { osal_stop_timerEx(Hal_TaskID, HAL_KEY_EVENT); /* Cancel polling if active */ } } else /* Interrupts NOT enabled */ { //HAL_KEY_SW_6_ICTL &= ~(HAL_KEY_SW_6_ICTLBIT); /* don't generate interrupt */ HAL_KEY_SW_6_IEN &= ~(HAL_KEY_SW_6_IENBIT); /* Clear interrupt enable bit */ osal_set_event(Hal_TaskID, HAL_KEY_EVENT); //HAL_KEY_SW_7_ICTL &= ~(HAL_KEY_SW_7_ICTLBIT); /* don't generate interrupt */ HAL_KEY_SW_7_IEN &= ~(HAL_KEY_SW_7_IENBIT); /* Clear interrupt enable bit */ osal_set_event(Hal_TaskID, HAL_KEY_EVENT); } /* Key now is configured */ HalKeyConfigured = TRUE; } /************************************************************************************************** * @fn HalKeyRead * * @brief Read the current value of a key * * @param None * * @return keys - current keys status **************************************************************************************************/ uint8 HalKeyRead ( void ) { uint8 keys = 0; if (HAL_PUSH_BUTTON1()) { keys |= HAL_KEY_SW_6; } if (HAL_PUSH_BUTTON2()) { keys |= HAL_KEY_SW_7; } return keys; } /************************************************************************************************** * @fn HalKeyPoll * * @brief Called by hal_driver to poll the keys * * @param None * * @return None **************************************************************************************************/ void HalKeyPoll (void) { uint8 keys = 0; /* If interrupts are not enabled, previous key status and current key status * are compared to find out if a key has changed status. */ if (!Hal_KeyIntEnable) { if (keys == halKeySavedKeys) { /* Exit - since no keys have changed */ return; } /* Store the current keys for comparation next time */ halKeySavedKeys = keys; } else { /* Key interrupt handled here */ } if (HAL_PUSH_BUTTON1()) { keys |= HAL_KEY_SW_6; } if (HAL_PUSH_BUTTON2()) { keys |= HAL_KEY_SW_7; } /* Invoke Callback if new keys were depressed */ if (keys && (pHalKeyProcessFunction)) { (pHalKeyProcessFunction) (keys, HAL_KEY_STATE_NORMAL); } } /************************************************************************************************** * @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; 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 */ valid = TRUE; } if (HAL_KEY_SW_7_PXIFG & HAL_KEY_SW_7_BIT) /* Interrupt Flag has been set */ { HAL_KEY_SW_7_PXIFG = ~(HAL_KEY_SW_7_BIT); /* Clear Interrupt Flag */ valid = TRUE; } if (valid) { osal_start_timerEx (Hal_TaskID, HAL_KEY_EVENT, HAL_KEY_DEBOUNCE_VALUE); } } /************************************************************************************************** * @fn halGetSWKeyInput * * @brief Map the multiple keys interrupts. * * @param None * * @return keys - current joy key status **************************************************************************************************/ uint8 halGetSWKeyInput(void) { /* The joystick control is encoded as an analog voltage. * Read the Multiple Key Interrrupt value and map it to correct key. */ uint8 ksave0 = 0; uint8 ksave1; /* Keep on reading the two consecutive key decisions are the same. */ do { ksave1 = ksave0; /* save previouse key reading */ if (HAL_PUSH_BUTTON1()) { ksave0 |= HAL_KEY_SW_6; } else if(HAL_PUSH_BUTTON2()) { ksave0 |= HAL_KEY_SW_7; } } while (ksave0 != ksave1); return ksave0; } /************************************************************************************************** * @fn HalKeyEnterSleep * * @brief - Get called to enter sleep mode * * @param * * @return **************************************************************************************************/ void HalKeyEnterSleep ( void ) { } /************************************************************************************************** * @fn HalKeyExitSleep * * @brief - Get called when sleep is over * * @param * * @return - return saved keys **************************************************************************************************/ uint8 HalKeyExitSleep ( void ) { /* Wake up and read keys */ return ( HalKeyRead () ); } /*************************************************************************************************** * INTERRUPT SERVICE ROUTINE ***************************************************************************************************/ /************************************************************************************************** * @fn halKeyPort0Isr * * @brief Port0 ISR * * @param * * @return **************************************************************************************************/ HAL_ISR_FUNCTION( halKeyPort0Isr, P0INT_VECTOR ) { HAL_ENTER_ISR(); if (HAL_KEY_SW_6_PXIFG & HAL_KEY_SW_6_BIT ) { halProcessKeyInterrupt(); /* Clear the CPU interrupt flag for Port_0 PxIFG has to be cleared before PxIF */ HAL_KEY_SW_6_PXIFG = 0; HAL_KEY_CPU_PORT_0_IF = 0; } if (HAL_KEY_SW_7_PXIFG & HAL_KEY_SW_7_BIT) { halProcessKeyInterrupt(); /* Clear the CPU interrupt flag for Port_0 PxIFG has to be cleared before PxIF */ HAL_KEY_SW_7_PXIFG = 0; HAL_KEY_CPU_PORT_0_IF = 0; } CLEAR_SLEEP_MODE(); HAL_EXIT_ISR(); } /************************************************************************************************** * @fn halKeyPort2Isr * * @brief Port2 ISR * * @param * * @return **************************************************************************************************/ HAL_ISR_FUNCTION( halKeyPort2Isr, P2INT_VECTOR ) { } #else void HalKeyInit(void){} void HalKeyConfig(bool interruptEnable, halKeyCBack_t cback){} uint8 HalKeyRead(void){ return 0;} void HalKeyPoll(void){} #endif /* HAL_KEY */ /************************************************************************************************** **************************************************************************************************/
Ryan, thanks a lot. Today I´ll finish the auxiliary hardware to test buttons according SMARTRF05 as I had promised you!
About IAR working around, do you see another way to check it without HAL_KEY_SW_6_PXIFG flags?
Your hal_key.c looks good. What are defines of your PUSH1_BV/PUSH1_SBIT and PUSH2_BV/PUSH2_SBIT? I suggest you using scope to monitor S1 and S2 signal when you set breakpoint and debug into "if (HAL_PUSH_BUTTON1())..." and "if (HAL_PUSH_BUTTON2())..." in hallKeyPool.
Mr Yk,
Regarding the Push Button Configuration (PUSH1_BV/PUSH1_SBIT and PUSH2_BV/PUSH2_SBIT) defined in the hal_board_cfg.h, you can see in the code below:
Soon, I´ll iforme you more details about the Signal observed in SCOPE when S1 and S2 are pressed.
Br,
AlexFullscreen123456789101112131415161718/* ------------------------------------------------------------------------------------------------* 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#define PUSH1_POLARITY ACTIVE_HIGH/* S2 */#define PUSH2_BV BV(4)#define PUSH2_SBIT P0_4#define PUSH2_POLARITY ACTIVE_HIGHXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/* ------------------------------------------------------------------------------------------------ * 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 #define PUSH1_POLARITY ACTIVE_HIGH /* S2 */ #define PUSH2_BV BV(4) #define PUSH2_SBIT P0_4 #define PUSH2_POLARITY ACTIVE_HIGH
Your (PUSH1_BV/PUSH1_SBIT and PUSH2_BV/PUSH2_SBIT) definitions look good. Next, you should use scope to check signal and debug it.
Mr YK.
I did the test using my custom board and SmartRF05 BB and I saw see the same effects or behavior in the HalKeyPoll, as I told before PUSH_BUTTON1 and PUSH_BUTTON2) were triggered senquencially. I prefed to take off my custom board and using SCOPE over SmartRF05 BB.
I cant see any electrical behavior that explain the main problem!
As you can see bellow:
SmartRF05 BB - Scope definitions and measurements.
S1 and S2 Scope Measurement without SOC GPIO PINs Connections (P0_1 and P0_4)
S1 and S2 Scope Measurement with SOC GPIO PINs Connected (P0_1 and P0_4)
S1 Pressed - Observed during KeyPoll breakpoint was reached
S2 Pressed - Observed during KeyPoll breakpoint was reached
Try to set breakpoints on "if (HAL_PUSH_BUTTON1())" and "if (HAL_PUSH_BUTTON2())" in your key_poll function. Then, press S1 or S2 to check values of P0_1 and P0_4 in your watch window and check P0.1 and P0.4 pins on scope at the same time to see the voltage level on those two pins and their reading.
Hi Mr. Yk.
As you told me I seted breakpoints on if (HAL_PUSH_BUTTON1())" and "if (HAL_PUSH_BUTTON2()) and saw that at this moment P0_1 and P0_4 kept presenting value = 1 (Active state). Even I pressing both buttons.
Please, can you give me an idea what is causing the P0_1/P0_4 always present value one?
Breakpoint at HAL_PUSH_BUTTON1()/HAL_PUSH_BUTTON2() and P0_1/P0_4 status - S1 or S2 are pressed:
S1 Pressed - Electrical Signal during breakpoint at HAL_PUSH_BUTTON1()/HAL_PUSH_BUTTON2()
Mr Yk,
I got P0SEL and P0DIR status during the breakpoints as you requested me. In additional I have include the port activation according my application file.
Port activation settings - App file
App profile 1 - EndPoint 1 P0SEL &= (~BV(0)); // LED GREEN CIRC. 1 P1SEL &= (~BV(4)); // RELAY CIRC. 1 P0DIR |= (BV(0)); P1DIR |= (BV(4)); App profile 2 - EndPoint 2 P0SEL &= (~BV(5)); // LED GREEN CIRC 2 P1SEL &= (~BV(5)|BV(6)); // RELAY CIRC 2 and RESET SWITCH P0DIR |= (BV(5)); P1DIR |= (BV(5)|BV(6));
Sorry Mr YK, I cant past the PIC before, I dint know why the insert file doesn't work for me.
P0SEL&P0DIR Before breakpoints
P0SEL&P0DIR after breakpoints reached.
BR,
Alex
Mr YK, I try to find in my code why SELP0_4 is set to 1 but I dind´t find anything to explain it. Do you have any idea?
Would you can see bellow PICs of my attempt to find.
BR,
Alex
You can try to debug step. Y step before and after key initialization to see where P0SEL is changed.
Mr YK,
As you advise-me I have debug set by step into key initialization and I found the code line that starts P0SEL_4 on the MT UART Inicialization procedure at specific line PxOUT &= ~HAL_UART_Px_RTS (Flow Control).
I follow those steps to found it:
Hal_key.c
.
.
.
OSAL.c
osal_init_system
OSAL_AZh0004.c
MT_TaskInit( taskID++ );
MT_TASK.c
MT_UartInit();
void MT_UartInit ()
if (config->flowControl)
PxOUT &= ~HAL_UART_Px_RTS
Mr Yk, please, Would you can advise me how do I change this behavior without damaging UART communication?
Hi Mr Yk,
Thanks a lot for your assistance!
I comment out the flow control procedure and P0SEL_4 stoped changing from zero to one, as you can see below, but I still have the double selection of Button 1 and Button 2 on HallKeyPoll. I can´t found nothing to explain it.
note:
Sorry for my wrong information before about the location, it is called from hal_uart.c and located at _hal_uart_dma.c.
_hal_uart_dma.c
HalUARTOpenDMA
if (config->flowControl)
Since both value of P0_1 and P0_4 are 1, it is normal to see both if statements are hit. Since you set both S1 and S2 to active high, you should check your HW to know why you only press S1 but both S1 and S2 go to high level.
Mr YK,
I changed from my device to SmartRF05 BB at the beginning, to not include other variables!
After you last post I changed the PUSH1_POLARITY and PUSH2_POLARITY from ACTIVE_HIGH to ACTIVE_LOW and after it the both statements (button 1 and Button 2) are HIT, Sorry my mistake is here after you advise how to fix P0SEL_4, running only when I make double click in the button!
Do you have and Idea why the statements are hit only when I do double click on the buttons?
Maybe due to button debounce. If you try to press button longer, can it hit with only one press?
Mr Yk! I´m very happy!
Wonderful, at this moment everything working!
About double click, I fixed it change the HAL_KEY_SW_X_EDGE form HAL_KEY_RISING_EDGE to HAL_KEY_FALLING_EDGE!
just to summarize to ALL the changes, considering my configurations conditions, for future queries:
- Comment out flow control on _hal_uart_dma.c, to fix P0SEL_4 that was always active (high level)
- Make sure you are using key state configuration at PUSHX_POLARITY correctly, in my case ACTIVE_LOW
- Make sure you are using key transaction signal correctly at HAL_KEY_SW_X_EDGE correctly, in my case HAL_KEY_FALLING_EDGE
Thank you very much!!!!
You are the best!!!
BR,
Alex
It's good to know it works now. Please help to mark this thread as answered. Thanks.