wiki:Docs/Prog/Manual/DeviceSupport/SerialPorts

Serial Ports

Using Serial Ports for Linux Shell

By default, the Cardinal 825 ships with the Linux console disabled. To enable it, start the indicator and press 3. Setup Menu. Next, press 4. Update Software Menu and then 3. Settings. If you see console=null, remove that line. Save the settings and reboot your indicator. You will now see Linux output from COM1.

Generic Serial Port Use

The “COM1” and “COM2” serial ports are routed through the main board to the MCF5329 processor on the operator interface board. These ports are controlled by the appropriate uCLinux device driver for the built in Coldfire serial ports. These ports may be accessed as:

/dev/ttyS0 = COM1 /dev/ttyS1 = COM2

For example you may test from the serial terminal by typing:

# echo “Hello” > /dev/ttyS1

This will send the message “Hello” out the COM2 serial port. The 825 COM3 port is connected to the main board MCF5213 processor. If the 825 is configured for OIML operation this port is dedicated to sending OIML format verification weight and may not be used by applications. If OIML is not enabled applications may access the COM3 port by means of the mnbd-comm device driver. For example:

# echo “H313233” > /dev/mnbd

This will output “123” to the COM3 port. Note 31 hexadecimal for the ASCII character “1”, 32 is hexadecimal for the ASCII character “2”, etc. As of kernel 2008-11-20 an additional device file /dev/com3 is provided to simplify COM3 application communications. This additional device file is also controlled by the mnbd-comm device driver.

# echo “123” > /dev/com3

Use of /dev/com3 is deprecated.

This will output “123” to the COM3 port.

To perform a similar operations within a C program you may use code similar to:

#include <stdlib.h>
#include <stdio.h>

int main()
{
   FILE* pFile = fopen("/dev/ttyS1", "w");
   if(pFile != NULL)
   {
      fprintf(pFile, "123\r\n");
      fclose(pFile);
   }
}

This will write to COM2. Note fprintf also allows format specifiers such as %d to be used:

    int nID = 240;
    fprintf(pFile, "ID: %d\r\n", nID);

This would output "ID: 240".

You may want a program that reads the serial port and responds:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

#include <string.h>

#include <math.h>
#include <time.h>

#include <signal.h>

#include <termios.h>

#include "lcd.h"

#include "touch.h"
#include "kypdbeep.h"
#include "form.h"
#include "mnbdcomm.h"
#include "login.h"

extern uint32 g_nRepWtIntv;

extern struct mnbd_wt_struct wtdata[MAX_SCALES];
extern uint32 g_nRepWtIntv;
extern unsigned char g_nRepWtTst;

extern int g_keycnt;
extern uint8 g_keybuf[20];

#define TIME_FREQ       100
#define SLP_FREQ        10
#define DSP_FREQ        10

// On terminal send ACK (CTRL-F) - 825 will send back "ACK received"
// On terminal send NACK (CTRL-U) - 825 will send back "NACK received"
// On terminal send STX (CTRL-B) - 825 will start buffering received data
// On termainl send ETX (CTRL-C) - 825 will send back data received and stop buffering


// ttyS1 = COM2
#define SERIAL_PORT "/dev/ttyS1"
#define ACK                     0x06
#define NACK            0x15
#define STX                     0x02
#define ETX                     0x03

#define ACK_RESPONSE            "ACK received\r\n"
#define ACK_RESPONSE_LEN        strlen(ACK_RESPONSE)

#define NACK_RESPONSE           "NACK received\r\n"
#define NACK_RESPONSE_LEN       strlen(NACK_RESPONSE)


