OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 2317|回复: 4

请教各位大神,为什么用酒精检测模块MQ-3的输出引脚做触发却进入不了中断函数

[复制链接]

2

主题

12

帖子

0

精华

初级会员

Rank: 2

积分
51
金钱
51
注册时间
2017-1-12
在线时间
9 小时
发表于 2017-2-25 10:42:33 | 显示全部楼层 |阅读模式
10金钱
       各位大神你们好,本人因项目需求,需要做一个酒精检测触发OLED显示屏显示内容和GSM模块发送短信的装置,现在已有的材料是淘宝上买的stm32最小系统板(stm32f103rct6),酒精检测模块用的是淘宝上的MQ-3模块,OLED显示屏模块是I2C的128×64的模块,短信模块是GSM A6 mini模块。      
       其中酒精检测模块我选用的是其D0引脚,输出的是TTL电平。
以下是硬件连接:
                    模块                                 最小系统板(stm32f103rct6)
               MQ-3的VCC             接                5V电源
               MQ-3的GND            接                GND
               MQ-3的D0               接                PB01      (其中当酒精模块检测到空气中有酒精分子的时候,D0输出低电平有效)


           OLED显示屏VCC          接                5V电源
           OLED显示屏GND          接                GND
           OLED显示屏SCL           接                 PB06
           OLED显示屏SDA           接                PB07


           GSM模块VCC               接                 5V电源
           GSM模块GND              接                 GND
           GSM模块UARST RX      接                 PA02
           GSM模块UARST TX      接                 PA03

以下是软件设计:

extern const unsigned char BMP1[];       
int main(void)
{       
        unsigned char j;         
        delay_init();                                                             //延时函数初始化       
        USART2_Init_Config(115200);                             //串口2初始化为115200
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
       
/********初始化显示屏***************/
        I2C_Configuration();                //初始化I2C和GPIOB口         
        OLED_Init();                      //初始化OLED
        OLED_Fill(0xFF);                        //全屏点亮
        delay_ms(1000);
        OLED_Fill(0x00);                        //全屏灭
        delay_ms(1000);
/********初始化指示灯***************/
        LED_Init();                                          //初始化与LED连接的硬件接口
        MQ3_Init();                                 //初始化酒精传感器
        Wait_CREG();                                    //查询等待模块注册成功
        Set_Text_Mode();                        //设置短信为TEXT模式
/********初始化中断*****************/       
        EXTIX_Init();
        while(1)
        {
                for(j=5;j<8;j++)
                {
                        OLED_ShowCN(1+j*16,0,j);//测试显示中文
                };
        }
}
/********串口2初始化函数 ***************/
void USART2_Init_Config(u32 bound)                             //串口2初始化函数
{
        GPIO_InitTypeDef  GPIO_InitStructure;
        USART_InitTypeDef USART_InitStructure;
        NVIC_InitTypeDef  NVIC_InitStructure;
       
        /*使能USART2外设时钟*/  
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);       
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);       
       
        /*复位串口2*/
        USART_DeInit(USART2);  
       
        /*USART2_GPIO初始化设置*/
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;                                      //USART2_TXD(PA.2)     
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                      //复用推挽输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;              //设置引脚输出最大速率为50MHz
        GPIO_Init(GPIOA, &GPIO_InitStructure);                                      //调用库函数中的GPIO初始化函数,初始化USART1_TXD(PA.9)  


        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;                                        //USART2_RXD(PA.3)
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;        //浮空输入
        GPIO_Init(GPIOA, &GPIO_InitStructure);                                        //调用库函数中的GPIO初始化函数,初始化USART1_RXD(PA.10)


        /*USART2 初始化设置*/
        USART_InitStructure.USART_BaudRate = bound;                                                                                //设置波特率
        USART_InitStructure.USART_WordLength = USART_WordLength_8b;                                                //8位数据格式
        USART_InitStructure.USART_StopBits = USART_StopBits_1;                                                                //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);                                                                                //初始化串口2

         /*Usart2 NVIC配置*/
        NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;                                                                 //抢占优先级2
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;                                                                          //从优先级2
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                                                                           //使能IRQ通道使能
        NVIC_Init(&NVIC_InitStructure);                                                                                                           //根据指定的参数初始化VIC寄存器
          
        USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);                                                                           //使能串口2接收中断

        USART_Cmd(USART2, ENABLE);                                                                                                       //使能串口
        USART_ClearFlag(USART2, USART_FLAG_TC);                                                                                  //清除发送完成标志
}
/********LED初始化***************/
void LED_Init(void)
{

       GPIO_InitTypeDef  GPIO_InitStructure;
       
       RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);         //使能PD
       
       GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;                                         //LED0-->PD2端口配置
       GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                          //推挽输出
       GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                         //IO口速度为50MHz
       GPIO_Init(GPIOD, &GPIO_InitStructure);                                         //根据设定参数初始化GPIOD2
       GPIO_ResetBits(GPIOD,GPIO_Pin_2);                                                 //PD2 输出低,灯不亮
}
/********MQ-3酒精模块初始化***************/
void         MQ3_Init(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;
       
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;                                    //PB1 低电平输入
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;                           //上拉电阻输入(其中PB01为低电平有效)
        GPIO_Init(GPIOB, &GPIO_InitStructure);       
}
/********中断初始化函数***************/
void EXTIX_Init(void)
{
        EXTI_InitTypeDef EXTI_InitStructure;
        NVIC_InitTypeDef NVIC_InitStructure;
       
        MQ3_Init();                                                                                    //初始化酒精传感器
       
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);             //使能AFIO时钟
       
        GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource1);     
        EXTI_InitStructure.EXTI_Line=EXTI_Line1;                                       //设置为中断线1中断
        EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;                      //设置为中断模式为打断
        EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;                     //设置为下降沿触发(因为酒精模块低电平有效)
        EXTI_Init(&EXTI_InitStructure);                                                              //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器

        NVIC_InitStructure.NVIC_IRQChannel=EXTI1_IRQn;                          //设置为中断线1中断通道
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;                //抢占优先级1
        NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;                           //从优先级0
        NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;                          //使能IRQ通道使能
        NVIC_Init(&NVIC_InitStructure);
}
/********外部中断线1的中断函数*********/
void EXTI1_IRQHandler(void)
{
/********设置变量在显示屏用**********/
        unsigned char i;
        delay_ms(10);
        if(PBin(1)==0)                                                                                 //通过位操作判断PB01是否是低电平,是低电平的时候表示酒精模块检测到空气中有酒精分子
                {
                        PDout(2)=1;                                                                    //让LED亮,代表酒精模块分子处于正常工作
                        for(i=0;i<4;i++)
                        {
                                OLED_ShowCN(22+i*16,0,i);                                     //测试显示中文
                        };
                         Send_Text_Sms();                                                           //发送一条短消息               
                }       
}

