12

RS-232 通信有时使用 9 位字节。这可用于与总线上的多个微控制器通信,其中 8 位是数据,额外的位表示地址字节(而不是数据)。非活动控制器只为地址字节生成中断。

Linux 程序可以通过串行设备发送和接收 9 位字节吗?如何?

4

6 回答 6

5

termios 系统不直接支持 9 位操作,但可以通过使用 CMSPAR 标志在某些系统上进行模拟。它没有记录,我没有出现在所有实现中。

以下是有关如何完成 9 位仿真的详细文章的链接:

http://www.lothosoft.ch/thomas/libmip/markspaceparity.php

于 2010-06-30T15:02:14.023 回答
3

9 位数据是 RS-485 的标准部分,用于多点应用。基于 16C950 设备的硬件可能支持 9 位,但前提是 UART 用于其 950 模式(而不是用于 RS-232 的更常见的 450/550 模式)。

可在此处找到对 16C950 的描述。

本页总结了 Linux RS-485 支持,该支持已融入更新的内核 (>=3.2 rc3)。

于 2013-01-18T23:13:00.820 回答
3

即使现实世界的 UARTs 没有,9 位数据帧也是可能的。找到了一个在 Windows 和 Linux 下也能做到这一点的库。请参阅http://adontec.com/9-bit-serial-communication.htm

于 2014-11-30T16:23:23.807 回答
2

basically what he wants is to output data from a linux box, then send it on let's say a 2 wire bus with a bunch of max232 ic's -> some microcontroller with uart or software rs232 implementation

one can leave the individual max232 level converter's away as long as there are no voltage potency issues between the individual microcontrollers (on the same pcb, for example, rather than in different buildings ;) up until the maximum output (ttl) load of the max232 (or clones, or a resistor and invertor/transistor) ic.

can't find linux termios settings for MARK or SPACE parity (Which i'm sure the hardware uarts actually do support, just not linux tty implementation), so we shall just hackzor the actual parity generation a bit.

8 data bits, 2 stop bits is the same length as 8 databits, 1 parity bit, 1 stop bit. (where the first stopbit is a logic 1, negative line voltage).

one would then use the 9th bit as an indicator that the other 8 bits are the address of the individual or group of microcontrollers, which then take the next bytes as some sort of command, or data, as well, they are 'addressed'.

this provides for an 8 bit transparant, although one way traffic, means to address 'a lot of things' (256 different (groups of) things, actually ;) on the same bus. it's one way, for when one would want to do 2 way, you'd need 2 wire pairs, or modulate at multiple frequencies, or implement colission detection and the whole lot of that.

PIC microcontrollers can do 9 bit serial communication with ehm 'some trickery' (the 9th bit is actually in another register ;)

now... considering the fact that on linux and the likes it is not -that- simple...

have you considered simply turning parity on for the 'address word' (the one in which you need 9 bits ;) and then either setting it to odd or even, calculate it so that the right one is chosen to make the 9th (parity) bit '1' with parity on and 8 bit 'data', then turn parity back off and turn 2 stop bits on. (which still keeps a 9 bit word length in as far as your microcontroller is concerned ;)... it's a long time ago but as far as i recall stop bits are just as long as data bits in the timing of things.

this should work on anything that can do 8 bit output, with parity, and with 2 stop bits. which includes pc hardware and linux. (and dos etc)

pc hardware also has options to just turn 'parity' on or off for all words (Without actually calculating it) if i recall correctly from 'back in the days'

furthermore, the 9th bit the pic datasheet speaks about, actually IS the parity bit as in RS-232 specifications. just that you're free to turn it off or on. (on PIC's anyway - in linux it's a bit more complicated than that)

(nothing a few termios settings on linux won't solve i think... just turn it on and off then... we've made that stuff do weirder things ;)

a pic microcontroller actually does exactly the same, just that it's not presented like 'what it actually is' in the datasheet. they actually call it 'the 9th bit' and things like that. on pc's and therefore on linux it works pretty much the same way tho.

anyway if this thing should work 'both ways' then good luck wiring it with 2 pairs or figuring out some way to do collission detection, which is hell a lot more problematic than getting 9 bits out.

