• QT串口助手-ZUA课设


    成品展示

    参考:【QT】串口助手(优化升级)
    在这里插入图片描述

    其他功能展示在文章 最后

    QT全部程序构成

    在这里插入图片描述

    zua.pro

    只添加了 QT += core gui serialport
    RC_ICONS =system.ico

    QT       += core gui serialport
    
    greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
    
    CONFIG += c++11
    
    DEFINES += QT_DEPRECATED_WARNINGS
    
    SOURCES += \
        main.cpp \
        serial.cpp
    
    HEADERS += \
        serial.h
    
    FORMS += \
        serial.ui
    
    RC_ICONS =system.ico
    
    qnx: target.path = /tmp/$${TARGET}/bin
    else: unix:!android: target.path = /opt/$${TARGET}/bin
    !isEmpty(target.path): INSTALLS += target
    
    RESOURCES += \
        zua.qrc
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    serial.h

    #ifndef SERIAL_H
    #define SERIAL_H
    
    #include 
    /*---port串口--*/
    #include 
    #include 
    /*---QString--*/
    #include 
    /*---QTimer定时器--*/
    #include 
    /*-----QToolBar工具栏------*/
    #include 
    /*---QDebug打印--*/
    #include 
    
    QT_BEGIN_NAMESPACE
    namespace Ui { class Serial; }
    QT_END_NAMESPACE
    
    class Serial : public QMainWindow
    {
        Q_OBJECT
    
    public:
        Serial(QWidget *parent = nullptr);
        ~Serial();
    
    private:
        Ui::Serial *ui;
        /*------------变量----------------*/
        QSerialPort mSerialPort;//串口全局类声明
        bool mIsOpen;//是否打开串口
        QTimer *timer;//自动发送定时器声明
    
        /*------------函数----------------*/
        bool getSerialPortConfig();// 获取串口配置 打开串口
        //用户系统初始化
        void sysIint();
        //字符串转16进制
        QByteArray QString2Hex(QString str);
        //字符转16进制
        char ConvertHexChar(char ch);
    
    
    signals:    //自定义信号
        //发送使能信号
        void my_send_signals(bool); //触发发送信号
    
    private slots:
        void on_SerialPort_readyRead();// 准备接收串口数据槽,自定义的
        void on_btnOpen_clicked();//打开串口按键槽,使用转到槽
        void on_btnClose_clicked();//关闭串口按键,使用转到槽
        void on_BtnSend_clicked();//发送按键,使用转到槽
        void on_btn_clear_clicked();//清楚接收区按键,使用转到槽
        void on_btn_clear_send_clicked();//清空发送区按键,使用转到槽
        void on_checkBox_3_stateChanged(int arg1);//自动触发复选框  启动定时器和停止定时器,使用转到槽
    };
    #endif // SERIAL_H
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    main.cpp

    没有改变

    serial.cpp

    #include "serial.h"
    #include "ui_serial.h"
    
    Serial::Serial(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::Serial)
    {
        ui->setupUi(this);
        sysIint();
    }
    
    Serial::~Serial()
    {
        delete ui;
    }
    // 获取串口配置 打开串口
    bool Serial::getSerialPortConfig()
    {
        //    获取串口配置
        QString mPortName = ui->cmd_port_name->currentText();//     端口号
        QString mBaudRate = ui->cmd_baud_rate->currentText();//     波特率
        QString mDataBits = ui->cmd_Data_Bits->currentText();//     数据位
        QString mParity = ui->cmd_parity->currentText();//     校验位
        QString mStopBits = ui->cmd_Stop_Bits->currentText();//      停止位
    
        //     设置串口
        //     端口号
        mSerialPort.setPortName(mPortName);
        //     波特率
        mSerialPort.setBaudRate(mBaudRate.toInt());
        /*if("9600" == mBaudRate)
        {
            mSerialPort.setBaudRate(QSerialPort::Baud9600);
        }
        else if("115200" == mBaudRate)
        {
            mSerialPort.setBaudRate(QSerialPort::Baud115200);
        }
        else
        {
            mSerialPort.setBaudRate(QSerialPort::Baud19200);
        }*/
    
        //     数据位
        if("5" == mDataBits)
        {
           mSerialPort.setDataBits(QSerialPort::Data5);
        }
        else if("6" == mDataBits)
        {
           mSerialPort.setDataBits(QSerialPort::Data6);
        }
        else if("7" == mDataBits)
        {
            mSerialPort.setDataBits(QSerialPort::Data7);
        }
        else
        {
            mSerialPort.setDataBits(QSerialPort::Data8);
        }
    
        //     校验位
    
        if("Even" == mParity)
        {
           mSerialPort.setParity(QSerialPort::EvenParity);// 偶数
        }
        else if ("ODD" == mParity)
        {
          mSerialPort.setParity(QSerialPort::OddParity);//奇数的
        }
        else
        {
          mSerialPort.setParity(QSerialPort::NoParity);
        }
    
        //      停止位
        if("1.5" == mStopBits)
        {
            mSerialPort.setStopBits(QSerialPort::OneAndHalfStop);
        }
        else if("2" == mStopBits)
        {
            mSerialPort.setStopBits(QSerialPort::TwoStop);
        }
        else
        {
            mSerialPort.setStopBits(QSerialPort::OneStop);
        }
    
        //      打开串口
        return mSerialPort.open(QSerialPort::ReadWrite);
    }
    //系统初始化
    void Serial::sysIint()
    {
        ui->cmd_port_name->clear();
        this->setWindowTitle("xxx的串口调试GUI");//窗口名字
        connect(&mSerialPort,&QSerialPort::readyRead,this,&Serial::on_SerialPort_readyRead);//XI
        mIsOpen = false;
        ui->BtnSend->setEnabled(mIsOpen);//没连接串口按键为灰色
    
        //    智能识别当前系统的有效串口号
        //通过QSerialPortInfo查找可用串口
        foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
        {
            //将可用串口添加到端口显示框
            ui->cmd_port_name->addItem(info.portName());
        }
        //timer 自动发送
        timer = new QTimer(this);
        connect(timer,&QTimer::timeout,[=](){
            emit my_send_signals(true); //触发发送信号
        });
    
        //QToolBar *toolBar1= addToolBar("工具栏");//QToolBar工具栏
        //发送信号   发送槽函数
        connect(this,&Serial::my_send_signals,this,&Serial::on_BtnSend_clicked);
    }
    //字符串转16进制
    QByteArray Serial::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;
    }
    //字符转16进制
    char Serial::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);
    }
    
    /*-----------------slot--------------------*/
    // 准备接收串口数据槽
    void Serial::on_SerialPort_readyRead()
    {
        QByteArray recvData = mSerialPort.readAll();//从串口读取数据
        QString str_rev;
        if(ui->chk_rev_hex->checkState() == Qt::Checked){   //HEX 16进制
                str_rev = QString(recvData.toHex(' ').toUpper().append(' '));
        }else{
                str_rev =QString::fromLocal8Bit(recvData);//处理汉语显示乱码,函数返回的是String类型的数
        }
    
    
        //文本框显示接收数据
        ui->textRecv->insertPlainText(str_rev);//显示内容,不会自动清空
        //将光标定位到最后
        ui->textRecv->moveCursor(QTextCursor::End);
    }
    
    
    //打开串口按键
    void Serial::on_btnOpen_clicked()
    {
        if(true == mIsOpen)
        {
            // 当前串口已经打开了一个串口,这时要执行关闭串口
            mSerialPort.close();
            mIsOpen = false;
            ui->BtnSend->setEnabled(mIsOpen);//发送按键不用
        }
        else
        {
            // 当前串口助手没有打开串口,这时要执行打开串口动作
            if(true == getSerialPortConfig())
            {
                mIsOpen = true;
                ui->BtnSend->setEnabled(mIsOpen);//发送按键可用
            }
            else
            {
                mIsOpen = false;
            }
        }
    }
    //关闭串口按键
    void Serial::on_btnClose_clicked()
    {
         mSerialPort.close();//执行关闭串口
         ui->BtnSend->setEnabled(false);//没连接串口按键为灰色
         mIsOpen = false;
         ui->textRecv->clear();//关闭串口,同时清楚接收区
    }
    
    //发送按键
    void Serial::on_BtnSend_clicked()
    {
        qDebug()<<"发送按键"<<endl;
        QString data = ui->textSend->toPlainText();
        QByteArray array;//字节数组
    
        //复选框  16 进制发送
        if(ui->chk_send_hex->checkState() == Qt::Checked){
            array = QString2Hex(data);  //HEX 16进制,QString转Hex QString转十六进制数,自己写的
        }else{
            array = data.toLatin1();    //ASCII,QString类提供的
        }
        mSerialPort.write(array);   //发送数据
        //发送完后,清空发送区
        ui->textSend->clear();
    }
    //清楚接收区按键
    void Serial::on_btn_clear_clicked()
    {
       qDebug()<<"清楚接收区按键"<<endl;
       ui->textRecv->clear();
    }
    //清空发送区按键
    void Serial::on_btn_clear_send_clicked()
    {
        qDebug()<<"清空发送区按键"<<endl;
        ui->textSend->clear();
    }
    //自动触发复选框  启动定时器和停止定时器
    void Serial::on_checkBox_3_stateChanged(int arg1)
    {
        if(arg1){
            timer->start(ui->spinBox->value()); //启动定时器
        }else{
            timer->stop();  //停止定时器
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258

    在Win10下编程,有可能会显示中文乱码
    不同编程环境使用不同

    1. QString::fromLocal8Bit("");//处理汉语显示乱码,函数返回的是String类
    
    2.QString::fromUtf8("")
    
    还有更多,目前我只用到这两个
    
    • 1
    • 2
    • 3
    • 4
    • 5

    槽函数slot 区分
    在这里插入图片描述在这里插入图片描述

    serial.ui

    • 左侧组QGroupBox
      在这里插入图片描述
    • 右侧组QGroupBox

    在这里插入图片描述

    Keil全部程序构成

    在这里插入图片描述

    main.c

    #include "stm32f10x.h"
    #include "./led/bsp_led.h" 
    #include "./usart/bsp_usart.h" 
    #include "./Key/bsp_exti.h" 
    #include "./dht11/bsp_dht11.h"
    
    static void Show_Message(void);
      
    int main(void)
    {	
      char ch;
    	
    	/* 初始化EXTI中断,按下按键会触发中断,
      *  触发中断会进入stm32f4xx_it.c文件中的函数
    	*  KEY1_IRQHandler和KEY2_IRQHandler,处理中断,反转LED灯,发送学号姓名。
    	*/
    	EXTI_Key_Config(); 
    	
    	/*初始化DTT11的引脚*/
    	DHT11_Init ();
      
      /* 初始化RGB彩灯 */
      LED_GPIO_Config();
      
      /* 初始化USART 配置模式为 115200 8-N-1 */
      USART_Config();
    	
    	
    	LED1_ON;
    	
      /* 打印指令输入提示信息 */
      Show_Message();
      while(1)
    	{	
    
        /* 获取字符指令 */
        ch=getchar();
        printf("接收到字符:%c\n",ch);
        
        /* 根据字符指令控制RGB彩灯颜色 */
        switch(ch)
        {
          case '1':
            LED_RED;
          break;
          case '2':
            LED_GREEN;
          break;
          case '3':
            LED_BLUE;
          break;
          case '4':
            LED_YELLOW;
          break;
          case '5':
            LED_PURPLE;
          break;
          case '6':
            LED_CYAN;
          break;
          case '7':
            LED_WHITE;
          break;
          case '8':
            LED_RGBOFF;
          break;
          default:
            /* 如果不是指定指令字符,打印提示信息 */
            Show_Message();
            break;      
        }   
    	}	
    }
    
    /* 打印指令输入提示信息*/
    static void Show_Message(void)
    {
      printf("\r\r这是一个通过串口通信指令控制RGB彩灯实验 \n");
      printf("使用  USART  参数为:%d 8-N-1 \n",DEBUG_USART_BAUDRATE);
    	printf("开发板接到指令后控制RGB彩灯颜色\n");
    	printf("指令对应如下:\n");
      printf("   指令   ------ 彩灯颜色 \n");
      printf("     1    ------    红 \n");
      printf("     2    ------    绿 \n");
      printf("     3    ------    蓝 \n");
      printf("     4    ------    黄 \n");
      printf("     5    ------    紫 \n");
      printf("     6    ------    青 \n");
      printf("     7    ------    白 \n");
      printf("     8    ------    灭 \n");  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91

    stm32f10x_conf.h

    注意文件中 有可能会 注释掉了一些头文件,把注释去掉就好啦

    stm32f10x_it.c

    在最后插入以下

    void KEY1_IRQHandler(void)
    {
    	
      //确保是否产生了EXTI Line中断
    	if(EXTI_GetITStatus(KEY1_INT_EXTI_LINE) != RESET) 
    	{
    		// LED1 取反		
    		LED1_TOGGLE;
    		printf("\r ---学号---姓名--\n");
    		/* 发送学号、姓名*/
    		Usart_SendString(DEBUG_USARTx,"191xxxxxx7-xxx\n");
    		
    		Usart_SendString(DEBUG_USARTx,"191xxxxxx0李x\n");
    		
    		Usart_SendString(DEBUG_USARTx,"190xxxxxx3周xx\n");
    		
    		Usart_SendString(DEBUG_USARTx,"191xxxxxx5卢xx\n");	
    			
    		
        //清除中断标志位
    		EXTI_ClearITPendingBit(KEY1_INT_EXTI_LINE);     
    	}  
    }
    
    void KEY2_IRQHandler(void)
    {
    	DHT11_Data_TypeDef DHT11_Data;
      //确保是否产生了EXTI Line中断
    	if(EXTI_GetITStatus(KEY2_INT_EXTI_LINE) != RESET) 
    	{
    		// LED2 取反		
    		LED2_TOGGLE;
    			/*调用DHT11_Read_TempAndHumidity读取温湿度,若成功则输出该信息*/
    			if( DHT11_Read_TempAndHumidity ( & DHT11_Data ) == SUCCESS)
    			{
    				printf("\r\n读取DHT11成功!\r\n\r\n湿度为%d.%d %RH ,温度为 %d.%d℃ \r\n",\
    				DHT11_Data.humi_int,DHT11_Data.humi_deci,DHT11_Data.temp_int,DHT11_Data.temp_deci);
    			}			
    			else
    			{
    				printf("Read DHT11 ERROR!\r\n");
    			}
        //清除中断标志位
    		EXTI_ClearITPendingBit(KEY2_INT_EXTI_LINE);     
    	}  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    5.stm32f10x_it.h

    添加了头文件,其他保留

    #include "stm32f10x.h"
    #include "./led/bsp_led.h" 
    #include "./usart/bsp_usart.h" 
    #include "./Key/bsp_exti.h"
    #include "./dht11/bsp_dht11.h"
    
    • 1
    • 2
    • 3
    • 4
    • 5

    bsp_usart.c

    #include "bsp_usart.h"
    
    
    void USART_Config(void)
    {
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    
    // 打开串口GPIO的时钟
    DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE);
    
    // 打开串口外设的时钟
    DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE);
    
    // 将USART Tx的GPIO配置为推挽复用模式
    GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);
    
      // 将USART Rx的GPIO配置为浮空输入模式
    GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);
    
    // 配置串口的工作参数
    // 配置波特率
    USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE;
    // 配置 针数据字长
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    // 配置停止位
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    // 配置校验位
    USART_InitStructure.USART_Parity = USART_Parity_No ;
    // 配置硬件流控制
    USART_InitStructure.USART_HardwareFlowControl = 
    USART_HardwareFlowControl_None;
    // 配置工作模式,收发一起
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    // 完成串口的初始化配置
    USART_Init(DEBUG_USARTx, &USART_InitStructure);
    
    // 使能串口
    USART_Cmd(DEBUG_USARTx, ENABLE);    
    }
    
    /*****************  发送一个字符 **********************/
    void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch)
    {
    /* 发送一个字节数据到USART */
    USART_SendData(pUSARTx,ch);
    
    /* 等待发送数据寄存器为空 */
    while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
    }
    
    /*****************  发送字符串 **********************/
    void Usart_SendString( USART_TypeDef * pUSARTx, char *str)
    {
    unsigned int k=0;
      do 
      {
          Usart_SendByte( pUSARTx, *(str + k) );
          k++;
      } while(*(str + k)!='\0');
      
      /* 等待发送完成 */
      while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET)
      {}
    }
    
    /*****************  发送一个16位数 **********************/
    void Usart_SendHalfWord( USART_TypeDef * pUSARTx, uint16_t ch)
    {
    uint8_t temp_h, temp_l;
    
    /* 取出高八位 */
    temp_h = (ch&0XFF00)>>8;
    /* 取出低八位 */
    temp_l = ch&0XFF;
    
    /* 发送高八位 */
    USART_SendData(pUSARTx,temp_h);
    while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
    
    /* 发送低八位 */
    USART_SendData(pUSARTx,temp_l);
    while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
    }
    
    ///重定向c库函数printf到串口,重定向后可使用printf函数
    int fputc(int ch, FILE *f)
    {
    /* 发送一个字节数据到串口 */
    USART_SendData(DEBUG_USARTx, (uint8_t) ch);
    
    /* 等待发送完毕 */
    while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET);
    
    return (ch);
    }
    
    ///重定向c库函数scanf到串口,重写向后可使用scanf、getchar等函数
    int fgetc(FILE *f)
    {
    /* 等待串口输入数据 */
    while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_RXNE) == RESET);
    
    return (int)USART_ReceiveData(DEBUG_USARTx);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110

    bsp_led.c

    #include "./led/bsp_led.h"   
    
     
    void LED_GPIO_Config(void)
    {
    /*定义一个GPIO_InitTypeDef类型的结构体*/
    GPIO_InitTypeDef GPIO_InitStructure;
    
    /*开启LED相关的GPIO外设时钟*/
    RCC_APB2PeriphClockCmd( LED1_GPIO_CLK | LED2_GPIO_CLK | LED3_GPIO_CLK, ENABLE);
    /*选择要控制的GPIO引脚*/
    GPIO_InitStructure.GPIO_Pin = LED1_GPIO_PIN;
    
    /*设置引脚模式为通用推挽输出*/
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   
    
    /*设置引脚速率为50MHz */   
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
    
    /*调用库函数,初始化GPIO*/
    GPIO_Init(LED1_GPIO_PORT, &GPIO_InitStructure);
    
    /*选择要控制的GPIO引脚*/
    GPIO_InitStructure.GPIO_Pin = LED2_GPIO_PIN;
    
    /*调用库函数,初始化GPIO*/
    GPIO_Init(LED2_GPIO_PORT, &GPIO_InitStructure);
    
    /*选择要控制的GPIO引脚*/
    GPIO_InitStructure.GPIO_Pin = LED3_GPIO_PIN;
    
    /*调用库函数,初始化GPIOF*/
    GPIO_Init(LED3_GPIO_PORT, &GPIO_InitStructure);
    
    /* 关闭所有led灯*/
    GPIO_SetBits(LED1_GPIO_PORT, LED1_GPIO_PIN);
    
    /* 关闭所有led灯*/
    GPIO_SetBits(LED2_GPIO_PORT, LED2_GPIO_PIN); 
        
        /* 关闭所有led灯*/
    GPIO_SetBits(LED3_GPIO_PORT, LED3_GPIO_PIN);
    }
    
    void assert_failed(uint8_t* file, uint32_t line)
    {
    // 断言错误时执行的代码
    LED1_ON;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    bsp_exit.c

    #include "bsp_exti.h"
    
    
    static void NVIC_Configuration(void)
    {
      NVIC_InitTypeDef NVIC_InitStructure;
      
      /* 配置NVIC为优先级组1 */
      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
      
      /* 配置中断源:按键1 */
      NVIC_InitStructure.NVIC_IRQChannel = KEY1_INT_EXTI_IRQ;
      /* 配置抢占优先级 */
      NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
      /* 配置子优先级 */
      NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
      /* 使能中断通道 */
      NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
      NVIC_Init(&NVIC_InitStructure);
      
      /* 配置中断源:按键2,其他使用上面相关配置 */  
      NVIC_InitStructure.NVIC_IRQChannel = KEY2_INT_EXTI_IRQ;
      NVIC_Init(&NVIC_InitStructure);
    }
    
     /**
      * @brief  配置 IO为EXTI中断口,并设置中断优先级
      * @param  无
      * @retval 无
      */
    void EXTI_Key_Config(void)
    {
    GPIO_InitTypeDef GPIO_InitStructure; 
    EXTI_InitTypeDef EXTI_InitStructure;
    
    /*开启按键GPIO口的时钟*/
    RCC_APB2PeriphClockCmd(KEY1_INT_GPIO_CLK,ENABLE);
    
    /* 配置 NVIC 中断*/
    NVIC_Configuration();
    
    /*--------------------------KEY1配置-----------------------------*/
    /* 选择按键用到的GPIO */
      GPIO_InitStructure.GPIO_Pin = KEY1_INT_GPIO_PIN;
      /* 配置为浮空输入 */
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
      GPIO_Init(KEY1_INT_GPIO_PORT, &GPIO_InitStructure);
    
    /* 选择EXTI的信号源 */
      GPIO_EXTILineConfig(KEY1_INT_EXTI_PORTSOURCE, KEY1_INT_EXTI_PINSOURCE); 
      EXTI_InitStructure.EXTI_Line = KEY1_INT_EXTI_LINE;
    
    /* EXTI为中断模式 */
      EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    /* 上升沿中断 */
      EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
      /* 使能中断 */
      EXTI_InitStructure.EXTI_LineCmd = ENABLE;
      EXTI_Init(&EXTI_InitStructure);
    
      /*--------------------------KEY2配置-----------------------------*/
    /* 选择按键用到的GPIO */
      GPIO_InitStructure.GPIO_Pin = KEY2_INT_GPIO_PIN;
      /* 配置为浮空输入 */
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
      GPIO_Init(KEY2_INT_GPIO_PORT, &GPIO_InitStructure);
    
    /* 选择EXTI的信号源 */
      GPIO_EXTILineConfig(KEY2_INT_EXTI_PORTSOURCE, KEY2_INT_EXTI_PINSOURCE); 
      EXTI_InitStructure.EXTI_Line = KEY2_INT_EXTI_LINE;
    
    /* EXTI为中断模式 */
      EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    /* 下降沿中断 */
      EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
      /* 使能中断 */
      EXTI_InitStructure.EXTI_LineCmd = ENABLE;
      EXTI_Init(&EXTI_InitStructure);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79

    bsp_dht11.c

    #include "./dht11/bsp_dht11.h"
    #include "./dwt_delay/core_delay.h" 
    
    /* 可以在下面的宏定义中把后面的延时函数替换换SysTick的延时函数,就是想用那个就换成那个的 */
    
    #define DHT11_DELAY_US(us)  CPU_TS_Tmr_Delay_US(us)
    #define DHT11_DELAY_MS(ms)  CPU_TS_Tmr_Delay_MS(ms)
    
    static void                           DHT11_GPIO_Config                       ( void );
    static void                           DHT11_Mode_IPU                          ( void );
    static void                           DHT11_Mode_Out_PP                       ( void );
    static uint8_t                        DHT11_ReadByte                          ( void );
    
    
    
     /**
      * @brief  DHT11 初始化函数
      * @param  无
      * @retval 无
      */
    void DHT11_Init ( void )
    {
    	DHT11_GPIO_Config ();
    	
    	DHT11_Dout_1;               // 拉高GPIOB10
    }
    
    
    /*
     * 函数名:DHT11_GPIO_Config
     * 描述  :配置DHT11用到的I/O口
     * 输入  :无
     * 输出  :无
     */
    static void DHT11_GPIO_Config ( void )
    {		
    	/*定义一个GPIO_InitTypeDef类型的结构体*/
    	GPIO_InitTypeDef GPIO_InitStructure; 
    
    	
    	/*开启DHT11_Dout_GPIO_PORT的外设时钟*/
      DHT11_Dout_SCK_APBxClock_FUN ( DHT11_Dout_GPIO_CLK, ENABLE );	
     
    	/*选择要控制的DHT11_Dout_GPIO_PORT引脚*/															   
      	GPIO_InitStructure.GPIO_Pin = DHT11_Dout_GPIO_PIN;	
    
    	/*设置引脚模式为通用推挽输出*/
      	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   
    
    	/*设置引脚速率为50MHz */   
      	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
    
    	/*调用库函数,初始化DHT11_Dout_GPIO_PORT*/
      	GPIO_Init ( DHT11_Dout_GPIO_PORT, &GPIO_InitStructure );		  
    	
    }
    
    
    /*
     * 函数名:DHT11_Mode_IPU
     * 描述  :使DHT11-DATA引脚变为上拉输入模式
     * 输入  :无
     * 输出  :无
     */
    static void DHT11_Mode_IPU(void)
    {
     	  GPIO_InitTypeDef GPIO_InitStructure;
    
    	  	/*选择要控制的DHT11_Dout_GPIO_PORT引脚*/	
    	  GPIO_InitStructure.GPIO_Pin = DHT11_Dout_GPIO_PIN;
    
    	   /*设置引脚模式为浮空输入模式*/ 
    	  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ; 
    
    	  /*调用库函数,初始化DHT11_Dout_GPIO_PORT*/
    	  GPIO_Init(DHT11_Dout_GPIO_PORT, &GPIO_InitStructure);	 
    	
    }
    
    
    /*
     * 函数名:DHT11_Mode_Out_PP
     * 描述  :使DHT11-DATA引脚变为推挽输出模式
     * 输入  :无
     * 输出  :无
     */
    static void DHT11_Mode_Out_PP(void)
    {
     	GPIO_InitTypeDef GPIO_InitStructure;
    
    	 	/*选择要控制的DHT11_Dout_GPIO_PORT引脚*/															   
      	GPIO_InitStructure.GPIO_Pin = DHT11_Dout_GPIO_PIN;	
    
    	/*设置引脚模式为通用推挽输出*/
      	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   
    
    	/*设置引脚速率为50MHz */   
      	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    
    	/*调用库函数,初始化DHT11_Dout_GPIO_PORT*/
      	GPIO_Init(DHT11_Dout_GPIO_PORT, &GPIO_InitStructure);	 	 
    	
    }
    
    
    /* 
     * 从DHT11读取一个字节,MSB先行
     */
    static uint8_t DHT11_ReadByte ( void )
    {
    	uint8_t i, temp=0;
    	
    
    	for(i=0;i<8;i++)    
    	{	 
    		/*每bit以50us低电平标置开始,轮询直到从机发出 的50us 低电平 结束*/  
    		while(DHT11_Dout_IN()==Bit_RESET);
    
    		/*DHT11 以26~28us的高电平表示“0”,以70us高电平表示“1”,
    		 *通过检测 x us后的电平即可区别这两个状 ,x 即下面的延时 
    		 */
    		DHT11_DELAY_US(40); //延时x us 这个延时需要大于数据0持续的时间即可	   	  
    
    		if(DHT11_Dout_IN()==Bit_SET)/* x us后仍为高电平表示数据“1” */
    		{
    			/* 等待数据1的高电平结束 */
    			while(DHT11_Dout_IN()==Bit_SET);
    
    			temp|=(uint8_t)(0x01<<(7-i));  //把第7-i位置1,MSB先行 
    		}
    		else	 // x us后为低电平表示数据“0”
    		{			   
    			temp&=(uint8_t)~(0x01<<(7-i)); //把第7-i位置0,MSB先行
    		}
    	}
    	
    	return temp;
    	
    }
    
    
    /*
     * 一次完整的数据传输为40bit,高位先出
     * 8bit 湿度整数 + 8bit 湿度小数 + 8bit 温度整数 + 8bit 温度小数 + 8bit 校验和 
     */
    uint8_t DHT11_Read_TempAndHumidity(DHT11_Data_TypeDef *DHT11_Data)
    {  
    	/*输出模式*/
    	DHT11_Mode_Out_PP();
    	/*主机拉低*/
    	DHT11_Dout_0;
    	/*延时18ms*/
    	DHT11_DELAY_MS(18);
    
    	/*总线拉高 主机延时30us*/
    	DHT11_Dout_1; 
    
    	DHT11_DELAY_US(30);   //延时30us
    
    	/*主机设为输入 判断从机响应信号*/ 
    	DHT11_Mode_IPU();
    
    	/*判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行*/   
    	if(DHT11_Dout_IN()==Bit_RESET)     
    	{
    		/*轮询直到从机发出 的80us 低电平 响应信号结束*/  
    		while(DHT11_Dout_IN()==Bit_RESET);
    
    		/*轮询直到从机发出的 80us 高电平 标置信号结束*/
    		while(DHT11_Dout_IN()==Bit_SET);
    
    		/*开始接收数据*/   
    		DHT11_Data->humi_int= DHT11_ReadByte();
    
    		DHT11_Data->humi_deci= DHT11_ReadByte();
    
    		DHT11_Data->temp_int= DHT11_ReadByte();
    
    		DHT11_Data->temp_deci= DHT11_ReadByte();
    
    		DHT11_Data->check_sum= DHT11_ReadByte();
    
    
    		/*读取结束,引脚改为输出模式*/
    		DHT11_Mode_Out_PP();
    		/*主机拉高*/
    		DHT11_Dout_1;
    
    		/*检查读取的数据是否正确*/
    		if(DHT11_Data->check_sum == DHT11_Data->humi_int + DHT11_Data->humi_deci + DHT11_Data->temp_int+ DHT11_Data->temp_deci)
    			return SUCCESS;
    		else 
    			return ERROR;
    	}
    	
    	else
    		return ERROR;
    	
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199

    bsp_delay.c

    /*使用内核寄存器精确延时*/ 
    #include "./dwt_delay/core_delay.h"   
    
    
    /*
    **********************************************************************
    *         时间戳相关寄存器定义
    **********************************************************************
    */
    /*
     在Cortex-M里面有一个外设叫DWT(Data Watchpoint and Trace),
     该外设有一个32位的寄存器叫CYCCNT,它是一个向上的计数器,
     记录的是内核时钟运行的个数,最长能记录的时间为:
     60s=2的32次方/72000000
     (假设内核频率为72M,内核跳一次的时间大概为1/72M=13.8ns)
     当CYCCNT溢出之后,会清0重新开始向上计数。
     使能CYCCNT计数的操作步骤:
     1、先使能DWT外设,这个由另外内核调试寄存器DEMCR的位24控制,写1使能
     2、使能CYCCNT寄存器之前,先清0
     3、使能CYCCNT寄存器,这个由DWT_CTRL(代码上宏定义为DWT_CR)的位0控制,写1使能
     */
     
    #if USE_DWT_DELAY
    
    
    #define  DWT_CR      *(__IO uint32_t *)0xE0001000
    #define  DWT_CYCCNT  *(__IO uint32_t *)0xE0001004
    #define  DEM_CR      *(__IO uint32_t *)0xE000EDFC
    
    
    #define  DEM_CR_TRCENA                   (1 << 24)
    #define  DWT_CR_CYCCNTENA                (1 <<  0)
    
    
    /**
      * @brief  初始化时间戳
      * @param  无
      * @retval 无
      * @note   使用延时函数前,必须调用本函数
      */
    void CPU_TS_TmrInit(void)
    {
        /* 使能DWT外设 */
        DEM_CR |= (uint32_t)DEM_CR_TRCENA;                
    
        /* DWT CYCCNT寄存器计数清0 */
        DWT_CYCCNT = (uint32_t)0u;
    
        /* 使能Cortex-M DWT CYCCNT寄存器 */
        DWT_CR |= (uint32_t)DWT_CR_CYCCNTENA;
    }
    
    /**
      * @brief  读取当前时间戳
      * @param  无
      * @retval 当前时间戳,即DWT_CYCCNT寄存器的值
      */
    uint32_t CPU_TS_TmrRd(void)
    {        
      return ((uint32_t)DWT_CYCCNT);
    }
    
    ///**
    //  * @brief  读取当前时间戳
    //  * @param  无
    //  * @retval 当前时间戳,即DWT_CYCCNT寄存器的值
    //	* 				此处给HAL库替换HAL_GetTick函数,用于os
    //  */
    //uint32_t HAL_GetTick(void)
    //{        
    //  return ((uint32_t)DWT_CYCCNT*1000/SysClockFreq);
    //}
    
    /**
      * @brief  采用CPU的内部计数实现精确延时,32位计数器
      * @param  us : 延迟长度,单位1 us
      * @retval 无
      * @note   使用本函数前必须先调用CPU_TS_TmrInit函数使能计数器,
                或使能宏CPU_TS_INIT_IN_DELAY_FUNCTION
                最大延时值为8秒,即8*1000*1000
      */
    void CPU_TS_Tmr_Delay_US(__IO uint32_t us)
    {
      uint32_t ticks;
      uint32_t told,tnow,tcnt=0;
    
      /* 在函数内部初始化时间戳寄存器, */  
    #if (CPU_TS_INIT_IN_DELAY_FUNCTION)  
      /* 初始化时间戳并清零 */
      CPU_TS_TmrInit();
    #endif
      
      ticks = us * (GET_CPU_ClkFreq() / 1000000);  /* 需要的节拍数 */      
      tcnt = 0;
      told = (uint32_t)CPU_TS_TmrRd();         /* 刚进入时的计数器值 */
    
      while(1)
      {
        tnow = (uint32_t)CPU_TS_TmrRd();  
        if(tnow != told)
        { 
            /* 32位计数器是递增计数器 */    
          if(tnow > told)
          {
            tcnt += tnow - told;  
          }
          /* 重新装载 */
          else 
          {
            tcnt += UINT32_MAX - told + tnow; 
          } 
          
          told = tnow;
    
          /*时间超过/等于要延迟的时间,则退出 */
          if(tcnt >= ticks)break;
        }  
      }
    }
    
    #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121

    介绍

    1.项目名称:基于cortex-M3的QT串口助手
    2.开发语言:C、C++
    3.开发平台:Windows10
    4.硬件平台:STM32F103(cortex-M3)、DHT11
    5.开发工具:QT5.14.2、Keil5
    6.关于项目:
    项目主要实现了串行通信软件上位机(PC),和下位机(嵌入式系统)的串口通信系统,串口调试软件,向下位机发送控制信号,控制下位机RGB灯 亮起不同颜色 和 熄灭;操作下位机按键1,向上位机发送本组成员的学号和姓名;操作下位机按键2,接收下位机传来的温湿度传感器检测数据。
    7.负责模块:
    嵌入式系统下位机开发,按键中断发送数据,获取上位机控制信号;
    QT上位机开发,上位机接收数据并做出相应的处理,向下位机发送控制信号;
    8.扩展:定时向上位机发送本组成员的姓名信息(定时器中断)

    硬件

    野火F103指南者+DHT11温湿度传感器

    在这里插入图片描述

    QT全部程序构成

    在这里插入图片描述

    QT设计的思路

    首先使用UI设计,搭建出串口调试界面,分为左右两侧GroupBox组控件,左侧数据区放置TextBrowser文本阅读器控件、PlainTextEdit纯文本编辑器控件和PushButton按键控件;右侧串口区放置Label标签控件、ComboBox组合选择框控件、CheckBox复选框控件、SpinBox数值微调器控件和PushButton按键控件;放置完成UI和对象与类如图6所示;
    图6 放置完成UI和对象与类
    在这里插入图片描述

    其中对窗口名称设置使用this->setWindowTitle(“xxx的串口调试GUI”); 窗口图标先添加QT Resource File类文件,然后添加 .ico 格式图片,设置在zua.pro文件中添加 RC_ICONS =system.ico;
    在对PushButton按键控件使用QT集成的转到槽函数,自动生成槽函数框架,再对不同操作进行逻辑编写,进而实现不同按键的功能;

    Keil全部程序构成

    在这里插入图片描述

    Keil程序设计的思路

    图2 程序设计的思路
    在这里插入图片描述

    按键K1向上位机发送本组成员的学号和姓名功能和按键K2向上位机发送温湿度功能,在stm32f10x_it.c文件,通过中断函数实现,逻辑图如图3所示;
    图3 按键逻辑设计
    在这里插入图片描述

    在main.c文件中while(1)主逻辑程序,设计实现上位机发送控制信号,下位机通过switch()函数选择二极管灯发出不同颜色的光,主逻辑程序设计如图4所示;
    图4 主逻辑控制RGB彩灯颜色程序

    在这里插入图片描述

    功能

    1.

    调试界面初始时,使用失能ui->BtnSend->setEnabled(false); 发送按键为灰色
    在这里插入图片描述

    2.

    选择端口,设置波特率、数据位、停止位和校验位,打开串口,开发板按下复位键
    在这里插入图片描述

    3.

    复位后,RGB灯为红色,向下位机发送控制信号,在发送数据区域发送2,控制下位机二极管灯发出不同颜色的光,发送2如下图10所示,下位机二极管亮起绿灯如下图11所示。
    图10图10
    图11 下位机二极管亮起绿灯
    在这里插入图片描述
    图12 发送3串口调试界面
    在这里插入图片描述
    图13 下位机二极管亮起蓝灯
    在这里插入图片描述
    图14 发送4串口调试界面
    在这里插入图片描述
    图15 下位机二极管亮起蓝灯
    在这里插入图片描述

    还有5-紫色,6-青色,7-白色,8-关闭,other-信息

    4.

    操作下位机按键K1,向上位机发送本组成员的学号和姓名
    在这里插入图片描述

    5.

    操作下位机按键K2,向上位机发送温湿度,接收下位机传来的温湿度传感器检测数据
    在这里插入图片描述

    6.

    点击关闭串口,会同时执行窗口清除ui->textRecv->clear();
    在这里插入图片描述

    全部功能

    在这里插入图片描述
    在这里插入图片描述

    BUG解决方法

    • QT编写时使用QString::fromLocal8Bit(recvData);处理汉语显示乱码
      在这里插入图片描述

    • 传输学号姓名时,数据部分丢失,解决:在丢失数据部分 加一个杠 -
      在这里插入图片描述
      解决
      在这里插入图片描述

    源码

    1. 有道云笔记: QT串口助手-ZUA课设
    1. 百度云:
      链接:https://pan.baidu.com/s/1C6IcP2pN99cxcWNOrNdxJA?pwd=ifhf
      提取码:ifhf
    1. Git:03QT串口助手-ZUA课设
  • 相关阅读:
    C# 去除utf-8 BOM头
    裸辞后进入阿里,斩获34k测开岗offer....
    Unity编辑器扩展
    【Android】Android应用性能优化总结
    Allegro166查看走线阻抗操作指导
    艾泊宇产品战略:用户满意度是衡量产品成功的关键指标
    力扣题解7.27
    视频剪辑srt字幕的添加步骤,三分钟学会这个方法
    【C刷题初阶】刷爆力扣第一弹
    数据可视化如何革新智慧物流管理?
  • 原文地址:https://blog.csdn.net/qq_47355554/article/details/126898479