初级会员
- 积分
- 51
- 金钱
- 51
- 注册时间
- 2017-1-12
- 在线时间
- 9 小时
|
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总线
}
谢谢,大神帮我看一下,现在急需解决这个问题,后面还有别的模块会陆续添加进来
|
|