基于STM32的485传感器数据收集
**单片机型号**:STM32F103ZET6(适用其他F1系列的)
**传感器**:超声波模块、DS18B20(温度传感器)、MQ-2(烟雾传感器)
数据显示:0.96OLED(IIC) 时钟(DS1302)
**数据传输**:485传输 (类似串口通信)
**连接方式**: PC(USB接口)---(USB)USB转485模块(A,B)--接--(A,B)485转TTL模块 (RX,TX)--接--STM32(TX,RX)
**数据接收**: PC端串口助手接受数据(此处用的是野火的调试助手)
(一)、传感器介绍
1.超声波模块
(1) 图片
(2)工作原理:
HC-SR04超声波测距模块可提供2cm-400cm的非接触式距离感测功能, 测距精度可达高到3mm;模块包括超声波发射器、接收器与控制电路。
(1)采用IO口TRIG触发测距,给至少10us的高电平信号;
(2)模块自动发送8个40khz的方波,自动检测是否有信号返回;
(3)有信号返回,通过IO口ECHO输出一个高电平,高电平持续的时间就是超声波从发射到返回的时间。
(3)超声波模块连接(以下为本代码中的样例,IO口可以自行进行配置)
超声波模块引脚(HC-SR04):
------------------------------------ TRIG—GPIOC-PIN2----------------------------------------
------------------------------------ ECHO—GPIOA-PIN4--------------------------------------
(4)代码
“shenbo.c”
#include "shenbo.h"
void TRIG_Config(void)
{
GPIO_InitTypeDef GPIO_InitStruct;//触发信号口初始化
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
GPIO_InitStruct.GPIO_Pin =GPIO_Pin_2; //选择端口号(0~15或all)
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; //输出触发信号(10us)
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; //设置IO接口速度(2/10/50MHz)
GPIO_Init(GPIOC, &GPIO_InitStruct);
}
void ECHO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStruct;//接收回响信号口初始化
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitStruct.GPIO_Pin =GPIO_Pin_4; //选择端口号(0~15或all)
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; //输入浮空
//GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; //设置IO接口速度(2/10/50MHz)
GPIO_Init(GPIOA, &GPIO_InitStruct);
}
“shenbo.h”
#ifndef __RANGING_H
#define __RANGING_H
#include "stm32f10x.h"
void TRIG_Config(void);//初始化
void ECHO_Config(void);
#endif
“main”主要部分(计算距离)
GPIO_SetBits(GPIOC, GPIO_Pin_2); //给10us高电平
Delay_us(11);//最少10us触发信号
GPIO_ResetBits(GPIOC, GPIO_Pin_2);//拉低电平
while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_4)==0);//等待接受高电平
TIMER_ON(); //定时器开
while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_4)==1);//等待接受低电平
TIMCounter = TIM_GetCounter(TIM6);//获取计数器值
TIMER_OFF(); //定时器关
Dis = TIMCounter/58;//计算距离
void TIM6_IRQHandler(void)
{
if ( TIM_GetITStatus( TIM6, TIM_IT_Update) != RESET )
{
TIM_ClearITPendingBit(TIM6 , TIM_FLAG_Update);
}
}
2.DHT11(温湿度传感器)
本实验采用的温度传感器模块,如果用单个DS18B20模块需要10K的上拉电阻,用于拉高总线。
(1)介绍及工作原理
单总线器件,支持多点组网功能,温度范围-55℃-+125℃,可编程的分辨率为9-12,分别对应0.5℃,0.25℃,0.125℃和0.0625℃高精度测温。
DQ端为数字输入输出端,开漏单总线引脚。不再需要外接AD电路转换成数字信号,也就是能将温度信号转换成数字信号。通过与微控制器(STM32)IO口进行数据的传输读取。
(2)连接方式(根据自己所需的IO口进行初始化等设置,本代码中采用PB7)
----------------------------------DQ—GPIOB-PIN7-----------------------------------
(3)代码
通过RAM指令表的约定代码对相应指令进行读取
严格按照时序图进行相应的编程
分为初始化、读时序、
“DS18B20.c”
#include "stdio.h"
#include "systick_delay.h"
#include "DS18B20.h"
#include "stm32f10x.h"
//配置成输出模式
void DS18B20_Out(void)
{
GPIO_InitTypeDef GPIO_InitStructure;//------------------------------第一步:串口的GPIO初始化
// 打开DQ引脚的时钟
DEBUG_DS18B20_APBxClkCmd(DEBUG_DS18B20_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = DEBUG_DS18B20_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;//
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DEBUG_DS18B20_GPIO_PORT, &GPIO_InitStructure);//其中第一个是指针,第二个是名字所以需要&取地址
}
//配置成输入模式
void DS18B20_Input(void)
{
GPIO_InitTypeDef GPIO_InitStructure;//------------------------------第一步:串口的GPIO初始化
// 打开DQ引脚的时钟
DEBUG_DS18B20_APBxClkCmd(DEBUG_DS18B20_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = DEBUG_DS18B20_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//因为发送,推挽复用输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DEBUG_DS18B20_GPIO_PORT, &GPIO_InitStructure);//其中第一个是指针,第二个是名字所以需要&取地址
}
void Ds18b20_Init()
{
uint8_t i=0;
DS18B20_Out();
GPIO_ResetBits(GPIOB,GPIO_Pin_7);
Delay_us(480);
GPIO_SetBits(GPIOB,GPIO_Pin_7);
DS18B20_Input();
while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_7)&&(i<200))
i++;
}
void Ds18b20WriteByte(uint8_t a)
{
uint8_t i=0;
uint8_t b=0x01;
uint8_t c=0;
DS18B20_Out();
for(i=0;i<8;i++)
{
c=b&a;
if(c)
{
GPIO_ResetBits(GPIOB,GPIO_Pin_7);
Delay_us(15);
GPIO_SetBits(GPIOB,GPIO_Pin_7);
Delay_us(40);
}
else
{
GPIO_ResetBits(GPIOB,GPIO_Pin_7);
Delay_us(60);
GPIO_SetBits(GPIOB,GPIO_Pin_7);
}
b=b<<1;
}
GPIO_SetBits(GPIOB,GPIO_Pin_7);
}
uchar Ds18b20ReadByte()
{
uint8_t a=0;
uint8_t i=0;
for(i=0;i<8;i++)
{
DS18B20_Out();
GPIO_ResetBits(GPIOB,GPIO_Pin_7);
Delay_us(1);
GPIO_SetBits(GPIOB,GPIO_Pin_7);
DS18B20_Input();
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_7))
{
a=a>>1;
a=a|0x80;
}
else
{
a=a>>1;
}
Delay_us(50);
DS18B20_Out();
GPIO_SetBits(GPIOB,GPIO_Pin_7);
}
return(a);
}
void Ds18b20ChangeTemp(){
Ds18b20_Init();
Delay_ms(1);
Ds18b20WriteByte(0xcc);//跳过ROM直接发送温度转换命令
Ds18b20WriteByte(0x44);//发送指令RAM设为0x44为温度变换
}
void Ds18b20ReadTempCom(){
Ds18b20_Init();
Delay_ms(1);
Ds18b20WriteByte(0xcc);//跳过ROM直接发送温度转换命令
Ds18b20WriteByte(0xbe);//发送指令RAM设为0xBE为读暂时寄存器
}
int Ds18b20ReadTemp(void){
int temp=0;
uchar tml,tmh;
Ds18b20ChangeTemp();
Ds18b20ReadTempCom();
tml=Ds18b20ReadByte();//读低8位数据
tmh=Ds18b20ReadByte();//读高8位数据
temp=tmh;
temp<<=8;
temp|=tml;//拼接为16位数据
return temp;//返回16位数据
}
4.OLED显示(0.96寸+IIC)
显示超声波测距、温度、烟雾等参数。
(1)工作原理:IIIC控制
(2)连接方式:
------------------------------------ SCL—GPIOB-PIN13----------------------------------------
------------------------------------ SDA—GPIOA-PIN15----------------------------------------
(3)代码:
DS1302时钟模块
为了取得定时效果,一共两个方案。第一种通过STM32内部自带的RTC进行时间定时,第二种就是通过DS1302时钟模块进行定时。通过资料的查找与实验,在项目中使用RTC虽说时间误差能减到很小但是所需晶振的精度和温漂要求更高,操做不当对时间有很大的影响,而DS1302的精度高、时间的测量定时也更加的稳定。因此我们采用DS1302模块。
心得:不同于51是通过准双向口驱动该时钟模块,我们采用的STM32是双向IO口进行读写设置,需要关注输入输出配置,所以我们在配置成开漏输出模式的时候外接40k的上拉电阻避免读出全是低电平的情况。
然后通过时序图进行相应的编程
单字节的读写—>整个数据的读写—>时间的读写
第一次写博客,后续会继续补完