出现的问题:
      (1)、将以上程序烧入单片机最小系统板后,并将检测酒精放置在酒精模块附近,酒精模块自带的工作指示LED显示模块处于工作状态。但是无法进入中断,执行中断函数。
      (2)、如果该程序不使用中断函数,使用if语句进行对PB01的判断,那么程序可以继续运行。
      (3)、本人现在对I2C_Configuration();        这个函数理解的还不够深刻,通过单步调试的时候,程序会卡死在该程序中。该程序在下面希望大神指点我一下,为什么会卡死在里面。
void I2C_Configuration(void)
{
        I2C_InitTypeDef  I2C_InitStructure;
        GPIO_InitTypeDef  GPIO_InitStructure;

        RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);

        /*STM32F103C8T6芯片的硬件I2C: PB6 -- SCL; PB7 -- SDA */
        GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_6 | GPIO_Pin_7;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;//I2C必须开漏输出
        GPIO_Init(GPIOB, &GPIO_InitStructure);

        I2C_DeInit(I2C1);//使用I2C1
        I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
        I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
        I2C_InitStructure.I2C_OwnAddress1 = 0x30;//主机的I2C地址,随便写的
        I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
        I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
        I2C_InitStructure.I2C_ClockSpeed = 400000;//400K

        I2C_Cmd(I2C1, ENABLE);
        I2C_Init(I2C1, &I2C_InitStructure);
}

void I2C_WriteByte(uint8_t addr,uint8_t data)
{
  while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
       
        I2C_GenerateSTART(I2C1, ENABLE);//开启I2C1   
        while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));/*EV5,主模式*/               单步调试,程序卡死在一句。

        I2C_Send7bitAddress(I2C1, OLED_ADDRESS, I2C_Direction_Transmitter);//器件地址 -- 默认0x78
        while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

        I2C_SendData(I2C1, addr);//寄存器地址
        while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

        I2C_SendData(I2C1, data);//发送数据
        while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
       
        I2C_GenerateSTOP(I2C1, ENABLE);//关闭I2C1总线
}


谢谢,大神帮我看一下,现在急需解决这个问题,后面还有别的模块会陆续添加进来

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165359
金钱
165359
注册时间
2010-12-1
在线时间
2110 小时
发表于 2017-2-25 21:28:34 | 显示全部楼层
回复

使用道具 举报

2

主题

12

帖子

0

精华

初级会员

Rank: 2

积分
51
金钱
51
注册时间
2017-1-12
在线时间
9 小时
 楼主| 发表于 2017-2-26 13:21:40 | 显示全部楼层

谢谢原子哥  麻烦问一下原子哥这个是怎么回事
回复

使用道具 举报

1

主题

3

帖子

0

精华

新手上路

积分
33
金钱
33
注册时间
2017-4-10
在线时间
3 小时
发表于 2017-4-25 17:04:14 | 显示全部楼层
你解决了吗?我也是想做酒精检测,有资料借鉴吗?
回复

使用道具 举报

2

主题

12

帖子

0

精华

初级会员

Rank: 2

积分
51
金钱
51
注册时间
2017-1-12
在线时间
9 小时
 楼主| 发表于 2017-7-13 19:08:12 | 显示全部楼层
等鱼的熊大 发表于 2017-4-25 17:04
你解决了吗?我也是想做酒精检测,有资料借鉴吗?

现在还是没有  老师把这个项目给改了  进入中断进不去,但是不用中断函数是可以实现的
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-12-18 18:45

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表