基于STM32利用串口读取香氛传感器的浓度值,并通过MatLab读取串口数据生成曲线
基于STM32利用串口读取香氛传感器的浓度值,并通过MatLab读取串口数据生成曲线
所需要的元器件/软件
- stm32f1c8t6最小核心板;
- 杜邦线;
- USB-TTL;
- 香氛传感器;
- MDK5;
- llcom串口助手;
- flymcu烧写软件;
- MatLab。
stm32f1c8t6最小核心板;
香氛传感器以及通讯协议
传感器正面图
传感器背面图
香氛传感器的引脚定义:
通讯设置:
通讯命令(主动发送):
ou值的计算
气体浓度值=(气体浓度高位*256+气体浓度低位)*分辨率
分辨率这边为0.1
串口1的配置
串口1初始化:将数据发送到上位机 代码
。
#include "stm32f10x.h"
#include "usart.h"
#include "sys.h"
#if 1
#pragma import(__use_no_semihosting)
struct __FILE
{
int handle;
};
FILE __stdout;
//定义_sys_exit()以避免使用半主机模式
_sys_exit(int x)
{
x = x;
}
//重定义fputc函数
int fputc(int ch,FILE *f)
{
USART1->SR;
USART_SendData(USART1, (unsigned char) ch);
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);
return(ch);
}
#endif
//功能:串口1初始化
void uart1_init(u32 bound) //初始化串口1,函数的参数是波特率
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING
GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = bound;
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(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE);
}
串口2初始化
串口2初始化:传感器通过串口2读取数据 代码
。
#include "stm32f10x.h"
#include "uart2.h"
#include "sys.h"
#include "usart.h"
#if 1
#pragma import(__use_no_semihosting)
struct __FILE
{
int handle;
};
#endif
void uart2_init(u32 bound)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
USART_InitStructure.USART_BaudRate = bound;
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(USART2, &USART_InitStructure);
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
USART_Cmd(USART2, ENABLE);
}
##串口中断触发
串口中断 代码
。
#define USART2_BUFFER_SIZE 10
u8 USART_RX_BUF[USART2_BUFFER_SIZE];
u8 USART_RX_STA = 0;
static char start = 0;
float ou;
void USART2_IRQHandler(void)
{
u8 Res = 0;
if (USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
{
Res = USART_ReceiveData(USART2);
if (start == 0)
{
if (Res == 0xFF)
{
start = 1;
USART_RX_STA = 0;
}
}
if (start == 1)
{
USART_RX_BUF[USART_RX_STA] = Res;
USART_RX_STA++;
if (USART_RX_STA >= 2 && USART_RX_BUF[USART_RX_STA - 1] == 0xFF)
{
if (USART_RX_STA >= 9)
{
ou = (USART_RX_BUF[4] * 256 + USART_RX_BUF[5]) * 0.1;
printf("%.1f\n", ou);
USART_RX_STA = 0;
start = 0;
}
}
if (USART_RX_STA >= USART2_BUFFER_SIZE)
{
start = 0;
USART_RX_STA = 0;
}
}
}
}
上位机演示效果
Matlab代码:
曲线 代码
。
% 创建串口对象
s = serial('COM3'); % 将COMx替换为实际的串口号
set(s, 'BaudRate', 9600); % 设置串口波特率
fopen(s);
% 初始化数据缓冲区
N = 100; % 假设数据点的数量为 100
dataBuffer = zeros(N, 1); % N为数据点数
% 创建图形窗口
figure;
% 绘制空曲线
hLine = plot(dataBuffer, '-');
ylim([0, 100]); % 根据实际情况设置y轴范围
% 实时读取和绘制数据
while true
% 读取数据
data = fscanf(s, '%f'); % 根据实际的数据格式进行读取
% 更新数据缓冲区
dataBuffer = [dataBuffer(2:end); data];
% 更新曲线数据
set(hLine, 'YData', dataBuffer);
% 实时刷新图形
drawnow;
% 控制刷新频率,调整延时时间以控制刷新频率
pause(0.1);
end
% 关闭串口对象
fclose(s);
delete(s);
clear s;
效果展示
总结
这次的项目难度不大,是我学习的一个分享,后期将继续分享一些可以实战的项目,需要源码的可以留言,非常感谢。