Subversion Repositories HomeAutomation

Rev

Rev 2175 | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

  1.  
  2. #include "sns_power.h"
  3.  
  4. static uint32_t volatile PreviusTimerValue, lastMeasurment;
  5.  
  6. #ifdef sns_power_10000_PULSES_PER_KWH
  7. static uint8_t volatile tmpCounter=0;
  8. #endif
  9. static uint8_t volatile StoreInEEPROM = 0;
  10. static uint8_t sns_power_ReportInterval = (uint8_t)sns_power_SEND_PERIOD;
  11. static uint16_t volatile MeasurmentBuffer[32]= {0x0000ffff,0x0000ffff,0x0000ffff,0x0000ffff,0x0000ffff,0x0000ffff,0x0000ffff,0x0000ffff,
  12.                                                 0x0000ffff,0x0000ffff,0x0000ffff,0x0000ffff,0x0000ffff,0x0000ffff,0x0000ffff,0x0000ffff,
  13.                                                 0x0000ffff,0x0000ffff,0x0000ffff,0x0000ffff,0x0000ffff,0x0000ffff,0x0000ffff,0x0000ffff,
  14.                                                 0x0000ffff,0x0000ffff,0x0000ffff,0x0000ffff,0x0000ffff,0x0000ffff,0x0000ffff,0x0000ffff};
  15. static uint8_t volatile MeasurmentBufferPointer=0;
  16. static uint32_t volatile EnergyCounter=0;
  17. #if sns_power_SEND_1_MIN_AVG == 1
  18.   static uint16_t volatile avgCounter = 0;
  19. #endif
  20.  
  21. #ifdef POWER_SNS_PIN_ch2
  22. static uint32_t volatile PreviusTimerValue_ch2, lastMeasurment_ch2;
  23.  
  24. #ifdef sns_power_10000_PULSES_PER_KWH
  25. static uint8_t volatile tmpCounter_ch2=0;
  26. #endif
  27. static uint16_t volatile MeasurmentBuffer_ch2[32]= {0x0000ffff,0x0000ffff,0x0000ffff,0x0000ffff,0x0000ffff,0x0000ffff,0x0000ffff,0x0000ffff,
  28.                                                     0x0000ffff,0x0000ffff,0x0000ffff,0x0000ffff,0x0000ffff,0x0000ffff,0x0000ffff,0x0000ffff,
  29.                                                     0x0000ffff,0x0000ffff,0x0000ffff,0x0000ffff,0x0000ffff,0x0000ffff,0x0000ffff,0x0000ffff,
  30.                                                     0x0000ffff,0x0000ffff,0x0000ffff,0x0000ffff,0x0000ffff,0x0000ffff,0x0000ffff,0x0000ffff};
  31.   static uint8_t volatile MeasurmentBufferPointer_ch2=0;
  32.   static uint32_t volatile EnergyCounter_ch2=0;
  33.   #if sns_power_SEND_1_MIN_AVG == 1
  34.     static uint16_t volatile avgCounter_ch2 = 0;
  35.   #endif
  36. #endif
  37. #if sns_power_USEEEPROM==1
  38.   #include "sns_power_eeprom.h"
  39.   struct eeprom_sns_power EEMEM eeprom_sns_power =
  40.   {
  41.       {   /// Define initialization values on the EEPROM variables here, this will generate a *.eep file that can be used to store this values to the node, can in future be done with a EEPROM module and the make-scrips. Write the values in the exact same order as the struct is defined in the *.h file.
  42.           (uint8_t)sns_power_SEND_PERIOD,   // reportInterval
  43.           0,    // EnergyCounterUpper
  44.           0,    // EnergyCounterLower
  45.           #ifdef POWER_SNS_PIN_ch2
  46.             0,  // EnergyCounterUpper_ch2
  47.             0,  // EnergyCounterLower_ch2
  48.           #endif
  49.       },
  50.       0 // crc, must be a correct value, but this will also be handled by the EEPROM module or make scripts
  51.   };
  52. #endif
  53.  
  54. #if sns_power_SEND_1_MIN_AVG == 1
  55.   void sns_power_timer_callback(uint8_t timer)
  56.   {
  57.       StdCan_Msg_t txMsg;
  58.       StdCan_Set_class(txMsg.Header, CAN_MODULE_CLASS_SNS);
  59.       StdCan_Set_direction(txMsg.Header, DIRECTIONFLAG_FROM_OWNER);
  60.       txMsg.Header.ModuleType = CAN_MODULE_TYPE_SNS_POWER;
  61.       txMsg.Header.ModuleId = sns_power_ID;
  62.       txMsg.Header.Command = CAN_MODULE_CMD_POWER_AVGPOWER;
  63.       txMsg.Length = 2;
  64.       cli();
  65.       txMsg.Data[0] = (uint8_t)((avgCounter>>8) & 0xff);
  66.       txMsg.Data[1] = (uint8_t)(avgCounter & 0xff);
  67.       avgCounter = 0;
  68.       sei();
  69.       while (StdCan_Put(&txMsg) != StdCan_Ret_OK);
  70.  
  71.       #ifdef POWER_SNS_PIN_ch2
  72.         txMsg.Length = 2;
  73.         txMsg.Header.ModuleId = sns_power_ID_ch2;
  74.         cli();
  75.         txMsg.Data[0] = (uint8_t)((avgCounter_ch2>>8) & 0xff);
  76.         txMsg.Data[1] = (uint8_t)(avgCounter_ch2 & 0xff);
  77.         avgCounter = 0;
  78.         sei();
  79.         while (StdCan_Put(&txMsg) != StdCan_Ret_OK);
  80.  
  81.       #endif
  82.   }
  83. #endif
  84.  
  85. void sns_power_pcint_callback(uint8_t id, uint8_t status)
  86. {
  87.     if (status == 0)
  88.     {
  89.         if (Timer_GetTicks() - PreviusTimerValue >= 16)
  90.         {
  91.             MeasurmentBufferPointer++;
  92.             if (MeasurmentBufferPointer >= 32) MeasurmentBufferPointer = 0;
  93.             lastMeasurment =  Timer_GetTicks() - PreviusTimerValue;
  94.             MeasurmentBuffer[MeasurmentBufferPointer] = (uint16_t) (lastMeasurment & 0x0000FFFF);
  95.             PreviusTimerValue = Timer_GetTicks();
  96.             #if sns_power_100_PULSES_PER_KWH == 1
  97.                 EnergyCounter+=10;
  98.                 if (EnergyCounter % 1024 == 0)
  99.                     StoreInEEPROM = 1;
  100.             #endif
  101.             #if sns_power_1000_PULSES_PER_KWH == 1
  102.                 EnergyCounter++;
  103.                 if (EnergyCounter % 1024 == 0)
  104.                     StoreInEEPROM = 1;
  105.             #endif
  106.             #if sns_power_10000_PULSES_PER_KWH == 1
  107.                 tmpCounter++;
  108.                 #if sns_power_SEND_1_MIN_AVG == 1
  109.                 avgCounter++;
  110.                 #endif
  111.                 if(tmpCounter >= 10) {
  112.                     EnergyCounter++;
  113.                     if (EnergyCounter % 1024 == 0)
  114.                         StoreInEEPROM = 1;
  115.                     tmpCounter = 0;
  116.                 }
  117.             #endif
  118.  
  119. #ifdef sns_power_LED_PIN
  120.             gpio_toggle_pin(sns_power_LED_PIN); // toggle pin
  121. #endif
  122.         }
  123.     }
  124. }
  125.  
  126. #ifdef POWER_SNS_PIN_ch2
  127. void sns_power_pcint_callback_ch2(uint8_t id, uint8_t status)
  128. {
  129.     if (status == 0)
  130.     {
  131.         if (Timer_GetTicks() - PreviusTimerValue_ch2 >= 16)
  132.         {
  133.             MeasurmentBufferPointer_ch2++;
  134.             if (MeasurmentBufferPointer_ch2 >= 32) MeasurmentBufferPointer_ch2 = 0;
  135.             lastMeasurment_ch2 =  Timer_GetTicks() - PreviusTimerValue_ch2;
  136.             MeasurmentBuffer_ch2[MeasurmentBufferPointer_ch2] = (uint16_t) (lastMeasurment_ch2 & 0x0000FFFF);
  137.             PreviusTimerValue_ch2 = Timer_GetTicks();
  138.             #if sns_power_100_PULSES_PER_KWH == 1
  139.                 EnergyCounter_ch2+=10;
  140.             #endif
  141.             #if sns_power_1000_PULSES_PER_KWH == 1
  142.                 EnergyCounter_ch2++;
  143.             #endif
  144.             #if sns_power_10000_PULSES_PER_KWH == 1
  145.                 tmpCounter_ch2++;
  146.                 #if sns_power_SEND_1_MIN_AVG == 1
  147.                 avgCounter_ch2++;
  148.                 #endif
  149.                 if(tmpCounter_ch2 >= 10) {
  150.                     EnergyCounter_ch2++;
  151.                     tmpCounter_ch2 = 0;
  152.                 }
  153.             #endif
  154. #ifdef sns_power_LED_PIN
  155.             gpio_toggle_pin(sns_power_LED_PIN); // toggle pin
  156. #endif
  157.         }
  158.     }
  159. }
  160. #endif
  161.  
  162. void sns_power_Init(void)
  163. {
  164. #if sns_power_USEEEPROM==1
  165.     if (EEDATA_OK)
  166.     {  /// Use stored data to set initial values for the module
  167.       sns_power_ReportInterval = eeprom_read_byte(EEDATA.reportInterval);
  168.       EnergyCounter = eeprom_read_word(EEDATA16.EnergyCounterLower);
  169.       EnergyCounter += (((uint32_t)(eeprom_read_word(EEDATA16.EnergyCounterUpper)))<<16);
  170.         #ifdef POWER_SNS_PIN_ch2
  171.           EnergyCounter_ch2 = eeprom_read_word(EEDATA16.EnergyCounterLower_ch2);
  172.           EnergyCounter_ch2 += (((uint32_t)(eeprom_read_word(EEDATA16.EnergyCounterUpper_ch2)))<<16);
  173.         #endif
  174.     } else
  175.     {   //The CRC of the EEPROM is not correct, store default values and update CRC
  176.       eeprom_write_byte_crc(EEDATA.reportInterval, sns_power_SEND_PERIOD, WITHOUT_CRC);
  177.       eeprom_write_word_crc(EEDATA16.EnergyCounterUpper, 0, WITHOUT_CRC);
  178.       eeprom_write_word_crc(EEDATA16.EnergyCounterLower, 0, WITHOUT_CRC);
  179.       #ifdef POWER_SNS_PIN_ch2
  180.         eeprom_write_word_crc(EEDATA16.EnergyCounterUpper_ch2, 0, WITHOUT_CRC);
  181.         eeprom_write_word_crc(EEDATA16.EnergyCounterLower_ch2, 0, WITHOUT_CRC);
  182.       #endif
  183.       EEDATA_UPDATE_CRC;
  184.       sns_power_ReportInterval = eeprom_read_byte(EEDATA.reportInterval);
  185.     }
  186. #endif  
  187.     ///Initialize hardware etc
  188.     gpio_set_in(POWER_SNS_PIN); // Set to input
  189. #if sns_power_PIN_PULLUP==1
  190.     gpio_set_pullup(POWER_SNS_PIN); // Enable pull-up
  191. #endif
  192.  
  193.     Pcint_SetCallbackPin(sns_power_PCINT, POWER_SNS_PIN, &sns_power_pcint_callback);
  194.  
  195.     MeasurmentBufferPointer = 0;
  196. #ifdef POWER_SNS_PIN_ch2
  197.     gpio_set_in(POWER_SNS_PIN_ch2); // Set to input
  198. #if sns_power_PIN_PULLUP_ch2==1
  199.     gpio_set_pullup(POWER_SNS_PIN_ch2); // Enable pull-up
  200. #endif
  201.    
  202.     Pcint_SetCallbackPin(sns_power_PCINT_ch2, POWER_SNS_PIN_ch2, &sns_power_pcint_callback_ch2);
  203.  
  204.     MeasurmentBufferPointer_ch2 = 0;
  205. #endif
  206.     Timer_SetTimeout(sns_power_SEND_TIMER, sns_power_ReportInterval*1000 , TimerTypeFreeRunning, 0);
  207. #if sns_power_SEND_1_MIN_AVG == 1
  208.     Timer_SetTimeout(sns_power_SEND_TIMER_1_MIN_AVG, 60000-10 , TimerTypeFreeRunning, &sns_power_timer_callback);
  209. #endif
  210.  
  211. #ifdef sns_power_LED_PIN
  212.     gpio_set_out(sns_power_LED_PIN);    // Set to output
  213.     gpio_clr_pin(sns_power_LED_PIN);    // clear pin
  214. #endif
  215. }
  216.  
  217. void sns_power_Process(void)
  218. {
  219.     if (StoreInEEPROM == 1)
  220.     {
  221.         StoreInEEPROM = 0;
  222.        
  223.         eeprom_write_word_crc(EEDATA16.EnergyCounterUpper, (uint16_t)((EnergyCounter>>16) & 0xffff), WITHOUT_CRC);
  224.         eeprom_write_word_crc(EEDATA16.EnergyCounterLower, (uint16_t)(EnergyCounter & 0xffff), WITH_CRC);
  225.     #ifdef POWER_SNS_PIN_ch2
  226.         eeprom_write_word_crc(EEDATA16.EnergyCounterUpper_ch2, (uint16_t)((EnergyCounter_ch2>>16) & 0xffff), WITHOUT_CRC);
  227.         eeprom_write_word_crc(EEDATA16.EnergyCounterLower_ch2, (uint16_t)(EnergyCounter_ch2 & 0xffff), WITH_CRC);
  228.     #endif
  229.     }
  230.     StdCan_Msg_t txMsg;
  231.     if (Timer_Expired(sns_power_SEND_TIMER)) {
  232.         //4 times average
  233.         /*uint32_t Avg4 = MeasurmentBuffer[MeasurmentBufferPointer] + MeasurmentBuffer[MeasurmentBufferPointer-1] + MeasurmentBuffer[MeasurmentBufferPointer-2] + MeasurmentBuffer[MeasurmentBufferPointer-3];
  234.         Avg4 = (360000/(Avg4/4));
  235.         */
  236.         //32 times average
  237.         uint32_t Avg32 = 0;
  238.         for (uint8_t i = 0; i<32;i++) {
  239.              Avg32 += MeasurmentBuffer[i];
  240.         }
  241.         Avg32 /= 32;
  242.         #if sns_power_100_PULSES_PER_KWH == 1
  243.             Avg32 = (36000000UL/Avg32);
  244.         #endif
  245.         #if sns_power_1000_PULSES_PER_KWH == 1
  246.             Avg32 = (3600000/Avg32);
  247.         #endif
  248.         #if sns_power_10000_PULSES_PER_KWH == 1
  249.             Avg32 = (360000/Avg32);
  250.         #endif
  251.  
  252.            
  253.         StdCan_Set_class(txMsg.Header, CAN_MODULE_CLASS_SNS);
  254.         StdCan_Set_direction(txMsg.Header, DIRECTIONFLAG_FROM_OWNER);
  255.         txMsg.Header.ModuleType = CAN_MODULE_TYPE_SNS_POWER;
  256.         txMsg.Header.ModuleId = sns_power_ID;
  257.         txMsg.Header.Command = CAN_MODULE_CMD_PHYSICAL_ELECTRICPOWER;
  258.         txMsg.Length = 8;
  259.         #if sns_power_100_PULSES_PER_KWH == 1
  260.             uint32_t tmp = 36000000UL/MeasurmentBuffer[MeasurmentBufferPointer];
  261.         #endif
  262.         #if sns_power_1000_PULSES_PER_KWH == 1
  263.             uint32_t tmp = 3600000/MeasurmentBuffer[MeasurmentBufferPointer];
  264.         #endif
  265.         #if sns_power_10000_PULSES_PER_KWH == 1
  266.             uint32_t tmp = 360000/MeasurmentBuffer[MeasurmentBufferPointer];
  267.         #endif
  268.         txMsg.Data[0] = (uint8_t)((tmp>>8) & 0xff);
  269.         txMsg.Data[1] = (uint8_t)(tmp & 0xff);
  270.         txMsg.Data[5] = (uint8_t)EnergyCounter & 0xff;
  271.         txMsg.Data[4] = (uint8_t)(EnergyCounter >> 8) & 0xff;
  272.         txMsg.Data[3] = (uint8_t)(EnergyCounter >> 16) & 0xff;
  273.         txMsg.Data[2] = (uint8_t)(EnergyCounter >> 24) & 0xff;
  274.         txMsg.Data[6] = (uint8_t)((Avg32>>8) & 0xff);
  275.         txMsg.Data[7] = (uint8_t)(Avg32 & 0xff);
  276.         while (StdCan_Put(&txMsg) != StdCan_Ret_OK);
  277.        
  278.     #ifdef POWER_SNS_PIN_ch2
  279.         uint32_t Avg32_ch2 = 0;
  280.         for (uint8_t i = 0; i<32;i++) {
  281.              Avg32_ch2 += MeasurmentBuffer_ch2[i];
  282.         }
  283.         Avg32_ch2 /= 32;
  284.         #if sns_power_100_PULSES_PER_KWH == 1
  285.             Avg32_ch2 = (36000000UL/Avg32_ch2);
  286.         #endif
  287.         #if sns_power_1000_PULSES_PER_KWH == 1
  288.             Avg32_ch2 = (3600000/Avg32_ch2);
  289.         #endif
  290.         #if sns_power_10000_PULSES_PER_KWH == 1
  291.             Avg32_ch2 = (360000/Avg32_ch2);
  292.         #endif
  293.            
  294.         txMsg.Header.ModuleId = sns_power_ID_ch2;
  295.         #if sns_power_100_PULSES_PER_KWH == 1
  296.             tmp = 36000000UL/MeasurmentBuffer_ch2[MeasurmentBufferPointer_ch2];
  297.         #endif
  298.         #if sns_power_1000_PULSES_PER_KWH == 1
  299.             tmp = 3600000/MeasurmentBuffer_ch2[MeasurmentBufferPointer_ch2];
  300.         #endif
  301.         #if sns_power_10000_PULSES_PER_KWH == 1
  302.             tmp = 360000/MeasurmentBuffer_ch2[MeasurmentBufferPointer_ch2];
  303.         #endif
  304.         txMsg.Data[0] = (uint8_t)((tmp>>8) & 0xff);
  305.         txMsg.Data[1] = (uint8_t)(tmp & 0xff);
  306.         txMsg.Data[5] = (uint8_t)EnergyCounter_ch2 & 0xff;
  307.         txMsg.Data[4] = (uint8_t)(EnergyCounter_ch2 >> 8) & 0xff;
  308.         txMsg.Data[3] = (uint8_t)(EnergyCounter_ch2 >> 16) & 0xff;
  309.         txMsg.Data[2] = (uint8_t)(EnergyCounter_ch2 >> 24) & 0xff;
  310.         txMsg.Data[6] = (uint8_t)((Avg32_ch2>>8) & 0xff);
  311.         txMsg.Data[7] = (uint8_t)(Avg32_ch2 & 0xff);
  312.         while (StdCan_Put(&txMsg) != StdCan_Ret_OK);
  313.        
  314.     #endif
  315.        
  316.        
  317.     }
  318. }
  319.  
  320. void sns_power_HandleMessage(StdCan_Msg_t *rxMsg)
  321. {
  322.     if (    StdCan_Ret_class(rxMsg->Header) == CAN_MODULE_CLASS_SNS &&
  323.         StdCan_Ret_direction(rxMsg->Header) == DIRECTIONFLAG_TO_OWNER &&
  324.         rxMsg->Header.ModuleType == CAN_MODULE_TYPE_SNS_POWER &&
  325.         rxMsg->Header.ModuleId == sns_power_ID)
  326.     {
  327. StdCan_Msg_t txMsg;
  328.         switch (rxMsg->Header.Command)
  329.         {
  330.         case CAN_MODULE_CMD_GLOBAL_REPORT_INTERVAL:
  331.             if (rxMsg->Length > 0)
  332.             {
  333.                 sns_power_ReportInterval = rxMsg->Data[0];
  334.                 Timer_SetTimeout(sns_power_SEND_TIMER, sns_power_ReportInterval*1000 , TimerTypeFreeRunning, 0);
  335.             }
  336.             StdCan_Set_class(txMsg.Header, CAN_MODULE_CLASS_SNS);
  337.             StdCan_Set_direction(txMsg.Header, DIRECTIONFLAG_FROM_OWNER);
  338.             txMsg.Header.ModuleType = CAN_MODULE_TYPE_SNS_POWER;
  339.             txMsg.Header.ModuleId = sns_power_ID;
  340.             txMsg.Header.Command = CAN_MODULE_CMD_GLOBAL_REPORT_INTERVAL;
  341.             txMsg.Length = 1;
  342.             txMsg.Data[0] = sns_power_ReportInterval;
  343.             StdCan_Put(&txMsg);
  344.             break;
  345.         case CAN_MODULE_CMD_POWER_SETENERGY:
  346.             if (rxMsg->Length == 4)
  347.             {
  348.                 EnergyCounter = rxMsg->Data[3];
  349.                 EnergyCounter += ((uint32_t)rxMsg->Data[2])<<8;
  350.                 EnergyCounter += ((uint32_t)rxMsg->Data[1])<<16;
  351.                 EnergyCounter += ((uint32_t)rxMsg->Data[0])<<24;
  352.             }
  353.             StdCan_Set_class(txMsg.Header, CAN_MODULE_CLASS_SNS);
  354.             StdCan_Set_direction(txMsg.Header, DIRECTIONFLAG_FROM_OWNER);
  355.             txMsg.Header.ModuleType = CAN_MODULE_TYPE_SNS_POWER;
  356.             txMsg.Header.ModuleId = sns_power_ID;
  357.             txMsg.Header.Command = CAN_MODULE_CMD_POWER_SETENERGY;
  358.             txMsg.Length = 1;
  359.             txMsg.Data[3] = (uint8_t)EnergyCounter & 0xff;
  360.             txMsg.Data[2] = (uint8_t)(EnergyCounter >> 8) & 0xff;
  361.             txMsg.Data[1] = (uint8_t)(EnergyCounter >> 16) & 0xff;
  362.             txMsg.Data[0] = (uint8_t)(EnergyCounter >> 24) & 0xff;
  363.             StdCan_Put(&txMsg);
  364.            
  365.             break;
  366.         }
  367.     }
  368.    
  369. #ifdef POWER_SNS_PIN_ch2   
  370.     if (    StdCan_Ret_class(rxMsg->Header) == CAN_MODULE_CLASS_SNS &&
  371.         StdCan_Ret_direction(rxMsg->Header) == DIRECTIONFLAG_TO_OWNER &&
  372.         rxMsg->Header.ModuleType == CAN_MODULE_TYPE_SNS_POWER &&
  373.         rxMsg->Header.ModuleId == sns_power_ID_ch2)
  374.     {
  375.         StdCan_Msg_t txMsg;
  376.         switch (rxMsg->Header.Command)
  377.         {
  378.         case CAN_MODULE_CMD_GLOBAL_REPORT_INTERVAL:
  379.             if (rxMsg->Length > 0)
  380.             {
  381.                 sns_power_ReportInterval = rxMsg->Data[0];
  382.                 Timer_SetTimeout(sns_power_SEND_TIMER, sns_power_ReportInterval*1000 , TimerTypeFreeRunning, 0);
  383.             }
  384.             StdCan_Set_class(txMsg.Header, CAN_MODULE_CLASS_SNS);
  385.             StdCan_Set_direction(txMsg.Header, DIRECTIONFLAG_FROM_OWNER);
  386.             txMsg.Header.ModuleType = CAN_MODULE_TYPE_SNS_POWER;
  387.             txMsg.Header.ModuleId = sns_power_ID_ch2;
  388.             txMsg.Header.Command = CAN_MODULE_CMD_GLOBAL_REPORT_INTERVAL;
  389.             txMsg.Length = 1;
  390.             txMsg.Data[0] = sns_power_ReportInterval;
  391.             StdCan_Put(&txMsg);
  392.             break;
  393.         case CAN_MODULE_CMD_POWER_SETENERGY:
  394.             if (rxMsg->Length == 4)
  395.             {
  396.                 EnergyCounter_ch2 = rxMsg->Data[3];
  397.                 EnergyCounter_ch2 += ((uint32_t)rxMsg->Data[2])<<8;
  398.                 EnergyCounter_ch2 += ((uint32_t)rxMsg->Data[1])<<16;
  399.                 EnergyCounter_ch2 += ((uint32_t)rxMsg->Data[0])<<24;
  400.             }
  401.             StdCan_Set_class(txMsg.Header, CAN_MODULE_CLASS_SNS);
  402.             StdCan_Set_direction(txMsg.Header, DIRECTIONFLAG_FROM_OWNER);
  403.             txMsg.Header.ModuleType = CAN_MODULE_TYPE_SNS_POWER;
  404.             txMsg.Header.ModuleId = sns_power_ID_ch2;
  405.             txMsg.Header.Command = CAN_MODULE_CMD_POWER_SETENERGY;
  406.             txMsg.Length = 1;
  407.             txMsg.Data[3] = (uint8_t)EnergyCounter_ch2 & 0xff;
  408.             txMsg.Data[2] = (uint8_t)(EnergyCounter_ch2 >> 8) & 0xff;
  409.             txMsg.Data[1] = (uint8_t)(EnergyCounter_ch2 >> 16) & 0xff;
  410.             txMsg.Data[0] = (uint8_t)(EnergyCounter_ch2 >> 24) & 0xff;
  411.             StdCan_Put(&txMsg);
  412.            
  413.             break;
  414.         }
  415.     }
  416. #endif
  417.    
  418. }
  419.  
  420. void sns_power_List(uint8_t ModuleSequenceNumber)
  421. {
  422.     StdCan_Msg_t txMsg;
  423.    
  424.     StdCan_Set_class(txMsg.Header, CAN_MODULE_CLASS_SNS);
  425.     StdCan_Set_direction(txMsg.Header, DIRECTIONFLAG_FROM_OWNER);
  426.     txMsg.Header.ModuleType = CAN_MODULE_TYPE_SNS_POWER;
  427.     txMsg.Header.ModuleId = sns_power_ID;
  428.     txMsg.Header.Command = CAN_MODULE_CMD_GLOBAL_LIST;
  429.     txMsg.Length = 6;
  430.  
  431.     uint32_t HwId=BIOS_GetHwId();
  432.     txMsg.Data[0] = HwId&0xff;
  433.     txMsg.Data[1] = (HwId>>8)&0xff;
  434.     txMsg.Data[2] = (HwId>>16)&0xff;
  435.     txMsg.Data[3] = (HwId>>24)&0xff;
  436.    
  437.     txMsg.Data[4] = NUMBER_OF_MODULES;
  438.     txMsg.Data[5] = ModuleSequenceNumber;
  439.    
  440.     while (StdCan_Put(&txMsg) != StdCan_Ret_OK);
  441.    
  442.    
  443. #ifdef POWER_SNS_PIN_ch2   
  444.     txMsg.Header.ModuleId = sns_power_ID_ch2;
  445.     txMsg.Data[5] = ModuleSequenceNumber;
  446.     while (StdCan_Put(&txMsg) != StdCan_Ret_OK);
  447. #endif
  448. }
  449.