STM32固件库案例:串口通信与OLED显示MQ135烟雾传感器

STM32固件库案例——串口、7针脚OLED显示MQ135烟雾传感器

本章基于本人前面发的SPI驱动7针脚OLED屏幕文档。加入通过ADC模块对MQ135烟雾传感器的数值进行采样并在OLED上显示以及串口上打印。
一、MQ135烟雾传感器模块
正面:

背面

接线:
烟雾模块  STM32开发板
AO —— PA0
VCC —— 3.3V
GND —— GND
二、ADC模块介绍:
ADC模块中文名为模拟/数字转换器,是12位逐次逼近型的模拟数字转换器,一般用于数值的采样,比如我最近在做一个示波器,那么就需要对信号进行采样,这就需要用到ADC模块。
将ADC模块与自己定义的引脚相连,再用该引脚去接入所要测试的地方,ADC模块便可以经过换算得到所要测试部位的电位。
三、ADC配置库函数解读:
1、初始化函数ADC_Init

void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct)

功能:

typedef struct
{
  uint32_t ADC_Mode;                    //将ADC配置为独立或操作双模式。


  FunctionalState ADC_ScanConvMode;//执行转换Scan(多通道)或Single(单通道)模式,可设置为“ENABLE”或“DISABLE” */

  FunctionalState ADC_ContinuousConvMode; //执行转换连续或单模。可设置为“ENABLE”或“DISABLE”

  uint32_t ADC_ExternalTrigConv;          //定义用于启动模拟的外部触发器对常规信道进行数字转换 

  uint32_t ADC_DataAlign;                 //指定ADC数据是左对齐还是右对齐。 

  uint8_t ADC_NbrOfChannel;        //指定要转换的ADC通道的数量使用顺序器为常规通道组。取值范围为1 ~ 16
}ADC_InitTypeDef;

ADC结构体配置如下(本次为单通道模数转换):

ADC_InitTypeDef ADC_InitStructure;        //定义ADC结构体
ADC_InitStructure.ADC_ScanConvMode = DISABLE;        //单通道模式    
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;        //单次转换模式    
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;        //ADC独立模式
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;        //ADC数据右对齐
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;        //转换由软件启动
ADC_InitStructure.ADC_NbrOfChannel = 1;        //顺序进行规则转换的ADC通道数目
ADC_Init(ADC1, &ADC_InitStructure);        //初始化ADC1外设
ADC_Cmd(ADC1, ENABLE);        //使能ADC1

ADC的通道相对应的引脚做一个补充,如下图:

四、下面为ADC模块的整体代码,
ADC.c文件

#include "stm32f10x.h"                  // Device header

void Adc_init(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);        //使能ADC1通道时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);        //使能GPIOA通道时钟
    
    RCC_ADCCLKConfig(RCC_PCLK2_Div6);    //设置ADC分频因子这里为6分频
    
    GPIO_InitTypeDef GPIO_InitStructure;        //定义结构体
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;        //模拟输入
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;        //GPIOA.0引脚
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        //速度50MHz
     GPIO_Init(GPIOA, &GPIO_InitStructure);        //初始化gpioa
    
    ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);//ADC1,通道0(GPIOA.0),采样顺序为1,采样周期为55.5个周期
    
    ADC_InitTypeDef ADC_InitStructure;        //定义ADC结构体
    ADC_InitStructure.ADC_ScanConvMode = DISABLE;        //单通道模式    
    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;        //单次转换模式    
    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;        //ADC独立模式
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;        //ADC数据右对齐
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;        //转换由软件启动
    ADC_InitStructure.ADC_NbrOfChannel = 1;        //顺序进行规则转换的ADC通道数目
    ADC_Init(ADC1, &ADC_InitStructure);        //初始化ADC1外设
    
    ADC_Cmd(ADC1, ENABLE);        //使能ADC1
    
    ADC_ResetCalibration(ADC1);        //开启复位校准
    while (ADC_GetResetCalibrationStatus(ADC1) == SET);        //等待复位校准结束
    ADC_StartCalibration(ADC1);        //开启AD校准
    while (ADC_GetCalibrationStatus(ADC1) == SET);        //等待校准结束
}

