7-bit ascii
Moderators: David Barker, Jerry Messina
7-bit ascii
Has anyone tried to do 7-bit ascii? I have a project to communicate with an old system that uses it.
-
- Swordfish Developer
- Posts: 1469
- Joined: Fri Jan 30, 2009 6:27 pm
- Location: US
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
Jerry
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.
What changes did you have to make to talk 7O1?
Thanks.
-
- Swordfish Developer
- Posts: 1469
- Joined: Fri Jan 30, 2009 6:27 pm
- Location: US
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
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
It isn't in the version of the standard that I downloaded:garryp4 wrote:Its a standard called SDI-12. The communication is 7n1 at 1200 baud.
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
-
- Swordfish Developer
- Posts: 1469
- Joined: Fri Jan 30, 2009 6:27 pm
- Location: US
Good catch nigle.
Here's some bits of code for dealing with transmitting 7E1...
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
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
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.
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