我在之前的程序中添加了水泵功能,这需要用到继电器,及其相关驱动代码,其次上位机利用QT以及串口通信来进行信息交互。
1、水泵模块
引脚连接:
| 引脚 | 连接 |
| 水泵正极 | 继电器DC+ |
| 水泵负极 | 继电器DC- |
| COM | DC- |
| IN | 单片机对应IP口 |
| DC+ | 正极 |
| DC- | 负极 |
驱动代码:
#include "stm32f10x.h" // Device header
#include "bump.h"
BUMP_INFO bump_info = {0};
void BUMP_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE );
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB,&GPIO_InitStructure);
BUMP_OFF();
}
void BUMP_ON(void){
GPIO_SetBits(GPIOB,GPIO_Pin_14);
bump_info.bump_Status = 1;
}
void BUMP_OFF(void){
GPIO_ResetBits(GPIOB,GPIO_Pin_14);
bump_info.bump_Status = 0;
}
void BUMP_Set(_Bool status) {
if(status) {
BUMP_ON();
} else {
BUMP_OFF();
}
}
#ifndef __BUMP_H
#define __BUMP_H
typedef struct
{
_Bool bump_Status;
} BUMP_INFO;
extern BUMP_INFO bump_info;
void BUMP_Init(void);
void BUMP_ON(void);
void BUMP_OFF(void);
void BUMP_Set(_Bool status);
#endif
2、QT上位机:
先看效果
#include "widget.h"
#include "ui_widget.h"
#include <QSerialPortInfo>
#include <QMessageBox>
#include <QTime>
#include <QTimer>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//初始化串口对象
serialport = new QSerialPort(this);
//自动获取串口名称
QStringList serialPortName;
foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts()){
serialPortName<<info.portName();
}
ui->serial_com->addItems(serialPortName); //在控件显示串口名称
//连接串口接收信号到处理槽
connect(serialport,SIGNAL(readyRead()),this,SLOT(serial_textedit_slot()));
}
Widget::~Widget()
{
delete ui;
}
//程序运行中只创建一个 Widget 实例,常用于全局逻辑共享
Widget* Widget::Singleton()
{
static Widget inst(nullptr);
return &inst;
}
bool Widget::SaveDataToLocal(QString Path, QString SaveName, QVariantMap Result )
{
try
{
QString FilePath = Path + "/" + SaveName;
//检查目录是否存在,不存在则创建
QDir dir(Path);
if (!dir.exists())
{
dir.mkpath(Path);
}
QFile SaveFile(FilePath);
QFileInfo f(FilePath);
//文件不存在,写入标题行
if (!f.isFile())
{
QString Title = "";
SaveFile.open(QIODevice::WriteOnly);
for (QString key: Result.keys())
{
Title += key + ",";
}
Title += "\r\n";
SaveFile.write(Title.toUtf8());
SaveFile.close();
}
//追加写入数据行
SaveFile.open(QIODevice::WriteOnly | QIODevice::Append);
foreach(auto it, Result)
{
SaveFile.write((it.toString().toStdString() + ",").c_str());
}
SaveFile.write("\r\n");
SaveFile.close();
return true;
}
catch (const std::exception&)
{
return false;
}
}
int send_flag=0;
QString str_time;
//触发槽函数,显示串口打印信息
void Widget::serial_textedit_slot()
{
QString buf,dhtbuf,str_t,str_h,str_o,str_r,str_co2,str_sq_buf;//获取串口的消息
buf = QString(serialport->readAll());
dhtbuf.append(buf);
str_t.append(dhtbuf.at(1));
str_t.append(dhtbuf.at(2));
ui->temp->setText(str_t);
str_h.append(dhtbuf.at(3));
str_h.append(dhtbuf.at(4));
ui->shidu->setText(str_h);
str_o.append(dhtbuf.at(5));
str_o.append(dhtbuf.at(6));
ui->tr->setText(str_o);
str_r.append(dhtbuf.at(7));
str_r.append(dhtbuf.at(8));
ui->rain->setText(str_r);
str_co2.append(dhtbuf.at(9));
str_co2.append(dhtbuf.at(10));
str_co2.append(".");
str_co2.append(dhtbuf.at(11));
str_co2.append(dhtbuf.at(12));
ui->smoke->setText(str_co2);
//拼接日志信息,显示到文本框
str_sq_buf.append(str_time);
str_sq_buf.append("温度:");
str_sq_buf.append(ui->temp->text());
str_sq_buf.append("湿度:");
str_sq_buf.append(ui->shidu->text());
str_sq_buf.append("土壤湿度:");
str_sq_buf.append(ui->tr->text());
str_sq_buf.append("雨量:");
str_sq_buf.append(ui->rain->text());
str_sq_buf.append("CO2:");
str_sq_buf.append(ui->smoke->text());
ui->serial_rx_edit->appendPlainText(str_sq_buf);
//不同时间更改阈值
if((current_time.hour()>4 && current_time.hour()<10) || (current_time.hour()>13 && current_time.hour()<18) ) //早晨/下午阈值
{
if(str_t.toInt() >30)QMessageBox::information(this,"提示","温度过高");
else if(str_t.toInt() <18)QMessageBox::information(this,"提示","温度过低");
if(str_h.toInt() >80)QMessageBox::information(this,"提示","湿度过高");
else if(str_h.toInt() <40)QMessageBox::information(this,"提示","湿度过低");
if(str_o.toFloat() >80)QMessageBox::information(this,"提示","土壤湿度过高");
else if(str_o.toFloat() <0)QMessageBox::information(this,"提示","土壤湿度过低");
if(str_co2.toInt() >100)QMessageBox::information(this,"提示","二氧化碳浓度过高");
}else //中午阈值/其他时间
{
if(str_t.toInt() >35)QMessageBox::information(this,"提示","温度过高");
else if(str_t.toInt() <20)QMessageBox::information(this,"提示","温度过低");
if(str_h.toInt() >90)QMessageBox::information(this,"提示","湿度过高");
else if(str_h.toInt() <50)QMessageBox::information(this,"提示","湿度过低");
if(str_o.toFloat() >80)QMessageBox::information(this,"提示","土壤湿度过高");
else if(str_o.toFloat() <0)QMessageBox::information(this,"提示","土壤湿度过低");
if(str_co2.toInt() >100)QMessageBox::information(this,"提示","二氧化碳浓度过高");
}
}
//串口初始化参数配置
void Widget::on_serial_open_clicked()
{
QSerialPort::BaudRate baudrate;
QSerialPort::DataBits databits;
QSerialPort::StopBits stopbits;
QSerialPort::Parity check;
//波特率
if(ui->serial_baud->currentText() == "9600"){
baudrate = QSerialPort::Baud9600;
}else if(ui->serial_baud->currentText() == "38400"){
baudrate = QSerialPort::Baud38400;
}else if(ui->serial_baud->currentText() == "115200"){
baudrate = QSerialPort::Baud115200;
}
//数据位
if(ui->serial_data->currentText() == "5"){
databits = QSerialPort::Data5;
}else if(ui->serial_data->currentText() == "6"){
databits = QSerialPort::Data6;
}else if(ui->serial_data->currentText() == "7"){
databits = QSerialPort::Data7;
}else if(ui->serial_data->currentText() == "8"){
databits = QSerialPort::Data8;
}
//停止位
if(ui->serial_stop->currentText() == "1"){
stopbits = QSerialPort::OneStop;
}else if(ui->serial_stop->currentText() == "1.5"){
stopbits = QSerialPort::OneAndHalfStop;
}else if(ui->serial_stop->currentText() == "2"){
stopbits = QSerialPort::TwoStop;
}
//校验位
if(ui->serial_check->currentText() == "none"){
check = QSerialPort::NoParity;
}
//初始化
serialport->setPortName(ui->serial_com->currentText());
serialport->setBaudRate(baudrate);
serialport->setDataBits(databits);
serialport->setStopBits(stopbits);
serialport->setParity(check);
//判断是否打开成功
if(serialport->open(QIODevice::ReadWrite) == true)
{
QMessageBox::information(this,"提示","成功");
}else{
QMessageBox::critical(this,"提示","错误");
}
}
void Widget::on_serial_close_clicked()
{
serialport->close();
}
void Widget::on_pushButton_clicked()
{
}
void Widget::on_pushButton_2_clicked()
{
// ui->serial_rx_edit->clear();
}
//打印数据到本地存储
void Widget::on_data_print_clicked()
{
//QString str_t,str_x,str_y,str_p,str_s,str_z;
for (int i = 1; i <= 100; i++)
{
QVariantMap data; // 可以从QTableWidget 的数据调入进来
data[u8"time"] = str_time;
data[u8"temp"] = ui->temp->text();
data[u8"humi"] = ui->shidu->text();
data[u8"trhumi"] = ui->tr->text();
data[u8"rain"] = ui->rain->text();
data[u8"smoke"] = ui->smoke->text();
Widget::Singleton()->SaveDataToLocal("d:/1", u8"环境监测数据.csv", data);
Widget::Singleton()->SaveDataToLocal("d:/1", u8"环境监测数据.txt", data);
}
}
void Widget::on_feng_released()
{
if(ui->feng->text()=="开启"){
QString buf;
buf = "B_ON";
serialport->write(buf.toLocal8Bit().data());
ui->feng->setText("关闭");
ui->label_23->setText("通风中");
}
else if(ui->feng->text()=="关闭"){
QString buf2;
buf2 = "B_OFF";
serialport->write(buf2.toLocal8Bit().data());
ui->feng->setText("开启");
ui->label_23->setText("待机中");
}
}
void Widget::on_shui_released()
{
if(ui->shui->text()=="开启"){
QString buf3;
buf3 = "b_ON";
serialport->write(buf3.toLocal8Bit().data());
ui->shui->setText("关闭");
ui->label_24->setText("灌溉中");
}
else if(ui->shui->text()=="关闭"){
QString buf4;
buf4 = "b_OFF";
serialport->write(buf4.toLocal8Bit().data());
ui->shui->setText("开启");
ui->label_24->setText("待机中");
}
}
要注意串口传输时的格式。
&spm=1001.2101.3001.5002&articleId=149741796&d=1&t=3&u=be25a7a37d3c498dadf9dfcbb69f9a37)

被折叠的 条评论
为什么被折叠?



