QT-基于STM32F103C8T6的简单串口通信上位机程序

1、界面展示

2、程序设计

2.1前期准备和思路

(1)设备准备

  • 一个USB转TTL
  • 一个ST-LINK烧录器
  • 一个STM32F103C8T6
  • 杜邦线若干

(2)根据C8T6的开发文档

PA9引脚发送数据

PA10引脚接收数据

(3)连线

将单片机PA9引脚与USB转TTL的RX连接;将单片机PA10引脚与USB转TTL的TX连接。

2.2单片机程序

 一个简单的收发程序

#include "stm32f10x.h"
#include <stdio.h>
#include "delay.h"
	
//中断函数
void USART1_IRQHandler(void){
    //判断数据接收标志位
    if(SET==USART_GetFlagStatus(USART1,USART_FLAG_RXNE)){
        uint16_t da=USART_ReceiveData(USART1);            //读取出接收的数据
		USART_SendData(USART1,da);
				
		//printf("Hello World! %d\r\n",da);
        USART_ClearITPendingBit(USART1,USART_FLAG_RXNE);    //清除数据接收标志位
    }
}

void sendbyte(uint16_t Data){
   
	USART_SendData(USART1,Data);
    //等待数据发送完毕
    while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}

int fputc(int ch, FILE *f){
    sendbyte(ch);
    return ch;
}

int main(void)
{
	//int i=0;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
	//GPIO端口设置
    GPIO_InitTypeDef itd;
	
	//USART1_TX   GPIOA.9
    itd.GPIO_Mode=GPIO_Mode_AF_PP;      //复用推挽输出
    itd.GPIO_Pin=GPIO_Pin_9;            //TX引脚
    itd.GPIO_Speed=GPIO_Speed_2MHz;     //这个随意
    GPIO_Init(GPIOA,&itd);
	
	//USART1_RX	  GPIOA.10初始化
    itd.GPIO_Mode=GPIO_Mode_IN_FLOATING;//浮空输入
    itd.GPIO_Pin=GPIO_Pin_10;           //RX引脚
    GPIO_Init(GPIOA,&itd);
    
	//USART 初始化设置
    USART_InitTypeDef uitd;
    uitd.USART_BaudRate=9600;                                       //波特率
    uitd.USART_HardwareFlowControl=USART_HardwareFlowControl_None;  //硬件流控制
    uitd.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;                    //串口模式
    uitd.USART_Parity=0;//USART_Parity_No;                          //校验
    uitd.USART_StopBits=1;//USART_StopBits_1;                       //停止位长度
    uitd.USART_WordLength=8;//USART_WordLength_8b;                  //传输的字长
	//初始化串口1
    USART_Init(USART1,&uitd);
    
	//开启串口接受中断
    USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);                    //开启USART接收中断
    
	//Usart1 NVIC 配置
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);                 //NVIC中断配置
    NVIC_InitTypeDef nitd;
    nitd.NVIC_IRQChannel=USART1_IRQn;
    nitd.NVIC_IRQChannelCmd=ENABLE;
    nitd.NVIC_IRQChannelPreemptionPriority=2;
    nitd.NVIC_IRQChannelSubPriority=2;
	//根据指定的参数初始化VIC寄存器
    NVIC_Init(&nitd);
    
    USART_Cmd(USART1,ENABLE);                                       //上电USART

	uint16_t data=0;
		
	delay_init();
		
  while (1)
  {
	//sendbyte(data);
	//printf("Hello World! %d\r\n",data);
	USART1_IRQHandler();
    data++;
    //for(i=0; i<0x7ff; i++);
    delay_ms(1000);

  }
}
2.3上位机程序 

 直接上正餐

#include "shangwei.h"
#include "ui_shangwei.h"

//接收数据
shangwei::shangwei(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::shangwei)
{
    ui->setupUi(this);

    //获取win系统串口
    QList<QSerialPortInfo> winSerialList = QSerialPortInfo::availablePorts();
    QStringList wSerialPNameList ;
    QStringList wDescription;

    foreach(const QSerialPortInfo &info,winSerialList){
        wSerialPNameList<<info.portName();
        wDescription<<info.description();
    }
    //qDebug()<<wSerialPNameList;
    //qDebug()<<wDescription;

    //为下拉框赋初始值
    ui->serialSelection->addItems(wSerialPNameList);

    QStringList bRateList = {"9600","115200"};
    ui->baudRate->addItems(bRateList);

    //qDebug()<<ui->baudRate->currentText().toInt();

    QStringList sBitList={"1","1.5","2"};
    ui->stopBit->addItems(sBitList);

    QStringList dBitList={"8","7","6","5"};
    ui->dataBits->addItems(dBitList);

    QStringList cBitList={"None","Odd","Even"};
    ui->checkBit->addItems(cBitList);

}

shangwei::~shangwei()
{
    delete ui;
}

