Linux串列埠程式收發16進位制資料錯誤
問題描述:
在linux下面通過通過C實現串列埠程式網zigbee中寫入16進位制數,但是zigbee執行總是接受不到資料,然後通過IAR檢視MT_UartProcessZToolData()函式中接收到的資料,發現當我傳送0x01時,zigbee接收到的資料為0x81,傳送0xfe時,zigbee接收到也是0xfe,但是寫寫回串列埠,linux接收到的是0x7f 。資料的最高位出現了問題,然後再x86中使用串列埠除錯工具並未出現這樣的狀況,所以鎖定我linux中串列埠程式有問題。最後是c_iflag設定錯誤
/*
*Uart.c
*串列埠初始化
*/
#include "Uart.h"
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <stdlib.h>
#include<linux/types.h>
#include<sys/time.h>
/*
巨集定義
*/
#ifdef DEBUG
#define A_OUT printf("%s:%s:%d:", __FILE__, __FUNCTION__,__LINE__);fflush(stdout);
#define Printf(fmt, arg...) A_OUT printf(fmt, ##arg)
#else
#define A_OUT
#define Printf(fmt, arg...)
#endif
/*
全域性變數
*/
int SerialFd;//儲存串列埠檔案描述符
/*
******************************************************************************************
** 函式名稱 : int HW_Uart_Config (int nSpeed, int nBits, char nEvent, int nStop)
** 函式功能 : 設定串列埠引數
** 入口引數 :
** nSpeed:波特率
** nBits:資料位
** nEvent:奇偶校驗位
** nStop:停止位
** 出口引數 : -1 設定失敗
** 0 設定成功
** 函式說明 : 設定串列埠詳細引數
******************************************************************************************
*/
int HW_Uart_Config (int nSpeed, int nBits, char nEvent, int nStop)
{
struct termios newtio, oldtio;
/*tcgetattr(SerialFd,&options)得到與SerialFd指向物件的相關引數,
並將它們儲存於oldtio,該函式,還可以測試配置是否正確,該串列埠是否
可用等。若呼叫成功,函式返回值為0,若呼叫失敗,函式返回值為1.*/
if (tcgetattr (SerialFd, &oldtio) != 0)
{
perror ("SetupSerial 1");
return -1;
}
bzero (&newtio, sizeof (newtio));
//CLOCAL:修改控制模式,保證程式不會佔用串列埠
//CREAD:修改控制模式,使得能夠從串列埠中讀取輸入資料
newtio.c_cflag |= CLOCAL | CREAD;
//設定資料位
newtio.c_cflag &= ~CSIZE; //遮蔽其他標誌位
switch (nBits)
{
case 7:
newtio.c_cflag |= CS7;
break;
case 8:
newtio.c_cflag |= CS8;
break;
}
//設定奇偶校驗
switch (nEvent)
{
case 'o':
case 'O': //設定為奇校驗
newtio.c_cflag |= PARENB;
newtio.c_cflag |= PARODD;
newtio.c_iflag |= (INPCK | ISTRIP);
break;
case 'e':
case 'E': //設定為偶校驗
newtio.c_iflag |= (INPCK | ISTRIP);
newtio.c_cflag |= PARENB;
newtio.c_cflag &= ~PARODD;
break;
case 'n': //無奇偶校驗位。
case 'N':
newtio.c_iflag &= ~INPCK ;//導致資料收發錯誤是由於這裡設定錯誤, 將c_iflag看出C_cflag
newtio.c_cflag &= ~PARENB;
// newtio.c_cflag &= ~INPCK;//導致收發資料錯誤
break;
case 'S':
case 's': /*as no parity */
newtio.c_cflag &= ~PARENB;
newtio.c_cflag &= ~CSTOPB;
break;
default :
return -1;
}
//設定串列埠輸入波特率和輸出波特率
switch (nSpeed)
{
case 2400:
cfsetispeed (&newtio, B2400);
cfsetospeed (&newtio, B2400);
break;
case 4800:
cfsetispeed (&newtio, B4800);
cfsetospeed (&newtio, B4800);
break;
case 9600:
cfsetispeed (&newtio, B9600);
cfsetospeed (&newtio, B9600);
break;
case 115200:
cfsetispeed (&newtio, B115200);
cfsetospeed (&newtio, B115200);
break;
case 460800:
cfsetispeed (&newtio, B460800);
cfsetospeed (&newtio, B460800);
break;
default:
return -1;
}
// 設定停止位
switch(nStop)
{
case 1:
newtio.c_cflag &= ~CSTOPB;
break;
case 2:
newtio.c_cflag |= CSTOPB;
break;
default:
return -1;
}
//設定等待時間和最小接收字元
newtio.c_cc[VTIME] = 0; //讀取一個字元等待1*(1/10)s
newtio.c_cc[VMIN] = 0; //讀取字元的最少個數
//如果不是開發終端之類的,只是串列埠傳輸資料,
//而不需要串列埠來處理,那麼使用原始模式(Raw Mode)方式來通訊
newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /*Input*/
newtio.c_oflag &= ~OPOST; /*Output*/
//如果發生資料溢位,接收資料,但是不再讀取
tcflush (SerialFd, TCIFLUSH);
//啟用配置 (將修改後的termios資料設定到串列埠中)
if ((tcsetattr (SerialFd, TCSANOW, &newtio)) != 0)
{
perror ("com set error");
return -1;
}
Printf("set done!\n");
return 0;
}
/*
******************************************************************************************
** 函式名稱 : int HW_Uart_Open (const char* DevicePath)
** 函式功能 : 開啟串列埠裝置
** 入口引數 : DevicePath: 開啟串列埠的絕對路徑
** 出口引數 : -1 開啟失敗
** 開啟成功 返回描述符
** 函式說明 : 以非阻塞的方式開啟串列埠裝置
******************************************************************************************
*/
int HW_Uart_Open (const char* DevicePath)
{
SerialFd = open( DevicePath, O_RDWR | O_NOCTTY | O_NDELAY );
if (-1 == SerialFd)
{
perror ("Can't Open Serial Port /dev/ttySAC0");
return (-1);
}
#if 0
if ( fcntl (SerialFd, F_SETFL, 0) < 0 )
Printf ("fcntl failed!\n");
else
Printf ("fcntl=%d\n", fcntl (SerialFd, F_SETFL, 0));
if ( 0 == isatty (STDIN_FILENO) )
Printf ("standard input is not a terminal device\n");
else
Printf ("isatty success!\n");
Printf ("SerialFd-open=%d\n", SerialFd);
#endif
return SerialFd;
}
/*
******************************************************************************************
** 函式名稱 : int HW_Uart_Close (int SerialFd)
** 函式功能 : 關閉串列埠裝置
** 入口引數 : SerialFd: 檔案描述符
** 出口引數 : void
** 函式說明 : 無
******************************************************************************************
*/
void HW_Uart_Close(int SerialFd)
{
close(SerialFd);
}
相關文章
- Uart進行的串列埠收發串列埠
- Linux 串列埠程式設計 使用termios與API進行串列埠程式開發Linux串列埠程式設計iOSAPI
- 資料轉換-16進位制字元字元
- Linux 串列埠程式設計 串列埠裝置程式開發Linux串列埠程式設計
- LED發光二極體,串列埠收發資料、按鍵控制串列埠
- c++ 16進位制資料轉doubleC++
- STM32應用DMA——串列埠收發不定長資料串列埠
- 使用Python輸入16進位制資料Python
- 口算 16 進位制轉換 10 進位制,但只適合兩位的 16 進位制
- 串列埠收發UART(Verilog HDL)串列埠
- JavaScript 進位制轉換(2進位制、8進位制、10進位制、16進位制之間的轉換)JavaScript
- shell 中轉換16進位制10進位制
- Linux Shell 不同進位制資料轉換Linux
- linux串列埠命令列除錯Linux串列埠命令列除錯
- C# 2進位制、8進位制、10進位制、16進位制...各種進位制間的輕鬆轉換C#
- 串列埠收發字元轉換為整數串列埠字元
- 10進位制和16進位制互轉的例子
- printf列印16進位制資料,高位補零的方法。
- 16進位制資料發生高位位元組和地位位元組互換
- Linux串列埠程式設計Linux串列埠程式設計
- Linux 串列埠程式設計Linux串列埠程式設計
- 2進位制_8進位制_16進位制之間快速轉換的技巧.txt
- Java中8進位制和16進位制的表示方法Java
- printf()將10進位制數安照輸出16進位制,8進位制輸出
- C printf按8進位制、10進位制、16進位制輸出以及高位補0
- 串列埠資料抓取及串列埠通訊模擬串列埠
- Java 16進位制字串 取反Java字串
- oracle_16進位制與10進位制轉換小示例Oracle
- C語言中printf打出2進位制與16進位制數C語言
- sql實現10進位制16進位制轉換函式SQL函式
- 3416:【例72.1】 二進位制轉化為十進位制
- 基於Atmega8微控制器的串列埠收發程式串列埠
- 複雜二進位制資料
- 在Java中操作串列埠實現簡訊收發Java串列埠
- 在c語言中輸出8進位制數,16進位制數C語言
- 負數補碼(16進位制轉10進位制的負數)
- 16進位制字串轉位元組字串
- 2/8/16轉10進位制