Subversion Repositories HomeAutomation

Rev

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