元件清单:
stm32f103c8t6、mq2 检测烟雾浓度(模拟量输出)、mq7 检测一氧化碳浓度、mq135 检测空气质量、OLED屏幕(四引脚仅支持iic协议通信)、dht11检测温湿度(数字量输出)、风扇模块、无源蜂鸣器、按键、WH-NB73-B5
第0天:实现了dht11的温湿度以及mq2烟雾浓度的采集并通过OLED显示屏显示
/*
湿度整数 湿度小数 温度整数 温度小数 校验位
00000000 00000000 00000000 00000000 00000000
1 看原理图确认GPIO引脚
2、 输出模式, 输出起始信号 :输出低电平18~30ms, 20ms
3、 IO口配置浮空输入模式,准检测响应信号
传感器把数据总线( SDA)拉低 83μs,
再接高 87μs 以响应主机的起始信号。
4、 40 个位的数据,高位先发;
一位一位的收,数据0: 54us低电平 + 23~27高电平
数据1: 54us低电平 + 68~74高电平
注意高位先发的(每个字节)
5、校验数据
前4个字节,求和,把和值的末八位和校验位对比
相同数据正确、否则数据异常
*/
//程序未写零下
char tmp = 0,hum = 0;
void DHT_GPIO_Config(u8 flag)
{
GPIO_InitTypeDef GPIO_Config;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); //开启端口时钟
GPIO_Config.GPIO_Pin = GPIO_Pin_8;
if(flag==OUTPUT)
GPIO_Config.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
else
GPIO_Config.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Config.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_Config);
}
u8 DHT_GetData(void)
{
u8 i = 0;
u8 count = 0;
u8 data[5]={0};
//输出模式, 输出起始信号 :输出低电平18~30ms, 20ms
DHT_GPIO_Config(OUTPUT);
DHT_High;
DHT_Low;
Delay_ms(20);
//DHT_High;
DHT_GPIO_Config(INPUT);
/*IO口配置浮空输入模式,准检测响应信号
传感器把数据总线( SDA)拉低 83μs,
再接高 87μs 以响应主机的起始信号。
*/
while(DHT_CHECK==1)
{
delay_1us();
count++;
if(count>100)
return 1;
}
count=0;
while(DHT_CHECK==0)
{
delay_1us();
count++;
if(count>100)
return 2;
}
for(i=0;i<40;i++)
{
count=0;
while(DHT_CHECK==1)
{
delay_1us();
count++;
if(count>100)
return 3;
}
count=0;
while(DHT_CHECK==0)
{
delay_1us();
count++;
if(count>100)
return 4;
}
Delay_us(30);
if(DHT_CHECK==1)
{
data[i/8] |= (1<<(7-i%8)); //置1
}else
{
data[i/8] &=~ (1<<(7-i%8));//清零
}
}
/*校验数据
前4个字节,求和,把和值的末八位和校验位对比
相同数据正确、否则数据异常*/
if((data[0]+data[1]+data[2]+data[3])==data[4])
{
tmp=data[2];
hum=data[0];
return 0;
}
else
{
return 5;
}
}
第1天:在昨天的基础上利用DMA实现多通道的数据采集(设置阀值,驱动风扇转动,并可手动按键改变阀值,并在屏幕显示变化;通过NB模块上传数据至有人云)
//mq2 mq7 mq135的采集
void ADC1_Config(void)
{
GPIO_InitTypeDef GPIO_Struct = {0};
ADC_InitTypeDef ADC_Struct = {0};
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_Struct.GPIO_Mode = GPIO_Mode_AIN;//模拟输入
GPIO_Struct.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_6|GPIO_Pin_7;
GPIO_Struct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_Struct);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
RCC_ADCCLKConfig(RCC_PCLK2_Div6);//设置ADC时钟 72/6<14
ADC_Struct.ADC_Mode = ADC_Mode_Independent; //独立工作模式
ADC_Struct.ADC_ContinuousConvMode = ENABLE;//连续模式
ADC_Struct.ADC_ScanConvMode = ENABLE; //多通道模式
ADC_Struct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //转换由软件触发启动
ADC_Struct.ADC_DataAlign = ADC_DataAlign_Right;//右对齐
ADC_Struct.ADC_NbrOfChannel = 3;//规定了顺序进行规则转换的 ADC 通道的数目
ADC_Init(ADC1,&ADC_Struct);
//设置指定 ADC 的规则组通道,设置它们的转化顺序和采样时间
//MQ2
ADC_RegularChannelConfig(ADC1,ADC_Channel_1,1,ADC_SampleTime_239Cycles5);
//MQ7
ADC_RegularChannelConfig(ADC1,ADC_Channel_6,2,ADC_SampleTime_239Cycles5);
//MQ135
ADC_RegularChannelConfig(ADC1,ADC_Channel_7,3,ADC_SampleTime_239Cycles5);
ADC_DMACmd(ADC1,ENABLE);
DMA_Config();
ADC_Cmd(ADC1,ENABLE);
//校准:减小误差
ADC_ResetCalibration(ADC1);//重置寄存器
while(ADC_GetResetCalibrationStatus(ADC1)==SET)//等待重置完成
{}
ADC_StartCalibration(ADC1);//启动校准,用校准寄存器 校准 ADC1
while(ADC_GetCalibrationStatus(ADC1)==SET)//等待校准完成
{}
ADC_SoftwareStartConvCmd(ADC1,ENABLE); //启动转换 使能或者失能指定的 ADC 的软件转换启动功能
}
u16 DMA_buf[3]={0};
void DMA_Config(void)
{
DMA_InitTypeDef DMA_Struct={0};
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE); //开启DMA时钟
DMA_Struct.DMA_PeripheralBaseAddr =(u32) &ADC1->DR; //定义DMA外设基地址
DMA_Struct.DMA_DIR = DMA_DIR_PeripheralSRC; //外设作为数据传输的来源
DMA_Struct.DMA_BufferSize = 3; //地址递增两次(单位为字宽)
DMA_Struct.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址寄存器不变
DMA_Struct.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址寄存器递增
DMA_Struct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //数据宽度为16位
DMA_Struct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //数据宽度为16位
DMA_Struct.DMA_Mode = DMA_Mode_Circular; //工作在循环缓存模式
DMA_Struct.DMA_Priority = DMA_Priority_High;//优先级
DMA_Struct.DMA_M2M = DMA_M2M_Disable;//DMA通道没有设置为内存到内存传输
DMA_Struct.DMA_MemoryBaseAddr = (u32)&DMA_buf[0]; //内存基地址
DMA_Init(DMA1_Channel1,&DMA_Struct);
DMA_Cmd(DMA1_Channel1,ENABLE);
}
//不采用DMA的多通道采集方法
//u16 ADC_Result(u8 ADC_Channel_x)
//{
// u16 ADC_val = ADC_GetConversionValue(ADC1); //返回最近一次 ADCx 规则组的转换结果
// ADC_RegularChannelConfig(ADC1,ADC_Channel_x,1,ADC_SampleTime_239Cycles5);
// ADC_SoftwareStartConvCmd(ADC1,ENABLE); //启动转换 使能或者失能指定的 ADC 的软件转换启动功能
// while((ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC))==RESET);
//
// //float ADC_Cha = (ADC_val*3.3/4096);
// //printf("ADC_val == %d\r\n",ADC_val);
// return ADC_val;
//}
?
?
?
?
|