RS-232通信有时使用9位字节。这可用于与总线上的多个微控制器通信,其中8位是数据,而额外位表示地址字节(而不是数据)。非活动控制器仅为地址字节生成中断。
Linux程序可以通过串行设备发送和接收9位字节吗?怎么样?
答案 0 :(得分:5)
termios系统不直接支持9位操作,但可以通过使用CMSPAR标志进行操作来模拟某些系统。它没有记录,我没有出现在所有实现中。
以下是有关如何完成9位仿真的详细说明的链接:
答案 1 :(得分:3)
9位数据是RS-485的标准部分,用于多点应用。基于16C950器件的硬件可能支持9位,但前提是UART用于950模式(而不是用于RS-232的更常见的450/550模式)。
可以找到16C950的说明here。
This页面总结了Linux RS-485支持,它支持更新的内核(> = 3.2 rc3)。
答案 2 :(得分:2)
即使现实世界的UART没有,也可以进行9位数据成帧。 在Windows和Linux下找到了一个也可以使用它的库。 见http://adontec.com/9-bit-serial-communication.htm
答案 3 :(得分:2)
无法找到MARK或SPACE奇偶校验的linux termios设置(我确定硬件uarts实际上支持,只是没有linux tty实现),所以我们只是稍微破解实际的奇偶校验生成。
8个数据位,2个停止位的长度与8个数据位相同,1个奇偶校验位,1个停止位。 (其中第一个停止位是逻辑1,负线电压)。
然后,将使用第9位作为指示,其他8位是单个或一组微控制器的地址,然后将下一个字节作为某种命令或数据,它们是'寻址”。这提供了8位transparant,虽然单向流量,意味着在同一总线上解决“很多事情”(实际上是256个不同的事物组)。这是一种方式,因为当你想要做2路时,你需要2个线对,或者在多个频率上进行调制,或者实现分离检测以及其中的全部。
PIC单片机可以与ehm'一些技巧'进行9位串行通信(第9位实际上在另一个寄存器中;)
现在......考虑到这个事实,在linux和喜欢它不是 - 那么简单......
您是否考虑过简单地为'地址字'(您需要9位的那个)开启奇偶校验;然后将其设置为奇数或偶数,计算它以便选择正确的一个来制作第9个(奇偶校验)位'1',奇偶校验打开,8位'数据',然后关闭奇偶校验并打开2个停止位。 (就微控制器而言,它仍然保持9位字长;)......很久以前,但据我所知,停止位与事物时序中的数据位一样长。
这适用于任何可以进行8位输出,带奇偶校验和2个停止位的操作。其中包括pc硬件和linux。 (和dos等)
pc硬件还可以选择只为所有单词打开或关闭'奇偶校验'(如果我没有实际计算它),如果我从'后面的日子'中正确回忆
此外,pic数据表所述的第9位,实际上是RS-232规范中的奇偶校验位。只是你可以自由关闭或打开它。 (无论如何,在PIC上 - 在Linux中它比这复杂一点)
(linux上没有一些termios设置无法解决,我认为......只需打开和关闭它......我们已经让那些东西做了更奇怪的东西;)
pic微控制器实际上完全相同,只是它没有像数据表中的“它实际是什么”那样呈现。他们实际上称之为“第9位”以及类似的东西。在PC上,因此在Linux上,它的工作原理与此类似。无论如何,如果这个东西应该“双向”运行,那么祝你好运用2对接线或找出一些方法来进行碰撞检测,这比得到9比特要困难得多。
无论哪种方式,它都不过是高估的移位寄存器。如果电脑上的uart不想这样做(我怀疑),只是滥用DTR引脚只是手动移出数据,或者滥用打印机端口做同样的操作,或挂机移位寄存器到打印机端口...但是使用奇偶校验技巧它应该可以正常工作。
#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);
};
有点工作..也许有些事情是错误的,但确实会发送9位。 (CSTOPB设置2个停止位,意味着在8位透明数据上第9位= 1,在寻址模式下第9位= 0;)
另请注意,实际的rs232线路电压水平与您的软件“读取”相反(这与您的PIC微控制器从晶体管或逆变器或max232克隆获得的'反向'5v ttl电平相同我知道了)。 (逻辑1为-19v或-10v(pc),逻辑0为+ 19 / + 10),停止位为负电压,如1,且长度相同。
位出0-7(在这种情况下:8;)...所以起始位 - &gt; 0,1,2,3,4,5,6,7,
答案 4 :(得分:1)
Linux程序可以通过串行设备发送和接收9位字节吗?
标准UART硬件(8251等)不支持9位数据模式。
答案 5 :(得分:0)