Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
dlms_comms.cpp@0:044dfba47660, 2014-11-11 (annotated)
- Committer:
- creatron
- Date:
- Tue Nov 11 16:01:12 2014 +0000
- Revision:
- 0:044dfba47660
- Child:
- 1:7091401482c5
Flashing led
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
creatron | 0:044dfba47660 | 1 | #include "mbed.h" |
creatron | 0:044dfba47660 | 2 | |
creatron | 0:044dfba47660 | 3 | #include "RawSerial.h" |
creatron | 0:044dfba47660 | 4 | #include "dlms_comms.h" |
creatron | 0:044dfba47660 | 5 | |
creatron | 0:044dfba47660 | 6 | //#define DEBUG_DLMS_COMMS |
creatron | 0:044dfba47660 | 7 | |
creatron | 0:044dfba47660 | 8 | // Instantiate the raw serial (2nd uart) Tx then Rx |
creatron | 0:044dfba47660 | 9 | RawSerial rs485(PA_9, PA_10); |
creatron | 0:044dfba47660 | 10 | // pin to switch the rs485 buffer direction |
creatron | 0:044dfba47660 | 11 | DigitalOut dir_485 (PB_0); |
creatron | 0:044dfba47660 | 12 | |
creatron | 0:044dfba47660 | 13 | /** --------------------------------------------------------------------------- |
creatron | 0:044dfba47660 | 14 | * @brief C O N S T R U C T O R |
creatron | 0:044dfba47660 | 15 | */ |
creatron | 0:044dfba47660 | 16 | dlms_comms::dlms_comms (void) |
creatron | 0:044dfba47660 | 17 | { |
creatron | 0:044dfba47660 | 18 | // enable the rs485 buffer receiver, |
creatron | 0:044dfba47660 | 19 | dir_485 = 0; |
creatron | 0:044dfba47660 | 20 | |
creatron | 0:044dfba47660 | 21 | // clear the pointers and ring buffer |
creatron | 0:044dfba47660 | 22 | rx_head_ptr = 0; |
creatron | 0:044dfba47660 | 23 | rx_tail_ptr = 0; |
creatron | 0:044dfba47660 | 24 | memset (rx_buffer, 0, sizeof(rx_buffer)); |
creatron | 0:044dfba47660 | 25 | |
creatron | 0:044dfba47660 | 26 | // // attach the receiver input to 'run' a method |
creatron | 0:044dfba47660 | 27 | // // when characters received |
creatron | 0:044dfba47660 | 28 | // rs485.attach(this, |
creatron | 0:044dfba47660 | 29 | // &dlms_comms::Rx_interrupt, |
creatron | 0:044dfba47660 | 30 | // RawSerial::RxIrq); |
creatron | 0:044dfba47660 | 31 | // transmit empty flag .. need to set buffer |
creatron | 0:044dfba47660 | 32 | // in receive mode again after we have transmitted |
creatron | 0:044dfba47660 | 33 | // all data characters |
creatron | 0:044dfba47660 | 34 | rs485.attach(this, |
creatron | 0:044dfba47660 | 35 | &dlms_comms::Tx_interrupt, |
creatron | 0:044dfba47660 | 36 | RawSerial::TxIrq); |
creatron | 0:044dfba47660 | 37 | timer = NULL; |
creatron | 0:044dfba47660 | 38 | debug_uart = NULL; |
creatron | 0:044dfba47660 | 39 | } |
creatron | 0:044dfba47660 | 40 | /** --------------------------------------------------------------------------- |
creatron | 0:044dfba47660 | 41 | * @brief bq34z110::init_port_expander Put all ports in INPUT mode |
creatron | 0:044dfba47660 | 42 | * @param parent_uart The debug uart class pionter |
creatron | 0:044dfba47660 | 43 | * @param parent_timer The main timer (system tick) class pointer |
creatron | 0:044dfba47660 | 44 | */ |
creatron | 0:044dfba47660 | 45 | void dlms_comms::init (RawSerial * parent_uart, |
creatron | 0:044dfba47660 | 46 | Timer * parent_timer) |
creatron | 0:044dfba47660 | 47 | { |
creatron | 0:044dfba47660 | 48 | // we use the parent timer and debug port |
creatron | 0:044dfba47660 | 49 | debug_uart = parent_uart; |
creatron | 0:044dfba47660 | 50 | timer = parent_timer; |
creatron | 0:044dfba47660 | 51 | //#ifdef DEBUG_DLMS_COMMS |
creatron | 0:044dfba47660 | 52 | debug_uart->printf (" init_dlms_comms..\r\n"); |
creatron | 0:044dfba47660 | 53 | //#endif |
creatron | 0:044dfba47660 | 54 | } |
creatron | 0:044dfba47660 | 55 | /** --------------------------------------------------------------------------- |
creatron | 0:044dfba47660 | 56 | * @brief dlms_comms::initialise This method initialise the rs485 comms port |
creatron | 0:044dfba47660 | 57 | * |
creatron | 0:044dfba47660 | 58 | * @param baudrate The RS485 baudrate |
creatron | 0:044dfba47660 | 59 | * @param bits The RS485 number of bits (8) |
creatron | 0:044dfba47660 | 60 | * @param parity The parity required 'n','o', 'e' |
creatron | 0:044dfba47660 | 61 | * @param stop_bits The number of stop bits 1 or 2 |
creatron | 0:044dfba47660 | 62 | */ |
creatron | 0:044dfba47660 | 63 | void dlms_comms::initialise (INT_16 baudrate, |
creatron | 0:044dfba47660 | 64 | UINT_8 bits, |
creatron | 0:044dfba47660 | 65 | UINT_8 parity, |
creatron | 0:044dfba47660 | 66 | UINT_8 stop_bits ) |
creatron | 0:044dfba47660 | 67 | { |
creatron | 0:044dfba47660 | 68 | // default comms parameters |
creatron | 0:044dfba47660 | 69 | SerialBase::Parity my_parity = SerialBase::None; |
creatron | 0:044dfba47660 | 70 | irq_count = 0; |
creatron | 0:044dfba47660 | 71 | // set the class baudrate |
creatron | 0:044dfba47660 | 72 | rs485.baud(baudrate); |
creatron | 0:044dfba47660 | 73 | // enable the receiver on the tranceiver buffer chip |
creatron | 0:044dfba47660 | 74 | dir_485 = 0; |
creatron | 0:044dfba47660 | 75 | // clear the ring buffer |
creatron | 0:044dfba47660 | 76 | rx_head_ptr = 0; |
creatron | 0:044dfba47660 | 77 | rx_tail_ptr = 0; |
creatron | 0:044dfba47660 | 78 | memset (rx_buffer, 0, sizeof(rx_buffer)); |
creatron | 0:044dfba47660 | 79 | // set the enum parity as required by class |
creatron | 0:044dfba47660 | 80 | switch (parity) |
creatron | 0:044dfba47660 | 81 | { |
creatron | 0:044dfba47660 | 82 | default: |
creatron | 0:044dfba47660 | 83 | case 'n' : |
creatron | 0:044dfba47660 | 84 | my_parity = SerialBase::None; |
creatron | 0:044dfba47660 | 85 | break; |
creatron | 0:044dfba47660 | 86 | case 'o': |
creatron | 0:044dfba47660 | 87 | my_parity = SerialBase::Odd; |
creatron | 0:044dfba47660 | 88 | break; |
creatron | 0:044dfba47660 | 89 | case 'e': |
creatron | 0:044dfba47660 | 90 | my_parity = SerialBase::Even; |
creatron | 0:044dfba47660 | 91 | break; |
creatron | 0:044dfba47660 | 92 | } |
creatron | 0:044dfba47660 | 93 | // lets doit .. config the rs485 now |
creatron | 0:044dfba47660 | 94 | rs485.format((int) bits, |
creatron | 0:044dfba47660 | 95 | my_parity, |
creatron | 0:044dfba47660 | 96 | (int) stop_bits); |
creatron | 0:044dfba47660 | 97 | # ifdef DEBUG_DLMS_COMMS |
creatron | 0:044dfba47660 | 98 | debug_uart->printf (" init_dlms_comms..Baudrate (%d) %d bits Parity=%c\r\n", |
creatron | 0:044dfba47660 | 99 | baudrate, bits, parity); |
creatron | 0:044dfba47660 | 100 | # endif |
creatron | 0:044dfba47660 | 101 | // dummy send packet to rs485 |
creatron | 0:044dfba47660 | 102 | //send_packet ("\r\nHello cruel world\r\n",12); |
creatron | 0:044dfba47660 | 103 | } |
creatron | 0:044dfba47660 | 104 | /** --------------------------------------------------------------------------- |
creatron | 0:044dfba47660 | 105 | * @brief dlms_comms::get_dir485 . This method returns the state of the rs485 |
creatron | 0:044dfba47660 | 106 | * direction |
creatron | 0:044dfba47660 | 107 | */ |
creatron | 0:044dfba47660 | 108 | bool dlms_comms::get_dir485 (void) |
creatron | 0:044dfba47660 | 109 | { |
creatron | 0:044dfba47660 | 110 | return dir_485; |
creatron | 0:044dfba47660 | 111 | } |
creatron | 0:044dfba47660 | 112 | /** --------------------------------------------------------------------------- |
creatron | 0:044dfba47660 | 113 | * @brief dlms_comms::Tx_interrupt |
creatron | 0:044dfba47660 | 114 | */ |
creatron | 0:044dfba47660 | 115 | void dlms_comms::Tx_interrupt(void) |
creatron | 0:044dfba47660 | 116 | { |
creatron | 0:044dfba47660 | 117 | irq_count++; |
creatron | 0:044dfba47660 | 118 | // enable the receiver, we are finito with the transmission of characters |
creatron | 0:044dfba47660 | 119 | // this changes the direction on the transceiver buffer |
creatron | 0:044dfba47660 | 120 | if (dir_485 == 1) |
creatron | 0:044dfba47660 | 121 | dir_485 = 0; |
creatron | 0:044dfba47660 | 122 | } |
creatron | 0:044dfba47660 | 123 | /** --------------------------------------------------------------------------- |
creatron | 0:044dfba47660 | 124 | * @brief dlms_comms::Rx_interrupt . This method received all characters from |
creatron | 0:044dfba47660 | 125 | * the uart and saved it in a ring buffer, 256 bytes long. The CPU only has 16 |
creatron | 0:044dfba47660 | 126 | * byte fifo, this makes it a 256 bit fifo |
creatron | 0:044dfba47660 | 127 | */ |
creatron | 0:044dfba47660 | 128 | void dlms_comms::Rx_interrupt(void) |
creatron | 0:044dfba47660 | 129 | { |
creatron | 0:044dfba47660 | 130 | UINT_8 value; |
creatron | 0:044dfba47660 | 131 | // read the uart and place character in ring buffer |
creatron | 0:044dfba47660 | 132 | value = rs485.getc(); |
creatron | 0:044dfba47660 | 133 | rx_buffer[rx_head_ptr++] = value; |
creatron | 0:044dfba47660 | 134 | } |
creatron | 0:044dfba47660 | 135 | /** --------------------------------------------------------------------------- |
creatron | 0:044dfba47660 | 136 | * @brief dlms_comms::available This method return if we have any characters |
creatron | 0:044dfba47660 | 137 | * available (received on the rs485 port) |
creatron | 0:044dfba47660 | 138 | * @return true if characters received on the rs485 |
creatron | 0:044dfba47660 | 139 | */ |
creatron | 0:044dfba47660 | 140 | bool dlms_comms::char_available (void) |
creatron | 0:044dfba47660 | 141 | { |
creatron | 0:044dfba47660 | 142 | if (rx_head_ptr == rx_tail_ptr) |
creatron | 0:044dfba47660 | 143 | // nope |
creatron | 0:044dfba47660 | 144 | return false; |
creatron | 0:044dfba47660 | 145 | else |
creatron | 0:044dfba47660 | 146 | return true; |
creatron | 0:044dfba47660 | 147 | } |
creatron | 0:044dfba47660 | 148 | /** --------------------------------------------------------------------------- |
creatron | 0:044dfba47660 | 149 | * @brief dlms_comms::get_char This method return the last character received |
creatron | 0:044dfba47660 | 150 | * on the rs485 port |
creatron | 0:044dfba47660 | 151 | * @return Unsigned byte |
creatron | 0:044dfba47660 | 152 | * @note The user must make sure that characters are available before, else |
creatron | 0:044dfba47660 | 153 | * this method shall wait for the next character, no timeouts yet |
creatron | 0:044dfba47660 | 154 | */ |
creatron | 0:044dfba47660 | 155 | UINT_8 dlms_comms::get_char (void) |
creatron | 0:044dfba47660 | 156 | { |
creatron | 0:044dfba47660 | 157 | // we have to wait for at least on charcter in the ring buffer |
creatron | 0:044dfba47660 | 158 | while (char_available() == false); |
creatron | 0:044dfba47660 | 159 | // return the character |
creatron | 0:044dfba47660 | 160 | return (rx_buffer[rx_tail_ptr++]); |
creatron | 0:044dfba47660 | 161 | } |
creatron | 0:044dfba47660 | 162 | /** --------------------------------------------------------------------------- |
creatron | 0:044dfba47660 | 163 | * @brief dlms_comms::send_packet This method sends a serial packet data to the |
creatron | 0:044dfba47660 | 164 | * rs485 bus, the directoion of the tranceiver chip is changed to transmit and |
creatron | 0:044dfba47660 | 165 | * the packet is tranmitted. |
creatron | 0:044dfba47660 | 166 | * @param ptr Pointer address for start of the packet |
creatron | 0:044dfba47660 | 167 | * @param length Packet length |
creatron | 0:044dfba47660 | 168 | * @note The direction is changed with a interrupt when the transmitter |
creatron | 0:044dfba47660 | 169 | * is empty |
creatron | 0:044dfba47660 | 170 | */ |
creatron | 0:044dfba47660 | 171 | void dlms_comms::send_packet (const UINT_8 *ptr, |
creatron | 0:044dfba47660 | 172 | const UINT_8 length) |
creatron | 0:044dfba47660 | 173 | { |
creatron | 0:044dfba47660 | 174 | // local stack variable |
creatron | 0:044dfba47660 | 175 | UINT_8 * tmp_ptr =(UINT_8 *) ptr; |
creatron | 0:044dfba47660 | 176 | |
creatron | 0:044dfba47660 | 177 | // change the tranceiver direction to output |
creatron | 0:044dfba47660 | 178 | dir_485 = 1; |
creatron | 0:044dfba47660 | 179 | for (UINT_8 i= 0; i < length; i++) |
creatron | 0:044dfba47660 | 180 | { |
creatron | 0:044dfba47660 | 181 | rs485.putc (*tmp_ptr++); |
creatron | 0:044dfba47660 | 182 | } |
creatron | 0:044dfba47660 | 183 | } |
creatron | 0:044dfba47660 | 184 | UINT_64 dlms_comms::ret_irq_count (void) |
creatron | 0:044dfba47660 | 185 | { |
creatron | 0:044dfba47660 | 186 | return irq_count; |
creatron | 0:044dfba47660 | 187 | } |
creatron | 0:044dfba47660 | 188 | bool dlms_comms::poll_rs485(void) |
creatron | 0:044dfba47660 | 189 | { |
creatron | 0:044dfba47660 | 190 | if (rs485.readable ()) |
creatron | 0:044dfba47660 | 191 | { |
creatron | 0:044dfba47660 | 192 | Rx_interrupt(); |
creatron | 0:044dfba47660 | 193 | return true; |
creatron | 0:044dfba47660 | 194 | } |
creatron | 0:044dfba47660 | 195 | return false; |
creatron | 0:044dfba47660 | 196 | } |
creatron | 0:044dfba47660 | 197 | //----[ the end ]-------------------------------------------------------------- |