either way it's not much more than an overrated shift register. if the uart on the pc doesn't want to do it (which i doubt), just abuse the DTR pin to just shift out the data by hand, or abuse the printer port to do the same, or hook up a shift register to the printer port... but with the parity trick it should work fine anyway.

   #include<termios.h>
   #include<stdio.h>
   #include<sys/types.h>
   #include<sys/stat.h>
   #include<fcntl.h>
   #include<unistd.h>
   #include<stdint.h>
   #include<string.h>
   #include<stdlib.h>

   struct termios com1pr;
   int com1fd;

   void bit9oneven(int fd){
   cfmakeraw(&com1pr);
   com1pr.c_iflag=IGNPAR;
   com1pr.c_cflag=CS8|CREAD|CLOCAL|PARENB;
   cfsetispeed(&com1pr,B300);
   cfsetospeed(&com1pr,B300);
   tcsetattr(fd,TCSANOW,&com1pr);
   };//bit9even

   void bit9onodd(int fd){
   cfmakeraw(&com1pr);
   com1pr.c_iflag=IGNPAR;
   com1pr.c_cflag=CS8|CREAD|CLOCAL|PARENB|PARODD;
   cfsetispeed(&com1pr,B300);
   cfsetospeed(&com1pr,B300);
   tcsetattr(fd,TCSANOW,&com1pr);
   };//bit9odd

   void bit9off(int fd){
   cfmakeraw(&com1pr);
   com1pr.c_iflag=IGNPAR;
   com1pr.c_cflag=CS8|CREAD|CLOCAL|CSTOPB;
   cfsetispeed(&com1pr,B300);
   cfsetospeed(&com1pr,B300);
   tcsetattr(fd,TCSANOW,&com1pr);
   };//bit9off

   void initrs232(){
   com1fd=open("/dev/ttyUSB0",O_RDWR|O_SYNC|O_NOCTTY);
   if(com1fd>=0){
   tcflush(com1fd,TCIOFLUSH);
   }else{printf("FAILED TO INITIALIZE\n");exit(1);};
   };//initrs232

   void sendaddress(unsigned char x){
   unsigned char n;
   unsigned char t=0;
   for(n=0;n<8;n++)if(x&2^n)t++;
   if(t&1)bit9oneven(com1fd);
   if(!(t&1))bit9onodd(com1fd);
   write(com1fd,&x,1);
   };

   void main(){

   unsigned char datatosend=0x00; //bogus data byte to send
   initrs232();
   while(1){
   bit9oneven(com1fd);
   while(1)write(com1fd,&datatosend,1);
   //sendaddress(223); // address microcontroller at address 223;
   //write(com1fd,&datatosend,1); // send an a
   //sendaddress(128); // address microcontroller at address 128;
   //write(com1fd,&datatosend,1); //send an a
   }
   //close(com1fd);
   };

somewhat works.. maybe some things the wrong way around but it does send 9 bits. (CSTOPB sets 2 stopbits, meaning that on 8 bit transparant data the 9th bit = 1, in addressing mode the 9th bit = 0 ;)

also take note that the actual rs232 line voltage levels are the other way around from what your software 'reads' (which is the same as the 'inverted' 5v ttl levels your pic microcontroller gets from the transistor or inverter or max232 clone ic). (-19v or -10v (pc) for logic 1, +19/+10 for logic 0), stop bits are negative voltage, like a 1, and the same lenght.

bits go out 0-7 (and in this case: 8 ;)... so start bit -> 0 ,1,2,3,4,5,6,7,

it's a bit hacky but it seems to work on the scope. enter image description here

于 2016-03-04T04:03:24.707 回答
1

Linux 程序可以通过串行设备发送和接收 9 位字节吗?

标准 UART 硬件(8251 等)不支持 9 位数据模式。

于 2010-06-30T15:12:26.680 回答
1

我还为 9 位 UART 仿真做了完整的演示(基于奇偶校验)。你可以在这里找到它。

git上可用的所有资源。

您可以轻松地将其调整为适合您的设备。希望你喜欢。

于 2016-10-30T15:51:03.090 回答