>將RTS設置為高.
>發送數據.
>將RTS設置為低.
int setRTS(int level) { int status; ioctl(ser_port, TIOCMGET, &status); if(level) { status |= TIOCM_RTS; } else { status &= ~TIOCM_RTS; } ioctl(ser_port, TIOCMSET, &status); return 1; }
我的問題是:Linux內核不應該自動切換RTS嗎?
以及如何確保在調用setRTS(0)之前發送數據?
shouldn’t the linux kernel be able to switch RTS automatically?
是的,從Linux 3.0開始就有這個內核框架.
RS485通信的時候,再應用程序中,可以進行對485設置為自動方向切換模式。防止由於我們手動切換引腳時,存在的時間問題,因為我們手動切換的時候,每次寫串口的時候,都要將引腳拉高或拉低來切換成寫模式,調用完寫串口的函數后,就要去進行延時一段時間,確保數據在底層硬件層傳輸完畢了,然后將引腳拉高或拉低在切換到讀狀態,這樣由於你計算的時間的誤差性於你拉高拉低引腳的時間誤差性都會導致485的通信不穩定。所以我們如果采用485的自動方向切換模式,將會將這個通信誤差縮小,當每次寫串口時,他自己就會切換為寫狀態,寫完后,又自動切換為讀狀態。
在arm linux上的485自動切換的應用程序操作如下解釋:
打開串口的方法,與設置串口的屬性等,更正常我們在應用程序中使用串口一樣,一樣的方式進行打開串口就可以。
打開串口之后,我們要進行下一面一部,設置一個關於RS485自動方向模式切換要用的結構體和幾個宏,這個結構體將來在填充好后,用ioctl函數寫入到所打開的串口文件描述符中即可。
#define TIOCGRS485 0x542E
#define TIOCSRS485 0x542F
struct my_serial_rs485 //關於485自動方向切換模式要設置的內容的結構體。
{
unsigned long flags; /* RS485 feature flags */
#define SER_RS485_ENABLED (1 << 0) /* If enabled */
#define SER_RS485_RTS_ON_SEND (1 << 1) /* Logical level for
RTS pin when
sending */
#define SER_RS485_RTS_AFTER_SEND (1 << 2) /* Logical level for
RTS pin after sent*/
#define SER_RS485_RX_DURING_TX (1 << 4)
unsigned long delay_rts_before_send; /* Delay before send (milliseconds) */
unsigned long delay_rts_after_send; /* Delay after send (milliseconds) */
unsigned long padding[5]; /* Memory is cheap, new structs
are a royal PITA .. */
};
int main(void)
{
struct my_serial_rs485 rs485conf;
bool flag = false;
flag = g_com1.open_com(Serial_COM_10, O_RDWR | O_NOCTTY); //打開串口,當然這個串口類是要你自己去封裝的
if ( !flag )
{
printf("open com 10 is failed.\n");
_exit(-1);
}
/**************458config 的填充***********************************************/
/* Enable RS485 mode: */
rs485conf.flags |= SER_RS485_ENABLED; //設置使能485
/* Set logical level for RTS pin equal to 1 when sending: */
rs485conf.flags |= SER_RS485_RTS_ON_SEND; //設置rts,當邏輯電平為高的時候,為發送
//rs485conf.flags |= SER_RS485_RTS_AFTER_SEND;
/* set logical level for RTS pin equal to 0 after sending: */
rs485conf.flags &= ~(SER_RS485_RTS_AFTER_SEND); //設置rts,當發送完后邏輯電平為低
//rs485conf.flags &= ~(SER_RS485_RTS_ON_SEND);
/****************************************************************************/
//485的使用
pthread_mutex_lock(&mutex_net1);
len = cclinet1.Recv_from_Net(recv_buffer, MAX_BUF_LEN); //從網絡中讀取數據,len表示讀取到的長度
pthread_mutex_unlock(&mutex_net1);
rs_485_wait_time = 10 * len / baudrate_list[g_info.baud] * 1000; //ms //根據len的長度和波特率算出輸出這么個len長度的字節的時間需要多少ms
/**********************************自動切換485******************/
pthread_mutex_lock(&mutex_com1);
rs485conf.delay_rts_after_send = rs_485_wait_time; //將計算出的發送len長度字節的時間,填充到結構體的成員中,表示發送完串口數據后延時一段時間
if (ioctl (g_com1.m_fd, TIOCSRS485, &rs485conf) < 0) //將填充的結構體寫入到文件描述符中
{
/* Error handling.*/
printf("ioctl TIOCSRS485 error.\n");
}
pthread_mutex_unlock(&mutex_com1);
/********************之后就可以像操作232的串口一樣去操作485的串口了。因為在每次要寫數據時,會自動切換為寫模式,並延時比較准確的時間后去自動切換為讀模式。
return 0;
}
由於程序是在工程開發中的一部分拿出來的,來做485記錄的,並不完整,但關於485的自動切換模式的使用,卻大致就是如此了。