请教使用SELECT函数如何监测串口 fcntl select发送数据

下面是一个简单的读取串口数据的例子,使用了上面定义的一些函数和头文件
/**********************************************************************
&*&代码说明:使用串口二测试的,发送的数据是字符,但是没有发送字符串结束符号,
&*&所以接收到后,后面加上了结束符号。我测试使用的是单片机发送数据到第二个串口,测试通过。
&**********************************************************************/
#define&FALSE& -1
#define&TRUE &&0
/*********************************************************************/
int&OpenDev(char&*Dev)
&&&&//Dev&就是设备,设备就是文件,就是给出该设备文件的路径
&&&&int&fd =&open(Dev, O_RDWR );&//| O_NOCTTY | O_NDELAY
&&&&if&(-1 == fd)
&&&&&&&perror("Can't&Open&Serial&Port");
&&&&&&&return&-1;
&&&&&&&return&
int&main(int&argc,&char&**argv)
&&&&char&buff[512];
&&&&char&*dev =&"/dev/ttyS1";&//串口二
&&& fd = OpenDev(dev);
&&& set_speed(fd, 19200);
&&&&if&(set_Parity(fd, 8, 1,&'N') == FALSE)
&&&&&&&printf("Set Parity Error\n");
&&&&&&&exit&(0);
&&&&while&(1)&//循环读取数据
&&&&&&&while&((nread =&read(fd, buff, 512))&0)
&&&&&&&&&&&printf("\nLen %d\n", nread);
&&&&&&&&&& buff[nread+1] =&'\0';
&&&&&&&&&&&printf("\n%s", buff);
&&&&//close(fd);&
&&&&// exit (0);
1、虚拟机下使用串口的方法&&&&&&使用vmwave,默认串口设备是没有添加的,通过vmwave将设备加入即可正常使用串口。虚拟机串口打开后,可能会占用windows下的串口。另外,虚拟机的串口收发比正常的速度的确要慢许多。
2、消除Linux串口收发的一些规则
Linux&串口收发有许多模式,如:
(1)&接收返回模式:&如果串口没有接收到数据,read()函数不返回。
(2)&数据接收\n才返回接收的数据,否则read()函数返回0
(3)&特殊字符解析问题,部分特殊字符接收/发送时,会被屏蔽或者转义。如发送0x0A&接收变为0x0A&0x0A&,0x0D被屏蔽等。
(4)&接收反馈:如串口接收到数据,立即将该数据发送出去。
(上面是我遇到的一些问题,可能表述不很清楚,呵呵。如果用于收发txt文件,一般不大注意。)
3、解决问题的方法是,消除这些默认规则,关键是struct termios&的参数影响。
struct&termios& {
&&&&&& tcflag_t&c_&&&&&&&&&&&&&&&/**//*&输入模式旗标&*/
&&&&&&& tcflag_t&c_&&&&&&&&&&&&&&&/**//*&输出模式旗标&*/
&&&&&&& tcflag_t&c_&&&&&&&&&&&&&&&/**//*&控制模式旗标&*/
&&&&&&& tcflag_t&c_&&&&&&&&&&&&&&&/**//*&区域模式旗标&*/
&&&&&&& cc_t&c_&&&&&&&&&&&&&&&&&&&&/**//*&行控制&(line discipline) */
&&&&&&& cc_t&c_cc[NCCS];&&&&&&&&&&&/**//*&控制特性&*/
由于研究不深,如果要消除所有上面的规则,我是如下处理的
&串口打开方式:
&&open ("dev/ttyS0"&, O_RDWR|O_NOCTTY| O_NDELAY );
&消除收发模式规则:
options.c_lflag&&&&&&& = 0;
options.c_oflag&&&&&&& = 0;
options.c_iflag&&&&&&& = 0;
消除字符屏蔽规则:
options.c_cc[VINTR]&&& = 0;&&&&&&&/**//* Ctrl-c */
options.c_cc[VQUIT]&&&& = 0;&&&/**//* Ctrl- */
options.c_cc[VERASE]&&& = 0;&&&/**//* del */
options.c_cc[VKILL]&&& = 0;&&&/**//* @ */
options.c_cc[VEOF]&&&& = 0;&&&/**//* Ctrl-d */
options.c_cc[VTIME]&&& = 1;&&&/**//*& */
options.c_cc[VMIN]&&&& = 0;&&&/**//*& */
options.c_cc[VSWTC]&&& = 0;&&&/**//* '' */
options.c_cc[VSTART]&& = 0;&&&/**//* Ctrl-q */
options.c_cc[VSTOP]&&& = 0;&&&/**//* Ctrl-s */
options.c_cc[VSUSP]&&& = 0;&&&/**//* Ctrl-z */
options.c_cc[VEOL]&&&& = 0;&&&/**//* '' */
options.c_cc[VREPRINT] = 0;&&&/**//* Ctrl-r */
options.c_cc[VDISCARD] = 0;&&&/**//* Ctrl-u */
options.c_cc[VWERASE]& = 0;&&&/**//* Ctrl-w */
options.c_cc[VLNEXT]&& = 0;&&&/**//* Ctrl-v */
options.c_cc[VEOL2]&&& = 0;&&&/**//* '' */
以上设置,在其它参数串口设置前执行,如果你需要保留部分参数,请参阅http://blog.chinaunix.net/article.php?articleId=15964&blogId=60在RedHat Feroda 4&下编译通过
= = = = = = = = = = =&非阻塞read= = = = = = = = = = =
Q:在调用串口read(fd, & buff, & len);时,如果串口没有数据,会停在read处,请问有没有办法让这个read动作中止?
A:使用非阻塞方式select函数(I/O多工机制)或者open的时候加O_NONBLOCK参数。
int&select(int&n,fd_set * readfds,fd_set *&writefds,fd_set * exceptfds,struct&timeval * timeout);关于这个函数的使用我会在下篇blog中整理。
= = = = = = = = = = =&串口收发源码= = = = = = = = = = =
&&&&&&&一下代码已经经过我测试,没有问题。开发环境Redhat9,运行环境s3c2410
= = = = = = receive.c= = = = = =
#include&&&&stdio.h&&&&&&
#include&&&&stdlib.h&&&&
#include&&&&unistd.h&&&& &
#include&&&&sys/types.h&&
#include&&&&sys/stat.h&&&
#include&&&&fcntl.h&&&&&
#include&&&&termios.h&&&
#include&&&&errno.h&&&&&
#include&&&&string.h&
#define&TRUE 1
//初始化串口选项:&&
void&setTermios(struct&termios * pNewtio,&int&uBaudRate)
&&& bzero(pNewtio,&sizeof(struct&termios));&/* clear struct for new port settings */
&&& pNewtio-&c_cflag = uBaudRate | CS8 | CREAD | CLOCAL;
&&& pNewtio-&c_iflag = IGNPAR;
&&& pNewtio-&c_oflag = 0;
&&&&pNewtio-&c_lflag = 0;&//non ICANON
&&& &initialize all control characters
&&& &default values can be found in /usr/include/termios.h, and
&&& &are given in the comments, but we don't need them here
&&& pNewtio-&c_cc[VINTR] = 0;&/* Ctrl-c */
&&& pNewtio-&c_cc[VQUIT] = 0;&/* Ctrl-\ */
&&&&pNewtio-&c_cc[VERASE] = 0;&/* del */
&&& pNewtio-&c_cc[VKILL] = 0;&/* @ */
&&& pNewtio-&c_cc[VEOF] = 4;&/* Ctrl-d */
&&&&pNewtio-&c_cc[VTIME] = 5;&/* inter-character timer, timeout VTIME*0.1 */
&&& pNewtio-&c_cc[VMIN] = 0;&/* blocking read until VMIN character arrives */
&&& pNewtio-&c_cc[VSWTC] = 0;&/* '\0' */
&&& pNewtio-&c_cc[VSTART] = 0;&/* Ctrl-q */
&&& pNewtio-&c_cc[VSTOP] = 0;&/* Ctrl-s */
&&& pNewtio-&c_cc[VSUSP] = 0;&/* Ctrl-z */
&&&&pNewtio-&c_cc[VEOL] = 0;&/* '\0' */
&&&&pNewtio-&c_cc[VREPRINT] = 0;&/* Ctrl-r */
&&& pNewtio-&c_cc[VDISCARD] = 0;&/* Ctrl-u */
&&& pNewtio-&c_cc[VWERASE] = 0;&/* Ctrl-w */
&&&&pNewtio-&c_cc[VLNEXT] = 0;&/* Ctrl-v */
&&&&pNewtio-&c_cc[VEOL2] = 0;&/* '\0' */
#define&BUFSIZE 512
int&main(int&argc,&char&**argv)
&&&&char&buff[BUFSIZE];
&&&&struct&termios oldtio,
&&&&struct&
&&&&char&*dev ="/dev/ttyS1";
&&&&if&((fd =&open(dev, O_RDWR | O_NOCTTY))&0)
&&&&&&&printf("err: can't open serial port!\n");
&&&&&&&return&-1;
&&& tcgetattr(fd, &oldtio);&/* save current serial port settings */
&&& setTermios(&newtio, B115200);
&&& tcflush(fd, TCIFLUSH);
&&& tcsetattr(fd, TCSANOW, &newtio);
&&& tv.tv_sec=30;
&&& tv.tv_usec=0;
&&&&while&(TRUE)
&&&&&&&printf("wait...\n");
&&&&&& FD_ZERO(&rfds);
&&&&&& FD_SET(fd, &rfds);
&&&&&&&if&(select(1+fd, &rfds, NULL, NULL, &tv)&0)
&&&&&&&&&&&if&(FD_ISSET(fd, &rfds))
&&&&&&&&&& {
&&&&&&&&&&&&& nread=read(fd, buff, BUFSIZE);
&&&&&&&&&&&&&&printf("readlength=%d\n", nread);
&&&&&&&&&&&&& buff[nread]='\0';
&&&&&&&&&&&&&&printf("%s\n", buff);
&&&&&&&&&& }
&&& tcsetattr(fd, TCSANOW, &oldtio);
&&&&close(fd);
= = = = = send.c= = = = = =
#include&&&&stdio.h&&&&&&
#include&&&&stdlib.h&&&&
#include&&&&unistd.h&&&& &
#include&&&&sys/types.h&&
#include&&&&sys/stat.h&&&
#include&&&&fcntl.h&&&&&
#include&&&&termios.h&&&
#include&&&&errno.h&&&&&
#include&&&&string.h&
//初始化串口选项:&&
void&setTermios(struct&termios * pNewtio,&int&uBaudRate)
&&& bzero(pNewtio,&sizeof(struct&termios));&/* clear struct for new port settings */
&&& pNewtio-&c_cflag = uBaudRate | CS8 | CREAD | CLOCAL;
&&& pNewtio-&c_iflag = IGNPAR;
&&& pNewtio-&c_oflag = 0;
&&&&pNewtio-&c_lflag = 0;&//non ICANON
&&& &initialize all control characters
&&& &default values can be found in /usr/include/termios.h, and
&&& &are given in the comments, but we don't need them here
&&& pNewtio-&c_cc[VINTR] = 0;&/* Ctrl-c */
&&& pNewtio-&c_cc[VQUIT] = 0;&/* Ctrl-\ */
&&&&pNewtio-&c_cc[VERASE] = 0;&/* del */
&&& pNewtio-&c_cc[VKILL] = 0;&/* @ */
&&& pNewtio-&c_cc[VEOF] = 4;&/* Ctrl-d */
&&&&pNewtio-&c_cc[VTIME] = 5;&/* inter-character timer, timeout VTIME*0.1 */
&&& pNewtio-&c_cc[VMIN] = 0;&/* blocking read until VMIN character arrives */
&&& pNewtio-&c_cc[VSWTC] = 0;&/* '\0' */
&&& pNewtio-&c_cc[VSTART] = 0;&/* Ctrl-q */
&&& pNewtio-&c_cc[VSTOP] = 0;&/* Ctrl-s */
&&& pNewtio-&c_cc[VSUSP] = 0;&/* Ctrl-z */
&&&&pNewtio-&c_cc[VEOL] = 0;&/* '\0' */
&&&&pNewtio-&c_cc[VREPRINT] = 0;&/* Ctrl-r */
&&& pNewtio-&c_cc[VDISCARD] = 0;&/* Ctrl-u */
&&& pNewtio-&c_cc[VWERASE] = 0;&/* Ctrl-w */
&&&&pNewtio-&c_cc[VLNEXT] = 0;&/* Ctrl-v */
&&&&pNewtio-&c_cc[VEOL2] = 0;&/* '\0' */
int&main(int&argc,&char&**argv)
&&&&int&nCount, nTotal,
&&&&struct&termios oldtio,
&&&&char&*dev ="/dev/ttyS1";
&&&&if&((argc!=3) || (sscanf(argv[1],&"%d", &nTotal) != 1))
&&&&&&&printf("err: need tow arg!\n");
&&&&&&&return&-1;
&&&&if&((fd =&open(dev, O_RDWR | O_NOCTTY))&0)
&&&&&&&printf("err: can't open serial port!\n");
&&&&&&&return&-1;
&&& tcgetattr(fd, &oldtio);&/* save current serial port settings */
&&& setTermios(&newtio, B115200);
&&& tcflush(fd, TCIFLUSH);
&&& tcsetattr(fd, TCSANOW, &newtio);
&&&&for&(i=0; i&nT i++)
&&&&&& nCount=write(fd, argv[2],&strlen(argv[2]));
&&&&&&&printf("send data\n");
&&&&&& sleep(1);
&&& tcsetattr(fd, TCSANOW, &oldtio);
&&&&close(fd);
&&&&return&0;
= = = = = =.makefile= = = = = =
CC = /usr/local/arm/2.95.3/bin/arm-linux-gcc
all:receive send
receive: receive.c
&&&&$(CC)&receive.c -o& receive
send: send.c
&&&&$(CC)&send.c -o& send
&&& -rm -rf testCOM receive send
到此基本就结束了,可能代码注释比较少些,写的太着急了,等有时间整理一下。最好再看看上一篇blog这样能更好的理解串口。
阅读(...) 评论()君,已阅读到文档的结尾了呢~~
串口数据处理实例串口,数据,处理,串口数据,数据处理,串口 数据,串口数据线
扫扫二维码,随身浏览文档
手机或平板扫扫即可继续访问
串口数据处理实例
举报该文档为侵权文档。
举报该文档含有违规或不良信息。
反馈该文档无法正常浏览。
举报该文档为重复文档。
推荐理由:
将文档分享至:
分享完整地址
文档地址:
粘贴到BBS或博客
flash地址:
支持嵌入FLASH地址的网站使用
html代码:
&embed src='/DocinViewer-4.swf' width='100%' height='600' type=application/x-shockwave-flash ALLOWFULLSCREEN='true' ALLOWSCRIPTACCESS='always'&&/embed&
450px*300px480px*400px650px*490px
支持嵌入HTML代码的网站使用
您的内容已经提交成功
您所提交的内容需要审核后才能发布,请您等待!
3秒自动关闭窗口java 如何向串口发送指令_百度知道注释:这段串口是自己学习特权老师后的一个总结,由于特权的视频很短(视频和具体代码可到网站上下载),讲得也不是很详细,自己学习后就整理总结了哈,并把代码中自己的一些理解写了出来,希望能够帮助初学者的学习,由于自己也才是初学,希望大家给予更多的建议。
串口的学习
相关理论:
串口通信是目前比较重要的一种通信方式,主要是用于计算机和外部的通信。首先简单的介绍一下串口通信的原理:
串口用于ASCII码字符的传输。通信使用3根线完成:(1)地线,(2)发送,(3)接收。由于串口通信是异步的,端口能够在一根线上发送数据同时在另一根线上接收数据。其他线用于握手,但不是必须的。串口通信最重要的参数是波特率、数据位、停止位和奇偶校验。对于两个进行通行的端口,这些参数必须匹配: a,波特率:这是一个衡量通信速度的参数。它表示每秒钟传送的bit的个数。例如300波特表示每秒钟发送300个bit。当我们提到时钟周期时,我们就是指波特率例如如果协议需要4800波特率,那么时钟是4800Hz。这意味着串口通信在数据线上的采样率为4800Hz。通常电话线的波特率为1和36600。波特率可以远远大于这些值,但是波特率和距离成反比。高波特率常常用于放置的很近的仪器间的通信,典型的例子就是GPIB设备的通信。 b,数据位:这是衡量通信中实际数据位的参数。当计算机发送一个信息包,实际的数据不会是8位的,标准的值是5、7和8位。如何设置取决于你想传送的信息。比如,标准的ASCII码是0~127(7位)。扩展的ASCII码是0~255(8位)。如果数据使用简单的文本(标准 ASCII码),那么每个数据包使用7位数据。每个包是指一个字节,包括开始/停止位,数据位和奇偶校验位。由于实际数据位取决于通信协议的选取,术语&包&指任何通信的情况。 c,停止位:用于表示单个包的最后一位。典型的值为1,1.5和2位。由于数据是在传输线上定时的,并且每一个设备有其自己的时钟,很可能在通信中两台设备间出现了小小的不同步。因此停止位不仅仅是表示传输的结束,并且提供计算机校正时钟同步的机会。适用于停止位的位数越多,不同时钟同步的容忍程度越大,但是数据传输率同时也越慢。 d,奇偶校验位:在串口通信中一种简单的检错方式。有四种检错方式:偶、奇、高和低。当然没有校验位也是可以的。对于偶和奇校验的情况,串口会设置校验位(数据位后面的一位),用一个值确保传输的数据有偶个或者奇个逻辑高位。例如,如果数据是011,那么对于偶校验,校验位为0,保证逻辑高的位数是偶数个。如果是奇校验,校验位位1,这样就有3个逻辑高位。高位和低位不真正的检查数据,简单置位逻辑高或者逻辑低校验。这样使得接收设备能够知道一个位的状态,有机会判断是否有噪声干扰了通信或者是否传输和接收数据是否不同步
对于CPLD/FPGA设计者而言,只需要关心与其接口的RS232_TX 和RS232_RX两个信号,RS232_TX是数据发送端,RS232_RX是数据接收端口(接收PC机发过来的信息),串口通信的数据传输时序如图:奇偶校验位是根据前面8个数据的1的个数判断,对于奇校验,如果前面有奇数个1,相应的校验位为0.
该实验实现的功能是CPLD实时监测RS232_RX信号是否有数据。若接收到数据,则把接收到的数据通过RS232_TX发回给对方。上位机用的是串口调试助手。在代码设计中,发送数据的波特率是可选择的,这部分在模块speed_select里,可以根据需要进行配置。发送的数据帧格式为:1bit起始位(保持一个传输位周期的低电平),8bit数据,无校验位。
该设计分为四个模块,4个模块的划分主要是依据数据流的方向。my_uart_rx模块完成数据的接收,speed_select(speed_rx)模块主要是响应my_uart_rx模块发出的使能信号进行波特率计数,并且送回一个数据采样使能信号。my_uart_tx模块在my_uart_rx模块接收好一个完整的数据帧启动,将接收到的数据返回给对方,他的波特率控制是由speed_select(speed_tx)模块产生。
逻辑电路图:
设计整体说明:
该设计分为三个字模块和一个顶层模块,子模块包括波特率模块、接收模块和发送模块,波特率模块的作用是控制数据的传输速度,当接收模块发现串口的接收端检测到数据的时候,就发送一个信号告诉波特率模块有数据了,这时波特率模块就开始工作,进行采样,每次采样到它规定速率的一半的时候就告诉接收模块开始进行数据的接收,一旦接收完一位,接收模块又会停止工作,直到波特率模块计数到下一个位的一半的时候,又告诉接收模块开始接收,直到接收完为止,这样就起到了速度的控制。而发送模块受到波特率模块和接收模块共同的控制,只有它们两个告诉发送模块工作时,发送模块才能工作。
接收模块,该模块可以分为三步走:
检测到数据,立刻给波特率发送信号,让波特率模块和发送模块开始开始工作。
收到波特率模块的信号后,一位一位的接收数据。
接收完数据后,停止接收,并且让波特率模块停止工作。
发送模块,该模块课分为两步走:
接收到波特率模块和发送模块的有效信号后开始工作。
发送完数据后,告诉波特率模块,让其停止工作。
部分代码分析:
1.&&&&& 边沿检测法:
检测下降沿:
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
&&&&&&&&&&&&&& rx_int0 &= 1'b0;
&&&&&&&&&&&&&& rx_int1 &= 1'b0;
&&&&&&&&&&&&&& rx_int2 &= 1'b0;
&&&&&&& end
else begin
&&&&&&&&&&&&&& rx_int0 &= rx_
&&&&&&&&&&&&&& rx_int1 &= rx_int0;
&&&&&&&&&&&&&& rx_int2 &= rx_int1;
&&&&&&& end
assign neg_rx_int =& ~rx_int1 & rx_int2;//捕捉到下降沿后,neg_rx_int拉高保持一个主时钟周期&
如图,经过1,、2、3三个时钟后,rx_int2变为高电平,而此时经过2、3两个时钟后,rx_int1变为低电平,这时neg_rx_int获得一个脉冲的高电平,为什么只有一个高脉冲的值,因为rx_int2获得的值是rx_int1上一个时钟的值,当rx_int由高变为低的时候,rx_int1先得到低电平,而此时rx_int2还是rx_int1上一个时钟的值高电平,neg_rx_int为高,而等到下一个时钟到来时,rx_int2变低电平,neg_rx_in也跟着变低了,所以只有一个时钟的高脉冲。
其作用:获得一个稳定的有效该电平
检测上升沿:
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
&&&&&&&&&&&&&& rx_int0 &= 1'b0;
&&&&&&&&&&&&&& rx_int1 &= 1'b0;
&&&&&&&&&&&&&& rx_int2 &= 1'b0;
&&&&&&& end
else begin
&&&&&&&&&&&&&& rx_int0 &= rx_
&&&&&&&&&&&&&& rx_int1 &= rx_int0;
&&&&&&&&&&&&&& rx_int2 &= rx_int1;
&&&&&&& end
assign neg_rx_int =& rx_int1 & ~rx_int2;//捕捉到上升沿后,neg_rx_int拉高保持一个主时钟周期。
说白了,边沿检测法就是获得一个时钟的高脉冲。
&2.&&&&& neg_rx_int在代码中起的作用
&&&&&& else if(neg_rx_int) begin& &&//接收数据完毕,准备把接收到的数据发回去
&&&&&&&&&&&&&&&&&&&& bps_start_r &= 1'b1;
&&&&&&&&&&&&&&&&&&&& tx_data &= rx_&& //把接收到的数据存入发送数据寄存器
&&&&&&&&&&&&&&&&&&&& tx_en &= 1'b1;&&&&& &&& //进入发送数据状态中
&&&&&&&&&&&&& end
在接收到上一个模块的有效命令后,就将输入的数据保存,并由tx_en代替了neg_rx_int,因为neg_rx_int只有一个高脉冲,所以为了让其在我们想要的时间内控制后面数据的发送,让tx_en在这段时间内一直有效;并行让neg_rx_int只有一个高电平,防止上一个模块来干扰。数据的发送,按照串口数据发送的协议来写。
reg rs232_tx_r;
always @ (posedge clk or negedge rst_n) begin
&&&&& if(!rst_n) begin
&&&&&&&&&&&&&&&&&&& num &= 4'd0;
&&&&&&&&&&&&&&&&&&& rs232_tx_r &= 1'b1;//未发送前,串口总线保持高
&&&&&&&&&&&& end
&&&&& else if(tx_en) begin
&&&&&&&&&&&&&&&&&&& if(clk_bps)begin
&&&&&&&&&&&&&&&&&&&&&&&&&& num &= num+1'b1;
&&&&&&&&&&&&&&&&&&&&&&&&&& case (num)
&&&&&&&&&&&&&&&&&&&&&&&&&& 4'd0: rs232_tx_r &= 1'b0; &&&&&& //发送起始位
&&&&&&&&&&&&&&&&&&&&&&&&&& 4'd1: rs232_tx_r &= tx_data[0];&&&&& //发送bit0
&&&&&&&&&&&&&&&&&&&&&&&&&& 4'd2: rs232_tx_r &= tx_data[1];&&&&& //发送bit1
&&&&&&&&&&&&&&&&&&&&&&&&&& 4'd3: rs232_tx_r &= tx_data[2];&&&&& //发送bit2
&&&&&&&&&&&&&&&&&&&&&&&&&& 4'd4: rs232_tx_r &= tx_data[3];&&&&& //发送bit3
&&&&&&&&&&&&&&&&&&&&&&&&&& 4'd5: rs232_tx_r &= tx_data[4];&&&&& //发送bit
&&&&&&&&&&&&&&&&&&&&&&&&&& 4'd6: rs232_tx_r &= tx_data[5];&&&&& //发送bit5
&&&&&&&&&&&&&&&&&&&&&&&&&& 4'd7: rs232_tx_r &= tx_data[6];&&&&& //发送bit6
&&&&&&&&&&&&&&&&&&&&&&&&&& 4'd8: rs232_tx_r &= tx_data[7];&&&&& //发送bit7
&&&&&&&&&&&&&&&&&&&&&&&&&& 4'd9: rs232_tx_r &= 1'b1;& //发送结束位
&&&&&&&&&&&&&&&&&&&&&&&&&& default: rs232_tx_r &= 1'b1;
&&&&&&&&&&&&&&&&&&&&&&&&&& endcase
&&&&&&&&&&&&&&&&&&&&&&&&&& end
&&&&&&&&&&&&&&&&&&& else if(num==4'd11) num &= 4'd0;//发送共11位
&&&&&&&&&&&& end
波特率模块:控制数据的传输速度
//-------------------控制计数多少,也就是传输速度-----------------------------------
always @ (posedge clk or negedge rst_n)
&&&&& if(!rst_n)
&&&&&&&&&&&&&&&&&&& cnt &= 13'd0;
&&&&& else if (cnt & `BPS_SPEED && bps_start)
&&&&&&&&&&&& cnt &= cnt +1'b1;//收到发送或者接收模块的bps_start命令开始计数
&&&&& else (!bps_start) cnt &= 13'd0;//收到停止命令计数结束,停止工作
//--------------记到一半,就告诉发送或者接收模块开始发送或者接收数据-----
always @ (posedge clk or negedge rst_n)
&&&&& if(!rst_n)
&&&&&&&&&&&& clk_bps_r &= 1'b0;
&&&&& else if(cnt == `BPS_SPEED_HALF)
&&&&&&&&&&&& clk_bps_r &= 1'b1;
&&&&& else clk_bps_r &= 1'b0;&&&&
assign clk_bps = clk_bps_r;
波特率计算方法:
bps9600 = 5207表示对于9600bit/s的速度在50MHZ的时钟下需要计数5027次,计算:1s=ns,则接收或者发送一位所需时间是/ns/位,50Mhz=20ns。则接收一位需要计数:N=(次)
//------------------------------------------------------------------------------------------------
接收模块:
1.&&&&& 边沿检测:
always @ (posedge clk or negedge rst_n) begin
&&&&& if(!rst_n) begin
&&&&&&&&&&&&&&&&&&& rs232_rx0 &= 1'b0;
&&&&&&&&&&&&&&&&&&& rs232_rx1 &= 1'b0;
&&&&&&&&&&&&&&&&&&& rs232_rx2 &= 1'b0;
&&&&&&&&&&&&&&&&&&& rs232_rx3 &= 1'b0;
&&&&&&&&&&&& end
&&&&& else begin
&&&&&&&&&&&&&&&&&&& rs232_rx0 &= rs232_
&&&&&&&&&&&&&&&&&&& rs232_rx1 &= rs232_rx0;
&&&&&&&&&&&&&&&&&&& rs232_rx2 &= rs232_rx1;
&&&&&&&&&&&&&&&&&&& rs232_rx3 &= rs232_rx2;
&&&&&&&&&&&& end
assign neg_rs232_rx = rs232_rx3 & rs232_rx2 & ~rs232_rx1 & ~rs232_rx0;
道理和开始的一样,但是这里检测更严格,高低电平都至少要保持2个时钟,目的是滤掉毛刺,获得更稳定的值。
2.&&&&&&& 数据接收:
这里比较特别的就是定义了两个寄存器来获取输入的值,rx_data_r和tx_temp_data,tx_temp_data的目的是为了一位一位的存取,存取完毕后再将值给rx_data_r,最后rx_data_r再把数据赋给输出端口。这样做也是为了能让输出直接获得最终的值,而不是接收一位变化一位。还有就是串口总线的第一位没接收,因为是起始位,我们需要的是八位数据,所以没接收。
//-----------------------------------------------------------------------------------------------
reg[7:0] rx_data_r;&&&&&&&&&& //串口接收数据寄存器,保存直至下一个数据来到
//----------------------------------------------------------------------------------------------
reg[7:0] rx_temp_&&& //当前接收数据寄存器
always @ (posedge clk or negedge rst_n)
&&&&& if(!rst_n) begin
&&&&&&&&&&&&&&&&&&& rx_temp_data &= 8'd0;
&&&&&&&&&&&&&&&&&&& num &= 4'd0;
&&&&&&&&&&&&&&&&&&& rx_data_r &= 8'd0;
&&&&&&&&&&&& end
&&&&& else if(rx_int) begin&&& //接收数据处理
&&&&&&&&&&&& if(clk_bps) begin //读取并保存数据,接收数据为一个起始位,8bit数据,1或2个结束位&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&& num &= num+1'b1;
&&&&&&&&&&&&&&&&&&&&&&&&&& case (num)
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 4'd1: rx_temp_data[0] &= rs232_&&&&& //锁存第0bit
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 4'd2: rx_temp_data[1] &= rs232_&&&&& //锁存第1bit
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 4'd3: rx_temp_data[2] &= rs232_&&&&& //锁存第2bit
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 4'd4: rx_temp_data[3] &= rs232_&&&&& //锁存第3bit
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 4'd5: rx_temp_data[4] &= rs232_&&&&& //锁存第4bit
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 4'd6: rx_temp_data[5] &= rs232_&&&&& //锁存第5bit
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 4'd7: rx_temp_data[6] &= rs232_&&&&& //锁存第6bit
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 4'd8: rx_temp_data[7] &= rs232_&&&&& //锁存第7bit
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& default: ;
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& endcase
&&&&&&&&&&&&&&&&&&& end
&&&&&&&&&&&& else if(num == 4'd12) begin&&&&&&&&&&& //我们的标准接收模式下只有1+8+1(2)=11bit的有效数据
&&&&&&&&&&&&&&&&&&&&&&&&&& num &= 4'd0;&&&&&&&&&&&&&&&&&&&& //接收到STOP位后结束,num清零
&&&&&&&&&&&&&&&&&&&&&&&&&& rx_data_r &= rx_temp_&&& //把数据锁存到数据寄存器rx_data中
&&&&&&&&&&&&&&&&&&& end
&&&&&&&&&&&& end
assign rx_data = rx_data_r;
阅读(...) 评论()

我要回帖

更多关于 串口select 的文章

 

随机推荐