Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
DS18B20
通过ESP8266 将DS18B20温度数据传至本地TCP服务器
发布于 2020-03-30 09:50:13 浏览:4180
订阅该版
作业题目5: ESP866连接网络成功之后,实现输入一个MSH命令,创建一个动态线程,在该线程回调函数中实现一分钟上传一次DS18B20温度数据至本地TCP服务器。 大家提交作业时,直接在本贴下方跟贴即可
查看更多
24
个回答
默认排序
按发布时间排序
风雨潇潇
2020-04-04
这家伙很懒,什么也没写!
本次课题我使用温湿度传感器DTH11,ESP8266-01S。在之前的工程上添加论文DTH11的驱动程序, ``` static void DHT11_Mode_IPU(void); static void DHT11_Mode_Out_PP(void); static uint8_t DHT11_ReadByte(void); /* 函数体 --------------------------------------------------------------------*/ /** * 函数功能: * 输入参数: 无 * 返 回 值: 无 * 说 明:无 */ void DHT11_Delay(rt_uint32_t time) { uint8_t i; while(time) { for (i = 0; i < 16; i++) { } time--; } } /** * 函数功能: DHT11 初始化函数 * 输入参数: 无 * 返 回 值: 无 * 说 明:无 */ void DHT11_Init ( void ) { DHT11_Dout_GPIO_CLK_ENABLE(); DHT11_Mode_Out_PP(); DHT11_Dout_HIGH(); // 拉高GPIO rt_thread_mdelay(3000); } /** * 函数功能: 使DHT11-DATA引脚变为上拉输入模式 * 输入参数: 无 * 返 回 值: 无 * 说 明:无 */ static void DHT11_Mode_IPU(void) { GPIO_InitTypeDef GPIO_InitStruct; /* 串口外设功能GPIO配置 */ GPIO_InitStruct.Pin = DHT11_Dout_PIN; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(DHT11_Dout_PORT, &GPIO_InitStruct); } /** * 函数功能: 使DHT11-DATA引脚变为推挽输出模式 * 输入参数: 无 * 返 回 值: 无 * 说 明:无 */ static void DHT11_Mode_Out_PP(void) { GPIO_InitTypeDef GPIO_InitStruct; /* 串口外设功能GPIO配置 */ GPIO_InitStruct.Pin = DHT11_Dout_PIN; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(DHT11_Dout_PORT, &GPIO_InitStruct); } /** * 函数功能: 从DHT11读取一个字节,MSB先行 * 输入参数: 无 * 返 回 值: 无 * 说 明:无 */ static uint8_t DHT11_ReadByte ( void ) { uint8_t i, temp=0; for(i=0;i<8;i++) { /*每bit以50us低电平标置开始,轮询直到从机发出 的50us 低电平 结束*/ while(DHT11_Data_IN()==GPIO_PIN_RESET); /*DHT11 以26~28us的高电平表示“0”,以70us高电平表示“1”, *通过检测 x us后的电平即可区别这两个状 ,x 即下面的延时 */ DHT11_Delay(40); //延时x us 这个延时需要大于数据0持续的时间即可 if(DHT11_Data_IN()==GPIO_PIN_SET)/* x us后仍为高电平表示数据“1” */ { /* 等待数据1的高电平结束 */ while(DHT11_Data_IN()==GPIO_PIN_SET); temp|=(uint8_t)(0x01<<(7-i)); //把第7-i位置1,MSB先行 } else // x us后为低电平表示数据“0” { temp&=(uint8_t)~(0x01<<(7-i)); //把第7-i位置0,MSB先行 } } return temp; } /** * 函数功能: 一次完整的数据传输为40bit,高位先出 * 输入参数: DHT11_Data:DHT11数据类型 * 返 回 值: ERROR: 读取出错 * SUCCESS:读取成功 * 说 明:8bit 湿度整数 + 8bit 湿度小数 + 8bit 温度整数 + 8bit 温度小数 + 8bit 校验和 */ uint8_t DHT11_Read_TempAndHumidity(DHT11_Data_TypeDef *DHT11_Data) { uint8_t temp; uint16_t humi_temp; /*输出模式*/ DHT11_Mode_Out_PP(); /*主机拉低*/ DHT11_Dout_LOW(); /*延时18ms*/ rt_thread_mdelay(18); /*总线拉高 主机延时30us*/ DHT11_Dout_HIGH(); DHT11_Delay(30); //延时30us /*主机设为输入 判断从机响应信号*/ DHT11_Mode_IPU(); /*判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行*/ if(DHT11_Data_IN()==GPIO_PIN_RESET) { /*轮询直到从机发出 的80us 低电平 响应信号结束*/ while(DHT11_Data_IN()==GPIO_PIN_RESET); /*轮询直到从机发出的 80us 高电平 标置信号结束*/ while(DHT11_Data_IN()==GPIO_PIN_SET); /*开始接收数据*/ DHT11_Data->humi_high8bit= DHT11_ReadByte(); DHT11_Data->humi_low8bit = DHT11_ReadByte(); DHT11_Data->temp_high8bit= DHT11_ReadByte(); DHT11_Data->temp_low8bit = DHT11_ReadByte(); DHT11_Data->check_sum = DHT11_ReadByte(); /*读取结束,引脚改为输出模式*/ DHT11_Mode_Out_PP(); /*主机拉高*/ DHT11_Dout_HIGH(); /* 对数据进行处理 */ humi_temp=DHT11_Data->humi_high8bit*100+DHT11_Data->humi_low8bit; DHT11_Data->humidity =(float)humi_temp/100; humi_temp=DHT11_Data->temp_high8bit*100+DHT11_Data->temp_low8bit; DHT11_Data->temperature=(float)humi_temp/100; /*检查读取的数据是否正确*/ temp = DHT11_Data->humi_high8bit + DHT11_Data->humi_low8bit + DHT11_Data->temp_high8bit+ DHT11_Data->temp_low8bit; if(DHT11_Data->check_sum==temp) { return SUCCESS; } else return ERROR; } else return ERROR; } ``` 使用stm32L476的USART3连接WiFi模块,代码移植老师是代码框架,但是其中的macESP8266_Usart函数也就是串口格式化输出函数,我修改后如下,并不能使用。不知道是不是hal库还是我哪里出错了的原因。调试看到传过来的数据到形参Data中就不对了,但是上一级的数据都是对的。 ``` void USART_printf ( UART_HandleTypeDef * USARTx, char * Data, ... ) { const char *s; uint8_t a; int d; char buf[16]; va_list ap; va_start(ap, Data); while ( * Data != 0 ) // 判断是否到达字符串结束符 { if ( * Data == 0x5c ) //'\' { switch ( *++Data ) { case 'r': //回车符 //USART_SendData(USARTx, 0x0d); a= 0x0d; HAL_UART_Transmit(USARTx, &a, 1, 10); Data ++; break; case 'n': //换行符 //USART_SendData(USARTx, 0x0a); a= 0x0a; HAL_UART_Transmit(USARTx, &a, 1, 10); Data ++; break; default: Data ++; break; } } else if ( * Data == '%') { // switch ( *++Data ) { case 's': //字符串 s = va_arg(ap, const char *); for ( ; *s; s++) { //USART_SendData(USARTx,*s); HAL_UART_Transmit(USARTx, (uint8_t *)s, 1, 0xFFFF); //while( __HAL_UART_GET_FLAG(USARTx,UART_FLAG_TXE) == RESET ); } Data++; break; case 'd': //十进制 d = va_arg(ap, int); itoa(d, buf, 10); for (s = buf; *s; s++) { //USART_SendData(USARTx,*s); HAL_UART_Transmit(USARTx, (uint8_t *)s, 1, 0xFFFF); //while( __HAL_UART_GET_FLAG(USARTx,UART_FLAG_TXE) == RESET ); } Data++; break; default: Data++; break; } } else HAL_UART_Transmit(USARTx, (uint8_t *)*Data++, 1, 0xFFFF); //while ( __HAL_UART_GET_FLAG(USARTx,UART_FLAG_TXE) == RESET ); __HAL_UART_ENABLE_IT(&huart3, UART_IT_RXNE); __HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE); } } ``` 没有用这个函数,我自己在ESP8266_Cmd函数中直接发送了代码如下 ``` rt_bool_t ESP8266_Cmd ( char * cmd, char * reply1, char * reply2, uint32_t waittime ) { volatile rt_uint8_t len = 0; rt_uint8_t i; char Scmd[50] = {0}; //Scmd = &cmd; rt_memcpy(Scmd,cmd,rt_strlen(cmd)); strEsp8266_Fram_Record .InfBit .FramLength = 0; //从新开始接收新的数据包 len = rt_strlen(Scmd); //macESP8266_Usart( "%s\r\n", cmd ); Scmd[rt_strlen(Scmd)] = 0x0D; Scmd[rt_strlen(Scmd)] = 0x0A; len = rt_strlen(Scmd); for(i = 0; i < len; i++) { HAL_UART_Transmit( &huart3,&Scmd[i], 1,0xFFFF ); } //rt_memset(Scmd,0,50); //HAL_UART_Transmit( &huart3,Scmd, rt_strlen(Scmd),0xFFFF ); if ( ( reply1 == 0 ) && ( reply2 == 0 ) ) //不需要接收数据 return true; rt_thread_mdelay(waittime); strEsp8266_Fram_Record .Data_RX_BUF [ strEsp8266_Fram_Record .InfBit .FramLength ] = '\0'; if ( ( reply1 != 0 ) && ( reply2 != 0 ) ) return ( ( rt_bool_t ) rt_strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply1 ) || ( rt_bool_t ) rt_strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply2 ) ); else if ( reply1 != 0 ) return ( ( rt_bool_t ) rt_strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply1 ) ); else return ( ( rt_bool_t ) rt_strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply2 ) ); } ``` ``` ```
风雨潇潇
2020-04-04
这家伙很懒,什么也没写!
``` void ATcmd(int argc,char **argv) { if(!rt_strcmp(argv[1],"AT")) { ESP8266_Cmd ( "AT", "OK", NULL, 500 ); printf("%s\r\n",strEsp8266_Fram_Record .Data_RX_BUF); } else if(!rt_strcmp(argv[1],"STA"))//设置为工作站模式 { ESP8266_Net_Mode_Choose ( STA ); printf("%s\n",strEsp8266_Fram_Record.Data_RX_BUF); } else if(!rt_strcmp(argv[1],"AP"))//设置为热点模式 { ESP8266_Net_Mode_Choose ( AP ); printf("%s\n",strEsp8266_Fram_Record.Data_RX_BUF); } else if(!rt_strcmp(argv[1],"STA_AP")) //设置为工作站+热点模式 { ESP8266_Net_Mode_Choose ( STA_AP ); printf("%s\n",strEsp8266_Fram_Record.Data_RX_BUF); } else if(!rt_strcmp(argv[1],"JoinAP")) //加入热点 { ESP8266_JoinAP ( argv[2], argv[3]); printf("%s\n",strEsp8266_Fram_Record.Data_RX_BUF); } else if(!rt_strcmp(argv[1],"ipconfig")) //查询本机IP { ESP8266_InquireIP( ); printf("%s\n",strEsp8266_Fram_Record.Data_RX_BUF); } else if(!rt_strcmp(argv[1],"Mult")) //开启多连接 { ESP8266_Enable_MultipleId(ENABLE); printf("%s\n",strEsp8266_Fram_Record.Data_RX_BUF); } else if(!rt_strcmp(argv[1],"GetStatus")) { ESP8266_Get_LinkStatus(); printf("%s\n",strEsp8266_Fram_Record.Data_RX_BUF); } else if(!rt_strcmp(argv[1],"LinkServer")) //加入服务器 { if(!rt_strcmp(argv[2],"TCP")) ESP8266_Link_Server ( enumTCP, argv[3], argv[4], Single_ID_0); else ESP8266_Link_Server ( enumUDP, argv[3], argv[4], Single_ID_0); printf("%s\n",strEsp8266_Fram_Record.Data_RX_BUF); } else if(!rt_strcmp(argv[1],"CloseLink")) //关闭TCP或UDP连接 { ESP8266_Close_Link(); printf("%s\n",strEsp8266_Fram_Record.Data_RX_BUF); } else if(!rt_strcmp(argv[1],"Unvarnish")) //开启透传 { ESP8266_UnvarnishSend(); printf("%s\n",strEsp8266_Fram_Record.Data_RX_BUF); } else if(!rt_strcmp(argv[1],"USendData")) //透传时发送数据,数据间不能包含空格;若需发送空格数据请加双引号 { ESP8266_SendString ( ENABLE, argv[2], rt_strlen(argv[2]), Single_ID_0 ); printf("Send Data:%s\r\n",argv[2]); } else if(!rt_strcmp(argv[1],"SendData")) //透传时发送数据,数据间不能包含空格;若需发送空格数据请加双引号 { ESP8266_SendString ( DISABLE, argv[2], rt_strlen(argv[2]), Single_ID_0 ); printf("Send Data:%s\r\n",argv[2]); } else if(!rt_strcmp(argv[1],"ExitUnvarnish")) //关闭透传 { ESP8266_ExitUnvarnishSend (); printf("%s\n",strEsp8266_Fram_Record.Data_RX_BUF); } else if(!rt_strcmp(argv[1],"Rece")) { ESP8266_ReceiveString(DISABLE); printf("%s\n",strEsp8266_Fram_Record.Data_RX_BUF); } else if(!rt_strcmp(argv[1],"URece")) { ESP8266_ReceiveString(ENABLE); printf("%s\n",strEsp8266_Fram_Record.Data_RX_BUF); } } MSH_CMD_EXPORT(ATcmd, ESP8266 Test.); ``` 两个驱动调试完成后,编写上传温湿度的线程函数 ``` void UpdateDTH11(void) { dht_thread = rt_thread_create("updataDTH11", dht_thread_entry, RT_NULL, 512, 4, 10); if(dht_thread != RT_NULL) { rt_thread_startup(dht_thread); } } MSH_CMD_EXPORT(UpdateDTH11, UpdataDTH Test.); ``` ``` void dht_thread_entry(void *parameter) { char cStr [50]; DHT11_Data_TypeDef DHT11_Data; DHT11_Init(); while(1) { DHT11_Read_TempAndHumidity(&DHT11_Data); //rt_kprintf("temperature = %d\n",(rt_uint32_t)DHT11_Data.temperature); //rt_kprintf("humidity = %d\n\n",(rt_uint32_t)DHT11_Data.humidity); sprintf ( cStr, "temperature = %d", (rt_uint32_t)DHT11_Data.temperature); ESP8266_Cmd ( cStr, "SEND OK", 0, 100 ); rt_memset(cStr,0,50); sprintf ( cStr, "humidity = %d\r\n", (rt_uint32_t)DHT11_Data.humidity); ESP8266_Cmd ( cStr, "SEND OK", 0, 100 ); rt_memset(cStr,0,50); rt_thread_mdelay(1000); } } ``` 通过控制台连接WiFi和TCP服务器后,打开透传模式,在调用命令UpdateDTH11初始化线程。
yichao
2020-04-05
这家伙很懒,什么也没写!
[i=s] 本帖最后由 yichao 于 2020-4-5 22:59 编辑 [/i] [md]- 创建动态线程 通过MSH命令触发 ``` static rt_thread_t uploadtemp_thread = RT_NULL; void uploadtemp_thread_entry(void *parameter); int create_thread_bymsh(void) { uploadtemp_thread = rt_thread_create("uploadtemp_thread", uploadtemp_thread_entry, RT_NULL, 1024, 5, 10); if(uploadtemp_thread != RT_NULL) { rt_thread_startup(uploadtemp_thread); } return 0; } MSH_CMD_EXPORT(create_thread_bymsh, create_thread_bymsh.); ``` - 线程回调函数定时上传 ``` static rt_timer_t Ds18B20ProcessSoftTimer; static char SendData[30];//发往服务器的包,暂存数组 void uploadtemp_thread_entry(void *parameter) { while(1) { //假设之前模块已经连接就绪 并处于透传模式 ESP8266_UnvarnishSend(); rt_kprintf("begin to upload..."); sprintf(SendData,"\r\nTemperature: %.1f\r\n",DS18B20_GetTemp_SkipRom()); ESP8266_SendString ( ENABLE, SendData, strlen(SendData), Single_ID_0 ); //发送数据 rt_thread_mdelay(60000-100); } } ```[/md]
BruceTan
2020-04-05
这家伙很懒,什么也没写!
帖子不好排版,直接贴CSDN地址交作业啦 [https://blog.csdn.net/qq_22902757/article/details/105335527](https://blog.csdn.net/qq_22902757/article/details/105335527)
赵撵猪
2020-04-06
这家伙很懒,什么也没写!
整体部分,分为三部分,以下是部分说明[list] [*]DS18B20驱动实现 [/list] DS18B20实现最重要的就是us的延迟实现,更改主频是十分不建议的!!建议的方式为定时器,[https://blog.csdn.net/zhaqonianzhu/article/details/105291715](https://blog.csdn.net/zhaqonianzhu/article/details/105291715) 我的实现笔记 ``` void HAL_Delay_us(uint32_t Delay_us) { uint16_t wait = Delay_us; if (wait < UINT16_MAX) //设定定时器计数器阈值 wait++; __HAL_TIM_SET_COUNTER(&htim14,1); //将CNT值设置为0 HAL_TIM_Base_Start(&htim14); //启动定时器 while(__HAL_TIM_GET_COUNTER(&htim14) < wait) //查询计数器的计数值判断 { } // HAL_TIM_Base_Stop(&htim14); } ``` 实现代码十行左右,接着就是DS18B20的数据读取,DS18B20每次操作都是三步, Step 1. InitializationStep 2. ROM Command (followed by any required data exchange) Step 3. DS18B20 Function Command (followed by any required data exchange) 需要注意的是指令是从低位先发送和接受。ROM使用0xCC跳过就好了,读取温度时建议时间长一点,默认12bit的数据转换时间为750ms。 ``` #include
#include "DS18B20.h" #include "tim.h" #include
#include
#include
#define DS18B20_PRIORITY 11 #define DS18B20_STACK_SIZE 1024 #define DS18B20_TIMESLICE 5 static rt_thread_t DS18B20_run_tid = RT_NULL; void HAL_Delay_us(uint32_t Delay_us) { uint16_t wait = Delay_us; if (wait < UINT16_MAX) //设定定时器计数器阈值 wait++; __HAL_TIM_SET_COUNTER(&htim14,1); //将CNT值设置为0 HAL_TIM_Base_Start(&htim14); //启动定时器 while(__HAL_TIM_GET_COUNTER(&htim14) < wait) //查询计数器的计数值判断 { } // HAL_TIM_Base_Stop(&htim14); } /** Configure pins as * * Input * * Output */ void PIN_Mode_Set(uint32_t Mode, uint32_t Pull ,GPIO_PinState PinState) { static GPIO_InitTypeDef GPIO_InitStruct = {0}; if(Mode == GPIO_MODE_OUTPUT_PP) { HAL_GPIO_WritePin(US_PIN_GPIO_Port, US_PIN_Pin, PinState); GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; } /*Configure GPIO pin : PtPin */ GPIO_InitStruct.Pin = US_PIN_Pin; GPIO_InitStruct.Mode = Mode; GPIO_InitStruct.Pull = Pull; HAL_GPIO_Init(US_PIN_GPIO_Port, &GPIO_InitStruct); } /*功能:向DS18B20发送一个复位信号*/ int DS18B20_RESET() { PIN_Mode_Set(GPIO_MODE_OUTPUT_PP,GPIO_PULLDOWN,GPIO_PIN_RESET);//拉低总线480~960 us ,对 DS18B20 芯片进行复位 HAL_Delay_us(500); PIN_Mode_Set(GPIO_MODE_INPUT,GPIO_PULLUP,GPIO_PIN_RESET);//释放总线15~60 us HAL_Delay_us(68); /*功能:检测DS18B20存在脉冲*/ for(int Index = 0;Index < 12;Index++) { if (GPIO_PIN_RESET == HAL_GPIO_ReadPin(US_PIN_GPIO_Port,US_PIN_Pin)) { HAL_Delay_us(500); return 0; } HAL_Delay_us(20); } return -1; } void DS18B20_Write_Bit(GPIO_PinState PinState) { PIN_Mode_Set(GPIO_MODE_OUTPUT_PP,GPIO_PULLDOWN,GPIO_PIN_RESET); if (GPIO_PIN_RESET == PinState) { HAL_Delay_us(80);//写 0 主机拉低总线60-120us PIN_Mode_Set(GPIO_MODE_OUTPUT_PP,GPIO_PULLUP,GPIO_PIN_SET); } else { HAL_Delay_us(10); PIN_Mode_Set(GPIO_MODE_OUTPUT_PP,GPIO_PULLUP,GPIO_PIN_SET); HAL_Delay_us(60); } HAL_Delay_us(50); return; } GPIO_PinState DS18B20_Read_Bit() { GPIO_PinState sta; PIN_Mode_Set(GPIO_MODE_OUTPUT_PP,GPIO_PULLDOWN,GPIO_PIN_RESET); HAL_Delay_us(2); PIN_Mode_Set(GPIO_MODE_INPUT,GPIO_PULLUP,GPIO_PIN_RESET); HAL_Delay_us(10); sta = HAL_GPIO_ReadPin(US_PIN_GPIO_Port,US_PIN_Pin); HAL_Delay_us(60); PIN_Mode_Set(GPIO_MODE_OUTPUT_PP,GPIO_PULLUP,GPIO_PIN_SET); return sta; } /*功能:向DS18B20写一个字节数据(命令)*/ void DS18B20_Write_Byte(uint8_t byte) { for(int Index = 0;Index < 8;Index++) { DS18B20_Write_Bit((byte&(0x01<
>4) + (MS_BYTE<<4) + ((LS_BYTE&0x0f)*0.625)); } return -1; } static void DS18B20_entry(void *param) { rt_base_t level ; float temp; static uint8_t data_send[128]; while (1) { level = rt_hw_interrupt_disable(); if(0 == DS18B20_Temperature_Conversion()) { rt_thread_mdelay(1000); temp = DS18B20_Get_Temperature(); } rt_hw_interrupt_enable(level); printf("DS18B20_Get_Temperature:%4.1f℃\r\n",temp); snprintf((char*)data_send,sizeof(data_send),"DS18B20:%4.1f℃",temp); HAL_UART_Transmit(&huart2,data_send,rt_strlen((char*)data_send),3000); rt_thread_mdelay(60*1000); } } int DS18B20_create(void) { DS18B20_run_tid = rt_thread_create("DS18B20_run", DS18B20_entry, RT_NULL, DS18B20_STACK_SIZE, DS18B20_PRIORITY, 50); if (DS18B20_run_tid != RT_NULL) rt_thread_startup(DS18B20_run_tid); return 0; } //INIT_DEVICE_EXPORT(DS18B20_create); MSH_CMD_EXPORT(DS18B20_create, DS18B20 create); ``` [list] [*]ESP8266联网实现 [/list]AT模块主要我实现的了简单的AT框架,建议使用os带的框架比较好,因为是透传模式,AT指令没有几条。串口数据接是直接send到消息队列中,读取数据时从消息队列取数据并进行判断数据。 ``` int at_cmd_send(uint32_t timeout,const char *cmd, ...) { int len = 0; char * p = echo.buffer; static uint8_t at_cmd[512]; memset(at_cmd,0,sizeof(at_cmd)); va_list args; va_start(args, cmd); len = vsnprintf((char*)at_cmd, sizeof(at_cmd)-1, cmd, args); va_end(args); HAL_UART_Transmit(&huart2,at_cmd,len,3000); rt_kprintf("\r\n>%s\r\n",at_cmd); if (-1 == at_uart_read((uint8_t*)echo.buffer,echo.buffer_size,timeout)) { echo.status = AT_ECHO_STATUS_NONE; return -1; } rt_kprintf("\r\n>%s\r\n",echo.buffer); for(int i = 0;i < (echo.buffer_size - 1);i++) { if (strncmp(echo.echo_expect,p++ ,strlen(echo.echo_expect)) == 0) { echo.status = AT_ECHO_STATUS_EXPECT; return 0; } else if(echo.echo_expect == NULL) { echo.status = AT_ECHO_STATUS_OK; return 0; } echo.status = AT_ECHO_STATUS_NONE; } return -1; } ``` [attach]14724[/attach]联网成功之后就进入到透传模式,串口可以直接收发数据 [list] [*]组合实现一分钟发送一次温度数据 [/list]见上面DS18B20代码实现,我们只需要把创建导入到msh命令中 ``` MSH_CMD_EXPORT(DS18B20_create, DS18B20 create); ``` 这里需要注意的是,假如有需要可以进行判断任务是否为空判断任务id是否存在 ``` int DS18B20_create(void) { if (DS18B20_run_tid != RT_NULL) return 0; DS18B20_run_tid = rt_thread_create("DS18B20_run", DS18B20_entry, RT_NULL, DS18B20_STACK_SIZE, DS18B20_PRIORITY, 50); if (DS18B20_run_tid != RT_NULL) rt_thread_startup(DS18B20_run_tid); return 0; } //INIT_DEVICE_EXPORT(DS18B20_create); MSH_CMD_EXPORT(DS18B20_create, DS18B20 create); ``` [attach]14725[/attach]到此完成了全部工作。
瑞尧
2020-04-07
这家伙很懒,什么也没写!
一直在等待传感器到货,今天刚到就直接开始玩起来,代码早就是弄好了的,就等着调试呢! 需求:向服务器发送温度数据 需要用到:串口数据收发,传感器数据读取,网络通信 串口数据收发在第二次作业中就已经完成,直接拿过来用 传感器是DS18B20,是单线通信传感器,驱动一大堆,就不贴出来了,直接开始下一步 网络通信,由于ESP8266是使用的AT指令方式和,比较简单,直接写一个指令发送检验就可以了,代码如下: ``` rt_err_t esp_send_cmd(char *cmd, char *reply1, char *reply2, uint32_t waittime) { UART4_RX_STA = 0; USART_printf(UART4, "%s\r\n", cmd); if ((reply1 == 0)&&(reply2 == 0)) return RT_EOK; while((UART4_RX_STA&0x8000)==0&&waittime) { rt_thread_mdelay(1); waittime--; } UART4_RX_STA = 0; if(waittime == 0) return -RT_ETIMEOUT; else if((reply1 != 0) && (reply2 != 0)) { if(strstr((char *)UART4_RX_BUF, reply1) != NULL || strstr((char *)UART4_RX_BUF, reply2) != NULL) return RT_EOK; } else if(reply1 != 0 && strstr((char *)UART4_RX_BUF, reply1) != NULL) { return RT_EOK; } else if(strstr((char *)UART4_RX_BUF, reply2) != NULL) return RT_EOK; else return -RT_ERROR; } ``` 模块驱动有了,就是一系列的配置,例如链接AP,链接服务器,发送数据,代码如下: ``` rt_err_t esp_joinap(char *pSSID, char *pPassWord) { char cCmd[120]; sprintf(cCmd, "AT+CWJAP=\"%s\",\"%s\"", pSSID, pPassWord); return(esp_send_cmd(cCmd, "OK", NULL, 5000)); } rt_err_t esp_start_socket(char *mode,u8 socket, char *ip, u16 port) { rt_err_t result = RT_EOK; char str[50]; result = esp_send_cmd("AT+CIPMUX=1","OK",NULL,500); if(RT_EOK != result) return result; sprintf(str,"AT+CIPSTART=%d,\"%s\",\"%s\",%d",socket,mode,ip,port); rt_kprintf("%s\n",str); result = esp_send_cmd(str, "CONNECT",NULL,2000); return result; } rt_err_t esp_close_socket(u8 socket) { char *str; sprintf(str, "AT+CIPCLOSE=%d",socket); return(esp_send_cmd(str,"CLOSED",NULL,1000)); } rt_err_t esp_send(u8 socket,char *str) { rt_err_t result = RT_EOK; char cmd[1024]; u8 data_len = strlen(str); sprintf(cmd, "AT+CIPSEND=%d,%d",socket,data_len); result = esp_send_cmd(cmd,">",NULL,100); if (RT_ETIMEOUT == result) { return result; } result = esp_send_cmd(str,"OK",NULL,500); return result; } ``` 最后就是app服务程序了,也很简单,就是将数据向服务器发送就可以了,代码如下: ``` static rt_thread_t server_thread = RT_NULL; void server_entry(void *parameter) { float temp = 0.0; char data[20]; rt_err_t result = RT_EOK; __retry: esp_init(); rt_kprintf("start esp8266!\n"); rt_thread_delay(5000); result = esp_start_socket("TCP",0,"192.168.31.178",1234); if(RT_EOK != result) goto __exit; rt_kprintf("link the server ok!\n"); while(1) { temp = DS18B20_GetTemp(); sprintf(data,"Temperature:%.1f\r\n",temp); result = esp_send(0,data); if(RT_EOK != result) goto __exit; rt_thread_delay(5000); } __exit: esp_close_socket(0); rt_kprintf("close the socket!\n"); goto __retry; } void wifi_task(void) { /* 创建线程 */ server_thread = rt_thread_create("server", server_entry, \ RT_NULL, 512, 10, 10); if(server_thread != RT_NULL) { /* 启动线程 */ rt_thread_startup(server_thread); rt_kprintf("server thread start!\n"); } } INIT_APP_EXPORT(wifi_task); ``` 得到结果如图所示: [attach]14744[/attach][attach]14745[/attach] 另外,针对定时一分钟发送一次数据,可以使用软件定时器,然后将发送数据放在定时器回调函数中,前提是将服务器链接成功,代码如下: ``` char data[50]; u8 server_socket = 0; static void Temp_callback(void* parameter) { sprintf(data,"Temperature:%.1f\r\n",temp); esp_send(server_socket,data); } int upload_data(void) { Ds18B20Timer = rt_timer_create("Temp", /* 软件定时器的名称 */ Temp_callback, /* 软件定时器的回调函数 */ 0, /* 定时器超时函数的入口参数 */ RT_TICK_PER_SECOND, /* 软件定时器的超时时间(周期回调时间) */ RT_TIMER_FLAG_PERIODIC );/* 软件定时器HARD_TIMER模式 周期模式 */ return 0; } MSH_CMD_EXPORT(upload_data); ``` 效果和上面的一样,就不贴图了。
奔跑的蜗牛大大
2020-04-08
这家伙很懒,什么也没写!
1创建一个任务线程,并导出到控制台 2,在任务线程里面首先初始化ESP8266 然后 切换工作模式为STA 链接WIFI网络,连接TCP服务器 进入透传模式,在任务线程的主循环里面每隔1分钟获取一下温度并封包通过ESP8266发送
。。。
2020-04-08
这家伙很懒,什么也没写!
观看何老师的RT-Thread Nano-DS18B20-高精度微秒延时和RT-Thread Nano-ESP82266 WIFI相关的视频之后,完成本次作业。 移植何老师TemperatureUploadLocalSer.c,WifiCmdTest.c,BspDs18b20.c和BspEsp8266.c以及相关的头文件,在这基础上进行代码修改。 移植完之后我在config.h的头文件中加入了以下头文件: ``` #include "stdbool.h" #include "BspDs18b20.h" #include "BspEsp8266.h" ``` 在TemperatureUploadLocalSer.c中,实现输入一个MSH命令(T_Process),创建一个动态线程,在该线程回调函数中创建一个定时器并开启,该定时器实现一分钟上传一次DS18B20温度数据至本地TCP服务器。 线程的创建相关代码如下: ``` // 线程相关参数宏定义 #define Ds18B20_THREAD_STACK_SIZE 512 #define Ds18B20_THREAD_PRIORITY 8 static rt_timer_t Ds18B20ProcessSoftTimer; void Ds18B20_thread_entry(void *parameter)//用户消息处理入口函数 { Ds18B20ProcessSoftTimer = rt_timer_create("Ds18B20ProcessSoftTimer", /* 软件定时器的名称 */ Ds18B20ProcessSoftTimer_callback,/* 软件定时器的回调函数 */ 0, /* 定时器超时函数的入口参数 */ 60*RT_TICK_PER_SECOND, /* 软件定时器的超时时间(周期回调时间) */ RT_TIMER_FLAG_PERIODIC ); /* 软件定时器HARD_TIMER模式 周期模式 */ if (Ds18B20ProcessSoftTimer != NULL) rt_timer_start(Ds18B20ProcessSoftTimer);//启动软件定时器 } int T_Process(void) { rt_thread_t tid; /* 创建动态线程Ds18B20Process */ tid = rt_thread_create("Ds18B20Process", Ds18B20_thread_entry, RT_NULL, Ds18B20_THREAD_STACK_SIZE, Ds18B20_THREAD_PRIORITY, 10); if (tid != NULL) { rt_thread_startup(tid); rt_kprintf("线程Ds18B20Process创建成功\n\n"); } return 0; } MSH_CMD_EXPORT(T_Process, Temperature Data Sendto Server Init.); ``` 其中软件定时器的回调函数代码如下: ``` static char SendData[30];//发往服务器的包,暂存数组 static void Ds18B20ProcessSoftTimer_callback(void* parameter) { sprintf(SendData,"\r\nTemperature: %.1f\r\n",DS18B20_GetTemp_SkipRom()); ESP8266_SendString ( ENABLE, SendData, strlen(SendData), Single_ID_0 );//每隔1分钟打印一次测得的温度值 } ``` 我在WifiCmdTest.c中编写了一个直接连接网络的,代码如下: ``` #define WIFI_IP "MERCURY_CC72" //热点名称 #define WIFI_password "fxmfy210." //热点密码 #define TcpServer_IP "192.168.0.103" //服务器IP地址 #define TcpServer_Port "8000" //服务器连接端口 int ESP8266_Network_Connection(void) { ESP8266_Cmd ( "AT", "OK", NULL, 500 );//AT命令 ESP8266_Rst(); ESP8266_Net_Mode_Choose ( STA );//设置为工作站模式 while(!ESP8266_JoinAP ( WIFI_IP, WIFI_password));//加入热点 while(!ESP8266_Link_Server ( enumTCP, TcpServer_IP, TcpServer_Port, Single_ID_0));//加入服务器 while(!ESP8266_UnvarnishSend());//开启透传 printf("ESP8266 Network connection successful.\n"); return 0; } INIT_APP_EXPORT(ESP8266_Network_Connection); ``` 接下来我改一下ESP8266和DS18B20的接入引脚。 ESP8266我使用PE.8为使能脚,PE.9为复位脚,串口使用串口3; DS18B20的数据接收脚为PE.11。 硬件调试结果如下: [attach]14792[/attach] 其中可看出网络连接成功了。 [attach]14791[/attach] 图片中可看出,MSH命令有一个叫T_Process的命令,以及输入后能成功创建动态线程Ds18B20Process,以及每隔1分钟将温度值发送给本地TCP服务器。
yoowiwi
2020-04-08
这家伙很懒,什么也没写!
[i=s] 本帖最后由 yoowiwi 于 2020-4-8 14:55 编辑 [/i] [md]## 小作业:通过ESP8266 将DS18B20温度数据传至本地TCP服务器 * 这里我选择将数据上传到OntNet平台上,与上传到本地TCP服务器原理基本一致。 * DS18B20介绍 * 只有一条总线,温度测量范围-55°至+125°,精度为±0.5°,工作电压3至5.5V,测量结果9至12位数字量 * DS18B20相关协议函数网上及老师的工程文件里有,这里就不展出,直接放出读取传感器温度的函数,同时在RTThread需要实现高精度微秒延迟才能与DS18B20通信,实现函数如下: ```C void rt_hw_us_delay(rt_uint32_t us) // RTT中实现微秒延迟 { rt_uint32_t delta; rt_uint32_t current_delay; us = us * (SysTick->LOAD/(1000000/RT_TICK_PER_SECOND)); delta = SysTick->VAL; do { if ( delta > SysTick->VAL ) current_delay = delta - SysTick->VAL; else current_delay = SysTick->LOAD + delta - SysTick->VAL; } while( current_delay < us ); } int GetTemperature(void) { float temp = DS18B20_GetTemp_SkipRom(); // 读取温度数据 if(temp < 1.0 || temp > 80.0) // 如果数据异常则直接返回 return 1; esp8266_upload_temp(temp); // 将温度数据上传到ONENET printf ( "\r\温度:%.1f\r\n", temp);// 打印DS18B20 获取的温度值 return 0; } MSH_CMD_EXPORT(GetTemperature, Get Ds18b20 Temperature); ``` * ESP8266使用 * 常用指令 ``` AT // 测试指令 AT+RST // 复位 AT+CWMODE=1 // 1:STA 2:AP 3:AP+STA AT+CWJAP="NAME","PAS" // NAME为wifi名称,PAS为wifi密码 AT+CIFSR // 查询模块IP地址 AT+CIPSTART="TCP","IP",PORT // 填入TCPserver的IP地址及端口号 AT+CIPMODE=1 // 开启透传模式 AT+CIPSEND // 发送数据,透传模式下使用 +++ // 结束透传,注意此处不能“发送新行” ``` * 带参数的msh命令示例 ```C #include
static void atcmd(int argc, char**argv) { if (argc < 2) { rt_kprintf("Please input'atcmd
'\n"); return; } if (!rt_strcmp(argv[1], "server")) rt_kprintf("AT server!\n"); else if (!rt_strcmp(argv[1], "client")) rt_kprintf("AT client!\n"); else rt_kprintf("Please input'atcmd
'\n"); } MSH_CMD_EXPORT(atcmd, atcmd sample: atcmd
); ``` * HTTP协议示例 ```http POST /devices/设备ID/datapoints?type=5 HTTP/1.1 api-key:密钥 Host:api.heclouds.com Content-Length:发送的数据包大小 ,;属性,具体值 ``` | ip | 域名 | 端口 | 功能 | | :------------------------- | :-------------------- | :-------- | :---------- | | 183.230.40.33 | api.heclouds.com | 80 | api | | 183.230.40.39 | jjfaedp.hedevice.com | 876 | edp协议 | | 183.230.40.42 | modbus.heclouds.com | 987 | modbus协议 | | 183.230.40.42 | jtext.heclouds.com | 4362 | jtext协议 | | 183.230.40.39 | mqtt.heclouds.com | 6002 | mqtt协议 | | 183.230.40.40 218.201.45.3 | nbiotacc.heclouds.com | 5683(UDP) | nbiot接入机 | | 183.230.40.39 | nbiotbt.heclouds.com | 5683(UDP) | nbiot引导机 | | 183.230.40.40 | dtu.heclouds.com | 1811 | tcp透传协议 | * rt_kprintf接收的数据大小取决于宏:`RT_CONSOLEBUF_SIZE`,默认为128 * 代码示例 * 相关宏、变量定义 ```C #define BUFF_REC_SIZE 256 // 接收的数据大小 rt_uint8_t buff3[BUFF_REC_SIZE]; ``` * 与esp8266相关的串口初始化,此处对8266的数据接收使用了DMA传输 ```C int USART3_Config(void) { GPIO_InitTypeDef gpio; USART_InitTypeDef usart; DEBUG_USART3_GPIO_APBxClkCmd(DEBUG_USART3_GPIO_CLK, ENABLE); DEBUG_USART3_APBxClkCmd(DEBUG_USART3_CLK, ENABLE); gpio.GPIO_Pin = DEBUG_USART3_TX_GPIO_PIN; gpio.GPIO_Mode = GPIO_Mode_AF_PP; gpio.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(DEBUG_USART3_TX_GPIO_PORT, &gpio); gpio.GPIO_Pin = DEBUG_USART3_RX_GPIO_PIN; gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(DEBUG_USART3_RX_GPIO_PORT, &gpio); usart.USART_BaudRate = DEBUG_USART3_BAUDRATE; usart.USART_WordLength = USART_WordLength_8b; usart.USART_StopBits = USART_StopBits_1; usart.USART_Parity = USART_Parity_No ; usart.USART_HardwareFlowControl = USART_HardwareFlowControl_None; usart.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(DEBUG_USART3, &usart); NVIC_Configuration(); USARTx_DMA_Config(); USART_DMACmd(USART3,USART_DMAReq_Rx,ENABLE); DMA_ClearFlag(DMA1_FLAG_TC3); DMA_ITConfig(DMA1_Channel3, DMA_IT_TE, ENABLE); USART_ITConfig(DEBUG_USART3, USART_IT_IDLE, ENABLE); USART_Cmd(DEBUG_USART3, ENABLE); return 0; } INIT_BOARD_EXPORT(USART3_Config); ``` * 串口空闲中断,用于数据接收 ```C void DEBUG_USART3_IRQHandler() { uint8_t len = 0; if(USART_GetFlagStatus(USART3, USART_FLAG_IDLE) != RESET) { USART3->SR;USART3->DR; // 清除中断标志位 DMA_Cmd(DMA1_Channel3, DISABLE); len = BUFF_REC_SIZE - DMA_GetCurrDataCounter(DMA1_Channel3); buff3[len]='\0'; DMA1_Channel3->CNDTR = BUFF_REC_SIZE; DMA_Cmd(DMA1_Channel3, ENABLE); } } ``` * esp8266 AT指令传输函数 ```C void esp8266_atcmd_send(char *str) { if(!rt_strcmp(str,"+++")) // 结束透传,不需要换行 { Usart_SendString(USART3,str); return; } Usart_SendString(USART3,str); Usart_SendString(USART3,"\r\n"); } ``` * esp8266上传温度到onenet平台 ```C int esp8266_upload_temp(float temp) { char buff_send[256]; sprintf(buff_send, "POST /devices/590754126/datapoints?type=5 HTTP/1.1\n" "api-key:pdGPsadeZ66PFPx5=lNj0MTcBqweqsarg=\n" "Host:api.heclouds.com\n" "Connection:close\n" "Content-Length:12\n\n" ",;Temp,%2.1f\n",temp); esp8266_atcmd_send("AT+CIPSTART=\"TCP\",\"183.230.40.33\",80"); rt_thread_mdelay(200); esp8266_atcmd_send("AT+CIPMODE=1"); rt_thread_mdelay(10); esp8266_atcmd_send("AT+CIPSEND"); rt_thread_mdelay(10); Usart_SendString(USART3,buff_send); // 发送数据 rt_thread_mdelay(100); esp8266_atcmd_send("+++"); rt_thread_mdelay(50); esp8266_atcmd_send("AT+CIPCLOSE"); return 0; } int UploadTemprature(void) { float temp = DS18B20_GetTemp_SkipRom(); if(temp < 1.0 || temp > 80.0) { return 1; } esp8266_upload_temp(temp); printf ( "\r\n温度监测上传:%.1f℃\r\n", temp); return 0; } MSH_CMD_EXPORT(UploadTemprature, Get Ds18b20 Temperature); ``` * 每5秒上传一次数据到ONENET平台: ```C static struct rt_thread tupload; rt_uint8_t upload_thread_stack[2048]; void UploadTemp_Thread(void *paramter); int UploadTemp_TimerInit() { rt_thread_init(&tupload,"UploadTemp",UploadTemp_Thread,RT_NULL, \ upload_thread_stack,sizeof(upload_thread_stack), \ 5,10); rt_thread_startup(&tupload); return 0; } INIT_APP_EXPORT(UploadTemp_TimerInit); MSH_CMD_EXPORT(UploadTemp_TimerInit, UploadTemp_TimerInit); void UploadTemp_Thread(void *paramter) { while(1) { UploadTemprature(); rt_thread_mdelay(5000); } } ```[/md] 效果截图; [attach]14794[/attach] [attach]14795[/attach]
打盹的消防车
2020-04-08
忙着打盹...
ESP866连接网络成功之后,实现输入一个MSH命令,创建一个动态线程,在该线程回调函数中实现一分钟上传一次DS18B20温度数据至本地TCP服务器。
撰写答案
登录
注册新账号
关注者
0
被浏览
4.2k
关于作者
RT-Thread小喇叭
这家伙很懒,什么也没写!
提问
29
回答
54
被采纳
1
关注TA
发私信
相关问题
1
F030读入18B20的温度全为0
2
关于ds18b20软件包微秒延时
3
关于ds18b20的问题
4
DS18b20 pkg 更换引脚无法读取问题问题
5
分享 rt-thread ds18b20 温度驱动
6
急救,关于DHT11和DS18B20温度传感器
7
rt thread ds18b20
8
ds18b20初始化失败
9
ds18b20采集温度为什么一直是4095?
10
51单片机 IO口作为参数问题
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
使用百度AI助手辅助编写一个rt-thread下的ONVIF设备发现功能的功能代码
2
RT-Thread 发布 EtherKit开源以太网硬件!
3
rt-thread使用cherryusb实现虚拟串口
4
《C++20 图形界面程序:速度与渲染效率的双重优化秘籍》
5
《原子操作:程序世界里的“最小魔法单位”解析》
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
WIZnet_W5500
ota在线升级
UART
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
keil_MDK
rt_mq_消息队列_msg_queue
at_device
ulog
C++_cpp
本月问答贡献
踩姑娘的小蘑菇
7
个答案
3
次被采纳
a1012112796
13
个答案
2
次被采纳
张世争
9
个答案
2
次被采纳
rv666
5
个答案
2
次被采纳
用户名由3_15位
11
个答案
1
次被采纳
本月文章贡献
程序员阿伟
7
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
大龄码农
1
篇文章
2
次点赞
ThinkCode
1
篇文章
1
次点赞
Betrayer
1
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部