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
- Committer:
- creatron
- Date:
- 2014-11-11
- Revision:
- 8:595258a79939
- Parent:
- 7:cfe1e0eafb7e
- Child:
- 9:d49cdc77f867
File content as of revision 8:595258a79939:
#include "mbed.h"
#include "RawSerial.h"
#include "dlms_comms.h"
//#define DEBUG_DLMS_COMMS
// Instantiate the raw serial (2nd uart) Tx then Rx
RawSerial rs485(PA_9, PA_10);
// pin to switch the rs485 buffer direction
// DigitalOut dir_485 (PB_0);
DigitalOut dir_485 (D7);
/** ---------------------------------------------------------------------------
* @brief C O N S T R U C T O R
*/
dlms_comms::dlms_comms (void)
{
// enable the rs485 buffer receiver,
dir_485 = 0;
// clear the pointers and ring buffer
rx_head_ptr = 0;
rx_tail_ptr = 0;
memset (rx_buffer, 0, sizeof(rx_buffer));
// transmit empty flag .. need to set buffer
// in receive mode again after we have transmitted
// all data characters
// rs485.attach(this,
// &dlms_comms::Tx_interrupt,
// //RawSerial::TxIrq
// Serial::TxIrq);
// attach the receiver input to 'run' a method
// when characters received
rs485.attach(this,
&dlms_comms::Rx_interrupt,
//RawSerial::RxIrq
Serial::RxIrq);
timer = NULL;
debug_uart = NULL;
tx_irq_count = 0l;
rx_irq_count = 0l;
// /** Set the flow control type on the serial port
// *
// * @param type the flow control type (Disabled, RTS, CTS, RTSCTS)
// * @param flow1 the first flow control pin (RTS for RTS or RTSCTS, CTS for CTS)
// * @param flow2 the second flow control pin (CTS for RTSCTS)
// */
// rs485.set_flow_control(RTSCTS , //Flow type,
// dir_485, //PB_0, //PinName flow1=NC,
// dir_485 //PB_0 //PinName flow2=NC
// );
}
/** ---------------------------------------------------------------------------
* @brief bq34z110::init_port_expander Put all ports in INPUT mode
* @param parent_uart The debug uart class pionter
* @param parent_timer The main timer (system tick) class pointer
*/
void dlms_comms::init (RawSerial * parent_uart,
Timer * parent_timer)
{
// we use the parent timer and debug port
debug_uart = parent_uart;
timer = parent_timer;
//#ifdef DEBUG_DLMS_COMMS
//debug_uart->printf (" init_dlms_comms..\r\n");
//#endif
}
/** ---------------------------------------------------------------------------
* @brief dlms_comms::initialise This method initialise the rs485 comms port
*
* @param baudrate The RS485 baudrate
* @param bits The RS485 number of bits (8)
* @param parity The parity required 'n','o', 'e'
* @param stop_bits The number of stop bits 1 or 2
*/
void dlms_comms::initialise (INT_16 baudrate,
UINT_8 bits,
UINT_8 parity,
UINT_8 stop_bits )
{
// default comms parameters
SerialBase::Parity my_parity = SerialBase::None;
tx_irq_count = 0l;
rx_irq_count = 0l;
// set the class baudrate
rs485.baud(baudrate);
// enable the receiver on the tranceiver buffer chip
dir_485 = 0;
// clear the ring buffer
rx_head_ptr = 0;
rx_tail_ptr = 0;
memset (rx_buffer, 0, sizeof(rx_buffer));
// set the enum parity as required by class
switch (parity)
{
default:
case 'n' :
my_parity = SerialBase::None;
break;
case 'o':
my_parity = SerialBase::Odd;
break;
case 'e':
my_parity = SerialBase::Even;
break;
}
// lets doit .. config the rs485 now
rs485.format((int) bits,
my_parity,
(int) stop_bits);
//# ifdef DEBUG_DLMS_COMMS
//debug_uart->printf (" init_dlms_comms..Baudrate (%d) %d bits Parity=%c\r\n",
// baudrate, bits, parity);
//# endif
// dummy send packet to rs485
//send_packet ("\r\nHello cruel world\r\n",12);
if ( rs485.readable())
rs485.getc();
}
/** ---------------------------------------------------------------------------
* @brief dlms_comms::get_dir485 . This method returns the state of the rs485
* direction
*/
bool dlms_comms::get_dir485 (void)
{
return dir_485;
}
/** ---------------------------------------------------------------------------
* @brief dlms_comms::Tx_interrupt
*/
void dlms_comms::Tx_interrupt(void)
{
tx_irq_count++;
// enable the receiver, we are finito with the transmission of characters
// this changes the direction on the transceiver buffer
if (dir_485 == 1)
dir_485 = 0;
}
/** ---------------------------------------------------------------------------
* @brief dlms_comms::Rx_interrupt . This method received all characters from
* the uart and saved it in a ring buffer, 256 bytes long. The CPU only has 16
* byte fifo, this makes it a 256 bit fifo
*/
void dlms_comms::Rx_interrupt(void)
{
UINT_8 value;
rx_irq_count++;
// read the uart and place character in ring buffer
value = rs485.getc();
rx_buffer[rx_head_ptr++] = value;
}
/** ---------------------------------------------------------------------------
* @brief dlms_comms::available This method return if we have any characters
* available (received on the rs485 port)
* @return true if characters received on the rs485
*/
bool dlms_comms::char_available (void)
{
if (rx_head_ptr == rx_tail_ptr)
// nope
return false;
else
return true;
}
/** ---------------------------------------------------------------------------
* @brief dlms_comms::get_char This method return the last character received
* on the rs485 port
* @return Unsigned byte
* @note The user must make sure that characters are available before, else
* this method shall wait for the next character, no timeouts yet
*/
UINT_8 dlms_comms::get_char (void)
{
// we have to wait for at least on charcter in the ring buffer
while (char_available() == false);
// return the character
return (rx_buffer[rx_tail_ptr++]);
}
/** ---------------------------------------------------------------------------
* @brief dlms_comms::send_packet This method sends a serial packet data to the
* rs485 bus, the directoion of the tranceiver chip is changed to transmit and
* the packet is tranmitted.
* @param ptr Pointer address for start of the packet
* @param length Packet length
* @note The direction is changed with a interrupt when the transmitter
* is empty
*/
void dlms_comms::send_packet (const UINT_8 *ptr,
const UINT_8 length)
{
// local stack variable
UINT_8 * tmp_ptr =(UINT_8 *) ptr;
// change the tranceiver direction to output
dir_485 = 1;
for (UINT_8 i= 0; i < length; i++)
{
rs485.putc (*tmp_ptr++);
}
//
rs485.attach(this,
&dlms_comms::Tx_interrupt,
Serial::TxIrq);
}
UINT_64 dlms_comms::ret_rx_irq_count (void)
{
return rx_irq_count;
}
UINT_64 dlms_comms::ret_tx_irq_count (void)
{
return tx_irq_count;
}
bool dlms_comms::ret_dir_485 (void)
{
return dir_485;
}
//----[ the end ]--------------------------------------------------------------