从机采集温湿度及超标报警并显示在oled屏幕上,按下按键通过lora模块传输给主机,主机再也显示在其搭载的屏幕上

1、项目简介

2、实现逻辑


#从机实现对温湿度数据的检测
#从机将数据显示到oled上
#从机检测到数据超标后进行蜂鸣器报警
#从机将检测到的数据进行编码并无线传输
#从机按键能控制数据发送和停止(按一下一直发,按一下停,发送快一些)
#从机上两个指示灯,绿色代表正在发送数据,红色代表停止发送
#主机通过规定好的协议进行数据解析及在oled上显示数据

3、应用场景

#远程(中距离)检测温湿度
#粮库使用

4、核心代码梳理

//从机程序
void RF_Initial(uint8_t mode)  //0 rx  1 tx
{SX1276_Init(MODE_LORA);SX1276_LoRa_SetDataRate(2);SX1276_SetFreq(23);             //23,433HzSX1276_SetPower(15, 1);         //20dBmSX1276_SetRxMode();          //
}uint8_t RF_SendPacket(uint8_t *Sendbuffer, uint8_t length)
{uint8_t error = 0, i=0, ack_len=0, ack_buffer[65]= { 0 }, TxBuffer[100];SX1276_SendPacket(Sendbuffer, length);return (0);
}void RF_RecvHandler(void)
{uint8_t error=0, i=0, length=0, recv_buffer[20]= { 0 };uint8_t temp;uint8_t TL,TH;uint16_t tem;length = SX1276_ReceivePacket(recv_buffer);     //if(length==9){if ((recv_buffer[0]==0x55) && (recv_buffer[1]==0xAA)){uint16_t sum = recv_buffer[3]+recv_buffer[4]+recv_buffer[5]+recv_buffer[6]+recv_buffer[7];sum = sum & 0x00ff;if(sum != recv_buffer[8])return;//HAL_GPIO_TogglePin(GPIOC, BOARD_LED_Pin);TH = recv_buffer[4];TL = recv_buffer[5];if(TH>7){TH=~TH;TL=~TL;temp=0;//温度为负} else temp=1;//温度为正tem=TH; //获得高八位tem<<=8;tem+=TL;//获得底八位check_temp = (float)tem*0.625;//转换if(!temp)check_temp = -check_temp;check_temp = check_temp/10;printf("The temp is: %.2fC\r\n", check_temp);check_hump = (float)recv_buffer[7];check_hump = recv_buffer[6] + check_hump/100;printf("The hump is: %.2f%c\r\n", check_hump, '%');}SX1276_SetRxMode();}
}/* USER CODE END 0 *//*** @brief  The application entry point.* @retval int*/
int main(void)
{/* USER CODE BEGIN 1 */uint32_t  clk;/* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_ADC1_Init();MX_I2C1_Init();MX_SPI1_Init();MX_USART1_UART_Init();MX_USART2_UART_Init();MX_USART3_UART_Init();/* USER CODE BEGIN 2 */OLED_Init();OLED_ColorTurn(0);//0正常显示,1 反色显示OLED_DisplayTurn(0);//0正常显示 1 屏幕翻转显示OLED_Refresh();DS18B20_Init();RF_Initial(0);OLED_Clear();OLED_ShowString(0,0,"TEMP:    .    C",16);OLED_ShowString(0,14,"HUMP:    .    %",16);OLED_ShowString(0,28,"ALARM:",24);OLED_ShowNum(53,0,12,2,16);OLED_ShowNum(77,0,34,2,16);OLED_ShowString(43,0,"-",16);OLED_ShowString(80,28,"T",24);OLED_ShowString(100,28,"H",24);OLED_ShowString(100,28," ",24);OLED_Refresh();/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */
#ifdef TX//check tempcheck_temp = DS18B20_Get_Temp()/10;intT = (int)check_temp;          /*合成实际温度整数部分****精度相对上面的更高*/float tem_tmp = check_temp-intT;         /*合成实际温度小数部分*/decT = tem_tmp*100;//check humpcheck_hump = 4092-ADC_num;check_hump = (float)(check_hump/3292*100);//ad->hump%if((check_hump >= 0) && (check_hump <= 100)){intH = (int)check_hump;float hum_tmp = check_hump - intH;hum_tmp *= 100;decH = hum_tmp;lora_order[6] = intH;lora_order[7] = decH;}HAL_ADC_Start_IT(&hadc1);//check alarmif((check_temp > TEMP_ALARM_UP) || (check_hump > HUMP_ALARM_UP) || (check_temp < TEMP_ALARM_DOWN)|| (check_hump < HUMP_ALARM_DOWN)) //超标报警{HAL_GPIO_WritePin(GPIOC, BEEP_Pin, GPIO_PIN_SET);if((check_temp > TEMP_ALARM_UP) || (check_temp < TEMP_ALARM_DOWN))OLED_ShowString(80,28,"T",24);else OLED_ShowString(80,28," ",24);if((check_hump > HUMP_ALARM_UP) || ((check_hump < HUMP_ALARM_DOWN)))OLED_ShowString(100,28,"H",24);else OLED_ShowString(100,28," ",24);OLED_Refresh();}else{HAL_GPIO_WritePin(GPIOC, BEEP_Pin, GPIO_PIN_RESET);OLED_ShowString(80,28," ",24);OLED_ShowString(100,28," ",24);OLED_Refresh();}//send by lora / led displayif(clk % 10 == 0){if(send_flag%2)//send{uint16_t sum = lora_order[3]+lora_order[4]+lora_order[5]+lora_order[6]+lora_order[7];sum = sum & 0x00ff;lora_order[8] = sum;RF_SendPacket(lora_order, 9);HAL_GPIO_WritePin(GPIOB, SEND_LED_Pin, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOB, STOP_LED_Pin, GPIO_PIN_SET);}else//stop{HAL_GPIO_WritePin(GPIOB, SEND_LED_Pin, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOB, STOP_LED_Pin, GPIO_PIN_RESET);}if(check_temp < 0)OLED_ShowString(43,0,"-",16);elseOLED_ShowString(43,0," ",16);OLED_ShowNum(53,0,intT,2,16);OLED_ShowNum(77,0,decT,2,16);OLED_ShowNum(53,14,intH,2,16);OLED_ShowNum(77,14,decH,2,16);OLED_Refresh();}HAL_Delay(100);//HAL_GPIO_TogglePin(GPIOC, BOARD_LED_Pin);clk++;
#endif#ifdef RXRF_RecvHandler();
#endif}/* USER CODE END 3 */
}//复位DS18B20
void DS18B20_Rst(void)
{HAL_GPIO_WritePin(DS18B20_GPIO_Port,DS18B20_Pin,GPIO_PIN_RESET); //拉低DQdelay_us(750);    //拉低750usHAL_GPIO_WritePin(DS18B20_GPIO_Port,DS18B20_Pin,GPIO_PIN_SET); //DQ=1delay_us(15);     //15US
}
//等待DS18B20的回应
//返回1:未检测到DS18B20的存在
//返回0:存在
uint8_t DS18B20_Check(void)
{uint8_t retry=0;//SET PB1 INPUTwhile (HAL_GPIO_ReadPin(DS18B20_GPIO_Port,DS18B20_Pin) && retry<200){retry++;delay_us(1);};if(retry>=200)return 1;else retry=0;while (!HAL_GPIO_ReadPin(DS18B20_GPIO_Port,DS18B20_Pin)&&retry<240){retry++;delay_us(1);};if(retry>=240)return 1;return 0;
}
//从DS18B20读取一个位
//返回值:1/0
uint8_t DS18B20_Read_Bit(void)           // read one bit
{uint8_t data;HAL_GPIO_WritePin(DS18B20_GPIO_Port,DS18B20_Pin,GPIO_PIN_RESET);delay_us(2);HAL_GPIO_WritePin(DS18B20_GPIO_Port,DS18B20_Pin,GPIO_PIN_SET);delay_us(12);if(HAL_GPIO_ReadPin(DS18B20_GPIO_Port,DS18B20_Pin))data=1;else data=0;delay_us(50);return data;
}
//从DS18B20读取一个字节
//返回值:读到的数据
uint8_t DS18B20_Read_Byte(void)    // read one byte
{uint8_t i,j,dat;dat=0;for (i=1; i<=8; i++){j=DS18B20_Read_Bit();dat=(j<<7)|(dat>>1);}return dat;
}
//写一个字节到DS18B20
//dat:要写入的字节
void DS18B20_Write_Byte(uint8_t dat)
{uint8_t j;uint8_t testb;for (j=1; j<=8; j++){testb=dat&0x01;dat=dat>>1;if (testb){HAL_GPIO_WritePin(DS18B20_GPIO_Port,DS18B20_Pin,GPIO_PIN_RESET);// Write 1delay_us(2);HAL_GPIO_WritePin(DS18B20_GPIO_Port,DS18B20_Pin,GPIO_PIN_SET);delay_us(60);}else{HAL_GPIO_WritePin(DS18B20_GPIO_Port,DS18B20_Pin,GPIO_PIN_RESET);// Write 0delay_us(60);HAL_GPIO_WritePin(DS18B20_GPIO_Port,DS18B20_Pin,GPIO_PIN_SET);delay_us(2);}}
}
//开始温度转换
void DS18B20_Start(void)// ds1820 start convert
{DS18B20_Rst();DS18B20_Check();DS18B20_Write_Byte(0xcc);// skip romDS18B20_Write_Byte(0x44);// convert
}
//初始化DS18B20的IO口 DQ 同时检测DS的存在
//返回1:不存在
//返回0:存在
uint8_t DS18B20_Init(void)
{DS18B20_Rst();return DS18B20_Check();
}
//从ds18b20得到温度值
//精度:0.1C
//返回值:温度值 (-550~1250)
float DS18B20_Get_Temp(void)
{uint8_t temp;uint8_t TL,TH;short tem;float return_tem;DS18B20_Start();                    // ds1820 start convertDS18B20_Rst();DS18B20_Check();DS18B20_Write_Byte(0xcc);// skip romDS18B20_Write_Byte(0xbe);// convertTL=DS18B20_Read_Byte(); // LSBTH=DS18B20_Read_Byte(); // MSBlora_order[4] = TH;lora_order[5] = TL;if(TH>7){TH=~TH;TL=~TL;temp=0;//温度为负} else temp=1;//温度为正tem=TH; //获得高八位tem<<=8;tem+=TL;//获得底八位return_tem = (float)tem*0.625;//转换if(temp)return return_tem; //返回温度值else return -return_tem;
}/*** @brief   EXIT中断回调函数* @param GPIO_Pin —— 触发中断的引脚* @retval   none
*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{/* 判断哪个引脚触发了中断 */switch(GPIO_Pin){case GPIO_PIN_8:/* 处理GPIO8发生的中断 */delay_us(10000);//消抖if(HAL_GPIO_ReadPin(SEND_BUT_GPIO_Port, SEND_BUT_Pin)){send_flag++;HAL_GPIO_TogglePin(GPIOC, BOARD_LED_Pin);}break;default:break;}
}//get hump by adc conv
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{HAL_ADC_Stop_IT(hadc);ADC_num = HAL_ADC_GetValue(hadc);
}//主机程序
//和从机差不太多,见资料包

5、部分参考资料

ds18b20参考:
https://mculover666.blog.csdn.net/article/details/108302704?utm_medium=distribute.pc_relevant.
none-task-blog-BlogCommendFromMachineLearnPai2-1.control&dist_request_id=&depth_1-utm_source=distribute.
pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.control

https://blog.csdn.net/qq153471503/article/details/102858978

yl69参考:
https://blog.csdn.net/qq_41960161/article/details/106118778?utm_medium=distribute.
pc_relevant.none-task-blog-baidujs_title-0&spm=1001.2101.3001.4242

LCD12864参考:
https://blog.csdn.net/as480133937/article/details/97765912?utm_medium=distribute.pc_relevant_download.
none-task-blog-baidujs-2.nonecase&depth_1-utm_source=distribute.pc_relevant_download.none-task-blog-baidujs-2.nonecase

通讯协议格式说明(注:为16进制):
帧头 数据帧长度 设备ID 温度(℃) 湿度(%) 和校验(低8位)
55 AA 1字节(0-255) 1字节(0-255) 2字节(TH TL) 2字节(HH HL) 1字节

温度转换:u8 temp;

      u8 TL,TH;short tem;

TL=DS18B20_Read_Byte(); // LSB
TH=DS18B20_Read_Byte(); // MSB
if(TH>7)
{

    TH=~TH;TL=~TL;temp=0;//温度为负

}else temp=1;//温度为正
tem=TH; //获得高八位
tem<<=8;
tem+=TL;//获得底八位
tem=(float)tem*0.625;//转换
if(temp) return tem; //返回温度值
else return -tem; //tem是实际温度的10倍

例:01 17 = (1*256+23)*0.625=174.375 则实际温度是17.4375℃(举例用) 温度范围 -55℃-+125℃
湿度转换:float hum = HH+HL%100 例:24 57 = 36+87%100 = 36.87 ->湿度36.87%
和校验 = (设备ID+TH+TL+HH+HL)低8位
例:55 AA 06 01(默认ID为01) 01 17 24 57 94



主从机硬件pcb、原理图见资料包

6、注意事项

#sx1276是spi通信,也有那种直接封装好使用串口的lora模块,比如E19
#本来要使用lcd做显示,后来种种原因使用的oled 9.6
#注意主从机之间的协议

完整可运行项目地址

技能梳理15@stm32+lora(sx1276)+oled+ds18b20+土壤湿度传感器+按键+蜂鸣器+电路板相关推荐

  1. 技能梳理37@stm32+按键+光耦+锁存+串行转并行+继电器

    技能梳理37@stm32+按键+光耦+锁存+串行转并行+继电器 1.项目简介 2.实现逻辑 3.应用场景 #主从机有线控制 #开关操作 4.核心代码梳理 //根据按下的按键执行相应的操作 void h ...

  2. 技能梳理14@stm32+esp8266+ds18b20+红外传感器+烟雾传感器+CO传感器+蜂鸣器

    画板子,有至少8个io口(分别连ds18b20.红外传感器.烟雾传感器.CO传感器,后面3个传感器都是检测到就发高电平),2个串口,1个蜂鸣器,nbiot用的YED-C724 核心板(AIR724) ...

  3. 技能梳理7@stm32+OLED+flash掉电保存+按键

    学校违纪分数记录,按键,1.3寸OLED显示,数据掉电保存 1.项目简介 2.实现逻辑 #如上图为显示屏显示内容 #三个物理按键,一个是选择对哪一项进行控制,两个是加减对应项的分数 #控制范围±10, ...

  4. 技能梳理21@stm32+oled+声音强度检测+舵机

    检测声音强度,显示大概的分贝数在oled上,不同强度下舵机转不同的角度 1.项目简介 2.实现逻辑 #通过STM32的adc检测大概声音强度 #在oled上显示声音强度 #舵机根据声音大小转动 3.应 ...

  5. 技能梳理20@stm32+ESP8266+onenet+dht11+mq2+led+风扇+oled

    F103C8T6 ESP8266和ONENET通信 DHT11测温湿度 MQ-2测烟雾浓度 LED模拟室内灯 温湿度和烟雾超标,蜂鸣器报警,风扇转动:OLED显示数据:数据传输onenet,控制LED ...

  6. 技能梳理18@stm32+柔性墨水屏+薄膜按键+二维码

    薄膜压力按键控制mos开关,切换给柔性墨水屏vcc供电方式,单片机控制vcc切换图像,其中有可以扫描的二维码 1.项目简介 2.实现逻辑 #有两个薄膜按键,一个控制墨水屏供电方式(其实就是一个继电器) ...

  7. K_A11_002 基于STM32等单片机驱动DS18B20串口与OLED0.96双显示

    K_A11_002 基于STM32等单片机驱动DS18B20 串口与OLED0.96双显示 一.资源说明 二.基本参数 1.参数 2.引脚说明 三.驱动说明 时序 对应程序: 四.部分代码说明 1.接 ...

  8. 51单片机+oled+ds18b20检测并显示温度第三篇:配置温度检测ds18b20

    51单片机+oled+ds18b20检测并显示温度第一篇:配置温度检测ds18b20 前提: DS18B20是一线总线(单总线)"接口的温度传感器.其引脚只有三个vcc,gnd和dq vcc ...

  9. STM32单片机学习(11) DS18B20温度传感器实验

    STM32单片机学习(11) DS18B20温度传感器实验 本程序主要实现 DS18B20温度传感器数据获取,并利用串口通信把温度数据传至计算机 注:使用普中科技开发板测试时,需要拔掉Boot1插口, ...

最新文章

  1. pandas使用fillna函数将dataframe中的缺失值按照列均值进行填充(fill missing values with the mean of the column)
  2. 人类“换头术”现在就是一场炒作 但医学界不会放弃研究
  3. cnblogs第一篇
  4. UVA Mapping the Swaps
  5. 2018南京java工资_2018年Java开发工程师的待遇如何?
  6. Linux服务部署之NTP时间服务器
  7. 牛客16596 计算系数(排列组合)
  8. SYBASE的管理(三)
  9. zepto源码--filtered, contains,funcArg,setAttribute,className,deserializeVale--学习笔记
  10. 从Myeclipe转向Idea,各种遇坑与填坑经验,持续更新(图文)
  11. HDU1850 Being a Good Boy in Spring Festival
  12. 二级计算机vf题型,计算机二级VF考试常见题型与解题技巧
  13. 【什么是DOM和BOM】
  14. 智能制造运筹优化_机械类(智能制造与智能装备)之工业工程专业
  15. 【2016】心有猛虎,细嗅蔷薇In me the tiger sniffs the rose
  16. 南京信息工程大学 第二届程序设计大赛团队赛 试题
  17. 杨海朝 mysql_老男孩Mysql高级DBA 实战新浪首席DBA 老男孩教育杨海朝老师全程主讲 老男孩Mysql视频...
  18. Appium自动化测试(五)——PO模式(一):短信案例
  19. 常见的网站攻击以及如何防御自己的网站被恶意攻击
  20. 周鸿祎360新手机真的会免费吗?

热门文章

  1. iOS 苹果开发者账号--个人账号,公司账号和企业账号的区别
  2. 图论(12)超哈密尔顿图与超可迹图
  3. Struts2框架学习总结(从入门到精通)
  4. shell教程一 :介绍
  5. 微擎支付提示下单用户不一致,授权快照移除
  6. 关于p分数反常积分的收敛与发散
  7. Mac Chrome浏览器取消自动升级(看这一篇就够了)
  8. php time()函数
  9. 常用wifi 加密方式区别
  10. n个元素的全排列C语言,n个元素的全排列(递归+去重)