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