Advertisement
PT_

Untitled

PT_
Mar 16th, 2021
1,280
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 23.60 KB | None | 0 0
  1. #include <low_power.h>
  2. #include <STM32LowPower.h>
  3. #include "stm32f4xx.h"
  4. #include <STM32SD.h>
  5. #include <EEPROM.h>
  6. #define DEBUG 0
  7.  
  8. /* Symbolic names for bit rate of CAN message                                */
  9. typedef enum {CAN_50KBPS, CAN_100KBPS, CAN_125KBPS, CAN_250KBPS, CAN_500KBPS, CAN_1000KBPS} BITRATE;
  10.  
  11. /* Symbolic names for formats of CAN message                                 */
  12. typedef enum {STANDARD_FORMAT = 0, EXTENDED_FORMAT} CAN_FORMAT;
  13.  
  14. /* Symbolic names for type of CAN message                                    */
  15. typedef enum {DATA_FRAME = 0, REMOTE_FRAME}         CAN_FRAME;
  16.  
  17. typedef struct
  18. {
  19.   uint32_t id;        /* 29 bit identifier                               */
  20.   uint8_t  data[8];   /* Data field                                      */
  21.   uint8_t  len;       /* Length of data field in bytes                   */
  22.   uint8_t  ch;        /* Object channel(Not use)                         */
  23.   uint8_t  format;    /* 0 - STANDARD, 1- EXTENDED IDENTIFIER            */
  24.   uint8_t  type;      /* 0 - DATA FRAME, 1 - REMOTE FRAME                */
  25. } CAN_msg_t;
  26.  
  27. typedef const struct
  28. {
  29.   uint8_t TS2;
  30.   uint8_t TS1;
  31.   uint8_t BRP;
  32. } CAN_bit_timing_config_t;
  33.  
  34. CAN_bit_timing_config_t can_configs[6] = {{2, 12, 56}, {2, 12, 28}, {2, 13, 21}, {2, 11, 12}, {2, 11, 6}, {1, 5, 6}};
  35.  
  36. /**
  37.  * Print registers.
  38. */
  39. void printRegister(char * buf, uint32_t reg) {
  40.   if (DEBUG == 0) return;
  41.   SerialUSB.print(buf);
  42.   SerialUSB.print(reg, HEX);
  43.   SerialUSB.println();
  44. }
  45.  
  46. /**
  47.  * Initializes the CAN GPIO registers.
  48.  *
  49.  * @params: addr    - Specified GPIO register address.
  50.  * @params: index   - Specified GPIO index.
  51.  * @params: speed   - Specified OSPEEDR register value.(Optional)
  52.  *
  53.  */
  54. void CANSetGpio(GPIO_TypeDef * addr, uint8_t index, uint8_t speed = 3) {
  55.     uint8_t _index2 = index * 2;
  56.     uint8_t _index4 = index * 4;
  57.     uint8_t ofs = 0;
  58.     uint8_t setting;
  59.  
  60.     if (index > 7) {
  61.       _index4 = (index - 8) * 4;
  62.       ofs = 1;
  63.     }
  64.  
  65.     uint32_t mask;
  66.     printRegister("GPIO_AFR(b)=", addr->AFR[1]);
  67.     mask = 0xF << _index4;
  68.     addr->AFR[ofs]  &= ~mask;         // Reset alternate function
  69.     setting = 0x9;                    // AF9
  70.     mask = setting << _index4;
  71.     addr->AFR[ofs]  |= mask;          // Set alternate function
  72.     printRegister("GPIO_AFR(a)=", addr->AFR[1]);
  73.  
  74.     printRegister("GPIO_MODER(b)=", addr->MODER);
  75.     mask = 0x3 << _index2;
  76.     addr->MODER   &= ~mask;           // Reset mode
  77.     setting = 0x2;                    // Alternate function mode
  78.     mask = setting << _index2;
  79.     addr->MODER   |= mask;            // Set mode
  80.     printRegister("GPIO_MODER(a)=", addr->MODER);
  81.  
  82.     printRegister("GPIO_OSPEEDR(b)=", addr->OSPEEDR);
  83.     mask = 0x3 << _index2;
  84.     addr->OSPEEDR &= ~mask;           // Reset speed
  85.     setting = speed;
  86.     mask = setting << _index2;
  87.     addr->OSPEEDR |= mask;            // Set speed
  88.     printRegister("GPIO_OSPEEDR(a)=", addr->OSPEEDR);
  89.  
  90.     printRegister("GPIO_OTYPER(b)=", addr->OTYPER);
  91.     mask = 0x1 << index;
  92.     addr->OTYPER  &= ~mask;           // Reset Output push-pull
  93.     printRegister("GPIO_OTYPER(a)=", addr->OTYPER);
  94.  
  95.     printRegister("GPIO_PUPDR(b)=", addr->PUPDR);
  96.     mask = 0x3 << _index2;
  97.     addr->PUPDR   &= ~mask;           // Reset port pull-up/pull-down
  98.     printRegister("GPIO_PUPDR(a)=", addr->PUPDR);
  99. }
  100.  
  101.  
  102.  
  103. /**
  104.  * Initializes the CAN filter registers.
  105.  *
  106.  * @preconditions   - This register can be written only when the filter initialization mode is set (FINIT=1) in the CAN_FMR register.
  107.  * @params: index   - Specified filter index. index 27:14 are available in connectivity line devices only.
  108.  * @params: scale   - Select filter scale.
  109.  *                    0: Dual 16-bit scale configuration
  110.  *                    1: Single 32-bit scale configuration
  111.  * @params: mode    - Select filter mode.
  112.  *                    0: Two 32-bit registers of filter bank x are in Identifier Mask mode
  113.  *                    1: Two 32-bit registers of filter bank x are in Identifier List mode
  114.  * @params: fifo    - Select filter assigned.
  115.  *                    0: Filter assigned to FIFO 0
  116.  *                    1: Filter assigned to FIFO 1
  117.  * @params: bank1   - Filter bank register 1
  118.  * @params: bank2   - Filter bank register 2
  119.  *
  120.  */
  121. void CANSetFilter(uint8_t index, uint8_t scale, uint8_t mode, uint8_t fifo, uint32_t bank1, uint32_t bank2) {
  122.   if (index > 27) return;
  123.  
  124.   CAN1->FA1R &= ~(0x1UL<<index);               // Deactivate filter
  125.  
  126.   if (scale == 0) {
  127.     CAN1->FS1R &= ~(0x1UL<<index);             // Set filter to Dual 16-bit scale configuration
  128.   } else {
  129.     CAN1->FS1R |= (0x1UL<<index);              // Set filter to single 32 bit configuration
  130.   }
  131.     if (mode == 0) {
  132.     CAN1->FM1R &= ~(0x1UL<<index);             // Set filter to Mask mode
  133.   } else {
  134.     CAN1->FM1R |= (0x1UL<<index);              // Set filter to List mode
  135.   }
  136.  
  137.   if (fifo == 0) {
  138.     CAN1->FFA1R &= ~(0x1UL<<index);            // Set filter assigned to FIFO 0
  139.   } else {
  140.     CAN1->FFA1R |= (0x1UL<<index);             // Set filter assigned to FIFO 1
  141.   }
  142.  
  143.   CAN1->sFilterRegister[index].FR1 = bank1;    // Set filter bank registers1
  144.   CAN1->sFilterRegister[index].FR2 = bank2;    // Set filter bank registers2
  145.  
  146.   CAN1->FA1R |= (0x1UL<<index);                // Activate filter
  147.  
  148. }
  149.  
  150. /**
  151.  * Initializes the CAN controller with specified bit rate.
  152.  *
  153.  * @params: bitrate - Specified bitrate. If this value is not one of the defined constants, bit rate will be defaulted to 125KBS
  154.  * @params: remap   - Select CAN port.
  155.  *                    =0:CAN1_RX mapped to PA11, CAN1_TX mapped to PA12
  156.  *                       CAN2_RX mapped to PB5 , CAN2_TX mapped to PB6
  157.  *                    =1:Not used
  158.  *                    =2:CAN1_RX mapped to PB8,  CAN1_TX mapped to PB9 (not available on 36-pin package)
  159.  *                       CAN2_RX mapped to PB12, CAN2_TX mapped to PB13
  160.  *                    =3:CAN1_RX mapped to PD0,  CAN1_TX mapped to PD1 (available on 100-pin and 144-pin package)
  161.  *                       CAN2_RX mapped to PB12, CAN2_TX mapped to PB13
  162.  *
  163.  */
  164. bool CANInit(BITRATE bitrate, int remap)
  165. {
  166.   // Reference manual
  167.   // https://www.st.com/content/ccc/resource/technical/document/reference_manual/3d/6d/5a/66/b4/99/40/d4/DM00031020.pdf/files/DM00031020.pdf/jcr:content/translations/en.DM00031020.pdf
  168.  
  169.   RCC->APB1ENR |= 0x2000000UL;           // Enable CAN1 clock
  170.   RCC->APB1ENR |= 0x4000000UL;           // Enable CAN2 clock
  171.  
  172.   if (remap == 0) {
  173.     // CAN1
  174.     RCC->AHB1ENR |= 0x1;                 // Enable GPIOA clock
  175.     CANSetGpio(GPIOA, 11);               // Set PA11
  176.     CANSetGpio(GPIOA, 12);               // Set PA12
  177.    
  178.     // CAN2
  179.     RCC->AHB1ENR |= 0x2;                 // Enable GPIOB clock
  180.     CANSetGpio(GPIOB, 5);                // Set PB5
  181.     CANSetGpio(GPIOB, 6);                // Set PB6
  182.   }
  183.  
  184.   if (remap == 2) {
  185.     // CAN1
  186.     RCC->AHB1ENR |= 0x2;                 // Enable GPIOB clock
  187.     CANSetGpio(GPIOB, 8);                // Set PB8
  188.     CANSetGpio(GPIOB, 9);                // Set PB9
  189.  
  190.     // CAN2
  191.     RCC->AHB1ENR |= 0x2;                 // Enable GPIOB clock
  192.     CANSetGpio(GPIOB, 12);               // Set PB12
  193.     CANSetGpio(GPIOB, 13);               // Set PB13
  194.   }
  195.    
  196.   if (remap == 3) {
  197.     // CAN1
  198.     RCC->AHB1ENR |= 0x8;                 // Enable GPIOD clock
  199.     CANSetGpio(GPIOD, 0);                // Set PD0
  200.     CANSetGpio(GPIOD, 1);                // Set PD1
  201.  
  202.     // CAN2
  203.     RCC->AHB1ENR |= 0x2;                 // Enable GPIOB clock
  204.     CANSetGpio(GPIOB, 12);               // Set PB12
  205.     CANSetGpio(GPIOB, 13);               // Set PB13
  206.   }
  207.  
  208.   CAN1->MCR |= 0x1UL;                    // Require CAN1 to Initialization mode
  209.   while (!(CAN1->MSR & 0x1UL));          // Wait for Initialization mode
  210.   printRegister("CAN1->MCR=", CAN1->MCR);
  211.  
  212.   CAN2->MCR |= 0x1UL;                    // Require CAN2 to Initialization mode
  213.   while (!(CAN2->MSR & 0x1UL));          // Wait for Initialization mode
  214.   printRegister("CAN2->MCR=", CAN2->MCR);
  215.  
  216.   //CAN1->MCR = 0x51UL;                  // Hardware initialization(No automatic retransmission)
  217.   CAN1->MCR = 0x41UL;                    // Hardware initialization(With automatic retransmission)
  218.  
  219.   //CAN2->MCR = 0x51UL;                  // Hardware initialization(No automatic retransmission)
  220.   CAN2->MCR = 0x41UL;                    // Hardware initialization(With automatic retransmission)
  221.  
  222.  
  223.   // Set bit rates
  224.   CAN1->BTR &= ~(((0x03) << 24) | ((0x07) << 20) | ((0x0F) << 16) | (0x1FF));
  225.   CAN1->BTR |=  (((can_configs[bitrate].TS2-1) & 0x07) << 20) | (((can_configs[bitrate].TS1-1) & 0x0F) << 16) | ((can_configs[bitrate].BRP-1) & 0x1FF);
  226.   printRegister("CAN1->BTR=", CAN1->BTR);
  227.  
  228.   CAN2->BTR &= ~(((0x03) << 24) | ((0x07) << 20) | ((0x0F) << 16) | (0x1FF));
  229.   CAN2->BTR |=  (((can_configs[bitrate].TS2-1) & 0x07) << 20) | (((can_configs[bitrate].TS1-1) & 0x0F) << 16) | ((can_configs[bitrate].BRP-1) & 0x1FF);
  230.   printRegister("CAN2->BTR=", CAN2->BTR);
  231.  
  232.   // Configure Filters to default values
  233.   CAN1->FMR  |=   0x1UL;                 // Set to filter initialization mode
  234.   CAN1->FMR  &= 0xFFFFC0FF;              // Clear CAN2 start bank
  235.   printRegister("CAN1->FMR=", CAN1->FMR);
  236.  
  237.   // bxCAN has 28 filters.
  238.   // These filters are used for both CAN1 and CAN2.
  239.   // STM32F405 has CAN1 and CAN2, so CAN2 filters are offset by 14
  240.   CAN1->FMR  |= 0xE00;                   // Start bank for the CAN2 interface
  241.  
  242.   // Set fileter 0
  243.   // Single 32-bit scale configuration
  244.   // Two 32-bit registers of filter bank x are in Identifier Mask mode
  245.   // Filter assigned to FIFO 0
  246.   // Filter bank register to all 0
  247.   CANSetFilter(0, 1, 0, 0, 0x0UL, 0x0UL);
  248.  
  249.   // Set fileter 14
  250.   // Single 32-bit scale configuration
  251.   // Two 32-bit registers of filter bank x are in Identifier Mask mode
  252.   // Filter assigned to FIFO 0
  253.   // Filter bank register to all 0
  254.   CANSetFilter(14, 1, 0, 0, 0x0UL, 0x0UL);
  255.  
  256.   CAN1->FMR   &= ~(0x1UL);               // Deactivate initialization mode
  257.  
  258.   uint16_t TimeoutMilliseconds = 1000;
  259.   bool can2 = false;
  260.   CAN2->MCR   &= ~(0x1UL);               // Require CAN2 to normal mode  
  261.  
  262.   // Wait for normal mode
  263.   // If the connection is not correct, it will not return to normal mode.
  264.   for (uint16_t wait_ack = 0; wait_ack < TimeoutMilliseconds; wait_ack++) {
  265.     if ((CAN2->MSR & 0x1UL) == 0) {
  266.       can2 = true;
  267.       break;
  268.     }
  269.     delayMicroseconds(1000);
  270.   }
  271.   //SerialUSB.print("can2=");
  272.   //SerialUSB.println(can2);
  273.   if (can2) {
  274.     SerialUSB.println("CAN2 initialize ok");
  275.   } else {
  276.     SerialUSB.println("CAN2 initialize fail!!");
  277.   }
  278.  
  279.   bool can1 = false;
  280.   CAN1->MCR   &= ~(0x1UL);               // Require CAN1 to normal mode
  281.  
  282.   // Wait for normal mode
  283.   // If the connection is not correct, it will not return to normal mode.
  284.   for (uint16_t wait_ack = 0; wait_ack < TimeoutMilliseconds; wait_ack++) {
  285.     if ((CAN1->MSR & 0x1UL) == 0) {
  286.       can1 = true;
  287.       break;
  288.     }
  289.     delayMicroseconds(1000);
  290.   }
  291.   //SerialUSB.print("can1=");
  292.   //SerialUSB.println(can1);
  293.   if (can1) {
  294.     SerialUSB.println("CAN1 initialize ok");
  295.   } else {
  296.     SerialUSB.println("CAN1 initialize fail!!");
  297.     //return false;
  298.   }
  299.   return true;
  300. }
  301.  
  302.  
  303. #define STM32_CAN_TIR_TXRQ              (1U << 0U)  // Bit 0: Transmit Mailbox Request
  304. #define STM32_CAN_RIR_RTR               (1U << 1U)  // Bit 1: Remote Transmission Request
  305. #define STM32_CAN_RIR_IDE               (1U << 2U)  // Bit 2: Identifier Extension
  306. #define STM32_CAN_TIR_RTR               (1U << 1U)  // Bit 1: Remote Transmission Request
  307. #define STM32_CAN_TIR_IDE               (1U << 2U)  // Bit 2: Identifier Extension
  308.  
  309. #define CAN_EXT_ID_MASK                 0x1FFFFFFFU
  310. #define CAN_STD_ID_MASK                 0x000007FFU
  311.  
  312. /**
  313.  * Decodes CAN messages from the data registers and populates a
  314.  * CAN message struct with the data fields.
  315.  *
  316.  * @preconditions     - A valid CAN message is received
  317.  * @params CAN_rx_msg - CAN message structure for reception
  318.  *
  319.  */
  320. void CANReceive(uint8_t ch, CAN_msg_t* CAN_rx_msg)
  321. {
  322.   if(ch == 1) {
  323.     uint32_t id = CAN1->sFIFOMailBox[0].RIR;
  324.     if ((id & STM32_CAN_RIR_IDE) == 0) { // Standard frame format
  325.         CAN_rx_msg->format = STANDARD_FORMAT;;
  326.         CAN_rx_msg->id = (CAN_STD_ID_MASK & (id >> 21U));
  327.     }
  328.     else {                               // Extended frame format
  329.         CAN_rx_msg->format = EXTENDED_FORMAT;;
  330.         CAN_rx_msg->id = (CAN_EXT_ID_MASK & (id >> 3U));
  331.     }
  332.  
  333.     if ((id & STM32_CAN_RIR_RTR) == 0) {  // Data frame
  334.         CAN_rx_msg->type = DATA_FRAME;
  335.     }
  336.     else {                                // Remote frame
  337.         CAN_rx_msg->type = REMOTE_FRAME;
  338.     }
  339.  
  340.    
  341.     CAN_rx_msg->len = (CAN1->sFIFOMailBox[0].RDTR) & 0xFUL;
  342.    
  343.     CAN_rx_msg->data[0] = 0xFFUL &  CAN1->sFIFOMailBox[0].RDLR;
  344.     CAN_rx_msg->data[1] = 0xFFUL & (CAN1->sFIFOMailBox[0].RDLR >> 8);
  345.     CAN_rx_msg->data[2] = 0xFFUL & (CAN1->sFIFOMailBox[0].RDLR >> 16);
  346.     CAN_rx_msg->data[3] = 0xFFUL & (CAN1->sFIFOMailBox[0].RDLR >> 24);
  347.     CAN_rx_msg->data[4] = 0xFFUL &  CAN1->sFIFOMailBox[0].RDHR;
  348.     CAN_rx_msg->data[5] = 0xFFUL & (CAN1->sFIFOMailBox[0].RDHR >> 8);
  349.     CAN_rx_msg->data[6] = 0xFFUL & (CAN1->sFIFOMailBox[0].RDHR >> 16);
  350.     CAN_rx_msg->data[7] = 0xFFUL & (CAN1->sFIFOMailBox[0].RDHR >> 24);
  351.    
  352.     CAN1->RF0R |= 0x20UL;
  353.   } // end CAN1
  354.  
  355.   if(ch == 2) {
  356.     uint32_t id = CAN2->sFIFOMailBox[0].RIR;
  357.     if ((id & STM32_CAN_RIR_IDE) == 0) { // Standard frame format
  358.         CAN_rx_msg->format = STANDARD_FORMAT;;
  359.         CAN_rx_msg->id = (CAN_STD_ID_MASK & (id >> 21U));
  360.     }
  361.     else {                               // Extended frame format
  362.         CAN_rx_msg->format = EXTENDED_FORMAT;;
  363.         CAN_rx_msg->id = (CAN_EXT_ID_MASK & (id >> 3U));
  364.     }
  365.  
  366.     if ((id & STM32_CAN_RIR_RTR) == 0) {  // Data frame
  367.         CAN_rx_msg->type = DATA_FRAME;
  368.     }
  369.     else {                                // Remote frame
  370.         CAN_rx_msg->type = REMOTE_FRAME;
  371.     }
  372.  
  373.    
  374.     CAN_rx_msg->len = (CAN2->sFIFOMailBox[0].RDTR) & 0xFUL;
  375.    
  376.     CAN_rx_msg->data[0] = 0xFFUL &  CAN2->sFIFOMailBox[0].RDLR;
  377.     CAN_rx_msg->data[1] = 0xFFUL & (CAN2->sFIFOMailBox[0].RDLR >> 8);
  378.     CAN_rx_msg->data[2] = 0xFFUL & (CAN2->sFIFOMailBox[0].RDLR >> 16);
  379.     CAN_rx_msg->data[3] = 0xFFUL & (CAN2->sFIFOMailBox[0].RDLR >> 24);
  380.     CAN_rx_msg->data[4] = 0xFFUL &  CAN2->sFIFOMailBox[0].RDHR;
  381.     CAN_rx_msg->data[5] = 0xFFUL & (CAN2->sFIFOMailBox[0].RDHR >> 8);
  382.     CAN_rx_msg->data[6] = 0xFFUL & (CAN2->sFIFOMailBox[0].RDHR >> 16);
  383.     CAN_rx_msg->data[7] = 0xFFUL & (CAN2->sFIFOMailBox[0].RDHR >> 24);
  384.    
  385.     CAN2->RF0R |= 0x20UL;
  386.   } // END CAN2
  387.  
  388. }
  389.  
  390. /**
  391.  * Encodes CAN messages using the CAN message struct and populates the
  392.  * data registers with the sent.
  393.  *
  394.  * @params CAN_tx_msg - CAN message structure for transmission
  395.  *
  396.  */
  397. void CANSend(uint8_t ch, CAN_msg_t* CAN_tx_msg)
  398. {
  399.   volatile int count = 0;
  400.  
  401.   uint32_t out = 0;
  402.   if (CAN_tx_msg->format == EXTENDED_FORMAT) { // Extended frame format
  403.       out = ((CAN_tx_msg->id & CAN_EXT_ID_MASK) << 3U) | STM32_CAN_TIR_IDE;
  404.   }
  405.   else {                                       // Standard frame format
  406.       out = ((CAN_tx_msg->id & CAN_STD_ID_MASK) << 21U);
  407.   }
  408.  
  409.   // Remote frame
  410.   if (CAN_tx_msg->type == REMOTE_FRAME) {
  411.       out |= STM32_CAN_TIR_RTR;
  412.   }
  413.  
  414.   if (ch == 1) {
  415.     CAN1->sTxMailBox[0].TDTR &= ~(0xF);
  416.     CAN1->sTxMailBox[0].TDTR |= CAN_tx_msg->len & 0xFUL;
  417.    
  418.     CAN1->sTxMailBox[0].TDLR  = (((uint32_t) CAN_tx_msg->data[3] << 24) |
  419.                                  ((uint32_t) CAN_tx_msg->data[2] << 16) |
  420.                                  ((uint32_t) CAN_tx_msg->data[1] <<  8) |
  421.                                  ((uint32_t) CAN_tx_msg->data[0]      ));
  422.     CAN1->sTxMailBox[0].TDHR  = (((uint32_t) CAN_tx_msg->data[7] << 24) |
  423.                                  ((uint32_t) CAN_tx_msg->data[6] << 16) |
  424.                                  ((uint32_t) CAN_tx_msg->data[5] <<  8) |
  425.                                  ((uint32_t) CAN_tx_msg->data[4]      ));
  426.  
  427.     // Send Go
  428.     CAN1->sTxMailBox[0].TIR = out | STM32_CAN_TIR_TXRQ;
  429.  
  430.     // Wait until the mailbox is empty
  431.     while(CAN1->sTxMailBox[0].TIR & 0x1UL && count++ < 1000000);
  432.  
  433.     // The mailbox don't becomes empty while loop
  434.     if (CAN1->sTxMailBox[0].TIR & 0x1UL) {
  435.       SerialUSB.println("Send Fail");
  436.       SerialUSB.println(CAN1->ESR);
  437.       SerialUSB.println(CAN1->MSR);
  438.       SerialUSB.println(CAN1->TSR);
  439.     }
  440.   } // end CAN1
  441.  
  442.   if (ch == 2) {
  443.     CAN2->sTxMailBox[0].TDTR &= ~(0xF);
  444.     CAN2->sTxMailBox[0].TDTR |= CAN_tx_msg->len & 0xFUL;
  445.    
  446.     CAN2->sTxMailBox[0].TDLR  = (((uint32_t) CAN_tx_msg->data[3] << 24) |
  447.                                  ((uint32_t) CAN_tx_msg->data[2] << 16) |
  448.                                  ((uint32_t) CAN_tx_msg->data[1] <<  8) |
  449.                                  ((uint32_t) CAN_tx_msg->data[0]      ));
  450.     CAN2->sTxMailBox[0].TDHR  = (((uint32_t) CAN_tx_msg->data[7] << 24) |
  451.                                  ((uint32_t) CAN_tx_msg->data[6] << 16) |
  452.                                  ((uint32_t) CAN_tx_msg->data[5] <<  8) |
  453.                                  ((uint32_t) CAN_tx_msg->data[4]      ));
  454.  
  455.     // Send Go
  456.     CAN2->sTxMailBox[0].TIR = out | STM32_CAN_TIR_TXRQ;
  457.  
  458.     // Wait until the mailbox is empty
  459.     while(CAN2->sTxMailBox[0].TIR & 0x1UL && count++ < 1000000);
  460.  
  461.     // The mailbox don't becomes empty while loop
  462.     if (CAN2->sTxMailBox[0].TIR & 0x1UL) {
  463.       SerialUSB.println("Send Fail");
  464.       SerialUSB.println(CAN1->ESR);
  465.       SerialUSB.println(CAN1->MSR);
  466.       SerialUSB.println(CAN1->TSR);
  467.     }
  468.   } // end CAN2
  469.  
  470. }
  471.  
  472.  /**
  473.  * Returns whether there are CAN messages available.
  474.  *
  475.  * @returns If pending CAN messages are in the CAN controller
  476.  *
  477.  */
  478. uint8_t CANMsgAvail(uint8_t ch)
  479. {
  480.   if (ch == 1) {
  481.     // Check for pending FIFO 0 messages
  482.     return CAN1->RF0R & 0x3UL;
  483.   } // end CAN1
  484.  
  485.   if (ch == 2) {
  486.     // Check for pending FIFO 0 messages
  487.     return CAN2->RF0R & 0x3UL;
  488.   } // end CAN2
  489.  
  490. }
  491.  
  492. uint8_t insertStr(uint8_t index, char* b1, char* b2)
  493. {
  494.   uint8_t i;
  495.   for(i = index; i < index + strlen(b1); i++)
  496.   {
  497.     b2[i] = b1[i - index];
  498.   }
  499.   return i;
  500. }
  501.  
  502. File dataFile;
  503.  
  504. uint8_t counter = 0;
  505. uint8_t frameLength = 0;
  506. unsigned long previousMillis = 0;     // stores last time output was updated
  507. bool haveBeenConnected = false;
  508. unsigned long oldFileSize;
  509. uint16_t fileVolume = 0;
  510. char fileIndex;
  511. char filename[20];
  512. char buf[30];
  513. char bigBuf[64];
  514.  
  515. void setup() {
  516.   SerialUSB.begin(115200);               // start up the uart module and initialize
  517.   while(!SerialUSB.available()) ;
  518.   while(SerialUSB.available()) SerialUSB.read();
  519.   SerialUSB.println("Startup");
  520.   delay(1000);                        // give the CAN wires time to connect
  521.   LowPower.begin();                   // start up the low power stuff
  522.   bool ret = CANInit(CAN_250KBPS, 2);  // CAN_RX mapped to PB12, CAN_TX mapped to PB13
  523.   while(!ret) ret = CANInit(CAN_250KBPS, 2); // init CAN while we haven't
  524.   pinMode(PA5, OUTPUT); //Green LED
  525.   pinMode(PA6, OUTPUT); //Yellow LED
  526.   pinMode(PA7, OUTPUT); //Red LED
  527.   pinMode(PA3, INPUT);  //Plugged in detection
  528.   SerialUSB.print("Initializing SD card...");
  529.   // see if the card is present and can be initialized:
  530.   uint8_t attempts = 0;
  531.   while (!SD.begin(SD_DETECT_NONE))
  532.   {
  533.     delay(100);
  534.     attempts++;
  535.     if(attempts > 20)
  536.     {
  537.       SerialUSB.println("Initialization failed.");
  538.       digitalWrite(PA7, HIGH);
  539.       while(true) ;
  540.     }
  541.   }
  542.   delay(100);
  543.   SerialUSB.println("card initialized.");
  544.  
  545.   // Create incrementing filename
  546.   if(EEPROM.read(1) != 0) { //This might be the first time this program has ever run
  547.     EEPROM.write(0, 0x00);  //so initialize the filename incrementing index at 0
  548.     EEPROM.write(1, 0x00);  //and store something that says it's been initialized
  549.   }
  550.  
  551.   fileIndex = (char) EEPROM.read(0);
  552.   sprintf(filename, "%s_%d%d.csv", "log", fileIndex, fileVolume);
  553.   // open the file
  554.   dataFile = SD.open(filename, FILE_WRITE);
  555.   // if the file is available, seek to last position
  556.   if (dataFile) {
  557.     EEPROM.write(0, (byte) (fileIndex + 1));
  558.     dataFile.seek(dataFile.size());
  559.     oldFileSize = dataFile.size();
  560.     SerialUSB.println("Opened file for writing");
  561.   }
  562.   // if the file isn't open, pop up an error, light the red LED and halt
  563.   else {
  564.     SerialUSB.println("error opening file for writing");
  565.     digitalWrite(PA7, HIGH);
  566.     while(true) ;
  567.   }
  568. }
  569.  
  570. void loop() {
  571.   CAN_msg_t CAN_TX_msg;
  572.   CAN_msg_t CAN_RX_msg;
  573.  
  574.   bool connectedToCAN = true;//digitalRead(PA3) == HIGH;
  575.   if(SerialUSB.available()) connectedToCAN = false;
  576.   digitalWrite(PA5, connectedToCAN); //green LED is CAN connection status
  577.   if(connectedToCAN) {
  578.     uint8_t recv_ch = 2;
  579.     digitalWrite(PA6, LOW);
  580.     if(CANMsgAvail(recv_ch)) {
  581.       haveBeenConnected = true; //light the yellow LED cause we've got a message
  582.       digitalWrite(PA6, HIGH);
  583.       CANReceive(recv_ch, &CAN_RX_msg);
  584.      
  585.       if(dataFile) { //if the file's still open
  586.         //digitalWrite(PA7, HIGH); //indicate that we're writing to the SD card
  587.         //Add timestamp,messageID,byte,byte,byte,...
  588.         uint8_t index = 0;
  589.         dataFile.seek(dataFile.size());
  590.         sprintf(buf, "%ld,\0", millis() - previousMillis);
  591.         previousMillis = millis();
  592.         index = insertStr(index, buf, bigBuf);
  593.         //dataFile.print(buf);
  594.         sprintf(buf, "%X,\0", CAN_RX_msg.id);
  595.         index = insertStr(index, buf, bigBuf);
  596.         //dataFile.print(buf);
  597.         for(uint8_t i=0; i<CAN_RX_msg.len; i++) {
  598.           sprintf(buf, "%02X\0", CAN_RX_msg.data[i]);
  599.           index = insertStr(index, buf, bigBuf);
  600.           //dataFile.print(buf);
  601.         }
  602.         index = insertStr(index, "\n\0", bigBuf);
  603.         SerialUSB.print(dataFile.write(bigBuf, index));
  604.         //SerialUSB.write(bigBuf, index);
  605.         SerialUSB.print("   ");
  606.         SerialUSB.print(dataFile.size());
  607.         SerialUSB.print(" ");
  608.         SerialUSB.println(oldFileSize);
  609.  
  610.         if(dataFile.size() - oldFileSize > 2000) { //Write to SD card before unwritten data becomes too large
  611.           digitalWrite(PA7, HIGH); //indicate that we're writing to the SD card
  612.           dataFile.flush();
  613.           digitalWrite(PA7, LOW);
  614.           oldFileSize = dataFile.size();
  615.         }
  616.        
  617.         if(dataFile.size() > 16777216) { //Limit individual file size to 16MB
  618.           dataFile.close();
  619.           fileVolume += 1;
  620.           sprintf(filename, "%s_%d%d.csv", "log", fileIndex, fileVolume);
  621.           dataFile = SD.open(filename, FILE_WRITE);
  622.           oldFileSize = dataFile.size();
  623.         }
  624.       }
  625.     }
  626.   }
  627.   else if(haveBeenConnected) {
  628.     SerialUSB.println("Powering Down");
  629.     dataFile.close(); //Neatly close down the file before we lose power (same as flush but also closes file)
  630.     delay(1000);
  631.     Serial.println("\nFiles found on the card (name, date and size in bytes): ");
  632.     File root = SD.openRoot();
  633.     // list all files in the card with date and size
  634.     root.ls(LS_R | LS_DATE | LS_SIZE);
  635.     root.close();
  636.     SerialUSB.println();
  637.     SerialUSB.println(filename);
  638.     delay(1000);
  639.     File reader = SD.open(filename);
  640.  
  641.     // if the file is available, write to it:
  642.     if (reader) {
  643.       while (reader.available()) {
  644.         SerialUSB.write(reader.read());
  645.       }
  646.       reader.close();
  647.     }
  648.    
  649.     digitalWrite(PA5, LOW); //Shut off all the lights
  650.     digitalWrite(PA6, LOW);
  651.     digitalWrite(PA7, LOW);
  652.  
  653.     while(true) ;
  654.    
  655.     //LowPower.deepSleep(); //Go into deep sleep to allow the SD card as much time to finish writing as possible
  656.   }
  657. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement