7-bit ascii

General discussion relating to the library modules supplied with the compiler

Moderators: David Barker, Jerry Messina

Post Reply
garryp4
Posts: 125
Joined: Mon May 21, 2007 7:18 am
Location: Loveland, CO USA

7-bit ascii

Post by garryp4 » Mon Mar 01, 2010 8:41 am

Has anyone tried to do 7-bit ascii? I have a project to communicate with an old system that uses it.

Raistlin
Registered User
Registered User
Posts: 69
Joined: Tue Apr 01, 2008 1:13 pm

Post by Raistlin » Mon Mar 01, 2010 9:02 am

7 bit ASCII is easy enough , depends on what your aiming to do 7 bit ASCII is the same as 8bit only without the other codes Ie highest 7 bit ASCII is 01111111
If you can read this you are too close

Jerry Messina
Swordfish Developer
Posts: 1469
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Post by Jerry Messina » Mon Mar 01, 2010 10:29 am

I assume you're talking about the hardware uart and 7-bit mode. Since the uart in the pic only supports 8/9 bit operation (depending on the pic), you'll have to manually manipulate the eighth bit to match what the end system is expecting. You may have to use it for parity, a stop bit, etc...exactly what depends on what you're talking to. I did this with a system using 7O1, and it worked fine.

Jerry

garryp4
Posts: 125
Joined: Mon May 21, 2007 7:18 am
Location: Loveland, CO USA

Post by garryp4 » Mon Mar 01, 2010 10:40 pm

Thanks for the quick reply. Its a standard called SDI-12. The communication is 7n1 at 1200 baud. Kind of dates the standard, but have a need none the less. I did look at the code for the usart and suart libraries but do not know assembly. That's why I use swordfish.

What changes did you have to make to talk 7O1?

Thanks.

Jerry Messina
Swordfish Developer
Posts: 1469
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Post by Jerry Messina » Tue Mar 02, 2010 10:18 am

To support 7O1 I had to make a number of changes to support dealing with the parity bit and inserting it into the eighth data bit.

For 7N1, things are a bit easier. Since there's no parity, the eighth bit is the stop bit (which is the same as an idle line), or a logic 1.
To transmit a byte, simple OR the ascii data with $80, and when receiving AND it with $7F.

When you transmit, you'll actually be sending a byte that looks like 7N2 since the uart will add a real stop bit, but the receiving system won't care.

When you receive, since the uart requires eight bits, you'll actually get the stop bit in bit 7 (which is why you AND out the msb).

There is one hiccup, and that's if the remote system is capable of sending back-to-back transmissions. For 7N1, a uart has 9 bits to deal with...
<start bit> <7 data bits> <stop bit>. The uart of the pic requires 10 bits...<start bit> <eight data bits> <stop bit>. For this to work, the remote
system must idle the line in between bytes for at least one bit time so that the pic's uart will see the idle line as a stop bit. If it doesn't do this,
then you can't use the hardware uart, and would have to resort to using a modified software uart that would deal with 7 bits.

Hopefully, it's an old, slow system and you'll have the extra bit time you need.

Jerry

nigle
Registered User
Registered User
Posts: 36
Joined: Tue Aug 12, 2008 3:13 pm
Location: West London

Post by nigle » Tue Mar 02, 2010 10:41 am

garryp4 wrote:Its a standard called SDI-12. The communication is 7n1 at 1200 baud.
It isn't in the version of the standard that I downloaded:

Code: Select all

4.1 Baud Rate and Byte Frame Format
   The baud rate for SDI-12 is 1200. Table 2 shows the byte frame format for SDI-12.
      1 start bit
      7 data bits, least significant bit transmitted first
      1 parity bit, even parity
      1 stop bit
The good news is that you can use the hardware UART, the bad is that you need to generate the parity bit.

Jerry Messina
Swordfish Developer
Posts: 1469
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Post by Jerry Messina » Tue Mar 02, 2010 11:10 am

Good catch nigle.

Here's some bits of code for dealing with transmitting 7E1...

