Hello,
This time I try to program a broadcaster that sends temperature and humidity.
So I used the sample project SimpleBLEBroadcaster and replaced the files simpleBLEBroadcaster.c and simpleBLEBroadcaster.h with my own files MesUnit.c/.h this files I added to this Post.
My own task includes th following events:
- SYS_EVENT_MSG:
Just deallocates a received message
- START_DEVICE :
This Event is set by the init function of my task
Calls the function GAPRole_StartDevice for setting the callback function that is called,
when the profile state is changing (just used for switch an LED on and of)
Sets the event UPDATE_TEMP_RH
- UPDATE_TEMP_RH:
reads the temperature from an external sensor via I2C
updates the advertising data
sets a timer that will set the START_ADVERT event after 2s
- START_ADVERT:
starts the advertising
sets a timer that will set the STOP_ADVERT event after 0,5s
- STOP_ADVERT:
stops the advertising
sets a timer that will set the UPDATE_TEMP_RHevent after 4,2s
So a endless loop is created: UPDATE_TEMP_RH --> START_ADVERT --> STOP_ADVERT --> UPDATE_TEMP_RH
Sometimes the advertising starts and stops a view times before the stack pointer runs outside the stack sometime it only stats once.
I don't know why. So can anybody help me please?MeasUnit.h
#include "MeasUnit.h" #include "att.h" #include "gap.h" #include "broadcaster.h" #include "hal_i2c.h" #define EXTERNAL_VOLTAGE_SUPPLY // Nummer des MeasUnit-Task uint8 MeasUnit_ProcessEvent_TaskID; uint8 EndlessTask_TaskID; gapAdvertisingParams_t params; // Zeit bis die temperatur und Luftfeuchtigkeit upgedated werden #define SLEEP_BETWEEN_MEASURING 6000 // What is the advertising interval when device is discoverable (units of 625us, 160=100ms) #define DEFAULT_ADVERTISING_INTERVAL 480 //Callbackfunction that is called when Gap Role has changed static void gapRoleChanged( gaprole_States_t newState ); static gapRolesCBs_t GapCallBacks = { gapRoleChanged, // Profile State Change Callbacks NULL // When a valid RSSI is read from controller (not used by application) }; uint8 myBleAddress[] = {0x00, 0x00, 0x19, 0x86, 0x22, 0x07}; uint8 timerset=0; uint8 advertising_enable= TRUE; bStatus_t bLED=0; // GAP - Advertisement data (max size = 31 bytes, though this is // best kept short to conserve power while advertisting) static uint8 advertData[] = { // Flags; this sets the device to use limited discoverable // mode (advertises for 30 seconds at a time) instead of general // discoverable mode (advertises indefinitely) 0x02, // length of this data GAP_ADTYPE_FLAGS, GAP_ADTYPE_FLAGS_GENERAL+GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED, 0x09, // length of this data GAP_ADTYPE_LOCAL_NAME_COMPLETE, 0x54, // 'T' 0x65, // 'e' 0x6d, // 'm' 0x70, // 'p' 0x73, // 's' 0x65, // 'e' 0x6e, // 'n' 0x73, // 's' // Tx power level 0x02, // length of this data GAP_ADTYPE_POWER_LEVEL, 0, // 0dBm // three-byte broadcast of the data "1 2 3" 0x08, // length of this data including the data type byte GAP_ADTYPE_MANUFACTURER_SPECIFIC, // manufacturer specific advertisement data type NT_COMPANY_ID, // Company ID 0x01, // Node ID 0x00, // Temp LSB 0x00,// Temp MSB 0x00,// Luftf LSB 0x00,// Luftf MSB }; /********************************************************************* * @fn SHT21_config * * @brief This function is called for configurate the SHT21/25. * SHT21/25 will be configurated that he reads Temperature * with 12 Bit and humidity with 8 Bit resolution. * * @param No parameter * @return No return */ void SHT21_config(void) { uint8 w_Reg[3]; uint8 r_Reg[3]; do { P1 &= 0xBF; // Definiere den Inhalt f�r das Register welches per I2C gesendet wird // ( Die Adresse des SHT21 wurde in der HalDriverInit Funktion definiert w_Reg[0] = write_userreg; // Befehl zum schreiben in das User Register w_Reg[1] = 0x01; // Zu schreibender Inhalt f�r das Userregister (8 Bit RH and 12 Bit Temp) w_Reg[2] = read_userreg; // Befehl auslesen des User Registers HalI2CWrite(3,w_Reg); // Sende die Daten des write Registers r_Reg[0] = 0; // Setze das read Register auf 0 r_Reg[1] = 0; // Setze das read Register auf 0 r_Reg[2] = 0; // Setze das read Register auf 0 HalI2CRead(1,r_Reg); // Empfange den Inhalt des Userregisters des SHT21 } while(r_Reg[0] != 0x01); // Kontrolliere ob das Userregister des SHT21 korrekt ist, ... // ... wenn nicht schreibe ihn erneut if (HalI2CReady2Sleep()) { HalI2CEnterSleep(); } return; } /********************************************************************* * @fn PORT_config * * @brief This function configurates the Controllerprts: * P2.0 will be configurated and aktivated as an Interruptpin * P0.7 will be defined as an output for the LED * P1.2 will be defined as an output for enabling the voltage divider before the A/D-converter * * @param No parameter * @return No return */ void PORT_config(void) { // Ge�ndert 29.08.2012 //************************ //* Port 2 konfigurieren * //************************ //IRCON2 &= 0xFE; // Interruptflag l�schen P2DIR &= 0xFF; // P2DIR &= 0xFE; // P2.0 Als Eingang // PICTL |= 0x08; // P2ICON = 1 -> P2.0 - P2.3 Interrupts with falling edge //IEN0 |= 0x80; // Global enable of the Interrupts //P2IEN |= 0x01; // Enable Port2.0 Interrupt //P2IEN &= 0x01; // //IEN2 |= 0x02; // Enable the Port 2 Interrupt //*********************** // Port 0 konfigurieren * //*********************** P0DIR |= 0x80; // P0.7 als Ausgang (LED) P0 |= OWN_LED; // LED anfangs ausschalten //P0 |= 0x80; // LED zum Anfang aus (Low-Aktiv) P0DIR &= 0xFE; // Configuate P0.0 as an input APCFG |= 0x01; // Configurate the P0.0 Pin as an analog input P0DIR |= 0x7C; // P0.1 - P0.6 als Ausg�nge P0 &= 0x81; // P0.1 - P0.6 auf LOW //************************ //* Port 1 konfigurieren * //************************ P1DIR |= 0x40; // P1.6 als Ausgang (Spannung an den SHT21 anlegen) P1 |= 0x40; // Spannung noch nicht an den SHT21 anlegen (Low-Aktiv) P1DIR |= 0x04; // P1.2 als Ausgang (Freischalten AD-Wandlung) P1 |= 0x04; // Zu beginn nicht frei geschalten (Low-Aktiv) P1DIR |= 0xB9; // P1.0, P1.3, P1.4, P1.5 und P1.7 als Ausg�nge 1011 1001 = 0xB9 P1 |= 0x46; // P1.0, P1.3, P1.4, P1.5 und P1.7 auf LOW ~1011 1001 = 0100 0110 = 0x46 return; } /********************************************************************* * @fn MeasUnit_Init * * @brief Initializes the MeasUnit Task * * @param uint8 task_id, uint16 events * @return uint16 events */ void MeasUnit_Init( uint8 task_id ) { MeasUnit_ProcessEvent_TaskID = task_id; PORT_config(); SHT21_config(); uint16 gapRole_AdvertOffTime = 200; // Advert off after 100ms uint8 advType = GAP_ADTYPE_ADV_NONCONN_IND; // use non-connectable advertisements GAPRole_SetParameter( GAPROLE_ADVERT_OFF_TIME, sizeof( uint16 ), &gapRole_AdvertOffTime ); GAPRole_SetParameter( GAPROLE_ADVERT_DATA, sizeof( advertData ), advertData ); GAPRole_SetParameter( GAPROLE_ADV_EVENT_TYPE, sizeof( uint8 ), &advType ); uint16 advInt = DEFAULT_ADVERTISING_INTERVAL; GAP_SetParamValue( TGAP_LIM_DISC_ADV_INT_MIN, advInt ); GAP_SetParamValue( TGAP_LIM_DISC_ADV_INT_MAX, advInt ); GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MIN, advInt ); GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MAX, advInt ); osal_set_event(MeasUnit_ProcessEvent_TaskID, START_DEVICE ); params.eventType = GAP_ADTYPE_ADV_NONCONN_IND; //!< Advertise Event Type: @ref GAP_ADVERTISEMENT_TYPE_DEFINES params.initiatorAddrType = ADDRTYPE_PUBLIC; //!< Initiator's address type: @ref GAP_ADDR_TYPE_DEFINES //params.initiatorAddr ={0,0,0,1,2,3}; //!< Initiator's addr - used only with connectable directed eventType (ADV_EVTTYPE_CONNECTABLE_DIRECTED). params.channelMap = GAP_ADVCHAN_ALL; //!< Channel Map: Bit mask @ref GAP_ADVCHAN_DEFINES params.filterPolicy = 0; //!< Filer Policy: @ref GAP_FILTER_POLICY_DEFINES. Ignored when directed advertising is used. } /********************************************************************* * @fn MeasUnit_ProcessEvent * * @brief * * @param uint8 task_id, uint16 events * @return uint16 events */ uint16 MeasUnit_ProcessEvent ( uint8 task_id, uint16 events ) { uint8 w_Reg[3]; uint8 r_Reg[3]; uint32 Temperatur_int; uint16 Luftfeuchte_int; uint8* msgPtr; // Verschiedene Events Handeln if ( events & START_DEVICE ) { // Start the Device VOID GAPRole_StartDevice( &GapCallBacks ); osal_set_event(task_id, UPDATE_TEMP_RH); return (events ^ START_DEVICE ); } if ( events & SYS_EVENT_MSG ) { msgPtr = osal_msg_receive(Hal_TaskID); while (msgPtr) { /* Do something here - for now, just deallocate the msg and move on */ /* De-allocate */ osal_msg_deallocate( msgPtr ); /* Next */ msgPtr = osal_msg_receive( Hal_TaskID ); } return (events ^ SYS_EVENT_MSG); } if (events & UPDATE_TEMP_RH) // Bereit zum messen { HalI2CExitSleep(); /*****************************************************************************************************/ /*** Temperatur einlesen *****************************************************************************/ /*****************************************************************************************************/ w_Reg[0] = trig_t_h; // Lade das Triggerkommando zum Messen der Temperatur HalI2CWrite(1,w_Reg); // Sende das Triggerkommando zum Messen der Temperatur HalI2CRead(3,r_Reg); // Lese die Temperaturantwort in das read Register Temperatur_int = ((r_Reg[0]*256)+(r_Reg[1]&0xF0)); /* Urspr�ngliche Berechnung: Temperatur_float = (float)Temperatur_int; Temperatur_float *= 175.720; Temperatur_float /= 65536.000; Temperatur_float -= 46.850; */ //Neu umgeschriebene Berechnung: // X * 175720 = X * (8 * 21965) Temperatur_int *= 21965; // Temperatur_int << 3; // *8 // Temperatur_int >> 16; // /65536 Temperatur_int >>= 13; // 8/65536 = 1/8192 Temperatur_int -= 46850; // Temperatur in m�C Temperatur_int = Temperatur_int/1000; // Temp in �C /*** Luftfeuchtigkeit einlesen ***********************************************************************/ w_Reg[0] = trig_rh_h; // Lade das Triggerkommando zum Messen der Luftfeuchtigkeit HalI2CWrite(1,w_Reg); // Sende das Triggerkommando zum Messen der Temperatur HalI2CRead(3,r_Reg); // Lese die Luftfeuchteaturantwort in das read Register Luftfeuchte_int = r_Reg[0]; /* Urspr�ngliche Berechnung: Luftfeuchte_int = ((125*(r_Reg[0]))/256); // Umwandeln des Ergebnisses der Luftfeuchtigkeitsmessung Luftfeuchte_int = *Luftfeuchte_int-6; */ //Neu umgeschriebene Berechnung: Luftfeuchte_int = 125*r_Reg[0]; Luftfeuchte_int >>= 8; // /256 Luftfeuchte_int -= 6; // Luftfeuchte in % if (HalI2CReady2Sleep()) {HalI2CEnterSleep();} // Update the advertising data advertData[sizeof(advertData)-4] = Temperatur_int % 256; // Low Byte advertData[sizeof(advertData)-3] = Temperatur_int >> 8; // High Byte advertData[sizeof(advertData)-2] = Luftfeuchte_int % 256; // Low Byte LF advertData[sizeof(advertData)-1] = 0; // High Byte Lf // bStatus_t stat = GAPRole_SetParameter( GAPROLE_ADVERT_DATA, sizeof( advertData ), advertData ); bStatus_t stat = GAP_UpdateAdvertisingData( task_id, TRUE, sizeof(advertData),advertData ); while (stat != SUCCESS) { stat = stat; } timerset = osal_start_timerEx(MeasUnit_ProcessEvent_TaskID,START_ADVERT,2000);// while (timerset != SUCCESS) { timerset = timerset; } return (events ^ UPDATE_TEMP_RH);// Reset READY_FOR_MEASURE Bit } if (events & START_ADVERT) { //bStatus_t stat_discoverable = GAP_MakeDiscoverable( task_id, ¶ms ); advertising_enable = TRUE; GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &advertising_enable ); timerset = osal_start_timerEx(MeasUnit_ProcessEvent_TaskID,STOP_ADVERT,500);// while (timerset != SUCCESS) { timerset = timerset; } return (events ^ START_ADVERT); } if (events & STOP_ADVERT) { uint8 gapRole_AdvEnabled; GAPRole_GetParameter(GAPROLE_ADVERT_ENABLED, &gapRole_AdvEnabled); if (gapRole_AdvEnabled == TRUE) { //bStatus_t stat_endiscoverable = GAP_EndDiscoverable(task_id); //while (stat_endiscoverable != SUCCESS) //{ stat_endiscoverable = stat_endiscoverable;} advertising_enable = FALSE; GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &advertising_enable ); } timerset = osal_start_timerEx(MeasUnit_ProcessEvent_TaskID,UPDATE_TEMP_RH,4200);//SLEEP_BETWEEN_MEASURING); while (timerset != SUCCESS) { timerset = timerset; } return (events ^ STOP_ADVERT); } while (1) //Should never be reached {;} return (events); } static void gapRoleChanged( gaprole_States_t newState ) { P0 |= OWN_LED; // schalte LED aus (Low aktiv) switch ( newState ) { case GAPROLE_STARTED: { uint8 ownAddress[B_ADDR_LEN]; GAPRole_GetParameter(GAPROLE_BD_ADDR, ownAddress); } break; case GAPROLE_ADVERTISING: { P0 &= ~(OWN_LED); // Schalte die LED ein } break; case GAPROLE_WAITING: { } break; case GAPROLE_ERROR: { while(1); //For debugging } break; default: { while(1); //For debugging } break; } } void EndlessTask_Init( uint8 task_id ) { EndlessTask_TaskID = task_id; osal_set_event(task_id,0x01); return; } uint16 EndlessTask_ProcessEvent ( uint8 task_id, uint16 events ) { return events; } /***********************************************************************************************/ /** P2 Interrupt Handling **********************************************************************/ /***********************************************************************************************/ /********************************************************************* * @fn Interruptroutine1 * * @brief This interruptfunction will be called by pressing * the external button for acyclic measuring and sending * It just calls the function P2_interrupthandling * * @param No parameter * @return No return */ /* _PRAGMA(vector=P2INT_VECTOR) __near_func __interrupt void Interruptroutine1 (void) { P2_InterruptHandling(); return; } */ /********************************************************************* * @fn P2_InterruptHandling * * @brief This is called after an Interrupt on P2.0 occourred. * It turns on the LED, sets the events START_MEASURING in task init_measuring, * ENOUGH_POWER_FOR_SEND in task send_data and LED_AUS in task led_blink. * * So after turning on the LED, there will be a measuring, then the * measured data will be sent and the LED wibb be turned off * * @param No parameter * @return No return */ /* void P2_InterruptHandling(void) { if ( P2IFG & 0x01 ) { P2IEN &= ~0x01; // Disable Port2.0 Interrupt P0 &= ~(OWN_LED); // schalte LED ein (Low aktiv) P2IF = 0; P2IFG &= 0xE0; } IRCON2 &= 0xFE; return; }*/