串口号(共17篇)
第1篇:串口中断
串口中断.txt 您现在的位置: 中国IT实验室 >> 嵌入式开发 >> 单片机 >> 正文 AVR串口程序例子----中断模式 加入Intel嵌入式官方平台与工程师在线交流 谈谈嵌入式操作系统的调试问题
软件测试中的性能测试的容量评估 【安博亚威】CCIE考试通过率第一![OPENLAB]RHCE+架构师优惠2200元
数据库工程师 高级项目经理 界面设计经理 中国IT实验室收集整理 佚名 2008-6-25 14:29:08 保存本文 推荐给好友 收藏本页 欢迎进入IT技术社区论坛,与200万技术人员互动交流 >>进入
/* Code adapted from Atmel AVR Application Note AVR306 * Interrupt mode driver for UART.*/ #include #include #include "uart.h"
/* IMPORTANT: these vector numbers are for 8515!If you use other devices * you must change them to the different set of numbers.* * UART_RX_interrupt set to UART, Rx complete * UART_TX_interrupt set to UART Data Register Empty */
#pragma interrupt_handler UART_RX_interrupt:10 UART_TX_interrupt:11
/* UART Buffer Defines */ #define UART_RX_BUFFER_SIZE 128 /* 1,2,4,8,16,32,64,128 or 256 bytes */ #define UART_RX_BUFFER_MASK(UART_RX_BUFFER_SIZE1)
#if(UART_RX_BUFFER_SIZE & UART_RX_BUFFER_MASK)#error RX buffer size is not a power of 2 #endif
/* Static Variables */ static unsigned char UART_RxBuf[UART_RX_BUFFER_SIZE];static volatile unsigned char UART_RxHead;static volatile unsigned char UART_RxTail;static unsigned char UART_TxBuf[UART_TX_BUFFER_SIZE];static volatile unsigned char UART_TxHead;static volatile unsigned char UART_TxTail;
/* initialize UART */ void InitUART(unsigned char baudrate){ unsigned char x;UBRR = baudrate;/* set the baud rate */ /* enable UART receiver and transmitter, and receive interrupt */ UCR =((1
/* interrupt handlers */ void UART_RX_interrupt(void){ unsigned char data;unsigned char tmphead;data = UDR;/* read the received data */ /* calculate buffer index */ tmphead =(UART_RxHead + 1)& UART_RX_BUFFER_MASK;UART_RxHead = tmphead;/* store new index */ if(tmphead == UART_RxTail){ /* ERROR!Receive buffer overflow */ } UART_RxBuf[tmphead] = data;/* store received data in buffer */ }
void UART_TX_interrupt(void){ unsigned char tmptail;
/* check if all data is transmitted */ if(UART_TxHead!= UART_TxTail){ /* calculate buffer index */ tmptail =(UART_TxTail + 1)& UART_TX_BUFFER_MASK;UART_TxTail = tmptail;/* store new index */ UDR = UART_TxBuf[tmptail];/* start transmition */ } else { UCR &= ~(1
/* Read and write functions */ unsigned char ReceiveByte(void){ unsigned char tmptail;
while(UART_RxHead == UART_RxTail)/* wait for incomming data */;tmptail =(UART_RxTail + 1)& UART_RX_BUFFER_MASK;/* calculate buffer index */ UART_RxTail = tmptail;/* store new index */ return UART_RxBuf[tmptail];/* return data */ }
void TransmitByte(unsigned char data){ unsigned char tmphead;/* calculate buffer index */ tmphead =(UART_TxHead + 1)& UART_TX_BUFFER_MASK;/* wait for free space in buffer */
while(tmphead == UART_TxTail);UART_TxBuf[tmphead] = data;/* store data in buffer */ UART_TxHead = tmphead;/* store new index */ UCR |=(1
unsigned char DataInReceiveBuffer(void){ return(UART_RxHead!= UART_RxTail);/* return 0(FALSE)if the receive buffer is empty */ }
#ifdef TEST /* main-a simple test program*/ void main(void){ InitUART(25);/* set the baudrate to 9600 bps using a 4MHz crystal */ _SEI();/* enable interrupts => enable UART interrupts */ while(1)/* forever */ { TransmitByte(ReceiveByte());/* echo the received character */ } }
演讲稿
尊敬的老师们,同学们下午好:
我是来自10级经济学(2)班的学习委,我叫张盼盼,很荣幸有这次机会和大家一起交流担任学习委员这一职务的经验。
转眼间大学生活已经过了一年多,在这一年多的时间里,我一直担任着学习委员这一职务。回望这一年多,自己走过的路,留下的或深或浅的足迹,不仅充满了欢愉,也充满了淡淡的苦涩。一年多的工作,让我学到了很多很多,下面将自己的工作经验和大家一起分享。
学习委员是班上的一个重要职位,在我当初当上它的时候,我就在想一定不要辜负老师及同学们我的信任和支持,一定要把工作做好。要认真负责,态度踏实,要有一定的组织,领导,执行能力,并且做事情要公平,公正,公开,积极落实学校学院的具体工作。作为一名合格的学习委员,要收集学生对老师的意见和老师的教学动态。在很多情况下,老师无法和那么多学生直接打交道,很多老师也无暇顾及那么多的学生,特别是大家刚进入大学,很多人一时还不适应老师的教学模式。学习委员是老师与学生之间沟通的一个桥梁,学习委员要及时地向老师提出同学们的建议和疑问,熟悉老师对学生的基本要求。再次,学习委员在学习上要做好模范带头作用,要有优异的成绩,当同学们向我提出问题时,基本上给同学一个正确的回复。
总之,在一学年的工作之中,我懂得如何落实各项工作,如何和班委有效地分工合作,如何和同学沟通交流并且提高大家的学习积极性。当然,我的工作还存在着很多不足之处。比日:有的时候得不到同学们的响应,同学们不积极主动支持我的工作;在收集同学们对自己工作意见方面做得不够,有些事情做错了,没有周围同学的提醒,自己也没有发觉等等。最严重的一次是,我没有把英语四六级报名的时间,地点通知到位,导致我们班有4名同学错过报名的时间。这次事使我懂得了做事要脚踏实地,不能马虎。
在这次的交流会中,我希望大家可以从中吸取一些好的经验,带动本班级的学习风气,同时也相信大家在大学毕业后找到好的工作。谢谢大家!
第2篇:串口接收字符串
串口接收字符串.txt
//串口接收以特定字符为开头的字符串并且保存特定字符之后的有效位
#include #define uint unsigned char #define uchar unsigned int
uchar ser_receive;//串口接收到的数据 uchar ser_flag=0;
uchar receive_number[11]={0};//接收串口发送来的数据的数组 uchar i=0;uchar j;uchar come=0;void init_ser(){
TMOD=0X20;//定时器1工作在方式2 TH1=0XFD;TL1=0XFD;//波特率9600 TR1=1;EA=1;SM0=0;SM1=1;REN=1;//允许串口接收
ES=1;//开串口 中断
}
void delay(uint z){ uint x,y;for(x=z;x>0;x--)
for(y=110;y>0;y--);
} /**************************************************************************************** * 程序目的:串口接收字符串,但是要以字符a为开头的后面的11位字符,若开头不为a则接收不写入数组
*
若开头为a 但是发送有效位超过11位 就把后面的截断 只要前11位 * *补充:该程序也可以改为接受任意字符串(但是字符串的长度 必须是大体确定的)* * ****************************************************************************************/
void ser()interrupt 4 //中断函数不用声明 { if(RI==1){
RI=0;
ser_receive=SBUF;
if(come==1)
{
if(ser_receive!=' '&&ser_receive!='a')
{
receive_number[i]=ser_receive;
i++;
if(i==11)
{
i=0;
ser_flag=1;
come=0;
}
}
}
else if(ser_receive=='a')
{
come=1;
}
}
}
void main(){ init_ser();while(1){
if(ser_flag==1)
{
ES=0;
ser_flag=0;
for(j=0;j
{
SBUF=receive_number[j];
while(!TI);
TI=0;
delay(10);
}
ES=1;
} }
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////下面程序接收字符串(不用特定字符开头)//////////////////////////////////////////////////////////////////// ///////下面程序接收字符串(不用特定字符开头)////////////////////////////////////////////////////////////////////// //////下面程序接收字符串(不用特定字符开头)/////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include #define uint unsigned char #define uchar unsigned int
uchar ser_receive;//串口接收到的数据 uchar ser_flag=0;
uchar receive_number[12]={0};uchar i=0;uchar j;void init_ser(){
TMOD=0X20;//定时器1工作在方式2 TH1=0XFD;TL1=0XFD;//波特率9600 TR1=1;EA=1;SM0=0;SM1=1;REN=1;//允许串口接收 ES=1;//开串口 中断
}
void delay(uint z){ uint x,y;for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void ser()interrupt 4 //中断函数不用声明 { if(RI==1){
RI=0;
ser_receive=SBUF;
if(ser_receive!=' ')
{
receive_number[i]=ser_receive;
i++;
if(i==12)
{
i=0;
ser_flag=1;
}
}
}
}
void main(){ init_ser();while(1){
if(ser_flag==1)
{
ES=0;
ser_flag=0;
for(j=0;j
{
SBUF=receive_number[j];
while(!TI);
TI=0;
delay(10);
}
ES=1;
} }
}
演讲稿
尊敬的老师们,同学们下午好:
我是来自10级经济学(2)班的学习委,我叫张盼盼,很荣幸有这次机会和大家一起交流担任学习委员这一职务的经验。
转眼间大学生活已经过了一年多,在这一年多的时间里,我一直担任着学习委员这一职务。回望这一年多,自己走过的路,留下的或深或浅的足迹,不仅充满了欢愉,也充满了淡淡的苦涩。一年多的工作,让我学到了很多很多,下面将自己的工作经验和大家一起分享。
学习委员是班上的一个重要职位,在我当初当上它的时候,我就在想一定不要辜负老师及同学们我的信任和支持,一定要把工作做好。要认真负责,态度踏实,要有一定的组织,领导,执行能力,并且做事情要公平,公正,公开,积极落实学校学院的具体工作。作为一名合格的学习委员,要收集学生对老师的意见和老师的教学动态。在很多情况下,老师无法和那么多学生直接打交道,很多老师也无暇顾及那么多的学生,特别是大家刚进入大学,很多人一时还不适应老师的教学模式。学习委员是老师与学生之间沟通的一个桥梁,学习委员要及时地向老师提出同学们的建议和疑问,熟悉老师对学生的基本要求。再次,学习委员在学习上要做好模范带头作用,要有优异的成绩,当同学们向我提出问题时,基本上给同学一个正确的回复。
总之,在一学年的工作之中,我懂得如何落实各项工作,如何和班委有效地分工合作,如何和同学沟通交流并且提高大家的学习积极性。当然,我的工作还存在着很多不足之处。比日:有的时候得不到同学们的响应,同学们不积极主动支持我的工作;在收集同学们对自己工作意见方面做得不够,有些事情做错了,没有周围同学的提醒,自己也没有发觉等等。最严重的一次是,我没有把英语四六级报名的时间,地点通知到位,导致我们班有4名同学错过报名的时间。这次事使我懂得了做事要脚踏实地,不能马虎。
在这次的交流会中,我希望大家可以从中吸取一些好的经验,带动本班级的学习风气,同时也相信大家在大学毕业后找到好的工作。谢谢大家!
第3篇:单片机串口总结
51单片机串口总结
有句话说“尽信书不如无书”,要学好单片机就要不断的、大胆的实验,要多怀疑,即使我们的怀疑最终被证明是错误的那么这也是进步(人们认识事物很多情况下来源于怀疑),当怀疑出现时就要去实践。有很多东西如果不通过实践是不可能掌握其中隐藏的奥秘,就拿51单片机串口通讯这一块,我认为掌握很好了,可以很轻松的实现数据的接收、发送,但这段时间当我重新学习串口时,我才发现里面还有很多小细节从没注意,更别说研究了。对于接收发送程序永远是按照别人的模式来编写程序,并没有真真正正的挖掘深层次的内容。我身边太多的人在临摹别人的程序,当然我不反对,但是希望自己多问几个问什么,单纯的会编程是学不好单片机的,毕竟单片机有自己独特的硬件结构。
开讲之前先简要说一下同步、异步通信:
同步通信:发送方时钟对接收方时钟控制,使双方达到完全同步。
异步通信:发送与接受设备使用各自的时钟控制数据的发送和接受过程(虽然时钟不同,但一般相差不大)。
51单片机串行口结构
从上图中我们看到,51单片机有两个物理上独立的接收、发送缓冲器SBUF,它们共用同一个地址99H,但是请注意:接收缓冲器只能读而不能写,发送缓冲器只写不读。单片机可以同时实现数据的发送与接收功能。
特别注意:接收器是双缓冲结构:当前一个字节从接收缓冲区取走之前,就已经开始接收第二个字节(串行输入至移位寄存器),此时如果在第二个字节接收完毕而前一个字节还未被读走,那么就会丢失前一个字节。
51单片机串口控制寄存器
关于51单片机的控制寄存器各个位表示的含义在这里我只谈SM2。
SM2为多机控制位,主要用于工作方式2和3,当接收机的SM2=1时,可以利用接收到的RB8来控制是否激活RI(RB8=0不激活RI,收到的数据丢失;RB8=1时收到的数据进入SBUF,并激活RI ,进而在中断服务程序中将数据从SBUF中读走)。当SM2=0时,不论收到的RB8为何值都将使接收到的数据进入SBUF,并激活RI,通过控制SM2实现多机通信。
51单片机串口通讯方式
51串口通讯方式有3种,方式0、方式
1、方式2与方式3,他们的工作模式不尽相同。 首先他们的波特率很容易忽视。方式0与方式2的波特率固定,而方式1和3的波特率由T1的溢出率决定。
方式0的波特率=f/12
系统晶振的12分频,换句话说12M晶振的情况下,其波特率可达1M,速度是很高的(当我们在选用串行器件并采用方式0时需要特别注意器件所能允许的最大时钟频率)。
方式2 =f/64或f/32(当SMOD=1时为f/32,SMOD=0时为f/64)。
曾经我用方式2进行MODBUS通信时,总是通讯失败,我仔细检查程序,没有发现逻辑错误,特别是当我参考别人的程序时,发现很少有人用方式2进行MODBUS通讯,所以当时自己妄下结论51单片机的串行方式2不可用,直到有一天夜里我突然想起方式2的波特率是固定的,试想晶振11.0592M/32或11.0592M/64怎么也不可能是9600啊,怎么可能通信成功。这才恍然大悟,看来还是自己太武断了,没有认真看书啊。有时我们认为我们犯这样的错误很低级,其实我们很多次都是因为这样的小细节导致我们整个系统不正常,正所谓“千里之堤毁于蚁穴”,这些细节真的伤不起啊。
方式
1、3波特率=(2smod/32)*T1的溢出率,其中TI的溢出率=f/{12*[256-(TH1)]}.关于3种通讯方式其中有几点特别容易出错:
1、无论采用哪种通讯方式,数据发送和接受都是低位在先,高位在后。
2、3种方式作为输出,由于输出是CPU主动发送,不会产生重叠错误,当数据写入SBUF后,发送便启动(通过单片机内部逻辑控制,与程序无关),当该字节发送结束(SBUF空),置TI。不要理解为当数据一写入SBUF就置位TI,如果中断允许则在中断中发送数据,这就大错特错了。
3 同样作为输入,可能会产生重叠错误(主要依赖于特定的环境),当一个字节的数据接收完毕(SBUF满)置位RI,表示缓冲区有数据提示CPU读取。
接下来通过一些实验具体说明串口通信中需要注意的地方
1 方式0输出
方式0主要功能是作为移位寄存器,将数据从SBUF中逐位移出,最常见的用法就是外接串入并出的移位寄存器,如74LS164。之前在做这一部分实验时总是利用单片机I/O端口模拟实现,现在想想在串口未被占用的情况下,方式0是最好的实现方式。
利用串口方式0,向74LS164输出字符“0”的编码,程序如下:
该程序采用了中断方式实现,结果是通过74LS164使数码管显示“0”。实验结果如下:
这里我说明几点:
1 如果采用查询方式,并且只发送一遍,那么程序最后的while(1);不可以省略,否则会出现数码管闪烁的现象(在KEIL环境下,main()函数也是作为一个调用函数,最后也有返回RET,它不像C中的main()函数,当执行完毕后就停止,而是重新复位执行,如此反复,这一点要特别注意)
这是查询方式下不加while(1);的现实效果
2 如果采用中断方式发送,请记得中断中清除TI,仅仅是为了解除中断标志,而不是等待发送结束,因为此时数据早已离开了SBUF跑到外边去了。3 74LS164最高25MHZ,采用方式0,没有问题。
方式0作为输入模式
以74ls165(最高时钟25MHZ)为例,可以满足要求。
对应结果如下:
(注意:74ls165线传送高位,而串口通信低位在先,所以显示的数据和实际数据高低位正好相反
P1.7---P1.0对应D0---D7)。
本程序只接收一次,也许有人会问,中断程序中REN=0,表示什么意思?可不可以改成ES=0?
这个问题很好,首先REN=0表示接收禁止,即不允许串口接收数据;ES=0是禁止中断和单片机是否接收数据没有关系,不接收数据自然中断允许也是徒劳,这两者有很大的区别。我们在很多接收程序中经常可以看到在判断RI标志后紧跟着清除标志位,我想问一下,为什么?)
如果我们也按照这种模式改写会怎样呢?
实验结果如下
两次结果差异怎么这么大?为什么会这样子?
为了便于理解,也为了说明问题方便,对中断程序做了如下处理:
结果又变了
是不是感觉很奇怪,究竟咋回事呢?
首先中断程序中当判断RI置位标志后紧跟着清零是为了接收下一个字节的数据,也为了避免单片机重复中断。
当51单片机串口方式0作输入时,在REN=1且RI=0的条件下就启动了单片机串口接收过程。如果有一个条件不满足就不能启动接收过程,以上出现的错误正式由于忽略了这个重要的因素造成的。在RI清零后由于REN仍然为1,单片机已经开始接收第二字节的数据,由于串口速度很快,RI仍会置位,而紧接着将REN清零只能阻止单片机接收数据,但是却
不能阻挡第二次中断。由于只接收了部分外部引脚数据(此时外部引脚为高电平,即逻辑1,其实单片机只接收了一位,对于12M晶振而言,方式0大约8us接收一个字节数据)。相反在RI=0与REN=0之间加上适当的延迟,就可以保证一个字节的数据全部接收完毕,故此时我们读上来的一个字节为0xff。
我在中断程序中添加了一个中断计数器(不加延迟),发现中断服务程序的确执行了两次
结果如下
加上延迟结果
这就验证了刚才的结论。
至于说可不可以换做ES=0,回答是可以的,尽管同样可以实现数据的读取,但是实质不同,当禁止中断后,单片机仍在接收外部数据,只是不再请求中断,自然的不再读取第2、3。。。字节的数据,那么P1将保留第一次中断时从SBUF中读出的数据。如果某一时刻打开中断发现结果不正常,如果理解了上面的机制就不会觉得惊讶了。建议:单次接收时,中断服务程序中REN清零放在RI之前。
还有一个问题非常重要:
如果我在中断服务程序中不清除RI,会怎样?
很少有人会这样用,但是经常有人忘记了(包括我)。课本上写得很清楚,务必在中断中用软件清除RI,为什么要这样呢?难道仅仅是为了接收下一次数据并且避免单片机不断的响应中断?的确如此,如果对于一个小系统而言,不清除中断标志,那么单片机将不停的中断,影响接下来任务的执行,系统必然瘫痪,而且不能正常的接收数据。总结:方式0作为发送方,只要向SBUF中写入数据就启动了发送过程;
方式0在座位接收模式时,REN=
1、RI=0的情况下就已经启动了接收过程。在中断程序中要注意两者清零的顺序。
还有一种情况要特别注意:单片机复位时SCON自动清零,如果单片机不工作在方式0,那么如果采用位操作SCON时也要注意REN=1与SM0、SM1的书写顺序,总之切记方式0启动发送、接收数据的条件。
方式1 方式1为10位异步通信模式。作为输出和方式0没有本质的区别,不同的是数据帧的形式,但是对于接受模式则有点不同,当REN=1且RI=0时,单片机并不启动接收过程。而是以已选择波特率的16倍速率采样RXD引脚的电平,当检测到输入引脚发生1---0负跳变时,则说明起始位有效,才开始接受本帧数据。方式1模式下 单片机可以工作在全双工以及半双工方式。下面举两个例子
半双工
主机发送某一字符,从机接收到数据后返回数据加1的值 比如 主机发送“1“,从机收到后回复主机”2“。实验结果如下:
方式1工作方式主要注意: 1 波特率可变。
2 数据接收以起始位为标志,停止位结束。
3 当RI=0且SM2=0或接收到有效停止位时,单片机将接收到的数据移入SBUF中,两个条件缺一不可。
方式2和方式3 方式2和3不同的只是波特率,这里以方式3为例
作为输出模式同方式1没有区别,只是增加了第八位数据位,第八位数据可以用作校验位或在多机通信中用作数据/地址帧的判别位。
首先我们来做模拟主从奇偶校验模式
主机发送一帧数据,并发送奇偶校验位,从机接收数据后,判断数据是否正确,如果正
确,接收指示灯亮,并且回送主机数据加1,反之回送0;主机接收从机信息,如果校验正确点亮LED指示灯.(从机、主机接收数据无论校验正确与否,均显示接收到的字节数据)。奇校验模式 演示结果如下:
(注:从接接收不正确,返回0)
主从机接收正确效果
之前我们已经介绍了SM2的具体用法,主要用于多机通信,将SM2作为数据/地址帧的判别位,在接收地址时令SM2=1,当接收到的第八位数据为1时激活RI产生中断,然后比较地址,如果地址符合则清除SM2准备接受数据信息,反之不理睬。
特别注意 当RI=0且SM2=0(或SM2=1时接收到第9位数据为1)时,单片机将接收到的数据移入SBUF中,两个条件缺一不可。
在这里我只举一个简单的例子 一个主机,两个从机
1 起始时,主机从机的SM2均置位,所有的从机等待主机发送地址帧,主机令TB8=1,发送地址帧。
2 所用的从机将接受到的地址和自己的地址比较,如果符合,点亮LED指示灯,清除SM2(准备接受主机发送的数据帧),并将自己的地址发送到主机。
3 主机接收从机发送的地址信息,如果地址符合则数码管显示从机地址并开始准备发送数据,反之发复位信号,TB8=1。
4 从机接收数据先判断RB8,如果RB8=1,则复位,重新开始接收主机发送的地址帧,反之通过P1口外接数码管显示接收到的数据。实验结果如下:
注意:如果主机没有得到正确的地址,则将按照一定的速率发送地址帧,直到接收正确的地址为止,该试验主机向从机2发送信息。
另外在这里我补充两点:
1 我们可以很方便的利用串口通信的工作方式2或3实现奇偶校验,注意技巧,当为偶校验时TB8=P,奇校验时TB8=~P;
2当单片机利用中断发送大量数据时,尽量采用中断发送,因为单片机在写入SBUF数据后由硬件将数据发送完,在发送过程中,单片机还可以做很多事情,利用中断发送数据可以提高CPU利用率。尤其在低波特率时效果更明显。
第4篇:路由器高速串口配置
实验名称:两台路由器的互连
实验目的:掌握区分两台路由器互连,DCE,DTE短的选择判断 技术原理:
两台路由器的高速串口直连,可以不用直接铺设光前,用一端作为DCE,一端作为DTE,在DCE端要配置同步时钟频率,并用专用串口线连接 实现功能:
用高速串口线配置两台路由,实现互相通信 实验步骤提示: 在模拟器中画出实验拓扑图 实验步骤配置以下各项
1、进入serial 0/0/0接口,配置IP地址为172.16.2.1 配置时钟频率为64000HZ,带宽为512K,开启端口 Router(config)#int s0/0/0 Router(config-if)#ip add 172.16.2.1 255.255.0.0 Router(config-if)#clock r 64000 Router(config-if)#band 512 Router(config-if)#no sh %LINK-5-CHANGED: Interface Serial0/0/0, changed state to down
2、进入serial 0/0/1接口,配置IP地址为172.16.2.2 配置带宽为512K,开启端口
Router(config)#int s0/0/1 Router(config-if)#ip add 172.16.2.2 255.255.0.0 Router(config-if)#band 512 Router(config-if)#no sh %LINK-5-CHANGED: Interface Serial0/0/1, changed state to up Router(config-if)# %LINEPROTO-5-UPDOWN: Line protocol on Interface Serial0/0/1, changed state to up
3、查看两个高速串口的接口状态,IP状态
4、从一台路由器PING另一台的接口地址,验证是否正常通信
Router#ping 172.16.2.1 Type escape sequence to abort.Sending 5, 100-byte ICMP Echos to 172.16.2.1, timeout is 2seconds:
!!!Succe rate is 100 percent(5/5), round-trip min/avg/max = 31/31/32 ms 实验报告:提交.PKT文件(画拓扑图),用.TXT文件保存配置命令.
第5篇:串口通信实验报告
实验三
双机通信实验
一、实验目的UART 串行通信接口技术应用
二、实验实现的功能
用两片核心板之间实现串行通信,将按键信息互发到对方数码管显示。
三、系统硬件设计
(1)单片机的最小系统部分
(2)电源部分
(3)人机界面部分
数码管部分
按键部分
(4)串口通信部分
四、系统软件设计
#include #define uchar unsigned char #define uint unsigned int void send();uchar code0[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//0-9的数码管显示
sbit H1=P3^6;sbit H2=P3^7;sbit L1=P0^5;sbit L2=P0^6;sbit L3=P0^7;
uint m=0,i=0,j;uchar temp,prt;/***y延时函数***/ void delay(uint k){ uint i,j;
}
/***键盘扫描***/ char scan_key(){ H1=0;H2=0;
L1=1;L2=1;L3=1;if(L1==0){ delay(5);if(L1==0){ L1=0;H1=1;H2=1;if(H1==0)} //定义局部变量ij
//外层循环 for(i=0;i
{ m=1;return(m);} if(H2==0){ m=4;return(m);} } }
//KEY1键按下
//KEY4键按下
if(L2==0){ delay(5);if(L2==0){ L2=0;H1=1;H2=1;if(H1==0)
{ m=2;return(m);} if(H2==0){ m=5;return(m);} } }
//KEY5键按下 //KEY2键按下
if(L3==0){ delay(5);if(L3==0){ L3=0;H1=1;H2=1;if(H1==0){ m=3;
//KEY3键按下
}
return(m);} if(H2==0){ m=6;return(m);} } } return(0);
// KEY6键按下
/***主函数***/ main(){ P1M1=0x00;P1M0=0xff;
SCON=0x50;//设定串行口工作方式1 TMOD=0x20;//定时器1,自动重载,产生数据传输速率 TH1=0xfd;//数据传输率为9600 TR1=1;//启动定时器1 P0&=0xf0;while(1){
//如果有按键按下 if(scan_key()){ SBUF=scan_key();//发送数据 while(!TI);TI=0;}
if(RI){ RI=0;}
// //
等待数据传送 清除数据传送标志
//是否有数据到来
// 清除数据传送标志
temp=SBUF;
// 将接收到的数据暂存在temp中
P1=code0[temp];// 数据传送到P1口输出 delay(500);} } //延时500ms
五、实验中遇到的问题及解决方法
(1)串行口和定时器的工作方式设定是关键,本次是按需传输的是两位十六进制数,串行口为工作方式1,定时器为8位自动重载;(2)采用P0&=0xf0语句使4个数码管静态点亮;
(3)在发送和接受过程中,用标识位TI和RI来检测发送和接受是否完成;(4)在用电脑和单片机进行串口通信测试时,电脑的传世速率一定要和单片机的传输速率相等,否则显示会出现错误。
指导老师签字:
日期:
第6篇:串口通信实验报告
华南农业大学
实验报告
----------目录----------
1、实验任务和目的 ..............................................................................................................2、实验准备 ..........................................................................................................................3、实验步骤 ................................................................................................................................4、实验分析与总结 ....................................................................................................................(1)、分析.............................................................................................................................(2)、总结.............................................................................................................................1、实验任务和目的了解串行通信的背景知识后,通过三线制制作一条串口通信线(PC-PC),并编程实现两台PC间通过RS-232C通信。要求两台PC机能进行实时的字符通信,并了解工业自动化控制中的基本通信方式。
2、实验准备
1、检查PC是否具有串行通信接口,并按其针脚类准备一条串口通信线缆。
2、串口包的安装,下载javacomm20-win32.zip并解压,将win32com.dll复制到bin目录下;将comm.jar复制到lib;把javax.comm.properties也同样拷贝到lib目录下,再将上面提到的文件放到JRE相应的目录下就可以了。
3、实验步骤
1、将实验所需RS-232缆线准备好,并将JAVA串口包复制到相应地目录下。
2、查找有关串口通信的书籍以及在网上查找相应地串口通信代码。
3、用JAVA编程软件JCreator编写代码。
4、实验分析与总结
(1)、分析
(I)、对串口读写之前需要先打开一个串口并检测串口是否被占用: public void open(){//打开串口以及输入输出流
recieve=false;
try
{serialPort=(SerialPort)portId.open("Serial communication", 2000);}
catch(PortInUseException e){System.out.println("端口正被占用!");}
try
{serialPort.setSerialPortParams(9600,SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_NONE);}
catch(UnsupportedcommOperationException e){System.out.println("不支持通信");}
try
{
outputStream=serialPort.getOutputStream();
inputStream=serialPort.getInputStream();
1-完整运行程序如图所示:
图1
(2)、总结
通过本次串口实验,我对串口通信的知识了解的更透彻,这是在刚开始对串口通信知识不了解的情况下就编程而造成许多错误之后才得到的结果。在网上查找资料的时候也接触到了不少其他的编程语言例如VB,delphi,C#等,这也让我对这些从没有学过的语言有所了解,我想这些知识对以后的实验工作都有帮助。
3--
第7篇:串口通讯实验报告
网络编程与实践实验报告
实验内容:串口通信编程 学号:S201502189 姓名:职荣豪 日期:2015-9-28
一、实验要求
使用VS2010编写基于对话框的MFC应用程序,两个窗口分别使用两个串口,使得这两个窗口可以进行通信,包括数据的发送与接收。
二、实验原理
本实验使用Microsoft communications Control控件,利用这个ActiveX控件,只需要编写少量代码即可轻松进行通信。
该控件相关的函数如下: put__commPort:设置串口号
put_Settings:以字符串的形式设置波特率、奇偶校验位(n-无校验,e-偶校验,o-奇校验)、数据位数、停止位数
put_InputMode:设置接收数据的类型(0-文本类型,1-二进制类型)put_InputLen:设置从接收缓冲区读取的字节数,0表示全部读取 put_InBufferSize:设置接收缓冲区大小 put_OutBufferSize:设置发送缓冲区大小
put_RThreshold:设定当接收几个字符时触发Oncomm事件,0表示不产生事件,1表示每接收一个字符就产生一个事件
put_SThreshold:设定在触发Oncomm事件前,发送缓冲区内所允许的最少的字符数,0表示发送数据时不产生事件,1表示当发送缓冲区空时产生Oncomm事件
put_PortOpen:打开或关闭串口,传入参数为true时打开串口,传入参数为false时关闭串口 get_commEvent:获得串口上刚发生的事件,事件值为2表示接收到数据
get_InBufferCount:获得缓冲区中的数据位数
get_Input:获取缓冲区数据,返回类型为VARIANT put_Output:发送数据
三、设计思路
需要添加一个Microsoft communications Control控件,用于进行串口通信。由于要求同一程序可运行两个窗口进行相互通信,需要两个窗口开启两个不同串口,故需要添加一个Edit Control控件用于输入串口号,并添加打开串口按钮,在点击该按钮时对串口控件的参数进行设置并开启串口。同时添加关闭串口按钮,点击后关闭串口并可以对串口号进行修改。
需要添加两个Edit Control 分别用于显示接收到的数据以及输入要发送的数据。需要添加一个发送按钮,点击后发送输入的数据。
四、实验步骤
1.建立基于对话框的MFC应用程序 2.添加界面控件并设置ID与Caption 添加Microsoft communications Control控件,用于进行串口通信 添加一个Edit Control控件,用于输入串口号,ID设置为IDC_PORT 添加一个Static Text控件,用于标注端口号,将Caption设置为“串口号:”
添加两个按钮,分别用于打开串口、关闭串口。IDC分别设置为IDC_BTN_OPEN、IDC_BTN_CLOSE,Caption分别设置为“打开”、“关闭” 添加两个Edit Control,分别用于显示接收到的数据以及输入要发送的数据,ID分别设置为IDC_RECEIVE、IDC_SEND 添加两个Static Text控件,用于标注接收区与发送区,Caption分别设置为“接收区”、“发送区”
添加一个按钮用于发送数据,ID设置为IDC_BTN_SEND,Caption设置为“发送” 调整控件的大小与位置。
完成后如图:
3.给控件绑定变量
右键单击Microsoft communications Control控件,选择“添加变量”,变量名为m_com 打开类向导给控件添加变量:
给IDC_PORT绑定变量,用于存放输入的端口号,数据类型为int,变量名为m_port 给IDC_RECEIVE绑定变量,用于存放接收到的数据,数据类型为CString,变量名为m_strReceive 给IDC_SEND绑定变量,用于存放输入的待发送的数据,数据类型为CString,变量名为m_strSend
4.给控件添加事件响应函数
右键单击Microsoft communications Control控件,选择“添加事件处理程序”,点击“添加编辑”,生成响应函数,此函数用于接收数据。
在函数中添加以下代码:
UpdateData(TRUE);if(nEvent == 2){
} UpdateData(FALSE);//将m_strReceive的值显示到控件中
//更新m_strReceive的值
//获取事件值
//获取缓冲区位数
//时间值为2,此时为收到数据 int nEvent = m_com.get_commEvent();int k = m_com.get_InBufferCount();if(k pvData;//获取接收到数据的字*(str + k)= ' ';//字符数组最后一位的下一位设置为' ',为字符串的结尾标志 m_strReceive +=(const char *)str;//在用于显示的字符串末尾添加刚接收到的符数组的首地址
字符串
双击IDC_BTN_OPEN控件,即“打开”按钮,生成响应函数,此函数用于设置串口参数并打开串口。
在函数中添加以下代码:
UpdateData(TRUE);
if(m_port
} m_com.put__commPort(m_port);//设定串口为m_port的值 m_com.put_Settings("9600,n,8,1");
//设定波特率9600,无奇偶校验位,8作为数据位,AfxMeageBox("请输入正确的串口号!");return;
//更新m_port的值 //端口号不小于等于0
1作为停止位
m_com.put_InputMode(1);//设定数据接收模式,1为二进制方式
m_com.put_InputLen(0);//设置从接收缓冲区读取的字节数,0表示全部读取
m_com.put_InBufferSize(1024);//设置输入缓冲区大小为1024byte
m_com.put_OutBufferSize(1024);//设置输出缓冲区大小为1024byte m_com.put_RThreshold(1);//每接收到一个字符时,触发Oncomm事件 m_com.put_SThreshold(0);//每发送一个字符时,不触发Oncomm事件 m_com.put_PortOpen(true);
//打开串口
GetDlgItem(IDC_BTN_OPEN)->EnableWindow(FALSE);//打开按钮设为不可用 GetDlgItem(IDC_BTN_CLOSE)->EnableWindow(TRUE);//关闭按钮设为可用 GetDlgItem(IDC_BTN_SEND)->EnableWindow(TRUE);
//发送按钮设为可用
双击IDC_BTN_CLOSE控件,即“关闭”按钮,生成响应函数,该函数用于关闭串口。在函数中添加以下代码:
m_com.put_PortOpen(false);//关闭串口
GetDlgItem(IDC_BTN_OPEN)->EnableWindow(TRUE);
//打开按钮设为可用
GetDlgItem(IDC_BTN_CLOSE)->EnableWindow(FALSE);//关闭按钮设为不可用 GetDlgItem(IDC_BTN_SEND)->EnableWindow(FALSE);//发送按钮设为不可用
双击IDC_BTN_SEND控件,即“发送”按钮,生成响应函数,该函数用于发送数据。在函数中添加以下代码:
UpdateData(TRUE);//更新m_strSend的值,读取编辑框内容 m_com.put_Output(COleVariant(m_strSend));//发送数据
5.在对话框初始化函数中添加额外初始化代码
在对话框刚打开时,此时串口没有开启,故“关闭”按钮与“发送”按钮需设为不可用。在OnInitDialog函数中添加以下代码:
GetDlgItem(IDC_BTN_CLOSE)->EnableWindow(FALSE);//关闭按钮设为不可用 GetDlgItem(IDC_BTN_SEND)->EnableWindow(FALSE);//发送按钮设为不可用
五、实验结果
对话框1 运行结果如下:
对话框2 运行结果如下:
六、实验心得
通过课上的学习,我学习到了数据通信的基础知识,对网络的分层结构以及相关协议有了进一步的认识。
通过本次实验,我对串口通信的原理有了更深的认识与理解,并对MFC界面制作更加熟练。总之,在本课程中我收获很多,不仅在通信方面的知识有所提升,同时也锻炼了编程能力,VC++软件的使用更加熟练。
第8篇:arduino mega 2560 串口
arduino mega 2560 串口
2560的串口一共有4个,分别对应数字接口0-1,18-19,16-17,14-15所有串口都可以跟pc通信,但只有0-1是跟板子上的usb2ttl连接,只有0-1是可以用来下载程序的,即使购买了usb2ttl的线,在0-1以外的串口也不能用来下载,除非修改bootloader将蓝牙模块接在14-15上(注意蓝牙的rx、tx跟板子上的rx、tx要反接)程序里面可以用serial3.read()等类似操作程序里面serial操作0-1,serial1操作18-19,serial2操作16-17,serial3操作14-15这样使用usb线下载程序同时可以用蓝牙接收数据到电脑上。
串口通讯中最重要的一点就的通讯协议,一般串口通讯协议都会有波特率、数据位、停止位、校验位等参数。大家不会设置也不用怕,Arduino语言中Serial.begin()函数就能使大家轻松完成设置,我们只需要改变该函数的参数即可,例如Serial.begin(9600),则表示波特率为9600bit/s(每秒比特数bps),其余参数默认即可。
Arduino语言中还提供了Serial.available()判断串口缓冲器状态、Serial.read()读串口、Serial.print()串口发送及Serial.println()带换行符串口发送四个函数。
下面用一段代码来演示这些函数的用途。无须外围电路,只需要将下载的USB线连接即可。char word;void setup(){ Serial.begin(9600);// 打开串口,设置波特率为9600 bps } void loop(){ if(Serial.available()> 0)//判断串口缓冲器是否有数据装入 { word = Serial.read();//读取串口 if(word=='a')//判断输入的字符是否为a { Serial.print("DFRobot ");//从串口发送字符串 Serial.println("is NO.1");//从串口发送字符串并换行 } } }
编译下载完程序后,点红圈里的按钮,打开串口监视器;
选择串口监视器的波特率为9600bps,在发送框里填上字母a,点send发送,下面的显示框里就会显示返回的数据,如果发送的是字母a,则显示字符串,否则无返回。
第9篇:串口通讯的工作方式
串口通讯的工作方式
由于 CPU 与接口之间按并行方式传输,接口与外设之间按串行方式传输,因此,在串行接口中,必须要有 " 接收移位寄存器 "(串→并)和 " 发送移位寄存器 "(并→串).1.在数据输入过程中,数据 1 位 1 位地从外设进入接口的 " 接收移位寄存器 ",2.当 " 接收移位寄存器 " 中已接收完 1 个字符的各位后,数据就从 " 接收移位寄存器 " 进入 " 数据输入寄存器 ".3.CPU 从 " 数据输入寄存器 " 中读取接收到的字符.(并行读取,即 D7~D0 同时被读至累加器中)." 接收移位寄存器 " 的移位速度由 " 接收时钟 " 确定.1.在数据输出过程中,CPU 把要输出的字符(并行地)送入 " 数据输出寄存器 ",2." 数据输出寄存器 " 的内容传输到 " 发送移位寄存器 "
3,然后由 " 发送移位寄存器 " 移位,把数据 1 位 1 位地送到外设." 发送移位寄存器 " 的移位速度由 " 发送时钟 " 确定.接口中的 " 控制寄存器 " 用来容纳 CPU 送给此接口的各种控制信息,这些控制信息决定接口的工作方式." 状态寄存器 " 的各位称为 " 状态位 ",每一个状态位都可以用来指示数据传输过程中的状态或某种错误.例如,用状态寄存器的 D5 位为 "1" 表示 " 数据输出寄存器 " 空,用 D0 位表示 " 数据输入寄存器满 ",用 D2 位表示 " 奇偶检验错 " 等.能够完成上述 " 串 并 " 转换功能的电路,通常称为 " 通用异步收发器 "(UART :Universal Asynchronous Receiver and Transmitter),典型的芯片有:Intel 8250/8251,16550
第10篇:单片机串口通信方式总结
IIC总线通信协议————数据传输高位在前p233 1,起始和停止条件
开始信号:SCL为高电平,SDA由高电平向低电平跳变,开始传送数据。void start()// 开始位 { SDA = 1;
//SDA初始化为高电平“1”
SCL = 1;
//开始数据传送时,要求SCL为高电平“1”
_nop_();
//等待一个机器周期
_nop_();
//等待一个机器周期
SDA = 0;
//SDA的下降沿被认为是开始信号
_nop_();
//等待一个机器周期
_nop_();
//等待一个机器周期
_nop_();
//等待一个机器周期
_nop_();
//等待一个机器周期
SCL = 0;
//SCL为低电平时,SDA上数据才允许变化(即允许以后的数据传递)} 结束信号:SCL为高电平,SDA由低电平向高电平跳变,结束传送数据。void stop()// 停止位 { SDA = 0;
//SDA初始化为低电平“0”
_nop_();
//等待一个机器周期
_nop_();
//等待一个机器周期
SCL = 1;
//结束数据传送时,要求SCL为高电平“1”
_nop_();
//等待一个机器周期
_nop_();
//等待一个机器周期
_nop_();
//等待一个机器周期
_nop_();
//等待一个机器周期
SDA = 1;
//SDA的上升沿被认为是结束信号 }
2,数据格式(数据输入)
在IIC总线开始信号后,送出的第一个字节数据是用来选择器件地址和数据方向的,其格式为
从器件收到地址型号后与自己的地址比较,一致则此器件就是主器件要找的器件,并返回ACK(不管是写数据还是地址都会返回)。IIC传送数据时SCL为低电平时SDA可改变高低电平,SCL转跳为高时数据输入(此时SDA不能跳变),发送数据:bit WriteCurrent(unsigned char y){ unsigned char i;bit ack_bit;
//储存应答位
for(i = 0;i
{
SDA =(bit)(y&0x80);
//通过按位“与”运算将最高位数据送到S
//因为传送时高位在前,低位在后
_nop_();
//等待一个机器周期
SCL = 1;
//在SCL的上升沿将数据写入AT24Cxx
_nop_();
//等待一个机器周期
_nop_();
//等待一个机器周期
SCL = 0;
//将SCL重新置为低电平,以在SCL线形成传送数据所需的8个脉冲
y
//将y中的各二进位向左移一位
} SDA = 1;
// 发送设备(主机)应在时钟脉冲的高电平期间(SCL=1)释放SDA线,//以让SDA线转由接收设备(AT24Cxx)控制
_nop_();
//等待一个机器周期
_nop_();
//等待一个机器周期
SCL = 1;
//根据上述规定,SCL应为高电平
_nop_();
//等待一个机器周期
_nop_();
//等待一个机器周期
_nop_();
//等待一个机器周期
_nop_();
//等待一个机器周期
ack_bit = SDA;//接受设备(AT24Cxx)向SDA送低电平,表示已经接收到一个字节
//若送高电平,表示没有接收到,传送异常
SCL = 0;
//SCL为低电平时,SDA上数据才允许变化(即允许以后的数据传递)
return ack_bit;
// 返回AT24Cxx应答位 } 读数据:unsigned char ReadData()// 从AT24Cxx移入数据到MCU { unsigned char i;unsigned char x;
//储存从AT24Cxx中读出的数据
for(i = 0;i
SCL = 1;
//SCL置为高电平
x
//将x中的各二进位向左移一位
x|=(unsigned char)SDA;//将SDA上的数据通过按位“或“运算存入x中
SCL = 0;
//在SCL的下降沿读出数据
} return(x);
//将读取的数据返回 } 发送数据步骤:
oid WriteSet(unsigned char add, unsigned char dat)// 在指定地址addr处写入数据WriteCurrent { start();
//开始数据传递
WriteCurrent(OP_WRITE);//选择要操作的AT24Cxx芯片,并告知要对其写入数据
WriteCurrent(add);
//写入指定地址
WriteCurrent(dat);
//向当前地址(上面指定的地址)写入数据
stop();
//停止数据传递
delaynms(4);
//1个字节的写入周期为1ms, 最好延时1ms以上 } 读数据步骤:
/*************************************************** 函数功能:从AT24Cxx中的当前地址读取数据 出口参数:x(储存读出的数据)
***************************************************/ unsigned char ReadCurrent(){ unsigned char x;start();
//开始数据传递
WriteCurrent(OP_READ);
//选择要操作的AT24Cxx芯片,并告知要读其数据
x=ReadData();
//将读取的数据存入x stop();
//停止数据传递
return x;
//返回读取的数据 } /*************************************************** 函数功能:从AT24Cxx中的指定地址读取数据 入口参数:set_add 出口参数:x
***************************************************/ unsigned char ReadSet(unsigned char set_add)// 在指定地址读取 { start();
//开始数据传递
WriteCurrent(OP_WRITE);
//选择要操作的AT24Cxx芯片,并告知要对其写入数据
WriteCurrent(set_add);
//写入指定地址
return(ReadCurrent());
//从指定地址读出数据并返回 }
单总线协议————数据传输低位在前——p237 1,初始化单总线器件
初始化时序程序:
函数功能:将DS18B20传感器初始化,读取应答信号 出口参数:flag
***************************************************/ bit Init_DS18B20(void){ bit flag;
//储存DS18B20是否存在的标志,flag=0,表示存在;flag=1,表示不存在DQ = 1;
//先将数据线拉高
for(time=0;time
;DQ = 0;
//再将数据线从高拉低,要求保持480~960us for(time=0;time
;
//以向DS18B20发出一持续480~960us的低电平复位脉冲
DQ = 1;
//释放数据线(将数据线拉高)
for(time=0;time
;//延时约30us(释放总线后需等待15~60us让DS18B20输出存在脉冲)
flag=DQ;
//让单片机检测是否输出了存在脉冲(DQ=0表示存在)
for(time=0;time
;return(flag);
//返回检测成功标志 }
单总线通信协议中存在两种写时隙:写0写1。主机采用写1时隙向从机写入1,而写0时隙向从机写入0。所有写时隙至少要60us,且在两次独立的写时隙之间至少要1us的恢复时间。两种写时隙均起始于主机拉低数据总线。产生1时隙的方式:主机拉低总线后,接着必须在15us之内释放总线,由上拉电阻将总线拉至高电平;产生写0时隙的方式为在主机拉低后,只需要在整个时隙间保持低电平即可(至少60us)。在写时隙开始后15~60us期间,单总线器件采样总电平状态。如果在此期间采样值为高电平,则逻辑1被写入器件;如果为0,写入逻辑0。
下图为写时隙(包括1和0)时序
上图中黑色实线代表系统主机拉低总线,黑色虚线代表上拉电阻将总线拉高。下面是代码:
WriteOneChar(unsigned char dat){ unsigned char i=0;for(i=0;i
{
DQ =1;
// 先将数据线拉高
_nop_();
//等待一个机器周期
DQ=0;
//将数据线从高拉低时即启动写时序
DQ=dat&0x01;
//利用与运算取出要写的某位二进制数据,//并将其送到数据线上等待DS18B20采样
for(time=0;time
;//延时约30us,DS18B20在拉低后的约15~60us期间从数据线上采样
DQ=1;
//释放数据线
for(time=0;time
;//延时3us,两个写时序间至少需要1us的恢复期
dat>>=1;
//将dat中的各二进制位数据右移1位
}
for(time=0;time
;//稍作延时,给硬件一点反应时间 }
对于读时隙,单总线器件仅在主机发出读时隙时,才向主机传输数据。所有主机发出读数据命令后,必须马上产生读时隙,以便从机能够传输数据。所有读时隙至少需要60us,且在两次独立的读时隙之间至少需要1us恢复时间。每个读时隙都由主机发起,至少拉低总线1us。在主机发出读时隙后,单总线器件才开始在总线上发送1或0。若从机发送1,则保持总线为高电平;若发出0,则拉低总线。
当发送0时,从机在读时隙结束后释放总线,由上拉电阻将总线拉回至空闲高电平状态。从机发出的数据在起始时隙之后,保持有效时间15us,因此主机在读时隙期间必须释放总线,并且在时隙起始后的15us之内采样总线状态。
下图给出读时隙(包括0或1)时序
图中黑色实线代表系统主机拉低总线,灰色实线代表总局拉低总线,而黑色的虚线则代表上拉电阻总线拉高。代码为:
unsigned char ReadOneChar(void){
unsigned char i=0;
unsigned char dat;//储存读出的一个字节数据
for(i=0;i
{
DQ =1;
// 先将数据线拉高
_nop_();
//等待一个机器周期
DQ = 0;
//单片机从DS18B20读书据时,将数据线从高拉低即启动读时序
dat>>=1;
_nop_();
//等待一个机器周期
DQ = 1;
//将数据线"人为"拉高,为单片机检测DS18B20的输出电平作准备
for(time=0;time
;
//延时约6us,使主机在15us内采样
if(DQ==1)
dat|=0x80;//如果读到的数据是1,则将1存入dat
else
dat|=0x00;//如果读到的数据是0,则将0存入dat
//将单片机检测到的电平信号DQ存入r[i]
for(time=0;time
;
//延时3us,两个读时序之间必须有大于1us的恢复期
}
return(dat);
//返回读出的十进制数据 }
每个单总线器件内部都光刻了一个全球唯一的64位二进制序列码,用于该单总线器件的识别
SPI总线协议
SPI总线有四种工作方式(SP0, SP1, SP2, SP3),其中使用的最为广泛的是SPI0和SPI3方式。
SPI是一个环形总线结构,由(cs)、sck、sdi、sdo构成,其时序其实很简单,主要是在sck的控制下,两个双向移位寄存器进行数据交换。
上升沿发送、下降沿接收、高位先发送。
上升沿到来的时候,sdo上的电平将被发送到从设备的寄存器中。
下降沿到来的时候,sdi上的电平将被接收到主设备的寄存器中。读代码:
unsigned char ReadCurrent(void){
unsigned char i;unsigned char x=0x00;
//储存从X5045中读出的数据
SCK=1;
//将SCK置于已知的高电平状态
for(i = 0;i
SCK=1;
//拉高SCK
SCK=0;
//在SCK的下降沿输出数据
x
x|=(unsigned char)SO;//将SO上的数据通过按位“或“运算存入 x
} return(x);
//将读取的数据返回
} 写代码:
void WriteCurrent(unsigned char dat){
unsigned char i;SCK=0;
//将SCK置于已知的低电平状态
for(i = 0;i
{
SI=(bit)(dat&0x80);
//通过按位“与”运算将最高位数据送到S
//因为传送时高位在前,低位在后
SCK=0;
SCK=1;
//在SCK上升沿写入数据
dat
//将y中的各二进位向左移一位,因为首先写入的是字节的最高位
} } RS232通讯协议 串行通讯方式3 RS485通讯协议 串行通讯方式1
第11篇:linux串口触摸屏设计总结
Linux serial touch 设计总结
概述:
最近在做嵌入式linux下串口触摸屏设计,遇到一些问题,经过查找资料和请教同事,总算把问题解决了,事后有把linux相关的内核代码仔细看了一遍,为了有点成果,特别写了个总结。如有任何问题请联系yxj_5421@163.com,转载请标明出处。
系统资源:
Linux:2.6.36
UI:QT+TSLIB 硬件资源不关心
设计方法:
有两种实现途径。
1、是将要使用的串口单独拿出来,作为一个platform总线设备实现,在嵌入式平台mach文件里面,加上串口中断号和寄存器首地址,然后将这个串口注册成一个platform总线设备。在驱动probe函数里面需要得到这个串口中断号以及寄存器映射地址,通过寄存器映射地址设置串口波特率,数据位,停止位等,通过中断号注册中断等,然后调用input_register_device注册一个input设备。在中断里面得到外面触摸屏的数据,然后根据input touch协议上报触摸数据。这种方法实现简单明了,不需要和linux的tty,serio等打交道。但是要求知道串口硬件spec,比如寄存器等,而且这个串口就只能给触摸屏使用了,不能作为tty使用。因为是嵌入式开发,因此很容易知道硬件spec,而且嵌入式平台一旦确定,那么这个串口肯定就是给触摸屏使用了。因此在嵌入式平台上,推荐使用这个方法。
是将串口作为一个serio总线设备,利用linux内核提供serio总线驱动,通过设置对应的串口,调用serport提供的函数将串口当做serio总线设备,在驱动里面需要按照serio总线设备驱动的框架来实现,这方面的例子linux里面有很多,比如touchright.c,在模块init函数里面调用serio_register_driver注册serio总线设备驱动,如果serio总线上对应的serio设备存在,就调用connect函数,在这个函数里面调用input_register_device注册一个input设备。具体驱动不再分析了,很简单,相信各位都能看的懂。
至此,两种方法都实现了串口触摸屏的驱动,讲到这里是不是就完了,非也,本文的重点还在后面,请看下面分析:
第一种方法只要驱动模块被加载,就会在/dev/input下面创建一个eventx节点,tslib就能访问这个节点,获得触摸坐标,然后送给qt。第二种方法驱动模块加载后,并没有创建eventx节点,也就是说connect函数没有被调用,按照linux驱动模型来看,就是serio总线上还没有对应的serio设备,因此驱动加载时没有对应的设备,就不会调用connect函数,这时的串口还是作为一个linux tty设备存在。
我遇到的问题就是serio驱动加载了,但是没有创建eventx节点,查找资料也只有一个说是要把tty设置成N_MOUSE,然后读,说的不清楚,也不知道怎么实现,经过自己摸索,终于把问题解决了。
2、Linux 启动后串口形式: Linux一启动是将串口作为tty来设置的。看下的调用:
start_kernel
init/main.c大家对这个函数不陌生吧,linux启动过程中重要的一个函数
console_init();
drivers/tty/tty_io.c
tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY);drivers/tty/tty_idisc.c 给串口注册一个tty链路层处理函数ops。
现在我们需要写一个上层的应用程序,对这个tty进行设置,需要设置波特率,数据位,停止位等,最重要的是要将这个tty设备设置成一个serio总线设备,然后把它注册在serio总线上,请看下面的代码:
fd = open(device, O_RDWR | O_NOCTTY | O_NONBLOCK);
if(fd
setline(fd, type->flags, type->speed);ldisc = N_MOUSE;if(ioctl(fd, TIOCSETD, &ldisc)){
} fprintf(stderr, "inputattach: can't set line disciplinen");return EXIT_FAILURE;
} fprintf(stderr, "inputattach: '%s'-%sn", device, strerror(errno));return 1;
里面的device就是对应要使用的那个串口,linux里面一般是/dev/ttyS0,首先是打开串口 open(device, O_RDWR | O_NOCTTY | O_NONBLOCK)接着设置波特率等 setline(fd, CS8, B9600);static void setline(int fd, int flags, int speed){
} struct termios t;tcgetattr(fd, &t);t.c_cflag = flags | CREAD | HUPCL | CLOCAL;t.c_iflag = IGNBRK | IGNPAR;t.c_oflag = 0;t.c_lflag = 0;t.c_cc[VMIN ] = 1;t.c_cc[VTIME] = 0;cfsetispeed(&t, speed);cfsetospeed(&t, speed);tcsetattr(fd, TCSANOW, &t);devt = type->type |(id
read(fd, NULL, 0);
接下来就是重点了
ldisc = N_MOUSE;if(ioctl(fd, TIOCSETD, &ldisc))
跟踪代码到内核层ioctl:
long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
drivers/tty/tty_io.c case TIOCSETD: return tiocsetd(tty, p);
drivers/tty/tty_io.c
tty_set_ldisc(tty, ldisc);drivers/tty/tty_idisc.c,ldisc等于N_MOUSE new_ldisc = tty_ldisc_get(ldisc);
ldops = get_ldops(disc);
这段代码需要得到N_MOUSE的链路层,先在tty_ldiscs里面查找是否有N_MOUSE链路层的处理函数ops,如果没有,就需要加载serport模块,看看这个模块init函数 retval = tty_register_ldisc(N_MOUSE, &serport_ldisc);注册一个N_MOUSE链路层的处理函数ops 创建一个新的N_MOUSE链路层new_ldisc,接着调用 tty_ldisc_aign(tty, new_ldisc);
把新的链路层放在tty里面 retval = tty_ldisc_open(tty, new_ldisc);打开这个新的链路层
至此,已经给串口增加了一个N_MOUSE的链路层,并且把链路层的处理函数也注册进去了。这个串口当前的链路层就是N_MOUSE。目前为止串口还只是个tty设备,并没有注册到serio总线上。继续看我们的应用程序:
devt = type->type |(id
fprintf(stderr, "inputattach: can't set device typen");
return EXIT_FAILURE;} ret = ld->ops->open(tty)
ld->ops就是serport注册的serport_ldisc static int serport_ldisc_open(struct tty_struct *tty)drivers/input/serio/serport.c 这个函数里面会创建一个serport结构体,并初始化
调用
long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
drivers/tty/tty_io.c retval = ld->ops->ioctl(tty, file, cmd, arg);static int serport_ldisc_ioctl(struct tty_struct * tty, struct file * file, unsigned int cmd, unsigned long arg)设置
serport->id.proto = type & 0x000000ff;serport->id.id
=(type & 0x0000ff00)>> 8;serport->id.extra =(type & 0x00ff0000)>> 16;这里三个值一定要和serio总线驱动里面对应的值一致,serio总线就是靠它们来给设备和驱动建立联系的。
调用
read(fd, NULL, 0);跟踪代码到内核层tty_read:
static ize_t tty_read(struct file *file, char __user *buf, size_t count,loff_t *ppos)(ld->ops->read)(tty, file, buf, count)
这个ld就是tty当前的链路层结构,上面我们已经设置N_MOUSE为tty的当前链路层,因此ld->ops就是serport注册的serport_ldisc static ize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, unsigned char __user * buf, size_t nr)
serio_register_port(serport->serio);
serio_init_port(serio);
serio_queue_event(serio, owner, SERIO_REGISTER_PORT);注册一个serio总线设备,关于serio总线,网络有很多资料介绍,这里就不说了。至此,我们的串口设备已经当做serio总线设备注册在serio总线上了,如果相应的驱动也在serio总线上,就会进行设备和驱动的匹配,然后调用驱动里面的connect函数,在这个函数里面就会创建input节点。我们的驱动和设备已经运行起来了,现在看看数据是如何传递的先看具体串口中断函数: 我们以altera_uart.c为例: altera_uart_interrupt
altera_uart_rx_chars(pp)
tty_flip_buffer_push(port->state->port.tty);
flush_to_ldisc(&tty->buf.work);
disc->ops->receive_buf(tty, char_buf,flag_buf, count);disc->ops就是serport注册的serport_ldisc static void serport_ldisc_receive(struct tty_struct *tty, const unsigned char *cp, char *fp, int count)
serio_interrupt(serport->serio, cp[i], ch_flags);
ret = serio->drv->interrupt(serio, data, dfl);drv->interrupt就是我们驱动函数提供一个函数,它每次接受一个字符,在这个函数里面,接受到足够信息后,就能得到触摸屏坐标信息,然后通过input_report上报上去。看看数据处理流程图:
总结:
要想让基于serio总线驱动的串口触摸屏能正常工作,在linux内核需要加载驱动模块,serport模块。还需要一个上层应用程序,这个程序需要进行以下工作
1、打开你要使用的串口,比如
open(device, O_RDWR | O_NOCTTY | O_NONBLOCK)
device为/dev/ttyS0
2、设置串口波特率等,和你的串口触摸屏一致
3、给串口增加一个N_MOUSE链路层
4、设置你的串口触摸屏type,id,extra
5、读串口read(fd, NULL, 0);
第12篇:VB中串口通讯的实现
VB中串口通讯的实现.txt VB中串口通讯的实现
------------------
一、概述
串口通讯作为一种古老而又灵活的通讯方式,被广泛地应用于PC间的通讯以及PC和单片机之间的通讯之中。提到串口通讯的编程,人们往往立刻想到C、汇编等对系统底层操作支持较好的编程语言以及大串繁琐的代码。
实际上,只要我们借助相关ActiveX控件的帮助,即使是在底层操作一向不被人看好的VB中,一样能够实现串口通 讯,甚至其实现方法和C、汇编相比,要更加快捷方便。下面,笔者就介绍一下在VB中实现串口通讯的方法。
在Visual Basic中有一个名为Microsoft communication Control(简称MScomm)的通讯控件。我们只要通 过对此控件的属性和事件进行相应编程操作,就可以轻松地实现串口通讯。下面,笔者就简要地介绍一下
MScomm控件的使用方法。
二、MScomm控件的主要属性、事件
1、MScomm的属性
由于MScomm控件属性很多,在此笔者仅介绍与实现串口通讯密切相关的核心属性。
commport:设置通讯所占用的串口号。如设成1(默认值),表示对com1进行操作。
Setting:对串口通讯的相关参数。包括串口通讯的比特率,奇偶校验,数据位长度、停止位等。其默认值 是“9600,N,8,1”,表示串口比特率是9600bit/s,不作奇偶校验,8位数据位,1个停止位。
Portopen:设置串口状态,值为True时打开串口,值为False时关闭串口。
Input:从输入寄存器读取数据,返回值为从串口读取的数据内容,同时输入寄存器将被清空。
Ouput:发送数据到输出寄存器。
InBufferCount:设置输入寄存器所存储的字符数,当将其值设为0时,则输入寄存器将被清空。
InputMode:设置从输入寄存器中读取数据的形式。若值为0,则表示以文本形式读取;值为1,则表示以 二进制形式读取。
OutBufferCount:设置输出寄存器所存储的字符数,当将其值设为0时,则输出寄存器将被清空。
RThreshold:设置在MScomm控件设置commEvent属性为comEvReceive并产生Oncomm事件之前要接受的字符 数。
commEvent属性:返回最近的通讯事件或错误。通过对它具体属性值的查询,我们就可以获得通讯事件和通 讯错误的完整信息。当其值是comEvReceive时表示接收到数据。
2、MScomm的事件
除了公共事件之外,MScomm只有一个Oncomm事件。当commEvent属性值变化时将发生Oncomm事件,指示发生 一个通讯事件或错误。当我们设置Rtheshold属性值为0时,将使得捕获comEvReceive事件无效。
三、串口通讯编程实例
在完成了对MScomm控件的简要介绍之后,笔者就以实际程序为例,介绍一下串口通讯的具体实现方法。
1、PC机间的串口通讯
(1)、实现方法:
A、新建一个窗体,在上面放两个Text控件、两个commandButton控件和两个Label控件(如图1.bmp所示)。
具体见下表:
控件类型 名称 Caption属性 作用
-----------------
Text Text1-------输入所要发送的信息
Text Text2-------显示接收到的信息
commandButton command1 发 送---------commandButton command2 退 出---------
Label Label1 发送的数据 提示
Label Label2 接收的数据 提示
B、在控件工具箱中的空白处点击鼠标右键,在弹出的菜单中选择“部件”,在弹出的窗口中的控件列表中 找到“Microsoft comm Control”,将其选中,在点击“应用”、“关闭”,在控件工具栏中就会出现一个电 话的小图标。
C、用串口线将两台电脑连接起来。您可以使用com1对com1的对应连接,也可以使用com1和com2的交叉连接。
本程序使用的是com1对com1的连接。
D、输入以下代码:
Private Sub command1_Click()
'...发送数据
MScomm1.OutBufferCount = 0 '...清空输出寄存器
MScomm1.Output = Text1.Text '...发送数据
End Sub
Private Sub command2_Click()
'...退出
Unload Me
End Sub
Private Sub Form_Load()
'...初始化
MScomm1.commPort = 1 '...使用com1口
MScomm1.Settings = "9600,n,8,1" '...设置通讯参数
MScomm1.PortOpen = True '...打开串口
End Sub
Private Sub Mscomm1_Oncomm()
'...通讯事件发生
Select Case MScomm1.commEvent
Case comEvReceive '...有接受事件发生
Text2.Text = MScomm1.Input '...接受显示数据
MScomm1.InBufferCount = 0 '...清空输入寄存器
End Select
End Sub
2、PC机与单片机之间的通讯
PC机与单片机之间的通讯被广泛的用于工业、医疗测控等领域之中。在应用中,我们通常将单片机作为“感 受器”和“效应器”,负责数据采集、响应计算机发出的指令对电路进行控制,有时也进行一些简单的运算,最后再将执行数据反馈给计算机处理。本程序将实现在PC机上输入一个0-255之间的整数,将此数据发送到单片 机,单片机接收到数据后,将数据在显示管上显示,再将此数除以2,将得数返回给PC机。(运行效果如图 3.BMP所示)其实现方法如下:
A、同PC机间通讯的实现方法A-B。
B、连接电脑和单片机。注意!由于PC机端的RS232电平与单片机端TTL的并不不匹配,故应注意电平转换。
C、在VB中输入以下代码:
Private Sub Mscomm1_Oncomm()
'...通讯事件发生
Dim indata As Variant
Dim bte(0)As Byte
Select Case MScomm1.commEvent
Case comEvReceive '...有接受事件发生
indata = MScomm1.Input
'...注意!要通过MScomm控件发送或接收二进制数据必须用Variant类型的变量对二进
'...制Byte类型的变量进行转换!
bte(0)= AscB(indata)
Text2.Text = bte(0)
MScomm1.InBufferCount = 0 '...清空输入寄存器
End Select
End Sub
Private Sub command1_Click()
'...发送数据
Dim Num As Integer
Dim outbte(0)As Byte
Num = Val(Text1.Text)
outbte(0)= CByte(Num)
MScomm1.OutBufferCount = 0 '...清空输出寄存器
MScomm1.Output = outbte(0)'...发送数据
End Sub
Private Sub command2_Click()
'...退出
Unload Me
End Sub
Private Sub Form_Load()
'...初始化
MScomm1.commPort = 1 '...使用com1口
MScomm1.Settings = "9600,n,8,1" '...设置通讯参数
MScomm1.PortOpen = True '...打开串口
End Sub
D、单片机工作方式置于1,比特率设为9600bit/s。在单片机上,我们只得使用汇编语言编写,并且调用中 断实现对串口数据的收发工作。源代码如下:
PUSH PSW ;将程序状态字压入堆栈
PUSH ACC ;将累加器压入堆栈
CLR EA ;关闭系统中断
CLR RI ;清除中断标志位
MOV A,SBUF ;从接收寄存器中读取数据
MOV 70H,A ;分解数据百、十、个位并显示
MOV B,#100
DIV AB
MOV 52H,A ;分解百位,送入存储器52H
MOV A,B
MOV B,#10
DIV AB
MOV 51H,A ;分解十位,送入存储器51H
MOV 50H,B ;分解个位,送入存储器50H MOV A,70H
MOV B,#2
DIV AB;将接受的数据除以2
MOV SBUF,A ;将得数发送到输出寄存器
ACALL DL1 ;延时保证数据完整发送
ACALL DL1
CLR RI ;清除中断标志位
SETB EA ;打开系统中断
POP ACC;累加器出栈
POP PSW ;程序状态字出栈
RETI ;中断程序返回
3、编程环境
以上程序在Windows 2000 Profeional,Visual Basic 6.0企业版,AT89C52型单片机下调试通过。
四、总结
从以上程序可以看出,在VB中利用MScomm控件,可以快速开发出串口通讯程序,从而大大提高编程效率。
演讲稿
尊敬的老师们,同学们下午好:
我是来自10级经济学(2)班的学习委,我叫张盼盼,很荣幸有这次机会和大家一起交流担任学习委员这一职务的经验。
转眼间大学生活已经过了一年多,在这一年多的时间里,我一直担任着学习委员这一职务。回望这一年多,自己走过的路,留下的或深或浅的足迹,不仅充满了欢愉,也充满了淡淡的苦涩。一年多的工作,让我学到了很多很多,下面将自己的工作经验和大家一起分享。
学习委员是班上的一个重要职位,在我当初当上它的时候,我就在想一定不要辜负老师及同学们我的信任和支持,一定要把工作做好。要认真负责,态度踏实,要有一定的组织,领导,执行能力,并且做事情要公平,公正,公开,积极落实学校学院的具体工作。作为一名合格的学习委员,要收集学生对老师的意见和老师的教学动态。在很多情况下,老师无法和那么多学生直接打交道,很多老师也无暇顾及那么多的学生,特别是大家刚进入大学,很多人一时还不适应老师的教学模式。学习委员是老师与学生之间沟通的一个桥梁,学习委员要及时地向老师提出同学们的建议和疑问,熟悉老师对学生的基本要求。再次,学习委员在学习上要做好模范带头作用,要有优异的成绩,当同学们向我提出问题时,基本上给同学一个正确的回复。
总之,在一学年的工作之中,我懂得如何落实各项工作,如何和班委有效地分工合作,如何和同学沟通交流并且提高大家的学习积极性。当然,我的工作还存在着很多不足之处。比日:有的时候得不到同学们的响应,同学们不积极主动支持我的工作;在收集同学们对自己工作意见方面做得不够,有些事情做错了,没有周围同学的提醒,自己也没有发觉等等。最严重的一次是,我没有把英语四六级报名的时间,地点通知到位,导致我们班有4名同学错过报名的时间。这次事使我懂得了做事要脚踏实地,不能马虎。
在这次的交流会中,我希望大家可以从中吸取一些好的经验,带动本班级的学习风气,同时也相信大家在大学毕业后找到好的工作。谢谢大家!
第13篇:RS232串口通信原理简介
串口是计算机上一种非常通用设备通信的协议。大多数计算机包含两个基于RS232的串口。串口同时也是仪器仪表设备通用的通信协议;很多GPIB兼容的设备也带有RS-232口。同时,串口通信协议也可以用于获取远程采集设备的数据。
串口通信的概念非常简单,串口按位(bit)发送和接收字节。尽管比按字节(byte)的并行通信慢,但是串口可以在使用一根线发送数据的同时用另一根线接收数据。它很简单并且能够实现远距离通信。比如IEEE488定义并行通行状态时,规定设备线总常不得超过20米,并且任意两个设备间的长度不得超过2米;而对于串口而言,长度可达1200米。
典型地,串口用于ASCII码字符的传输。通信使用3根线完成:(1)地线,(2)发送,(3)接收。由于串口通信是异步的,端口能够在一根线上发送数据同时在另一根线上接收数据。其他线用于握手,但是不是必须的。串口通信最重要的参数是波特率、数据位、停止位和奇偶校验。对于两个进行通行的端口,这些参数必须匹配:
波特率:这是一个衡量通信速度的参数。它表示每秒钟传送的bit的个数。例如300波特表示每秒钟发送300个bit。当我们提到时钟周期时,我们就是指波特率例如如果协议需要4800波特率,那么时钟是4800Hz。这意味着串口通信在数据线上的采样率为4800Hz。通常电话线的波特率为14400,28800和36600。波特率可以远远大于这些值,但是波特率和距离成反比。高波特率常常用于放置的很近的仪器间的通信,典型的例子就是GPIB设备的通信。
数据位:这是衡量通信中实际数据位的参数。当计算机发送一个信息包,实际的数据不会是8位的,标准的值是
5、7和8位。如何设置取决于你想传送的信息。比如,标准的ASCII码是0~127(7位)。扩展的ASCII码是0~255(8位)。如果数据使用简单的文本(标准 ASCII码),那么每个数据包使用7位数据。每个包是指一个字节,包括开始/停止位,数据位和奇偶校验位。由于实际数据位取决于通信协议的选取,术语“包”指任何通信的情况。
停止位:用于表示单个包的最后一位。典型的值为1,1.5和2位。由于数据是在传输线上定时的,并且每一个设备有其自己的时钟,很可能在通信中两台设备间出现了小小的不同步。因此停止位不仅仅是表示传输的结束,并且提供计算机校正时钟同步的机会。适用于停止位的位数越多,不同时钟同步的容忍程度越大,但是数据传输率同时也越慢。
奇偶校验位:在串口通信中一种简单的检错方式。有四种检错方式:偶、奇、高和低。当然没有校验位也是可以的。对于偶和奇校验的情况,串口会设置校验位(数据位后面的一位),用一个值确保传输的数据有偶个或者奇个逻辑高位。例如,如果数据是011,那么对于偶校验,校验位为0,保证逻辑高的位数是偶数个。如果是奇校验,校验位位1,这样就有3个逻辑高位。高位和低位不真正的检查数据,简单置位逻辑高或者逻辑低校验。这样使得接收设备能够知道一个位的状态,有机会判断是否有噪声干扰了通信或者是否传输和接收数据是否不同步。
第14篇:串口转网口TCPIP RS232转以太网串口服务器致力于油田生产
串口转网口TCP/IP RS232转以太网串口服务器致力于油田生产
在石油的开采、储运等生产过程中,动态监测是生产管理的重要工作内容,也是保证油田正常、安全、经济运行的重要手段,在西方发达国家自动化数据采集与控制(SCADA)已经成为生产的配套设施。
动态监测的主要内容包括泄漏监测、压力超高保护、温度异常、含水超标等。油田被称为“没有围墙的工厂”,油井、集输站、联合站星罗棋布,偏远分散,而石油的整个生产流程又通过管道连接起来,成为一个压力系统,可谓牵一发而动全身,特别是泄漏事故时有发生,给油田造成巨大的经济损失和环境污染。因此,实现油田生产系统的动态监测,对于及时发现泄漏等故障、优化生产运行参数、减少盗油犯罪案件的发生、提高油田的现代化管理水平等具有重要的意义。
一、油田数据采集系统的需求
为实现油田生产的监控,生产调度中心需要实时得到各站的压力、温度、流量等数据,从而进行数据分析,得到生产能耗指标情况和生产运行状况,如对于长距离输油管道,就需要实时得到管道进出口的压力数据,由泄漏监测报警系统软件即可进行泄漏报警和泄漏点的定位。
简短地说,数据采集系统主要包括数据采集与通信两个方面的内容。
1.串口仪表设备在数据采集系统中应用广泛
在基于计算机的数据采集系统中,通过485总线方式连接计算机串口是相当流行的数据采集方式,串口输出的仪表设备得到了广泛的应用。很多时候,自动化工程师会遇到PC机中的插槽数量超过了实际能够有的数量,使用串行接口来连接测量与自动化设备,摆脱了对计算机内部ISA或PCI插槽的额外硬件要求。
RS-485总线是用一对简单的双绞线构成分布式系统,通过RS485-RS232转换即可连入计算机,实现多点、双向通信和数据采集,设备简单,价格低廉,它所具有的噪声抑制能力、数据传输速率、电缆长度及可靠性是其他标准无法比拟的。正因为此,RS-485在工业数据采集与控制、仪器仪表、汽车电子、电信设备等领域得到广泛应用。
2.以太网/互联网已成为油田数据传输的主要途径
近年来,Internet在全世界范围内发展迅猛,作为Internet的核心技术TCP/IP也越来越被大家所熟悉,基于TCP/IP的www.xiexiebang.com5110调试使用说明
CN5110使用及调试说明
CN-5110是一款为串口联网而设计的一种简约的快捷设备。它的主要特点如下:
轻松安装和简易设定 价格低廉;信用卡般大小 立即使您的串口设备联网
点对点连接模式,可在不使用PC的情况下经由网络连接两个串口设备 可利用简单易用的windows Utility 执行大量安装 自动自测 10/100Mbps Ethernet 所有串口信号皆内建15KV ESD突波保护 支持SNMP MIB-II网管功能
可通过网络/TELNET/控制器端口进行配置
配置工具可在网络上自动寻找Nport设备联网服务器
安装步骤:
1、首先打开Nport Administrator管理软件
主界面
2、对网内的CN5110进行广播检测
3、若网内按有N5110设备,则会检测到此设备的IP地址及MAC Addre。广播结束后可关闭此窗口。
4、在主界面右边的窗口中就会看到刚刚广播到的CN510
5、双击刚刚检测到的设备名称进入设置对话框。在Basic选项卡中可以设置5110的名称及时钟。
6、在Network选项卡中可以设置5110的IP地址,子网掩码及网关。
7、在Paword选项卡中可以设置进入设置选项的密码提示。设置完毕后按OK键确定并退出。
8、回到主界面,在左边的树型目录中选”COM mapping” COM口映射选项,此时系统已自动为你刚刚检测到的5110映射好了COM口。
9、进入设置界面,在设置界面中也可以为5110手动设置一个COM口,并为其配置相关串口通信的参数。设置完毕后,按OK键确定并退出。
10、回到主界面,目前为止已经为新的5110虚拟了一个新的串口。在快捷键按钮中选择”Apply”对以上所有设置进行保存。
11、若在前面的设置中对CN5110进行了密码设置,下次进入设置界面时需首先对5110进行解锁。
12、选择你要解锁的5110,然后选择菜单->Configuration->Unlock->输入密码
第17篇:嵌入式串口和网络编程实验报告
嵌入式实验报告
题目:linux
串口和网络编程
一、实验目的:
1、强化本学期所学的相关的内容。
2、掌握串口相关设置。
3、强化基于TCP网络传输的三次握手。
4、自学Linux线程的使用。
二、实验内容:
本试验基于server和client的透明传输来实现类似于QQ的聊天功能。
三、实验过程:
1、linux开发环境的建立
2、嵌入式linux系统的搭建
1>BootLoader的移植
2>linux系统的裁剪与移植 Linux内核裁剪
./make_image生成自己的uImage2638
上电验证:
3>根文件系统的移植 修改hostname为:whmtt
./mkcramfsdisk_new 生成rootfs_new.cramfs
大小从老师给的40000到37b00(因为有的没有用到,大小变小了):
上电验证:
3、客服端编程client.c 相关代码: #include #include #include #include #include #include #include #include
#define SERVER_PORT 20000 //设置服务端口
#define CLIENT_PORT((20001+rand())%65536)//设置客户端端口(随机)#define BUFFER_SIZE 256 #define LENGTH_OF_LISTEN_QUEUE 10 //可窃听队列长为10 #define WELCOME_MESSAGE "welcome to connect the server."
void usage(char* name){ printf("usage: %s IpAddrn " ,name);}
struct sockaddr_in servaddr,cliaddr;int servfd,clifd,length=0;struct sockaddr_in servaddr,cliaddr;socklen_t socklen=sizeof(servaddr);char buf[BUFFER_SIZE],buf2[BUFFER_SIZE];pthread_t tidp,tidp2;int pth;int runflag=0;
void *Thread1(void *arg)/*等待runflag为1,当为1时清空buf,同时接收来自server的数据并输出。
但当没有清空,则break.*/ { while(runflag){
memset(buf,0,BUFFER_SIZE);
length=recv(clifd,buf,BUFFER_SIZE,0);
if(strstr(buf,"$")>0){runflag=0;printf("stop!n");break;}
if(length>0)printf("from server:%s",buf);
} }
void *Thread2(void *arg)/*等待发送数据给Server*/ { printf("Please input your words to Server:--$ to stopn");while(runflag){
memset(buf2,0,BUFFER_SIZE);
scanf("%s",buf2);
send(clifd,buf2,strlen(buf2),0);
if(strstr(buf2,"$")>0){runflag=0;printf("stop!n");break;}
} }
int main(int argc, char** argv){ if(argc
usage(argv[0]);
exit(1);} if((clifd = socket(AF_INET,SOCK_STREAM,0))
printf(" create socket error!n ");
exit(1);}
srand(time(NULL));// initialize random generator
bzero(& cliaddr, sizeof(cliaddr));cliaddr.sin_family = AF_INET;cliaddr.sin_port = htons(CLIENT_PORT);cliaddr.sin_addr.s_addr = htons(INADDR_ANY);
if(bind(clifd,(struct sockaddr*)&cliaddr,sizeof(cliaddr))
printf("bind to port %d failure!n " ,CLIENT_PORT);
exit(1);}//绑定的目的是让其端口是随机的,否则端口是自增1 //一般情况下client端不用绑定
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;inet_aton(argv[1], &servaddr.sin_addr);servaddr.sin_port = htons(SERVER_PORT);
if(connect(clifd,(struct sockaddr *)&servaddr, socklen)
printf("can't connect to %s!n", argv[1]);
exit(1);}
runflag=1;
pth=pthread_create(&tidp,NULL,Thread1,NULL);
if(pth!=0){printf("error!");return-1;}
pth=pthread_create(&tidp2,NULL,Thread2,NULL);
if(pth!=0){printf("error!");return-1;}
pthread_detach(tidp);
pthread_detach(tidp2);
while(runflag){;}
close(clifd);
return 0;}
4、服务端server.c编写
相关代码: #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include
#define COM0 0 #define BLOCK_MODE 1 #define NONBLK_MODE 0 #define SERVER_PORT 20000 #define LENGTH_OF_LISTEN_QUEUE 10 #define QUEUE 20 #define BUFFER_SIZE 256 #define WELCOME_MESSAGE "welcome to connect the server."
static struct termios g_newtio,g_oldtio;
static int speed_arr[] = { B115200, B57600, B38400, B19200, B9600, B4800, B2400, B1200, B300, B115200, B57600, B38400, B19200, B9600, B4800, B2400, B1200, B300, };
static int name_arr[] = { 115200, 57600, 38400, 19200, 9600, 4800, 2400, 1200, 300, 115200, 57600, 38400, 19200, 9600, 4800, 2400, 1200, 300, };
int Init_COM(int comm,int Baudrate,int Parity,int Stopbit,int Flagblock){ int ret,i;char dev_buf[16];
if(comm > 3){
printf("com%d not existn",comm);
return-1;}
memset(dev_buf,0x00,sizeof(dev_buf));sprintf(dev_buf,"/dev/ttyS%d",comm);
if(Flagblock){
ret = open(dev_buf, O_RDWR | O_NOCTTY);//以默认阻塞方式打开
} else {
ret = open(dev_buf, O_RDWR | O_NOCTTY | O_NONBLOCK);//以非阻塞方式打开
}
if(ret
printf("Open ttyS%d failedn",comm);
return-1;
}
if(tcgetattr(ret, &g_oldtio)
{
printf("Get com Parameter Error.n");
return-1;}
for(i= 0;i
if(Baudrate == name_arr[i])
{
cfsetispeed(&g_newtio,speed_arr[i]);/*设置输入输出波特率*/
cfsetospeed(&g_newtio,speed_arr[i]);
break;
} }
if(i>=sizeof(speed_arr)/ sizeof(int)){
printf("Unsupported Speed!n");
return-1;}
switch(Parity){
case 'n':
case 'N':
g_newtio.c_cflag &= ~PARODD;
g_newtio.c_cflag &= ~PARENB;
break;
case 'o':
case 'O':
g_newtio.c_cflag |= PARENB;
g_newtio.c_cflag |= PARODD;//奇校验
break;
case 'e':
case 'E':
g_newtio.c_cflag |= PARENB;//偶校验
g_newtio.c_cflag &= ~PARODD;
break;
default:
printf("Unsupported Parityn");
return-1;}
switch(Stopbit)//设置停止校验位是为2,否为1.{
case 1:
g_newtio.c_cflag &= ~CSTOPB;
break;
case 2:
g_newtio.c_cflag |= CSTOPB;
break;
default:
printf("Unsupported Stopbit!n");
return-1;} g_newtio.c_iflag = 0;g_newtio.c_oflag = 0;g_newtio.c_lflag = 0;
g_newtio.c_cc[VTIME] = 1;//最大等待时间为1*100ms g_newtio.c_cc[VMIN] = 1;//最小读数为1
g_newtio.c_iflag &= ~INPCK;g_newtio.c_cflag &= ~CRTSCTS;g_newtio.c_cflag &= ~CSIZE;//设置数据位
g_newtio.c_cflag |= CS8;// g_newtio.c_cflag |= CLOCAL;g_newtio.c_cflag |= CREAD;
if(tcsetattr(ret, TCSANOW, &g_newtio)!= 0)//激活设置
{
printf("Set com Parameter Error!n");
return-1;}
tcflush(ret, TCIOFLUSH);//刷新输入输出缓存
return ret;}
//以上为套接字的相关定义
//一下类似与client一样设置数据接收和发送。
void RestorecomConfiguration(int fd,struct termios *ptios){ if(tcsetattr(fd, TCSANOW, ptios)!= 0){
printf("Restore com Parameter Error!n");} }
int fd;char buf[1024],buf2[1024];int servfd,clifd;
struct sockaddr_in servaddr,cliaddr;int runflag=0;
void *Thread1(void *arg){ printf("Please input your words to Server:--$ to stopn");while(runflag){
memset(buf,0,BUFFER_SIZE);
read(fd,buf,1024);
send(clifd,buf,strlen(buf),0);
if(strstr(buf,"$")>0){runflag=0;printf("stop!n");break;}
} }
void *Thread2(void *arg){ int length=0;while(runflag){char stdstr[1024]="from client:";
memset(buf2,0,BUFFER_SIZE);
length=recv(clifd,buf2,1024,0);if(length>0){
strcat(stdstr,buf2);strcat(stdstr,"n");
if(strstr(buf2,"$")>0)
{runflag=0;printf("stop!n");break;}
write(fd,stdstr,strlen(stdstr));
}
}
} void socket_init(void){ if((servfd=socket(AF_INET,SOCK_STREAM,0))= 0)RestorecomConfiguration(fd,&g_oldtio);
runflag=1;
pth=pthread_create(&tidp,NULL,Thread1,NULL);
if(pth!=0){printf("error!");return-1;}
pth=pthread_create(&tidp2,NULL,Thread2,NULL);
if(pth!=0){printf("error!");return-1;}
pthread_detach(tidp);
pthread_detach(tidp2);
while(runflag){;}
close(clifd);close(fd);close(servfd);//全部关闭
return 0;} 编译结果:
5、nfs挂载
四、实验结果:
五、心得体会:
