如何给网站做app,唐山网站建设多少钱,北京官网seo推广,成都园林景观设计公司推荐文章目录 需求一、KQM6600模块及接线方法二、模块配置流程1.环境2.配置时钟和IO3.配置串口初始化#xff0c;使能以及中断4.中断函数 三、数据处理四、关键代码总结 需求
能够在串口实时显示当前的VOC#xff08;挥发性有机化合物#xff09;#xff0c;甲醛和Co2浓度。 … 文章目录 需求一、KQM6600模块及接线方法二、模块配置流程1.环境2.配置时钟和IO3.配置串口初始化使能以及中断4.中断函数 三、数据处理四、关键代码总结 需求
能够在串口实时显示当前的VOC挥发性有机化合物甲醛和Co2浓度。 一、KQM6600模块及接线方法
KQM6600TAUs型空气质量检测模块使用MEMS VOC传感器件作为检测空气中有机化合物气体VOC的模块。UART通信数据输出根据VOC数据计算和等效甲醛CO2输出。其具有体积小功耗低灵敏度高响应速度快等居多优点广泛应用在空气质量检 测及控制领域。 要注意该模块的电压和波特率。 由官方的说明书可知只需在将该模块的V供电ATX和GGND三个引脚接到板子上即可。 本次例程由于没有使用SD卡模块所以选择将KQM6600模块的数据传输到UART4上只需将该模块的ATX接到PC11即可。
二、模块配置流程
1.环境
1.首先要保证串口1能够将接收到的实时数据发送到串口上。 2.还要对printf进行重定向让其能够打印到串口上。详情见STM32第三课串口调试 代码如下 usart.c
#include usart.h
#include stdio.hvoid Usart1_Config()
{//开时钟GPIOAUSART1RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA,ENABLE);//配置对应的IO口 PA9tx:复用推挽 PA10RX浮空输入GPIO_InitTypeDef GPIO_InitStruct {0};GPIO_InitStruct.GPIO_Mode GPIO_Mode_AF_PP;GPIO_InitStruct.GPIO_Pin GPIO_Pin_9;GPIO_InitStruct.GPIO_Speed GPIO_Speed_50MHz;GPIO_Init(GPIOA,GPIO_InitStruct);GPIO_InitStruct.GPIO_Mode GPIO_Mode_IN_FLOATING;GPIO_InitStruct.GPIO_Pin GPIO_Pin_10;GPIO_Init(GPIOA,GPIO_InitStruct);//配置串口1 8数据位0校验位1停止位波特率115200USART_InitTypeDef USART_InitStruct {0};//可以通过结构体类型跳转USART_InitStruct.USART_BaudRate 115200;//波特率USART_InitStruct.USART_HardwareFlowControl USART_HardwareFlowControl_None;//硬件控制流不开USART_InitStruct.USART_Mode USART_Mode_Tx|USART_Mode_Rx;//打开发送和接收USART_InitStruct.USART_Parity USART_Parity_No;USART_InitStruct.USART_StopBits USART_StopBits_1;USART_InitStruct.USART_WordLength USART_WordLength_8b;USART_Init(USART1,USART_InitStruct);USART_Cmd(USART1,ENABLE);//配置串口1的中断//在串口1产生接收的时候会产生中断我们直接去中断函数里面处理就可以了//选择串口1的中断原因USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//USART1-CR1 | 0x15;//使能串口1的接收非空中断NVIC_SetPriority(USART1_IRQn,7);//设置优先级0~15NVIC_EnableIRQ(USART1_IRQn);//使能中断通道
}void SendData(uint8_t data)
{while((USART1-SR0x016)0){}//等待上次发送完成USART1-DR data;//发送数据
}int fputc(int ch, FILE *f)
{//printf函数最终会跳转到这里来运行while((USART1-SR0x16)0);//发送数据USART1-DR (uint8_t)ch;return ch;
}void USART1_IRQHandler(void)
{uint8_t data0;if((USART1-SR0x15)!0){//执行该中断函数的原因有很多所以判断一下是不是接收导致的//接收数据data USART_ReceiveData(USART1);//读操作同时也是清空中断标志位USART_SendData(USART1, data); }
}usart.h
#ifndef _USART_H_
#define _USART_H_
#include stm32f10x.h
#include stdio.hvoid Usart1_Config();
void SendData(uint8_t data);
int fputc(int ch, FILE *f);#endif
2.配置时钟和IO
首先创建一个kqm.c.h文件用来专门配置该模块 和串口1一样只不过要注意此时是UART4引脚为PC11。 //开时钟 U4 PC11RXRCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4,ENABLE);//配置ioGPIO_InitTypeDef GPIO_InitStruct {0};GPIO_InitStruct.GPIO_Mode GPIO_Mode_IN_FLOATING;GPIO_InitStruct.GPIO_Pin GPIO_Pin_11;GPIO_InitStruct.GPIO_Speed GPIO_Speed_50MHz;GPIO_Init(GPIOC,GPIO_InitStruct);3.配置串口初始化使能以及中断 初始化要将波特率改为9600然后只用打开接收就行其他与串口1一样。 使能就不说了改个参数就行。 中断也一样只用改改参数。 //配置串口 波特率9600 数据位8校验位0停止位1USART_InitTypeDef USART_InitStruct {0};//可以通过结构体类型跳转USART_InitStruct.USART_BaudRate 9600;//波特率USART_InitStruct.USART_HardwareFlowControl USART_HardwareFlowControl_None;//硬件控制流不开USART_InitStruct.USART_Mode USART_Mode_Rx;//打开接收USART_InitStruct.USART_Parity USART_Parity_No;USART_InitStruct.USART_StopBits USART_StopBits_1;USART_InitStruct.USART_WordLength USART_WordLength_8b;USART_Init(UART4,USART_InitStruct);//使能串口USART_Cmd(UART4,ENABLE);//配置串口4的中断(采用中断接收)USART_ITConfig(UART4,USART_IT_RXNE,ENABLE);//使能串口4 的接收非空中断USART_ITConfig(UART4,USART_IT_IDLE,ENABLE);//总线空闲中断NVIC_SetPriority(UART4_IRQn,7);//设置优先级0~15NVIC_EnableIRQ(UART4_IRQn);//使能中断通道4.中断函数
依旧是先去启动文件中找到该串口的中断函数复制过来。 然后使用USART_GetITStatus函数进行标志位判断若为1则代表传输完成。 由于数据位为8位所以此时需要定义一个数组来存放这8位数组。 还需要定义一个参数来计数每当存放够8位时清0再从头开始覆盖存入数据。此刻就完成了8位数据获取。 uint8_t data0;//判断接收中断是否发生if(USART_GetITStatus(UART4,USART_IT_RXNE)SET){data UART4-DR;u4recive[u4count]data;u4count;u4count%8;//USART1-DR data;//回显}为了判断该模块是否传输完数据此时我们要使用一个新的知识中断空闲 USART_GetITStatus(UART4,USART_IT_IDLE) 当结尾时IDLE时就代表此时判断的是中断空闲。 当中断空闲被置为1时就代表示总线空闲8位数据传完了接收完毕。此时想要清理中断空闲的话需要先读SR再读DR。 然后在设置一个标志位u4flag将其置为1代表接收完毕。 //触发空闲中断表示总线空闲接收完毕if(USART_GetITStatus(UART4,USART_IT_IDLE)SET){data UART4-SR;//清理空闲中断先读SR再读DRdata UART4-DR;u4flag1;}三、数据处理
先判断标志位u4flag是否为0若为0这直接退出不进入数据处理函数。 由手册可知该模块有预热操作为了屏蔽掉预热操作的数据此时需要判断传输过来的8位数组检查是否每位都为0xff只要有一位不是就继续进行否则向串口打印‘数据预热’。 if(u4flag0){return 0;}u4flag0;for(i1;i7;i){if(u4recive[i]!0xff){break;}}if(i7){u4count0;printf(数据预热\r\n);memset(u4recive,0,102);return 0;}
以上都没有问题之后此时获取到的数组才是真正有用的数据。 由手册可知该数据的转换模式照着做就行。记得用完将数据位和标志位都清零。 voc((u4recive[1]8)u4recive[2])*0.11;ch2o ((u4recive[3]8)u4recive[4])*0.01;co2 ((u4recive[5]8)u4recive[6]);printf(VOC %.1f PPM\r\n甲醛 %.2f MG/M3\r\nCo2 %.0fPPM\r\n,voc,ch2o,co2);u4count0;memset(u4recive,0,102);return 0;最后记得将处理函数添加到主函数的while1死循环中。 由于串口4用到了串口1输出所以在main函数的配置应在串口1的后面。
四、关键代码
main.c
#include stm32f10x.h
#include usart.h
#include stdio.h
#include delay.h
#include kqm.h
#include string.hint main()
{NVIC_SetPriorityGrouping(5);//两位抢占两位次级Usart1_Config(); Kqm_U4Config();while(1){ KQM_DealData();}
}kqm.c
#include stm32f10x.h
#include stdio.h
#include string.hfloat voc,ch2o,co2;
void Kqm_U4Config()
{//开时钟 U4 PC11RXRCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4,ENABLE);//配置ioGPIO_InitTypeDef GPIO_InitStruct {0};GPIO_InitStruct.GPIO_Mode GPIO_Mode_IN_FLOATING;GPIO_InitStruct.GPIO_Pin GPIO_Pin_11;GPIO_InitStruct.GPIO_Speed GPIO_Speed_50MHz;GPIO_Init(GPIOC,GPIO_InitStruct);//配置串口 波特率9600 数据位8校验位0停止位1USART_InitTypeDef USART_InitStruct {0};//可以通过结构体类型跳转USART_InitStruct.USART_BaudRate 9600;//波特率USART_InitStruct.USART_HardwareFlowControl USART_HardwareFlowControl_None;//硬件控制流不开USART_InitStruct.USART_Mode USART_Mode_Rx;//打开接收USART_InitStruct.USART_Parity USART_Parity_No;USART_InitStruct.USART_StopBits USART_StopBits_1;USART_InitStruct.USART_WordLength USART_WordLength_8b;USART_Init(UART4,USART_InitStruct);//使能串口USART_Cmd(UART4,ENABLE);//配置串口4的中断(采用中断接收)USART_ITConfig(UART4,USART_IT_RXNE,ENABLE);//使能串口4 的接收非空中断USART_ITConfig(UART4,USART_IT_IDLE,ENABLE);//总线空闲中断NVIC_SetPriority(UART4_IRQn,7);//设置优先级0~15NVIC_EnableIRQ(UART4_IRQn);//使能中断通道
}uint8_t u4recive[102]{0};
uint8_t u4count0;
uint8_t u4flag0;
uint8_t i0;void UART4_IRQHandler(void)
{uint8_t data0;//判断接收中断是否发生if(USART_GetITStatus(UART4,USART_IT_RXNE)SET){data UART4-DR;u4recive[u4count]data;u4count;u4count%8;//USART1-DR data;//回显}//触发空闲中断表示总线空闲接收完毕if(USART_GetITStatus(UART4,USART_IT_IDLE)SET){data UART4-SR;//清理空闲中断先读SR再读DRdata UART4-DR;u4flag1;}}uint8_t KQM_DealData()
{if(u4flag0){return 0;}u4flag0;for(i1;i7;i){if(u4recive[i]!0xff){break;}}if(i7){u4count0;printf(数据预热\r\n);memset(u4recive,0,102);return 0;}voc((u4recive[1]8)u4recive[2])*0.11;ch2o ((u4recive[3]8)u4recive[4])*0.01;co2 ((u4recive[5]8)u4recive[6]);printf(VOC %.1f PPM\r\n甲醛 %.2f MG/M3\r\nCo2 %.0fPPM\r\n,voc,ch2o,co2);u4count0;memset(u4recive,0,102);return 0;
}
kqm.h
#ifndef _KQM_H_
#define _KQM_H_
#include stm32f10x.h
void Kqm_U4Config();
uint8_t KQM_DealData();#endif
其他代码遇上几节课一样。 总结
1.学会了KQM6600空气质量传感器模块的接线和配置。 2.学会了使用空闲中断以及数据的获取与处理。