1.先看QT上位机部分
1.首先写一个页面
点击隐藏BOSS后弹出第二个页面
因为我的语音模块里面是周杰伦反方向的钟,所以我把歌词加进去了,你可以自由更改;
要想QT实现串口,需要两个头文件,加到mainwindow.cpp中
#include <QtSerialPort/QSerialPort> // 提供访问串口的功能 #include <QtSerialPort/QSerialPortInfo> // 提供系统中存在的串口信息
此时会报错,因为工程文件(shangwei.pro)还需要添加
QT +=serialport
此时就可以正常使用头文件内部的函数了。首先我们要配置串口。
2.mainwindow.cpp主要函数。
配置串口函数:
void MainWindow::on_pushButton_5_clicked() //打开,关闭 { //是OPEN时,代表没有打开串口 if(ui->pushButton_5->text() == QString("OPEN")) { //检查串口是否被占用,再次检查一遍 //串口配置 //清空缓冲区 serial = new QSerialPort; //申请内存,并设置父对象 // 获取计算机中有效的端口号,然后将端口号的名称给端口选择控件 //QSerialPortInfo::availablePorts()的返回值为QList<QSerialPortInfo> 每一个可用端口组成的容器 foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts()) { serial->setPort(info); if(serial->open(QIODevice::ReadWrite)) // 以读写方式打开串口 { // 在对象中设置串口 qDebug() << "串口打开成功"; serial->close(); // 关闭 } else { qDebug() << "串口打开失败,请重试"; } } //设置波特率 serial->setBaudRate( static_cast<QSerialPort::BaudRate> (ui->comboBox_2->currentText().toInt()) ); //设置停止位 serial->setStopBits( static_cast<QSerialPort::StopBits> (ui->comboBox_3->currentText().toInt())); //设置数据位 serial->setDataBits( static_cast<QSerialPort::DataBits> (ui->comboBox_6->currentText().toInt()) ); //设置校验 serial->setParity ( static_cast<QSerialPort::Parity> (ui->comboBox_4->currentIndex())); //设置流控 serial->setFlowControl(QSerialPort::NoFlowControl); //改变按钮上的文本 ui->pushButton_5->setText("CLOSE"); //输出通道的端口名字 ui->lineEdit->setText(serial->portName()); 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: ") ; } }else{ ui->pushButton_5->setText("OPEN"); serial->close(); } }
我这个波特率,停止位等串口设置依赖于窗口的选择;
选择参数函数:
void MainWindow::initConfig() { // //创建对象,并建立信号槽 serial = new QSerialPort(this); // //读函数的信号槽 QObject::connect(serial, &QSerialPort::readyRead, this, &MainWindow::serial_readyRead); //添加波特率 QStringList baudList; baudList << "115200" << "57600" << "9600" ; ui->comboBox_2->addItems(baudList); ui->comboBox_2->setCurrentText("115200"); //添加停止位 QStringList baudList1; baudList1 << "0.5" << "1" << "1.5"<<"2" ; ui->comboBox_3->addItems(baudList1); ui->comboBox_3->setCurrentText("1"); //添加数据位 QStringList baudList2; baudList2 << "8" << "9" ; ui->comboBox_6->addItems(baudList2); ui->comboBox_6->setCurrentText("8"); //奇偶校验 QStringList baudList3; baudList3 << "NO" << "EVEN" ; ui->comboBox_4->addItems(baudList3); ui->comboBox_4->setCurrentText("NO"); }
配置完串口函数后需要书写发串口发送数据和接受数据;
发送数据:
void MainWindow::on_pushButton_3_clicked() //发送 { if(ui->pushButton_5->text() == QString("CLOSE")) { QByteArray data = ui->textEdit_2->toPlainText().toUtf8(); serial->write(data); qDebug() <<serial ; }else{ ui->textEdit->append("请打开串口!!!!!"); } }
接收函数:
void MainWindow::serial_readyRead() { //从接收缓冲区中读取数据 QByteArray buffer = serial->readAll(); //从界面中读取以前收到的数据 QString recv = ui->textEdit->toPlainText(); recv += QString(buffer); //清空以前的显示 ui->textEdit->clear(); //重新显示 ui->textEdit->append(recv); qDebug() <<recv<<"cxc" ; }
清空函数:
void MainWindow::on_pushButton_2_clicked() //清除 接收 { //清除显示 ui->textEdit->clear(); }
主要函数就这么多,后面会给出完整代码;
2.form.cpp主要函数
其实和上一个函数类型差不多,只是利用槽函数进行发送数据而已
初始化函数:
void Form::on_pushButton_10_clicked() { if(ui->pushButton_10->text() == QString("打开串口")) { //串口配置 //清空缓冲区 serial = new QSerialPort; //申请内存,并设置父对象 // 获取计算机中有效的端口号,然后将端口号的名称给端口选择控件 //QSerialPortInfo::availablePorts()的返回值为QList<QSerialPortInfo> 每一个可用端口组成的容器 foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts()) { serial->setPort(info); if(serial->open(QIODevice::ReadWrite)) // 以读写方式打开串口 { // 在对象中设置串口 qDebug() << "串口打开成功"; serial->close(); // 关闭 } else { qDebug() << "串口打开失败,请重试"; } } // 参数配置,波特率V serial->setBaudRate(QSerialPort::Baud115200); // 校验位,校验默认选择无 serial->setParity(QSerialPort::NoParity); // 数据位,数据位默认选择8位 serial->setDataBits(QSerialPort::Data8); // 停止位,停止位默认选择1位 serial->setStopBits(QSerialPort::OneStop); // 控制流,默认选择无 serial->setFlowControl(QSerialPort::NoFlowControl); //改变按钮上的文本 ui->pushButton_10->setText("关闭串口"); //输出通道的端口名字 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(); configSetEnable1(false); }else { qDebug()<< QString("The serial port is open: ") ; configSetEnable1(true); } }else{ configSetEnable1(false); ui->pushButton_10->setText("打开串口"); serial->close(); } }
发送函数:
void Form::on_pushButton_13_clicked() { QByteArray data ="55"; serial->write(data); qDebug() <<serial ; }
我只列举了主要函数,后面会给出完整的代码。
3.STM32部分
我使用的是信盈达的STM32F103ZET6,JQ8900N-16P 语音模块,MQ135模块,MQ2模块以及DHT11温湿度模块和一块LED屏幕。
STM32部分代码太多,后面会打包成压缩文件,先看一下主函数。
1.main函数
#include "stm32f10x.h" #include "stm32f10x_conf.h" #include <stdio.h> #include <string.h> #include "delay.h" #include "usart.h" #include "sys.h" #include "led.h" #include "key.h" #include "relay.h" #include "beep.h" #include "time.h" #include "lcd_gui.h" #include "pic.h" #include "touch.h" #include "dht11.h" #include "adc.h" int main() { u8 T,H; int num=0,i=0,X=0,Y=0; u8 ledflag =1; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); Delay_Init(); USART_Config(115200); BEEPGpioInit(); LEDInit(); KEYGpioInit(); RELAYInit(); LCD_Init(); Adc_Init(); Voice_Config(9600); int count=5; Set_Song_Volume(5); int bo=2; char MQ[11]={'#','M','Q','1','3','5',':'}; char WEN[5]; char SHI[6]; char MQ22[10]={'#','M','Q','2',':'}; SHI[5]='\0'; WEN[4]='\0'; WEN[0]='T'; SHI[0]='H'; WEN[1]=':'; SHI[1]=':'; MQ[10]='\0'; MQ22[9]='\0'; // LCD_Dis_String(0,0,"棒打林渊!",0x0000, 0xffff, 2,0); // LCD_Dis_String(0,32,"Hello Tomorrow",0x0000, 0xffff, 2,0); while(1) { if(uart1_finish_flage) { if(strcmp(USART1_Rcv_Buff,"11") == 0){ LCD_Clear(0,239,0,319,0xffff); //处理数据 USART1_Rcv_Buff LED1_ON; //处理结束将数组进行清空 LCD_Dis_String(0,0,"LED1_ON",0x0000, 0xffff, 2,0); }else if(strcmp(USART1_Rcv_Buff,"12") == 0){ LCD_Clear(0,239,0,319,0xffff); LED1_OFF; LCD_Dis_String(0,0,"LED1_OFF",0x0000, 0xffff, 2,0); }else if(strcmp(USART1_Rcv_Buff,"21") == 0){ LCD_Clear(0,239,0,319,0xffff); LED2_ON; LCD_Dis_String(0,0,"LED2_ON",0x0000, 0xffff, 2,0); }else if(strcmp(USART1_Rcv_Buff,"22") == 0){ LCD_Clear(0,239,0,319,0xffff); LED2_OFF; LCD_Dis_String(0,0,"LED2_OFF",0x0000, 0xffff, 2,0); }else if(strcmp(USART1_Rcv_Buff,"31") == 0){ LCD_Clear(0,239,0,319,0xffff); LED3_ON; LCD_Dis_String(0,0,"LED3_ON",0x0000, 0xffff, 2,0); }else if(strcmp(USART1_Rcv_Buff,"32") == 0){ LCD_Clear(0,239,0,319,0xffff); LED3_OFF; LCD_Dis_String(0,0,"LED3_OFF",0x0000, 0xffff, 2,0); }else if(strcmp(USART1_Rcv_Buff,"41") == 0){ LCD_Clear(0,239,0,319,0xffff); LED4_ON; LCD_Dis_String(0,0,"LED4_ON",0x0000, 0xffff, 2,0); }else if(strcmp(USART1_Rcv_Buff,"42") == 0){ LCD_Clear(0,239,0,319,0xffff); LED4_OFF; LCD_Dis_String(0,0,"LED4_OFF",0x0000, 0xffff, 2,0); }else if(strcmp(USART1_Rcv_Buff,"55") == 0){ Set_Song_Volume(count++); }else if(strcmp(USART1_Rcv_Buff,"66") == 0){ Set_Song_Volume(count--); }else if(strcmp(USART1_Rcv_Buff,"77") == 0){ Appoint_Song_Name("00001"); }else if(strcmp(USART1_Rcv_Buff,"88") == 0){ Stop_Song(); }else if(strcmp(USART1_Rcv_Buff,"99") == 0){ Xiayi_Song(); }else if(strcmp(USART1_Rcv_Buff,"98") == 0){ Shangyi_Song(); }else if(strcmp(USART1_Rcv_Buff,"13") == 0){ bo=1; }else if(strcmp(USART1_Rcv_Buff,"14") == 0){ BEEP_ON; }else if(strcmp(USART1_Rcv_Buff,"15") == 0){ BEEP_OFF; }else if(strcmp(USART1_Rcv_Buff,"16") == 0){ bo=0; } memset(USART1_Rcv_Buff,0,sizeof(USART1_Rcv_Buff)); uart1_count = 0; uart1_finish_flage =0; } if(bo==1){ dht11_read_ht(&T,&H); LCD_Clear(0,239,0,319,0xffff); // if(H>80)BEEP_ON ;else BEEP_OFF; WEN[2]=T/10+'0'; WEN[3]=T%10+'0'; SHI[2]=H/100+'0'; SHI[3]=H/10%10+'0'; SHI[4]=H%10+'0'; int m=ADC_Val_Disp(Mq135); int m2=ADC_Val_Disp(Mq2); MQ[7]=m/100+'0'; MQ[8]=m/10%10+'0'; MQ[9]=m%10+'0'; MQ22[5]=m2/1000+'0'; MQ22[6]=m2/100%10+'0'; MQ22[7]=m2/10%10+'0'; MQ22[8]=m2%10+'0'; LCD_Clear(0,239,0,319,0xffff); LCD_Dis_String(0,0,WEN,0x0000, 0xffff, 2,0); LCD_Dis_String(0,32,SHI,0x0000, 0xffff, 2,0); LCD_Dis_String(0,64,MQ,0x0000, 0xffff, 2,0); LCD_Dis_String(0,32*3,MQ22,0x0000, 0xffff, 2,0); Delay_ms(500); }else if(bo==0){ LCD_Clear(0,239,0,319,0xffff); bo=2; } } return 0; }
先通过QT给单片机发送指令,单片机收到后会判断是哪一种指令,实行相应的操作。