//串口开关
void shangwei::on_serialOperation_clicked()
{
    qDebug()<<ui->serialOperation->text();
    if(ui->serialOperation->text() == "关闭串口")
    {
        ui->serialOperation->setText("打开串口");
        QIcon icon1(":/res/closeSerial.png");
        ui->serialOperation->setIcon(icon1);
        // 关闭串口
        serial->close();
    }else if(ui->serialOperation->text() == "打开串口")
    {
        serial_paramsCheck();//判断串口参数是否有null
        if(paramsCheckFlag){
            //打开串口:
            //获取当前的端口
            serial = new QSerialPort;
            bool serialIsBusy=true; //判断端口是否忙碌
            QList<QSerialPortInfo> wCurrentSList = QSerialPortInfo::availablePorts();
            foreach(const QSerialPortInfo &info,wCurrentSList){
                if(info.portName()==ui->serialSelection->currentText())
                {
                    serialIsBusy=info.isBusy();
                    serial->setPort(info);
                }
            }

            if(!serialIsBusy){
                //配置串口参数
                serial->setBaudRate(QSerialPort::BaudRate (ui->baudRate->currentText().toInt()));
                serial->setDataBits(QSerialPort::DataBits (ui->dataBits->currentText().toInt()));
                serial->setStopBits(QSerialPort::StopBits (ui->stopBit->currentText().toInt()));
                serial->setParity(QSerialPort::NoParity);
                serial->setFlowControl(QSerialPort::NoFlowControl);

                qDebug()<<ui->baudRate->currentText();

                ui->serialOperation->setText("关闭串口");
                QIcon icon2(":/res/openSerial.png");
                ui->serialOperation->setIcon(icon2);

                bool isSerialOpen = serial->open(QIODevice::ReadWrite);
                serial->setDataTerminalReady(true);
                serial->setReadBufferSize(3);
                if (!isSerialOpen) {
                    qDebug()<< QString("Failed to open serial port:")  << serial->errorString();
                    serial->clearError();
                }else {
                    qDebug()<< QString("The serial port is open: ") ;
                    serial->setDataTerminalReady(true);
                    //串口中有数据就接收
                    QObject::connect(serial,&QSerialPort::readyRead,this,&shangwei::serial_readyRead);
                }
            }
            else{
                QMessageBox::warning(this,"警告","该端口已被占用");
            }
        }
    }
}

//接收数据、数据处理的槽函数
void shangwei::serial_readyRead(){
    /*
     * 当前设备数据是一个字节一个字节的发送
    */
    //读取数据
    recevierData =serial->readAll();
    qDebug()<<recevierData;

    showDateTime();
    showRHexStyle();
    changeTextStyle();

    isSend = false;
}

//判断传递参数不为空
void shangwei::serial_paramsCheck(){
    if(ui->serialSelection->currentText()=="" || ui->baudRate->currentText()=="" || ui->dataBits->currentText()=="" || ui->stopBit->currentText()==""){
        QMessageBox::warning(this,"警告","请输入正确的参数");
        paramsCheckFlag = false;
    }
    else{
        paramsCheckFlag = true;
    }
}

//清空接收的数据
void shangwei::on_clearRecevier_clicked()
{
    ui->recevierEdit->clear();
}

void shangwei::on_sendData_clicked()
{
    //对串口操作来说显示“关闭串口”才是打开了串口
    if(ui->serialOperation->text() == "关闭串口"){
        qDebug()<<ui->sendEdit->toPlainText();
        QString sendTextData = ui->sendEdit->toPlainText();
        sendByteArrayData= sendTextData.toUtf8();
        sendData = serial->write(sendByteArrayData);
        //qDebug()<<sendData;
        //qDebug()<<sendByteArrayData;

        isSend = true;

        showDateTime();
        showSHexStyle();
        changeTextStyle();
    }else{
        QMessageBox::warning(this,"警告","请正确打开串口");
    }

}

//清空发送的数据
void shangwei::on_clearSend_clicked()
{
     ui->sendEdit->clear();
}

//更改文本样式
void shangwei::changeTextStyle(){
    //给接收的数据更改样式(字体颜色换成黑色)
    QTextCursor cursor = ui->recevierEdit->textCursor();
    cursor.setPosition(cursor.position()+3,QTextCursor::MoveAnchor);
    cursor.select(QTextCursor::WordUnderCursor);

    QTextCharFormat format;
    QBrush brush(Qt::black);
    //将前景刷设置为指定刷,前景刷是为了渲染文本
    format.setForeground(brush);
    //光标指向的字符格式与设置的文本格式合并
    cursor.mergeCharFormat(format);
    //将光标移到当前行的末尾
    cursor.movePosition(QTextCursor::EndOfLine);
}

//显示当前时间戳
void shangwei::showDateTime(){
    if(ui->showDateBox->isChecked()){
        QDateTime currentDateTime = QDateTime::currentDateTime();
        qDebug()<<currentDateTime.toString("yyyy-MM-dd hh:mm:ss.zzz");

        ui->recevierEdit->append("["+currentDateTime.toString("yyyy-MM-dd hh:mm:ss.zzz")+"]");
    }
}

//接收的数据以16进制显示
void shangwei::showRHexStyle(){
    if(ui->showHexBox->isChecked()){
        //转16进制
        ui->recevierEdit->append("RX:"+recevierData.toHex().toUpper());
    }else{
        ui->recevierEdit->append("RX:"+recevierData);
    }
}

//发送的数据以16进制显示
void shangwei::showSHexStyle(){
    if(ui->showHexBox->isChecked()){
        //转16进制
        //以QBetyArray形式返回字符串的UTF-8(Unicode编码)表示
        //如字符串"123" -> "1":0x31; "2":0x32; "3":0x33
        ui->recevierEdit->append("TX:"+sendByteArrayData.toHex().toUpper());
    }else{
        ui->recevierEdit->append("TX:"+sendByteArrayData);
    }
}

虽然功能很简单,但是断断续续写得挺久的,忘记咋描述了,以后有需求了再修改。

完整的单片机与qt程序代码资源:https://download.csdn.net/download/qq_51442463/89488882

可参考文章:Qt串口通信-接收数据_qt 串口数据接收完整后显示-CSDN博客

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值