Linux下 QT串口与51单片机通信实例
51单片机的串口通信程序(C语言)
51单片机的串口通信程序(C语言) 51单片机的串口通信程序(C语言)在嵌入式系统中,串口通信是一种常见的数据传输方式,也是单片机与外部设备进行通信的重要手段之一。
本文将介绍使用C语言编写51单片机的串口通信程序。
1. 硬件准备在开始编写串口通信程序之前,需要准备好相应的硬件设备。
首先,我们需要一块51单片机开发板,内置了串口通信功能。
另外,我们还需要连接一个与单片机通信的外部设备,例如计算机或其他单片机。
2. 引入头文件在C语言中,我们需要引入相应的头文件来使用串口通信相关的函数。
在51单片机中,我们需要引入reg51.h头文件,以便使用单片机的寄存器操作相关函数。
同时,我们还需要引入头文件来定义串口通信的相关寄存器。
3. 配置串口参数在使用串口通信之前,我们需要配置串口的参数,例如波特率、数据位、停止位等。
这些参数的配置需要根据实际需要进行调整。
在51单片机中,我们可以通过写入相应的寄存器来配置串口参数。
4. 初始化串口在配置完串口参数之后,我们需要初始化串口,以便开始进行数据的发送和接收。
初始化串口的过程包括打开串口、设置中断等。
5. 数据发送在串口通信中,数据的发送通常分为两种方式:阻塞发送和非阻塞发送。
阻塞发送是指程序在发送完数据之后才会继续执行下面的代码,而非阻塞发送是指程序在发送数据的同时可以继续执行其他代码。
6. 数据接收数据的接收与数据的发送类似,同样有阻塞接收和非阻塞接收两种方式。
在接收数据时,需要不断地检测是否有数据到达,并及时进行处理。
7. 中断处理在串口通信中,中断是一种常见的处理方式。
通过使用中断,可以及时地响应串口数据的到达或者发送完成等事件,提高程序的处理效率。
8. 串口通信实例下面是一个简单的串口通信实例,用于在51单片机与计算机之间进行数据的传输。
```c#include <reg51.h>#include <stdio.h>#define BAUDRATE 9600#define FOSC 11059200void UART_init(){TMOD = 0x20; // 设置定时器1为模式2SCON = 0x50; // 设置串口为模式1,允许接收TH1 = 256 - FOSC / 12 / 32 / BAUDRATE; // 计算波特率定时器重载值TR1 = 1; // 启动定时器1EA = 1; // 允许中断ES = 1; // 允许串口中断}void UART_send_byte(unsigned char byte){SBUF = byte;while (!TI); // 等待发送完成TI = 0; // 清除发送完成标志位}unsigned char UART_receive_byte(){while (!RI); // 等待接收完成RI = 0; // 清除接收完成标志位return SBUF;}void UART_send_string(char *s){while (*s){UART_send_byte(*s);s++;}}void main(){UART_init();UART_send_string("Hello, World!"); while (1){unsigned char data = UART_receive_byte();// 对接收到的数据进行处理}}```总结:通过以上步骤,我们可以编写出简单的51单片机串口通信程序。
51单片机串口通信实例
51单片机串口通信实例一、原理简介51 单片机内部有一个全双工串行接口。
什么叫全双工串口呢?一般来说,只能接受或只能发送的称为单工串行;既可接收又可发送,但不能同时进行的称为半双工;能同时接收和发送的串行口称为全双工串行口。
串行通信是指数据一位一位地按顺序传送的通信方式,其突出优点是只需一根传输线,可大大降低硬件成本,适合远距离通信。
其缺点是传输速度较低。
与之前一样,首先我们来了解单片机串口相关的寄存器。
SBUF 寄存器:它是两个在物理上独立的接收、发送缓冲器,可同时发送、接收数据,可通过指令对SBUF 的读写来区别是对接收缓冲器的操作还是对发送缓冲器的操作。
从而控制外部两条独立的收发信号线RXD(P3.0)、TXD(P3.1),同时发送、接收数据,实现全双工。
串行口控制寄存器SCON(见表1) 。
表1 SCON寄存器表中各位(从左至右为从高位到低位)含义如下。
SM0 和SM1 :串行口工作方式控制位,其定义如表2 所示。
经验分享:学习单片机重要的是实践,所以开发板是很重要,给大家推荐些淘宝上信誉良好并且软硬件及小零件等、售前售后服务良好的皇冠级金钻店铺给大家,在硬件购买上少走弯路。
按住Ctrl键单击即可:慧净电子单片机(一皇冠)【天津商盟】天津锐志(电子)单片机经营部(两皇冠)金沙滩工作室(5钻)深圳育松电子元件,模块,传感器,批发部:淘宝最全最平价(5皇冠)志宏电子(4钻)表2 串行口工作方式控制位其中,fOSC 为单片机的时钟频率;波特率指串行口每秒钟发送(或接收)的位数。
SM2 :多机通信控制位。
该仅用于方式2 和方式3 的多机通信。
其中发送机SM2 = 1(需要程序控制设置)。
接收机的串行口工作于方式2 或3,SM2=1 时,只有当接收到第9 位数据(RB8)为1 时,才把接收到的前8 位数据送入SBUF,且置位RI 发出中断申请引发串行接收中断,否则会将接受到的数据放弃。
当SM2=0 时,就不管第位数据是0 还是1,都将数据送入SBUF,并置位RI 发出中断申请。
两个单片机间串口通讯
}
while(temp!=0xf0)
{
temp=P2;
temp=temp&0xf0;
}
send(num);
}
}
}
void main()
{
TMOD=0x20;//设置定时器1为工作方式2
TH1=0xfd;//装初值设置波特率
TL1=0xfd;
TR1=1;//打开定时器1
SM0=0;//8位异步收发
单片机间通讯
作者:冉纯雷
1.程序设计
发送程序:
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
uchar num,temp;
void delay(uint z)//延时函数
{
uint x,y;
for(x=z;x>0;x--)
temp=P2;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P2;
switch(temp)
{
case 0xee:num=16;
break;
case 0xde:num=12;
break;
case 0xbe:num=8;
break;
case 0x7e:num=4;
break;
}
{
delay(5);
temp=P2;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P2;
switch(temp)
{
case 0xe7:num=13;
linux下的串口通信原理及编程实例
linux下的串⼝通信原理及编程实例linux下的串⼝通信原理及编程实例⼀、串⼝的基本原理1 串⼝通讯串⼝通讯(Serial Communication),是指外设和计算机间,通过数据信号线、地线等,按位进⾏传输数据的⼀种通讯⽅式。
串⼝是⼀种接⼝标准,它规定了接⼝的电⽓标准,没有规定接⼝插件电缆以及使⽤的协议。
2 串⼝通讯的数据格式 ⼀个字符⼀个字符地传输,每个字符⼀位⼀位地传输,并且传输⼀个字符时,总是以“起始位”开始,以“停⽌位”结束,字符之间没有固定的时间间隔要求。
每⼀个字符的前⾯都有⼀位起始位(低电平),字符本⾝由7位数据位组成,接着字符后⾯是⼀位校验位(检验位可以是奇校验、偶校验或⽆校验位),最后是⼀位或⼀位半或⼆位停⽌位,停⽌位后⾯是不定长的空闲位,停⽌位和空闲位都规定为⾼电平。
实际传输时每⼀位的信号宽度与波特率有关,波特率越⾼,宽度越⼩,在进⾏传输之前,双⽅⼀定要使⽤同⼀个波特率设置。
3 通讯⽅式单⼯模式(Simplex Communication)的数据传输是单向的。
通信双⽅中,⼀⽅固定为发送端,⼀⽅则固定为接收端。
信息只能沿⼀个⽅向传输,使⽤⼀根传输线。
半双⼯模式(Half Duplex)通信使⽤同⼀根传输线,既可以发送数据⼜可以接收数据,但不能同时进⾏发送和接收。
数据传输允许数据在两个⽅向上传输,但是,在任何时刻只能由其中的⼀⽅发送数据,另⼀⽅接收数据。
因此半双⼯模式既可以使⽤⼀条数据线,也可以使⽤两条数据线。
半双⼯通信中每端需有⼀个收发切换电⼦开关,通过切换来决定数据向哪个⽅向传输。
因为有切换,所以会产⽣时间延迟,信息传输效率低些。
全双⼯模式(Full Duplex)通信允许数据同时在两个⽅向上传输。
因此,全双⼯通信是两个单⼯通信⽅式的结合,它要求发送设备和接收设备都有独⽴的接收和发送能⼒。
在全双⼯模式中,每⼀端都有发送器和接收器,有两条传输线,信息传输效率⾼。
显然,在其它参数都⼀样的情况下,全双⼯⽐半双⼯传输速度要快,效率要⾼。
Linux串口通信编程
2) 设置属性:奇偶校验位、数据位、停止位。
主要设置<termbits.h>中的termios3) 打开、关闭和读写串口。
串口作为设备文件,可以直接用文件描述符来进行网上的一个例子:/*串口设备无论是在工控领域,还是在嵌入式设备领域,应用都非常广泛。
而串口编程也就显得必不可少。
偶然的一次机会,需要使用串口,而且操作系统还要求是Linux,因此,趁着这次机会,综合别人的代码,进行了一次整理和封装。
具体的封装格式为C代码,这样做是为了很好的移植性,使它可以在C和C++环境下,都可以编译和使用。
代码的头文件如下: *//////////////////////////////////////////////////////////////////// //////////////filename:stty.h#ifndef__STTY_H__#define__STTY_H__//包含头文件#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<pthread.h>//// 串口设备信息结构typedef struct tty_info_t{int fd;// 串口设备IDpthread_mutex_t mt;// 线程同步互斥对象char name[24];// 串口设备名称,例:"/dev/ttyS0"struct termios ntm;// 新的串口设备选项struct termios otm;// 旧的串口设备选项}TTY_INFO;//// 串口操作函数TTY_INFO *readyTTY(int id);int setTTYSpeed(TTY_INFO *ptty,int speed);int setTTYParity(TTY_INFO *ptty,int databits,int parity,int st opbits);int cleanTTY(TTY_INFO *ptty);int sendnTTY(TTY_INFO *ptty,char*pbuf,int size);int recvnTTY(TTY_INFO *ptty,char*pbuf,int size);int lockTTY(TTY_INFO *ptty);int unlockTTY(TTY_INFO *ptty);#endif/*从头文件中的函数定义不难看出,函数的功能,使用过程如下:(1)打开串口设备,调用函数setTTYSpeed();(2)设置串口读写的波特率,调用函数setTTYSpeed();(3)设置串口的属性,包括停止位、校验位、数据位等,调用函数setTTYParity ();(4)向串口写入数据,调用函数sendnTTY();(5)从串口读出数据,调用函数recvnTTY();(6)操作完成后,需要调用函数cleanTTY()来释放申请的串口信息接口;其中,lockTTY()和unlockTTY()是为了能够在多线程中使用。
51单片机串口通信(相关例程)
51单片机串口通信(相关例程) 51单片机串口通信(相关例程)一、简介51单片机是一种常用的微控制器,它具有体积小、功耗低、易于编程等特点,被广泛应用于各种电子设备和嵌入式系统中。
串口通信是51单片机的常见应用之一,通过串口通信,可以使单片机与其他外部设备进行数据交互和通信。
本文将介绍51单片机串口通信的相关例程,并提供一些实用的编程代码。
二、串口通信基础知识1. 串口通信原理串口通信是通过串行数据传输的方式,在数据传输过程中,将信息分为一个个字节进行传输。
在51单片机中,常用的串口通信标准包括RS232、RS485等。
其中,RS232是一种常用的串口标准,具有常见的DB-9或DB-25连接器。
2. 串口通信参数在进行串口通信时,需要设置一些参数,如波特率、数据位、停止位和校验位等。
波特率表示在单位时间内传输的比特数,常见的波特率有9600、115200等。
数据位表示每个数据字节中的位数,一般为8位。
停止位表示停止数据传输的时间,常用的停止位有1位和2位。
校验位用于数据传输的错误检测和纠正。
三、串口通信例程介绍下面是几个常见的51单片机串口通信的例程,提供给读者参考和学习:1. 串口发送数据```C#include <reg51.h>void UART_Init(){TMOD = 0x20; // 设置计数器1为工作方式2(8位自动重装) TH1 = 0xFD; // 设置波特率为9600SCON = 0x50; // 设置串口工作方式1,允许串行接收TR1 = 1; // 启动计数器1}void UART_SendChar(unsigned char dat){SBUF = dat; // 发送数据while (!TI); // 等待发送完成TI = 0; // 清除发送完成标志}void main(){UART_Init(); // 初始化串口while (1){UART_SendChar('A'); // 发送字母A}}```2. 串口接收数据```C#include <reg51.h>void UART_Init(){TMOD = 0x20; // 设置计数器1为工作方式2(8位自动重装) TH1 = 0xFD; // 设置波特率为9600SCON = 0x50; // 设置串口工作方式1,允许串行接收TR1 = 1; // 启动计数器1}void UART_Recv(){unsigned char dat;if (RI) // 检测是否接收到数据{dat = SBUF; // 读取接收到的数据 RI = 0; // 清除接收中断标志// 处理接收到的数据}}void main(){UART_Init(); // 初始化串口EA = 1; // 允许中断ES = 1; // 允许串口中断while (1)// 主循环处理其他任务}}```3. 串口发送字符串```C#include <reg51.h>void UART_Init(){TMOD = 0x20; // 设置计数器1为工作方式2(8位自动重装) TH1 = 0xFD; // 设置波特率为9600SCON = 0x50; // 设置串口工作方式1,允许串行接收TR1 = 1; // 启动计数器1}void UART_SendString(unsigned char *str){while (*str != '\0')SBUF = *str; // 逐个发送字符while (!TI); // 等待发送完成TI = 0; // 清除发送完成标志str++; // 指针指向下一个字符}}void main(){UART_Init(); // 初始化串口while (1){UART_SendString("Hello, World!"); // 发送字符串}}```四、总结本文介绍了51单片机串口通信的基础知识和相关编程例程,包括串口发送数据、串口接收数据和串口发送字符串。
51单片机串口通信程序。。含详细例子
{ P3_4=0; P3_3=1;
} void RstPro()//编程器复位 {
pw.fpProOver();//直接编程结束 SendData();//通知上位机,表示编程器就绪,可以直接用此函数因为协议号(ComBuf[0])还没被修改,下同 }
void ReadSign()//读特征字 {
} void serial () interrupt 4 using 3 //串口接收中断函数 {
if (RI) { RI = 0 ; ch=SBUF; read_flag= 1 ; //就置位取数标志 }
} main()
{ init_serialcom(); //初始化串口 while ( 1 ) { if (read_flag) //如果取数标志已置位,就将读到的数从串口发出 { read_flag= 0 ; //取数标志清 0 send_char_com(ch); } }
while(RI == 0); RI = 0; c = SBUF; // 从缓冲区中把接收的字符放入 c 中 SBUF = c; // 要发送的字符放入缓冲区 while(TI == 0); TI = 0; } }
4.//////////////// /////////////////////////////////////////////////////////
SendData(); } else break;//等待回应失败 } pw.fpProOver();//操作结束设置为运行状态 ComBuf[0]=0;//通知上位机编程器进入就绪状态 SendData(); }
void Lock()//写锁定位
{
pw.fpLock();
SendData();
51单片机与串口通信代码
51单片机与串口通信代码串口调试1. 发送:向总线上发命令2. 接收:从总线接收命令,并分析是地址还是数据。
3. 定时发送:从内存中取数并向主机发送.经过调试,以上功能基本实现,目前可以通过上位机对单片机进行实时控制。
程序如下://这是一个单片机C51串口接收(中断)和发送例程,可以用来测试51单片机的中断接收//和查询发送,另外我觉得发送没有必要用中断,因为程序的开销是一样的#i nclude <reg51.h>#i nclude<stdio.h>#i nclude <string.h>#define INBUF_LEN 4 //数据长度unsigned char inbuf1[INBUF_LEN];unsigned char checksum,count3 , flag,temp,ch;bit read_flag=0;sbit cp=P1^1;sbit DIR=P1^2;int i;unsigned int xdata *RAMDATA; /*定义RAM地址指针*/unsigned char a[6] ={0x11,0x22,0x33,0x44,0x55,0x66} ;void init_serialcomm(void){SCON=0x50; //在11.0592MHz下,设置串行口波特率为9600,方式1,并允许接收PCON=0x00;ES=1;TMOD=0x21; //定时器工作于方式2,自动装载方式 TH0=(65536-1000)%256;TL0=(65536-1000)/256;TL1=0xfd;TH1=0xfd;ET0=1;TR0=1;TR1=1;// TI=0;EA=1;// TI=1;RAMDATA=0x1F45;}void serial () interrupt 4 using 3{if(RI){ RI=0;ch=SBUF;TI=1; //置SBUF空switch(ch){case 0x01 :printf("A"); TI=0;break;case 0x02 :printf("B"); TI=0;break;case 0x03 :printf("C"); TI=0;break;case 0x04 :printf("D"); TI=0;break; default :printf("fg"); TI=0;break; }}}//向串口发送一个字符void timer0() interrupt 1 using 3{// char i;flag++;TH0=0x00;TL0=0x00;if(flag==10){// cp=!cp;// for(i=0;i<6;i++)P2=0x25;TI=1;temp=*RAMDATA;printf("%c",temp); TI=0;// RAMDATA--;flag=0;}}//主程序main(){init_serialcomm(); //初始化串口//向6264中送数据{*RAMDATA=0x33;}while(1){*RAMDATA=0x33;;}}调试过程中遇到的问题:1. 发送过程:在发送时必须保证TI=1:即发送缓冲器为空,否则将导致数据发不出去,如果想强制发送可以用:TI=1.具体发送数据:利用printf(“akjdfaklfj”);函数直接发送即可。
Qt编写串口通信程序全程图文讲解(大图版)
Qt编写串口通信程序全程图文讲解(一)(原创)首先说明我们的编程环境是windows xp下,在Qt Creator中进行,如果在Linux下或直接用源码编写,程序稍有不同,请自己改动。
在Qt中并没有特定的串口控制类,现在大部分人使用的是第三方写的qextserialport 类,我们这里也是使用的该类。
我们可以去/projects/qextserialport/files/进行下载,也可以去下载论坛上的/bbs/read.php?tid=22847下载到的文件为:qextserialport-1.2win-alpha.zip其内容如下图:我们在windows下只需要使用其中的6个文件:qextserialbase.cpp和qextserialbase.h,qextserialport.cpp和qextserialport.h,win_qextserialport.cpp和win_qextserialport.h如果在Linux下只需将win_qextserialport.cpp和win_qextserialport.h 换为posix_qextserialport.cpp和posix_qextserialport.h即可。
下面我们将讲述详细编程过程,这里我们先给出完整的程序,然后再进行逐句分析。
1.打开Qt Creator,新建Qt4 Gui Application,工程名设置为mycom,其他使用默认选项。
(注意:建立的工程路径不能有中文。
)2.将上面所说的6个文件复制到工程文件夹下,如下图。
3.在工程中添加这6个文件。
在Qt Creator中左侧的文件列表上,鼠标右击工程文件夹,在弹出的菜单中选择Add Existing Files,添加已存在的文件。
如下图:选择工程文件夹里的那6个文件,进行添加。
如下图。
添加好后文件列表如下图所示:4.点击mainwindow.ui,在窗口上加入一个Text Browser,用来显示信息。
基于linux和Qt的串口通信调试器调的设计及应用
基于linux和Qt的串口通信调试器调的设计及应用摘要:目前基于Linux操作系统的应用开发越来越广泛,Qt是一个跨平台的C++图形用户界面应用程序框架,它可以开发基于Linux上的图形应用程序。
Linux操作系统对串行口提供了很好的支持,为了在Linux系统下能让串口与其它硬件设备方便直观地进行通信,本文介绍了在Ubuntu10.10系统平台Qt-4.7及Qt Creator2.0编程环境下串口调试界面的设计及程序的编写。
关键词:串口通信Linux QT1 Qextserialport 类介绍在Qt类库中并没有特定的串口基础类,现在很多人使用的是第三方写的qextserialport类,它是一个跨平台的串口类,可以很方便地在Qt 中对串口进行读写操作。
本文也使用了该类。
文件下载地址: /projects/qextserialport/files/下载到的文件名为qextserialport-1.2win-alpha。
在linux平台中,我们只需用到其中的四个文件:qextserialbase.cpp和qextserialbase.h以及posix_qextserialport.cpp和posix_qextserialport.h。
其中前两个文件定义了一个QextSerialBase 类,它提供了操作串口所必需的一些变量和函数等;后两个文件定义了一个Posix_QextSerialPort 类,Posix_QextSerialPort类添加了Linux平台下操作串口的一些功能。
2 串口的基本设置串口的基本参数在posix_qextserialport.cpp文件里的构造函数中进行设置,它的最后一个构造函数:Posix_QextSerialPort::Posix_QextSerialPort(const QString & name, const PortSettings&settings, QextSerialBase::QueryMode mode)它共有3个参数,第一个是串口名,第二个是对串口参数的基本设置,第三个是读取串口的方式。
51单片机的2个串口分别通信的方法
51单片机的2个串口资源分别通信的方法当使用51单片机的2个串口资源进行通信时,比如用一个串口与PLC的串口使用RS485协议通信,一个串口通过蓝牙模块和另一个单片机无线通信时,该如何处理呢?传统的51单片机只有1个串口资源,只能采用分时复用的方法。
STC的15系列增强版51单片机具有多个串口资源,本文将描述如何使用IAP15W4K58S单片机用一个串口资源与PLC的RS485有线通信,另一个串口资源与Arduino单片机通过蓝牙模块无线通信,该通讯连接过程中PLC作为主机,IAP15W4K58S作为中间机,Arduino单片机作为最低层级。
工作过程是按下启动按键,PLC发信息给IAP15W4K58S单片机发高速脉冲控制步进电机驱动的机械臂运动取走货物,当货物取走后,IAP15W4K58S单片机通过蓝牙模块通知Arduino单片机控制的小车将新货物运送过来。
连接结构示意图如下图所示。
本例程使用的单片机型号为:IAP15W4K58S,该单片机有4个采用UART 工作方式的全双工异步串行通信接口(分别为串口1、串口2、串口3和串口4),每个串行口由2个数据缓冲器、1个移位寄存器、1个串行控制寄存器和1个波特率发生器等组成。
本项目使用串行口1和串行口2。
串行口1的两个缓冲器共用寄存器SBUF (99H),串行口2的两个缓冲器共用寄存器S2BUF(9BH)。
10位(1起始位,8位数据位,1停止位)可变波特率(9600)。
串口1对应的硬件部分是TxD和RxD,串行口2对应硬件部分是TxD2和RxD2。
串口1选择引脚P3.0(RxD)和P3.1(TxD),串口2选择引脚P1.0(RxD)和P1.1(TxD)。
串口1既可以选择T1作为波特率发生器,也可以选择T2作为波特率发生器。
本文串口1提供2个选择(T1和T2),串口2只能选择T2作波特率发生器。
但是当串口1和串口2的波特率相同时,可以共用T2作为波特率发器,当T2工作在1T模式时,串行口1的波特率=SYSclk/(65536-[RL_TH2,RL_TL2])/4,SYSclk表示系统时钟频率,[RL_TH2,RL_TL2]表示T2H,T2L的定时初值设置值。
Linux下串口协议控制51单片机
linux下串口协议控制51单片机(涉及多线程操作)/***************************************************************************writen by jingshui 7-17 2011 12:53说明:这是一个linux下串口,多线程测试程序Version 0.26***************************************************************************/ # include <stdio.h># include <unistd.h># include <stdlib.h># include <termios.h># include <fcntl.h># include <string.h># include <sys/time.h># include <sys/types.h># include <pthread.h>int fd;pthread_t thread[2];pthread_mutex_t mutex;/**************************************************************************** 结构体说明:传送控制单片机的信息成员1:select 选择功能模块成员2:control 控制单片机相应的动作*****************************************************************************/ struct protocal{unsigned char select;unsigned char control;};struct protocal ptr[14]={{0xa1,0x01},{0xa1,0x02},{0xa1,0x03},{0xa1,0x04},{0xa1,0x05},{0xa1,0x06},{0xa1,0x07},{0xa1,0x08},{0xb2,0x00},{0xb2,0x03},{0xb2,0x06},{0xb2,0x09},{0xb2,0x0e},{0xc3,0xd4}};/********************************************************************功能说明:设置linux串口参数传入参数:fd nspeed nbit nevent nstop文件句柄波特率数据位奇偶校验停止位返回值: fd 文件句柄********************************************************************/int set_port(int fd ,int nspeed ,int nbits ,char nevent ,int nstop){struct termios newtio,oldtio;if (tcgetattr(fd,&oldtio)!= 0){perror("setup serial");return -1;}bzero(&newtio,sizeof(newtio));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 'N':newtio.c_cflag &= ~PARENB;break;}switch (nspeed){case 9600:cfsetispeed(&newtio,B9600);cfsetospeed(&newtio,B9600);break;}switch (nstop){case 1:newtio.c_cflag &= ~CSTOPB;break;case 2:newtio.c_cflag |= CSTOPB;break;}newtio.c_cc[VTIME]= 0;newtio.c_cc[VMIN]= 14;tcflush(fd,TCIFLUSH);if ((tcsetattr(fd,TCSANOW,&newtio))!= 0){perror("com set");return -1;}return 0;}int open_port(int fd,int comport){if (comport == 1){fd = open ("/dev/ttyUSB0",O_RDWR);if ( -1 == fd ){perror("can't open serial port");return -1;}}return fd;}void write_port(void){int nwrite,i;for (i=0;i<14;i++){nwrite = write(fd,&ptr[i],2);usleep(200000);/*每200ms秒发一次数据*/}}void read_port(void){fd_set rd;int nread,retval;unsigned char msg[14];struct timeval timeout;FD_ZERO(&rd);FD_SET(fd,&rd);_sec = 1;_usec = 0;retval = select (fd+1,&rd,NULL,NULL,&timeout);/*select 实现i/o复用*/ switch (retval){case 0:printf("no data input within 1 seconds.\n");break;case -1:perror("select");break;default:if((nread=read(fd,msg,14))>0){printf("nread=%d,msg=%s\n",nread,msg);}break;}}void *recv_thread(void ){pthread_mutex_lock(&mutex);read_port();pthread_mutex_unlock(&mutex);pthread_exit(NULL);}void *send_thread(void ){pthread_mutex_lock(&mutex);write_port();pthread_mutex_unlock(&mutex);pthread_exit(NULL);}void create_thread(void ){int temp;memset(thread, 0, sizeof(thread));if((temp = pthread_create(&thread[0], NULL,(void *)send_thread, NULL)) != 0) printf("create send_thread failed!\n");if((temp = pthread_create(&thread[1], NULL,(void *)recv_thread, NULL)) != 0) printf("create recev_thread failed!\n");}void wait_thread(void ){if(thread[0] !=0){pthread_join(thread[0],NULL);printf("send_thread end\n");}if(thread[1] !=0){pthread_join(thread[1],NULL);printf("recev_thread end\n");}}int main(void ){int i;if((fd=open_port(fd,1))<0){perror("open_port error");}if((i=set_port(fd,9600,8,'N',1))<0){perror("set_opt error");}/*用默认属性初始化互斥锁*/pthread_mutex_init(&mutex,NULL);int num = 100;while (num){create_thread();wait_thread();num--;}pthread_mutex_destroy(&mutex);close(fd);return 0;}51单片机程序#include <reg52.h>typedef unsigned char uint8;typedef unsigned int uint16;sbit key = P3^2;sbit s1 = P2^0; //选通数码管1sbit s2 = P2^1;sbit s3 = P2^2;sbit s4 = P2^3;sbit en = P2^5; //573锁存使能位sbit buzzer = P2^4; //蜂鸣器选通位sbit key1 = P3^2;sbit key2 = P3^3;sbit key3 = P3^4;sbit key4 = P3^5;sbit key5 = P3^7;uint8 i=0;uint8 r_data[2]; //用来接收数据的缓冲区uint8 code smg[16] = {0xC0,0xF9,0xA4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e}; unsigned char code pmd[8] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};unsigned char code s_data1[]="key1 pressed\n";unsigned char code s_data2[]="key2 pressed\n";unsigned char code s_data3[]="key3 pressed\n";unsigned char code s_data4[]="key4 pressed\n";unsigned char code s_data5[]="key5 pressed\n";void init_serial(void) //初始化串口{TMOD = 0x20; //设置定时器1工作方式1;TH1 = 0xFD; //波特率发生器,产生9600的波特率TL1 = 0xFD;PCON = 0x00;SCON = 0x50; //选择串口工作方式1,允许接收EA = 1; //开中断ES = 1;TR1 = 1; //启动定时器}void delay(uint16 i)//20ms{unsigned char j,k;for(j=i;j>0;j--)for(k=115;k>0;k--);}void test_serial1(void ){int i;EA=0;for(i=0;i<sizeof(s_data1);i++){SBUF=s_data1[i];while(TI==0);TI=0;}EA=1;}void test_serial2(void ){int i;EA=0;for(i=0;i<sizeof(s_data2);i++){SBUF=s_data2[i];while(TI==0);TI=0;}EA=1;}void test_serial3(void ){int i;EA=0;for(i=0;i<sizeof(s_data3);i++){SBUF=s_data3[i];while(TI==0);TI=0;}EA=1;}void test_serial4(void ){int i;EA=0;for(i=0;i<sizeof(s_data4);i++){SBUF=s_data4[i];while(TI==0);TI=0;EA=1;}void test_serial5(void ){int i;EA=0;for(i=0;i<sizeof(s_data5);i++){SBUF=s_data5[i];while(TI==0);TI=0;}EA=1;}void led_control(uint8 i) //led控制模块{unsigned char x;if (i>8){P1 = 0xff;delay(10);}else{x = i-1;P1 = pmd[x];delay(80);P1 = 0xff;}}void seg_control(uint8 i) //数码管控制模块{en = 1;s1 = 0;s3 = 0;s2 = 0;s4 = 0;if (i>0x0f)P0 = 0xff;delay(10);}else{P0 = smg[i];delay(80);P0 = 0xff;}}void buzzer_control(uint8 i) //蜂鸣器控制模块{if (i == 0xd4)buzzer = 0;delay(100);buzzer = 1;}void handle_date(){uint8 i = r_data[0];switch(i){case 0xa1:led_control(r_data[1]);break;case 0xb2:seg_control(r_data[1]);break;case 0xc3:buzzer_control(r_data[1]);default:break;}}void readkey(void){RI=0;if(!key1)delay(30);if(!key1){test_serial1();while(!key1);}}if(!key2){delay(30);if(!key2){test_serial2();while(!key2);}}if(!key3){delay(30);if(!key3){test_serial3();while(!key3);}}if(!key4){delay(30);if(!key4){test_serial4();while(!key4);}}if(!key5){delay(30);if(!key5){test_serial5();while(!key5);}}}void main(void ){init_serial();while(1){readkey();}}void server(void ) interrupt 4{ES = 0;RI = 0;r_data[i] = SBUF;if(2 == ++i){handle_date();i = 0;}ES = 1;}/****************************************************************************** *writen by jingshui说明:51单片机检测程序,把从上位机接收的数据发回去。
linux下Qt通信小结
linux下Qt串口通信小结2011-09-19 15:09由于项目需要,实现在linux下qt串口通信问题,搞了一周,算是实验通过了,记录一下。
主机:ubuntu11.04 qt版本:4.7.2当要实现在linux下qt串口通信时,首先查看qt有没有自带的类,如果有自带的类,实现起来是最方便的,但令人遗憾的时,没有,但可以使用QIOdevice,因为在linux下,万物结文件,但是,我不想用这种方式,太麻烦了,所有的一切都要自己来实现,于是在网上继续查找。
1,就是用网上都在用的yafei linux 的那个linux串口通信全程图文讲解。
这个类第一次看到我很兴奋,因为它太好用了,而且教程一步一步都有解释,对我这种菜鸟再好也不过了,可是网上有很多人说在linux下用这不爽,因为在读串口时,容易使串口连续读而卡死,于是我在犹豫了,继续再找一种方法吧于是就找到了第2中方法2,线程+定时器实现linux下qt串口通信:/blog/static/36491958201041593711817/ 这是链接,我用了一下,能编译通过,可是现在需求有变化了,需要查询程序运行的机器上可以使用的串口总数,以实现自动连接。
于是这中方式就不能完全满足要求了,于是回过头来继续研究yafei linux的那个类,因为里面有个enumerator的类,就是用来满足我的这种需求的。
3,刚开始使用这个类的时候怎么也不能编译通过,我检查语法也没有问题,于是我把enumerator这个类的头文件重新抄写了一遍,什么都没变,神奇的时,编译通过了,qt这个大变态,怎么能这么捉弄人呢,不过看到能编译通过,我还是很欣慰的,于是就调用了enumerator类的getports(),这个方法就是专门用来实现机器上可以使用的串口个数,名称等信息的,等我信心漫漫的等待结果发生时,结果是出现了:给我打印了一句:"Enumeration for POSIX systems is not implemented yet.",跟踪定位发现在enumarator的实现文件的getports()方法中,原来这个类在POSIX系统中还没有实现,这个让我情何以堪啊,我可是搞了几天了。
基于linux (fedora 17)的QT串口通信实例
2.解压下载的文件到当前目录
# unzip qextserialport-1.2win-alpha.zip
这里不对压缩包内的详细信息及qextserialport类的结构做详细介绍,直接说明需要用到的源文件
linux下:
myCom->setParity(PAR_NONE);
//奇偶校验设置,我们设置为无校验
myCom->setStopBits(STOP_1);
//停止位设置,我们设置为1位停止位
myCom->setFlowControl(FLOW_OFF);
//数据流控制设置,我们设置为无数据流控制
ui(new Ui::MainWindow){
ui->setupUi(this);
//myCom = new Win_QextSerialPort("COM1",QextSerialBase::EventDriven);
//【windows下使用】定义串口对象,指定串口名和查询模式,这里使用事件驱动EventDriven
3.打开Qt Creator集成开发环境,新建工程Qt4 Gui Application ,工程名为com ,其他默认即可。
4.将上述linux下需要用到的4个文件拷贝至com工程目录下,然后将该4个文件添加至工程。
5.将整个工程编译,会报错如下:
error: 'struct PortSettings' has no member named 'Timeout_Sec'
qextserialbase.cpp qextserialbase.h posix_qextserialport.cpp posix_qextserialport.h
qtserialport例子
qtserialport例子QtSerialPort是Qt框架中用于串口通信的模块,它提供了一组类和函数,用于在Qt应用程序中实现串口通信功能。
下面将介绍一些使用QtSerialPort的例子。
1. 示例一:打开串口```cppQSerialPort serialPort;serialPort.setPortName("COM1");serialPort.setBaudRate(QSerialPort::Baud9600);serialPort.setDataBits(QSerialPort::Data8);serialPort.setParity(QSerialPort::NoParity);serialPort.setStopBits(QSerialPort::OneStop);serialPort.setFlowControl(QSerialPort::NoFlowControl);if (serialPort.open(QIODevice::ReadWrite)) {qDebug() << "串口打开成功";} else {qDebug() << "串口打开失败";}```2. 示例二:发送数据```cppQByteArray data = "Hello, World!";qint64 bytesWritten = serialPort.write(data);if (bytesWritten == -1) {qDebug() << "数据发送失败";} else {qDebug() << "成功发送" << bytesWritten << "字节的数据"; }```3. 示例三:接收数据```cppconnect(&serialPort, &QSerialPort::readyRead, [&serialPort]() { QByteArray data = serialPort.readAll();qDebug() << "接收到数据:" << data;});```4. 示例四:关闭串口```cppserialPort.close();if (!serialPort.isOpen()) {qDebug() << "串口关闭成功";} else {qDebug() << "串口关闭失败";}```5. 示例五:设置串口参数```cppserialPort.setBaudRate(QSerialPort::Baud115200); serialPort.setDataBits(QSerialPort::Data8);serialPort.setParity(QSerialPort::NoParity);serialPort.setStopBits(QSerialPort::OneStop);serialPort.setFlowControl(QSerialPort::NoFlowControl);```6. 示例六:查询可用串口列表```cppQList<QSerialPortInfo> ports = QSerialPortInfo::availablePorts(); foreach (const QSerialPortInfo &portInfo, ports) {qDebug() << "可用串口:" << portInfo.portName();}```7. 示例七:查询当前串口信息```cppQSerialPortInfo portInfo(serialPort);qDebug() << "串口名:" << portInfo.portName();qDebug() << "描述:" << portInfo.description();qDebug() << "制造商:" << portInfo.manufacturer();qDebug() << "是否为模拟器:" << portInfo.isBusy();```8. 示例八:设置流控制```cppserialPort.setFlowControl(QSerialPort::HardwareControl);```9. 示例九:设置超时时间```cppserialPort.setTimeout(1000);```10. 示例十:清空串口缓冲区```cppserialPort.clear();```以上是一些使用QtSerialPort的例子,通过这些例子可以实现串口的打开、关闭、发送和接收数据等功能。
51单片机串口通信
51单片机串口通信串行口通信是一种在计算机和外部设备之间进行数据传输的通信方式,其中包括了并行通信、RS-232通信、USB通信等。
而在嵌入式系统中,最常见、最重要的通信方式就是单片机串口通信。
本文将详细介绍51单片机串口通信的原理、使用方法以及一些常见问题与解决方法。
一、串口通信的原理串口通信是以字节为单位进行数据传输的。
在串口通信中,数据传输分为两个方向:发送方向和接收方向。
发送方将待发送的数据通过串行转并行电路转换为一组相对应的并行信号,然后通过串口发送给接收方。
接收方在接收到并行信号后,通过串行转并行电路将数据转换为与发送方发送时相对应的数据。
在51单片机中,通过两个寄存器来实现串口通信功能:SBUF寄存器和SCON寄存器。
其中,SBUF寄存器用于存储要发送或接收的数据,而SCON寄存器用于配置串口通信的工作模式。
二、51单片机串口通信的使用方法1. 串口的初始化在使用51单片机进行串口通信之前,需要进行串口的初始化设置。
具体的步骤如下:a. 设置波特率:使用波特率发生器,通过设定计算器的初值和重装值来实现特定的波特率。
b. 串口工作模式选择:设置SCON寄存器,选择串行模式和波特率。
2. 发送数据发送数据的过程可以分为以下几个步骤:a. 将要发送的数据存储在SBUF寄存器中。
b. 等待发送完成,即判断TI(发送中断标志位)是否为1,如果为1,则表示发送完成。
c. 清除TI标志位。
3. 接收数据接收数据的过程可以分为以下几个步骤:a. 等待数据接收完成,即判断RI(接收中断标志位)是否为1,如果为1,则表示接收完成。
b. 将接收到的数据从SBUF寄存器中读取出来。
c. 清除RI标志位。
三、51单片机串口通信的常见问题与解决方法1. 波特率不匹配当发送方和接收方的波特率不一致时,会导致数据传输错误。
解决方法是在初始化时确保两端的波特率设置一致。
2. 数据丢失当发送方连续发送数据时,接收方可能会出现数据丢失的情况。
51单片机C语言应用开发实例精讲8结构实例6:单片机的串口通信
8. 结构实例6:单片机串口通信虽然那个流水灯游戏的可玩性和按键手感问题还值得再好好提升一下,但小月更希望调剂一下,转而开始了对手头烧写板上关于RS-232转换部分的学习。
小月的做法并不难以理解,毕竟与RS-232转换的相关电路在原理图中还是相当显眼的,甚至于他手头编程器的别名就是RS-232转换器。
图8.1 单片机中负责RS-232通讯的电路在烧写器一端与电脑连接的两个接头中,9针的RS-232接口就是串口通信线,而另一个USB口仅接通了+5V和GND,只有给烧写器供电的作用。
这样就可以知道,电脑可以通过RS-232对单片机的内部程序进行改写。
那么,这就意味着单片机与电脑间必然可以进行数据的交换,这种交换,就叫做通信。
所谓串口通信,就是指这种基于RS-232串口的通信方式。
RS-232(ANSI/EIA-232标准)是IBM-PC及其兼容机上的串行连接标准。
最早是为使电脑通过电话线系统相互通信的调制解调器上而是设计的。
后来发展到连接鼠标或打印机上,目前已经被支持设备的即插即用和热插拔功能的USB所替代,但仍广泛的用于工业仪器仪表中,同时也是单片机最基础和最常见的通信方式。
不过要把“最基础和最常见”这两个最拆开来说,就要在后面加上“之一”了。
虽然目前的通信技术日新月异,但这种说法在今后很长一段时期内都是成立的,也正因为这样的特点,STC的51系列单片机都是默认通过RS-232方式进行烧写的。
作为两台设备之间进行的通信,必然需要共同遵守某种规定或规则,包括交流什么、怎样交流及何时交流。
这个规则就是通信协议。
RS-232通信中通信协议的原则就是串口按位(bit)发送和接收数据。
线路上,RS-232通信使用3根线完成,分别是地线、发送、接收。
端口能够在一根线上发送数据的同时在另一根线上接收数据,即全双工传输。
全双工传输是传输制式的一种分类方式中的一类,除此还有单工传输和半双工传输。
单工传输,是指消息只能单方向传输的工作方式。
Qt与单片机通讯协议
《Qt下界面控制与单片机通讯协议》目录一、系统连接测试协议 (1)二、控制LED通讯协议 (2)三、设置实时时钟信息协议 (3)四、获取实时时钟信息协议 (4)五、获取超声波测距协议 (5)六、蜂鸣器报警协议 (6)七、获取按键状态信息协议 (7)八、读取模拟输入通道值协议 (8)一、系统连接测试协议功能:1、检测服务器与客户端连接是否成功指令:第一字节0x01 注【1.1】返回:第一字节注【1.2】0xF1注【1.1】第一字节代表服务器与客户端连接的命令字、【1.2】第一字节代表响应服务器与客户端连接的命令字、二、控制LED连接协议功能:1、通过该协议,控制目标系统中八个LED灯任意一个的点亮或者熄灭。
指令:第一字节第二字节第三字节0x02注【2.1】LED的编码号0x01返回:第一字节第二字节第三字节第四字节0xF2注【2.2】LED的编码号0x01 校验注【2.3】注【2.1】第一字节代表操作目标系统上LED设备的命令字。
第二字节代表八个LED中的编码:编码的取值范围为(1~8),第三个字节代表LED灯的点亮或者熄灭的状态:0x01为亮,0x00为灭。
【2.2】第一字节是响应控制目标系统LED设备,第二字节是响应八个LED中被选定的灯的编码,第三字节是响应被选定灯的点亮或者熄灭。
【2.3】:校验:接收指令第一个字节与返回数据进行异或运算,结果作为校验字节,后续协议,如无特殊说明均为此算法。
例:0xD1 XOR 0x02 XOR 0x00 XOR 0x00 X0R 0x0E=0xDD三、设置时钟信息协议功能:1.设置系统时间指令:第一字节第二字节第三字节第四字节第五字节第六字节第七字节第八字节第九字节0xA3注【3.1】年月日周时分秒指令校验数据:第一字节第二字节第三字节第四字节第五字节第六字节第七字节第八字节第九字节0xA4注【3.2】年月日周时分秒校验注【3.1】:第一字节代表目标系统的命令字:RTC、注【3.2】:第一字节代表响应目标系统中RTC的命令字,第(二~八)字节代表响应设置系统的编码值(依次为年,月,日,周,时,分,秒的编码)。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
QT串口与51单片机通信通过这个小例子主要想说明QT怎样进行线程编程的思想,实例如图,好吧,下面是过程上一个例子我们采用的是手工编写代码的方法,这个例子我们来玩一下designer,其实Qt4己经把界面与功能分开了,用designer来进行界面设计,再手工编写一些功能,如信号与槽,这样开发效率会大大提高,呵呵,开一个终端,输入/usr/local/Trolltech/Qt-4.5.1/bin/designer,如果第一次打开出现字体不对,可以打开qtconfig进行一些相关配置,打开后我们新建一个Main Window,在右边的属性框中设置一下界面大小,1.我ARM板的LCD大小为320x240,所以我也设为320x240;2.左边是一些我们常用的窗口部件,这里我们用到一个lable标签来做显示,再放几个pushButton按钮,在属性objectName重新更改它的名字,改为我们记得的,这样在写功能时记得哪个按钮叫什么名字,对于一个初学QT的人来说,很想知道每一个部件到底有什么信号和槽,别急,我们可以这样来看,选中一个lable,按F4,再点击lable拖动出现接地符号时松开,弹出编辑信号与槽,这时左边列出的是信号,右边为槽,这里我们不用配置连接,等下我们再手工写,3最后我们用到一个lable标签和三个pushButton按钮,并命名为dis_label、writeButton、readButton、closeButton,然后保存为mainwindow.ui,这样designer就完工了,呵呵..4.下面我们编写一个线程,用于管理串口收发工作,它不涉及到任何界面,只做好它的本份工作就得了,编写一个thread.h文件gedit thread.h,#ifndef THREAD_H#define THREAD_H#include<QThread>class Thread:public QThread{Q_OBJECTpublic:Thread();char buf[128];volatile bool stopped;volatile bool write_rs;volatile bool read_rs;protected:virtual void run();};#endif我们定义一个Thread类,它继承于QThread,看到只设有一些变量和一个run函数,virtual表示为虚函数,你也可以去掉,加上去会增加一些内存开销,但提高了效率,对于这个小程序是看不出什么效果的,volatile这个大家都懂了吧,就是防止偷懒,呵呵,5.再看看thread.cpp#include"thread.h"#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <termios.h> //串口用到的#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <strings.h>#define BAUDRATE B9600//#define RS_DEVICE "/dev/ttyS0" //串口1#define RS_DEVICE "/dev/ttySAC1" //串口1Thread::Thread(){} //析构void Thread::run() //这就是线程的具体工作了int fd,c=0,res;struct termios oldtio,newtio; //termios结构是用来保存波特率、字符大小等printf("start...\n");fd=open(RS_DEVICE,O_RDWR|O_NOCTTY); //以读写方式打开串口。
不控制TTYif(fd<0){perror("error");exit(1); //失败退出}printf("Open...\n");tcgetattr(fd,&oldtio); //保存当前设置到oldtiobzero(&newtio,sizeof(newtio)); //清除newtio结构,并重新对它的成员设置如下newtio.c_cflag=BAUDRATE|CS8|CLOCAL|CREAD; //9600、8位、忽略DCD信号、启用接收装置newtio.c_iflag|=IGNPAR; //忽略奇偶newtio.c_oflag=0;newtio.c_lflag=0;newtio.c_cc[VMIN]=0;newtio.c_cc[VTIME]=100; //在规定时间(VTIME)内读取(VMIN)个字符;tcflush(fd,TCIFLUSH); //清除所有队列在串口的输入与输出;tcsetattr(fd,TCSANOW,&newtio); //把我们的设置写入termioswhile(stopped) //stopped为0时将退出线程{if(write_rs) //write_rs为1时把字符串从串口中输出{write_rs=0;write(fd,"QtEmbedded-4.5.1",16);}if(read_rs) //read_rs为1时读取,并存在buf{read_rs=0;res=read(fd,buf,10);buf[res]=0;emit finished(); //读完后发一个信号}}printf("Close...\n");tcsetattr(fd,TCSANOW,&oldtio); //重新设置回原来的close(fd);quit();}QT有terminated()和wait函数来停止或暂停线程,为什么不用呢,具书上说会造成阻塞什么的,呵呵,我也不懂,所以我就用stopped变量来控制,让它死循环在那里,其它我已经在注释上说明了,应该没什么问题了吧,没有的话再写一个.6.mainwindow.h#ifndef MAINWINDOW_H#define MAINWINDOW_H#include<QtGui>#include"ui_mainwindow.h" //奇怪?这个头文件从哪里来的?呵呵,刚才用designer做的mainwindow.ui文件,经过make后会生成这个头文件,#include"thread.h" //把我们前面定义的线程包含进来class MainWindow:public QMainWindow,public Ui::MainWindow //多继承{Q_OBJECTpublic:MainWindow(QWidget *parent=0);public slots:void writeThread();void readThread();void closeThread();void display();private:Thread *yy;};#endifMainWindow继承于QMainWindow和MainWindow,即多继承,对于不是很复杂的程序,用多继承是一个较好的方法,如果程序较复杂,还是用单继承了,我们再看一下mainwindow.cpp,看这些槽具有什么功能:#include"mainwindow.h"MainWindow::MainWindow(QWidget *parent):QMainWindow(parent){setupUi(this);yy = new Thread;yy->start(); //启动线程yy->stopped=1; //初始化变量yy->write_rs=0;yy->read_rs=0;connect(writeButton,SIGNAL(clicked()),this,SLOT(writeThread())); //信号与槽connect(readButton,SIGNAL(clicked()),this,SLOT(readThread()));connect(closeButton,SIGNAL(clicked()),this,SLOT(closeThread()));connect(yy,SIGNAL(finished()),this,SLOT(display())); //前面线程读完了不是发一个信号么,这个信号就是发到这个槽}void MainWindow::display(){dis_label->setText(yy->buf); //读到的在dis_label显示,dis_label就是我们前面designer放的标签,}void MainWindow::writeThread() //前面线程都是根据stopped、write_rs、read_rs的状态来工作的^_^{yy->write_rs=1;}void MainWindow::readThread(){yy->read_rs=1;}void MainWindow::closeThread(){yy->stopped=0;}还差个main.cpp就完工了,哈哈...#include<QApplication>#include"mainwindow.h"int main(int argc,char *argv[]){QApplication app(argc,argv);MainWindow mw;mw.show();return app.exec();}啊!终于完成了,不!这只是完成了ARM这边,还有MCU这边,呵呵,很久不玩单片机了,下面为AT89S51编一个串口程序,并用1602来显示:/**************************************************************//* 三贱客龙& 07机电(1)班*//* 目标器件AT89S51 *//* 晶振11.0592 MHZ *//* 编译环境keil uVsion3 *//* 适用于51综合开发实验板*//**************************************************************//********************** 1602 ********************************//**************一定要关了上拉电阻再下载,有干拢****************/#include <reg51.h>#include <intrins.h>typedef unsigned char BYTE; //类型定义,编译时再处理typedef bit BOOL ; //位/****************串口部份**********************************/unsigned char key_s, key_v, tmp;sbit K1 = P1^4;BOOL flag1=0;BYTE i=0;BYTE z=0;void isr_uart(void); //串口中断服务函数void send_str(); // 传送字串bit scan_key(); // 扫描按键void proc_key(); // 键处理void delayms(unsigned char ms);com_init() //串口初始部分{TMOD = 0x20; // 定时器1工作于8位自动重载模式, 用于产生波特率方式2TH1 = 0xFD; // 波特率9600TL1 = 0xFD;SCON = 0x50; // 设定串行口工作方式为1且没有校验位PCON=0X00; // 波特率不倍增,倍增时为0x80TR1 = 1; // 启动定时器1运行ET1 = 0; // 禁T1定时器产生中断ES=1; //允串口中断EA=1; //开总中断}/****************************串口部分************************************/sbit rs = P2^0; // 寄存器选择sbit rw = P2^1; //读写信号线sbit ep = P2^2; //使能端sbit right = P2^6; //背光char idata display[16] = {"zhilong2382@163"}; //开机时显示的字符串char code str[] = {"xxxI Love you ! "}; //按K1时将发送这个内容,由于前3位对方总是收不到,这里用xxx干掉了,用串口调试助手也一样,delay(BYTE ms){ // 延时子程序BYTE i;while(ms--){for(i = 0; i< 250; i++){_nop_();_nop_();_nop_();_nop_();}}}BOOL lcd_bz() //只检测最高位{ // 测试LCD忙碌状态BOOL result;rs = 0; //指令寄存器rw = 1; //读ep = 1; //接收指令,为下降沿做准备_nop_(); //空语句,延时约1US_nop_();_nop_();_nop_();result = (BOOL)(P0 & 0x80); //取最高位ep = 0; //执行命令return result;}/************** 写入指令数据到LCD **************/lcd_wcmd(BYTE cmd){while(lcd_bz()); //忙时执行空语句rs = 0;rw = 0;ep = 0;_nop_();_nop_();P0 = cmd;_nop_();_nop_();_nop_();_nop_();ep = 1;_nop_();_nop_();_nop_();_nop_();ep = 0;}lcd_pos(BYTE pos){ //设定显示位置lcd_wcmd(pos | 0x80); //指令8}lcd_wdat(BYTE dat) //写入字符显示数据到LCD { //写入要显示的字符串while(lcd_bz()); //读忙rs = 1; //写数据命令rw = 0;ep = 0;P0 = dat;_nop_();_nop_();_nop_();_nop_();ep = 1;_nop_();_nop_();_nop_();_nop_();ep = 0;}lcd_init(){ //LCD初始化设定lcd_wcmd(0x38); //指令6,不检测忙信号delay(1);lcd_wcmd(0x0c); //指令4,显示开/关控制delay(1);lcd_wcmd(0x06); //指令3,输入模式delay(1);lcd_wcmd(0x01); //清除LCD的显示内容delay(1);}/*****************************************main********************************/ main(){BYTE i,j; j=0;right=0; //开背光lcd_init(); // LCDdelay(10);com_init(); // 初始化串口/*************** 显示内容及方式*********************/while(1){if(scan_key()) // 扫描按键第一遍为真{delayms(10); // 延时去抖动if(scan_key()) // 再次扫描{key_v = key_s; // 保存键值proc_key(); // 键处理}}lcd_wcmd(0x01); //清除LCD的显示内容delay(1);lcd_pos(0); // 设置显示位置为第一行的第3个字符i = 0;while(display[i] != '\0') //是否到字符串末尾{ // 显示字符lcd_wdat(display[i]);i++; delay(70);}}}// 扫描按键bit scan_key(){key_s = 0x00;key_s |= K1; //字节与位运算改变的是最低位return(key_s ^ key_v);}// 键处理void proc_key(){if((key_v & 0x01) == 0){ // K1按下TI=1; //send_str(); // 传送字串到PC}}// 每次传送完一串字符void send_str(){unsigned char i = 0;while(str[i] != '\0'){SBUF = str[i];while(!TI); // 等特数据传送,发完后TI=1TI = 0; // 清除数据传送标志i++; // 下一个字符}}// 延时子程序void delayms(unsigned char ms){unsigned char i;while(ms--){for(i = 0; i < 120; i++);}}void isr_uart(void) interrupt 4 //串口服务函数{if(RI==1){ RI=0;display[z]=SBUF;z++;if(z>=16)z=0;}if(TI==1)send_str();}呵呵,这个是我大一时学单片机时弄的,看起来乱乱的,但我保证绝对能用,程序编译后把hex 文件烧到单片机,插上串口线,串口线我是自己做的,注意有直通与交叉之分,一切准备好后,通电...怎么样,当在ARM板上点击write按钮时,将发送QtEmbedded-4.5.1给单片机,并在1602上显示出来,点read后,再按下p1.4键时(按久点,因为我是用查询方法读键),单片机发送xxxI Love you !给ARM,ARM板上显示I Love you !,怎么样,是不是更爽了,是的话我们再编一个复杂点的例子,编什么呢?PWM吧,可以用来控制电机的转速,我是学机电的,也就是我的专业是机电一体化,是不是很奇怪学机电的也搞程序?哈哈..兴趣!!这个例子为在QT上可以改变频率、占空比,并有语音提示,还专门编了个数字小键盘方便输入,代码下次再贴了。