Guest User

STM8_I2C_DS1307

a guest
Nov 2nd, 2017
151
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.  *  Project:
  3.  *  Description:
  4.  *
  5.  *
  6.  *  Date:
  7.  */
  8.  
  9.  
  10.  
  11. #include "inc/stm8s.h"
  12. #include "inc/stm8s_gpio.h"
  13. #include <stdlib.h>
  14. #include "inc/uCLI.h"
  15.  
  16. #define DS1307_ADDR       0xD0
  17. #define DS1307_CH_MASK    0x80
  18. #define DS1307_MODE_MASK  0x40
  19. #define DS1307_AMPM_MASK  0x20
  20.  
  21. #define DS1307_BUF_SIZE   64
  22.  
  23. // #define UART_BUF_LENGTH 0x10
  24.  
  25. typedef enum DS1307_REGS
  26. {
  27.   DS1307_REG_SEC       = 0x00,
  28.   DS1307_REG_MIN       = 0x01,
  29.   DS1307_REG_HOUR      = 0x02,
  30.   DS1307_REG_DAY       = 0x03,
  31.   DS1307_REG_DATE      = 0x04,
  32.   DS1307_REG_MONTH     = 0x05,
  33.   DS1307_REG_YEAR      = 0x06,
  34.   DS1307_REG_CONTROL   = 0x07,
  35.   DS1307_REG_RAM_START = 0x08,
  36.   DS1307_REG_RAM_END   = 0x3F
  37. }DS1307_REGS_t;
  38.  
  39. typedef enum UART_STATUS
  40. {
  41.   UART_BUF_EMPTY       = 0x00,
  42.   UART_BUF_UPDATED,
  43.   UART_BUF_FULL,
  44.   UART_BUF_READ,  // If buffer contain valid but old data
  45.   UART_BUF_OVERRUN, // Buffer hasn't been properly proceed and new data available
  46.   UART_BUF_RESET_INDEX
  47. } UART_STATUS_t;
  48.  
  49. CMD_BUF_t cmd_buf; // ring buffer to store commands from uart
  50.  
  51. uint8_t ds1307_buf[DS1307_BUF_SIZE];
  52.  
  53. const char* weekday[] = {"mon", "tue", "wed", "thu", "fri", "sat", "sun"};
  54. unsigned char time_str[30];// 2016/07/02 sat AM 12:04:36
  55.  
  56. void uart_tx_string(unsigned char *str);
  57.  
  58. //========================= Commands declarations ============================//
  59.  
  60. enum CMD
  61. {
  62.   CMD_NONE = 0x00,
  63.   CMD_STOP_CLOCK,
  64.   CMD_START_CLOCK,
  65.   CMD_READ_DS1307,
  66.   CMD_WRITE_DS1307,
  67.   CMD_GET_TIME,
  68.   CMD_SET_TIME
  69. };
  70.  
  71. void cmd_none(void*);
  72. void cmd_start_clock(void*);
  73. void cmd_stop_clock(void*);
  74. // void cmd_get_time(void*);
  75. // void cmd_set_time(void*);
  76. void cmd_read_from_ds1307(void*);
  77. // void cmd_write_to_ds1307(void*);
  78.  
  79. // this is may seems unclear, but just look at CMD_HASHED_t typedef
  80. const CMD_HASHED_t cmd_list[] =
  81. {
  82.   [CMD_NONE].action = cmd_none,
  83.   [CMD_STOP_CLOCK].action = cmd_stop_clock,
  84.   [CMD_START_CLOCK].action = cmd_start_clock,
  85.   [CMD_READ_DS1307].action = cmd_read_from_ds1307
  86. //   {[CMD_WRITE_DS1307] = cmd_write_to_ds1307},
  87. //   {[CMD_GET_TIME] = cmd_get_time},
  88. //   {[CMD_SET_TIME] = cmd_set_time}
  89. };
  90.  
  91.  
  92. //====================== Commands declarations END ===========================//
  93.  
  94.  
  95.  
  96. //================================= I2C ======================================//
  97.  
  98. void I2C_init() // TODO: rewrite this function to more versatile
  99. {
  100.   I2C->FREQR = (HSI_VALUE/(1e6));
  101.   // For standard mode:
  102.   // I2C_period = 2*CCR/F_master => CCR = F_master/(2*I2C_frequency)
  103.   // Let choose I2C_frequency = 50 kHz
  104.   I2C->CCRH = (uint8_t) (((HSI_VALUE)/(2*50000)) >> 8);
  105.   I2C->CCRL = (uint8_t) (((HSI_VALUE)/(2*50000)) & 0xFF);
  106.  
  107.   I2C->TRISER = 16+1; // For standard mode
  108.   I2C->CR1 = I2C_CR1_PE;
  109.   I2C->CR2 = I2C_CR2_ACK;
  110. }
  111.  
  112. inline void I2C_set_START_bit()
  113. {
  114.   I2C->CR2 |= I2C_CR2_START;
  115. }
  116.  
  117. inline void I2C_set_STOP_bit()
  118. {
  119.   I2C->CR2 |= I2C_CR2_STOP;
  120. }
  121.  
  122. inline void I2C_set_ACK_bit()
  123. {
  124.   I2C->CR2 |= I2C_CR2_ACK;
  125. }
  126.  
  127. inline void I2C_reset_ACK_bit()
  128. {
  129.   I2C->CR2 &= ~I2C_CR2_ACK;
  130. }
  131.  
  132. inline uint8_t I2C_is_busy()
  133. {
  134.   return I2C->SR3 & I2C_SR3_BUSY;
  135. }
  136.  
  137. inline void I2C_gen_START_event()
  138. {
  139.   I2C_set_START_bit();
  140.   while (!(I2C->SR1 & I2C_SR1_SB));
  141. }
  142.  
  143. inline void I2C_gen_ADDRESS_event(uint8_t slave_addr)
  144. {
  145.   I2C->DR = slave_addr;
  146.   //uart_tx_string("F I2C_gen_ADDRESS_event. Slave addr set in DR.\n");
  147.   while (!(I2C->SR1 & I2C_SR1_ADDR));
  148.   //uart_tx_string("F I2C_gen_ADDRESS_event. Waiting ADDR flag.\n");
  149.   I2C->SR3; // Dummy read to clear ADDR in SR1
  150.   //uart_tx_string("F I2C_gen_ADDRESS_event. Dummy read of SR3 done.\n");
  151. }
  152.  
  153. inline void I2C_wait_end_of_transmission()
  154. {
  155.   uint8_t tmp_SR1;
  156.   while (1)
  157.   {
  158.     tmp_SR1 = I2C->SR1;
  159.     if ((tmp_SR1 & I2C_SR1_BTF) && (tmp_SR1 & I2C_SR1_TXE)) {break;}
  160.   }
  161. }
  162.  
  163. void I2C_master_tx (uint8_t *data_ptr, uint8_t length)
  164. {
  165.   while (length--)
  166.   {
  167.     while(!(I2C->SR1 & I2C_SR1_TXE));
  168.     I2C->DR = *data_ptr++;
  169.   }
  170. }
  171.  
  172. // TODO: add error check and rewrite possible infinite loops
  173. void I2C_master_send (uint8_t slave_addr, uint8_t *data_ptr, uint8_t length)
  174. {
  175.   I2C_gen_START_event();
  176.   I2C_gen_ADDRESS_event(slave_addr);
  177.   I2C_master_tx(data_ptr, length);
  178.   I2C_wait_end_of_transmission();
  179.   I2C_set_STOP_bit();
  180. }
  181.  
  182. // Method 2 from Ref Manual
  183. void I2C_master_receive (uint8_t slave_addr, uint8_t *data_buf, uint8_t length)
  184. {
  185.   I2C_set_ACK_bit();
  186.  
  187.   I2C_gen_START_event();
  188.   I2C->DR = slave_addr | 0x01;
  189.  
  190.   if (length == 1)
  191.   {
  192.     I2C_reset_ACK_bit();
  193.  
  194.     while (!(I2C->SR1 & I2C_SR1_ADDR));
  195.     __critical // Workaround from errata. EV6_3
  196.     {
  197.       I2C->SR3; // Dummy read to clear ADDR in SR1
  198.       I2C_set_STOP_bit();
  199.     }
  200.  
  201.     while (!(I2C->SR1 & I2C_SR1_RXNE));
  202.     *data_buf = I2C->DR;
  203.   }
  204.   else if (length == 2)
  205.   {
  206.     I2C->CR2 |= I2C_CR2_POS | I2C_CR2_ACK;
  207.  
  208.     while (!(I2C->SR1 & I2C_SR1_ADDR));
  209.     __critical // Workaround from errata. EV6_1
  210.     {
  211.       I2C->SR3; // Dummy read to clear ADDR in SR1
  212.       I2C_reset_ACK_bit();
  213.     }
  214.  
  215.     while (!(I2C->SR1 & I2C_SR1_BTF));
  216.     __critical // Workaround from errata. EV7_3
  217.     {
  218.       I2C_set_STOP_bit();
  219.  
  220.       *data_buf = I2C->DR;
  221.       data_buf++;
  222.       *data_buf = I2C->DR;
  223.     }
  224.  
  225.     I2C->CR2 &= ~I2C_CR2_POS;
  226.   }
  227.   else // Number of bytes to transfer > 2
  228.   {
  229.     while (!(I2C->SR1 & I2C_SR1_ADDR)); // wait for EV6
  230.     I2C->SR3; // Dummy read to clear ADDR in SR1
  231.  
  232.     while (length-- > 3)
  233.     {
  234.       while (!(I2C->SR1 & I2C_SR1_RXNE));
  235.  
  236.       *data_buf++ = I2C->DR;
  237.     }
  238.  
  239.     while (!(I2C->SR1 & I2C_SR1_BTF)); // wait for EV7_2
  240.  
  241.     // EV7_2. Now DataN-2 is in DR, DataN-1 is in hw buffer. Set ACK=0,
  242.     // read DataN-2 from DR, Program STOP=1, read DataN-1.
  243.     I2C_reset_ACK_bit();
  244.     __critical // Workaround from errata
  245.     {
  246.       *data_buf++ = I2C->DR;
  247.       I2C_set_STOP_bit();
  248.       *data_buf++ = I2C->DR;
  249.     }
  250.  
  251.     while (!(I2C->SR1 & I2C_SR1_RXNE)); // wait for EV7
  252.     *data_buf++ = I2C->DR;
  253.   }
  254. }
  255.  
  256. //============================== I2C END =====================================//
  257.  
  258.  
  259.  
  260. //=============================== DS1307 =====================================//
  261.  
  262. void ds1307_write (uint8_t reg_addr, uint8_t *data_ptr, uint8_t length)
  263. {
  264.   I2C_gen_START_event();
  265.   I2C_gen_ADDRESS_event(DS1307_ADDR);
  266.   // Set DS1307 address pointer
  267.   I2C_master_tx(&reg_addr, sizeof(reg_addr));
  268.   I2C_wait_end_of_transmission();
  269.   // Send data
  270.   I2C_master_tx(data_ptr, length);
  271.   // Close transmission
  272.   I2C_wait_end_of_transmission();
  273.   I2C_set_STOP_bit();
  274. }
  275.  
  276. void ds1307_read(uint8_t reg_addr, uint8_t *data_buf_ptr, uint8_t length)
  277. {
  278.   //uart_tx_string("FUNCT ds1307_read.\n");
  279.   I2C_gen_START_event();
  280.   //uart_tx_string("Start event generated.\n");
  281.   I2C_gen_ADDRESS_event(DS1307_ADDR);
  282.   //uart_tx_string("Address event generated.\n");
  283.   I2C_master_tx(&reg_addr, sizeof(reg_addr));
  284.  // uart_tx_string("Register address transmission in progress.\n");
  285.   I2C_wait_end_of_transmission();
  286.   //uart_tx_string("Register address transmitted.\n");
  287.  
  288.   I2C_master_receive(DS1307_ADDR, data_buf_ptr, length);
  289. }
  290.  
  291. //============================= DS1307 END ===================================//
  292.  
  293.  
  294.  
  295. //================================ UART ======================================//
  296.  
  297.  void UART1_init(void)
  298.  {
  299.    // Baudrate 9600 for F_CPU = 16 MHz
  300.    UART1->BRR2 = 0x03;
  301.    UART1->BRR1 = 0x68;
  302.  
  303.    UART1->CR1 = 0x00;
  304.    UART1->CR2 = UART1_CR2_REN | UART1_CR2_RIEN | UART1_CR2_TEN;
  305.  }
  306.  
  307.  // Отправка байта
  308.  inline void uart_tx_byte(uint8_t data)
  309.  {
  310.      while(!(UART1->SR & UART1_SR_TXE));
  311.      UART1->DR = data;
  312.  }
  313.  
  314.  // For debugging feature
  315.  void uart_tx_string(unsigned char *str)
  316.  {
  317.    while(*str != 0) {uart_tx_byte(*str++);};
  318.  }
  319.  
  320. //============================ UART END ======================================//
  321.  
  322.  
  323.  
  324. //================== Commands, settings and control ==========================//
  325.  
  326. // data should be in ds1307 format
  327. void time_to_str(uint8_t *data, uint8_t *str)
  328. {
  329.   // Year
  330.   *str++ = '2';
  331.   *str++ = '0';
  332.   *str++ = (data[6] >> 4) + '0';
  333.   *str++ = (data[6] & 0x0F) + '0';
  334.   *str++ = '/';
  335.   // Month
  336.   *str++ = (data[5] >> 4) + '0';
  337.   *str++ = (data[5] & 0x0F) + '0';
  338.   *str++ = '/';
  339.   // Day
  340.   *str++ = (data[4] >> 4) + '0';
  341.   *str++ = (data[4] & 0x0F) + '0';
  342.   *str++ = ' ';
  343.  
  344.   { // Day of week
  345.     const uint8_t *day = weekday[data[3] - 1];
  346.     uint8_t i;
  347.     for (i = 0; i < 3; i++)
  348.     {
  349.       *str++ = day[i];
  350.     }
  351.     *str++ = ' ';
  352.   }
  353.   // Hours
  354.   if (data[2] & DS1307_MODE_MASK) // 12h  mode
  355.   {
  356.     if (data[2] & DS1307_AMPM_MASK) {*str++ = 'P';}
  357.     else {*str++ = 'A';}
  358.     *str++ = 'M';
  359.     *str++ = ' ';
  360.  
  361.     *str++ = (data[2] >> 4) + '0';
  362.     *str++ = (data[2] & 0x0F) + '0';
  363.   }
  364.   else // 24h mode
  365.   {
  366.     *str++ = (data[2] >> 4) + '0';
  367.     *str++ = (data[2] & 0x0F) + '0';
  368.   }
  369.   *str++ = ':';
  370.   // Minutes
  371.   *str++ = (data[1] >> 4) + '0';
  372.   *str++ = (data[1] & 0x0F) + '0';
  373.   *str++ = ':';
  374.   // Seconds
  375.   *str++ = ((data[0] >> 4) & 0x07) + '0'; // &0x07 to exclude CH bit
  376.   *str++ = (data[0] & 0x0F) + '0';
  377.  
  378.   *str++ = '\n';
  379.   *str = '\0';
  380. }
  381.  
  382. void stop_clock()
  383. {
  384.   ds1307_read(DS1307_REG_SEC, ds1307_buf, 1);
  385.   ds1307_buf[0] |= DS1307_CH_MASK;
  386.   ds1307_write(DS1307_REG_SEC, ds1307_buf, 1);
  387. }
  388.  
  389. void start_clock()
  390. {
  391.   ds1307_read(DS1307_REG_SEC, ds1307_buf, 1);
  392.   ds1307_buf[0] &= ~DS1307_CH_MASK;
  393.   ds1307_write(DS1307_REG_SEC, ds1307_buf, 1);
  394. }
  395.  
  396. void get_time()
  397. {
  398.   // Excluding control register
  399.   ds1307_read(DS1307_REG_SEC, ds1307_buf, sizeof(ds1307_buf) - 1);
  400.   time_to_str(ds1307_buf, time_str);
  401.   uart_tx_string(time_str);
  402. }
  403.  
  404. void set_time(uint8_t *data_buf_ptr, uint8_t length)
  405. {
  406.   // Excluding control register
  407.   ds1307_write(DS1307_REG_SEC, data_buf_ptr, \
  408.              (length < sizeof(ds1307_buf) - 1) ? \
  409.              (length) : (sizeof(ds1307_buf) - 2));
  410. }
  411.  
  412. // ------------------- Command actions --------------------------//
  413.  
  414. void cmd_none(void *ptr)
  415. {
  416.   uart_tx_string("This is dummy command. No action has been taken.\n");
  417. }
  418.  
  419. void cmd_start_clock(void *ptr)
  420. {
  421.   start_clock();
  422.   uart_tx_string("Clock is started.\n");
  423. }
  424.  
  425. void cmd_stop_clock(void *ptr)
  426. {
  427.   stop_clock();
  428.   uart_tx_string("Clock is stopped.\n");
  429. }
  430.  
  431. void cmd_read_from_ds1307(void *ptr)
  432. {
  433.   uint8_t *data = ptr;
  434.  
  435.   /* data[0] -- register address
  436.    * data[1] -- number of bytes to read
  437.    */
  438.   ds1307_read(data[0], ds1307_buf, data[1]);
  439.  
  440.   uart_tx_string("Read ");
  441.   uart_tx_byte(data[1]);
  442.   uart_tx_string(" bytes. Star addr = ");
  443.   uart_tx_byte(data[0] + '0');
  444.   uart_tx_byte('\n');
  445.   {
  446.     uint8_t i;
  447.     uint8_t str[6];
  448.     for (i = 0; i < data[1] - 1; i++)
  449.     {
  450.       _uitoa((unsigned int)ds1307_buf[i], str, 10);
  451.       uart_tx_string(str);
  452.       uart_tx_byte('\n');
  453.     }
  454.   }
  455. }
  456.  
  457.  
  458. //------------------------- Work with command buffer -------------------------//
  459.  
  460. void check_cmd_buf(CMD_BUF_t *buf)
  461. {
  462.   // This logic FIXED
  463.   if (buf->status != CMD_BUF_RECEIVED) return;
  464.  
  465.   if (buf->data[2] < (sizeof(cmd_list)/sizeof(CMD_HASHED_t)))
  466.   {
  467.     uart_tx_string("Processing command\n");
  468.     cmd_list[buf->data[2]].action( & buf->data[3]);
  469.   }
  470.   else
  471.   {
  472.     uart_tx_string("Unknown command ");
  473.     uart_tx_byte(buf->data[2]);
  474.     uart_tx_byte('\n');
  475.   }
  476.  
  477.   uart_tx_string("Reset idx\n");
  478.   buf->idx = 0;
  479.  
  480.   uart_tx_string("reset cmd_buf\n");
  481.   {
  482.     uint8_t i;
  483.     for (i = 0; i < buf->size; i++) {buf->data[i] = 0;}
  484.   }
  485.  
  486.   buf->status = CMD_BUF_EMPTY;
  487.  
  488.   uart_tx_string("Leaving check_cmd_buf\n");
  489. }
  490.  
  491. //================ Commands, settings and control END ========================//
  492.  
  493.  
  494.  
  495. void main(void)
  496. {
  497.   // Disable clock prescaler. F_CPU = 16 MHz
  498.   CLK->CKDIVR = 0x00;
  499.  
  500.   UART1_init();
  501.   I2C_init();
  502.  
  503.   cmd_buf_init(&cmd_buf);
  504.  
  505.   uart_tx_string("Initialization complete.\n");
  506.  
  507.  
  508.  
  509.   __asm__("rim");
  510.  
  511.   while(1)
  512.   {
  513.    check_cmd_buf(&cmd_buf);
  514.   }
  515. }
  516.  
  517. void UART_RX_vector() __interrupt(18)
  518. {
  519.   uart_tx_string("Entering RX ISR\n");
  520.  
  521. //  uart_tx_string("cmd_buf.idx = ");
  522. //  uart_tx_byte(cmd_buf.idx + '0');
  523. //  uart_tx_byte('\n');
  524.  
  525.   // Get data
  526.   {
  527.     uint8_t tmp;
  528.  
  529.     tmp = UART1->DR;
  530.  
  531.     switch (cmd_buf.status)
  532.       {
  533.       case CMD_BUF_EMPTY:
  534.         {
  535.           if (tmp == '#')
  536.           {
  537.             cmd_buf.data[cmd_buf.idx] = '#';
  538.             cmd_buf.idx++;
  539.             cmd_buf.status = CMD_BUF_RECEIVING;
  540.           }
  541.           break;
  542.         }
  543.       case CMD_BUF_RECEIVING:
  544.         {
  545.           if(cmd_buf.idx == 1)
  546.           {
  547.             cmd_buf.data[1] = tmp;
  548.           }
  549.           else
  550.           {
  551.             cmd_buf.data[cmd_buf.idx] = tmp;
  552.  
  553.             if ((cmd_buf.idx - 1) == cmd_buf.data[1])
  554.             {
  555. //              cmd_buf.idx++;
  556. //              cmd_buf.data[cmd_buf.idx] = '\r';
  557.               cmd_buf.status = CMD_BUF_RECEIVED;
  558.             }
  559.           }
  560.  
  561.           cmd_buf.idx++;
  562.           break;
  563.         }
  564.       case CMD_BUF_RECEIVED:
  565.         {
  566.           uart_tx_string("Buffer is full. Command not processed yet.\n");
  567.           break;
  568.         }
  569.       default: break;
  570.     }
  571.   }
  572.  
  573.   uart_tx_string("Leaving RX ISR\n");
  574. }
RAW Paste Data