1.传感器简介
智能终端是在感知层,如果想要感知采集数据必定需要使用传感器
市面上的传感器有很多:
检测气体的 温度 湿度 稀有气体含量(CO CO2 O2 甲醛 乙醇 甲烷 …)
检测液体的 温度 PH值 浑浊 液位
检测固体的 湿度 元素含量
检测人体 温度 血压 心率 血糖…传感器的接口也有很多:
GPIO接口 串口接口(USART/UART IIC IIS SPI …) 并口接口数字型传感器 和 模拟型传感器
传感器可以从采集种类、接口种类、采集到的数据种类分为很多种
串口与并口
串口:串行的接口或者串行的通信接口|串行的通讯接口,是指数据按照串行的方式进行传输(是指数据一位一位进行传输)
并口:并行的接口或者并行的通信接口|并行的通讯接口,是指数据按照并行的方式进行传输(是指数据多位多位进行传输)
注意:并不是说并口可以一次发送多位数据就说明并口比串口通信快,实际上正好相反,串口通信速度要比并口快
并口有很多的限制,(数据线与数据线之间会有电平干扰、需要同时发送同时接收)
单工与半双工
单工模式 A–>---->–B
半双工模式 A–>----<–B
全双工模式 ---->-----
略…
上拉电阻:是用来供应电流的
下拉电阻:是用来分担电流的
2.DHT11传感器
从手册中了解DHT11传感器:
- 是用来采集温度和湿度的传感器
- 采集到的是数字量
- 4管脚的封装形式
- 采集的范围:湿度 : 20% - 90%(误差:±5%),温度 : 0℃ - 50℃(误差:±2℃),
- 分辨力 : 1(指的是采集的精度<只能采集整数部分>)
- 连接方式:一个管脚用来接电源,一个管脚用来接地,一个管脚用来接MCU,一个管脚悬空(NC<没有连接>)
- 串行接口:是指数据按照串行的方式进行传输
- 单线双向(半双工的工作模式):指的是串行接口的工作模式
单工模式,半双工模式,全双工模式 - 一次完整的数据传输为40bit<5个字节>,高位先出
8bit湿度整数数据+8bit湿度小数数据
+8bit温度整数数据+8bit温度小数数据
+8bit校验和
数据传送正确时校验和数据等于“8bit湿度整数数据+8bit湿度小数数据 +8bi温度整数数据+8bit温度小数数据”所得结果的末8位。 - 软件有软件的协议,硬件也有硬件的协议:硬件的协议就是读写时序,读写时序都是官方定义出来的
例子:DHT11在出产的时候,官方就已经定义好了一套读写时序,MCU想要和DHT11交互数据,就需要让MCU遵守DHT11的读写时序 - 分析DHT11的读写时序
串行接口收发数据
需要把形参c保存的8bit二进制数据,通过高位先出的方式进行传输
假设:MCU连接了PC9管脚,可以使用位带发数据PCOut(9) 收数据PCIn(9)
数据线低电平代表数据0,数据线高电平代表数据1
/*发送数据*/
void func(u8 c)//10111110
{
u8 i = 0;//循环变量
for(i = 0; i < 8; i++)
{
if(c & 0x80)
PCOut(9) = 1;
else
PCOut(9) = 0;
c <<= 1;//01111100
}
}
需要接收8bit二进制数据,传感器通过高位先出的方式发送数据
假设:MCU连接了PC9管脚,可以使用位带发数据PCOut(9) 收数据PCIn(9)
数据线低电平代表数据0,数据线高电平代表数据1
u8 func(void)
{
u8 c = 0;//用来接收数据的变量
u8 i = 0;//循环变量
for(i = 0; i < 8; i++)
{
c <<= 1;//c >>= 1;
if(PCIn(9) == 1)
c |= 1;//c |= 0x80;
}
}
分析DHT11的读写时序
传输数据之前需要先检测DHT11存不存在|DHT11有没有损坏
void set_dht_output(void)//内部函数,把PC10管脚配置为输出模式
{
GPIO_InitTypeDef Gpio_Value;//定义了GPIO初始化结构体类型的变量
Gpio_Value.GPIO_Mode = GPIO_Mode_Out_PP;//选择了推挽的输出模式
Gpio_Value.GPIO_Pin = GPIO_Pin_10;//选择了10号管脚
Gpio_Value.GPIO_Speed = GPIO_Speed_50MHz;//选择了50MHz的输出速率
GPIO_Init(GPIOC, &Gpio_Value);//按照上述配置初始化GPIOC组的管脚
}
void set_dht_input(void)//内部函数,把PC10管脚配置为输入模式
{
GPIO_InitTypeDef Gpio_Value;//定义了GPIO初始化结构体类型的变量
Gpio_Value.GPIO_Mode = GPIO_Mode_IN_FLOATING;//选择了浮空的输入模式
Gpio_Value.GPIO_Pin = GPIO_Pin_10;//选择了10号管脚
GPIO_Init(GPIOC, &Gpio_Value);//按照上述配置初始化GPIOC组的管脚
}
void dht_output_status(int n)
{
set_dht_output();//先把PC10管脚初始化为输出模式
if(n == 0)
PCOut(10) = 0;
else
PCOut(10) = 1;
}
int dht_input_status(void)
{
set_dht_input();//先把PC10管脚初始化为输入模式
return PCIn(10);
}
void dht_init(void)//DHT11初始化
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
//通过APB2总线使能GPIOC组的时钟
}
void get_dht_value(char buf[5])//获取DHT11传感器采集的数据
{
u8 flag = 0;//该变量是用来获取PC10管脚的电平高低
u8 time = 0;//该变量是用来计数
dht_output_status(1);//把PC10管脚拉高
dht_output_status(0);//把PC10管脚拉低
delay_ms(20);//延时20ms
dht_output_status(1);//把PC10管脚拉高
//while(dht_input_status());//以死等的方式等待PC10管脚被拉低
do
{
flag = dht_input_status();//获取PC10管脚的电平高低
delay_us(2);//延时2us
time++;//计数自增
}while(flag == 1 && time <= 20);//以超时处理的方式等待PC10管脚被拉低
if(time > 20)//判断是否超时
return ;//提前结束程序
while(!dht_input_status());//以死等的方式等待PC10管脚被拉高
/*开始接收40bit的数据*/
//...............
}
3.DS18B20传感器
DS18B20有九个字节的暂存器
0byte 温度低字节
1byte 温度高字节
2byte 温度上限
3byte 温度下限
4byte 配置
5 6 7byte 保留
8byte 校验
DS18B20的暂存器:共有九个字节
暂存器的配置位:
低五位保留
DS18B20的时序图:
DS18B20官方手册列举的案例:0xCC->11001100