现在我要使用到v3s的uart0和uart1,其中我uart0接控制控制台做调试,uart1接串口做数据的收发并将程序运行结果显示在控制台上,由于uart0的波特率为115200,uart1的波特率为9600,请问有必要将串口1的波特率调成115200吗?需要修改的话在哪修改,根据帖子我已经修改了,开启了uart1和uart2
sun8i-v3s.dtsi:
uart0_pins_a: uart0@0 { pins = “PB8”, “PB9”;function = “uart0”;bias-pull-up; };
uart1_pins_a: uart1@0 { pins = “PE21”, “PE22”;function = “uart1”;bias-pull-up; };
uart2_pins_a: uart2@0 { pins = “PB0”, “PB1”;function = “uart2”;bias-pull-up; };
sun8i-v3s-licheepi-zero.dts:
&uart0 { pinctrl-0 = <&uart0_pins_a>;pinctrl-names = “default”;status = “okay”; };
&uart1 { pinctrl-0 = <&uart1_pins_a>;pinctrl-names = “default”;status = “okay”; };
&uart2 { pinctrl-0 = <&uart2_pins_a>;pinctrl-names = “default”;status = “okay”; };
最近编辑记录 605364021 (2019-05-11 12:50:02)
离线
uart0 是 ttyS0, 并且是系统的控制台, 现在要显示 ttyS1 收到的数据?
是的,这样可以?控制台跑的程序读取的串口是/dev/ttyS1
离线
605364021 说:晕哥 说:uart0 是 ttyS0, 并且是系统的控制台, 现在要显示 ttyS1 收到的数据?
是的,这样可以?控制台跑的程序读取的串口是/dev/ttyS1
那不用改 uart0 的设置, 他们之间并没有关系。
uart1的波特率也不用修改?应该我通过串口助手往uart1写入数据时候,控制台运行的串口读写程序好像无法收到。。
离线
uart1 要改, 网上有标准的 ttySx 读写代码, 编译一下就可以在 V3s Linux 下面跑了。
那怎么修改uart1的波特率呢?修改设备树?
最近编辑记录 605364021 (2019-05-11 15:29:19)
离线
不用改设备树,直接应用程序操作即可。
通过 open() 系统调用, 然后通过 tcsetattr() 设置
http://www.cs.cmu.edu/afs/cs/usr/jmd/serialtest.c
#include <termios.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
//#include <sys/signal.h>
#include <signal.h>
#include <sys/types.h>
#define BAUDRATE B38400
#define MODEMDEVICE "/dev/ttyS1"
#define _POSIX_SOURCE 1 //POSIX compliant source
#define FALSE 0
#define TRUE 1
volatile int STOP=FALSE;
void signal_handler_IO (int status); //definition of signal handler
int wait_flag=TRUE; //TRUE while no signal received
char devicename[80];
long Baud_Rate = 38400; // default Baud Rate (110 through 38400)
long BAUD; // derived baud rate from command line
long DATABITS;
long STOPBITS;
long PARITYON;
long PARITY;
int Data_Bits = 8; // Number of data bits
int Stop_Bits = 1; // Number of stop bits
int Parity = 0; // Parity as follows:
// 00 = NONE, 01 = Odd, 02 = Even, 03 = Mark, 04 = Space
int Format = 4;
FILE *input;
FILE *output;
int status;
main(int Parm_Count, char *Parms[])
{
char version[80] = "Program start\n";
char Param_strings[7][80];
char message[90];
int fd, tty, c, res, i, error;
char In1, Key;
struct termios oldtio, newtio; //place for old and new port settings for serial port
struct termios oldkey, newkey; //place tor old and new port settings for keyboard teletype
struct sigaction saio; //definition of signal action
char buf[255]; //buffer for where data is put
input = fopen("/dev/tty", "r"); //open the terminal keyboard
output = fopen("/dev/tty", "w"); //open the terminal screen
if (!input || !output)
{
fprintf(stderr, "Unable to open /dev/tty\n");
exit(1);
}
error=0;
fputs(version,output); //display the program introduction
//read the parameters from the command line
if (Parm_Count==7) //if there are the right number of parameters on the command line
{
for (i=1; i<Parm_Count; i++) // for all wild search parameters
{
strcpy(Param_strings[i-1],Parms[i]);
}
i=sscanf(Param_strings[0],"%s",devicename);
if (i != 1) error=1;
i=sscanf(Param_strings[1],"%li",&Baud_Rate);
if (i != 1) error=1;
i=sscanf(Param_strings[2],"%i",&Data_Bits);
if (i != 1) error=1;
i=sscanf(Param_strings[3],"%i",&Stop_Bits);
if (i != 1) error=1;
i=sscanf(Param_strings[4],"%i",&Parity);
if (i != 1) error=1;
i=sscanf(Param_strings[5],"%i",&Format);
if (i != 1) error=1;
sprintf(message,"Device=%s, Baud=%li\r\n",devicename, Baud_Rate); //output the received setup parameters
fputs(message,output);
sprintf(message,"Data Bits=%i Stop Bits=%i Parity=%i Format=%i\r\n",Data_Bits, Stop_Bits, Parity, Format);
fputs(message,output);
} //end of if param_count==7
if ((Parm_Count==7) && (error==0)) //if the command line entrys were correct
{ //run the program
tty = open("/dev/tty", O_RDWR | O_NOCTTY | O_NONBLOCK); //set the user console port up
tcgetattr(tty,&oldkey); // save current port settings //so commands are interpreted right for this program
// set new port settings for non-canonical input processing //must be NOCTTY
newkey.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
newkey.c_iflag = IGNPAR;
newkey.c_oflag = 0;
newkey.c_lflag = 0; //ICANON;
newkey.c_cc[VMIN]=1;
newkey.c_cc[VTIME]=0;
tcflush(tty, TCIFLUSH);
tcsetattr(tty,TCSANOW,&newkey);
switch (Baud_Rate)
{
case 38400:
default:
BAUD = B38400;
break;
case 19200:
BAUD = B19200;
break;
case 9600:
BAUD = B9600;
break;
case 4800:
BAUD = B4800;
break;
case 2400:
BAUD = B2400;
break;
case 1800:
BAUD = B1800;
break;
case 1200:
BAUD = B1200;
break;
case 600:
BAUD = B600;
break;
case 300:
BAUD = B300;
break;
case 200:
BAUD = B200;
break;
case 150:
BAUD = B150;
break;
case 134:
BAUD = B134;
break;
case 110:
BAUD = B110;
break;
case 75:
BAUD = B75;
break;
case 50:
BAUD = B50;
break;
} //end of switch baud_rate
switch (Data_Bits)
{
case 8:
default:
DATABITS = CS8;
break;
case 7:
DATABITS = CS7;
break;
case 6:
DATABITS = CS6;
break;
case 5:
DATABITS = CS5;
break;
} //end of switch data_bits
switch (Stop_Bits)
{
case 1:
default:
STOPBITS = 0;
break;
case 2:
STOPBITS = CSTOPB;
break;
} //end of switch stop bits
switch (Parity)
{
case 0:
default: //none
PARITYON = 0;
PARITY = 0;
break;
case 1: //odd
PARITYON = PARENB;
PARITY = PARODD;
break;
case 2: //even
PARITYON = PARENB;
PARITY = 0;
break;
} //end of switch parity
//open the device(com port) to be non-blocking (read will return immediately)
fd = open(devicename, O_RDWR | O_NOCTTY | O_NONBLOCK);
printf("After opening serial port...\n");
if (fd < 0)
{
printf("Didn't open serial port successfully...\n");
perror(devicename);
exit(-1);
}
//install the serial handler before making the device asynchronous
printf("Installing serial handler...\n");
saio.sa_handler = signal_handler_IO;
sigemptyset(&saio.sa_mask); //saio.sa_mask = 0;
saio.sa_flags = 0;
// saio.sa_restorer = NULL;
sigaction(SIGIO,&saio,NULL);
// allow the process to receive SIGIO
printf("Before fcntl...\n");
fcntl(fd, F_SETOWN, getpid());
// Make the file descriptor asynchronous (the manual page says only
// O_APPEND and O_NONBLOCK, will work with F_SETFL...)
fcntl(fd, F_SETFL, FASYNC);
tcgetattr(fd,&oldtio); // save current port settings
// set new port settings for canonical input processing
newtio.c_cflag = BAUD | CRTSCTS | DATABITS | STOPBITS | PARITYON | PARITY | CLOCAL | CREAD;
newtio.c_iflag = IGNPAR;
newtio.c_oflag = 0;
newtio.c_lflag = 0; //ICANON;
newtio.c_cc[VMIN]=1;
newtio.c_cc[VTIME]=0;
tcflush(fd, TCIFLUSH);
tcsetattr(fd,TCSANOW,&newtio);
// loop while waiting for input. normally we would do something useful here
printf("About to wait for keys...\n");
while (STOP==FALSE)
{
printf("Before status...\n");
status = fread(&Key,1,1,input);
if (status==1) //if a key was hit
{
printf("A key was hit...\n");
switch (Key)
{ /* branch to appropiate key handler */
case 0x1b: /* Esc */
STOP=TRUE;
break;
default:
printf("Output key...\n");
fputc((int) Key,output);
// sprintf(message,"%x ",Key); //debug
// fputs(message,output);
write(fd,&Key,1); //write 1 byte to the serial port
break;
} //end of switch key
} //end if a key was hit
// after receiving SIGIO, wait_flag = FALSE, input is available and can be read
if (wait_flag==FALSE) //if input is available
{
res = read(fd,buf,255);
if (res)
{
for (i=0; i<res; i++) //for all chars in string
{
In1 = buf[i];
switch (Format)
{
case 1: //hex
sprintf(message,"%x ",In1);
fputs(message,output);
break;
case 2: //decimal
sprintf(message,"%d ",In1);
fputs(message,output);
break;
case 3: //hex and asc
if ((In1) || (In1))
{
sprintf(message,"%x",In1);
fputs(message,output);
}
else fputc ((int) In1, output);
break;
case 4: //decimal and asc
default:
if ((In1) || (In1))
{
sprintf(message,"%d",In1);
fputs(message,output);
}
else fputc ((int) In1, output);
break;
case 5: //asc
fputc ((int) In1, output);
break;
} //end of switch format
} //end of for all chars in string
} //end if res
// buf[res]=0;
// printf(":%s:%d\n", buf, res);
// if (res==1) STOP=TRUE; /* stop loop if only a CR was input */
wait_flag = TRUE; /* wait for new input */
} //end if wait flag == FALSE
} //while stop==FALSE
printf("Got ESC key...\n");
// restore old port settings
tcsetattr(fd,TCSANOW,&oldtio);
printf("After tcsetattr1...\n");
tcsetattr(tty,TCSANOW,&oldkey);
printf("After tcsetattr2...\n");
close(tty);
printf("After close(tty)...\n");
close(fd); //close the com port
printf("After close(fd)...\n");
printf("End of command line entries correct...\n");
} //end if command line entrys were correct
printf("Before fclose...\n");
fclose(input);
fclose(output);
printf("After fclose...\n");
} //end of main
/************************************************************************
* signal handler. sets wait_flag to FALSE, to indicate above loop that *
* characters have been received. *
************************************************************************/
void signal_handler_IO (int status)
{
printf("received SIGIO signal.\n");
wait_flag = FALSE;
}
试一下这个 demo ?
离线
licheepi zero 使用UART 2 发送串口数据时候,出现乱码,数据根本不对。晕哥,你帮我分析下看看问题出在哪?
[uart2]
uart_used = 1
uart_port = 2
uart_type = 2
uart_tx = port:PB00<2><1><default><default>
uart_rx = port:PB01<2><1><default><default>
应用层代码为:
#include<stdio.h>
#include<stdlib.h>
#include<fcntl.h>
#include<unistd.h>
#include<assert.h>
#include<termios.h>
#include<string.h>
#include<sys/time.h>
#include<sys/types.h>
#include<errno.h>
#include "uart.h"
#include "global.h"
static int ret;
static int fd;
/*
* 安全读写函数
*/
ssize_t safe_write(int fd, const void *vptr, size_t n)
{
size_t nleft;
ssize_t nwritten;
const unsigned char *ptr;
ptr = vptr;
nleft = n;
while(nleft > 0)
{
if((nwritten = write(fd, ptr, nleft)) <= 0)
{
if(nwritten < 0&&errno == EINTR)
nwritten = 0;
else
return -1;
}
nleft -= nwritten;
ptr += nwritten;
}
return(n);
}
ssize_t safe_read(int fd,void *vptr,size_t n)
{
size_t nleft;
ssize_t nread;
char *ptr;
ptr=vptr;
nleft=n;
while(nleft > 0)
{
if((nread = read(fd,ptr,nleft)) < 0)
{
if(errno == EINTR)//被信号中断
nread = 0;
else
return -1;
}
else
if(nread == 0)
break;
nleft -= nread;
ptr += nread;
}
return (n-nleft);
}
int uart_open(gSealData *pgsd,const char *pathname)
{
if (NULL == pgsd)
{
printf("In \"uart_open\" parameter is NULL.\n");
return -1;
}
if (NULL == pathname)
{
zlog_error(pgsd->zc, "pathname is NULL.\n");
return -2;
}
pgsd->fInfo.fd = open(pathname,O_RDWR|O_NOCTTY|O_NDELAY);
if(UART2_FD_INITIALIZATION == pgsd->fInfo.fd)
{
zlog_error(pgsd->zc, "open [%s] failed.\n", pathname);
return -3;
}
#if 0
/*清除串口非阻塞标志*/
if(fcntl(fd,F_SETFL,0) < 0)
{
fprintf(stderr,"fcntl failed!\n");
return -1;
}
#endif
return 0;
}
int uart_set(gSealData *pgsd)
{
if (NULL == pgsd)
{
printf("In \"uart_set\" parameter is NULL.\n");
return -1;
}
int baude = pgsd->fInfo.baude;
int c_flow = pgsd->fInfo.flow;
int bits = pgsd->fInfo.bits;
int parity = pgsd->fInfo.parity;
int stop = pgsd->fInfo.stop;
struct termios options;
/*获取终端属性*/
if(tcgetattr(pgsd->fInfo.fd,&options) < 0)
{
perror("tcgetattr error");
return -1;
}
/*设置输入输出波特率,两者保持一致*/
switch(baude)
{
case 4800:
cfsetispeed(&options,B4800);
cfsetospeed(&options,B4800);
break;
case 9600:
cfsetispeed(&options,B9600);
cfsetospeed(&options,B9600);
break;
case 19200:
printf("baude = 19200.\n");
cfsetispeed(&options,B19200);
cfsetospeed(&options,B19200);
break;
case 38400:
cfsetispeed(&options,B38400);
cfsetospeed(&options,B38400);
break;
case UART_BAUDE_57600:
cfsetispeed(&options,B57600);
cfsetospeed(&options,B57600);
break;
default:
fprintf(stderr,"Unkown baude!\n");
return -1;
}
#if 0
/*设置控制模式*/
options.c_cflag |= CLOCAL;//保证程序不占用串口
options.c_cflag |= CREAD;//保证程序可以从串口中读取数据
/*设置数据流控制*/
switch(c_flow)
{
case 0://不进行流控制
options.c_cflag &= ~CRTSCTS;
break;
case 1://进行硬件流控制
options.c_cflag |= CRTSCTS;
break;
case 2://进行软件流控制
options.c_cflag |= IXON|IXOFF|IXANY;
break;
default:
fprintf(stderr,"Unkown c_flow!\n");
return -1;
}
#endif
/*设置数据位*/
switch(bits)
{
case 5:
options.c_cflag &= ~CSIZE;//屏蔽其它标志位
options.c_cflag |= CS5;
break;
case 6:
options.c_cflag &= ~CSIZE;//屏蔽其它标志位
options.c_cflag |= CS6;
break;
case 7:
options.c_cflag &= ~CSIZE;//屏蔽其它标志位
options.c_cflag |= CS7;
break;
case 8:
printf("bits = 8.\n");
options.c_cflag &= ~CSIZE;//屏蔽其它标志位
options.c_cflag |= CS8;
break;
default:
fprintf(stderr,"Unkown bits!\n");
return -1;
}
/*设置校验位*/
switch(parity)
{
/*无奇偶校验位*/
case 'n':
case 'N':
printf("parity = n.\n");
options.c_cflag &= ~PARENB;//PARENB:产生奇偶位,执行奇偶校验
options.c_cflag &= ~INPCK;//INPCK:使奇偶校验起作用
break;
/*设为空格,即停止位为2位*/
case 's':
case 'S':
options.c_cflag &= ~PARENB;//PARENB:产生奇偶位,执行奇偶校验
options.c_cflag &= ~CSTOPB;//CSTOPB:使用两位停止位
break;
/*设置奇校验*/
case 'o':
case 'O':
options.c_cflag |= PARENB;//PARENB:产生奇偶位,执行奇偶校验
options.c_cflag |= PARODD;//PARODD:若设置则为奇校验,否则为偶校验
options.c_cflag |= INPCK;//INPCK:使奇偶校验起作用
options.c_cflag |= ISTRIP;//ISTRIP:若设置则有效输入数字被剥离7个字节,否则保留全部8位
break;
/*设置偶校验*/
case 'e':
case 'E':
options.c_cflag |= PARENB;//PARENB:产生奇偶位,执行奇偶校验
options.c_cflag &= ~PARODD;//PARODD:若设置则为奇校验,否则为偶校验
options.c_cflag |= INPCK;//INPCK:使奇偶校验起作用
options.c_cflag |= ISTRIP;//ISTRIP:若设置则有效输入数字被剥离7个字节,否则保留全部8位
break;
default:
fprintf(stderr,"Unkown parity!\n");
return -1;
}
/*设置停止位*/
switch(stop)
{
case 1:
printf("stop = 1\n");
options.c_cflag &= ~CSTOPB;//CSTOPB:使用两位停止位
break;
case 2:
options.c_cflag |= CSTOPB;//CSTOPB:使用两位停止位
break;
default:
fprintf(stderr,"Unkown stop!\n");
return -1;
}
/*设置输出模式为原始输出*/
options.c_oflag &= ~OPOST;//OPOST:若设置则按定义的输出处理,否则所有c_oflag失效
/*设置本地模式为原始模式*/
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
/*
*ICANON:允许规范模式进行输入处理
*ECHO:允许输入字符的本地回显
*ECHOE:在接收EPASE时执行Backspace,Space,Backspace组合
*ISIG:允许信号
*/
/*设置等待时间和最小接受字符*/
options.c_cc[VTIME] = 0;//可以在select中设置
options.c_cc[VMIN] = 1;//最少读取一个字符
/*如果发生数据溢出,只接受数据,但是不进行读操作*/
tcflush(pgsd->fInfo.fd,TCIFLUSH);
/*激活配置*/
if(tcsetattr(pgsd->fInfo.fd,TCSANOW,&options) < 0)
{
perror("tcsetattr failed");
return -1;
}
return 0;
}
int uart_read(void *args, char *r_buf,size_t len)
{
ssize_t cnt = 0;
fd_set rfds;
struct timeval time;
gSealData *pgsd = (pgSealData)args;
if (NULL == pgsd)
{
printf("In \"uart_read\" parameter is NULL.\n");
return -1;
}
/*将文件描述符加入读描述符集合*/
FD_ZERO(&rfds);
FD_SET(pgsd->fInfo.fd,&rfds);
/*设置超时为15s*/
time.tv_sec = 15;
time.tv_usec = 0;
/*实现串口的多路I/O*/
ret = select(pgsd->fInfo.fd+1,&rfds,NULL,NULL,&time);
switch(ret)
{
case -1:
fprintf(stderr,"select error!\n");
return -1;
case 0:
fprintf(stderr,"time over!\n");
return -1;
default:
cnt = safe_read(pgsd->fInfo.fd,r_buf,len);
if(cnt == -1)
{
fprintf(stderr,"read error!\n");
return -1;
}
return cnt;
}
}
int uart_write(void *args, const unsigned char *w_buf,size_t len)
{
ssize_t cnt = 0;
gSealData *pgsd = (pgSealData)args;
if (NULL == pgsd)
{
printf("In \"uart_write\" parameter is NULL.\n");
return -1;
}
zlog_info(pgsd->zc, "uart_buf len = [%d]\n", len);
int i = 0;
for(i = 0; i < len; i++)
{
printf("w_buf[%d] = 0x%02x\n", i, w_buf[i]);
}
cnt = safe_write(pgsd->fInfo.fd,w_buf,len);
if(cnt == -1)
{
zlog_error(pgsd->zc, "safe_write failed.\n");
return -1;
}
return cnt;
}
int uart_init(void *args)
{
int ret = -1;
const char *w_buf = "something to write";
size_t w_len = sizeof(w_buf);
char r_buf[1024];
bzero(r_buf,1024);
gSealData *pgsd = (pgSealData)args;
if (NULL == pgsd)
{
printf("In \"uart_init function\" parameter is NULL.\n");
return -1;
}
ret = uart_open(pgsd, FINGER_UART2_DEV_NAME);/*串口号/dev/ttySn,USB口号/dev/ttyUSBn*/
if(-1 == ret)
{
zlog_error(pgsd->zc, "uart_open error.\n");
return -2;
}
if(uart_set(pgsd) == -1)
{
fprintf(stderr,"uart set failed!\n");
return -2;
}
return 0;
}
int uart_close(void *args)
{
int ret = -1;
gSealData *pgsd = (pgSealData)args;
if (NULL == pgsd)
{
printf("In \"uart_close function\" parameter is NULL.\n");
return -1;
}
close(pgsd->fInfo.fd);
pgsd->fInfo.fd = UART2_FD_INITIALIZATION;
return 0;
}
离线
公司没有。
离线
我也碰到这种情况,串口数据乱码,抓波形也没用。
离线
如何更改Uart1的波特率? 在keil中是否有数据和收发中断的示例?
离线
我正在使用互联网翻译将其翻译成中文,所以这些单词可能无法完全理解
离线
哈哈,只有我偷懒,为了访问串口,直接用Qt,库中的QSerialPort比上面的代码感觉好懂多了。
离线
串口本身比较简单,看到晕哥写这么细致,不错学习。
离线
串口乱码,首先发送接收的波特率需要一致,
还有一个关键点是,发送接收需要共地
离线