int main(int argc, char* argv[])
{
   int n;
   char szMsg[41];
   struct timespec delaytm;

   int i, nFile;
   struct termios options;
   unsigned char rcvdata[11];

   char rcv_buf[50];
   unsigned int rcv_buf_pos = 0;
   enum { rcv_idle, rcv_cmd };
   int rcv_mode = rcv_idle;
    
   nFile = open(SERIAL_PORT, O_RDWR | O_NOCTTY | O_NONBLOCK);
   tcgetattr(nFile, &options);
   options.c_iflag = IGNBRK | IGNPAR;
   options.c_cflag = CS8 | CREAD | CLOCAL | CRTSCTS;
   options.c_lflag = 0;
   options.c_oflag = 0;
   options.c_cc[VMIN] = 1;
   options.c_cc[VTIME] = 0;
   tcsetattr(nFile, TCSADRAIN, &options);
        
   delaytm.tv_sec = 0;
   delaytm.tv_nsec = 100000;
        
   ReadTouchCal();

   OpenBeeper();

   OpenMnBd(0); // Mainboard settings
        
   OpenTouch();
        
   InitLCD();

   OpenMnBd(REQ_SCALE(1));
        
   g_nRepWtIntv = REP_INTV_SAMPLE_RATE;
   MnBdRequest(REQ_SCALE(1), MNBD_REQ_REP_WT, NO_WAIT_ACK);

   int tm_cnt = TIME_FREQ;
   int slp_cnt = SLP_FREQ;
   int dsp_cnt = DSP_FREQ;

   while(1)
   {
      slp_cnt--;
      if(slp_cnt == 0)
      {
          nanosleep(&delaytm, NULL);
          slp_cnt = SLP_FREQ;
      }
        
      if(ind_check_for_wt_rcv(1))
      {
          dsp_cnt--;
          if(dsp_cnt == 0)
          {
              LocateLCD(0,0);
              sprintf(szMsg, "%6.2f", wtdata[1].grosswt);
              PrintLCD(szMsg);

              ReadKeypad();
              if(g_keycnt > 0)
              {
                  g_keycnt = 0;
                  if(g_keybuf[0] == ESC)
                      break;
              }
              dsp_cnt = DSP_FREQ;
          }
      }

      int n = read(nFile, rcvdata, sizeof(rcvdata));
      for(i = 0; i < n; i++)
      {
         if(rcvdata[i] == ACK)
         {
            // Handle ACK
            write(nFile, ACK_RESPONSE, ACK_RESPONSE_LEN);
            rcv_mode = rcv_idle;
         }
         else if(rcvdata[i] == NACK)
         {
            // Handle NACK
            write(nFile, NACK_RESPONSE, NACK_RESPONSE_LEN);
            rcv_mode = rcv_idle;
         }
         else if(rcv_mode == rcv_idle)
         {
            if(rcvdata[i] == STX)
            {
               rcv_mode = rcv_cmd;
               rcv_buf_pos = 0;
            }
         }
         else if(rcv_mode == rcv_cmd)
         {
            if(rcvdata[i] == ETX)
            {
               // Command received - write it 
               write(nFile, rcv_buf, rcv_buf_pos);
               rcv_mode = rcv_idle;
            }
            else
            {
               if(rcv_buf_pos < sizeof(rcv_buf) - 1)
               {
                  rcv_buf[rcv_buf_pos++] = rcvdata[i];
               }
            }
         }
       }
    }
    g_nRepWtIntv = REP_INTV_STOP;
    MnBdRequest(REQ_SCALE(0), MNBD_REQ_REP_WT, NO_WAIT_ACK);

    CloseMnBd(0);
    CloseMnBd(REQ_SCALE(1));
    ClearLCD();
    return 0;
}

This sample displays updating weight on the LCD display and will exit when the Shift-ESC key on the keypad is pressed. If CTRL-F is received on the COM2 port this application will send "ACK received<CR><LF>" out the serial port in response. If CTRL-U is received on the COM2 port this application will send "NACK received<CR><LF>" out the serial port in response. If CTRL-B is received the application will start buffering subsequent received characters. When CTRL-C is received the application will respond back with the buffered characters and stop buffering.

