QT串口通信是上位机和下位机通信常用的通信方式,也是学习QT必须学会的基础知识, 这篇就简单介绍一下QT串口通信的简单使用.
| 创建项目
1: 创建新项目
2: 配置相关信息
3: 设计界面
4:编写代码
目的: 通过简单实验验证串口通信.
4.1: 配置项目
4.2: 编写上位机代码
widget.h文件
#ifndefWIDGET_H #defineWIDGET_H #include//引入头文件 #include #include namespaceUi{ classWidget; } classWidget:publicQWidget { Q_OBJECT public: explicitWidget(QWidget*parent=0); ~Widget(); //定义曹函数 privateslots: voidon_pushButton_clicked(); voidreceiveInfo(); voidsendInfo(); private: Ui::Widget*ui; //串口对象指针 QSerialPort*m_serialPort; }; #endif//WIDGET_H
widget.cpp文件
#include"widget.h" #include"ui_widget.h" //调试输出头文件 #includeWidget::Widget(QWidget*parent): QWidget(parent), ui(newUi::Widget) { ui->setupUi(this); //实例化一个串口对象 m_serialPort=newQSerialPort(); //获取可用的串口号 foreach(constQSerialPortInfoinfo,QSerialPortInfo::availablePorts()) { qDebug()<< "Port name:" << info.portName(); ui->comboBox->addItem(info.portName()); } } Widget::~Widget() { deleteui; } //pushButton点击触发的槽函数 voidWidget::on_pushButton_clicked() { if(m_serialPort->isOpen())//如果串口已经打开了先给他关闭了 { m_serialPort->clear(); m_serialPort->close(); } m_serialPort->setPortName(ui->comboBox->currentText());//当前选择的串口名字 if(!m_serialPort->open(QIODevice::ReadWrite))//用ReadWrite的模式尝试打开串口 { qDebug()<<"打开失败!"; return; } qDebug()<<"串口打开成功!"; m_serialPort->setBaudRate(QSerialPort::Baud115200,QSerialPort::AllDirections);//设置波特率和读写方向 m_serialPort->setDataBits(QSerialPort::Data8);//数据位为8位 m_serialPort->setFlowControl(QSerialPort::NoFlowControl);//无流控制 m_serialPort->setParity(QSerialPort::NoParity);//无校验位 m_serialPort->setStopBits(QSerialPort::OneStop);//一位停止位 //手动绑定槽函数 connect(m_serialPort,SIGNAL(readyRead()),this,SLOT(receiveInfo())); connect(ui->pushButton_2,SIGNAL(clicked()),this,SLOT(sendInfo())); } //接收到单片机发送的数据进行解析 voidWidget::receiveInfo() { qDebug()<<"接收"; QByteArray info = m_serialPort->readAll(); qDebug()<<"receive info:"< write("0x55"); m_serialPort->write("0xaa"); }
4.3: 编写下位机代码
main.c文件
#include"stm32f10x.h" #include"stdio.h" voidled_init(void); voidusart_init(uint32_tbound); intmain(void) { uint32_ti=0; led_init(); usart_init(115200); printf("ok "); while(1) { GPIO_ResetBits(GPIOE,GPIO_Pin_5); for(i=0;i< 0xfffff; i++); GPIO_SetBits(GPIOE,GPIO_Pin_5); for(i = 0; i< 0xfffff; i++); } } void led_init(void) { GPIO_InitTypeDef GPIO_InitStructure;//定义结构体变量 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE); GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5; //选择你要设置的IO口 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //设置推挽输出模式 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //设置传输速率 GPIO_Init(GPIOE,&GPIO_InitStructure); /* 初始化GPIO */ GPIO_SetBits(GPIOE,GPIO_Pin_5); //将LED端口拉高,熄灭所有LED } void usart_init(uint32_t bound) { //GPIO端口设置 GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); /* 配置GPIO的模式和IO口 */ GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;//TX //串口输出PA9 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; //复用推挽输出 GPIO_Init(GPIOA,&GPIO_InitStructure); /* 初始化串口输入IO */ GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;//RX //串口输入PA10 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING; //模拟输入 GPIO_Init(GPIOA,&GPIO_InitStructure); /* 初始化GPIO */ //USART1 初始化设置 USART_InitStructure.USART_BaudRate = bound;//波特率设置 USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式 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(USART1, &USART_InitStructure); //初始化串口1 USART_Cmd(USART1, ENABLE); //使能串口1 USART_ClearFlag(USART1, USART_FLAG_TC); USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启相关中断 //Usart1 NVIC 配置 NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//串口1中断通道 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//抢占优先级3 NVIC_InitStructure.NVIC_IRQChannelSubPriority =3; //子优先级3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器 } int fputc(int ch,FILE *f) //printf重定向函数 { USART_SendData(USART1,(uint8_t)ch); //发送一字节数据 while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET); //等待发送完成 return ch; } void USART1_IRQHandler(void) { if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) { uint8_t r = USART_ReceiveData(USART1); USART_SendData(USART1,r); while(USART_GetFlagStatus(USART1,USART_FLAG_TC) != SET); } USART_ClearFlag(USART1,USART_FLAG_TC); }
| 验证效果
把下位机代码下到开发板, 然后运行自己编写的上位机, 点击上位机发送数据, 下位机就会把收到的数据返回到上位机, 可以通过控制台查看接收到的数据;
| 简单shell
main.c文件
#include"stm32f10x.h" #include"stdio.h" #include"string.h" #defineCMD_MAX_LEN16//定义最大命令长度 charcmd_buf[CMD_MAX_LEN];//定义命令缓冲区 uint8_tcmd_len=0;//定义命令长度 uint8_tcmd_flag=0;//定义命令接收完成标志 voidled_init(void); voidusart_init(uint32_tbound); voiduser_shell_irq(void); intmain(void) { led_init(); usart_init(115200); printf("ok "); while(1) { if(cmd_flag) { //匹配指令 if(strcmp(cmd_buf,"ledon")==0) { printf("ledon"); } //清理缓存 cmd_len=0;//清零命令长度 memset(cmd_buf,0,CMD_MAX_LEN);//清空命令缓冲区 cmd_flag=0;//清除命令接收完成标志 } } } voidled_init(void) { GPIO_InitTypeDefGPIO_InitStructure;//定义结构体变量 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE); GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;//选择你要设置的IO口 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//设置推挽输出模式 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//设置传输速率 GPIO_Init(GPIOE,&GPIO_InitStructure);/*初始化GPIO*/ GPIO_SetBits(GPIOE,GPIO_Pin_5);//将LED端口拉高,熄灭所有LED } voidusart_init(uint32_tbound) { //GPIO端口设置 GPIO_InitTypeDefGPIO_InitStructure; USART_InitTypeDefUSART_InitStructure; NVIC_InitTypeDefNVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); /*配置GPIO的模式和IO口*/ GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;//TX//串口输出PA9 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出 GPIO_Init(GPIOA,&GPIO_InitStructure);/*初始化串口输入IO*/ GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;//RX//串口输入PA10 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;//interwetten与威廉的赔率体系 输入 GPIO_Init(GPIOA,&GPIO_InitStructure);/*初始化GPIO*/ //USART1初始化设置 USART_InitStructure.USART_BaudRate=bound;//波特率设置 USART_InitStructure.USART_WordLength=USART_WordLength_8b;//字长为8位数据格式 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(USART1,&USART_InitStructure);//初始化串口1 USART_Cmd(USART1,ENABLE);//使能串口1 USART_ClearFlag(USART1,USART_FLAG_TC); USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//开启相关中断 //Usart1NVIC配置 NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQn;//串口1中断通道 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//抢占优先级3 NVIC_InitStructure.NVIC_IRQChannelSubPriority=3;//子优先级3 NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//IRQ通道使能 NVIC_Init(&NVIC_InitStructure);//根据指定的参数初始化VIC寄存器 } intfputc(intch,FILE*f)//printf重定向函数 { USART_SendData(USART1,(uint8_t)ch);//发送一字节数据 while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);//等待发送完成 returnch; } voidUSART1_IRQHandler(void) { if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET) { //shell user_shell_irq(); } } //获取 voiduser_shell_irq(void) { uint8_ttemp=USART_ReceiveData(USART1); if(temp==' '||temp==' ') { cmd_buf[cmd_len]='�'; cmd_flag=1; } else { cmd_buf[cmd_len++]=temp; if(cmd_len>=CMD_MAX_LEN) { //清理缓存 cmd_len=0; memset(cmd_buf,0,CMD_MAX_LEN); } } }
验证:
简单介绍了QT的串口如何与下位机通信, 同时也简单通过shell交互, 进一步拓展了串口通信场景.
-
串口通信
+关注
关注
34文章
1622浏览量
55476 -
上位机
+关注
关注
27文章
940浏览量
54766 -
Qt
+关注
关注
1文章
301浏览量
37868 -
下位机
+关注
关注
0文章
94浏览量
18745
原文标题:QT|串口通信
文章出处:【微信号:玩转单片机,微信公众号:玩转单片机】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
评论