uint16_t Adc_GetValue(void)
{
        ADC_SoftwareStartConvCmd(ADC1, ENABLE);        //使能软件转换功能
          while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);        //等待转换结束
        return ADC_GetConversionValue(ADC1);        //返回最近一次ADC1规则组的转换结果
}

ADC.h文件

#ifndef __ADC_H
#define __ADC_H

void Adc_init(void);
uint16_t Adc_GetValue(void);

#endif

五、串口打印数据
我们需要导入我们的USART函数
用printf串口打印接收到的数值我们需要在串口代码中加入串口重定向

int fputc(int ch,FILE *f)
{
    Usart_SendByte(ch);
    return ch;
}

main.c文件

uint16_t ADValue;
float Voltage;

int main(void)
{
    
    Usart_Init();
    Adc_init();
    NVIC_Configuration();        //设置NVIC中断分组2:2位抢占优先级,2位响应优先级     
    OLED_Init();                     //初始化OLED  
    OLED_Clear(0);             //清屏(全黑)
    
    while (1)
    {

        ADValue = Adc_GetValue();
        Voltage = (float)ADValue / 4095 * 3.3;
//        GUI_ShowCHinese(0,20,16,"数值:",1);
//        GUI_ShowNum(30,20,ADValue,6,16,1);//oled显示数字
        printf("检测到的数值为  %d, 转换后的电压值为: %.1f V\n", ADValue, Voltage);        
        Delay_ms(1000);
    }
}

结果展示:

6、7针脚OLED显示数值

显示中文(GUI_ShowCHinese)
x:中文字符串的起始x坐标
y:中文字符串的起始y坐标
hsize:中文字符串的大小
*str:中文字符串的起始地址
模式:       0-白底黑字,1-黑底白字
void GUI_ShowCHinese(u8 x,u8 y,u8 hsize,u8 *str,u8 mode)
{ 
    while(*str!='\0')
    {
        if(hsize == 16)
        {
            GUI_ShowFont16(x,y,str,mode);
        }
        else if(hsize == 24)
        {
            GUI_ShowFont24(x,y,str,mode);
        }
        else if(hsize == 32)
        {
            GUI_ShowFont32(x,y,str,mode);
        }
        else
        {
            return;
        }
        x+=hsize;
        if(x>WIDTH-hsize)
        {
            x=0;
            y+=hsize;
        }
        str+=2;
    }            
}

显示数值(GUI_ShowNum)

x:                数字的开始坐标x
Y:                数字的起始Y坐标
num:              (0 ~ 4294967295)
Len:              显示号的长度
大小:             显示编号的大小
模式:             0-白底黑字,1-黑底白字
void GUI_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 Size,u8 mode)
{             
    u8 t,temp;
    u8 enshow=0,csize;
  if(Size == 16)
  {
      csize = Size/2;
    }
  else if(Size == 8)
  {
      csize = Size/2+2;
    }     
    else
    {
        return;
    }
    for(t=0;t<len;t++)
    {
        temp=(num/mypow(10,len-t-1))%10;
        if(enshow==0&&t<(len-1))
        {
            if(temp==0)
            {
                GUI_ShowChar(x+csize*t,y,' ',Size,mode);
                continue;
            }else enshow=1; 
              
        }
         GUI_ShowChar(x+csize*t,y,temp+'0',Size,mode); 
    }
}  

main.c

int main(void)
{
    
    Usart_Init();
    Adc_init();
    NVIC_Configuration();        //设置NVIC中断分组2:2位抢占优先级,2位响应优先级     
    OLED_Init();                     //初始化OLED  
    OLED_Clear(0);             //清屏(全黑)
    
    while (1)
    {

        ADValue = Adc_GetValue();
        Voltage = (float)ADValue / 4095 * 3.3;
        GUI_ShowCHinese(0,20,16,"数值:",1);
        GUI_ShowNum(30,20,ADValue,6,16,1);//oled显示数字
//        printf("检测到的数值为:%d  电压值为:%.1fV\n", ADValue, Voltage);        
        Delay_ms(1000);
    }
}

最后效果图

作者:初心远隔山河

物联沃分享整理
物联沃-IOTWORD物联网 » STM32固件库案例:串口通信与OLED显示MQ135烟雾传感器

发表评论