Since COM3 and COM4 are handled by the mainboard processor they allow repeating outputs to be specified with variables for weight, units, etc... This is used by the CScoreboard class in applications such as ID storage. This can be useful because the application can just specify the output and does not have to continue sending constantly.

	bool SetMnBdRepeatFormat(void)
	{
		g_serial_fmt.fmt = 1;

		switch(_format)
		{
		case FMT_SB500:
			if(_sbOverCap)
			{
				strcpy((char*)g_serial_fmt.data, "%%%0 O CAP   r\r");
			}
			else
			{
				if(_scale == 0)
				{
					strcpy((char*)g_serial_fmt.data, "%%%0%G6%%U%G \r");
					g_serial_fmt.data[12] = _sbLightCode;
				}
				else
				{
					sprintf((char*)g_serial_fmt.data, "%%%%%%0%%G(%d)6%%%%U%%G%c\r", _scale, _sbLightCode);
				}
			}
			break;
		case FMT_COMPIF:
			strcpy((char*)g_serial_fmt.data, "%G% %U% G %M%  \r");
			break;
		case FMT_SB200:
			strcpy((char*)g_serial_fmt.data, "%G% %U% G %M%  \r");
			break;
		case FMT_GENERIC:
			strcpy((char*)g_serial_fmt.data, "%G% %U% G %M%  \r");
			break;
		default:
			strcpy((char*)g_serial_fmt.data, "%G% %U% G %M%  \r");
		}

		g_serial_fmt.len = strlen((char*)g_serial_fmt.data);

		if(MnBdRequest(MNBD_DEV, MNBD_REQ_SET_SERIAL_FMT, WAIT_ACK) != OK)
		{
			_errStr = "Error setting format\r\n";
			return false;
		}
		else
		{
			return true;
		}
	}


	bool Start(void)
	{
		_errStr = "";
		bool result = false;

		Stop();
		if (_port != 0)
		{
			//  If COM3 tell mainboard to automatically send output
			if(_port > 2)
			{
				int minor_ver = 0;
				int ver = GetMnBdVer(&minor_ver);
				if(ver >= 120 && minor_ver >= 6)
				{
					if(SetMnBdRepeatFormat())
					{
						if(_scale == 0)
						{
							SetMnBdSerialDefaultScale(0x7F);
						}

						g_serial_rep.fmt = 1;
						g_serial_rep.intv = _interval;
						if (MnBdRequest(MNBD_DEV + _port - 3, MNBD_REQ_REP_SEND_SERIAL_FMT, WAIT_ACK) != OK)
						{
							_errStr = "Error starting scoreboard repeat\r\n";
						}
						else
						{
							_mnbdRepeating = true;
							result = true;
						}
					}
				}
				else if (ver == 0)
				{
					_errStr = "Call MnBdStartup before SB start";
				}
				else
				{
					_errStr = "Update MnBd for SB repeating";
				}
			}
			else
			{
				_file.Open(pszCommPortDev[_port], "w");
				_timer.Start(_interval, true);
				result = true;
			}
		}
		return result;
	}

Variables

%<item code>{(<scale number>)}{<len>}%

{ optional } example %G% = grosswt, %G6% = length 6 characters grosswt, %G(2)6% = length 6 characters scale 2 gross wt

Weight field length may be prefixed with minus sign for left justified negative sign if value is negative. For example %G-6% may produce output such as "- 240". If value is positive a space will be output. Weight field length may be prefixed with a plus sign for left justified plus or minus sign to show positive or negative value. For example %G+6% may produce output such as "+ 50280" or "- 140".

item codedecriptionSupported revisions
GGross weight
TTare weight
NNet weight
Uupper case weight units
ulower case weight units
Cweight status OC=Over Capacity, MO=Motion, BZ=Below Zero, CZ=Center of Zero, two spaces=none of previous
SSMA weight status O=Over Capacity, Z=Center of Zero, one space=none of previous
Mmotion status M=Motion, one space=stable
aSMA format weight output [similar to %S(scl)%1G%M(scl)%(scl)%G(scl)%%u(scl)% ]MnBd DLC 1.21.018 and above, or MnBd 1.20.011 and above
b13 spaces or length specifiedMnBd DLC 1.21.023 and above, or MnBd 1.20.016 and above
dnumber of decimal places (single digit)MnBd DLC 1.21.024 and above, or MnBd 1.20.017 and above
eGross weight no decimal (default 6 digits)MnBd DLC 1.21.024 and above, or MnBd 1.20.017 and above

Use three percent characters %%% to output a percent character

Last modified 12 months ago Last modified on 04/24/23 18:39:16
Note: See TracWiki for help on using the wiki.