赞
踩
最近有项目需求要做PC端Qt与某嵌入式设备的通信的任务,初步确定需要通过一根USB转RS232串口线与该嵌入式设备连接,在PC端任意输入0~255,这256个十进制数字,在该嵌入式设备上也能显示相应的数字内容。
本篇博客主要记录一下相关操作的实现过程。
涉及到带RS232接口的嵌入式设备,我这边用了一个很久之前买的STC89C52单片机开发板做模拟。
主要思路:
(1)硬件:PC机,USB转RS232串口线,STC89C52单片机开发板;
(2)软件:PC端通过Qt的serialport模块相关操作,单片机端通过keil uversion5进行51C语言编程、STC-ISP烧写软件实现软件烧写编程;
PC端的Widget界面内有个QlineEdit输入窗口,可以修改输入数据,输入数据为0~255共256个数据,按回车键后,单片机开发版上的Led数码管显示相应的数据内容。
需要购买一根USB转RS232串口线,下载好相应的串口驱动,通过“计算机”的设备管理器界面的COM端口查看该串口的串口号,可以在此处修改串口号。
我此处为COM8口,此处有个USB-SERIAL CH340(COM7)是用于单片机的烧写,也可做串口通信,需要将Qt上位机的端口号修改,即可实现通信。
通过Qt的
serialport
模块进行串口通信实现相关功能。
这里面主要逻辑是当lineEdit实例的editingFinished()信号产生的时候,调用send_data()
槽函数,对lineEdit内的数据进行采集后传输,需要将lineEdit内的数据转化为QByteArray
型的数据,从而通过m_serialPort->write(ba);
进行数据传输。
这里的QByteArray
数据转化需要稍微注意一下,举个例子,如果需要将QString
类型的‘ff’直接转化为QByteArray
类型,它QByteArray
产生的是一个2字节的数组
,即每个字母占一个字节,即QByteArray[0] = f,QByteArray[1] = f,而不是想当然的只占一个字节,不是0xff。
具体怎么转化可以参照代码,代码也是找的网上相关博客里,涉及到十进制如何转化为QByteArray
的十六进制存储。代码内容不展开记录了。
widget.cpp
#include "widget.h" #include "ui_widget.h" #include <QDebug> Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget) { ui->setupUi(this); m_serialPort = new QSerialPort(); m_serialPort->setPortName("COM8"); m_serialPort->setBaudRate(QSerialPort::Baud9600); m_serialPort->setDataBits(QSerialPort::Data8); m_serialPort->setParity(QSerialPort::NoParity); m_serialPort->setStopBits(QSerialPort::OneStop); m_serialPort->setFlowControl(QSerialPort::NoFlowControl); m_serialPort->setReadBufferSize(40960); m_serialPort->open(QIODevice::ReadWrite); connect(ui->lineEdit, SIGNAL(editingFinished()), this, SLOT(send_data())); } Widget::~Widget() { m_serialPort->clear(); m_serialPort->close(); delete ui; } char ConvertHexChar(char ch) { if((ch >= '0') && (ch <= '9')) return ch-0x30; else if((ch >= 'A') && (ch <= 'F')) return ch-'A'+10; else if((ch >= 'a') && (ch <= 'f')) return ch-'a'+10; else return (-1); } void Widget::send_data() { uint8_t data_10 = ui->lineEdit->text().toInt(); qDebug() << "data_10" << data_10; QString s = QString::number(data_10, 16); if(s.length() == 1) { s = '0' + s; } qDebug() << "s" <<s; QByteArray ba = QString2Hex(s); qDebug() << "ba" <<ba; m_serialPort->write(ba); } QByteArray Widget::QString2Hex(QString str) { QByteArray senddata; int hexdata,lowhexdata; int hexdatalen = 0; int len = str.length(); senddata.resize(len/2); char lstr,hstr; for(int i=0; i<len; ) { hstr=str[i].toLatin1(); if(hstr == ' ') { i++; continue; } i++; if(i >= len) break; lstr = str[i].toLatin1(); hexdata = ConvertHexChar(hstr); lowhexdata = ConvertHexChar(lstr); if((hexdata == 16) || (lowhexdata == 16)) break; else hexdata = hexdata*16+lowhexdata; i++; senddata[hexdatalen] = (char)hexdata; hexdatalen++; } senddata.resize(hexdatalen); return senddata; }
keil uVersion5。
STC-isp
通过Qt的
serialport
模块进行串口通信实现相关功能。
注意点:(1)如果在开发板的RS232串口处如果有选择开关帽,需要将开关帽打开。如下图所示,此时已经打开。
#include<reg52.h> #define uint unsigned int #define uchar unsigned char sbit dula=P2^6; sbit wela=P2^7; sbit d1=P1^0; //led0 unsigned char dat; int num = 0; uchar code tabel[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; uchar led[]={0x7e,0x7d,0x7b,0x4f,0x66,0x6d}; void display(uint data_input); void delay(uint z); void Uart_Init() //初始化串口uart { TMOD=0x20; SCON=0x50; PCON&=0x7F; TH1=0xfd; //9600波特率下的初值 TL1=0xfd; // TL1= TH1 ET1=0; //禁止定时器1被中断 TR1=1; //开启定时器1 ES=1; //开启串口中断 EA=1; //开启总中断 } void Uart_Send_Byte(unsigned char uartData) //发送一个字节Byte { //SBUF此时为发送寄存器,需要将要发送的数据uartData存储在SBUF中 SBUF=uartData; //作为发送时的SBUF将自动发出存储在其中的数据(uartData)至接收区缓存 while(!TI); //发送完成时TI将置1,需要软件清0 TI=0; //软件清0 } void main() { Uart_Init(); //串口初始化 wela=1; P0=0x00; //位选信号,决定亮的数码管的位置 wela=0; while(1) { // for(num=0;num<256;num++) // { // display(num); // } display(dat); } } void delay(uint z) { uint x,y; for(x=z;x>0;x--) for(y=110;y>0;y--); } void display(uint data_input) { uint baiwei = (data_input/100) % 10; uint shiwei = (data_input/10) % 10; uint gewei = (data_input/1) % 10; dula = 1; P0 = tabel[baiwei]; dula = 0; P0 = 0xff; //消影 wela = 1; P0 = led[0]; wela = 0; delay(1); wela = 1; P0 = 0xff; wela = 0; dula = 1; P0 = tabel[shiwei]; dula = 0; P0 = 0xff; wela = 1; P0 = led[1]; wela = 0; delay(1); wela = 1; P0 = 0xff; wela = 0; dula = 1; P0 = tabel[gewei]; dula = 0; P0 = 0xff; wela = 1; P0 = led[2]; wela = 0; delay(1); wela = 1; P0 = 0xff; wela = 0; } void Uart_Service() interrupt 4 //开启串口通信中断(由RI TI触发) { /*数据存在SBUF,使用"Uart_Send_Byte(dat)-发送寄存器SBUF"将会自动发出SBUF(SBUF=dat)*/ while(!RI); //当接收到发送缓存器的一个字节的数据后时,RI置1 dat= SBUF; //此时可将SBUF存储到dat中(dat为一个字节,相当于dat读取接收区SBUF) // P1=dat; //再将dat值赋给P2-有8个led灯的特殊寄存器,即可实现控制LED Uart_Send_Byte(dat); //这里是发送一个字节dat RI=0; //手动将RI置0 }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。