文章目录
- 一、设备平台
- 二、功能说明
- 三、硬件系统设计实现与图表
- 四、软件系统设计实现与流程图
- 五、调试过程中出现的问题及相应解决办法
- 六、程序设计
- 1. 开始任务函数
- 2. LED任务函数
- 3. KEY任务函数
- 4. UART任务函数
- 5. OLED任务函数
- 6. DHT11任务函数
- 7. BEEP任务函数
- 8. ADC任务函数
- 9. PWM任务函数
- 10. ESP8266任务函数
一、设备平台
二、功能说明
利用stm32开发板实现智慧农业的设计,基于STM32F407FreeRTOS实现如下九个功能模块:
- 智慧农业定时系统:根据智慧农业的定时系统通过led灯的翻转现象变现系统的定时警告,具体利用定时器time4实现led2的每秒翻转。
- 智慧农业PWM模块:根据脉冲调制实现呼吸灯led0的效果。
- 智慧农业按键模块:通过按键key2实现led3的翻转效果。
- 智慧农业显示系统:通过oled屏幕显示智慧农业的中文信息。
- 智慧农业的串口打印模块:利用uart串口通信协议实现无线收发功能。
- 智慧农业光照采集系统:利用ADC通过光敏电阻采集光照强度。
- 智慧农业湿度采集系统:利用DHTL1采集温湿度,当温度大于30摄氏度使,蜂鸣器报警。
- 智慧农业ESP8622模块:通过QT制图实现可视化的智慧农业系统。
- 智慧农业风扇模块:通过电机驱动风扇,实现智慧农业的风扇降温系统。
三、硬件系统设计实现与图表
四、软件系统设计实现与流程图
本智慧农业系统模块,一共涉及9个模块(智慧农业定时系统、智慧农业PWM模块、智慧农业按键模块、智慧农业显示系统、智慧农业的串口打印模块、智慧农业光照采集系统、智慧农业湿度采集系统、智慧农业ESP8622模块、智慧农业风扇模块)。具体如下:
- 1. 利用定时器time4实现led2的每秒翻转,LED2每隔1s闪烁一次,采用定时器TIM2计数功能实现,计数值到的时候产生溢出中断,灯的状态发送切换(RCC、NVIC,TIM2,GPIO,位操作,定时器2中断处理函数)
- 2. 根据脉冲调制实现呼吸灯的效果,脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多领域中。 STM32F4 的定时器除了 TIM6 和 TIM7。其他的定时器都可以用来产生 PWM 输出。通过查看我们开发板的原理图发现,PF9引脚连接的是LED0,而且同时也是作TIM14_CH1的复用输出端口,这时候,我们可以使用PF9引脚,输出PWM波,来控制我们的LED0,使得LED0的亮灭有了更加美妙的呼吸状态。
- 3. 通过按键key2实现led3的翻转效果,通过检测按键的按下的情况控制小灯的翻转
- 4. 通过oled屏幕显示智慧农业的中文信息,通过对字符串s的取指操作,判断当前字节是否大于127,大于127说明对应的是汉字,将接下来的两个字节取出组合为汉字内码,通过内码查询字模数组中是否包含该字,查找到之后再将数据写入,显示到屏幕上。如果当前的字节小于128,则对应的是英文字符,直接使用例程的OLED_ShowChar函数写数据,就可以显示出来。
- 5. 利用uart串口通信协议实现无线收发功能,通用异步收发器 UART是一种串行、异步、全双工的通信协议,将所需传输的数据一位接一位地传输,在UART通讯协议中信号线上的状态位高电平代表’1’,低电平代表’0’。其特点是通信线路简单,只要一对传输线就可以实现双向通信,大大降低了成本,但传送速度较慢。在串口通信中,尤其需要关注的是数据流以及波特率。一个数据流由10个数据位组成,包含1位起始位,7位有效数据位,1位奇偶校验位,1位停止位。uart串口信号线上空闲时常驻高电平,当检测到低电平下降沿时认为数据传输开始,到停止位时数据传输结束,一共10位数据位组成一个数据包。起始位:通信线路上空闲时为“1”,当检测到“0”即下降沿时,认为数据传输开始。有效数据位:传输开始后传递的需要接收和发送的数据值,可以表示指令或数据。奇偶校验位:奇偶校验,通过来校验传输数据中“1”的个数为奇数个(奇校验)或偶数个(偶校验)来指示传输数据是否正确。停止位:数据传输结束,传输线恢复常“1”状态。串口时钟使能 GPIO 时钟使能
串口复位、GPIO 端口模式设置、串口参数初始化、开启中断 并且初始化 NVIC(如果需要开启中断才需要这个步骤)、使能串口、编写中断处理函数。程序功能是STM32通过 串口1 和上位机(PC)对话,STM32收到上位机发送的数据(字符串)后,将数据原原本本的返回给上位机。采用USART1的全双工异步串行收发模式。 - 6. 利用ADC通过光敏电阻采集光照强度。
光敏电阻内部就是一个PN结,光的强弱会引起其导通的变化,从而会引起电流的变化;电路设计方面,主要是利用电流的变化,然后在串联一个电阻,就可以转换成电压的变化,然后在利用ADC来采集电压的变化进行处理。同时光线与电压值成反比。ADC采集:电路上选择某个ADC和使用相应的通道选择。ADC的使用步骤:
(1)第一步:开启相关ADC的时钟,设置分频因子。ADC_CCR寄存器。
(2)第二步:ADC的工作模式设置,主要是:转换模式、触发方式、数据对齐等,
ADCx_CR1,ACDx_CR2。
(3)第三步:ADC规则序列通道设置规则序列中的通道数、和通道的采样周期,ADCx_SQR,ADCx_SMPR。
(4)第四步:开启AD转换器,ADC_CRx寄存器。
(5)第五步:读取ADC的值,ADC_DR寄存器的值
具体过程是:转换序列设置,选择相应的规则序列,并添加要开启的通道。通过ADCx_CR来启动规则转换通道。通过ADCx_SR状态标志位,循环等待转换完成,直接还回ADCx_DR数据寄存器即可。 - 7. 利用DHTL1采集温湿度,当温度大于30摄氏度使,蜂鸣器报警。HT11是一款湿温度一体化的数字传感器。该传感器包括一个电阻式测湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接。通过单片机等微处理器简单的电路连接就能够实时的采集本地湿度和温度。DHT11与单片机之间能采用简单的单总线进行通信,仅仅需要一个1/0口。传感器内部湿度和温度数据40Bit的数据一次性传给单片机,数据采用校验和方式进行校验,有效的保证数据传输的准确性。DHT11功耗很低, 5V电源电压下,工作平均最大电流0.5mA。DHT11数字湿温度传感器采用单总线数据格式。即,单个数据引脚端口完成输入输出双向传输。其数据包由SByte (40Bit)组成。数据分小数部分和整数部分,一次完整的数据传输为40bit,高位先出。DHT11的数据格式为: 8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据+8bit校验和。其中校验和数据为前四个字节相加。传感器数据输出的是未编码的二进制数据。数据(湿度、温度、整数、小数)之间应该分开处理。
- 8. 基于QT现象ESP8266无线连接,RXD、TXD、GND、VCC,分别和USB转TTL模块的TXD、RXD、GND、VCC相连接。ESP8266的RXD(数据的接收端)需要连接USB转TTL模块的TXD,TXD(数据的发送端)需要连接USB转TTL模块的RXD,在USB转TTL模块上有3.3V和5V两个引脚可以作为VCC,选取5V作为VCC。AT指令在使用USB转TTL模块与电脑连接之后,就可以使用串口调试助手进行WIFI模块的调试了。可将用户的物理设备连接到Wi-Fi 无线网络上,进行互联网或局域网通信,实现联网功能,使用AT指令进行控制。两个模组通过TCP/UDP相互通信。其中Server端为AP模式,Client端为Station模式。
项目通过下位机采集数据,传输到电脑,所以下位机WIFI模块为Client端,电脑WIFI模块为Server端。 - 9. 通过电机驱动风扇,实现智慧农业的风扇降温系统,利用电机控制风扇的转动,选择合适的电压控制电机的转动。
五、调试过程中出现的问题及相应解决办法
在本次项目过程中我们出现的问题有:
-
程序代码反复核对没有出现问题但实验板没有出现实验现象,最后经过更换实验板和更换电脑进行对比发现是实验板和模块之间的连接出现接触不良的问题,更换了实验板后调试成功。
-
通信串口无法建立连接,我们通过串口调试功能,实现了串口通信。
-
温湿度数据有误,通过串口调试,实现温湿度精准读取。
六、程序设计
1. 开始任务函数
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); //进入临界区
//创建TASK1任务
xTaskCreate((TaskFunction_t )LED_task,
(const char* )"LED_task",
(uint16_t )LED_STK_SIZE,
(void* )NULL,
(UBaseType_t )LED_TASK_PRIO,
(TaskHandle_t* )&LED_Handler);
xTaskCreate((TaskFunction_t )KEY_task,
(const char* )"KEY_task",
(uint16_t )KEY_STK_SIZE,
(void* )NULL,
(UBaseType_t )KEY_TASK_PRIO,
(TaskHandle_t* )&KEY_Handler);
xTaskCreate((TaskFunction_t )UART1_task,
(const char* )"UART1_task",
(uint16_t )UART1_STK_SIZE,
(void* )NULL,
(UBaseType_t )UART1_TASK_PRIO,
(TaskHandle_t* )&UART1_Handler);
xTaskCreate((TaskFunction_t )OLED_task,
(const char* )"OLED_task",
(uint16_t )OLED_STK_SIZE,
(void* )NULL,
(UBaseType_t )OLED_TASK_PRIO,
(TaskHandle_t* )&OLED_Handler);
xTaskCreate((TaskFunction_t )DHT11_task,
(const char* )"DHT11_task",
(uint16_t )DHT11_STK_SIZE,
(void* )NULL,
(UBaseType_t )DHT11_TASK_PRIO,
(TaskHandle_t* )&DHT11_Handler);
xTaskCreate((TaskFunction_t )BEEP_task,
(const char* )"BEEP_task",
(uint16_t )BEEP_STK_SIZE,
(void* )NULL,
(UBaseType_t )BEEP_TASK_PRIO,
(TaskHandle_t* )&BEEP_Handler);
xTaskCreate((TaskFunction_t )ADC_task,
(const char* )"ADC_task",
(uint16_t )ADC_STK_SIZE,
(void* )NULL,
(UBaseType_t )ADC_TASK_PRIO,
(TaskHandle_t* )&ADC_Handler);
xTaskCreate((TaskFunction_t )PWM_task,
(const char* )"PWM_task",
(uint16_t )PWM_STK_SIZE,
(void* )NULL,
(UBaseType_t )PWM_TASK_PRIO,
(TaskHandle_t* )&PWM_Handler);
xTaskCreate((TaskFunction_t )ESP8266_task,
(const char* )"ESP8266_task",
(uint16_t )ESP8266_STK_SIZE,
(void* )NULL,
(UBaseType_t )ESP8266_TASK_PRIO,
(TaskHandle_t* )&ESP8266_Handler);
vTaskDelete(StartTask_Handler); //删除开始任务
taskEXIT_CRITICAL(); //退出临界区
}
2. LED任务函数
void LED_task(void *pvParameters)
{
while(1)
{
//LED1=!LED1;
vTaskDelay(500);
}
}
3. KEY任务函数
void KEY_task(void *pvParameters)
{
while(1)
{
vTaskDelay(500);
}
}
4. UART任务函数
void UART1_task(void *pvParameters)
{
while(1)
{
m=Rece_Data();
if(!strncmp(m,"LED_ON",6))
{
LED0=0;
LED1=0;
LED2=0;
printf("LED_ON success!\r\n");
memset(m, 0, 8);
}
if(!strncmp(m,"LED_OFF",7))
{
LED0=1;
LED1=1;
LED2=1;
printf("LED_OFF success!\r\n");
memset(m, 0, 8);
}
if(!strncmp(m,"BEEP_ON",8))
{
BEEP=1;
printf("BEEP_ON success!\r\n");
memset(m, 0, 8);
}
if(!strncmp(m,"BEEP_OFF",9))
{
BEEP=0;
printf("BEEP_OFF success!\r\n");
memset(m, 0, 8);
}
printf("ADC 光照强度:%ld LUX\r\n",guangzhao);
printf("DHT11 温度:%d.%d °C, 湿度:%d.%d %%rh\r\n",(int)temp,(int)tx,(int)humi,(int)hx);
printf(" \r\n");
vTaskDelay(500);
}
}
5. OLED任务函数
void OLED_task(void *pvParameters)
{
while(1)
{
//在屏幕上打印结果
Oled_print(50, 2,"IOT");
Oled_print(0, 4," Intelligent ");
Oled_print(0, 6," Agriculture ");
//第1行显示重量
OLed_ShowChina(50,0,HZ12);
OLed_ShowChina(66,0,HZ13);
//OLed_Fill(0x00);//描点清屏函数;
vTaskDelay(500000);
}
}
6. DHT11任务函数
void DHT11_task(void *pvParameters)
{
while(1)
{
DHT_Recevice_Data(&humi,&temp,&hx,&tx);
vTaskDelay(500);
}
}
7. BEEP任务函数
void BEEP_task(void *pvParameters)
{
while(1)
{
if(temp>=30)
{
BEEP=!BEEP;
delay_ms(50);
}
else{
BEEP=0;
}
vTaskDelay(200);
}
}
8. ADC任务函数
void ADC_task(void *pvParameters)
{
while(1)
{
guangzhao=getAdcAverage(4);
vTaskDelay(500);
}
}
9. PWM任务函数
void PWM_task(void *pvParameters)
{
while(1)
{
int i=0;
for(i=0;i<=1000;i=i+10)
{
TIM_SetCompare1(TIM1,i);
delay_ms(20);
}
vTaskDelay(500);
}
}
10. ESP8266任务函数
void ESP8266_task(void *pvParameters)
{
while(1)
{
ESP8266_test();
vTaskDelay(500);
}
}
若需完整工程联系下方wx即可👇👇👇