Code: Select all

//
// parity functions
// (these functions assume 7-bit data mode with parity in msb (8-bit)
//
public const
    EVEN_PARITY = 0,
    ODD_PARITY = 1

public const
    PARITY_BIT = 7

' returns parity of b...
'   0 = even
'   1 = odd
public function parity(b as byte) as bit

    ' breakdown the following into a simpler expression...
    ' b = b xor ((b >> 4) or (b << 4))
    asm
        swapf b,W
    end asm
    b = b xor WREG

    ' magic parity calculation
    b = b + $41
    b = b or $7c
    b = b + 2

    ' check if (b >= 128)
    if (b.bits(7) = 1) then
        result = ODD_PARITY
    else
        result = EVEN_PARITY
    endif

end function

' 7-bit parity (parity bit in msb)
public function set_odd_parity(b as WREG) as byte
    result = b
    result.bits(PARITY_BIT) = 0
    if (parity(result) = EVEN_PARITY) then
        result.bits(PARITY_BIT) = 1
    endif
end function

public function set_even_parity(b as WREG) as byte
    result = b
    result.bits(PARITY_BIT) = 0
    if (parity(result) = ODD_PARITY) then
        result.bits(PARITY_BIT) = 1
    endif
end function


#define USART_PARITY = EVEN_PARITY

public sub WriteByte(b as byte)

	// 7 data bits. parity is in msb of data char
    #if (USART_PARITY = ODD_PARITY)        // odd parity
        b = set_odd_parity(b)
    #elseif (USART_PARITY = EVEN_PARITY)    // even parity
        b = set_even_parity(b)
    #endif

	USART.WriteByte(b)
end sub


garryp4
Posts: 125
Joined: Mon May 21, 2007 7:18 am
Location: Loveland, CO USA

Post by garryp4 » Mon Mar 08, 2010 5:13 am

Thanks for the replies. And Nigle, you are correct. I want 7E1 not 7N1. Think I am so used to 8N1 and failed to check what I typed.

So, I came up with

Code: Select all

// device and clock...                                                                                                                                                                                                                                         
Device = 18F4620
Clock = 40

// import modules...
Include "usart.bas"
Include "convert.bas"

Private Dim
  an_sw      As PORTD.4,               ' High for RS port, low for Zigbee
  red        As PORTB.3,               ' Red LED
  green      As PORTB.4                ' Green LED

Private Dim
  b1              As Byte,
  b2              As Byte,
  lp1             as byte
  
ADCON0 = $00                           ' Turn off internal A/D
ADCON1 = $0F
ADCON2 = $B2

USART.SetBaudrate(br57600)             ' and baud rate
High(an_sw)
DelayMS(500)
USART.Write(0,10,13,"TEST PARITY! ",10,13)' 
DelayMS(5)

'******************************************************************************
MAIN:

  b2 = 0
  USART.Write(10,13,"ENTER CHARACTER ",10,13)
  b1 = USART.ReadByte
  USART.Write(10,13,"CHARACTER = ",BinToStr(b1,8),10,13)
  for lp1 = 0 to 7
    if b1.bits(lp1) = 1 then  
      b2 = b2 + 1
    endif
  next
  b1 = b1 << 1
  USART.Write("SHIFTED CHARACTER = ",BinToStr(b1,8),10,13)  
  USART.Write("quantity of 1's = ",decToStr(b2),10,13)
  if b2.bits(0) = 1 then               ' 1 if odd number, 0 if even
    B1 = b1 + 1
  endif
  
  USART.Write("7E1 CHARACTER = ",BinToStr(b1,8),10,13)  
      
  GoTo MAIN
It seems to work as I understand the SDI requirement. Now will have to connect and see how it works, of course without the extra messages.

karam
Posts: 1
Joined: Sun Jun 24, 2012 10:51 pm

C code

Post by karam » Mon Jun 25, 2012 12:10 pm

how could i use this in MPLAB, sorry if this is not a place to ask about MPLAB

Post Reply